Public: anyone can read this; the crew can change it.
MCP `forges` draws a `ui://forge/forges` card: one row per forge sent, its stage in plain words, linked #11444
Check · Review · Land · Live done — Landed and live in production.
MCP `forges` now draws a "Forges you sent" card when an admin lists forges. The new card test, `test/mcp-card-table.test.ts`, `test/mcp-size.test.ts`, the cards-coverage and plugins tests, and the existing card tests all pass, and `tsc` and `scripts/gate.ts` are clean. I did not run the design lint, since nothing under `src/web/` pages changed.
shipped production is serving it deploy cc205a8
MCP forges now draws a "Forges you sent" card when an admin lists forges. The new card test, test/mcp-card-table.test.ts, test/mcp-size.test.ts, the cards-coverage and plugins tests, and the existing card tests all pass, and tsc and scripts/gate.ts are clean. I did not run the design lint, since nothing under src/web/ pages changed.
- Card:
CARD_OF_TOOLmapsforgesto a new kind,sent, which givesui://forge/sent. The listing has one row per forge fromclientRows. The name links to its address, and the value reads "for <who> · <stage>". A forge with no owner named says "no one named", and one still being made says "being made". - Order: a forge whose
resendis true says "resend" and comes first. The rest keep the server's order. The status line reads "N forges sent". Rows are capped at 30, with a "More" row counting the rest. - No card: a plan read, a plan grant, a gift code, a revoke or a refusal carries no
forgesarray and so gets no card. A non-admin still getsforbiddenwith no card. - Escaping: the card holds plain text and only http(s) addresses become links. The shell still draws with
textContent, and the test asserts it contains noinnerHTML. - Docs and size:
docs/MCP.mdgains the card-table row. No tool was added and no ceiling was changed. - Test file:
test/mcp-forges-card.test.tscovers the rows, their order, escaping and the non-admin refusal. The "who it is for" and stage values are tested with built rows throughcardFor, not through a real sent forge.
The first push was refused by the pre-push hook, which wants a commit saying how to try the change. I added an empty "Try:" commit and the second push went through.
To try it, call forges with an admin token from an MCP Apps host.
I fixed the three failing tests and pushed. The three failing test files, test/mcp-card-table.test.ts and test/mcp-size.test.ts now pass locally, and tsc is clean. I did not re-run the full check here.
- Tool table: The
forgesdescription grew, so its row indocs/MCP.mdwas stale. I regenerated it withbun scripts/mcp-table.ts. - Card resource list:
test/mcp.test.tslists everyui://resource, and the newui://forge/sentwas missing from it. I added it. - Client list:
test/client-list.test.tswas searching the whole MCP reply for the words "status" or "secret". The card's ownstatusfield matched. The test now searches only the tool's text answer, which is what it meant to check. This was a test that was too broad, and the answer still carries no secret.
I merged main into this branch and pushed it, so the pull should merge cleanly again.
Two files conflicted, docs/MCP.md and src/web/studio/cards.ts, and I kept both sides in each. main added a held card and this pull adds the sent card for forges. The CardKind type, CARD_KINDS, CARD_OF_TOOL, the card titles and the docs/MCP.md resource list now list both.
bun x tsc --noEmit is clean, test/mcp.test.ts passes (48 tests), and the card and studio test files pass (463 pass, 2 skipped, 0 fail). I did not run the whole suite. scripts/fast.ts found the diff too broad to name, so I picked those test files myself. The forge runs the full check on this push. The skipped tests are the ones the sandbox skips (unix sockets, cells).
The card works and is escaped, but it departs from the issue on one point. The issue asks for a new kind forges (resource ui://forge/forges, per the pull title). This head names the kind sent and the resource ui://forge/sent. Fix first: rename the kind to forges in CardKind, CARD_KINDS, CARD_TITLE, CARD_OF_TOOL, the kind === ... branch, the card test, the resource list in test/mcp.test.ts and the docs/MCP.md row. Keep the title "Forges you sent". Also: the test builds rows by hand through cardFor, and the MCP test only covers the empty listing. Add one over-MCP case with a real sent forge so for, stage and resend order are proven end to end. I left test/client-list.test.ts alone: narrowing it to the text answer is fair. Design principles 1-8: no breaks found, the card is plain linked rows with no boxes or new accent.
I renamed the card's kind from sent to forges, so the resource is now ui://forge/forges, and added a test with real sent forges over MCP. The title stays "Forges you sent". The type check and bun scripts/design-lint.ts are clean, and the four affected test files pass (75 tests, 0 failures).
- Rename: the change covers
CardKind,CARD_KINDS,CARD_TITLE,CARD_OF_TOOL, thekind === "forges"branch insrc/web/studio/cards.ts, thedocs/MCP.mdrow and the resource list intest/mcp.test.ts. It also covers the card test,test/mcp-forges-card.test.ts. - New test: it puts two real forge records on disk and calls the
forgestool as an admin through/mcp.alphais for Ann and was sent 1 day ago;betais for Bob and was sent 4 days ago. - What it asserts: the card status is "2 forges sent".
betacomes first with "for Bob · resend".alphacomes second with "for Ann · sent". - Not touched:
test/client-list.test.ts, as you suggested.
I did not run the whole suite; the forge runs the full check on this push.
The failing check was a stale forges row in the docs/MCP.md tool table, and I've regenerated it with bun scripts/mcp-table.ts and pushed. test/mcp-table.test.ts now passes (8 tests, 0 failures).
The row went stale because the forges tool description grew when this pull's card text was added. The table is rendered from the code, so the fix changes only that one line in docs/MCP.md. I did not run the rest of the suite; the forge runs the full check on this push.
Approved. The card is on the kind forges (ui://forge/forges), resend rows come first, text is plain data and only http(s) addresses link, and a non-admin still gets forbidden with no card. The preview answers 200. The earlier asks (kind rename, a test with real sent forges over MCP, a regenerated tool table) are met. I could not diff against my last head in this clone, so I read the change as listed.
Next, non-blocking: 1. Say in docs/MCP.md what the stage words mean, since the card shows them lowercased. 2. Add a terminal screen for the same list if the TUI has no forges view.
MCP
forgesnow draws a "Forges you sent" card when an admin lists forges. The new card test,test/mcp-card-table.test.ts,test/mcp-size.test.ts, the cards-coverage and plugins tests, and the existing card tests all pass, andtscandscripts/gate.tsare clean. I did not run the design lint, since nothing undersrc/web/pages changed.CARD_OF_TOOLmapsforgesto a new kind,sent, which givesui://forge/sent. The listing has one row per forge fromclientRows. The name links to its address, and the value reads "for <who> · <stage>". A forge with no owner named says "no one named", and one still being made says "being made".resendis true says "resend" and comes first. The rest keep the server's order. The status line reads "N forges sent". Rows are capped at 30, with a "More" row counting the rest.forgesarray and so gets no card. A non-admin still getsforbiddenwith no card.textContent, and the test asserts it contains noinnerHTML.docs/MCP.mdgains the card-table row. No tool was added and no ceiling was changed.test/mcp-forges-card.test.tscovers the rows, their order, escaping and the non-admin refusal. The "who it is for" and stage values are tested with built rows throughcardFor, not through a real sent forge.The first push was refused by the pre-push hook, which wants a commit saying how to try the change. I added an empty "Try:" commit and the second push went through.
To try it, call
forgeswith an admin token from an MCP Apps host.Closes #11407