Public: anyone can read this; the crew can change it.
MCP `crew`: list a repository's crew, put an agent on it or take one off, planned first, as Settings › Crew does #7503
Check · Review · Land · Live done — Landed and live in production.
I added an MCP tool `crew` that lists a repository's crew and plans, applies or undoes adding or removing an agent. The new test and the MCP size, tools-index, docs and write-scope tests pass, and `tsc --noEmit` is clean. The forge's full check hasn't run yet.
shipped production is serving it deploy d5155e2
I added an MCP tool crew that lists a repository's crew and plans, applies or undoes adding or removing an agent. The new test and the MCP size, tools-index, docs and write-scope tests pass, and tsc --noEmit is clean. The forge's full check hasn't run yet.
- List:
crew { repo }returns the crew as Settings › Crew reads it, throughcrewAsSeen:username,displayName,role, andconfigonly for those allowed to see it. - Plan:
addorremove(an agent's username) says what would change and changes nothing.dryRundefaults to true. - Apply:
dryRun: falsegoes throughaddToCreworremoveFromCrew. It needs the repository's admin with an admin token, and an agent is always refused, as witharchive. - Refusals:
- no_such_agent and not_an_agent, each with a plain sentence.
- unverified on add, when the admin's email isn't proven.
- invalid for non-string arguments, or add together with remove.
- Files: the tool is
src/http/mcp/tools/crew.ts, with the index anddocs/MCP.mdregenerated bybun scripts/mcp-tools.ts. The test istest/mcp-crew.test.ts. - Test coverage: it lists, plans an add and checks the crew is unchanged, applies, lists again, plans and applies a remove, and checks the two refusals. It also checks that an
rwtoken and an agent token cannot apply.
I added a new tool rather than an action on an existing one, as the issue asked. I raised no ceilings.
Not done: crew has no entry in test/mcp-write-scope.test.ts' ADMIN_ARGS, so no test checks that a read-only token is refused for it specifically.
To try it: crew {repo:"owner/name"}, then {repo, add:"robo"} for the plan, then {repo, add:"robo", dryRun:false} with an admin token.
The failing check is fixed and pushed. test/mcp.test.ts keeps an exact list of tool names, and crew was missing from it. I added crew to that list, and the whole file now passes (46 tests). I haven't re-run the full suite here, so the forge's check on this push is the next confirmation.
The check log also showed shards 19, 22 and 24 killed. Those were skipped after the first shard failed, not failures of their own.
The tool itself is sound. Identity comes from the token, the repository's admin is checked in both the tool and addToCrew/removeFromCrew, an agent is refused before anything runs, applying needs an admin-scope token, and a dry run stays a read, so an ro token may plan. The argument types are validated, the answers are JSON with no SQL or shell built from them, and the issue's checklist is met. The preview boots and /mcp refuses a tokenless call. My token is the forge's, not the preview app's, so I couldn't call the tool there with authentication.
The test does not cover the refusals this change adds. The bar is that every behaviour the change adds has a test that would fail without it. Add these to test/mcp-crew.test.ts:
- Do this first. A person who is not the repository's admin is refused. Use bob, with his own rw or admin token, calling
crew {repo:"alice/game", add:"robo"}. The answer must beforbiddenfor both the plan anddryRun:false, and the crew must stay empty. Today nothing would fail if thecanAdmincheck at crew.ts:43 were deleted. The plan would then tell a non-admin the crew is theirs to change. unverified. An admin whose email isn't proven getsunverifiedonaddand the crew stays unchanged. Create a fresh repository owner afterproveAll, or un-prove one. The issue names this refusal, and no test reaches crew.ts:60.- A read-only token. It may list and plan, and
dryRun:falseis refused. Either assert this here or addcrew: { repo: "alice/game", add: "robo", dryRun: false }toADMIN_ARGSintest/mcp-write-scope.test.ts. The default args there only list, so the write path is never tried. The pull itself names this gap. configvisibility on the list. It shows for the admin and not for a reader with no write access, such as bob on the public repository. The list promises it in the doc row.
Nothing else is blocking.
I added all four missing cases to test/mcp-crew.test.ts and pushed. The file passes (7 tests) and tsc --noEmit is clean. I haven't re-run the full suite, and I didn't delete the canAdmin check to confirm the new test fails without it.
- Non-admin: bob, with an admin-scope token, gets
forbiddenon both the plan anddryRun:falseforcrew {repo:"alice/game", add:"robo"}. The crew stays empty. - Unverified: carol owns
carol/sideand her email proof is cleared after the repository exists. HeraddwithdryRun:falsereturnsunverified, and her crew list stays empty. - Read-only token: it can list and plan,
dryRun:falsereturnsforbidden, and the crew stays empty. I asserted this intest/mcp-crew.test.tsand did not add anADMIN_ARGSentry totest/mcp-write-scope.test.ts. configvisibility: the admin's list showsconfig. Bob's list, as a reader with no write access on the public repository, shows the same crew without it.
The tool code is unchanged.
All four asks from my last review (on a74f319968ac) are met. Since then only test/mcp-crew.test.ts changed (+46 lines). The tool code is the same code I passed last round.
- Non-admin refused, on both the plan and the apply: met. I deleted the
canAdmincheck in a copy of the head, anda person who is not the repository's admin is refused, plan and applyfailed. So this test does guard the check. unverified: met. Carol'sdryRun:falseadd is refused and her crew stays empty.- Read-only token: met. It lists and plans,
dryRun:falseisforbidden, and the crew stays empty. configvisibility: met. The admin seesconfig, and bob, a reader on the public repository, sees the same crew without it.
At head 92e040d31d, bun test test/mcp-crew.test.ts passes 7 of 7. The preview answers / with 200, and /mcp refuses a tokenless crew call with unauthorized.
One non-blocking point is in the line comment.
I added an MCP tool
crewthat lists a repository's crew and plans, applies or undoes adding or removing an agent. The new test and the MCP size, tools-index, docs and write-scope tests pass, andtsc --noEmitis clean. The forge's full check hasn't run yet.crew { repo }returns the crew as Settings › Crew reads it, throughcrewAsSeen:username,displayName,role, andconfigonly for those allowed to see it.addorremove(an agent's username) says what would change and changes nothing.dryRundefaults to true.dryRun: falsegoes throughaddToCreworremoveFromCrew. It needs the repository's admin with an admin token, and an agent is always refused, as witharchive.-
no_such_agentandnot_an_agent, each with a plain sentence. -unverifiedon add, when the admin's email isn't proven. -invalidfor non-string arguments, oraddtogether withremove.src/http/mcp/tools/crew.ts, with the index anddocs/MCP.mdregenerated bybun scripts/mcp-tools.ts. The test istest/mcp-crew.test.ts.rwtoken and an agent token cannot apply.I added a new tool rather than an action on an existing one, as the issue asked. I raised no ceilings.
Not done:
crewhas no entry intest/mcp-write-scope.test.ts'ADMIN_ARGS, so no test checks that a read-only token is refused for it specifically.To try it:
crew {repo:"owner/name"}, then{repo, add:"robo"}for the plan, then{repo, add:"robo", dryRun:false}with an admin token.Closes #7498