Skip to main content
Glama
keegancsmith

Linear Issues MCP Server

by keegancsmith

linear_get_issue_with_comments

Retrieve a Linear issue with all comments and complete details using its URL or identifier. This tool fetches issue information for analysis and collaboration.

Instructions

Fetch a Linear issue with all its comments and complete information.

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 that executes the core logic for the linear_get_issue_with_comments tool by invoking the shared fetchLinearIssue helper with comments enabled.
     * Tool handler for linear_get_issue_with_comments - Fetches a Linear issue with its comments
     * @param {Object} params - Parameters from the tool call
     * @param {string} params.issue - Linear issue URL or ID
     * @returns {Object} - Response object with issue details and comments or error
     */
    async function getLinearIssueWithComments({ issue }) {
      return fetchLinearIssue(issue, true);
    }
  • Zod input schema defining the 'issue' parameter as a string with description.
    {
      issue: z
        .string()
        .describe(
          "Linear issue URL or identifier (e.g., 'ENG-123' or 'https://linear.app/team/issue/ENG-123/issue-title')"
        ),
    },
  • MCP server tool registration including name, description, schema, handler, and annotations.
    server.tool(
      "linear_get_issue_with_comments",
      "Fetch a Linear issue with all its comments and complete information.",
      {
        issue: z
          .string()
          .describe(
            "Linear issue URL or identifier (e.g., 'ENG-123' or 'https://linear.app/team/issue/ENG-123/issue-title')"
          ),
      },
      getLinearIssueWithComments,
      {
        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
        },
      }
    );
  • Shared helper function that implements the main logic for fetching Linear issues via GraphQL API, parsing URLs, handling authentication, formatting data including comments, and error handling.
    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,
        };
      }
    }

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