Skip to main content
Glama

search_jira_issues

Search Jira issues using JQL queries with pagination and customizable field selection to find specific tickets based on criteria like project, status, or assignee.

Instructions

Search issues using JQL with pagination and field selection.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
jqlYesJQL query (e.g., project=PROJ AND status="In Progress")
startAtNoPagination start index (default 0)
maxResultsNoPage size (1-100, default 50)
fieldsNoComma-separated fields to return (default: key,summary,status,assignee,priority,issuetype,updated)

Implementation Reference

  • The handler function executes the tool logic: constructs JQL search body, POSTs to Jira /search API, maps response issues to structured content with summaries, URLs, etc., handles pagination, errors.
    async (args: { jql: string; startAt?: number; maxResults?: number; fields?: string }) => { try { const body: any = { jql: args.jql, startAt: args.startAt ?? 0, maxResults: args.maxResults ?? 50, fields: (args.fields ? args.fields.split(",").map(s => s.trim()) : ["key","summary","status","assignee","priority","issuetype","updated"]).filter(Boolean) }; const url = `${JIRA_URL}/rest/api/3/search`; const response = await fetch(url, { method: "POST", headers: getJiraHeaders(), body: JSON.stringify(body) }); if (!response.ok) { const errorText = await response.text(); return { content: [{ type: "text", text: `Failed to search issues: ${response.status} ${response.statusText}\n${errorText}` }], isError: true }; } const data = await response.json() as any; const items = (data.issues || []).map((it: any) => ({ key: it.key, summary: it.fields?.summary, status: it.fields?.status?.name, assignee: it.fields?.assignee?.displayName, priority: it.fields?.priority?.name, type: it.fields?.issuetype?.name, updated: it.fields?.updated, url: `${JIRA_URL}/browse/${it.key}` })); return { content: [{ type: "text", text: `Found ${data.total ?? items.length} issues (showing ${items.length}).` }], structuredContent: { total: data.total ?? items.length, startAt: data.startAt ?? 0, maxResults: data.maxResults ?? items.length, issues: items, raw: data } }; } catch (error) { return { content: [{ type: "text", text: `Error searching issues: ${error instanceof Error ? error.message : String(error)}` }], isError: true }; } }
  • Input schema using Zod for validation of JQL query, pagination parameters (startAt, maxResults), and optional fields.
    { title: "Search Jira Issues (JQL)", description: "Search issues using JQL with pagination and field selection.", inputSchema: { jql: z.string().describe("JQL query (e.g., project=PROJ AND status=\"In Progress\")"), startAt: z.number().int().min(0).optional().describe("Pagination start index (default 0)"), maxResults: z.number().int().min(1).max(100).optional().describe("Page size (1-100, default 50)"), fields: z.string().optional().describe("Comma-separated fields to return (default: key,summary,status,assignee,priority,issuetype,updated)") }, },
  • src/server.ts:240-273 (registration)
    Registration of the 'search_jira_issues' tool with McpServer, including name, schema, and handler reference.
    mcp.registerTool( "search_jira_issues", { title: "Search Jira Issues (JQL)", description: "Search issues using JQL with pagination and field selection.", inputSchema: { jql: z.string().describe("JQL query (e.g., project=PROJ AND status=\"In Progress\")"), startAt: z.number().int().min(0).optional().describe("Pagination start index (default 0)"), maxResults: z.number().int().min(1).max(100).optional().describe("Page size (1-100, default 50)"), fields: z.string().optional().describe("Comma-separated fields to return (default: key,summary,status,assignee,priority,issuetype,updated)") }, }, async (args: { jql: string; startAt?: number; maxResults?: number; fields?: string }) => { try { const body: any = { jql: args.jql, startAt: args.startAt ?? 0, maxResults: args.maxResults ?? 50, fields: (args.fields ? args.fields.split(",").map(s => s.trim()) : ["key","summary","status","assignee","priority","issuetype","updated"]).filter(Boolean) }; const url = `${JIRA_URL}/rest/api/3/search`; const response = await fetch(url, { method: "POST", headers: getJiraHeaders(), body: JSON.stringify(body) }); if (!response.ok) { const errorText = await response.text(); return { content: [{ type: "text", text: `Failed to search issues: ${response.status} ${response.statusText}\n${errorText}` }], isError: true }; } const data = await response.json() as any; const items = (data.issues || []).map((it: any) => ({ key: it.key, summary: it.fields?.summary, status: it.fields?.status?.name, assignee: it.fields?.assignee?.displayName, priority: it.fields?.priority?.name, type: it.fields?.issuetype?.name, updated: it.fields?.updated, url: `${JIRA_URL}/browse/${it.key}` })); return { content: [{ type: "text", text: `Found ${data.total ?? items.length} issues (showing ${items.length}).` }], structuredContent: { total: data.total ?? items.length, startAt: data.startAt ?? 0, maxResults: data.maxResults ?? items.length, issues: items, raw: data } }; } catch (error) { return { content: [{ type: "text", text: `Error searching issues: ${error instanceof Error ? error.message : String(error)}` }], isError: true }; } } );
  • Shared helper function that creates authentication headers using Jira email and API token, used by the search handler and other tools.
    function getJiraHeaders(): Record<string, string> { const auth = Buffer.from(`${JIRA_EMAIL}:${JIRA_API_TOKEN}`).toString('base64'); return { 'Authorization': `Basic ${auth}`, 'Accept': 'application/json', 'Content-Type': 'application/json', }; }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/imrnbeg/jira-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server