---
name: CAO MCP Apps
slug: cao-mcp-apps
category: Frontend
description: "CAO MCP Apps enables and extends CAO’s host-rendered fleet UI inside MCP App hosts like Claude Desktop, ChatGPT, VS Code Copilot, Goose, and Postman. Use it to turn on the surface, rebuild bundles, or add and troubleshoot ui://cao views."
github: "https://github.com/awslabs/cli-agent-orchestrator/tree/main/skills/cao-mcp-apps"
language: Python
stars: 1087
forks: 226
install: "npx degit https://github.com/awslabs/cli-agent-orchestrator/tree/main/skills/cao-mcp-apps ~/.claude/skills/cao-mcp-apps"
installs_to: ~/.claude/skills/cao-mcp-apps
source_path: skills/cao-mcp-apps/SKILL.md
collection_size: 18
category_size: 567
collection_url: "https://dirskills.com/collections/awslabs/cli-agent-orchestrator"
added: 2026-08-21T05:13:16.781Z
last_synced: 2026-08-21T05:13:16.781Z
canonical_url: "https://dirskills.com/skills/cao-mcp-apps"
---

# CAO MCP Apps

CAO MCP Apps enables and extends CAO’s host-rendered fleet UI inside MCP App hosts like Claude Desktop, ChatGPT, VS Code Copilot, Goose, and Postman. Use it to turn on the surface, rebuild bundles, or add and troubleshoot ui://cao views.

**Install:**

```bash
npx degit https://github.com/awslabs/cli-agent-orchestrator/tree/main/skills/cao-mcp-apps ~/.claude/skills/cao-mcp-apps
```

## README

# CAO MCP Apps

Operator + developer playbook for CAO's host-rendered fleet UI. Reference docs:
[`docs/mcp-apps.md`](../../docs/mcp-apps.md); example: [`examples/mcp-apps/`](../../examples/mcp-apps/).

**Authoritative spec & sources of truth:**
[MCP Apps Overview](https://modelcontextprotocol.io/extensions/apps/overview) ·
[Build an MCP App](https://modelcontextprotocol.io/extensions/apps/build) ·
[capability negotiation](https://modelcontextprotocol.io/extensions/overview#negotiation) ·
[client matrix](https://modelcontextprotocol.io/extensions/client-matrix) ·
stable spec [`2026-01-26/apps.mdx`](https://github.com/modelcontextprotocol/ext-apps/blob/main/specification/2026-01-26/apps.mdx)
(SEP-1865, Status: Stable) ·
SDK [`@modelcontextprotocol/ext-apps`](https://www.npmjs.com/package/@modelcontextprotocol/ext-apps) v1.7.4
([API ref](https://apps.extensions.modelcontextprotocol.io/api/index.html) ·
[repo](https://github.com/modelcontextprotocol/ext-apps)) ·
provenance [PR #1865](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/1865).

## Turn it on

The surface is **default-off**. Enable and run:

```bash
export CAO_MCP_APPS_ENABLED=true
uv run cao-server        # :9889 (REST + SSE /events)
uv run cao-mcp-server    # registers tools/resources via the mcp_apps plugin
```

It is packaged as the built-in `mcp_apps` plugin (`cao.plugins` entry-point). The
plugin's `on_mcp_server` hook registers the `ui://cao/*` resources, the five app
tools, the topology widget, and advertises the `io.modelcontextprotocol/ui`
capability — best-effort and default-off, so nothing changes when the flag is unset.

## What the operator gets

- `ui://cao/dashboard` — fleet overview + the mutation entry point.
- `ui://cao/agent` — one terminal's status, output tail, inbox, sub-agents.
- `ui://cao/event-stream` — live governance ticker (app-only).
- `cao://widget/topology` + `/widgets/topology/` — build-free live event view.

All mutations flow through `submit_command(kind, payload)` — kinds:
`send_message`, `assign`, `create_session` (standard); `interrupt`, `pause`,
`resume` (lifecycle); `shutdown_session` (destructive).
For full payload schemas and scope requirements per kind, see [references/submit-command-kinds.md](references/submit-command-kinds.md).

## Full capability scope (what the views use)

Beyond `tools/call`, the views exercise the spec's bidirectional channel:

- **Host-delegated open-link** (`ui/open-link`) — the dashboard shows
  "Open full Web UI ↗" → `http://127.0.0.1:9889` **only when** the host
  advertises `hostCapabilities.openLinks` (gate on `app.canOpenLinks()`; the
  sandbox forbids `window.open`).
- **Display modes** (`ui/request-display-mode`) — views declare
  `availableDisplayModes: ["inline","fullscreen"]` at `ui/initialize`.
- **Streamed tool input** (`ui/notifications/tool-input` / `-partial`) — render
  before the result lands.
- **Model-context notes** (`ui/update-model-context`) — body-free gesture
  summaries keep the agent aware without leaking message contents.

`preferredFrameSize` and `requiredScopes` are CAO additions, **not** spec
`_meta.ui` fields (the spec sizes via `containerDimensions` +
`ui/notifications/size-changed`); CAO requests **no** elevated `permissions`.

See [assets/mcp-apps-example.md](assets/mcp-apps-example.md) for a worked MCP Apps integration example.

## Gotchas

- **Host doesn't offer the views** → confirm `CAO_MCP_APPS_ENABLED=true` and that
  `initialize` advertises `io.modelcontextprotocol/ui` (the host must speak
  SEP-1865). Non-SEP-1865 hosts still get text-only tool results.
- **Views are blank / fail to load** → the React bundles aren't built. Run
  `cd cao_mcp_apps && npm ci && npm run build:all`. The topology widget needs no
  build and is the quickest smoke test (`curl /widgets/topology/topology.html`).
- **Mutations rejected with 403** → the auth layer is enabled and the token lacks
  `cao:write`/`cao:admin` (`cao:admin` for `delete_session`). Unset
  `AUTH0_DOMAIN`/`CAO_AUTH_JWKS_URI` to disable enforcement.
- **Events don't stream** → check `GET /events` (SSE) directly; the bus is
  drop-on-slow, so a stalled consumer silently loses events — re-hydrate via
  `cao_fetch_history`.

## Extending the surface

- **Agents emitting UI intents into this surface?** Load the **`agui-author`** skill
  — it teaches how to call `emit_ui` with the six allow-listed components. Your
  `emit_ui` intents feed the L2 constructs that these views render.
- **Building or migrating an MCP App? Load the `mcp-apps-builder` skill first.**
  It equips the official ext-apps Agent Skills (`create-mcp-app`,
  `add-app-to-server`, `migrate-oai-app`, `convert-web-app`) and the build guide.
  Use `add-app-to-server` when adding a new `ui://cao/<name>` view.
- **New command kind** → add it to `submit_command`'s classifier + router in
  `mcp_server/app_tools.py` (map to a real Backplane HTTP endpoint; never bypass
  the HTTP-only boundary) and to the scope pre-check.
- **New view** → add a `ui://cao/<name>` resource in `ext_apps/apps.py` + an entry
  point under `cao_mcp_apps/`, build it, and tag the rendering tool with
  `ui_meta(...)`.
  For the full step-by-step view creation procedure, see [references/extending-views.md](references/extending-views.md).
- **New host-delegated action** → add a thin method on the `McpApp` bridge
  (`cao_mcp_apps/src/shared/mcpApp.ts`) that issues the spec `ui/*` request
  (e.g. `openLink` → `ui/open-link`, `requestDisplayMode` →
  `ui/request-display-mode`); gate UI on the matching `hostCapabilities` flag and
  cover it with a `mockHost` test.
- **Keep the boundary** → `mcp_server/*` must reach state only over HTTP; the AST
  guard test (`test/test_http_only_boundary.py`) enforces it.
- **Keep bundles JIT-free** → no `eval`/`new Function` (host CSP forbids it); the
  CI scan fails the build otherwise.

## Recording & Verification

After building or modifying views, regenerate the demo media:

```bash
cd cao_mcp_apps && npm run build:all && npm run demo
```

This runs `scripts/record-demo.mjs` which:
1. Boots the E2E harness server (serves built bundles in a real MCP-host iframe)
2. Drives Chromium through: dashboard → agent detail → unified → event-stream
3. Records video (`docs/media/mcp-apps-demo.webm`)
4. Captures screenshots (`docs/media/mcp-apps-{dashboard,agent,unified,event-stream}.png`)
5. Generates an optimized GIF (`docs/media/mcp-apps-demo.gif`) when ffmpeg is available

The GIF is referenced in `README.md` and `docs/mcp-apps.md` — always regenerate after
view changes so docs stay current.

**Env overrides:** `CHROMIUM_BIN` (path to Chrome), `FFMPEG_BIN` (for GIF), `DEMO_PORT`.

For a worked example of the full MCP Apps surface in action, see [assets/mcp-apps-example.md](assets/mcp-apps-example.md).
