Skip to main content
Glama

linear-strict

Unofficial and opinionated. This is an independent project, not affiliated with or endorsed by Linear. It enforces one team's way of keeping tickets current, and it refuses writes that other Linear servers would make. For Linear's own MCP server, see linear.app/docs/mcp.

An MCP server for Linear for teams where agents keep tickets up to date. It reads a ticket whole and treats the description as the ticket's current state. The rules are enforced in the server, so a prompt that goes unread or a client hook that stops matching can't switch them off.

It has one runtime dependency, the MCP SDK. It began as a fork of tacticlaunch/mcp-linear (MIT), whose OAuth login it keeps.

The problem it addresses

Linear keeps full history, yet agents working from it drift:

  • State ends up in comments. A comment answers the ticket's open question and the description still says it is open. Nothing marks which claim is current.

  • Reads are lossy without saying so. Listings cut descriptions short, comment APIs default to newest first, and summaries read like the whole ticket.

  • Tickets change after they are read. An agent works from a snapshot, acceptance criteria are added later, and the work ships without them.

  • Rules in client hooks go dark when a server is renamed and the matcher no longer fires.

Related MCP server: Linear MCP Server

How it works

  • Description is state, comments are the log. The description has named sections: Observed, Cause, Fix, Done when, Open questions. It changes only through validated section patches. An Observed line must read YYYY-MM-DD · source · result (a time after the date is fine), and Done when lines must be checklist items.

  • A reconciled marker is the description's HEAD. It records the last comment the description accounts for, when that was checked, and the hash of the description it was checked against. It lives in one attachment on the ticket, titled "linear-strict: description reconciled through …", so the description stays clean. Every read reports comments after it, comments edited since the check, and edits to the description made outside this server, as drift.

  • Repair on read. Not everyone on a team will use this server. get_issue reports format findings and drift on tickets written from any client, and tells the agent to fold them into the description.

  • Whole reads. Every comment, oldest first, across all pages. list_issues and the workspace lists (teams, cycles, projects, initiatives) walk every page too, so an agent never holds a cursor it can stop following. Anything not fetched is listed in omitted; a gap is never silent.

  • Typed comments. evidence, correction, ask, answer and closed_by. A correction must carry the description patch that makes it true. An answer flips its question row. closed_by also sets the Linear relation.

  • Writes name what they were written against. get_issue returns a hash of the description, description_sha. A patch passes it as base and is refused, with what changed, if the description moved since that read. Linear has no conditional update, so this is how a patch shows it was built from the current text.

  • Claim, then a Done gate. claim records the description as it stands. Moving to a completed state needs a Done when section with every item ticked and cited (- [x] item · <SHA, PR, file:line, link, CI run, Observed 2, or a command and its result>), any cited PR that is linked to the ticket merged, and your claim, and is refused with a diff if the description changed since then. Priority or label changes don't count. Dropping an unticked item needs a reason and a yes from the person at the client, or from a model judge in unattended sessions.

  • Shipped-state facts. A ticket marked Done or Merged with no linked pull request, or with PRs merged only into a non-main branch, gets a finding. The facts come from Linear's GitHub attachment metadata.

  • A hands-off label. A ticket labelled no-agents (configurable) is people-only: every write through this server is refused, and reads still work.

  • Authorship. An agent (app) token writes as the agent. A personal key writes comments headed 🤖 <agent> via <person>. Each comment on a read is marked agent or person, with the basis for that call.

  • Linear's agent best practices warn that "Comments may not be reliable to read from, as they are editable and may have changed since your agent’s last run." Their answer, Agent Activities, covers agents running in Linear's Agent Sessions. Here, drift lists comments edited after the description accounted for them.

  • Linear's agent team found it "more effective to encode constraints into the design of Linear Agent’s tools than to spell them out in a prompt", which is the approach this server takes. claim follows their delegation model: a person stays the assignee, accountable for the result, and the agent is the delegate.

  • Linear keeps version history and text attribution for documents. description_history reads the same snapshots for an issue's description.

  • OpenAI's Symphony keeps an agent's progress in one persistent comment per ticket and tells the agent to leave Backlog tickets alone. This server keeps that state in the description, which Linear versions and every client shows first, and enforces the hands-off label in the server rather than in the prompt.

  • Cyrus has each sub-issue's agent hand back verification commands for the parent to run, and openclaw-linear-plugin has a separate auditor so the worker "cannot self-certify". The Done gate here asks for cited evidence but still lets the agent that did the work supply it.

  • Staleness in the wild: herdr-factory#97 shipped work against a ticket snapshot that lacked acceptance criteria added later, trac-mcp#57 had an agent stop trusting an MCP server after silent data loss, and beads#3708 and catalyst-otel#68 had Linear mirrors go stale without saying so.

Install

Quickstart (Claude Code)

  1. Get a Linear credential. A personal API key (Linear → Settings → Security & access → Personal API keys) writes as you. An agent (app) token, an OAuth token for a Linear app with actor=app starting with lin_oauth_, writes under the agent's own identity and can be set as a ticket's delegate.

  2. Add the server and the sign-off hooks:

    npm install -g https://github.com/justinstimatze/linear-strict/releases/download/v0.2.0/linear-strict-0.2.0.tgz
    claude mcp add linear-strict -e LINEAR_API_TOKEN=<token> -- linear-strict
    linear-strict install
  3. Reconnect with /mcp, then ask the agent to read a ticket.

You need Node 22 or later. Each GitHub release carries the built package; it is not on npm. To upgrade, npm install -g the newer release's .tgz, then run linear-strict install again and reconnect.

To work on it, run it from a checkout instead:

git clone https://github.com/justinstimatze/linear-strict.git
cd linear-strict && npm ci && npm run build
claude mcp add linear-strict -e LINEAR_API_TOKEN=<token> -- node "$PWD/dist/index.js"
node dist/index.js install

After a git pull, run npm run build again and reconnect the server.

Pin the version, and give the server its own name, linear-strict. Tool names such as get_issue also exist on Linear's official server, so the server name is what tells an agent and any hook matcher which rules apply. To sign in through the browser instead of pasting a token, see OAuth login.

The two hook installers

  • linear-strict install adds the sign-off hooks to ~/.claude/settings.json, once per machine. install --status says whether they are installed and whether they can still run; install --uninstall removes them and nothing else. Installed through npx, the hooks run the same pinned version through npx, since npm prunes the cache npx runs from. After upgrading, run install again so the hooks match the server; until then the server asks through the form.

  • examples/claude-code-hooks/install.sh is optional and per project: it refuses ticket writes through other Linear servers and runs a project's own Linear checks on strict writes (Blocking writes through other Linear servers). Its hooks run its scripts by path, so run it from a checkout or the global install above, not through npx.

The two write different entries and can both be installed.

Other clients

Claude Desktop, in claude_desktop_config.json, after the global install above:

{
  "mcpServers": {
    "linear-strict": {
      "command": "linear-strict",
      "env": { "LINEAR_API_TOKEN": "<token>" }
    }
  }
}

Everything except sign-off works the same in any MCP client. Sign-off depends on what the client offers:

Client

How a descope is approved

Claude Code with linear-strict install

AskUserQuestion, with the whole change in its preview box

Claude Code without the hooks

An elicitation form, with rows of about 100 characters

Other clients that support MCP elicitation

That client's elicitation form

Clients without elicitation, Claude Desktop included as far as its docs say

Refused; a person makes the edit in Linear, or run with LINEAR_STRICT_SIGN_OFF=judge

Hooks are a Claude Code feature, so no other client gets the preview route.

Sign-off

Dropping or rewording an unticked Done when item removes a check that has not passed, so someone other than the agent approves it. LINEAR_STRICT_SIGN_OFF picks who:

  • person (the default): the person at the client. In Claude Code with the sign-off hooks installed, set_state hands the agent an AskUserQuestion to put to them, and the change is shown in full in its preview box. A hook refuses the question if the agent changes a word of it, another hook records the answer, and the retry is approved from that record, never from what the agent says. Elsewhere, and in Claude Code without the hooks, the server asks through an MCP elicitation form, which Claude Code shows as rows of about 100 characters.

  • judge: a model with no stake in the ticket decides, so an unattended session never waits for someone who isn't there. It reads the ticket's description, the change, the reason and the risk, approves only when the description backs the reason, and the descope comment names the model and gives its reason for a person to review later. It needs an Anthropic API key: linear-strict auth judge-key set saves one from a hidden prompt to $XDG_CONFIG_HOME/linear-strict/anthropic-api-key (mode 600), next to the auth login credentials, or set ANTHROPIC_API_KEY in the server's environment, which wins. A key of its own, in a workspace with a spend limit, keeps the judge's cost on its own line. LINEAR_STRICT_JUDGE_MODEL overrides the model (default claude-opus-5-5). Each verdict is one API call of about 2 seconds, roughly 900 input tokens (most of them the cached brief) and 90 output tokens, well under a cent at Opus 5.5's rates (measured 2026-09-27). If the call fails (no credit, an outage, a refusal), the descope is refused with the error and nothing changes. MCP sampling would let the judge run on the client's own model with no key, but Claude Code doesn't offer it to servers (2.1.283 declares elicitation and roots only).

The hooks only guard against an agent cutting corners. An agent with a shell could still write an answer record by hand; a third hook refuses tool calls that name the records' directory, which closes the obvious route.

Blocking writes through other Linear servers

The server can only enforce its rules on writes that go through it. If Linear's official server is also connected, an agent can still edit a ticket there. examples/claude-code-hooks has Claude Code hooks that refuse ticket writes through other Linear servers and run a project's own Linear checks on strict writes. They are optional, and they are the only part of this setup that lives in the client.

OAuth login

linear-strict auth login signs in through the browser and stores a refreshing token, which the server uses when no token is set in its environment. It needs a Linear OAuth application of your own: create one at https://linear.app/settings/api/applications/new with the redirect URI http://localhost:8734/callback, then:

linear-strict auth login --client-id <client id>        # global install
node dist/index.js auth login --client-id <client id>   # from a checkout

The flow uses PKCE, so a client secret is optional. auth status shows whether you're signed in and when the token expires. auth logout revokes the token and deletes it. Credentials live in $XDG_CONFIG_HOME/linear-strict/credentials.json, readable only by you.

Configuration

Variable

Default

Purpose

LINEAR_API_TOKEN

—

Personal API key, or a lin_oauth_ token (sent as Bearer); --token on the command line also works

LINEAR_OAUTH_ACCESS_TOKEN

—

Any OAuth access token, sent as Bearer

LINEAR_STRICT_MAIN_BRANCH

main

Branch a PR must merge into for Done to count as shipped

LINEAR_STRICT_PRODUCTION_ENV

production

Environment named in posthog-<env>: flag labels that counts as live

LINEAR_STRICT_HANDS_OFF_LABELS

no-agents

Comma-separated labels that make a ticket people-only: every write through this server is refused, reads still work

LINEAR_STRICT_SIGN_OFF

person

Who approves dropping an unticked Done when item: person or judge (Sign-off)

LINEAR_STRICT_JUDGE_MODEL

claude-opus-5-5

The model that decides when LINEAR_STRICT_SIGN_OFF=judge

LINEAR_STRICT_OVERLAP

model

How create_issue finds the open tickets a new one overlaps: model has claude-sonnet-5-5 read every open title on the team when a judge key is set, else Linear's searches; search always uses the searches

ANTHROPIC_API_KEY

—

The judge's key, if not saved with auth judge-key set

LINEAR_STRICT_STATE_DIR

$XDG_STATE_HOME/linear-strict

Where claim records and pending sign-offs are kept

LINEAR_STRICT_CONFIG_DIR

$XDG_CONFIG_HOME/linear-strict

Where auth login stores credentials

LINEAR_STRICT_SINGLE_INSTANCE

1

0 turns off the check that lets a replaced server exit (below)

LINEAR_STRICT_DEBUG

—

1 logs startup detail to stderr

Claim records live on the machine running the server. A Done check from a machine with no claim on record is refused.

One server per connection

Claude Code's /mcp reconnect starts a new server and leaves the old one running with its pipes open, so the old one never sees its input close. Each server records its pid under LINEAR_STRICT_STATE_DIR/instances, keyed by its parent process and launch settings. When a newer server has replaced it and it has served no tool call for a minute since, the older one exits. A server whose parent exits, or whose input closes, exits too.

Reconciled marker

Each ticket this server has reconciled carries one attachment titled "linear-strict: description reconciled through date". It records the last comment the description accounts for, when that was checked, and a hash of the description at the time, so the next agent to read the ticket knows which comments are new and whether the description was edited elsewhere since. Deleting it does no harm: agents then check the whole thread again, and the next reconcile puts it back. It is written by whoever runs this server, not by Linear.

Tools

Tool

What it does

get_issue

Whole ticket, plus findings, drift, pull_requests, releases, claim and omitted

description_history

Past versions of the description with who made each and a diff; blame names the version behind every current line

list_issues

Every matching ticket in one call, paged to the end by the server: identifier, title, state, assignee, delegate and updatedAt, filterable by team, state, open, cycle and project; no description excerpts

claim

Take a ticket and snapshot its description; refuses one another agent holds

check_claim

Whether the description changed since your claim, with a diff

set_state

Patch description sections and/or move the reconciled marker

comment

Typed comment: evidence, correction, ask, answer, closed_by

set_status

Move to a workflow state; completed states pass the Done gate

set_fields

Priority, owner, labels, cycle, project, milestone, parent, dates, relations and linked PRs; never the description or state

create_issue

New ticket with validated sections, under a parent or in a project, placed against the closest open tickets

list_teams

Teams with their workflow states in board order

list_cycles

Cycles, active and next by default; pair a number with list_issues

list_projects, list_initiatives

Open projects and initiatives with status, owner and dates

notifications

Your inbox as pointers (ticket, type, actor, time), no excerpt text, paginated

get_principal_notifications

The same, for the human this identity acts for, on their own credential — needs LINEAR_PRINCIPAL_TOKEN/LINEAR_PRINCIPAL_ID configured

mark_principal_notifications_read

Mark the principal's notifications read: ones get_principal_notifications returned, by id or every one an agent caused

mark_notifications_read

Mark handled notifications read

whoami

The user or app behind the token, which is who claims and _is_me filters mean

The server also returns these rules as MCP instructions on initialize, so an agent learns the workflow when it connects. TOOLS.md has each tool's arguments, and docs/design.md the reasoning behind the rules, their limits, and what is still open.

From a script

A program that files tickets, such as a CI job turning test findings into tickets, can go through the same rules without an agent in between:

import { StrictLinear, OverlapRefusal, linearGql, memoryClaimStore } from 'linear-strict/library';

const strict = new StrictLinear({ gql: linearGql({ token }), claims: memoryClaimStore() });
try {
  await strict.createIssue({ team: 'ENG', title, sections, project_id });
} catch (error) {
  if (!(error instanceof OverlapRefusal)) throw error;
  // error.candidates: the closest open tickets. Comment on the one this repeats,
  // file under one with parent, or retry with new_because and distinct_from.
}

Citation audit

Tickets cite code by path:line and by commit hash, and nothing checks either once the ticket is written. The audit does, offline, in two steps:

linear-strict audit export --team ENG --out eng.jsonl
linear-strict audit check --export eng.jsonl --repo ~/src/app

export writes each ticket's description, every saved version of it, and its comments, open tickets first. That is about three API calls per ticket, spaced one ticket every --pace seconds (20 by default, about a fifth of a key's hourly quota), so a long export doesn't crowd out the key's other users. It saves every 25 tickets. A rerun with the same --out fetches only tickets updated since, and carries on where --max-fetch (500 by default), a rate limit or an interruption stopped the last run.

check reads that file and a git checkout and makes no network calls. Each citation is dated by the description version or comment it first appears in, then compared with the cited branch (--ref, default origin/main; a repo that lands work on a branch such as develop before main passes that) as it was on that date and as it is now:

Verdict

Meaning

holds

The cited lines read the same today

moved

The same lines are elsewhere in the file now; the finding gives the new line

changed

The cited lines say something else now; the finding gives both

file_gone

The file is no longer on the branch

trivial_line

The cited line is a brace or blank, so it can't anchor anything

line_missing_when_cited, not_in_tree_when_cited

The branch didn't have that line or file on the day it was cited, so it was cited from somewhere else

ambiguous_path

More than one file ends with the cited path

A commit-shaped hex string is on_main, off_main (--main, default origin/main), or not_a_commit_here, which is often a different kind of id: a comment, a request, a deployment. --json prints every finding; --issue narrows to named tickets.

Development

npm test         # typecheck, lint, format and unused-code checks, unit tests, MCP smoke test, and the sign-off routes end to end
npm run build
node scripts/e2e/sign-off.mjs --live-judge  # the same, with the judge on the real API (one call, well under a cent)
npm run test:live  # against a real workspace: creates temporary tickets on LIVE_TEAM and deletes them
npm run eval       # a model works tickets in the fake Linear through the strict tools; graded on final state
npm run format     # Prettier; `npm test` fails on unformatted code

git config core.hooksPath hooks once, after cloning, turns on the tracked pre-commit hook: a non-blocking CodeScene delta check on staged changes when cs is on PATH. It warns and never blocks the commit.

npm run test:live needs LINEAR_API_TOKEN and LIVE_TEAM (a team key). It writes to that workspace. npm run eval needs ANTHROPIC_API_KEY; evals/README.md covers cases, caching and results.

License

MIT. See LICENSE.md; the OAuth login code is from tacticlaunch/mcp-linear and keeps its notice.

Available Tools

19 tools
check_claimA
Read-onlyIdempotent

Whether the description changed since your claim, with a line diff. Run before opening or merging a PR for the ticket.

ParametersJSON Schema
NameRequiredDescriptionDefault
issueYesIssue identifier (e.g. ENG-123) or UUID

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, so the safety profile is covered. The description adds the temporal scoping ('since your claim') and the diff output shape. However, it doesn't say what happens when no claim exists or what the diff looks like in edge cases, leaving gaps beyond the annotation coverage.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences with zero filler; the core behavior and the invocation trigger are both front-loaded. Every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With rich annotations, a fully documented parameter, and an existing output schema, the description covers what the tool does and when to call it. Only minor edge-case behavior (no prior claim, empty diff) is missing, which is not essential for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and the single `issue` parameter is fully documented in the schema with a format example (ENG-123 or UUID). The description adds nothing parameter-specific, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific check: whether the ticket description changed since the caller's claim, plus a line diff of the change. It's phrased as a question rather than a verb+resource statement, but an agent can identify the operation. It relates to the `claim` and `description_history` siblings without explicitly distinguishing itself from them.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit timing guidance: 'Run before opening or merging a PR for the ticket.' This gives clear context for invocation. It does not name alternatives (e.g., description_history) or state when not to use it, so it falls short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

claimA
Destructive

Take a ticket and record the description as it stands, so a later Done check can tell whether it changed underneath you. Sets assignee to you when the ticket is unowned; sets delegate to you when a human owns it and you are an agent (app) identity. Refuses a ticket another agent holds. Claiming again after a change is how you acknowledge the new description.

ParametersJSON Schema
NameRequiredDescriptionDefault
asNoOverride the automatic choice
issueYesIssue identifier (e.g. ENG-123) or UUID
take_overNoTake the assignment from the person who holds it. Only when they handed it to you; a ticket held by another agent is never taken.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations flag it as destructive, non-read-only and non-idempotent, and the description adds substantial context beyond them: the refusal rule for other agents, the identity-dependent assignee/delegate behavior, and that re-claiming after a change is an acknowledgement act. These are behavioral traits the annotations cannot convey.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tightly packed sentences that lead with the core action and effect, then the routing rules, then the re-claim case. Dense but every clause carries information; no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists so return values need not be described. Combined with the annotations, the description covers identity semantics, refusal conditions, and the acknowledgement workflow, leaving no significant gap for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is already 100%, so the schema baseline is 3; the description adds meaning by explaining the automatic assignee/delegate choice that the 'as' override modifies, and reinforcing the take_over restriction. It goes beyond restating the schema, though it does not detail format for 'issue'.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

It states a specific verb and resource ('Take a ticket and record the description as it stands') and immediately differentiates the action from its sibling check_claim by explaining the later Done check that consumes the record. An agent can tell what this does without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit about when it applies (assignee when unowned, delegate when a human owns and you are an app identity), when it refuses (a ticket held by another agent), and the re-claim workflow as acknowledgement. This is when/when-not guidance rather than implied usage.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

commentA
Destructive

Post a typed comment. evidence: a finding, optionally with an Observed patch. correction: must carry the description patch that makes the description say the corrected thing. ask: adds an OPEN row to Open questions. answer: must name the row it closes (answers: "Q3") and flips it to ANSWERED with a link. closed_by: this ticket's work landed under another ticket; names it (closed_by), sets the Linear relation (relation "duplicate" or "fixed_there") and records it under Fix. Move the state separately with set_status.

ParametersJSON Schema
NameRequiredDescriptionDefault
baseNoRequired with patch. description_sha of the description this patch was written against: from get_issue, or from your last write to this ticket. The write is refused, with what changed, if the description has moved since.
bodyYesComment text, without a header: the server writes the header from kind and drops a copy typed here. For ask, the first line becomes the question row.
kindYes
issueYesIssue identifier (e.g. ENG-123) or UUID
patchNoDescription sections to change. Impact is the one plain-language line at the top saying who notices this work (mode replace). Observed lines must be "YYYY-MM-DD · <source: command, SHA or query> · <what it showed>". Done when lines must be checklist items ("- [ ] <check that proves it>"). Open questions changes only through comment kinds ask and answer.
ask_toNoFor kind ask: who should answer
answersNoFor kind answer: the question id, e.g. Q3
relationNoFor kind closed_by: duplicate (same problem) or fixed_there (a different ticket whose change fixed this one)
closed_byNoFor kind closed_by: the ticket that carried the work
author_labelNoAgent name for the comment header, e.g. the model. With a personal API key the header reads "<author_label> via <you>"; with an agent (app) token it defaults to the agent identity.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare the safety profile (destructive, non-idempotent, closed-world); the description goes further by disclosing the side effects of each kind — ask opens a row in Open questions, answer flips it to ANSWERED with a link, closed_by writes a Linear relation and records under Fix, patches mutate description sections. It does not mention the base/description_sha concurrency refusal (that lives only in the schema) or duplicate-post behavior, which keeps it from a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose is front-loaded in the first three words, and each following clause is a compact kind:behavior pair with no filler. It reads as a dense colon-separated block rather than flowing prose, but nothing in it is redundant against the schema or annotations.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 10-parameter, five-mode write tool with annotations and an output schema, the description covers the mode semantics and the sibling boundary that an agent needs. It leaves the return payload to the output schema (correct) and only omits failure/duplicate behavior that the schema's base note partially covers.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 90%, so the baseline is 3, but the description adds cross-parameter semantics the schema cannot express: which patch/kinds pair with which field (evidence → optional Observed patch, correction → mandatory description patch, answer → answers id, closed_by → closed_by + relation). That mapping is genuine added meaning over the enum listing.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a concrete verb+resource ("Post a typed comment") and then enumerates the five kinds, so an agent knows this is a polymorphic write endpoint rather than a generic note-taker. It also carves out scope against set_status ("Move the state separately"). The tool name "comment" alone is vague, but the description disambiguates it well.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Each kind carries its own condition of use and its prerequisite: correction "must carry the description patch", answer "must name the row it closes (answers: \"Q3\")", closed_by names the carrying ticket and sets the relation. It also states explicitly that state changes belong to set_status, which is a real exclusion. This is about as close to per-kind when-to-use guidance as a tool gets.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

create_issueA

Create a ticket. Before filing, ask whether the work is part of a ticket that already exists: widening that ticket, or filing under it with parent, keeps one change in one place. A new ticket needs a home, parent or project_id, and ends up in a project: a sub-ticket goes in its parent's, and a parent with no project is refused until it has one. A team with no open projects is exempt. Without a parent, the server finds the team's open tickets closest to this one and refuses until you've placed the work: under one of them (parent), into one of them (widen it and file nothing), or apart from all of them (new_because and distinct_from). The result lists what you filed on this team that no agent has taken up; filing a ticket is not doing the work, so see each into a queue. Its description is built from named sections (Observed, Cause, Fix, Done when), checked the same way set_state checks them. Include a Done when section if the ticket will be closed through set_status.

ParametersJSON Schema
NameRequiredDescriptionDefault
teamYesTeam key, e.g. ENG
titleYes
parentNoThe ticket this work is part of, identifier or UUID. A sub-ticket skips the check for close open tickets.
sectionsNoDescription sections to change. Impact is the one plain-language line at the top saying who notices this work (mode replace). Observed lines must be "YYYY-MM-DD · <source: command, SHA or query> · <what it showed>". Done when lines must be checklist items ("- [ ] <check that proves it>"). Open questions changes only through comment kinds ask and answer.
project_idNoThe project this ticket belongs to; list_projects gives the ids.
new_becauseNoWhy this work is separate from every close open ticket the server named, in one sentence of at most 300 characters. Posted on the new ticket.
distinct_fromNoEach close open ticket the server named, by identifier, that this one is separate from.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.3/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare the mutating, non-idempotent, non-destructive profile, and the description adds substantial behavior beyond that: the server auto-discovers the team's closest open tickets and refuses until placed, parent-without-project is refused, and the result lists filed tickets no agent has claimed. It also ties section validation to set_state and explains the Done-when/set_status dependency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

It is front-loaded with the core action, but the remaining prose is a long run-on chain of dependent clauses ('A new ticket needs a home... and ends up in a project...') that is harder to parse than necessary. Every sentence carries useful information, so it is not padding, but the structure could be tighter.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 7-param, mutating tool with conditional server-side refusals, the description covers the branching logic, required sections, and return summary well; an output schema exists so return values need no explanation. It leaves only minor gaps such as the exact shape of the refusal response, which is acceptable.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is already 86%, so baseline is 3, but the description adds real meaning on top: new_because is capped at 300 characters and posted on the ticket, distinct_from names the server-named tickets, and Done when sections must be checklist items. Only marginal gaps remain for `team`/`title`/`project_id` semantics, which the schema covers.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb+resource ('Create a ticket'), and the rest of the text clearly delineates it from siblings like comment, set_status and set_state by describing filing semantics. It is unambiguous for an agent, though the purpose statement is buried under a dense block of constraints rather than front-loaded crisply.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit when-to-use branches: widen an existing ticket, file under one with `parent`, or file apart using `new_because`/`distinct_from`. It also states the exemption (team with no open projects), the refusal conditions, and the requirement that a parent with no project is refused. This is a full decision tree, not vague guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

description_historyA
Read-onlyIdempotent

The description's past versions, from the snapshots Linear saves as it is edited: when, by whom, and a line diff against the version before. current says whether the live description is in a version yet, with a diff if not. With blame, every line of the current description names the version that introduced it and who made that version. Use it to see when and by whom a section or tick changed before overwriting or disputing it.

ParametersJSON Schema
NameRequiredDescriptionDefault
blameNoAlso attribute each current line to the version that introduced it
issueYesIssue identifier (e.g. ENG-123) or UUID

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare the safe read-only, idempotent, non-destructive profile, so the bar is lower. The description adds behavioral context beyond annotations by explaining snapshots, line diffs against the previous version, what `current` means, and how blame attributes each line to a version and author.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with a clear definition and proceeds logically through return semantics, blame behavior, and usage. It is appropriately sized for a tool with an output schema, though the `current` and `blame` sentences overlap somewhat with structured documentation.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With annotations covering safety and an output schema covering return fields, the description supplies all remaining context an agent needs: what the tool retrieves, what blame does, and when to reach for it. Nothing essential for correct invocation is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents both parameters, establishing a baseline of 3. The description elaborates on the `blame` effect and mentions `current`, but adds little syntax or meaning beyond what the schema already provides for `issue` and `blame`.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the resource: past versions of a description, with when, by whom, and line diffs. It is specific about what the tool returns, though it does not explicitly differentiate itself from sibling tools like get_issue or comment.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly says when to use it: to see when and by whom a section or tick changed before overwriting or disputing it. No alternative tools or when-not conditions are named, so it stops short of full routing guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_issueA
Read-onlyIdempotent

Read one ticket whole: full description, every comment oldest-first (all pages), who edited the description and when, relations, children, attachments. omitted lists anything not returned; an empty list means nothing was left out. findings lists format problems in the description and drift.unreconciled_comments lists comments the description may not reflect yet, and drift.edited_after_reconcile comments edited after it accounted for them. When drift.needs_reconcile is true, fold what those comments establish into the description with set_state (reconciled_through = newest comment id) before acting on the ticket. Tickets written from other clients get repaired this way. Pass issue.description_sha as base to the write that patches the description.

ParametersJSON Schema
NameRequiredDescriptionDefault
issueYesIssue identifier (e.g. ENG-123) or UUID

Output Schema

ParametersJSON Schema
NameRequiredDescription
claimNoYour claim on this ticket and whether the description changed since
driftNoComments after the reconciled marker, needs_reconcile and next_step
issueNoFull description and fields, description_sha (pass it as base when you patch the description), and open_questions parsed from the description
omittedNoAnything not fetched, with the reason; empty means nothing was left out
childrenNoSub-issues
commentsNoEvery comment, oldest first, each with author_kind (agent or person) and its basis
findingsNoFormat and shipped-state problems to fix with set_state
relationsNoBlocks, duplicates and related tickets, both directions
attachmentsNoOther attachments
comment_orderNoAlways oldest first
pull_requestsNoLinked GitHub PRs with status, target branch and merge time
description_editsNoWho changed the description and when, oldest first

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly/idempotent/non-destructive, so safety is covered. The description goes further by disclosing retrieval behavior (all comment pages, oldest-first) and the semantics of derived fields like `omitted` and `drift.unreconciled_comments`, plus the repair workflow for tickets edited by other clients. Return format details are partly duplicated by the output schema, but the drift semantics are genuinely additive.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose is front-loaded in the first clause, and every subsequent sentence carries substantive meaning for a tool with this many return structures. The middle sentences are dense run-ons packing several field semantics together, which costs a little readability but not enough to call it bloated.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, the description does not need to spell out every returned field, and it correctly focuses on interpretation (omitted, findings, drift) and the reconcile-first workflow. An agent has enough to call the tool and act on results, though the relationship to description_history for non-full reads is left unstated.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% with a single parameter already documented in-schema as 'Issue identifier (e.g. ENG-123) or UUID'. The description adds no syntax or format nuance for `issue` itself (description_sha is a field of the ticket, not the argument), so the baseline of 3 for high-coverage schemas applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb+resource ('Read one ticket whole') and enumerates exactly what is retrieved: description, comments oldest-first across all pages, editors, relations, children, attachments. This clearly separates it from list_issues (multiple tickets) and comment (writes) among the siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives concrete follow-up guidance: when drift.needs_reconcile is true, fold the flagged comments into the description via set_state using reconciled_through, and pass issue.description_sha as the base for the description patch. That names the alternative tool and the triggering condition, though it never explicitly says when to prefer get_issue over description_history.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_principal_notificationsA
Read-onlyIdempotent

The inbox of the human this identity acts for — a different person's notifications from notifications, which is this identity's own. Same shape, deliberately a separate tool rather than a parameter, so which inbox you're reading is never ambiguous. Errors if LINEAR_PRINCIPAL_TOKEN isn't configured for this identity, or if it resolves to someone other than LINEAR_PRINCIPAL_ID.

ParametersJSON Schema
NameRequiredDescriptionDefault
afterNonext_cursor from the previous call
firstNoHow many to return, default 50
sinceNoOnly notifications created on or after this date, e.g. 2026-09-24
unread_onlyNoDefault true

Output Schema

ParametersJSON Schema
NameRequiredDescription
noteNoHow to use these results
orderNoHow results are ordered
has_moreNoTrue when more results exist; pass next_cursor as after
next_cursorNoCursor for the next page
unread_countNoLinear's unread count
notificationsNoPointers: id, type, time, read, actor, actor_kind and the ticket
stopped_earlyNoPresent when a later page failed; next_cursor resumes there

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover the safety profile (readOnly, idempotent, non-destructive, closed world), so the bar is lower. The description still adds genuinely new behavior: it errors when LINEAR_PRINCIPAL_TOKEN is unconfigured or resolves to someone other than LINEAR_PRINCIPAL_ID, and it notes the payload mirrors `notifications`.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three front-loaded sentences that state what it reads, why it is separate from the sibling, and when it fails; nothing is redundant. The em-dash stacking makes it slightly denser than necessary, keeping it out of the top band.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists so return values need not be described, and annotations carry the safety profile. What remains — identity/principal semantics and the token-resolution error conditions — is exactly the context an agent needs before invoking, and it is all present.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% (all four params documented, including defaults and formats), so the schema does the heavy lifting. The description adds only the hint that the shape matches `notifications`; it gives no additional parameter semantics. Baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific resource (the principal's inbox) and immediately distinguishes it from the sibling `notifications`, which reads this identity's own inbox. The sentence 'Same shape, deliberately a separate tool rather than a parameter' makes the boundary with the sibling unambiguous without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description names the alternative (`notifications`) and the condition that selects it ('a different person's notifications'), plus the failure conditions under which this tool must not be used. It stops short of an explicit trigger phrase such as 'use when acting on behalf of the human', leaving a small amount of inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_cyclesA
Read-onlyIdempotent

Cycles, earliest first. Defaults to the active and next cycle. Use a cycle number with list_issues (cycle + team) to see its tickets.

ParametersJSON Schema
NameRequiredDescriptionDefault
teamNoTeam key; omit for every team
whenNocurrent (active and next, default), upcoming, past or all

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already establish readOnly, idempotent, non-destructive, and non-open-world behavior, so the safety profile is covered. The description adds genuinely useful behavior the annotations cannot convey: results are ordered earliest-first and the default window is the active and next cycle.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences, zero filler, with ordering and default scope front-loaded ahead of the cross-reference. Every clause carries information an agent can act on.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so the description need not explain return values, and the annotations cover safety. What remains is ordering and default scope, both stated; only a brief note on pagination or team-scoping behavior is absent, which is minor.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so both the team key and the when enum are fully documented in the schema; the description restates the default value ('active and next cycle') without adding format or syntax detail. The reference to a 'cycle number' describes a list_issues parameter rather than this tool's own inputs, so there is no real gain over the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The fragment 'Cycles, earliest first' names the resource and its ordering, and the follow-up sentence clarifies scope by noting the default of active-plus-next cycles. The verb is only implied (list), but the content is specific enough to separate it from list_issues, list_teams, and other siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It states the default scope and explicitly routes the agent to list_issues with a cycle number plus team to see a cycle's tickets, which is a concrete handoff condition. It does not state when-not to use this tool or contrast it with other listing tools, so it falls short of full when/when-not coverage.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_initiativesA
Read-onlyIdempotent

Initiatives with status, owner and target date. Unfinished ones only unless include_closed.

ParametersJSON Schema
NameRequiredDescriptionDefault
include_closedNoInclude completed initiatives

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly/idempotent/non-destructive, so the safety burden is lifted. The description adds a real behavioral fact not in the annotations: the default result set silently excludes completed initiatives unless include_closed is set. That is the kind of default-behavior disclosure that prevents miscalls.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short, front-loaded sentences with no filler. Slightly telegraphic ('Initiatives with status, owner and target date' reads as a fragment), but every clause carries information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, return values need no explanation, and annotations cover the safety profile. The description supplies the only missing piece an agent needs — the default filtering behavior — so it is essentially complete for a one-parameter list tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the single parameter's description ('Include completed initiatives') is already documented structurally. The description reinforces the include_closed semantics by stating the default filter, but adds no format or edge-case detail beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Names the resource (initiatives) and the fields it surfaces (status, owner, target date), so the agent knows what listing this returns. It does not differentiate from the many list_* siblings (list_issues, list_projects, list_cycles, list_teams), but the resource itself is unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The second sentence defines the default scope ('Unfinished ones only unless include_closed'), which is genuinely useful selection guidance. However, there is no statement of when to prefer this tool over alternatives or any prerequisite context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_issuesA
Read-onlyIdempotent

Every ticket matching the filters, in one call: the server pages through Linear to the end, so the answer is the whole set (total, by_state, and one row per ticket under columns). Rows hold identifier, title, state, assignee, delegate and updatedAt; there are no description excerpts, so read a ticket with get_issue before acting on it. More than 2000 matches is refused; narrow with open, state, cycle, project, assignee_is_me or delegate_is_me. When a task covers a set, work every row.

ParametersJSON Schema
NameRequiredDescriptionDefault
openNoOnly tickets not in a completed or canceled state
teamNoTeam key, e.g. ENG
cycleNoCycle number within team (list_cycles gives them); needs team
queryNoFull-text search term. Omit to list by most recently updated.
stateNoWorkflow state name, e.g. "In Progress"
projectNoProject name or id
assignee_is_meNo
delegate_is_meNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
rowsNoOne array per ticket: identifier, title, state, assignee, delegate, updatedAt; no descriptions
totalNoHow many tickets match; rows holds every one of them
columnsNoNames of the values in each row, in order
by_stateNoCount of matching tickets per workflow state
completeNoAlways true: a partial set is refused, never returned

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations cover the safety profile, but the description adds substantial non-obvious behavior: server-side pagination to completion, a hard refusal above 2000 matches, and the exact row columns returned. These are operational traits the annotations cannot express.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three dense sentences, front-loaded with scope, then return shape, then constraints and routing. No filler; every clause carries information (cap, pagination, columns, alternative tool).

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Even though an output schema exists, the description clarifies what the rows actually contain and the failure mode at 2000 matches. Combined with annotations and schema, an agent has everything needed to call and interpret this tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 75%, so the schema already documents most params. The description enumerates the narrowing filters, which adds modest signal about which params constrain the result set, but does not add format or syntax detail beyond the schema. Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Every ticket matching the filters, in one call') and distinguishes itself from get_issue by noting rows hold no description excerpts. An agent can tell what it returns and how it differs from the sibling detail tool without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes the agent: 'read a ticket with get_issue before acting on it', and 'narrow with open, state, cycle, project, assignee_is_me or delegate_is_me' when matches exceed 2000. Also names the use case 'when a task covers a set, work every row'. Covers when-to-use, when-not (too broad), and the alternative.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_projectsA
Read-onlyIdempotent

Projects with status, lead, teams, dates and progress. Open projects only unless include_closed.

ParametersJSON Schema
NameRequiredDescriptionDefault
teamNoTeam key
include_closedNoInclude completed and canceled projects

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, so the safety profile is covered. The description adds non-obvious behavior beyond that: results are filtered to open projects by default, which an agent would not know from the schema alone. It does not mention any pagination or result-limit behavior, keeping it short of a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences, no filler, with the returned-field summary front-loaded and the filtering caveat placed last where it is actionable. Nothing here is wasted or redundant.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, the description need not explain return values, and it correctly covers the default filtering behavior for a simple two-parameter read tool. The only mild gap is the team scoping parameter, which is left entirely to the schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents both parameters (team key, include_closed flag), making 3 the baseline. The description restates include_closed's semantics ('Open projects only unless include_closed') but says nothing about the team parameter's scoping behavior, so it adds little beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names the resource (projects) and enumerates the returned fields (status, lead, teams, dates, progress), which combined with the tool name 'list_projects' makes the operation unambiguous. It is distinguishable from sibling list_* tools (list_teams, list_issues, list_cycles), though it never states the verb explicitly and reads as a field listing rather than an action.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The clause 'Open projects only unless include_closed' tells the agent when the default behavior applies and how to widen it, which is real usage guidance. However, no alternatives are named and there is no statement about when to prefer this tool over, say, list_issues or list_cycles when scoping a query.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_teamsA
Read-onlyIdempotent

Every team with its key and workflow states in board order. State names are what set_status takes.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already establish readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is covered. The description adds genuinely useful context beyond them: entries are returned in board order and the returned state names are the valid inputs for set_status, which is a cross-tool contract not captured anywhere in structured fields.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short, declarative sentences with no filler, and the content description is front-loaded before the set_status cross-reference. Every sentence carries information an agent can act on.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, the description is not obliged to detail return values, and the annotations cover the safety profile. The set_status linkage supplies the main missing rationale for calling it, leaving little an agent needs that is absent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, so the baseline of 4 applies; there is nothing for the description to disambiguate. Schema coverage is reported at 100% with an empty property set, leaving no semantic gap to fill.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific resource (teams) and enumerates what each entry contains (key plus workflow states in board order), so an agent knows exactly what comes back. It does not explicitly distinguish itself from sibling list tools like list_projects or list_cycles, but the resource naming makes the boundary self-evident.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied rather than stated: by noting that 'state names are what set_status takes,' it signals this is the lookup to run before calling set_status. There is no explicit when-to-use or when-not-to-use framing and no named alternative to prefer in other situations.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

mark_notifications_readA
Idempotent

Mark notifications read once you have handled them. Reports each id separately.

ParametersJSON Schema
NameRequiredDescriptionDefault
idsYesIds from notifications

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare idempotentHint=true, destructiveHint=false and readOnlyHint=false, so the safety and repeatability profile is covered. 'Reports each id separately' hints at per-id outcome reporting, but with an output schema present that detail is already documented structurally, so the description adds only modest value.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences, zero filler, with the action and the timing cue front-loaded ahead of the reporting note.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-required-param tool with full schema coverage, annotations, and an output schema, the description covers the intent and the per-id reporting behavior. It is complete enough to invoke correctly, though it could say more about bulk failure handling.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the single 'ids' array parameter is fully described in the schema as 'Ids from notifications'. The description adds no syntax, ordering, or batch-limit meaning beyond that, so baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('mark notifications read') and scopes it with 'once you have handled them'. It is clearly distinguishable from the read-oriented sibling 'notifications', though it never names or contrasts with a sibling explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrase 'once you have handled them' gives an implied precondition for use, but there is no when-not guidance and no mention of alternatives such as the 'notifications' listing tool. Adequate but leaves routing to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

mark_principal_notifications_readA
Idempotent

Mark notifications in the inbox of the human this identity acts for as read — the write twin of get_principal_notifications, separate from mark_notifications_read so which inbox is written is never ambiguous. Only notifications get_principal_notifications returned in this server can be marked; others are refused per id. Pass ids, or only_agent_actors: true to mark every unread one an agent or integration caused (fleet bookkeeping), optionally only those created before a date. Needs a principal token with write access; a read-only one is refused with what to tell your user.

ParametersJSON Schema
NameRequiredDescriptionDefault
idsNoIds from get_principal_notifications
beforeNoWith only_agent_actors: only those created before this date, e.g. 2026-10-02
only_agent_actorsNoMark every unread notification an agent or integration caused, among those get_principal_notifications returned

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond annotations: per-id refusal of notifications not returned by the sibling read tool, the required principal token with write access, and the read-only-token failure mode with the message to relay to the user. Annotations cover the safety profile (idempotent, non-destructive), and the description adds prerequisite and partial-failure semantics.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the core action and the disambiguation before anything else, and every sentence carries new information. Slightly dense as a single paragraph with several parentheticals, but nothing is wasted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present the return shape need not be described, and the description still covers scope, selection modes, prerequisite auth, and partial-refusal behavior. Nothing an agent needs to call this correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3; the description adds meaning by framing only_agent_actors as 'fleet bookkeeping' and clarifying the interaction between before and only_agent_actors (only unread agent-caused notifications created before a date).

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (mark read) and resource (notifications in the principal's inbox), and explicitly positions itself as the write twin of get_principal_notifications and as distinct from the similarly named mark_notifications_read. An agent can disambiguate among siblings without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Names the two selection modes explicitly (pass ids, or only_agent_actors: true for agent/integration-caused unread notifications) and the alternative tools it must not be confused with. It also states the constraint that only notifications previously returned by get_principal_notifications are markable.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

notificationsA
Read-onlyIdempotent

Your Linear inbox, newest first, as pointers: ticket, notification type, who did it (agent or person) and when. Excerpt text is left out, so read the ticket with get_issue before acting. Unread only by default; paginated with next_cursor.

ParametersJSON Schema
NameRequiredDescriptionDefault
afterNonext_cursor from the previous call
firstNoHow many to return, default 50
sinceNoOnly notifications created on or after this date, e.g. 2026-09-24
unread_onlyNoDefault true

Output Schema

ParametersJSON Schema
NameRequiredDescription
noteNoHow to use these results
orderNoHow results are ordered
has_moreNoTrue when more results exist; pass next_cursor as after
next_cursorNoCursor for the next page
unread_countNoLinear's unread count
notificationsNoPointers: id, type, time, read, actor, actor_kind and the ticket
stopped_earlyNoPresent when a later page failed; next_cursor resumes there

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare a safe, idempotent read, so the bar is lower, yet the description adds real value: excerpt text is deliberately omitted, so a follow-up get_issue call is required before acting, and unread-only filtering is the default. It doesn't mention rate limits or the notification-type vocabulary, but the behavioral caveat it does give is the one an agent would otherwise get wrong.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences, front-loaded with what the tool is, then the critical caveat, then defaults. No sentence is filler; each carries a distinct fact.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need no explanation, and the description still covers the three things an agent needs: the pointer-only return shape, the pre-action read requirement, and pagination/default filtering. Nothing required to call it correctly is absent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so 'unread_only' default true and cursor paging are already documented in the schema; the description only restates them at a high level. Baseline 3 is appropriate — no new syntax, format, or constraint meaning is added.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific resource ('Your Linear inbox') plus ordering ('newest first') and the exact shape of each row (ticket, notification type, actor, timestamp). An agent can distinguish it from sibling list tools like list_issues and from the mutating mark_notifications_read without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes the agent onward ('read the ticket with get_issue before acting') and states the default filter and paging behavior. What's missing is a direct comparison point against mark_notifications_read or list_issues, but the when-to-use context is otherwise clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_fieldsA
Destructive

Change a ticket's fields other than its content: title, priority, assignee or delegate, labels, cycle, project, milestone, parent, due date, estimate, relations to other tickets, and linked GitHub pull requests. The description changes only through set_state and the workflow state only through set_status. Names are resolved to ids first and the whole call is refused if any is unknown or ambiguous, so nothing is half-applied. Taking a ticket from its current assignee needs take_over; another agent's ticket is refused, and so is one delegated to someone else unless it is assigned to the human this identity acts for (LINEAR_PRINCIPAL_ID): then take_over moves the delegation and a comment records it.

ParametersJSON Schema
NameRequiredDescriptionDefault
cycleNoCycle number, "current", "next", or null to remove it from its cycle
issueYesIssue identifier (e.g. ENG-123) or UUID
titleNo
blocksNoIssue identifiers this ticket blocks
parentNoParent issue identifier, or null
projectNoProject name or id, or null
assigneeNoName, display name, email or id, "me", or null to unassign
delegateNoAgent (app) user to delegate to, "me", or null to clear
due_dateNoYYYY-MM-DD, or null
estimateNo
link_prsNoGitHub pull request URLs to link to this ticket, such as the promotion PR that carried the work to main. Linear's GitHub integration then records where each merged, which the Done gate reads.
priorityNo0 none, 1 urgent, 2 high, 3 medium, 4 low
milestoneNoMilestone name in the ticket's project (or the project set in this call), or null
take_overNoRequired to change a person's assignment to someone else, or to move a delegation off another agent on a ticket assigned to the human you act for
add_labelsNoLabel names on the team or workspace. Labels are not created here.
blocked_byNoIssue identifiers that block this ticket
related_toNoIssue identifiers to mark as related
remove_labelsNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With annotations only declaring destructive=true, non-idempotent, and not read-only, the description adds critical behavioral context: names are resolved to IDs first, the entire call is refused if any name is unknown or ambiguous, and nothing is half-applied. It also discloses permission rules around reassignment, take_over, and delegations, which an agent could not infer from annotations alone.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is four dense sentences, all of which earn their place: purpose, alternatives, atomic validation behavior, and permission rules for assignment changes. It is front-loaded with the primary action and does not repeat annotation or schema content.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given 18 parameters, destructive annotations, an output schema, and 83% schema description coverage, the description supplies the missing high-level context: alternatives, atomic refusal behavior, and reassignment/delegation constraints. It does not need to explain return values because an output schema exists, and it covers the complexity inherent in this mutation tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 83%, so most parameters are already documented in the schema. The description lists the mutable field categories but does not add format, syntax, or edge-case meaning beyond what the schema provides for individual parameters. Baseline 3 is appropriate when structured fields carry the parameter semantics.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Change a ticket's fields other than its content.' It then enumerates the field categories and explicitly distinguishes the tool from set_state and set_status, which handle description and workflow state respectively. An agent can identify this as a field-mutation tool without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description names explicit alternatives and constraints: description changes go through set_state, workflow state through set_status, taking over an assignment needs take_over, and other agents' tickets are refused. It gives clear when-not conditions and routing guidance for an agent's own identity and for the human principal case.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_stateA
Destructive

Change what the ticket says is true by patching named description sections (Observed, Cause, Fix, Done when). The description is current state; comments are the log. Pass reconciled_through (a comment id) to record that the description now reflects the thread through that comment, with accounts_for saying how each skipped comment was handled. Tick a Done when item only once its check has run, and cite what showed it after the item text: "- [x] · ", where evidence is a commit SHA, a PR (#123), a file:line, a link, a CI run, "Observed 2" for a line under Observed, or command → result. A merge, a deploy, or being told something shipped is not the check; if nobody has run it, leave it open and say so. Removing or rewording an unticked Done when item needs descope_reason and descope_risk, and your user is asked to approve it from those two alone, so write them for someone without the ticket open. In Claude Code the call may come back asking you to put a question to your user with AskUserQuestion first; do exactly that, then retry with the sign_off token it gives.

ParametersJSON Schema
NameRequiredDescriptionDefault
baseYesdescription_sha of the description this patch was written against: from get_issue, or from your last write to this ticket. The write is refused, with what changed, if the description has moved since.
issueYesIssue identifier (e.g. ENG-123) or UUID
patchNoDescription sections to change. Impact is the one plain-language line at the top saying who notices this work (mode replace). Observed lines must be "YYYY-MM-DD · <source: command, SHA or query> · <what it showed>". Done when lines must be checklist items ("- [ ] <check that proves it>"). Open questions changes only through comment kinds ask and answer.
sign_offNoThe token from a set_state refusal that asked you to put a sign-off question to your user. Retry the same call with it after they answer.
accounts_forNoWith reconciled_through: for each comment the marker moves past, whether it was folded into this call's patch or changes nothing (with a reason). Typed comments that already changed the description count on their own. {comment: "*"} covers every comment not named.
descope_riskNoRequired with descope_reason: what stops being checked if your user approves, and what could get through because of it. At most 100 characters; they see it on one line as "If you accept".
descope_reasonNoRequired when the patch removes or rewords an unticked Done when item: why that check no longer applies. At most 100 characters; your user sees it on one line as "Why the agent wants it", and it is recorded as a comment. Keep the detail in Observed.
reconciled_throughNoId of the newest comment the description now reflects

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already flag destructive=true and non-idempotent, and the description adds substantial behavior beyond them: the base-SHA optimistic-concurrency refusal ('The write is refused, with what changed, if the description has moved since'), the sign_off/AskUserQuestion retry flow, and the user-approval path for descopes. This tells the agent exactly what can go wrong and how the call may return without mutating.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The core purpose and its contrast with comments are front-loaded, and most sentences carry non-obvious rules. It is dense and runs long with several parenthetical asides (source lists, Claude Code sign-off), which slightly taxes readability but each clause is doing work.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be described, and annotations carry the safety profile. Given the tool's complexity (8 params, nested patch array) the description covers the concurrency, sign-off, and descope flows that an agent would otherwise guess wrong; nothing essential is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 100% schema coverage the baseline is 3, but the description adds real meaning the schema lacks: the evidence format for ticked Done when items ('- [x] <item> · <evidence>'), what qualifies as a check versus a merge/deploy, and the semantics of reconciled_through/accounts_for ('accounts_for saying how each skipped comment was handled'). This meaningfully enriches several parameters beyond their structured definitions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb+resource: 'Change what the ticket says is true by patching named description sections (Observed, Cause, Fix, Done when).' It immediately distinguishes itself from the sibling comment tool ('The description is current state; comments are the log'), so an agent can tell it apart from comment/set_status without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives clear conditional guidance: pass reconciled_through to record the description reflects a thread, tick a Done when item only once its check has run, and require descope_reason/descope_risk when removing unticked items. It contrasts with comments as the alternative, though it never states when *not* to use set_state versus a plain comment.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_statusA
DestructiveIdempotent

Move a ticket to a workflow state by name. Moving to a completed state (Done) needs a Done when section with every item ticked and cited, any cited PR linked here merged, a linked PR merged into the main branch when any merged at all (link a promotion PR with set_fields link_prs), and your claim, and refuses, returning the diff, if the description changed since you claimed it. This call carries no evidence of its own: write it into the description with set_state first, where this check and any close gate a project hooks onto this tool read it. Moving to a canceled state skips those checks, so it needs reason, which is posted as a comment.

ParametersJSON Schema
NameRequiredDescriptionDefault
issueYesIssue identifier (e.g. ENG-123) or UUID
stateYesWorkflow state name
reasonNoWhy the work stops. Required for a canceled state, optional otherwise; posted as a comment.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.1/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the annotations by disclosing refusal behavior ('refuses, returning the diff, if the description changed since you claimed it'), the empty-evidence contract ('this call carries no evidence of its own'), external gate checks a project can hook, and the side effect that canceled reasons are posted as a comment. This is unusually rich behavioral disclosure layered on top of destructiveHint/idempotentHint.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The purpose is front-loaded in the first clause, but the remainder is a single tangled run-on sentence ('...and your claim, and refuses, returning the diff, if the description changed since you claimed it') that is grammatically broken and hard to parse. The content mostly earns its place, but the structure does not.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be explained, and the description still covers refusal/diff behavior. For a tool with conditional gates and mutation semantics, it conveys enough that an agent can call it correctly in both the completed and canceled paths, though the set_state cross-reference stays muddy.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds genuine semantic meaning about the 'state' parameter: completed names trigger Done-when gates and canceled names bypass checks and consume 'reason'. It does not add anything about 'issue' beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb+resource+scope: 'Move a ticket to a workflow state by name.' That is unambiguous about what the tool does. However, it does not differentiate itself from the confusingly similar sibling set_state, which it references as a separate tool for writing evidence, leaving the agent to disambiguate the two names on its own.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit conditional guidance: completed states require the Done-when checklist, merged PRs, and a claim, while canceled states skip those checks and need a reason. This is real when-to-use context. It stops short of stating when to prefer this over set_state or set_fields for state changes.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

whoamiA
Read-onlyIdempotent

Who this server acts as: the Linear user or app behind the token. Claims, assignee_is_me and delegate_is_me all mean this identity.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
idNoLinear user id
appNoTrue for an app (agent) identity, false for a person
nameNoUser name
displayNameNoDisplay name

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover readOnly/idempotent/non-destructive safety, so the bar is lower; the description adds meaningful context by explaining what the returned identity semantically drives (claims, self-referential fields). It does not need to explain return values since an output schema exists.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences, the core meaning front-loaded before the clarifying note about claims. No wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With zero params, a full output schema, and complete annotations, the description only needs to convey the identity's meaning and its relationship to related fields. It does so adequately.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, so the baseline is 4. There are no argument semantics to clarify beyond the empty schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States specifically what the tool reveals: the Linear user or app behind the token. It clearly identifies the resource and scope, though it does not explicitly name which sibling (e.g. check_claim vs claim) it differs from.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage by tying the result to claims, assignee_is_me, and delegate_is_me, giving the agent context for interpretation. However, it never states when to call this tool versus alternatives like check_claim, so guidance remains implicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 3 tool updatesv0.2.0
    • Changedcreate_issue4 fields changed
      • addedInput schema / properties / distinct_from
        Added value: +{
        +  "description": "Each close open ticket the server named, by identifier, that this one is separate from.",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
      • addedInput schema / properties / new_because
        Added value: +{
        +  "description": "Why this work is separate from every close open ticket the server named, in one sentence of at most 300 characters. Posted on the new ticket.",
        +  "type": "string"
        +}
      • changedInput schema / properties / parent / description
        Previous value: -"Parent issue identifier or UUID"New value: +"The ticket this work is part of, identifier or UUID. A sub-ticket skips the check for close open tickets."
      • addedInput schema / properties / project_id / description
        Added value: +"The project this ticket belongs to; list_projects gives the ids."
    • Addedmark_principal_notifications_read
    • Changedset_fields1 field changed
      • changedInput schema / properties / take_over / description
        Previous value: -"Required to change a person's assignment to someone else"New value: +"Required to change a person's assignment to someone else, or to move a delegation off another agent on a ticket assigned to the human you act for"
  2. 3 tool updatesv0.1.1
    • Changedcomment1 field changed
      • changedInput schema / properties / body / description
        Previous value: -"Comment text. For ask, the first line becomes the question row."New value: +"Comment text, without a header: the server writes the header from kind and drops a copy typed here. For ask, the first line becomes the question row."
    • Addedget_principal_notifications
    • Changedset_fields1 field changed
      • addedInput schema / properties / link_prs
        Added value: +{
        +  "description": "GitHub pull request URLs to link to this ticket, such as the promotion PR that carried the work to main. Linear's GitHub integration then records where each merged, which the Done gate reads.",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
  3. 17 tool updatesv0.1.0
    • First observedcheck_claim
    • First observedclaim
    • First observedcomment
    • First observedcreate_issue
    • First observeddescription_history
    • First observedget_issue
    • First observedlist_cycles
    • First observedlist_initiatives
    • First observedlist_issues
    • First observedlist_projects
    • First observedlist_teams
    • First observedmark_notifications_read
    • First observednotifications
    • First observedset_fields
    • First observedset_state
    • First observedset_status
    • First observedwhoami

TDQS

A4/5.0

Scored across 19 tools

Disambiguation4/5

The set is largely distinct and even deliberately splits near-twins (mark_notifications_read vs mark_principal_notifications_read, notifications vs get_principal_notifications) with explicit rationale. The one real risk is the set_state / set_status / set_fields triple, which share a prefix and could be mis-picked at a glance, though the descriptions clearly delimit each (content vs workflow state vs other fields).

Naming Consistency4/5

Most tools follow a verb_noun snake_case pattern (list_issues, create_issue, set_status, mark_notifications_read) with consistent prefixes for related operations. Minor deviations exist (whoami, notifications as a bare noun, claim), but overall the convention is readable and predictable.

Tool Count4/5

19 tools sits just above the well-scoped band, but the strict workflow governance (claim, check_claim, set_state, set_status, comment typing, principal-inbox separation) justifies most of them. Few tools appear redundant; the count is slightly heavy rather than bloated.

Completeness4/5

Issue lifecycle is well covered (create, read, list, field edits, state transitions, claims, comments, history) plus teams, projects, cycles, initiatives and notifications. Gaps are minor: no delete/archive, no single-team/user lookups, and no global search beyond list_issues filters.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables AI agents to manage a file-backed ticketing system directly within a local repository using a structured state machine and directory hierarchy. It enforces strict markdown schemas and provides specialized tools for claiming tasks, appending work logs, and validating ticket metadata.
    -
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables AI agents to manage Linear workspace resources such as issues, projects, teams, cycles, and comments via Streamable HTTP MCP, with LLM-optimized tools and batch operations.
    82 npm
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    Enables agents to manage an event-sourced, git-backed ticket store through MCP tools, supporting operations like ticket creation, claiming, and transitions.
    54 PyPI
    4
    Apache 2.0
  • F
    license
    A
    quality
    B
    maintenance
    Enables reading and managing Linear issues by human-readable ID, with tools for searching, creating, updating, commenting, and resolving teams, states, labels, and assignees by name.
    11
    -