MCP Linear.app Server
by MoshPitLabs
README.md
# MCP Linear.app Server
A Model Context Protocol (MCP) server that enables OpenCode and other 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 & Team Operations**: List projects and teams, 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 OpenCode
Add this server to your OpenCode configuration:
**macOS**: `~/Library/Application Support/OpenCode/opencode_config.json`
**Windows**: `%APPDATA%/OpenCode/opencode_config.json`
**Linux**: `~/.config/OpenCode/opencode_config.json`
```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 OpenCode.
### 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
**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` (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_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
```
### 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
```
### 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")
### Changes not appearing in OpenCode
- Restart OpenCode after modifying the configuration
- Check OpenCode 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
## 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)