get_issue_details
Retrieve comprehensive information for a specific Jira issue using its issue key to view details, status, and related data.
Instructions
Get full details of a specific Jira issue
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| issueKey | Yes | The issue key (e.g., "PROJ-123") |
Implementation Reference
- src/jira-client.ts:284-361 (handler)Core handler function that fetches detailed issue information from Jira REST API, processes ADF content, extracts recent comments, and maps parent issue data.export async function getIssueDetails(issueKey: string): Promise<JiraIssue> { const fields = ['summary', 'status', 'priority', 'updated', 'description', 'assignee', 'reporter', 'created', 'comment', 'project', 'parent']; const params = new URLSearchParams({ fields: fields.join(','), }); const response = await jiraFetch<{ key: string; fields: { summary: string; status: { name: string }; priority: { name: string }; updated: string; description?: unknown; assignee?: { displayName: string; accountId: string }; reporter?: { displayName: string; accountId: string }; created: string; comment?: { comments: Array<{ id: string; author: { displayName: string }; body: unknown; created: string; updated: string; }>; }; project?: { key: string; name: string; }; parent?: { key: string; fields: { summary: string; status: { name: string }; priority: { name: string }; issuetype: { name: string }; }; }; }; }>(`/issue/${issueKey}?${params.toString()}`); const comments: JiraComment[] = response.fields.comment?.comments.slice(-5).map((c) => ({ id: c.id, author: c.author.displayName, body: extractTextFromADF(c.body), created: c.created, updated: c.updated, })) || []; // Build parent object if present const parent: JiraIssueParent | undefined = response.fields.parent ? { key: response.fields.parent.key, summary: response.fields.parent.fields.summary, status: response.fields.parent.fields.status.name, priority: response.fields.parent.fields.priority?.name || 'None', issueType: response.fields.parent.fields.issuetype.name, } : undefined; return { key: response.key, summary: response.fields.summary, status: response.fields.status.name, priority: response.fields.priority?.name || 'None', updated: response.fields.updated, description: extractTextFromADF(response.fields.description), assignee: response.fields.assignee?.displayName, reporter: response.fields.reporter?.displayName, created: response.fields.created, comments, project: response.fields.project ? { key: response.fields.project.key, name: response.fields.project.name } : undefined, parent, }; }
- src/index.ts:349-413 (registration)MCP tool registration including input/output schemas and thin wrapper handler that validates input and delegates to the core getIssueDetails function.server.registerTool( 'get_issue_details', { title: 'Get Issue Details', description: 'Get full details of a specific Jira issue', inputSchema: { issueKey: z.string().describe('The issue key (e.g., "PROJ-123")'), }, outputSchema: { key: z.string().optional(), summary: z.string().optional(), description: z.string().optional(), status: z.string().optional(), priority: z.string().optional(), assignee: z.string().optional(), reporter: z.string().optional(), created: z.string().optional(), updated: z.string().optional(), comments: z.array(z.object({ id: z.string(), author: z.string(), body: z.string(), created: z.string(), updated: z.string(), })).optional(), project: z.object({ key: z.string(), name: z.string(), }).optional(), parent: z.object({ key: z.string(), summary: z.string(), status: z.string(), priority: z.string(), issueType: z.string(), }).optional(), error: z.object({ message: z.string(), statusCode: z.number().optional(), details: z.unknown().optional(), }).optional(), }, }, async ({ issueKey }) => { try { if (!issueKey || !issueKey.trim()) { throw new Error('issueKey is required'); } const issue = await getIssueDetails(issueKey); const output = { ...issue }; return { content: [{ type: 'text', text: JSON.stringify(output, null, 2) }], structuredContent: output, }; } catch (error) { const errOutput = formatError(error); return { content: [{ type: 'text', text: JSON.stringify(errOutput, null, 2) }], structuredContent: errOutput, isError: true, }; } } );
- src/jira-client.ts:25-41 (schema)TypeScript interface defining the structure of JiraIssue returned by getIssueDetails, used for type safety and matching the tool's outputSchema.export interface JiraIssue { key: string; summary: string; status: string; priority: string; updated: string; description?: string; assignee?: string; reporter?: string; created?: string; comments?: JiraComment[]; project?: { key: string; name: string; }; parent?: JiraIssueParent; }
- src/index.ts:351-391 (schema)Zod schemas for input (issueKey) and output (detailed issue fields matching JiraIssue) validation in the tool registration.{ title: 'Get Issue Details', description: 'Get full details of a specific Jira issue', inputSchema: { issueKey: z.string().describe('The issue key (e.g., "PROJ-123")'), }, outputSchema: { key: z.string().optional(), summary: z.string().optional(), description: z.string().optional(), status: z.string().optional(), priority: z.string().optional(), assignee: z.string().optional(), reporter: z.string().optional(), created: z.string().optional(), updated: z.string().optional(), comments: z.array(z.object({ id: z.string(), author: z.string(), body: z.string(), created: z.string(), updated: z.string(), })).optional(), project: z.object({ key: z.string(), name: z.string(), }).optional(), parent: z.object({ key: z.string(), summary: z.string(), status: z.string(), priority: z.string(), issueType: z.string(), }).optional(), error: z.object({ message: z.string(), statusCode: z.number().optional(), details: z.unknown().optional(), }).optional(), }, },
- src/jira-client.ts:190-206 (helper)Helper function to extract plain text from Jira's ADF (Atlassian Document Format) used in getIssueDetails for description and comment bodies.function extractTextFromADF(adf: unknown): string { if (!adf || typeof adf !== 'object') return ''; const doc = adf as { content?: unknown[] }; if (!doc.content) return ''; function extractText(nodes: unknown[]): string { return nodes.map((node) => { const n = node as { type?: string; text?: string; content?: unknown[] }; if (n.type === 'text' && n.text) return n.text; if (n.content) return extractText(n.content); return ''; }).join(' '); } return extractText(doc.content).trim(); }