get_issue
Retrieve detailed information about a specific Linear issue by providing its ID to access status, assignees, and related project data.
Instructions
Get detailed information about a specific issue
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| issueId | Yes | Issue ID |
Implementation Reference
- src/index.ts:445-643 (handler)The main handler for the 'get_issue' tool. It retrieves the issue by ID using LinearClient, fetches related entities (state, assignee, etc.), constructs a detailed issue object, extracts embedded images and image attachments, and returns a formatted JSON response.case "get_issue": { const args = request.params.arguments as unknown as GetIssueArgs; if (!args?.issueId) { throw new Error("Issue ID is required"); } const issue = await linearClient.issue(args.issueId); if (!issue) { throw new Error(`Issue ${args.issueId} not found`); } try { const [ state, assignee, creator, team, project, parent, cycle, labels, comments, attachments, ] = await Promise.all([ issue.state, issue.assignee, issue.creator, issue.team, issue.project, issue.parent, issue.cycle, issue.labels(), issue.comments(), issue.attachments(), ]); const issueDetails: { id: string; identifier: string; title: string; description: string | undefined; priority: number; priorityLabel: string; status: string; url: string; createdAt: Date; updatedAt: Date; startedAt: Date | null; completedAt: Date | null; canceledAt: Date | null; dueDate: string | null; assignee: { id: string; name: string; email: string } | null; creator: { id: string; name: string; email: string } | null; team: { id: string; name: string; key: string } | null; project: { id: string; name: string; state: string } | null; parent: { id: string; title: string; identifier: string } | null; cycle: { id: string; name: string; number: number } | null; labels: Array<{ id: string; name: string; color: string }>; comments: Array<{ id: string; body: string; createdAt: Date }>; attachments: Array<{ id: string; title: string; url: string }>; embeddedImages: Array<{ url: string; analysis: string }>; estimate: number | null; customerTicketCount: number; previousIdentifiers: string[]; branchName: string; archivedAt: Date | null; autoArchivedAt: Date | null; autoClosedAt: Date | null; trashed: boolean; } = { id: issue.id, identifier: issue.identifier, title: issue.title, description: issue.description, priority: issue.priority, priorityLabel: issue.priorityLabel, status: state ? await state.name : "Unknown", url: issue.url, createdAt: issue.createdAt, updatedAt: issue.updatedAt, startedAt: issue.startedAt || null, completedAt: issue.completedAt || null, canceledAt: issue.canceledAt || null, dueDate: issue.dueDate, assignee: assignee ? { id: assignee.id, name: assignee.name, email: assignee.email, } : null, creator: creator ? { id: creator.id, name: creator.name, email: creator.email, } : null, team: team ? { id: team.id, name: team.name, key: team.key, } : null, project: project ? { id: project.id, name: project.name, state: project.state, } : null, parent: parent ? { id: parent.id, title: parent.title, identifier: parent.identifier, } : null, cycle: cycle && cycle.name ? { id: cycle.id, name: cycle.name, number: cycle.number, } : null, labels: await Promise.all( labels.nodes.map(async (label: any) => ({ id: label.id, name: label.name, color: label.color, })) ), comments: await Promise.all( comments.nodes.map(async (comment: any) => ({ id: comment.id, body: comment.body, createdAt: comment.createdAt, })) ), attachments: await Promise.all( attachments.nodes.map(async (attachment: any) => ({ id: attachment.id, title: attachment.title, url: attachment.url, })) ), embeddedImages: [], estimate: issue.estimate || null, customerTicketCount: issue.customerTicketCount || 0, previousIdentifiers: issue.previousIdentifiers || [], branchName: issue.branchName || "", archivedAt: issue.archivedAt || null, autoArchivedAt: issue.autoArchivedAt || null, autoClosedAt: issue.autoClosedAt || null, trashed: issue.trashed || false, }; // Extract embedded images from description const imageMatches = issue.description?.match(/!\[.*?\]\((.*?)\)/g) || []; if (imageMatches.length > 0) { issueDetails.embeddedImages = imageMatches.map((match) => { const url = (match as string).match(/\((.*?)\)/)?.[1] || ""; return { url, analysis: "Image analysis would go here", // Replace with actual image analysis if available }; }); } // Add image analysis for attachments if they are images issueDetails.attachments = await Promise.all( attachments.nodes .filter((attachment: any) => attachment.url.match(/\.(jpg|jpeg|png|gif|webp)$/i) ) .map(async (attachment: any) => ({ id: attachment.id, title: attachment.title, url: attachment.url, analysis: "Image analysis would go here", // Replace with actual image analysis if available })) ); return { content: [ { type: "text", text: JSON.stringify(issueDetails, null, 2), }, ], }; } catch (error: any) { console.error("Error processing issue details:", error); throw new Error(`Failed to process issue details: ${error.message}`); } }
- src/index.ts:256-258 (schema)TypeScript type definition for the input arguments of the get_issue tool.type GetIssueArgs = { issueId: string; };
- src/index.ts:207-216 (schema)JSON schema definition for the input parameters of the get_issue tool, as exposed in the listTools response.inputSchema: { type: "object", properties: { issueId: { type: "string", description: "Issue ID", }, }, required: ["issueId"], },
- src/index.ts:204-217 (registration)Registration of the get_issue tool in the listTools handler response, including name, description, and input schema.{ name: "get_issue", description: "Get detailed information about a specific issue", inputSchema: { type: "object", properties: { issueId: { type: "string", description: "Issue ID", }, }, required: ["issueId"], }, },
- src/index.ts:46-54 (registration)Server capabilities declaration indicating support for the get_issue tool.tools: { create_issue: true, list_issues: true, update_issue: true, list_teams: true, list_projects: true, search_issues: true, get_issue: true, },