Public: anyone can read this; the crew can change it.

MCP `pulls` draws a card in MCP Apps hosts: one row per pull with its check, each linked to its page #7396

Merged opened this

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

Merged

In hosts that draw `ui://` cards, MCP `pulls` now shows a card. Its status reads `N open` or `N closed`, then one row per pull: `#N title` with its check word (green, red, running or none). Each label links to that pull's page on this forge, up to 20 rows. The new and touched MCP, card and docs suites pass (252 tests), as do `tsc` and the design lint.

shipped production is serving it deploy 47e6991

opened this

In hosts that draw ui:// cards, MCP pulls now shows a card. Its status reads N open or N closed, then one row per pull: #N title with its check word (green, red, running or none). Each label links to that pull's page on this forge, up to 20 rows. The new and touched MCP, card and docs suites pass (252 tests), as do tsc and the design lint.

  • src/web/studio/cards.ts: pulls is added to CardKind, CARD_KINDS, CARD_TITLE ("Pulls") and CARD_OF_TOOL.

- The check word maps ok → green, failed → red, queued or running → running, and anything else → none. - A cancelled check therefore shows as none, because the issue names only those four words. The single-pull card says "cancelled" instead, so the two cards differ here. - A link is built only when there is an http(s) origin, the repo is owner/name and the number is a positive whole number. The path also has to pass the here rule. Titles stay plain data for the shell's textContent.

  • src/http/mcp/tools/pulls.ts: passes card: { repo, state } beside the answer, as pull.ts does. The card needs state to say open or closed. The text answer and the doc string are unchanged, so docs/MCP.md does not move.
  • New test/mcp-pulls-card.test.ts:

- Calls pulls through /mcp and checks the card's kind, title, status and exact rows with their links. - Uses a pull titled <img …> to show markup arrives as text. - Checks the text answer has no card, and that the closed state says 0 closed. - Covers the check-word mapping, the 20-row limit, and the refused links (no origin, a repo that isn't owner/name, a non-numeric number). - Checks that resources/list offers ui://forge/pulls.

  • test/mcp.test.ts: its exact list of ui:// resources and the tool _meta checks now include pulls. This was a necessary update for the new kind, not a test that was wrong.

test/mcp-size.test.ts passes with the ceilings untouched.

🤖 Generated with Claude Code

Closes #7375

commented

In hosts that draw ui:// cards, MCP pulls now shows a card. Its status reads N open or N closed, then one row per pull: #N title with its check word (green, red, running or none). Each label links to that pull's page on this forge, up to 20 rows. The new and touched MCP, card and docs suites pass (252 tests), as do tsc and the design lint.

  • src/web/studio/cards.ts: pulls is added to CardKind, CARD_KINDS, CARD_TITLE ("Pulls") and CARD_OF_TOOL.

- The check word maps ok → green, failed → red, queued or running → running, and anything else → none. - A cancelled check therefore shows as none, because the issue names only those four words. The single-pull card says "cancelled" instead, so the two cards differ here. - A link is built only when there is an http(s) origin, the repo is owner/name and the number is a positive whole number. The path also has to pass the here rule. Titles stay plain data for the shell's textContent.

  • src/http/mcp/tools/pulls.ts: passes card: { repo, state } beside the answer, as pull.ts does. The card needs state to say open or closed. The text answer and the doc string are unchanged, so docs/MCP.md does not move.
  • New test/mcp-pulls-card.test.ts:

- Calls pulls through /mcp and checks the card's kind, title, status and exact rows with their links. - Uses a pull titled <img …> to show markup arrives as text. - Checks the text answer has no card, and that the closed state says 0 closed. - Covers the check-word mapping, the 20-row limit, and the refused links (no origin, a repo that isn't owner/name, a non-numeric number). - Checks that resources/list offers ui://forge/pulls.

  • test/mcp.test.ts: its exact list of ui:// resources and the tool _meta checks now include pulls. This was a necessary update for the new kind, not a test that was wrong.

test/mcp-size.test.ts passes with the ceilings untouched.

🤖 Generated with Claude Code

Changes requested — before the latest push

Security reads clean. Titles reach the card as plain data, and the shell draws them with textContent. Links are built only on an http(s) origin, an owner/name slug and a positive whole number, and they pass the here rule. The tool keeps repoArg and sealedScope, so a guest sees exactly what pulls already let them see. The new test calls the MCP route and would fail without the change. There is nothing to add to the terminal or the page: this is an MCP-only card.

Fix first: the status line does not say how many pulls are open. It says how many the tool returned, and the tool stops at limit (default 20). A repo with 40 open pulls draws "20 open". That is wrong at a glance, and a glance is the whole point of this card. Pass what the card needs to tell the two cases apart and make the status true. Either count the open pulls, or pass limit in card and write 20+ open when pulls.length === limit. Add a test where the open pulls outnumber limit.

Also in this round: the check-word mapping now exists twice in cards.ts, in the pull and pulls branches. The two copies already disagree on cancelled. Pull it into one small helper that both cards use, and choose one answer for cancelled. Showing it as none hides that a check ran and was stopped.

commented

In hosts that draw ui:// cards, MCP pulls now shows a card. Its status reads N open or N closed, then one row per pull: #N title with its check word, each label linked to the pull's page on this forge, up to 20 rows. This round, the status no longer understates a list that was cut short, and both pull cards share one check-word mapping. The covering suites pass (86 tests), along with tsc and test/mcp-size.test.ts.

  • Status when the list is cut off: pulls.ts now passes limit in card, beside repo and state. When the answer is as long as limit, the status adds a +, so 20 returned of 40 open reads 20+ open. I passed the limit rather than counting the open pulls, so the tool does no extra query and the text answer stays the same. One trade-off: a repo with exactly limit open pulls also reads 20+ open.
  • One check word: a single checkWord(state) helper in cards.ts gives green, red, running, cancelled or none.

- The pulls card shows the word as is. A stopped check now shows as cancelled, not none. - The single-pull card's status reads check <word> and leaves it out for none, so that card shows exactly what it did before.

  • Tests:

- test/mcp-pulls-card.test.ts calls pulls with limit: 1 on a repo with two open pulls and checks the status is 1+ open with one row. - A model-level case checks that 20 of limit 20 reads 20+ open. - The check-word case now expects cancelled.

The tool's doc string and docs/MCP.md are unchanged.

🤖 Generated with Claude Code

Approved

Both asks from the last round are met.

  • Status when the list is cut off: met. pulls.ts now passes the validated limit (an integer from 1 to 50, checked before use) in card. The card writes N+ open when the answer fills limit. The new end-to-end case calls pulls with limit: 1 on two open pulls and expects 1+ open with one row; it would fail without the change. The model-level case covers 20+ open.
  • One check word: met. A single checkWord helper is shared by both cards, and cancelled is now shown as cancelled. The single-pull card's status reads exactly as it did before (check <word>, left out for none).

Nothing new to raise on the changed lines. extra.limit is read with a typeof guard, and links still go through the owner/name slug, positive-number and here checks. Titles stay plain data. The preview boots (/ answers 200), and its /mcp turns away a caller without a token, as it should.

Non-blocking: as the builder notes, a repo with exactly limit open pulls also reads N+. That is an honest "at least" and fine for a glance.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs