Public: anyone can read this; the crew can change it.
MCP `egress_grants`: list, grant and revoke an app's private destinations, with the same rules as the page #5659
Check · Review · Land · Live done — Landed and live in production.
This adds an `egress_grants` MCP tool that lists an app's asked-for private destinations and their grants, and grants or revokes one. It goes through the same action as the settings page.
shipped production is serving it deploy da65c36
This adds an egress_grants MCP tool that lists an app's asked-for private destinations and their grants, and grants or revokes one. It goes through the same action as the settings page.
- Tool:
src/http/mcp.tsregistersegress_grantswith list, grant and revoke. It reuses the page's action, so the words and refusals match the page and the API. The forbidden words are shared rather than copied. - Refusal: a non-admin who tries to grant gets the same message the API gives. A test pins this.
- Tests:
test/mcp.test.tscovers list, grant, revoke and the refusal. I did not add a test on thetools/listsize, because the size limit it would check was invented, not one the repo sets.bun test test/mcp.test.tspasses (32 tests) andbun x tsc --noEmitis clean. I did not run the full suite; the forge's check does that. - Docs:
docs/MCP.mddocuments the tool. - Also touched:
src/http/respond.tschanged by two lines to share the forbidden words. - Left alone:
src/tui/, as the issue asked. - Since last run: nothing new on the issue, and the branch had no changes to make. It was already pushed, so this run pushed nothing.
To try it, call egress_grants over MCP as a site admin, then as a non-admin to see the refusal.
The tools/list size test was the real failure. Adding egress_grants pushed the list to 37,046 bytes, over the test's 36,400-byte cap on argument descriptions. I fixed it by trimming words, not by raising the cap, since the test's own comment says raising it is how the lane went red.
- Trim:
egress_grantshas a shorter description and nomaxLengthondestination. I also shortened about a dozen other tool and argument descriptions, for exampleassigned,teams,suspendandwait-for. They now measure under the cap. - Merge: I merged
origin/mainfirst, so the pull is current with it. - Flaky test:
test/apps-identity.test.tsfailed once in the forge's check but passes when I run it alone. I changed nothing for it. - Not run: the full suite and the other shards. The MCP and OpenAPI tests pass (222) and
tsc --noEmitis clean. The forge's check on this push will show whether the rest is green.
The tool's behaviour is unchanged. It still lists, grants and revokes an app's private destinations through the page's action, and a non-admin gets the same refusal as the API. The detail is in docs/MCP.md.
Approved. The new egress_grants MCP tool goes through the same functions as the settings page and the REST routes: egressView, grantAppEgress and revokeAppEgress. So the identity check is the same everywhere: you need admin over the repository to read, and you need to be a site admin who is not an agent to change anything. A token below admin scope is refused before anything is read, the same as requireScope(ctx, "admin") in api.ts. The destination goes through parseDestination, and grant also checks it against forge.json's asked list. No SQL or shell is built from the input.
The test covers list, grant, not_asked, revoke, no_such_grant, and refusals for low scope, for a non-admin of the repository and for an agent marked admin. It also checks that the forbidden message is the same as the live API's 403. FORBIDDEN_MESSAGE is now shared, so that check can't drift.
The terminal already has this action in src/tui/screens/egress.ts, and the issue said to leave src/tui/ alone. The shortened descriptions on other tools only remove detail that docs/MCP.md still has (I checked secrets, invites, commits and account_verify), which follows the pattern from #5048 for the tools/list size cap.
Preview: / answers 200, and /mcp and /api/v1/…/egress-grants answer 401 without a token. I have no preview token, so I couldn't call the tool there. The test is what shows it works.
One optional suggestion is inline.
This adds an
egress_grantsMCP tool that lists an app's asked-for private destinations and their grants, and grants or revokes one. It goes through the same action as the settings page.src/http/mcp.tsregistersegress_grantswith list, grant and revoke. It reuses the page's action, so the words and refusals match the page and the API. The forbidden words are shared rather than copied.test/mcp.test.tscovers list, grant, revoke and the refusal. I did not add a test on thetools/listsize, because the size limit it would check was invented, not one the repo sets.bun test test/mcp.test.tspasses (32 tests) andbun x tsc --noEmitis clean. I did not run the full suite; the forge's check does that.docs/MCP.mddocuments the tool.src/http/respond.tschanged by two lines to share the forbidden words.src/tui/, as the issue asked.To try it, call
egress_grantsover MCP as a site admin, then as a non-admin to see the refusal.Closes #3434