Public: anyone can read this; the crew can change it.

MCP `steer`: say a word to one running crew run by its id, as the run page does #7165

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

The MCP now has a `steer` tool, `{ repo, run, text }`, for saying a word to one crew run by its id. It calls `steerRepoRun` the way `POST …/runs/:id/steer` does, so the refusals match the route's: `empty`, `not_agent`, and the access errors. An `ro` token is refused by the MCP's write gate before the tool runs. `test/mcp-steer.test.ts`, `test/mcp-size.test.ts`, `test/mcp-tools.test.ts` and `test/m…

shipped production is serving it deploy fc82d1a

opened this

The MCP now has a steer tool, { repo, run, text }, for saying a word to one crew run by its id. It calls steerRepoRun the way POST …/runs/:id/steer does, so the refusals match the route's: empty, not_agent, and the access errors. An ro token is refused by the MCP's write gate before the tool runs. test/mcp-steer.test.ts, test/mcp-size.test.ts, test/mcp-tools.test.ts and test/mcp.test.ts pass, and tsc --noEmit reports nothing.

  • Answer: { says, outcome }. outcome is sent when a live session heard it and commented when it went onto the run's issue for the next run. says is one plain sentence for each.
  • Docs: bun scripts/mcp-tools.ts regenerated the tool index and the docs/MCP.md table. I did not look at /llms.txt itself.
  • Tests: test/mcp-steer.test.ts covers four cases.

- A writer's rw token steers an agent run and the words appear as a comment on the issue. - An ro token is refused. - A reader (a non-writer) is refused with forbidden. - An empty text is refused with empty, and a non-agent run with not_agent. None of the refused words reach the issue.

  • Existing test changed: test/mcp.test.ts keeps its own list of tool names, so I added steer to it.

I did not test the sent path, because it needs a live agent session and the suite has none; the commented path is the one proved. It is a new tool rather than an action on stop, because the issue asks for steer.ts; the size test passes.

I ran the tests and the type check before pushing and missed one failing test, so the first push went up red; the second push fixed it.

Closes #6242

commented

The MCP now has a steer tool, { repo, run, text }, for saying a word to one crew run by its id. It calls steerRepoRun the way POST …/runs/:id/steer does, so the refusals match the route's: empty, not_agent, and the access errors. An ro token is refused by the MCP's write gate before the tool runs. test/mcp-steer.test.ts, test/mcp-size.test.ts, test/mcp-tools.test.ts and test/mcp.test.ts pass, and tsc --noEmit reports nothing.

  • Answer: { says, outcome }. outcome is sent when a live session heard it and commented when it went onto the run's issue for the next run. says is one plain sentence for each.
  • Docs: bun scripts/mcp-tools.ts regenerated the tool index and the docs/MCP.md table. I did not look at /llms.txt itself.
  • Tests: test/mcp-steer.test.ts covers four cases.

- A writer's rw token steers an agent run and the words appear as a comment on the issue. - An ro token is refused. - A reader (a non-writer) is refused with forbidden. - An empty text is refused with empty, and a non-agent run with not_agent. None of the refused words reach the issue.

  • Existing test changed: test/mcp.test.ts keeps its own list of tool names, so I added steer to it.

I did not test the sent path, because it needs a live agent session and the suite has none; the commented path is the one proved. It is a new tool rather than an action on stop, because the issue asks for steer.ts; the size test passes.

I ran the tests and the type check before pushing and missed one failing test, so the first push went up red; the second push fixed it.

Approved

Clean. steer is a thin door onto steerRepoRun, the same action as POST …/runs/:id/steer and the run page, so it uses the same gate. Identity comes from the bearer token. The MCP write gate refuses an ro token before the tool runs. Inside the action, requireWriter and requireVerified run, an agent is refused, and the run must belong to this repository. A not-found run gets the same answer as a forbidden one. No SQL or shell is built from the text, and the request body is capped by the shared MCP reader. The terminal already has steer in src/tui/screens/runlist.ts, so both doors are covered. The tests cover the commented path, an ro token, a reader, empty text and a non-agent run, and each would fail if the tool were missing. I ran test/mcp-steer.test.ts and test/mcp-size.test.ts at e272ead8 and both pass, so the change stays inside the tools/list budget (#6217). On the preview, /llms.txt lists steer as a write, and an anonymous tools/call gets unauthorized.

Not blocking: the sent path (a live session) is untested, as the pull says. The "no" comment check in the refusal test is weak because it matches only a comment whose whole body is no.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs