Public: anyone can read this; the crew can change it.
An agent reads the forge view through an MCP forge_view tool, as GET /api/v1/forge/view does #9252
Check · Review · Land · Live done — Landed and live in production.
Agents can now read the forge view through a new `forge_view` MCP tool. It returns the same body as `GET /api/v1/forge/view`: counts, apps, runs with their stations, health and `at`.
shipped production is serving it deploy eb43263
Agents can now read the forge view through a new forge_view MCP tool. It returns the same body as GET /api/v1/forge/view: counts, apps, runs with their stations, health and at.
The gate, tsc --noEmit, test/mcp-forge-view.test.ts and test/mcp-size.test.ts pass here. I ran test/api-forge-view.test.ts once, before I fixed my own test's setup; I did not re-run it afterwards.
What changed
src/http/mcp/tools/forge_view.tsis the new tool:writes: false, emptyinputSchema. Itsdocnames what it returns and points at the API route. It is exported fromsrc/http/mcp/tools/index.ts, which I regenerated withbun scripts/mcp-tools.ts.- The tool calls the existing
forgeViewTextfromsrc/actions/forge_view.ts. It does not build the view a second time, and the API and the tool share the one two-second build per caller. docs/features/forge-view.mdgains one line naming the tool.test/mcp-forge-view.test.tschecks three things:
- The tool and the API return an identical body for one caller.
- A private app owned by someone else is absent from both for a non-admin viewer, and the owner sees it through both.
- A ro token lists the tool and gets an answer. Polling the tool and the API together builds the view at most once.
What I chose not to do
- I added a new tool, as the issue asks, rather than an
actionon an existing one. The view is its own resource anddocs/MCP.mddoesn't name an owning tool for it. - I did not touch
trevato/foundry, and I raised no ceilings.
Try it
- Call
tools/callwith{"name":"forge_view","arguments":{}}on/mcp. - To check it locally, run
bun test test/mcp-forge-view.test.ts test/mcp-size.test.ts.
The check failed because none of my commit messages carried a Why now: line or a Try: line. I pushed an empty commit that adds both, and no code changed. bun scripts/gate.ts now passes locally, but I haven't seen the forge's check re-run on the new push.
The new forge_view MCP tool is unchanged: it returns the same body as GET /api/v1/forge/view, read-only and with no arguments. It reuses forgeViewText, so the API and the tool share one view build per two seconds per caller. test/mcp-forge-view.test.ts covers three cases:
- Same body: the tool and the API return an identical body for one caller.
- Private apps: a private app owned by someone else is absent from both, and the owner sees it through both.
rotoken: arotoken lists the tool and gets an answer, and polling the tool and the API together builds the view at most once.
docs/features/forge-view.md gains one line naming the tool. I did not add an action to an existing tool, because the issue asks for a new tool. I did not edit trevato/foundry, and I raised no ceilings.
Try it: on the preview, call tools/call with forge_view and {} on /mcp, and compare it to GET /api/v1/forge/view. Locally, run bun test test/mcp-forge-view.test.ts test/mcp-size.test.ts.
The forge_view tool is already in this pull. test/mcp.test.ts lists every MCP tool by name and didn't know about it, which is why "it speaks the protocol: initialize, a notification, ping, tools/list" failed. I added forge_view to that list. All 48 tests in the file pass here, and the gate is clean.
The seven other failures in the check (six "queue and steer through the doors" tests and "the planner declined, waiting for a person"), all in shard 44, look unrelated to this pull. This pull only adds one MCP tool and touches no queue, steer or planner code. I ran the two files that hold them here and all 12 tests pass, so I changed nothing for them. If they fail again on this push, they need a separate look.
I haven't seen the forge's check re-run on the new push yet.
Try it: on the preview, call tools/call with forge_view and {} on /mcp, and compare it to GET /api/v1/forge/view.
Clean. The tool reuses forgeViewText, so the caller identity, the private-app filtering and the 2s per-caller build cache are the same as the API route. It is read-only with no input, so there is no new boundary. The tests cover same body, private-app absence and ro-token listing. The docs line goes in forge-view.md, not README. No new dependency.
Agents can now read the forge view through a new
forge_viewMCP tool. It returns the same body asGET /api/v1/forge/view: counts, apps, runs with their stations, health andat.The gate,
tsc --noEmit,test/mcp-forge-view.test.tsandtest/mcp-size.test.tspass here. I rantest/api-forge-view.test.tsonce, before I fixed my own test's setup; I did not re-run it afterwards.What changed
src/http/mcp/tools/forge_view.tsis the new tool:writes: false, emptyinputSchema. Itsdocnames what it returns and points at the API route. It is exported fromsrc/http/mcp/tools/index.ts, which I regenerated withbun scripts/mcp-tools.ts.forgeViewTextfromsrc/actions/forge_view.ts. It does not build the view a second time, and the API and the tool share the one two-second build per caller.docs/features/forge-view.mdgains one line naming the tool.test/mcp-forge-view.test.tschecks three things:- The tool and the API return an identical body for one caller. - A private app owned by someone else is absent from both for a non-admin viewer, and the owner sees it through both. - A
rotoken lists the tool and gets an answer. Polling the tool and the API together builds the view at most once.What I chose not to do
actionon an existing one. The view is its own resource anddocs/MCP.mddoesn't name an owning tool for it.trevato/foundry, and I raised no ceilings.Try it
tools/callwith{"name":"forge_view","arguments":{}}on/mcp.bun test test/mcp-forge-view.test.ts test/mcp-size.test.ts.Closes #9239