# MCP Apps widget, approval status and plugin marketplaces

The todo widget runs the MCP Apps handshake so Claude and ChatGPT render it, agents can read the outcome of an approval and follow an absolute link to it, the server announces instructions and annotations, and the agent plugin installs from Claude Code, Codex, Cursor and Grok with production URLs.

The `todo_list` widget now renders in hosts that follow the MCP Apps specification. The view performs the `ui/initialize` → `ui/notifications/initialized` handshake the specification requires before a host may send tool data, then renders `ui/notifications/tool-result`; it keeps reading `window.openai.toolOutput` for ChatGPT builds that still inject it. There is one resource, `ui://widget/todos/v2` with `text/html;profile=mcp-app` and an explicit empty CSP; `openai/outputTemplate` is the ChatGPT alias of `_meta.ui.resourceUri` and points at the same URI, so the `text/html+skybridge` duplicate is gone. A jsdom harness plays the host side in the test suite.

The MCP server says what it is. `initialize` names it after the OAuth issuer host instead of the template, returns `instructions` that summarize the approval flow, and declares `listChanged: false` for tools, resources and prompts, since a server built per request never notifies. Every tool sets all four annotations (reads are read-only and idempotent; nothing is destructive or open-world) and write tools publish the approval envelope as their `outputSchema`.

Agents can follow an approval to its end. A write call returns an absolute `approvalUrl`, `/integrations?approval=<id>` on the deployment that served it, which opens Integrations on that record. The new read-only `approval_status` tool reports whether the user executed (with the stored result), denied or let the request expire; the catalog has sixteen tools. The OAuth provider offers the `email` scope so UserInfo returns `email` and `email_verified`, and `/.well-known/openai-apps-challenge` serves the `OPENAI_APPS_CHALLENGE_TOKEN` Worker var during an OpenAI plugin review (404 while unset).

The agent plugin package is installable again. The Cursor and Grok marketplaces pointed at a folder that had been renamed, every manifest used the workers.dev origin instead of the production domain, and `plugin.json` carried a top-level `logo` the Agent Plugins 1.0.0 schema rejects. Listing copy and logo moved under `extensions["com.openai"].interface`, `mcp.json` declares the OAuth client, and new `.claude-plugin/marketplace.json` and `.agents/plugins/marketplace.json` files make it installable from Claude Code, the ChatGPT desktop app and Codex. The connection guide describes ChatGPT's current path, chatgpt.com/plugins → + → Add custom MCP server.

- [MCP and agent connections](/docs/features/mcp)
- [Connect your agent](/docs/connect-your-agent)
- [ADR-0007](/docs/adr/0007-ai-assistant-and-tool-catalog)

Sources: [widget and server](https://github.com/CarlosZiegler/template-cloudflare/commit/f09f9ddc), [approval status](https://github.com/CarlosZiegler/template-cloudflare/commit/19ff59ad), [challenge route and email scope](https://github.com/CarlosZiegler/template-cloudflare/commit/bebc6578), [plugin marketplaces](https://github.com/CarlosZiegler/template-cloudflare/commit/309f43e4).

