jira_search_issues
Search for Jira issues by project and assignee to track tasks and manage workflow efficiently.
Instructions
Searches for Jira issues by project and assignee
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| jiraHost | No | The Jira host URL (e.g., 'your-domain.atlassian.net') | |
| No | Email address associated with the Jira account | ||
| apiToken | No | API token for Jira authentication | |
| projectKey | Yes | The Jira project key (e.g., 'PROJECT') | |
| assigneeName | No | The display name of the assignee to filter by (e.g., 'John Doe') |
Implementation Reference
- src/tools/searchIssues.ts:59-124 (handler)The main handler function `searchIssues` that implements the core logic for the `jira_search_issues` tool. It validates input arguments, constructs a JQL query for searching issues by project key and optional assignee, makes an API call to Jira's search endpoint, and formats the results as a markdown table.export async function searchIssues(args: any) { const validatedArgs = await JiraSearchIssuesRequestSchema.validate(args); const jiraHost = validatedArgs.jiraHost || process.env.JIRA_HOST; const email = validatedArgs.email || process.env.JIRA_EMAIL; const apiToken = validatedArgs.apiToken || process.env.JIRA_API_TOKEN; const projectKey = validatedArgs.projectKey; const assigneeName = validatedArgs.assigneeName; if (!jiraHost || !email || !apiToken) { throw new Error('Missing required authentication credentials. Please provide jiraHost, email, and apiToken.'); } validateCredentials(jiraHost, email, apiToken); let jql = `project = "${projectKey}"`; if (assigneeName) { jql += ` AND assignee ~ "${assigneeName}"`; } jql += ` ORDER BY created DESC`; const authHeader = createAuthHeader(email, apiToken); const response = await axios.get(`https://${jiraHost}/rest/api/3/search`, { params: { jql, maxResults: 50, fields: "summary,status,assignee,created,issuetype,priority", }, headers: { 'Authorization': authHeader, 'Accept': 'application/json', }, }); const searchResults = response.data; const issues = searchResults.issues || []; let formattedResponse = `# Issues for Project: ${projectKey}`; if (assigneeName) { formattedResponse += ` assigned to ${assigneeName}`; } formattedResponse += "\n\n"; if (issues.length > 0) { formattedResponse += "| Issue Key | Summary | Status | Type | Assignee | Created |\n"; formattedResponse += "|-----------|---------|--------|------|----------|--------|\n"; issues.forEach((issue: any) => { const key = issue.key; const summary = issue.fields.summary || 'No summary'; const status = issue.fields.status?.name || 'Unknown'; const type = issue.fields.issuetype?.name || 'Unknown'; const assignee = issue.fields.assignee?.displayName || 'Unassigned'; const created = new Date(issue.fields.created).toLocaleDateString(); formattedResponse += `| ${key} | ${summary} | ${status} | ${type} | ${assignee} | ${created} |\n`; }); } else { formattedResponse += "No issues found matching the specified criteria."; } return { content: [{ type: "text", text: formattedResponse }], isError: false, }; }
- src/handlers/handlerTools.ts:36-39 (registration)Registers the `jira_search_issues` tool in the `toolConfigs` mapping, associating it with `JiraSearchIssuesRequestSchema` for validation and the `searchIssues` handler for execution. This is used in `handleCallTool` to dispatch tool calls.jira_search_issues: { schema: JiraSearchIssuesRequestSchema, handler: searchIssues },
- src/validators/index.ts:52-59 (schema)Defines `JiraSearchIssuesRequestSchema`, a Yup schema extending `JiraApiRequestSchema` to validate required `projectKey` and optional `assigneeName` for the `jira_search_issues` tool inputs.export const JiraSearchIssuesRequestSchema = JiraApiRequestSchema.shape({ projectKey: yup.string() .required("Project key is required") .matches(/^[A-Z][A-Z0-9_]+$/, "Invalid project key format. Only uppercase letters, numbers, and underscores are allowed"), assigneeName: yup.string() .optional() .min(2, "Assignee name must be at least 2 characters long"), });
- src/tools/searchIssues.ts:12-124 (helper)Exports `searchIssuesToolDescription` object containing the tool name, description, and JSON schema for input parameters, used potentially for tool metadata.export const searchIssuesToolDescription = { name: "jira_search_issues", description: "Searches for Jira issues by project and assignee", inputSchema: { type: "object", properties: { jiraHost: { type: "string", description: "The Jira host URL (e.g., 'your-domain.atlassian.net')", default: process.env.JIRA_HOST || "", }, email: { type: "string", description: "Email address associated with the Jira account", default: process.env.JIRA_EMAIL || "", }, apiToken: { type: "string", description: "API token for Jira authentication", default: process.env.JIRA_API_TOKEN || "", }, projectKey: { type: "string", description: "The Jira project key (e.g., 'PROJECT')", }, assigneeName: { type: "string", description: "The display name of the assignee to filter by (e.g., 'John Doe')", }, }, required: ["projectKey"], }, }; /** * Searches for Jira issues by project key and optional assignee name * * @async * @param {Object} args - The arguments for the search * @param {string} args.jiraHost - The Jira host URL * @param {string} args.email - Email for authentication * @param {string} args.apiToken - API token for authentication * @param {string} args.projectKey - The project key to search in * @param {string} [args.assigneeName] - Optional assignee name to filter by * @returns {Promise<Object>} A formatted response with the search results * @throws {Error} If the required credentials are missing or the request fails */ export async function searchIssues(args: any) { const validatedArgs = await JiraSearchIssuesRequestSchema.validate(args); const jiraHost = validatedArgs.jiraHost || process.env.JIRA_HOST; const email = validatedArgs.email || process.env.JIRA_EMAIL; const apiToken = validatedArgs.apiToken || process.env.JIRA_API_TOKEN; const projectKey = validatedArgs.projectKey; const assigneeName = validatedArgs.assigneeName; if (!jiraHost || !email || !apiToken) { throw new Error('Missing required authentication credentials. Please provide jiraHost, email, and apiToken.'); } validateCredentials(jiraHost, email, apiToken); let jql = `project = "${projectKey}"`; if (assigneeName) { jql += ` AND assignee ~ "${assigneeName}"`; } jql += ` ORDER BY created DESC`; const authHeader = createAuthHeader(email, apiToken); const response = await axios.get(`https://${jiraHost}/rest/api/3/search`, { params: { jql, maxResults: 50, fields: "summary,status,assignee,created,issuetype,priority", }, headers: { 'Authorization': authHeader, 'Accept': 'application/json', }, }); const searchResults = response.data; const issues = searchResults.issues || []; let formattedResponse = `# Issues for Project: ${projectKey}`; if (assigneeName) { formattedResponse += ` assigned to ${assigneeName}`; } formattedResponse += "\n\n"; if (issues.length > 0) { formattedResponse += "| Issue Key | Summary | Status | Type | Assignee | Created |\n"; formattedResponse += "|-----------|---------|--------|------|----------|--------|\n"; issues.forEach((issue: any) => { const key = issue.key; const summary = issue.fields.summary || 'No summary'; const status = issue.fields.status?.name || 'Unknown'; const type = issue.fields.issuetype?.name || 'Unknown'; const assignee = issue.fields.assignee?.displayName || 'Unassigned'; const created = new Date(issue.fields.created).toLocaleDateString(); formattedResponse += `| ${key} | ${summary} | ${status} | ${type} | ${assignee} | ${created} |\n`; }); } else { formattedResponse += "No issues found matching the specified criteria."; } return { content: [{ type: "text", text: formattedResponse }], isError: false, }; }
- src/handlers/handlerListTools.ts:63-80 (registration)Lists the `jira_search_issues` tool in `handleListTools` response, providing description and input schema for MCP client tool discovery.name: "jira_search_issues", description: "Searches for Jira issues by project and assignee", inputSchema: { type: "object", properties: { ...getCommonJiraProperties(), projectKey: { type: "string", description: "The Jira project key (e.g., 'PROJECT')", }, assigneeName: { type: "string", description: "The display name of the assignee to filter by (e.g., 'John Doe')", }, }, required: ["projectKey"], }, },