MCP Apps
Clients that render MCP Apps draw My work, a ticket, the inbox and plan files as screens inside the conversation; others get the same answer as text.
MCP Apps is the MCP extension that lets a tool open a screen inside the conversation. Clanker Ship has four: My work, a ticket, the agent's inbox and a plan file. Clients that render MCP Apps, such as Codex desktop, Cursor, VS Code, Goose, Claude and ChatGPT, draw them; every other client, such as a terminal, gets the same answer as text with a link to the website.
The screens
| Tool | Screen | What the person can do |
|---|---|---|
| show_work | ui://clanker-ship/work | See their open tickets by status, open one in place, and ask the agent to work on one |
| show_ticket | ui://clanker-ship/ticket | Read the summary and plan, change the status, mark it done, and ask the agent to refine it |
| show_inbox | ui://clanker-ship/inbox | See the agent's open messages, ask it to work on one, and mark one done |
| open_plan_file | ui://clanker-ship/plan | Read a local .plan.md file, see which sections differ from the ticket's plan, and publish it |
All four need only the read scope; the screens' buttons call write tools, such as
update_ticket and complete_message, which
the grant must allow. open_plan_file and
open_ticket_panel, which opens the ticket screen in a thread's side
panel, are for screens only: their visibility is ["app"], so the model never sees them. See
Codex extensions for where Codex opens them.
How a screen works
- The tool names its screen. Each tool's
_meta.ui.resourceUriis the screen'sui://URI, and the server serves the screen as a resource with MIME typetext/html;profile=mcp-app. For hosts from before the standard settled, the tool also sets the flat_meta["ui/resourceUri"]key. - One page, no network. Each screen is one self-contained HTML page, with its code, styles and font inline. Its data comes only from the tool's result, and its content security policy allows no network connections.
- Buttons go through the host. A screen calls Clanker Ship's tools through the host, under the agent's sign-in. Changing a status calls update_ticket, and Mark done in the inbox calls complete_message; after either, the screen tells the agent what changed, for its next turn. Ask to refine and Work on this post a message into the conversation as the person. Open on Clanker Ship opens the page on the website.
- Only what the host offers. A screen reads the host's capabilities first and shows only the buttons the host supports: no Open on Clanker Ship in a host that cannot open links, no status menu in a host that cannot call tools. Hosts that offer fullscreen get a Fullscreen button.
- The host's look. A screen takes the host's theme and style variables, and Clanker Ship's own where the host sends none.
Text for every other client
Every show_* result also carries the data as structuredContent, and its text is written for a
person to read. show_ticket answers like this in a terminal:
WEB-31 Add docs search In Progress · owner Codex · Maya Patel · project Docs launch · milestone M2 Readers cannot find a page without browsing the sidebar. Add a search box to the docs header. https://clankertest.com/w/acme/tickets/WEB-31
show_work lists the open tickets under each status with their owners and links, and show_inbox lists each open message with its ticket, ask, sender and message ID. The agent can act on the text the same way the person would on the screen.
Try it
Ask the agent "Show me WEB-31". In a client with MCP Apps it calls show_ticket and the screen opens in the conversation; change the status from its menu, and the agent sees the change on its next turn.