Read and write Linear issues, comments, projects, cycles, users, documents, initiatives, milestones, and more via the Linear MCP server. Attach chat-uploaded screenshots to issues.
72
91%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
High
Do not use without reviewing
Linear is reachable through the mcp_call tool. Each call hits the hosted Linear MCP server; the runtime resolves the Authorization header from the connected Linear token. You never see the token or the endpoint — you pass server: "linear" and a tool name.
Every Linear call has the same shape:
mcp_call({
server: "linear",
tool: "<tool name>",
arguments: { ... }
})The response is a JSON string. Parse it before reporting back to the user — Linear sometimes returns nested pageInfo or arrays you should summarize, not dump.
The full inventory of Linear MCP tools is in your system prompt under "Configured MCP servers — linear — tools: ...". That list is authoritative; do not assume a tool doesn't exist just because it isn't called out below. The categories below give you defaults and taste; reach for tools from the inventory list whenever the user asks for something outside them.
When you're unsure of a tool's argument shape, either:
mcp_call({ server: "linear", tool: "search_documentation", arguments: { query: "..." } }) to query Linear's own docs, orDo not refuse a Linear-related ask unless you've actually checked. "Linear doesn't support that" is a claim that requires evidence.
save_issue handles both create and update — with an id it updates, without one it creates.
mcp_call({ server: "linear", tool: "list_issues",
arguments: { assignee: "me", state: "started" } })
mcp_call({ server: "linear", tool: "get_issue",
arguments: { id: "LIN-123" } })
mcp_call({ server: "linear", tool: "save_issue",
arguments: { team: "ENG", title: "Login fails on Safari 17",
description: "Steps to reproduce…" } })Useful argument quirks Linear's tool descriptions sometimes leave terse:
assignee: "me" resolves to the authenticated viewer — no user-id lookup needed.team accepts the team key (ENG) or UUID.state accepts either the workflow state id or its display name ("In Progress", "Done"). Workflow state groups for filtering: backlog, unstarted, started, completed, cancelled.priority is 0|1|2|3|4 where 1 is urgent, 4 is low, 0 is no priority.list_issues truncates description for compactness. Follow up with get_issue when the user needs the full body.cursor from pageInfo.endCursor back into the same call.When the user provides images in chat and asks you to file or update a Linear issue, attach them after you know the issue identifier. The flow is three steps; the middle step (PUT bytes to Linear's signed URL) lives in the attachments skill — read_skill name='attachments' for the full reference. Linear-specific args are documented here.
Prepare (Linear-specific) — mcp_call({ server: "linear", tool: "prepare_attachment_upload", arguments: { issue, filename, contentType, size } }). The response carries uploadRequest.url, uploadRequest.headers, and assetUrl. The signed URL expires in 60 seconds; move immediately.
PUT the bytes (attachments skill) — skill_run({ skill: "attachments", script: "signed-upload", args: { uploadId, url: prep.uploadRequest.url, headers: prep.uploadRequest.headers } }). The script reads the upload off disk and PUTs it; the model never has to touch raw bytes. Returns { ok, status, bytesSent }.
Finalize (Linear-specific) — mcp_call({ server: "linear", tool: "create_attachment_from_upload", arguments: { issue, assetUrl, title, subtitle } }) with the assetUrl from step 1 and an optional title / subtitle.
Each user message that carries attachments ends with a system note listing each upload's id, mime type, and size:
Attached image uploads (in order):
- abc-123-... (image/png, 36116 bytes)
- def-456-... (image/jpeg, 24512 bytes)Read the size and mimeType from that marker — prepare_attachment_upload rejects requests where size doesn't match the actual bytes (GCS returns EntityTooLarge / EntityTooSmall). One 3-step sequence per image.
If the skill_run step returns ok: false, the bytes did not land. Don't run the finalize step; either re-prepare (the signed URL is dead after 60s) or tell the user the upload failed and offer to paste the assetUrl into the issue body manually.
To inspect or describe an attachment that's already on a Linear issue: combine mcp_call(get_attachment) with the attachments skill's signed-download script to land the bytes as a Gini upload, then vision_query to ask the model about the image. The attachments skill documents the full pattern — read_skill name='attachments'.
Use the matching tool from the inventory list in your system prompt. The shapes are predictable: list_* returns an array with pageInfo, get_* takes an id, save_* creates without id / updates with id, delete_* takes an id. Examples:
mcp_call({ server: "linear", tool: "list_teams", arguments: {} })
mcp_call({ server: "linear", tool: "list_projects", arguments: { team: "ENG" } })
mcp_call({ server: "linear", tool: "list_cycles",
arguments: { team: "ENG", type: "current" } }) // also "next", "previous"
mcp_call({ server: "linear", tool: "list_comments",
arguments: { issueId: "LIN-123" } })
mcp_call({ server: "linear", tool: "save_comment",
arguments: { issueId: "LIN-123", body: "Reproduced on macOS 14." } })
mcp_call({ server: "linear", tool: "list_issue_labels", arguments: { team: "ENG" } })
mcp_call({ server: "linear", tool: "list_issue_statuses", arguments: { team: "ENG" } })For label / status names passed to save_issue, confirm via list_issue_labels / list_issue_statuses first — Linear returns a generic validation error otherwise.
get_attachment returns metadata, not bytes. Outbound uploads (chat → Linear) work via the 3-step sequence above.mcp_call with server: "linear" (or signed_upload for the PUT step of attachment uploads). Do not call any other tool to reach Linear.search_documentation first.list_issues({ assignee: "me", state: "started" }) and summarize, not dump.LIN-123, not 123). Linear's deeplinks resolve those directly.6c5d85e
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.