Skip to main content
Glama

jira_get_issue

Retrieve specific Jira issue details by key, using the Jira host URL, account email, and API token for authentication. Part of the Jira MCP Server for managing project tasks.

Instructions

Retrieves details of a specific Jira issue by key

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
apiTokenNoAPI token for Jira authentication
emailNoEmail address associated with the Jira account
issueKeyYesThe Jira issue key (e.g., 'PROJECT-123')
jiraHostNoThe Jira host URL (e.g., 'your-domain.atlassian.net')

Implementation Reference

  • The main execution function for the jira_get_issue tool. Fetches issue details from Jira API, formats response with tables for basic info, description, comments, attachments, worklog, and changelog.
    export async function getIssue(args: any) { const validatedArgs = await JiraIssueRequestSchema.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 issueKey = validatedArgs.issueKey; if (!jiraHost || !email || !apiToken) { throw new Error('Missing required authentication credentials. Please provide jiraHost, email, and apiToken.'); } validateCredentials(jiraHost, email, apiToken); const authHeader = createAuthHeader(email, apiToken); try { const response = await axios.get(`https://${jiraHost}/rest/api/3/issue/${issueKey}`, { params: { expand: 'renderedFields,names,changelog,operations', fields: 'summary,status,assignee,issuetype,priority,created,creator,reporter,description,comment,attachment,worklog,updated,labels,fixVersions,components,duedate' }, headers: { 'Authorization': authHeader, 'Accept': 'application/json', }, }); const issue = response.data; const formattedDate = new Date(issue.fields.created).toLocaleString(); const updatedDate = issue.fields.updated ? new Date(issue.fields.updated).toLocaleString() : 'Not updated'; let formattedResponse = `# Issue: ${issue.key} - ${issue.fields.summary}\n\n`; formattedResponse += `## Basic Information\n\n`; formattedResponse += `| Field | Value |\n`; formattedResponse += `|-------|-------|\n`; formattedResponse += `| Status | ${issue.fields.status?.name || 'Unknown'} |\n`; formattedResponse += `| Type | ${issue.fields.issuetype?.name || 'Unknown'} |\n`; formattedResponse += `| Priority | ${issue.fields.priority?.name || 'Not set'} |\n`; formattedResponse += `| Assignee | ${issue.fields.assignee?.displayName || 'Unassigned'} |\n`; formattedResponse += `| Reporter | ${issue.fields.reporter?.displayName || 'Unknown'} |\n`; formattedResponse += `| Created | ${formattedDate} |\n`; formattedResponse += `| Updated | ${updatedDate} |\n`; if (issue.fields.duedate) { const dueDate = new Date(issue.fields.duedate).toLocaleString(); formattedResponse += `| Due Date | ${dueDate} |\n`; } if (issue.fields.labels && issue.fields.labels.length > 0) { formattedResponse += `| Labels | ${issue.fields.labels.join(', ')} |\n`; } if (issue.fields.components && issue.fields.components.length > 0) { const componentNames = issue.fields.components.map((comp: any) => comp.name).join(', '); formattedResponse += `| Components | ${componentNames} |\n`; } if (issue.fields.fixVersions && issue.fields.fixVersions.length > 0) { const fixVersionNames = issue.fields.fixVersions.map((ver: any) => ver.name).join(', '); formattedResponse += `| Fix Versions | ${fixVersionNames} |\n`; } if (issue.fields.description) { formattedResponse += `\n## Description\n\n${issue.renderedFields?.description || issue.fields.description}\n`; } if (issue.fields.comment && issue.fields.comment.comments && issue.fields.comment.comments.length > 0) { formattedResponse += `\n## Comments (${issue.fields.comment.comments.length})\n\n`; issue.fields.comment.comments.forEach((comment: any, index: number) => { const commentDate = new Date(comment.created).toLocaleString(); formattedResponse += `### Comment ${index + 1} - ${comment.author.displayName} (${commentDate})\n\n`; formattedResponse += `${comment.body}\n\n`; }); } if (issue.fields.attachment && issue.fields.attachment.length > 0) { formattedResponse += `\n## Attachments (${issue.fields.attachment.length})\n\n`; formattedResponse += `| Filename | Size | Uploaded by | Date |\n`; formattedResponse += `|----------|------|-------------|------|\n`; issue.fields.attachment.forEach((attachment: any) => { const attachmentDate = new Date(attachment.created).toLocaleString(); const sizeInKb = Math.round(attachment.size / 1024); formattedResponse += `| ${attachment.filename} | ${sizeInKb} KB | ${attachment.author.displayName} | ${attachmentDate} |\n`; }); } if (issue.fields.worklog && issue.fields.worklog.worklogs && issue.fields.worklog.worklogs.length > 0) { formattedResponse += `\n## Work Log (${issue.fields.worklog.worklogs.length})\n\n`; formattedResponse += `| User | Time Spent | Date | Comment |\n`; formattedResponse += `|------|------------|------|--------|\n`; issue.fields.worklog.worklogs.forEach((worklog: any) => { const worklogDate = new Date(worklog.started).toLocaleString(); formattedResponse += `| ${worklog.author.displayName} | ${worklog.timeSpent} | ${worklogDate} | ${worklog.comment || 'No comment'} |\n`; }); } if (issue.changelog && issue.changelog.histories && issue.changelog.histories.length > 0) { formattedResponse += `\n## Change History\n\n`; formattedResponse += `| Date | User | Changes |\n`; formattedResponse += `|------|------|--------|\n`; issue.changelog.histories.forEach((history: any) => { const historyDate = new Date(history.created).toLocaleString(); const changes = history.items.map((item: any) => { return `${item.field} changed from "${item.fromString || 'none'}" to "${item.toString || 'none'}"`; }).join('; '); formattedResponse += `| ${historyDate} | ${history.author.displayName} | ${changes} |\n`; }); } return { content: [{ type: "text", text: formattedResponse }], isError: false, }; } catch (error: any) { let errorMsg = "An error occurred while retrieving the issue."; if (error.response) { if (error.response.status === 404) { errorMsg = `Issue ${issueKey} not found or you don't have permission to view it.`; } else { errorMsg = `Error ${error.response.status}: ${error.response.data?.errorMessages?.join(', ') || error.message}`; } } else if (error.message) { errorMsg = error.message; } return { content: [{ type: "text", text: `# Error\n\n${errorMsg}` }], isError: true, }; } }
  • Yup validation schema for jira_get_issue input parameters, extending base Jira API schema with required issueKey validation.
    export const JiraIssueRequestSchema = JiraApiRequestSchema.shape({ issueKey: yup.string() .required("Issue key is required") .matches(/^[A-Z][A-Z0-9_]+-[1-9][0-9]*$/, "Invalid issue key format. The correct format is PROJECT-123"), });
  • Registers the jira_get_issue tool in the toolConfigs map used by handleCallTool to map tool name to its schema and handler function.
    jira_get_issue: { schema: JiraIssueRequestSchema, handler: getIssue },
  • JSON schema description for the tool, including input schema properties for jiraHost, email, apiToken, issueKey.
    export const getIssueToolDescription = { name: "jira_get_issue", description: "Retrieves detailed information about a specific Jira issue by key", 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 || "", }, issueKey: { type: "string", description: "The Jira issue key (e.g., 'PROJECT-123')", }, }, required: ["issueKey"], }, };
  • Tool description registration in the listTools handler response for MCP tool listing.
    name: "jira_get_issue", description: "Retrieves details of a specific Jira issue by key", inputSchema: { type: "object", properties: { ...getCommonJiraProperties(), issueKey: { type: "string", description: "The Jira issue key (e.g., 'PROJECT-123')", }, }, required: ["issueKey"], }, },

Other Tools

Related Tools

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/samuelrizzo/jira-mcp-server'

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