Skip to main content
Glama
magarcia

Linear MCP Server

linear_get_team_issues

Retrieve and filter issues assigned to a specific team in Linear, including options to limit results, filter by status, priority, assignee, and include archived items.

Instructions

Get issues for a specific team

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
assigneeIdNoFilter by assignee ID
includeArchivedNoInclude archived issues
limitNoMaximum number of issues to return (default: 50)
priorityNoFilter by priority level (0-4), where 0=no priority, 1=urgent, 4=low
statusNoFilter by issue status name
teamIdYesTeam ID to get issues for

Implementation Reference

  • The main handler function that executes the tool logic: fetches a Linear team by ID, applies optional filters for status, priority, assignee, and retrieves a list of issues with details like title, state, assignee, priority, URL, etc. Returns JSON or error.
    export const linearGetTeamIssuesHandler: ToolHandler = async args => {
      const params = args as {
        teamId: string;
        includeArchived?: boolean;
        limit?: number;
        status?: string;
        priority?: number;
        assigneeId?: string;
      };
    
      try {
        // Validate required parameters
        if (!params.teamId) {
          return {
            content: [
              {
                type: 'text',
                text: 'Error: Team ID is required',
              },
            ],
            isError: true,
          };
        }
    
        // Set up query parameters
        const queryParams: {
          first: number;
          includeArchived: boolean;
          filter?: {
            stateId?: { eq: string };
            priority?: { eq: number };
            assigneeId?: { eq: string };
          };
        } = {
          first: params.limit || 50,
          includeArchived: params.includeArchived || false,
        };
    
        // Get the team
        const team = await linearClient.team(params.teamId);
        if (!team) {
          return {
            content: [
              {
                type: 'text',
                text: `Error: Team with ID ${params.teamId} not found`,
              },
            ],
            isError: true,
          };
        }
    
        // Setup filter
        const filter: {
          stateId?: { eq: string };
          priority?: { eq: number };
          assigneeId?: { eq: string };
        } = {};
    
        // Add status filter if provided
        if (params.status) {
          const states = await team.states();
          const state = states.nodes.find(s => s.name.toLowerCase() === params.status?.toLowerCase());
    
          if (!state) {
            return {
              content: [
                {
                  type: 'text',
                  text: `Error: Status "${params.status}" not found for team ${await team.name}`,
                },
              ],
              isError: true,
            };
          }
    
          filter.stateId = { eq: state.id };
        }
    
        // Add priority filter
        if (params.priority !== undefined) {
          filter.priority = { eq: params.priority };
        }
    
        // Add assignee filter
        if (params.assigneeId) {
          filter.assigneeId = { eq: params.assigneeId };
        }
    
        // Add filter to query params if we have any filters
        if (Object.keys(filter).length > 0) {
          queryParams.filter = filter;
        }
    
        // Get team issues
        const issuesResponse = await team.issues(queryParams);
        if (!issuesResponse || !issuesResponse.nodes) {
          return {
            content: [
              {
                type: 'text',
                text: 'Error: Failed to fetch team issues',
              },
            ],
            isError: true,
          };
        }
    
        // Extract issue data
        const issueData = await Promise.all(
          issuesResponse.nodes.map(async issue => {
            const state = await issue.state;
            const assignee = await issue.assignee;
    
            return {
              id: await issue.id,
              identifier: await issue.identifier,
              title: await issue.title,
              description: await issue.description,
              state: state ? await state.name : null,
              assignee: assignee ? await assignee.name : null,
              priority: await issue.priority,
              url: await issue.url,
              createdAt: await issue.createdAt,
              updatedAt: await issue.updatedAt,
            };
          })
        );
    
        // Get team data
        const teamData = {
          id: await team.id,
          name: await team.name,
          key: await team.key,
          issues: issueData,
        };
    
        return {
          content: [
            {
              type: 'text',
              text: JSON.stringify(teamData),
            },
          ],
        };
      } catch (error) {
        const errorMessage =
          error instanceof Error
            ? error.message
            : typeof error === 'string'
              ? error
              : 'Unknown error occurred';
    
        return {
          content: [
            {
              type: 'text',
              text: `Error: ${errorMessage}`,
            },
          ],
          isError: true,
        };
      }
    };
  • Input schema defining the parameters for the linear_get_team_issues tool, including required teamId and optional filters.
    inputSchema: {
      type: 'object',
      properties: {
        teamId: {
          type: 'string',
          description: 'Team ID to get issues for',
        },
        includeArchived: {
          type: 'boolean',
          description: 'Include archived issues',
        },
        limit: {
          type: 'number',
          description: 'Maximum number of issues to return (default: 50)',
        },
        status: {
          type: 'string',
          description: 'Filter by issue status name',
        },
        priority: {
          type: 'number',
          description: 'Filter by priority level (0-4), where 0=no priority, 1=urgent, 4=low',
        },
        assigneeId: {
          type: 'string',
          description: 'Filter by assignee ID',
        },
      },
      required: ['teamId'],
    },
  • Registers the linear_get_team_issues tool with its name, description, input schema, and associates it with the handler function.
    export const linearGetTeamIssuesTool = registerTool(
      {
        name: 'linear_get_team_issues',
        description: 'Get issues for a specific team',
        inputSchema: {
          type: 'object',
          properties: {
            teamId: {
              type: 'string',
              description: 'Team ID to get issues for',
            },
            includeArchived: {
              type: 'boolean',
              description: 'Include archived issues',
            },
            limit: {
              type: 'number',
              description: 'Maximum number of issues to return (default: 50)',
            },
            status: {
              type: 'string',
              description: 'Filter by issue status name',
            },
            priority: {
              type: 'number',
              description: 'Filter by priority level (0-4), where 0=no priority, 1=urgent, 4=low',
            },
            assigneeId: {
              type: 'string',
              description: 'Filter by assignee ID',
            },
          },
          required: ['teamId'],
        },
      },
      linearGetTeamIssuesHandler
    );
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden of behavioral disclosure. It states the action ('Get issues') but doesn't describe whether this is a read-only operation, how results are returned (e.g., pagination, sorting), rate limits, or authentication needs. For a tool with 6 parameters and no annotation coverage, this is a significant gap in transparency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, efficient sentence ('Get issues for a specific team') that is front-loaded and wastes no words. It directly conveys the core purpose without unnecessary elaboration, making it highly concise and well-structured.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complexity of a tool with 6 parameters, no annotations, and no output schema, the description is incomplete. It doesn't explain return values, behavioral traits like pagination or sorting, or how to handle errors. For a read operation with filtering options, more context is needed to guide effective use.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has 100% description coverage, providing clear documentation for all 6 parameters (e.g., 'Filter by assignee ID', 'Include archived issues'). The description adds no additional parameter semantics beyond the schema, so it meets the baseline of 3 where the schema does the heavy lifting without compensating for gaps.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb ('Get') and resource ('issues for a specific team'), making the purpose immediately understandable. However, it doesn't differentiate from similar sibling tools like 'linear_get_user_issues' or 'linear_get_project_issues', which also retrieve issues but with different scopes, so it lacks sibling differentiation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives. It doesn't mention sibling tools like 'linear_get_user_issues' for user-specific issues or 'linear_get_project_issues' for project-specific issues, nor does it specify prerequisites such as needing a team ID. This leaves the agent without clear usage context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

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/magarcia/mcp-server-linearapp'

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