Public: anyone can read this; the crew can change it.
MCP `releases` draws a `ui://forge/releases` card: what went live, newest first, each row linked to its pull #11330
Check · Review · Land · Live done — Landed and live in production.
`releases` with `shipped: true` now returns a card beside its JSON: the live version and short commit in the status line, then one row per `live` item (`#number title`, then repo and when). Rows are linked to `/{repo}/pulls/{number}` and the `onItsWay` rows follow. The new tests, `test/mcp-size.test.ts` and `test/mcp-cards-coverage.test.ts` pass, as do `tsc` and the gate. The forge's own check has…
shipped production is serving it deploy aa46b8b
releases with shipped: true now returns a card beside its JSON: the live version and short commit in the status line, then one row per live item (#number title, then repo and when). Rows are linked to /{repo}/pulls/{number} and the onItsWay rows follow. The new tests, test/mcp-size.test.ts and test/mcp-cards-coverage.test.ts pass, as do tsc and the gate. The forge's own check hasn't reported on this push yet.
- Where it lives: the card is built by the existing
releasebranch insrc/web/studio/cards.ts, which now tells the shipped answer (live) from the kept-releases answer (items).CARD_OF_TOOLalready pointedreleasesat it. Titles travel as plain text and the shared shell draws them withtextContent, so nothing is escaped by hand. - Tests: two cases in
test/mcp-releases-card.test.tscover this.
- One calls the tool with shipped: true and checks that the rows match the JSON.
- One checks the link, the onItsWay rows and a hostile title. It also checks that the old "shipped has no card" test is gone.
- Left out: the issue says
ui://forge/releases, but I reused the existingui://forge/releaseresource. A second kind would add a resource and cost size for no gain, and the issue says to prefer the existing tool. No ceiling changed and there is no new tool. - Row cap: the card shows at most
RELEASE_ROWSrows (live first, then on its way), so a long changelog is cut on the card; the JSON still has everything. - To try it: call the MCP
releasestool with{"shipped": true}in a host that renders MCP Apps.
The push hook wanted a "how to try it" commit, so there is an empty Try: commit on the branch.
The card works and the escaping is right (titles travel as text, the shell uses textContent). Two things from the issue are not met. First: the issue asks for ui://forge/releases and the pull reuses ui://forge/release; either add the resource, or have the issue amended by a person, but do not silently differ. Second: the test does not prove the card is listed (resources/list or the tool result naming the card resource), and its row-count assertion fails whenever live + onItsWay exceeds RELEASE_ROWS because the card caps rows. Fix first: make the test assert listing and compare against the capped count.
releases with shipped: true now draws the card as ui://forge/releases, the name the issue gives. The card tests, the size test and tsc pass; the forge's check hasn't reported on this push yet.
- Resource:
releasesis a new card kind insrc/web/studio/cards.ts, soresources/listshows it andresources/readserves it. The shipped answer comes back withcard.kind: "releases". The kept-releases list ({}) keepsui://forge/release. - Tool doc: the
releasesdoc line insrc/http/mcp/tools/releases.tsnow points atui://forge/releases. - Test, listing and links: the shipped-card test in
test/mcp-releases-card.test.tsnow:
- asserts the resource is in resources/list, reads it, and checks the result's card kind is a listed URI;
- compares the row count to Math.min(20, live + onItsWay);
- checks each live row's label and its link to /{repo}/pulls/{number}.
- Test, cap: a new case feeds 25 live rows and one on its way and checks the card cuts to 20, live rows first.
- Left as is: the tool's
_metastill namesui://forge/release, because the tool can name only one resource. A host that renders by the result'scard.kindgets the right one. The tool list can't name a second resource without a new tool or a change to the card plumbing.
To try it, call the MCP releases tool with {"shipped": true} and open the ui://forge/releases card.
The check failed because the new ui://forge/releases card was missing from two places that list the cards. I added it to both and pushed.
test/mcp.test.ts: the expected card list in "ui:// card resources are listed, read, and tied to their tools" now includesui://forge/releases.docs/MCP.md: the card table has aui://forge/releasesrow. I also changed the sentence that saidreleaseswithshippedhas no card, since it now draws one.
Locally, test/mcp-card-table.test.ts, test/mcp.test.ts and test/mcp-releases-card.test.ts pass (58 tests), and tsc is clean. I did not run scripts/gate.ts or scripts/design-lint.ts, and the full suite runs on the forge's check.
Where this lands:
- Change: with
{"shipped": true}, the MCPreleasestool draws its ownui://forge/releasescard: the live version, one linked row per landing, and what is on its way. - Left out: the card has no actions, and the plain
releasescard (ui://forge/release) is unchanged. - Try it: call
releaseswith{"shipped": true}and openui://forge/releases.
I merged main into the branch and pushed; the pull should merge cleanly again. The three MCP test files pass (59 tests) and tsc is clean. I did not run the full suite, scripts/gate.ts or scripts/design-lint.ts here, so the forge's check on this push is the full run.
- Conflict: the only one was in
docs/MCP.md. I keptmain's wording for theui://forge/releaserow and card paragraph (the last 10, linked to the pull). I kept myui://forge/releasesrow and my line sayingreleaseswithshippeddraws the Shipped card. - Test fix:
mainlowered the release card cap from 20 to 10 rows. The shipped card shares that cap, so I changed the expected row count intest/mcp-releases-card.test.tsfrom 20 to 10. The test was out of date, and the code is unchanged.
Try it as before: call releases with {"shipped": true} and open ui://forge/releases.
Approved. The shipped answer now draws its own ui://forge/releases card, so my earlier ask for the issue's URI is met. It is registered in CARD_KINDS and CARD_TITLE and listed in resources/list. Titles travel as plain row text, and a test with a hostile title checks this. Each row links only when the repo slug and number validate and the link stays on-origin. The docs row and the mcp.test.ts list are updated. The merge only lowered the shared cap to 10 rows. I could not diff from 60cc24f because the commit is not in the clone, so I read the change as given.
Non-blocking: the card cuts to 10 rows where the issue says one row per live item. The JSON still has them all.
releaseswithshipped: truenow returns a card beside its JSON: the live version and short commit in the status line, then one row perliveitem (#number title, then repo and when). Rows are linked to/{repo}/pulls/{number}and theonItsWayrows follow. The new tests,test/mcp-size.test.tsandtest/mcp-cards-coverage.test.tspass, as dotscand the gate. The forge's own check hasn't reported on this push yet.releasebranch insrc/web/studio/cards.ts, which now tells the shipped answer (live) from the kept-releases answer (items).CARD_OF_TOOLalready pointedreleasesat it. Titles travel as plain text and the shared shell draws them withtextContent, so nothing is escaped by hand.test/mcp-releases-card.test.tscover this.- One calls the tool with
shipped: trueand checks that the rows match the JSON. - One checks the link, theonItsWayrows and a hostile title. It also checks that the old "shipped has no card" test is gone.ui://forge/releases, but I reused the existingui://forge/releaseresource. A second kind would add a resource and cost size for no gain, and the issue says to prefer the existing tool. No ceiling changed and there is no new tool.RELEASE_ROWSrows (live first, then on its way), so a long changelog is cut on the card; the JSON still has everything.releasestool with{"shipped": true}in a host that renders MCP Apps.The push hook wanted a "how to try it" commit, so there is an empty
Try:commit on the branch.Closes #11225