Skip to main content
Glama
tiovikram

Linear MCP Server

by tiovikram

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
NameRequiredDescriptionDefault
issueIdYesIssue ID

Implementation Reference

  • 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}`);
      }
    }
  • TypeScript type definition for the input arguments of the get_issue tool.
    type GetIssueArgs = {
      issueId: string;
    };
  • 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,
    },

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/tiovikram/linear-mcp'

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