Skip to main content
Glama
keegancsmith

Linear Issues MCP Server

by keegancsmith

linear_get_issue

Fetch details of a Linear issue using its URL or identifier to access information and comments for project management.

Instructions

Fetch details of a single Linear issue by providing its URL or identifier.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
issueYesLinear issue URL or identifier (e.g., 'ENG-123' or 'https://linear.app/team/issue/ENG-123/issue-title')

Implementation Reference

  • The handler function for the 'linear_get_issue' tool. It extracts the 'issue' parameter and calls the shared fetchLinearIssue helper without comments.
    /**
     * Tool handler for linear_get_issue - Fetches a single Linear issue by URL or ID
     * @param {Object} params - Parameters from the tool call
     * @param {string} params.issue - Linear issue URL or ID
     * @returns {Object} - Response object with issue details or error
     */
    async function getLinearIssue({ issue }) {
      return fetchLinearIssue(issue, false);
    }
  • Zod input schema defining the 'issue' parameter (string: URL or ID) for the linear_get_issue tool.
    issue: z
      .string()
      .describe(
        "Linear issue URL or identifier (e.g., 'ENG-123' or 'https://linear.app/team/issue/ENG-123/issue-title')"
      ),
  • Registration of the 'linear_get_issue' tool on the MCP server, including name, description, schema, handler, and annotations.
    // Register the linear_get_issue tool
    server.tool(
      "linear_get_issue",
      "Fetch details of a single Linear issue by providing its URL or identifier.",
      {
        issue: z
          .string()
          .describe(
            "Linear issue URL or identifier (e.g., 'ENG-123' or 'https://linear.app/team/issue/ENG-123/issue-title')"
          ),
      },
      getLinearIssue,
      {
        annotations: {
          readOnlyHint: true, // This tool doesn't modify anything
          destructiveHint: false, // This tool doesn't make destructive changes
          idempotentHint: true, // Repeated calls have the same effect
          openWorldHint: true, // This tool interacts with the external Linear API
        },
      }
    );
  • Core helper function that implements the logic to fetch a Linear issue using GraphQL API, parse URL if needed, format response. Called by the handler.
    async function fetchLinearIssue(issue, includeComments = false) {
      // Get access token from environment variable
      const accessToken = process.env.LINEAR_API_TOKEN;
    
      if (!accessToken) {
        return {
          content: [
            {
              type: "text",
              text: "Error: No Linear API token found in environment. Set the LINEAR_API_TOKEN environment variable.",
            },
          ],
          isError: true,
        };
      }
      try {
        let issueId = issue;
    
        // Check if it's a URL and extract the ID if it is
        if (issue.startsWith("http")) {
          const parsedId = parseIssueIDFromURL(issue);
          if (!parsedId) {
            return {
              content: [
                {
                  type: "text",
                  text: `Error: Invalid Linear issue URL: ${issue}`,
                },
              ],
              isError: true,
            };
          }
          issueId = parsedId;
        }
    
        const data = await linearApiRequest(
          issueQuery,
          { id: issueId, includeComments },
          accessToken
        );
    
        if (!data.issue) {
          return {
            content: [
              {
                type: "text",
                text: `Error: Linear issue not found: ${issue}`,
              },
            ],
            isError: true,
          };
        }
    
        const issueData = data.issue;
    
        // Format the base issue data
        const formattedIssue = {
          identifier: issueData.identifier,
          title: issueData.title,
          url: issueData.url,
          description: issueData.description || "",
          state: issueData.state?.name || "",
          priority: issueData.priorityLabel || "",
          assignee: issueData.assignee
            ? issueData.assignee.displayName || issueData.assignee.name
            : "Unassigned",
          createdAt: new Date(issueData.createdAt).toISOString(),
          updatedAt: new Date(issueData.updatedAt).toISOString(),
        };
    
        // Add comments if requested
        if (includeComments && issueData.comments) {
          const formattedComments = (issueData.comments.nodes || []).map(
            (comment) => ({
              body: comment.body,
              author: comment.user
                ? comment.user.displayName || comment.user.name
                : "Unknown",
              createdAt: new Date(comment.createdAt).toISOString(),
            })
          );
          formattedIssue.comments = formattedComments;
        }
    
        return {
          content: [
            {
              type: "text",
              text: JSON.stringify(formattedIssue, null, 2),
            },
          ],
        };
      } catch (error) {
        return {
          content: [
            {
              type: "text",
              text: `Error fetching Linear issue${
                includeComments ? " with comments" : ""
              }: ${error.message}`,
            },
          ],
          isError: true,
        };
      }
    }
  • Helper function to parse Linear issue ID from a full URL, used in fetchLinearIssue.
     * Extracts an issue ID from a Linear URL
     * @param {string} url - The Linear issue URL
     * @returns {string|null} - The extracted issue ID or null if not a valid Linear issue URL
     */
    function parseIssueIDFromURL(urlStr) {
      try {
        const url = new URL(urlStr);
        if (!url.hostname.endsWith("linear.app")) {
          return null;
        }
        const match = url.pathname.match(/\/issue\/([a-zA-Z0-9_-]+)/);
        return match ? match[1] : null;
      } catch (e) {
        return null;
      }
    }

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/keegancsmith/linear-issues-mcp-server'

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