radish2951/linear-lite-mcp
If you are the rightful owner of linear-lite-mcp and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to dayong@mcphub.com.
A lightweight Linear MCP server on Cloudflare Workers designed to minimize payload size and avoid UUID floods.
Linear Lite MCP Server
A lightweight Linear MCP server on Cloudflare Workers. This implementation uses GraphQL field selection to minimize payload size and avoid UUID floods.
Design Philosophy
- Minimal Payload: Only fetch essential fields in list views
- Two-Stage Fetch: Lean lists + detailed gets on demand
- Flat Structure: No nested objects (e.g.,
assigneeNameinstead ofassignee.name) - Type-Safe: Full TypeScript with Cloudflare Workers types
Available Tools
Note: Tool inputs accept human-readable names instead of IDs. The server resolves them to Linear IDs at runtime, so duplicate team/user/label names may lead to ambiguous matches—keep names unique for reliable results.
issues_list
List issues with minimal payload. Returns only essential fields:
identifier,title,state,priorityprojectName(flattened)dueDate
Default behavior: Excludes both completed/canceled and backlog issues.
Parameters:
query(optional): Freetext search across title and descriptionteamName(optional): Filter by team name (resolved to ID server-side)assigneeName(optional): Filter by assignee name (resolved to ID server-side)state(optional): Filter by state namepriority(optional): Filter by priority (0: No Priority, 1: Urgent, 2: High, 3: Medium, 4: Low)limit(optional): Number of results (1-100, default: 25)includeCompleted(optional): Include completed/canceled issues (default: false)includeBacklog(optional): Include backlog issues (default: false)updatedAt(optional): Filter by update time using ISO 8601 duration format (e.g., "-P1D" for last 24 hours, "-P7D" for last week)
issue_get
Get full issue details.
Parameters:
identifier(required): Issue identifier (e.g., "JHS-1")
Returns:
- Full issue details:
identifier,title,state,priority,projectName,dueDate,description,labels,assigneeName,creatorName,createdAt,updatedAt
workspace_overview
Fetch workspace metadata in a single call. Returns:
- Teams with keys, states, labels, and active projects
- Workspace-level labels and initiatives
- Active users (without IDs to keep payload small)
- Active issues: Up to 50 most recently updated issues (excludes completed, canceled, and backlog)
Parameters: None
issue_create
Create a new issue by human-friendly names. Resolves names to IDs internally before calling Linear.
Parameters:
teamName(required): Team to create the issue intitle(required): Issue titledescription(optional): Issue descriptionpriority(optional): Issue priority (0: No Priority, 1: Urgent, 2: High, 3: Medium, 4: Low)assigneeName(optional): Assign by user display namelabelNames(optional): Array of label names (team or workspace labels)projectName(optional): Associate with a projectstateName(optional): Set initial workflow state
Returns:
success: Boolean indicating if creation succeededissue.identifier: Created issue identifier
issue_update
Update an existing issue by human-friendly names. Resolves names to IDs internally before calling Linear.
Parameters:
identifier(required): Issue identifier (e.g., "JHS-1")title(optional): New titledescription(optional): New descriptionpriority(optional): New priority (0: No Priority, 1: Urgent, 2: High, 3: Medium, 4: Low)assigneeName(optional): Reassign by user display namelabelNames(optional): Replace labels with new array of label namesprojectName(optional): Move to a different projectstateName(optional): Change workflow state
Returns:
success: Boolean indicating if update succeeded
documents_list
List documents with minimal payload. Returns only essential fields:
title,slugId
Default behavior: Excludes archived documents.
Parameters:
query(optional): Freetext search by document title (note: content search not supported by Linear API)projectName(optional): Filter by project name (resolved to ID server-side)initiativeName(optional): Filter by initiative name (resolved to ID server-side)limit(optional): Number of results (1-100, default: 25)includeArchived(optional): Include archived documents (default: false)
document_get
Get full document details including content.
Parameters:
slugId(required): Document slug ID (e.g., "roadmap-2024")
Returns:
- Full document details:
title,slugId,url,icon,color,content,createdAt,updatedAt,archivedAt,creatorName,projectName,initiativeName
document_create
Create a new document by human-friendly names. Resolves names to IDs internally before calling Linear.
Parameters:
title(required): Document titleprojectName(required): Project to create the document incontent(optional): Document content in markdown
Returns:
success: Boolean indicating if creation succeededdocument.title: Created document titledocument.slugId: Created document slug IDdocument.url: Created document URL
document_update
Update an existing document by human-friendly names. Resolves names to IDs internally before calling Linear.
Parameters:
slugId(required): Document slug ID (e.g., "roadmap-2024")title(optional): New titlecontent(optional): New content in markdownprojectName(optional): Move to a different projectinitiativeName(optional): Associate with an initiative
Returns:
success: Boolean indicating if update succeeded
Setup
1. Install dependencies
pnpm install
2. Create a Linear OAuth Application
- Go to https://linear.app/settings/api/applications
- Click "Create new OAuth Application"
- Fill in the details:
- Name: Linear Lite MCP Server (or any name you prefer)
- Callback URLs: Add your callback URL(s):
- For local development:
http://localhost:8787/callback - For production:
https://your-worker-name.workers.dev/callback
- For local development:
- Save the application
- Copy the Client ID and Client Secret - you'll need these in the next step
3. Configure Secrets and Environment Variables
Required Secrets
# For local development (.dev.vars)
cat > .dev.vars << EOF
LINEAR_OAUTH_CLIENT_ID=your_linear_oauth_client_id
LINEAR_OAUTH_CLIENT_SECRET=your_linear_oauth_client_secret
COOKIE_ENCRYPTION_KEY=$(openssl rand -base64 32)
MCP_API_KEY_SECRET=$(openssl rand -base64 32)
PUBLIC_BASE_URL=http://localhost:8787
EOF
# For production deployment
wrangler secret put LINEAR_OAUTH_CLIENT_ID
wrangler secret put LINEAR_OAUTH_CLIENT_SECRET
wrangler secret put COOKIE_ENCRYPTION_KEY
wrangler secret put MCP_API_KEY_SECRET
# Also set PUBLIC_BASE_URL as an environment variable (not a secret)
# via the Cloudflare dashboard or wrangler.jsonc
Secret Descriptions:
LINEAR_OAUTH_CLIENT_ID/LINEAR_OAUTH_CLIENT_SECRET: OAuth credentials from LinearCOOKIE_ENCRYPTION_KEY: Used to encrypt session cookies and Linear tokens in KV storage (generate withopenssl rand -base64 32)MCP_API_KEY_SECRET: Required for/mcp-no-oauthendpoint security (generate withopenssl rand -base64 32)
Important: Each user will authenticate with their own Linear account via OAuth. The server does not use a shared API key.
Get your Linear OAuth credentials at:
- Linear OAuth: https://linear.app/settings/api/applications
4. Run locally
pnpm run dev
Server will be available at: http://localhost:8787/mcp
Note: As of MCP protocol version 2024-11-05, the standalone SSE transport is deprecated in favour of Streamable HTTP.1 This server therefore exposes only the Streamable HTTP endpoint at
/mcp.
5. Deploy to Cloudflare
pnpm run deploy
After deployment, don't forget to update your Linear OAuth application's callback URL to include your production URL: https://your-worker-name.workers.dev/callback
Usage Examples
Freetext search
{
"query": "ヒアリング"
}
Search issues by state
{
"state": "In Progress",
"limit": 10
}
Search high priority issues
{
"priority": 1,
"state": "Todo"
}
Combined search
{
"query": "API",
"state": "In Progress"
}
Search recently updated issues
{
"updatedAt": "-P1D",
"teamName": "Product"
}
Create an issue
{
"teamName": "Product",
"title": "API モニタリングを追加",
"assigneeName": "Daiki",
"labelNames": ["Backend"],
"priority": 2
}
Update an issue
{
"identifier": "JHS-1",
"stateName": "Done",
"priority": 1
}
Get issue details
{
"identifier": "JHS-1"
}
Fetch workspace overview
{}
List documents
{
"projectName": "Engineering",
"limit": 10
}
Search documents by title
{
"query": "roadmap",
"projectName": "Product"
}
Get document details
{
"slugId": "roadmap-2024"
}
Create a document
{
"title": "API Design Guidelines",
"projectName": "Engineering",
"content": "# API Design Guidelines\n\n## REST API Standards\n..."
}
Update a document
{
"slugId": "api-design-guidelines",
"content": "# Updated API Design Guidelines\n\n## REST API Standards\n...",
"initiativeName": "Platform Improvement"
}
Authentication Flow
When you first connect to this MCP server from Claude.ai or Claude Desktop:
- You'll be redirected to the Linear OAuth authorization page
- Log in with your Linear account and grant permissions
- You'll be redirected back to the MCP server
- The server will store your Linear access token securely
- All subsequent Linear API calls will use your own Linear account
Each user authenticates with their own Linear account, so you can only access the Linear workspaces and issues you have permission to view.
Connect to Claude Web (claude.ai)
- Go to Claude.ai
- Click on your profile → Settings → Integrations
- Add a new MCP server:
- URL:
https://your-worker-name.workers.dev/mcp
- URL:
- Follow the OAuth flow to authenticate with Linear
Connect to Claude Desktop
Add to your Claude Desktop config (~/.config/Claude/claude_desktop_config.json):
{
"mcpServers": {
"linear-lite": {
"command": "npx",
"args": [
"mcp-remote",
"http://localhost:8787/mcp"
]
}
}
}
For production, replace with your deployed URL: https://your-worker.workers.dev/mcp
When you first use the server, you'll be prompted to authenticate via OAuth in your browser.
: Model Context Protocol documentation, “Server-Sent Events (SSE) - Deprecated”.
Why Lightweight?
Traditional Linear integrations often return bloated payloads with:
- Full UUID chains for every nested object
- Unnecessary fields in list views
- Deep object nesting
This implementation:
- ✅ Returns only 7 fields in list views (vs. 20+ in typical implementations)
- ✅ Flattens nested objects to reduce token usage
- ✅ Separates "list" and "detail" operations
- ✅ Uses GraphQL field selection to avoid over-fetching
Result: ~70% smaller payloads for list operations.
Implementation Details
- Authentication: Linear OAuth 2.0 - each user authenticates with their own Linear account
- GraphQL Client: Minimal
fetch-based implementation (no Apollo overhead) - Type Safety: Full TypeScript with Cloudflare Workers bindings
- Security: OAuth tokens stored securely in Durable Objects session storage
- Rate Limiting: Respects Linear's rate limits automatically
- Multi-User: Supports multiple users, each with their own Linear workspace access
Future Enhancements
- Issue updates
- Document management (list, get, create, update)
- Project and Initiative search
- Webhook support for real-time updates
- Pagination with cursor support