All articles

Workflows

How to let an agent read Linear issues but wait for approval to write them

Tier Two7 min read

Suppose you want an agent to turn Monday's standup notes into comments on the right Linear issues. Finding the issues is a read, and a good agent does it well. Posting the comments is a write that the whole team sees within seconds, and one wrong match puts a confident paragraph on the wrong ticket. The same workflow needs two different levels of trust, and Linear's MCP server hands you both tools in one list.

There are two clean ways to draw the line. Linear can give the agent read-only access natively, and then a person does the writing. Or reads can run and writes can pause for a person to approve the exact call, either in your host's rules or in a shared policy. This is a walkthrough of both, with the actual endpoints, tool names and rule syntax.

The short answer

Use Linear's read-only endpoint or read scope when the deliverable is an answer: a summary, a triage list, a draft. When the deliverable is a change in Linear, keep the read tools on Allow and put save_issue and save_comment on Ask, in Claude Code or Cursor rules for one machine, or in a shared gate when the approver is someone else or there's more than one host.

What Linear gives you natively

Linear's MCP documentation describes a hosted server at mcp.linear.app/mcp with read-write access by default, and a second endpoint at mcp.linear.app/mcp/readonly that only ever exposes read tools. Setup runs OAuth 2.1 with dynamic client registration, so a host signs in as you and the token carries your permissions. Two more read-only routes exist: authorize the standard endpoint with only the read scope, or use an API key created with only the Read permission. The older /sse endpoint is deprecated.

Linear doesn't publish its tool list; the names below come from what the server returns to tools/list, and they can change. At the time of writing the reads include list_issues, get_issue, list_comments, list_projects, get_project, list_teams, list_users, list_cycles and search_documentation. The writes are save_issue and save_comment, which create or update, plus save_project and delete_comment. Notice there's no create_issue: one save tool covers create and update, which matters when you write a rule against the name.

Pick by the last action, not the cleverness of the analysis

The only question that decides the access shape is what a successful run ends with. If it ends with something delivered to the person, the agent never needed write access. If it ends with Linear changed, it did, and the question becomes who approves.

TaskA successful run ends withAccess shape
Summarize the cycle that just closedA summary in the chatRead-only endpoint
Find likely duplicates of a new bugA list of issue idsRead-only endpoint
Draft release notes from shipped issuesA draft the person editsRead-only endpoint
Triage inbound bugs into the right projectIssues updated in LinearReads on Allow, save_issue on Ask, scoped by project if the tool carries one
Turn standup notes into issue commentsComments postedReads on Allow, save_comment on Ask
Close issues untouched for 90 daysIssues closedsave_issue on Ask; consider approve once per batch
Clean up old commentsComments deleteddelete_comment on Block until a workflow needs it

The first three rows are most of what teams actually ask agents to do with Linear, and they need no approval design at all. Start there, and add the write path only for the workflow that earns it.

Option A: read-only, enforced by Linear, configured in the host

The simplest boundary is the one Linear enforces: point the host at the read-only endpoint and the write tools don't exist. In Claude Code that's one command, and the rules in your settings then only need to allow the reads you want to run without a prompt:

claude mcp add --transport http linear https://mcp.linear.app/mcp/readonly

# settings.json
{
  "permissions": {
    "allow": ["mcp__linear__list_issues", "mcp__linear__get_issue", "mcp__linear__list_comments"]
  }
}

In Cursor, add the same endpoint as an MCP server and, if you'd rather not click through every read, add patterns such as linear:list_* and linear:get_* to the mcpAllowlist in a permissions.json file. Cursor prompts for anything not listed. Either way the write tools are absent, so there's nothing to deny.

If you keep the read-write endpoint and rely on host rules instead, remember the precedence: in Claude Code, deny is checked before ask, and ask before allow, so a deny on mcp__linear__delete_comment holds no matter what an allow says. That's a gate on one machine, reviewed by the person driving the agent. Fine for one developer; it's the second person, or the second host, that makes the next option worth reading.

Option B: reads run, writes wait, in one place for everyone

In Tier Two, add Linear from the catalog and choose 'Sign in with your account' so each person's calls run as them; the alternative, a shared key, would make every comment come from one account and would make the tool's mode the only limit on it. The Recommended preset classifies the pinned tool list by name and hint: list_, get_ and search_ tools become Allow, and save_ and delete_ tools become Ask. Set delete_comment to Block. If save_issue carries a project id in its arguments, declare that argument as the tool's scope, and the mode can differ per project, with a call that omits the id refused rather than guessed.

Now follow the standup workflow. The agent calls linear__list_issues and linear__get_issue; both run and each leaves a row in Activity naming Dana, the agent, the host and the tool. It drafts three comments and calls linear__save_comment for the first one. That call is held. An admin gets a link, opens the request, and sees Dana, Claude Code, the tool, and a preview showing the issue id and the first 80 characters of the comment body. For a Monday standup, approving for eight hours makes sense: the next two comments go straight through, and by afternoon the tool asks again. A mismatched comment gets a deny, and the agent is told not to retry and not to reach the same goal another way. Nobody around? The call is refused after fifteen minutes and nothing is posted.

The mechanics that make this safe are covered in the approval article, and the important one bears repeating: on approval the held call itself is forwarded, so the comment that was reviewed is the comment that lands. Members see their own pending requests; only workspace admins decide.

Identity: who Linear says did it

A comment in Linear has an author, and the access shape decides who that is. With a personal sign-in, the comment appears as Dana, because the credential is hers, and Linear's own permissions apply: if she can't write to the Billing project, the approved call fails there, which is the right outcome and one the authentication and authorization explainer traces step by step. With a shared workspace key, everything appears as the key's owner, and the trail of which person asked exists only on the gateway side. Linear's OAuth flow can also attribute an integration's mutations to the application rather than the authorizing user; that's a choice for a custom integration, and it doesn't change who approved the call.

So there are two 'who' questions, and you want both answerable. Who did Linear record? That's the credential. Who asked, from which agent, and who said yes? That's the activity trail, which is why every call and every refusal leaves a row with the person, agent and host even when Linear only saw the app.

Where this stops

  • Read-only still returns everything Dana can read, across every team she belongs to. If some projects are confidential, the read-only access article explains why list_issues might deserve an Ask of its own.
  • There's no filter on the comment body. Neither host rules nor Tier Two match on arguments; the Ask, with its preview, is the filter, and a reviewer approving a batch of forty stops reading.
  • A remembered approval belongs to Dana, not to the agent, so an eight-hour approval covers every host she signs into that day.
  • If the host keeps a direct entry to mcp.linear.app beside the governed one, the agent has two doors. Tier Two's setup command offers to remove the direct entry and can put it back; until then, check the host config.
  • Of the hosts Tier Two writes config for, only Claude Code and Cursor are verified end to end with this flow at the time of writing.

Keep the deliverable in mind

Most Linear work an agent can do ends with an answer, and for that the read-only endpoint is the whole design. When the work ends with Linear changed, decide who approves, and put the gate where that person can see the actual comment before it posts. Everything else is configuration.

Tier Two connects Linear with each person's own sign-in, guesses the read and write split for you, and holds every save_comment for a workspace admin until someone says yes. Set up the standup workflow on the Free plan and approve the first comment yourself.

Sign up for Tier Two