# MCP Linear.app Server
A Model Context Protocol (MCP) server that enables MCP clients to interact with Linear.app's API for issue tracking, project management, and workflow automation.
## Features
- **Issue Management**: Create, update, list, search, and get detailed issue information
- **Project Management**: Create, update, list, archive, and get detailed project information with full team and member management
- **Custom Views**: Create, update, list, and delete custom filtered views for organizing issues
- **Team & Workflow Operations**: List teams and access workflow states
- **Cycle Management**: Create and manage sprints/cycles
- **Label Management**: Create and organize labels
- **User Operations**: List users and assign issues
- **Advanced Filtering**: Filter issues by status, assignee, project, labels, and more
- **Type-Safe**: Built with TypeScript and Zod validation for robust error handling
- **Production-Ready**: Comprehensive error handling, logging, and rate limit awareness
## Installation
### Prerequisites
- Bun 1.0.0 or higher (or Node.js 18.0.0+)
- A Linear.app account and API key
### Setup
1. Clone this repository:
```bash
git clone <repository-url>
cd mcp-linearapp
```
2. Install dependencies:
```bash
bun install
```
3. Create a `.env` file with your Linear API key:
```bash
cp .env.example .env
```
4. Edit `.env` and add your Linear API key:
```
LINEAR_API_KEY=lin_api_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
```
**How to get your Linear API key:**
1. Go to https://linear.app/settings/api
2. Click "Create new API key"
3. Give it a name and copy the key
4. Paste it into your `.env` file
5. Build the project:
```bash
bun run build
```
## Usage
### With MCP Clients
Add this server to your MCP client's configuration file. The configuration format may vary slightly depending on your client, but typically follows this pattern:
```json
{
"mcpServers": {
"linear": {
"command": "node",
"args": ["/absolute/path/to/mcp-linearapp/dist/index.js"],
"env": {
"LINEAR_API_KEY": "lin_api_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
}
}
}
```
After adding the configuration, restart your MCP client.
### With Other MCP Clients
The server uses stdio transport and can be integrated with any MCP-compatible client:
```bash
bun run dist/index.js
# or with Node.js:
node dist/index.js
```
## Available Tools
### Issue Management
#### `linear_list_issues`
List Linear issues with optional filters.
**Parameters:**
- `teamId` (optional): Filter by team ID
- `projectId` (optional): Filter by project ID
- `assigneeId` (optional): Filter by assignee user ID
- `status` (optional): Filter by status (backlog, unstarted, started, completed, canceled, triage, in_progress, done)
- `priority` (optional): Filter by priority (0=None, 1=Urgent, 2=High, 3=Medium, 4=Low)
- `label` (optional): Filter by label name
- `limit` (optional): Maximum number of issues (1-100, default: 25)
- `includeArchived` (optional): Include archived issues (default: false)
**Example:**
```
List all high priority issues assigned to me
```
#### `linear_create_issue`
Create a new Linear issue.
**Parameters:**
- `title` (required): Issue title
- `teamId` (required): Team ID where the issue will be created
- `description` (optional): Issue description in markdown
- `projectId` (optional): Project ID to assign the issue to
- `assigneeId` (optional): User ID to assign the issue to
- `priority` (optional): Priority (0-4)
- `labelIds` (optional): Array of label IDs
- `stateId` (optional): Workflow state ID
- `estimate` (optional): Estimate in points
- `dueDate` (optional): Due date (YYYY-MM-DD)
- `parentId` (optional): Parent issue ID for sub-issues
- `cycleId` (optional): Cycle ID to assign the issue to
**Example:**
```
Create an issue titled "Fix login bug" in the Engineering team with high priority
```
#### `linear_update_issue`
Update an existing Linear issue.
**Parameters:**
- `issueId` (required): Issue ID or identifier (e.g., "ENG-123")
- `title`, `description`, `assigneeId`, `priority`, `stateId`, `labelIds`, `estimate`, `dueDate`, `projectId`, `cycleId` (all optional)
**Example:**
```
Update issue ENG-123 to change priority to urgent and assign to John
```
#### `linear_get_issue`
Get detailed information about a specific issue.
**Parameters:**
- `issueId` (required): Issue ID or identifier (e.g., "ENG-123")
**Example:**
```
Get details for issue ENG-123
```
#### `linear_search_issues`
Search issues by text query.
**Parameters:**
- `query` (required): Search query text
- `teamId` (optional): Limit search to specific team
- `limit` (optional): Maximum results (1-100, default: 25)
- `includeArchived` (optional): Include archived issues
**Example:**
```
Search for issues about authentication
```
#### `linear_assign_issue`
Assign an issue to a user.
**Parameters:**
- `issueId` (required): Issue ID or identifier
- `assigneeId` (required): User ID to assign to
**Example:**
```
Assign issue ENG-123 to user abc-123
```
#### `linear_add_comment`
Add a comment to an issue.
**Parameters:**
- `issueId` (required): Issue ID or identifier
- `body` (required): Comment body in markdown
**Example:**
```
Add a comment to ENG-123 saying "This is fixed in the latest build"
```
### Team & Workflow
#### `linear_list_teams`
List all teams in your workspace.
**Parameters:**
- `includeArchived` (optional): Include archived teams (default: false)
**Example:**
```
List all teams
```
#### `linear_get_team`
Get detailed information about a specific team.
**Parameters:**
- `teamId` (required): Team ID
**Example:**
```
Get details for team abc-123
```
#### `linear_create_team`
Create a new Linear team.
**Parameters:**
- `name` (required): Team name
- `key` (required): Team key (1-5 uppercase letters, e.g., "ENG")
- `description` (optional): Team description
- `icon` (optional): Team icon (emoji)
- `color` (optional): Team color in hex format
- `timezone` (optional): Team timezone
- `private` (optional): Whether the team is private
**Example:**
```
Create a team called "Engineering" with key "ENG"
```
#### `linear_update_team`
Update an existing Linear team.
**Parameters:**
- `teamId` (required): Team ID
- `name`, `key`, `description`, `icon`, `color`, `timezone`, `private` (all optional)
**Example:**
```
Update team abc-123 to change the description
```
#### `linear_list_workflow_states`
List workflow states for a team.
**Parameters:**
- `teamId` (required): Team ID
**Example:**
```
List workflow states for team abc-123
```
### Projects
#### `linear_list_projects`
List all projects.
**Parameters:**
- `teamId` (optional): Filter by team ID
- `includeArchived` (optional): Include archived projects (default: false)
**Example:**
```
List all projects for the Engineering team
```
#### `linear_create_project`
Create a new Linear project.
**Parameters:**
- `name` (required): Project name
- `teamIds` (required): Array of team IDs this project is associated with
- `description` (optional): Project description
- `leadId` (optional): User ID of the project lead
- `memberIds` (optional): Array of user IDs for project members
- `color` (optional): Project color in hex format (e.g., "#FF0000")
- `icon` (optional): Project icon (emoji or icon name)
- `priority` (optional): Priority (0=None, 1=Urgent, 2=High, 3=Normal, 4=Low)
- `startDate` (optional): Planned start date (YYYY-MM-DD)
- `targetDate` (optional): Planned target/completion date (YYYY-MM-DD)
- `statusId` (optional): Project status ID
- `content` (optional): Project content in markdown format
**Example:**
```
Create a project called "Website Redesign" for the Design and Engineering teams with a target date of end of Q1
```
#### `linear_update_project`
Update an existing Linear project.
**Parameters:**
- `projectId` (required): Project ID
- `name`, `description`, `leadId`, `memberIds`, `color`, `icon`, `priority`, `startDate`, `targetDate`, `statusId`, `content`, `teamIds` (all optional)
- `state` (optional): Project state (planned, started, paused, completed, canceled)
**Example:**
```
Update project abc-123 to mark it as completed and set the target date to today
```
#### `linear_get_project`
Get detailed information about a specific project.
**Parameters:**
- `projectId` (required): Project ID
**Example:**
```
Get details for project abc-123
```
#### `linear_archive_project`
Archive a Linear project.
**Parameters:**
- `projectId` (required): Project ID to archive
**Example:**
```
Archive project abc-123
```
#### `linear_unarchive_project`
Unarchive a previously archived Linear project.
**Parameters:**
- `projectId` (required): Project ID to unarchive
**Example:**
```
Unarchive project abc-123
```
### Cycles (Sprints)
#### `linear_create_cycle`
Create a new cycle/sprint.
**Parameters:**
- `teamId` (required): Team ID
- `name` (required): Cycle name
- `description` (optional): Cycle description
- `startsAt` (required): Start date (YYYY-MM-DD)
- `endsAt` (required): End date (YYYY-MM-DD)
**Example:**
```
Create a 2-week sprint starting today for the Engineering team
```
#### `linear_list_cycles`
List cycles for a team.
**Parameters:**
- `teamId` (required): Team ID
- `includeArchived` (optional): Include archived cycles
**Example:**
```
List all active cycles for team abc-123
```
#### `linear_get_cycle`
Get detailed information about a specific cycle.
**Parameters:**
- `cycleId` (required): Cycle ID
**Example:**
```
Get details for cycle abc-123
```
#### `linear_update_cycle`
Update an existing cycle.
**Parameters:**
- `cycleId` (required): Cycle ID
- `name` (optional): New cycle name
- `description` (optional): New cycle description
- `startsAt` (optional): New start date (YYYY-MM-DD)
- `endsAt` (optional): New end date (YYYY-MM-DD)
**Example:**
```
Update cycle abc-123 to extend the end date by one week
```
#### `linear_archive_cycle`
Archive a cycle.
**Parameters:**
- `cycleId` (required): Cycle ID to archive
**Example:**
```
Archive cycle abc-123
```
#### `linear_unarchive_cycle`
Unarchive a previously archived cycle.
**Parameters:**
- `cycleId` (required): Cycle ID to unarchive
**Example:**
```
Unarchive cycle abc-123
```
### Custom Views
#### `linear_list_custom_views`
List all custom views.
**Parameters:**
- `includeArchived` (optional): Include archived custom views (default: false)
**Example:**
```
List all custom views
```
#### `linear_create_custom_view`
Create a new custom view with filters. Filters allow you to save specific issue queries for quick access.
**Parameters:**
- `name` (required): Custom view name
- `description` (optional): Custom view description
- `teamId` (optional): Team ID to associate the view with
- `projectId` (optional): Project ID to associate the view with
- `icon` (optional): View icon (emoji or icon name)
- `color` (optional): View icon color in hex format (e.g., "#FF0000")
- `shared` (optional): Whether the view is shared with everyone in the organization
- `filters` (optional): JSON object containing issue filters (see [Filters Guide](./docs/CUSTOM_VIEW_FILTERS.md))
**Filter Example:**
```json
{
"priority": { "eq": 1 },
"state": { "type": { "eq": "started" } },
"assignee": { "id": { "eq": "user-id" } }
}
```
**Example:**
```
Create a custom view called "My High Priority Bugs" that shows only high priority bugs assigned to me
```
**See also:** [Custom View Filters Guide](./docs/CUSTOM_VIEW_FILTERS.md) for comprehensive filter documentation
#### `linear_update_custom_view`
Update an existing custom view.
**Parameters:**
- `viewId` (required): Custom view ID
- `name`, `description`, `teamId`, `projectId`, `icon`, `color`, `shared`, `filters` (all optional)
**Example:**
```
Update custom view abc-123 to change the name and make it shared
```
#### `linear_get_custom_view`
Get detailed information about a specific custom view.
**Parameters:**
- `viewId` (required): Custom view ID
**Example:**
```
Get details for custom view abc-123
```
#### `linear_delete_custom_view`
Delete a custom view.
**Parameters:**
- `viewId` (required): Custom view ID to delete
**Example:**
```
Delete custom view abc-123
```
### Labels
#### `linear_create_label`
Create a new label.
**Parameters:**
- `name` (required): Label name
- `teamId` (required): Team ID
- `color` (optional): Color in hex format (e.g., "#FF0000")
- `description` (optional): Label description
**Example:**
```
Create a label called "bug" with red color for the Engineering team
```
#### `linear_list_labels`
List all labels.
**Parameters:**
- `teamId` (optional): Filter by team ID
**Example:**
```
List all labels
```
### Users
#### `linear_list_users`
List all users in your workspace.
**Parameters:**
- `includeDisabled` (optional): Include disabled users (default: false)
**Example:**
```
List all active users
```
## Workflow Examples
### Creating an Issue with Full Context
1. First, list teams to get the team ID:
```
List all teams
```
2. Optionally, list users to assign the issue:
```
List all users
```
3. Create the issue:
```
Create an issue titled "Implement OAuth authentication" in team abc-123, assign to user xyz-456, with high priority and description "Need to add OAuth 2.0 support for Google and GitHub"
```
### Managing a Sprint
1. Create a new cycle:
```
Create a 2-week sprint called "Q1 Sprint 3" for team abc-123 starting 2024-02-01
```
2. List issues to find what to include:
```
List backlog issues for team abc-123
```
3. Update issues to add them to the sprint and assign:
```
Update issue ENG-45 to add to cycle cycle-123 and assign to user xyz-456
```
### Tracking Progress
1. Search for issues in a specific area:
```
Search for issues about "authentication"
```
2. Get detailed information:
```
Get details for issue ENG-123
```
3. Add progress updates:
```
Add comment to ENG-123: "Authentication flow is complete, working on tests"
```
## Development
### Scripts
- `bun run build` - Build the TypeScript project
- `bun run dev` - Watch mode for development
- `bun start` - Start the MCP server
- `bun run lint` - Run ESLint
- `bun run format` - Format code with Prettier
- `bun run typecheck` - Type check without emitting files
### Project Structure
```
mcp-linearapp/
├── src/
│ ├── index.ts # Main MCP server entry point
│ ├── linear-client.ts # Linear API client wrapper
│ ├── tools/ # MCP tool implementations
│ │ ├── issues.ts # Issue-related tools
│ │ ├── projects.ts # Project tools
│ │ ├── cycles.ts # Cycle/sprint tools
│ │ ├── teams.ts # Team tools
│ │ ├── labels.ts # Label tools
│ │ └── users.ts # User tools
│ └── schemas/ # Zod validation schemas
│ └── index.ts
├── dist/ # Compiled JavaScript (generated)
├── package.json
├── tsconfig.json
└── README.md
```
### Architecture
The server is built with:
- **MCP SDK**: Handles the Model Context Protocol communication
- **Linear SDK**: Official Linear API client
- **Zod**: Runtime type validation and schema enforcement
- **TypeScript**: Type safety throughout the codebase
Key design decisions:
1. **Type Safety**: All inputs are validated with Zod schemas before reaching the Linear API
2. **Error Handling**: Comprehensive error handling with meaningful error messages
3. **Modular Design**: Tools are organized by domain (issues, projects, cycles, etc.)
4. **Client Wrapper**: LinearAPIClient provides a clean abstraction over the Linear SDK with consistent error handling and data formatting
## Error Handling
The server provides clear error messages for common issues:
- **Missing API Key**: "LINEAR_API_KEY environment variable is required"
- **Invalid Parameters**: Zod validation errors with specific field information
- **API Errors**: Linear API errors are caught and formatted with context
- **Not Found**: Clear messages when issues, teams, or other resources don't exist
## Rate Limiting
Linear's API has rate limits. The server doesn't implement client-side rate limiting, but:
- Uses the official Linear SDK which handles some retry logic
- Provides clear error messages when rate limits are hit
- Consider implementing delays between bulk operations
## Troubleshooting
### Server won't start
- Verify LINEAR_API_KEY is set in your environment
- Check that Bun version is 1.0.0 or higher (or Node.js 18.0.0+)
- Ensure `bun run build` completed successfully
### "Invalid API key" error
- Verify your API key is correct
- Check that the key hasn't been revoked in Linear settings
- Ensure there are no extra spaces in the .env file
### "Team not found" or similar errors
- Use `linear_list_teams` to get valid team IDs
- Use `linear_list_users` to get valid user IDs
- Use `linear_list_projects` to get valid project IDs
- Issue identifiers are case-sensitive (e.g., "ENG-123" not "eng-123")
### "Parent labels" or "label group" errors
Linear organizes labels hierarchically - some labels are **parent/group labels** that cannot be assigned directly to issues.
**The server now automatically handles this:**
- When creating or updating issues, parent labels are automatically filtered out
- You'll receive a warning message indicating which labels were skipped
- Use `linear_list_labels` to see which labels are parents (marked with `isParent: true`)
- Assign child labels instead of parent labels
**Example:**
```
Label "Module" (parent) has children:
- "Module/Auth"
- "Module/API"
- "Module/Frontend"
❌ Don't use: labelIds: ["module-id"] // Parent label - will be filtered
✅ Use instead: labelIds: ["module-auth-id"] // Child label - works!
```
### Changes not appearing in your MCP client
- Restart your MCP client after modifying the configuration
- Check your client's logs for connection errors
- Verify the absolute path in the configuration is correct
## Contributing
Contributions are welcome! Please:
1. Fork the repository
2. Create a feature branch
3. Make your changes with proper TypeScript types
4. Add/update tests if applicable
5. Run `bun run lint` and `bun run typecheck`
6. Submit a pull request
## Additional Documentation
- **[API Reference](./docs/API_REFERENCE.md)** - Complete documentation for all 32 MCP tools
- **[Custom View Filters Guide](./docs/CUSTOM_VIEW_FILTERS.md)** - Comprehensive guide to creating filtered views
- **[Quick Start Guide](./docs/QUICK_START.md)** - Get started in 5 minutes
- **[Deployment Guide](./docs/DEPLOYMENT.md)** - Deploy to production environments
- **[Development Guide](./DEVELOPMENT.md)** - Contribute to the project
## License
MIT
## Acknowledgments
- Built with the [Model Context Protocol SDK](https://github.com/modelcontextprotocol)
- Uses the [Linear SDK](https://github.com/linear/linear) for API access
- Inspired by the Linear community and MCP ecosystem
## Support
- Linear API Documentation: https://developers.linear.app/
- MCP Documentation: https://modelcontextprotocol.io/
- Report issues: [GitHub Issues](https://github.com/yourusername/mcp-linearapp/issues)