A Linear MCP server for Dedalus.
- Python 3.11+
uv- A Linear workspace
cd linear-mcp
cp .env.example .env # then fill in your values
uv syncLinear uses OAuth2 for authentication. The Dedalus platform (DAuth) handles the
OAuth flow. The MCP server declares the secret name it needs (e.g. LINEAR_ACCESS_TOKEN).
OAuth provider configuration (consumed by the Dedalus platform):
| Variable | Description |
|---|---|
OAUTH_ENABLED |
true |
OAUTH_AUTHORIZE_URL |
https://linear.app/oauth/authorize |
OAUTH_TOKEN_URL |
https://api.linear.app/oauth/token |
OAUTH_CLIENT_ID |
Your Linear OAuth app client ID |
OAUTH_CLIENT_SECRET |
Your Linear OAuth app client secret |
OAUTH_SCOPES_AVAILABLE |
read,write,issues:create,comments:create |
OAUTH_BASE_URL |
https://api.linear.app |
Dedalus client configuration (for _client.py testing):
| Variable | Description |
|---|---|
DEDALUS_API_KEY |
Your Dedalus API key (dsk_*) |
DEDALUS_API_URL |
Defaults to https://api.dedaluslabs.ai |
DEDALUS_AS_URL |
Defaults to https://as.dedaluslabs.ai |
uv run src/main.pyuv run src/_client.pyThis opens an interactive agent loop. On first use, DAuth will prompt you to complete the Linear OAuth flow in your browser.
uv run --group lint ruff format src/
uv run --group lint ruff check src/ --fix
uv run --group lint ty check src/| Tool | R/W | Description |
|---|---|---|
linear_get_issue |
R | Get issue by ID or identifier (ENG-123) |
linear_list_issues |
R | List issues with filters |
linear_create_issue |
W | Create a new issue |
linear_update_issue |
W | Update an existing issue |
linear_list_comments |
R | List comments on an issue |
linear_create_comment |
W | Add a comment to an issue |
linear_get_project |
R | Get project by ID |
linear_list_projects |
R | List projects |
linear_create_project |
W | Create a new project |
linear_update_project |
W | Update an existing project |
linear_list_cycles |
R | List cycles for a team |
linear_get_cycle |
R | Get a cycle by ID |
linear_active_cycle |
R | Get the current active cycle for a team |
linear_list_teams |
R | List all teams |
linear_get_team |
R | Get a team by ID |
linear_list_team_states |
R | List workflow states (statuses) for a team |
linear_whoami |
R | Get authenticated user profile |
linear_list_users |
R | List workspace members |
linear_list_labels |
R | List labels |
linear_create_label |
W | Create a new label |
linear_search_issues |
R | Full-text search across issues |
21 tools (14 read, 7 write)
Linear uses a single GraphQL endpoint (POST /graphql) for all operations. The
request layer in src/linear/request.py dispatches queries through Dedalus's HTTP
enclave, which injects OAuth credentials transparently.
src/
├── linear/
│ ├── config.py # Connection definition (OAuth)
│ ├── request.py # GraphQL dispatch + coercion helpers
│ └── types.py # Typed dataclass models
├── tools/
│ ├── issues.py # Issue CRUD
│ ├── comments.py # Comment operations
│ ├── projects.py # Project CRUD
│ ├── cycles.py # Cycle queries
│ ├── teams.py # Team + workflow states
│ ├── users.py # User queries
│ ├── labels.py # Label operations
│ └── search.py # Issue search
├── server.py # MCPServer setup
├── main.py # Entry point
└── _client.py # Interactive agent loop (DAuth)
- Linear's API is GraphQL-only. Every tool dispatches a GraphQL query or mutation.
- Workflow states (statuses) vary per team. Use
linear_list_team_statesto discover valid state IDs before creating or transitioning issues. - Issue identifiers (e.g.
ENG-123) can be used interchangeably with UUIDs in most tools. - Priority values: 0 = No priority, 1 = Urgent, 2 = High, 3 = Medium, 4 = Low.
- Archived resources are hidden by default. Some tools accept
include_archivedto surface them. - Authentication uses OAuth2 via DAuth. Personal API keys are not supported in this server.