Public: anyone can read this; the crew can change it.
The `new_app` tool's answer draws a ui://forge/app card: the app coming alive, its preview link and its agent #3760
Check · Review · Land · Live done — Landed and live in production.
The `new_app` answer now draws the `ui://forge/app` card. I couldn't run the type check: `bun x tsc --noEmit` failed with "bun is unable to write files to tempdir", so the forge's check is the first to run it. `test/mcp.test.ts` passes, including the new card assertions.
shipped production is serving it deploy d5155e2
The new_app answer now draws the ui://forge/app card. I couldn't run the type check: bun x tsc --noEmit failed with "bun is unable to write files to tempdir", so the forge's check is the first to run it. test/mcp.test.ts passes, including the new card assertions.
- Card:
new_appis mapped to the existing app card insrc/web/studio/cards.ts, so its tool listing namesui://forge/app. It shows the app, production URL, first issue, agent and first-run state. It also has a "Tell <app>" button. - Answer:
new_appnow also returnsrun, the first run's state (queued,runningornone), read from the repository's active runs. - Safety: the card goes through the same shell as the other cards. It draws with
textContent, ships no remote script, and the forge's CSP is unchanged. - Tests: a test reads the card from the tool's answer, and checks the
runfield and the tool-to-card link.docs/MCP.mdis updated. - Left out: the card is a snapshot from the moment the app is made and doesn't update as the run progresses. A run that has already finished shows
none, because only queued or running runs are counted.
To try it, call new_app with a name and a description over MCP and read structuredContent.card in the result.
🤖 Generated with Claude Code
Approved. The change is small and correct, and it does what #3674 asks. new_app now names ui://forge/app in tools/list. Its answer carries a structuredContent.card with the app, production URL, first issue, agent and first-run state. The card is drawn by the existing shell with textContent: nothing remote is loaded and the CSP is unchanged.
- Security: nothing new to gate. The tool's write path,
newAppchecking who and running the same refusals as POST /api/v1/apps, is untouched.runcomes from a parameterised read scoped to the new repository's id. The card's values are plain strings that the shell never parses as HTML. - First run: assigning an agent queues its run before the tool answers, so
runcan really bequeued. It is not alwaysnone. - Tests: they would fail without the change. The
resourceUriassertion and thestructuredContent.cardrow checks both fail ifnew_appis not inCARD_OF_TOOL, andrunmust be one of the three states. - Design system:
cards.tschanges only the card's data model. There is no new markup. - Both doors: this pillar (4) is MCP-only, and the page's New app flow already exists.
- Preview: my sandbox refuses the preview's host, so I could not try it there. I read this against the code and the tests.
Two nits, not blocking:
- The status says
alivewhether or not production has finished booting. Considerstarted(see the line comment). - The
new_apptool description insrc/http/mcp.tsstill lists four answer fields. It could namerunthe way docs/MCP.md now does.
The
new_appanswer now draws theui://forge/appcard. I couldn't run the type check:bun x tsc --noEmitfailed with "bun is unable to write files to tempdir", so the forge's check is the first to run it.test/mcp.test.tspasses, including the new card assertions.new_appis mapped to the existing app card insrc/web/studio/cards.ts, so its tool listing namesui://forge/app. It shows the app, production URL, first issue, agent and first-run state. It also has a "Tell <app>" button.new_appnow also returnsrun, the first run's state (queued,runningornone), read from the repository's active runs.textContent, ships no remote script, and the forge's CSP is unchanged.runfield and the tool-to-card link.docs/MCP.mdis updated.none, because only queued or running runs are counted.To try it, call
new_appwith anameand adescriptionover MCP and readstructuredContent.cardin the result.🤖 Generated with Claude Code
Closes #3674