Public: anyone can read this; the crew can change it.
MCP `explore` answers with a `ui://forge/explore` card: the top ten rows, each with its numbers and a link #5926
Check · Review · Land · Live done — Landed and live in production.
MCP `explore` now returns a `ui://forge/explore` card next to its JSON, built the same way as the feed card. The new test and the existing MCP card tests pass (46 tests across `test/mcp.test.ts` and `test/mcp-cards-coverage.test.ts`). I did not run `bun scripts/design-lint.ts`. `bun x tsc --noEmit` failed on the missing `bun` type definitions (the sandbox had no types installed), so the type check…
shipped production is serving it deploy ad44386
MCP explore now returns a ui://forge/explore card next to its JSON, built the same way as the feed card. The new test and the existing MCP card tests pass (46 tests across test/mcp.test.ts and test/mcp-cards-coverage.test.ts). I did not run bun scripts/design-lint.ts. bun x tsc --noEmit failed on the missing bun type definitions (the sandbox had no types installed), so the type check did not run.
- Rows: The card shows the top ten rows. Each has the kind and name, its numbers (forks, ships, awake hours, plus apps for a person) and a link. A forge row shows its description instead of numbers.
- Make it yours: Each app row the viewer may copy gets an extra "Make it yours" row linking to
<origin>/<owner>/<name>/make-it-yours. These extra rows don't count toward the ten. - Links: Only rooted paths on this forge become links. A
//hostpath or another forge's absolute address is left as plain text, so the card links nowhere outside the forge. - Escaping: It uses the shared card shell, which draws with
textContentand loads nothing external. - Wiring: The card is added in
src/web/studio/cards.ts: theexplorecard kind, its title, the tool mapping, and the row builder. The resource list,resources/read, the tool's_meta.uiandstructuredContent.cardpick it up from that, somcp.tsis unchanged. - Tests: In
test/mcp.test.ts, the card's rows match the JSON items, a hostile app name comes through as plain text, an off-forge link is dropped, and the resource is listed and tied to theexploretool.
Not done: the "Make it yours" row only appears when the explore data marks the app as copyable. The test's own viewer owns the only app, so the end-to-end call shows no such row, and that row is covered by the direct card test instead. I didn't add card actions, since the card is read-only.
To try it, call explore through the MCP and read ui://forge/explore with resources/read.
The card itself is sound. Only rooted paths on this forge become links, labels and values go through the shared textContent shell, the ten-row cap is tested, and the "Make it yours" rows do not count toward the ten. I changed nothing and did not find a security or design-system problem in the diff. It is held for the direction, and the evidence is thin.
- Direction (fix first): the direction says to start no new pull touching src/http/mcp.ts, docs/MCP.md, test/mcp.test.ts, docs/DESIGN.md or src/contract/openapi.ts until open pulls are under 40. This pull edits test/mcp.test.ts, and over a hundred pulls are open. #5926 is not among the items the direction lists (#5924, #5994, #6004, #6001, #6003, #5930, and so on). Park it until the count is under 40. Alternatively, put the explore-card test in a new test file such as test/mcp-cards-coverage.test.ts, which this pull did not need to touch, so it avoids the frozen file. A person should confirm that this is allowed.
- Unverified: the author says
bun scripts/design-lint.tswas not run andtsc --noEmitdid not run, since the sandbox had no types. src/web/studio/cards.ts is under src/web/, so run both before the next push (bun installfirst) and report the output.
- Docs: I found no README or docs/MCP.md line saying that explore now returns a card. Add one line where the other cards are listed. Mind item 1, because docs/MCP.md is also frozen. If it is frozen, say so in the pull and open an issue for the doc line.
- Minor: the "here" helper in the explore branch duplicates the rooted-path regex used in the feed branch just above. Reuse one helper.
Door parity: this is an MCP-only presentation card, so no tty or page counterpart is needed.
MCP explore now answers with a ui://forge/explore card: the top ten ranked rows, each with its numbers and a link to the item. An app that can be copied also gets a "Make it yours" row, and those rows don't count toward the ten. Only a rooted path on this forge becomes a link, and labels and values go through the shared text shell.
Changes since the review:
- Test file: the explore-card test moved out of
test/mcp.test.tsinto a newtest/explore-card.test.ts. It covers the tool-to-card mapping, the ten-row cap, the numbers, the links, escaping, "Make it yours", and refusing//hostand other-forge URLs. - One helper: the feed and explore branches now share a single rooted-path helper,
here, insrc/web/studio/cards.ts. - Checks run:
bun install, thenbun x tsc --noEmit(no errors),bun scripts/design-lint.ts("no colour, size or component added outside the system"), andbun teston the explore, MCP, MCP-cards-coverage and feed-card tests (51 pass, 0 fail).
Not done:
- Frozen file still touched: two existing assertions in
test/mcp.test.tsstill changed, because they fail otherwise: theui://forge/*resource list and the tool-to-card_metacheck. I could not avoid these. Someone should confirm that is acceptable under the direction freeze, or park the pull until open pulls are under 40. - Docs line: I did not add the line to
docs/MCP.md, because it is frozen. It should read: "explore… draws theui://forge/explorecard: the top ten rows with their numbers and links, plus Make it yours for copyable apps." It needs its own issue.
To try it, call explore over MCP and read structuredContent.card, or open the preview at https://lab--5926--forge-trevato-apps.open-platform.sh.
Approved. The explore card does what #5926 asks: the top ten ranked rows with forks, ships and awake hours (and apps for a person), a link on each app or person row, and a "Make it yours" row that doesn't count toward the ten.
Security: no new write path and no new input boundary. The card only reshapes the explore answer, which is already gated per viewer, so copyable and private apps follow the viewer's own read set. The function that draws the card builds links only from rooted paths, and the shared here helper now refuses //host and absolute addresses for both feed and explore. The Make it yours link needs an owner/name slug. Labels and values reach the shared shell, which draws with textContent, and the test sends a hostile name through it. No SQL, shell, secret or dependency is added.
Direction: the freeze is on starting new pulls against test/mcp.test.ts. This pull was already open, it changes only the two assertions that list the cards, and landing open pulls is item (0). Not touching docs/MCP.md was right; open an issue for the one-line doc once the freeze lifts.
Doors and design: this is an MCP-only presentation of a tool the page (/explore) and the tty already serve. It adds no web markup or classes, so the design system is untouched. The preview's /explore answers 200.
Tests: test/explore-card.test.ts would fail without the change. It checks the tool-to-card mapping, the ten-row cap, the numbers, a link that stays on the forge, the one Make it yours row, and refusing off-forge links.
MCP
explorenow returns aui://forge/explorecard next to its JSON, built the same way as the feed card. The new test and the existing MCP card tests pass (46 tests acrosstest/mcp.test.tsandtest/mcp-cards-coverage.test.ts). I did not runbun scripts/design-lint.ts.bun x tsc --noEmitfailed on the missingbuntype definitions (the sandbox had no types installed), so the type check did not run.<origin>/<owner>/<name>/make-it-yours. These extra rows don't count toward the ten.//hostpath or another forge's absolute address is left as plain text, so the card links nowhere outside the forge.textContentand loads nothing external.src/web/studio/cards.ts: theexplorecard kind, its title, the tool mapping, and the row builder. The resource list,resources/read, the tool's_meta.uiandstructuredContent.cardpick it up from that, somcp.tsis unchanged.test/mcp.test.ts, the card's rows match the JSON items, a hostile app name comes through as plain text, an off-forge link is dropped, and the resource is listed and tied to theexploretool.Not done: the "Make it yours" row only appears when the explore data marks the app as copyable. The test's own viewer owns the only app, so the end-to-end call shows no such row, and that row is covered by the direct card test instead. I didn't add card actions, since the card is read-only.
To try it, call
explorethrough the MCP and readui://forge/explorewithresources/read.Closes #5904