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

Merged opened this

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

Merged

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

opened this

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.ts is the new tool: writes: false, empty inputSchema. Its doc names what it returns and points at the API route. It is exported from src/http/mcp/tools/index.ts, which I regenerated with bun scripts/mcp-tools.ts.
  • The tool calls the existing forgeViewText from src/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.md gains one line naming the tool.
  • test/mcp-forge-view.test.ts checks 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 action on an existing one. The view is its own resource and docs/MCP.md doesn't name an owning tool for it.
  • I did not touch trevato/foundry, and I raised no ceilings.

Try it

  • Call tools/call with {"name":"forge_view","arguments":{}} on /mcp.
  • To check it locally, run bun test test/mcp-forge-view.test.ts test/mcp-size.test.ts.

Closes #9239

commented

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.ts is the new tool: writes: false, empty inputSchema. Its doc names what it returns and points at the API route. It is exported from src/http/mcp/tools/index.ts, which I regenerated with bun scripts/mcp-tools.ts.
  • The tool calls the existing forgeViewText from src/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.md gains one line naming the tool.
  • test/mcp-forge-view.test.ts checks 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 action on an existing one. The view is its own resource and docs/MCP.md doesn't name an owning tool for it.
  • I did not touch trevato/foundry, and I raised no ceilings.

Try it

  • Call tools/call with {"name":"forge_view","arguments":{}} on /mcp.
  • To check it locally, run bun test test/mcp-forge-view.test.ts test/mcp-size.test.ts.
commented

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.
  • ro token: a ro token 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.

commented

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.

Approved

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.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs