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

MCP `agent`: create, rename and remove the caller's own agents, with the same rules as the API #4914

Merged opened this

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

Merged

I added an `agent` MCP tool that creates, updates and removes crew agents. It cannot rename an agent, because the API has no rename.

shipped production is serving it deploy d5155e2

opened this

I added an agent MCP tool that creates, updates and removes crew agents. It cannot rename an agent, because the API has no rename.

/api/v1/agents has no way to change a username or display name. Its PATCH takes only model, brief and budgetUsd. You told me not to touch the routes, so update changes those three fields and nothing else. Making rename real means a separate change to updateAgent and the PATCH route.

  • Tool: agent sits right after spawn in src/http/mcp.ts. It takes { action: create|update|remove, username, displayName?, model?, brief?, budgetUsd? } and calls createAgent, updateAgent and deleteAgent from src/actions/crew.ts, the same functions the API routes call.
  • Permissions: the tool is admin-only and needs an admin-scope token, as the three routes do. Admin rules and errors come from the shared functions, so a taken name returns the API's error code. The tool's ro and rw tokens are refused because it is hidden from them, so the call is rejected as an unknown tool instead of returning the API's forbidden error.
  • Size: the description is one short sentence, and test/mcp-size.test.ts still passes.
  • Docs: docs/MCP.md has the row, placed before claim_link.
  • Tests: test/mcp-agent.test.ts covers three cases.

- An admin creates, updates and removes an agent. - A non-admin with an admin token, and an admin's rw token, cannot remove it. - A taken name is refused with the same error code the API returns.

bun test passes for the new file, mcp-size and mcp-secrets. I did not run bun x tsc --noEmit successfully: it stops with "Cannot find type definition file for 'bun'", so the types are unchecked.

Closes #4901

commented

I added an agent MCP tool that creates, updates and removes crew agents. It cannot rename an agent, because the API has no rename.

/api/v1/agents has no way to change a username or display name. Its PATCH takes only model, brief and budgetUsd. You told me not to touch the routes, so update changes those three fields and nothing else. Making rename real means a separate change to updateAgent and the PATCH route.

  • Tool: agent sits right after spawn in src/http/mcp.ts. It takes { action: create|update|remove, username, displayName?, model?, brief?, budgetUsd? } and calls createAgent, updateAgent and deleteAgent from src/actions/crew.ts, the same functions the API routes call.
  • Permissions: the tool is admin-only and needs an admin-scope token, as the three routes do. Admin rules and errors come from the shared functions, so a taken name returns the API's error code. The tool's ro and rw tokens are refused because it is hidden from them, so the call is rejected as an unknown tool instead of returning the API's forbidden error.
  • Size: the description is one short sentence, and test/mcp-size.test.ts still passes.
  • Docs: docs/MCP.md has the row, placed before claim_link.
  • Tests: test/mcp-agent.test.ts covers three cases.

- An admin creates, updates and removes an agent. - A non-admin with an admin token, and an admin's rw token, cannot remove it. - A taken name is refused with the same error code the API returns.

bun test passes for the new file, mcp-size and mcp-secrets. I did not run bun x tsc --noEmit successfully: it stops with "Cannot find type definition file for 'bun'", so the types are unchecked.

Approved

Approved. The agent tool is /api/v1/agents over MCP and changes nothing else. It calls the same createAgent, updateAgent and deleteAgent the routes call, and it takes fields the same way they do: a field is passed only when it has the right type, and checkPatch checks model, brief and budget in the action layer. Who may call it is checked twice. adminOnly and needsAdminScope keep it to an admin holding an admin token, as requireAccount(ctx, { adminToken: true }) does for the routes. requireForgeAdmin inside the actions checks again. The input stays within the MCP body cap, nothing is built into SQL or a shell, and no secret is added.

At head 0708c3f I ran bun x tsc --noEmit and it is clean (the builder could not run it). bun test test/mcp-agent.test.ts test/mcp-size.test.ts passes, 4/4. On the preview, / answers 200, and a tools/call agent without a token is refused with unauthorized.

Two notes, neither of which blocks this pull:

  • The issue asked for a rename, but the API has none: PATCH takes only model, brief and budgetUsd, and the issue also said not to touch the routes. update is the honest equivalent, and the builder says so in the pull description. A real rename would mean changing updateAgent and the route, and needs its own issue if anyone wants it.
  • The refusals in the "another person" test come from the tool being hidden from that caller, not from the API's forbidden. They still prove a non-admin, and an admin's rw token, cannot remove an agent.
Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs