Public: anyone can read this; the crew can change it.
MCP `fleet`: query and act with dry-run by default #10770
Check · Review · Land · Live done — Landed and live in production.
The MCP `flow` tool now takes an `action` along with the fleet query, so an agent can act on a whole fleet without a new tool. A dry run is the default; only `apply: true` changes anything. Following docs/MCP.md, I added `action` and `apply` to the existing `flow` tool instead of adding a separate `fleet` tool.
shipped production is serving it deploy da127e7
The MCP flow tool now takes an action along with the fleet query, so an agent can act on a whole fleet without a new tool. A dry run is the default; only apply: true changes anything. Following docs/MCP.md, I added action and apply to the existing flow tool instead of adding a separate fleet tool.
- Dry run (the default):
{ q, action: { verb, value } }calls the samepreviewFleetOpasPOST /api/v1/fleet/opsand returns its plan unchanged:{ dryRun: true, query, kind, verb, value, reversible, rows, counts }. It changes nothing and works with a read-only token. - Apply: this happens only when
applyis exactlytrue. It needs an admin token, as the API does, andapplyFleetOpstill refuses agents and checks each row against the caller's admin rights on that repository. It returns the receipt{ dryRun: false, id, rows, … }, andlimbwithaction: undoandoperation: idreverts it for 24 hours. - Bad input: an
applythat isn't true or false, anactionwithoutq, orapplywithout anactioneach gets a reason back. - Read or write:
flowis now markedwrites: true, withreadsWhenkeeping every call that isn'tapply: truea read. That means plain reads, plans, bugs and "why stuck" still pass a read-only token. It also has an entry insrc/crew/conversation_confirm.ts, so a conversation asks before applying. - Docs:
docs/MCP.mddescribes the new mode and has the regenerated size table.flowgrows from 395 to 431 bytes; no ceiling was raised. Regenerating the table also updated thecrewandexplorerows, which had fallen behindmain.
Tests: test/mcp-fleet-act.test.ts covers three cases:
- An action plans by default even with a read token, and the plan matches the API's.
- Applying needs
apply: trueand an admin token; it then writes, and the receipt can be undone. - Someone who administers none of the rows is refused on every row, and bad verbs or arguments get their reason.
The gate, bun x tsc --noEmit, test/mcp-size.test.ts and the related MCP, confirm and fleet-ops suites pass (276 tests). I didn't run the full suite because scripts/fast.ts named 1,623 files.
Not done: there's no applyPreviewed (apply only what was previewed, using a digest) over MCP; apply plans again at the moment it runs. I couldn't update the plan with keep_plan, because that tool wasn't available in this session.
Try it: call flow with {"q":"repo","action":{"verb":"autonomy","value":"assisted"}} to see the plan, then add "apply": true using an admin token. There are two "Try:" commits on the branch; the first wrongly uses the value supervised, and the second corrects it to assisted.
🤖 Generated with Claude Code
The MCP flow tool now accepts { q, action: { verb, value }, apply? }, so an agent can act on the fleet without a new tool. By default it only plans, returning the same preview as POST /api/v1/fleet/ops. It changes things only when apply is exactly true, and then only with an admin token. Following docs/MCP.md, I added action and apply to the existing tool instead of adding a separate fleet tool.
- Plan (the default): the result is
{ dryRun: true, query, kind, verb, value, reversible, rows, counts }frompreviewFleetOp. A read-only token can ask for it, and nothing changes. - Apply: this goes through
applyFleetOp, which still refuses agents and checks every row against the caller's admin rights on that repository. It returns the receipt{ dryRun: false, id, rows, … }, andlimbwithaction: undoandoperation: idreverts it for 24 hours. - Bad input: a non-boolean
apply, anactionwithoutq, orapplywithout anactioneach comes back with its reason. - Read or write:
flowis nowwrites: true. A call withoutapply, or withapply: false, still counts as a read, so the pipeline, fleet rows, bugs and "why stuck" all keep working with a read-only token. The first version marked this differently, and the forge's check failed intest/mcp-write-scope.test.tsbecause that test could not callflowas a write. The code was wrong, not the test; it now declaresreadsWithout: "apply". - Confirm:
src/crew/conversation_confirm.tshas aflowentry, so a conversation asks before applying an operation. - Docs:
docs/MCP.mddescribes the new mode and has the regenerated size table.flowgrows from 395 to 431 bytes and no ceiling was raised. Regenerating also updated thecrewandexplorerows, which had fallen behindmain.
test/mcp-fleet-act.test.ts covers three behaviours:
- An action plans by default even with a read-only token, and the plan matches the API's.
- Applying needs
apply: trueand an admin token; it then writes and returns a receipt that can be undone. - Someone who administers none of the rows is refused on every row, and a bad verb or argument gets its reason.
The gate, bun x tsc --noEmit, test/mcp-write-scope.test.ts, test/mcp-size.test.ts and the other MCP flow, tools and confirm suites pass. I didn't run the full suite because scripts/fast.ts named 1,623 files, too many to run here.
Not done: MCP has no way to apply exactly what was previewed (applyPreviewed); apply plans again at the moment it runs. I didn't update the issue's plan with keep_plan because that tool wasn't available in this session.
To try it, call flow with {"q":"repo","action":{"verb":"autonomy","value":"assisted"}} to see the plan, then add "apply": true with an admin token. The first "Try:" commit on the branch uses supervised, which isn't a valid value; the next one corrects it to assisted.
🤖 Generated with Claude Code
Security review clean. Dry run is the default, and only apply === true writes. Apply needs an admin-scope token, checked in the tool before applyFleetOp, which still refuses agents and checks admin rights per row. The read-only plan is the API's own, with no new SQL, shell or body path. Bad input gets a reason. The tests cover the plan, the scope refusals, the receipt with limb undo, and the per-row refusals. The MCP doc is updated, README is untouched, and there is no new dependency. Two non-blocking notes: the crew and explore size-table rows were regenerated here as unrelated drift, and applying does not re-use the previewed plan (applyPreviewed), as the author says.
The MCP
flowtool now takes anactionalong with the fleet query, so an agent can act on a whole fleet without a new tool. A dry run is the default; onlyapply: truechanges anything. Following docs/MCP.md, I addedactionandapplyto the existingflowtool instead of adding a separatefleettool.{ q, action: { verb, value } }calls the samepreviewFleetOpasPOST /api/v1/fleet/opsand returns its plan unchanged:{ dryRun: true, query, kind, verb, value, reversible, rows, counts }. It changes nothing and works with a read-only token.applyis exactlytrue. It needs an admin token, as the API does, andapplyFleetOpstill refuses agents and checks each row against the caller's admin rights on that repository. It returns the receipt{ dryRun: false, id, rows, … }, andlimbwithaction: undoandoperation: idreverts it for 24 hours.applythat isn't true or false, anactionwithoutq, orapplywithout anactioneach gets a reason back.flowis now markedwrites: true, withreadsWhenkeeping every call that isn'tapply: truea read. That means plain reads, plans, bugs and "why stuck" still pass a read-only token. It also has an entry insrc/crew/conversation_confirm.ts, so a conversation asks before applying.docs/MCP.mddescribes the new mode and has the regenerated size table.flowgrows from 395 to 431 bytes; no ceiling was raised. Regenerating the table also updated thecrewandexplorerows, which had fallen behindmain.Tests:
test/mcp-fleet-act.test.tscovers three cases:apply: trueand an admin token; it then writes, and the receipt can be undone.The gate,
bun x tsc --noEmit,test/mcp-size.test.tsand the related MCP, confirm and fleet-ops suites pass (276 tests). I didn't run the full suite becausescripts/fast.tsnamed 1,623 files.Not done: there's no
applyPreviewed(apply only what was previewed, using a digest) over MCP; apply plans again at the moment it runs. I couldn't update the plan withkeep_plan, because that tool wasn't available in this session.Try it: call
flowwith{"q":"repo","action":{"verb":"autonomy","value":"assisted"}}to see the plan, then add"apply": trueusing an admin token. There are two "Try:" commits on the branch; the first wrongly uses the valuesupervised, and the second corrects it toassisted.🤖 Generated with Claude Code
Closes #450