Skip to main content
The apps conformance command validates the server-side MCP Apps surface your server exposes through tools and ui:// resources. Use tools call --ui when you want to execute one UI-capable tool and render the completed result in the local Inspector App Builder.
This is currently server-side MCP Apps conformance only. A passing run does not prove full SEP-1865 host behavior such as ui/initialize, ui/notifications/tool-input ordering, sandbox proxy behavior, or host display-mode handling.

Quick start

For a local stdio server:
You can emit CI-friendly JUnit XML from either the single-run or suite command:
To reproduce one tool result in the local Inspector:

What it checks

The current runner validates:
  1. MCP Apps tools are present.
  2. Tool metadata uses valid _meta.ui.resourceUri and visibility values.
  3. Tool inputSchema is a non-null JSON Schema object.
  4. Listed UI resources use ui:// URIs and text/html;profile=mcp-app.
  5. Referenced UI resources can be fetched with resources/read.
  6. Resource contents provide exactly one HTML payload via text or blob.
  7. _meta.ui.csp, permissions, domain, and prefersBorder use valid shapes.

Example output

Typical success summary:

Suite runner

Use apps conformance-suite when you want a named CI matrix from a config file. Example config:
Run it with:
target uses the same shared server shape as the rest of the CLI, so it can point at either:
  • an HTTP target with url
  • a stdio target with command, optional args, optional env, and optional cwd

Categories and check ids

Two categories are available:
  • tools
  • resources
Specific check ids:
  • ui-tools-present
  • ui-tool-metadata-valid
  • ui-tool-input-schema-valid
  • ui-listed-resources-valid
  • ui-resources-readable
  • ui-resource-contents-valid
  • ui-resource-meta-valid
Use --category to run a subset by category, or --check-id to run specific checks.
If you pass both --category and --check-id, the explicit --check-id selection wins.

Render one app result

Use tools list to find UI-capable tools. A tool has interactive UI when its metadata includes _meta.ui.resourceUri, deprecated _meta["ui/resourceUri"], or openai/outputTemplate in toolsMetadata. Then use tools call --ui when you need to inspect the output of one UI-capable tool call. The CLI starts or attaches to the local Inspector backend, opens Inspector by default in a TTY, connects the target server, focuses App Builder in the active Inspector browser client, injects the already-completed tool result, and requests a UI snapshot. --inspector-url is the Inspector backend/API URL; --frontend-url is the browser/client URL and skips frontend discovery. Use --no-open when browser automation already opened http://127.0.0.1:6274/#app-builder; use --attach-only to disallow startup, browser opening, and discovery. Default non-TTY --ui runs do not open a browser unless --open is passed. TTY stderr runs print the App Builder URL and initial wait progress unless --quiet is set; the elapsed-seconds heartbeat only appears when stderr is a TTY.
tools call --ui executes the server tool once. Inspector receives the completed result through renderToolResult, so the UI render path does not call the tool a second time. The rendered state lives in the active Inspector client; opening the URL in a fresh tab later does not hydrate the old render.
If inspectorRender.status is skipped, the tool call succeeded but Inspector had no active browser client, a render precondition was missing, or the render wait timed out; the envelope includes a stable root warning and inspectorRender.warning with one of the stable codes no_active_client, timeout, disconnected_server, or unsupported_in_mode, plus an inspectorRender.remediation hint. Non-quiet runs print a stderr tip, and the command keeps the tool-call exit code unless --require-render is set. If the command returns success: false with an error, check whether the failure came from result or from an Inspector render command. Raw ui:// resource HTML can be inspected directly:

Shared connection flags

apps conformance uses the same shared target flags as the rest of the CLI: Stdio child processes inherit the parent shell environment by default. Use -e/--env to add values or override inherited ones when the app server needs project-specific configuration. --transport is optional; without it, --url implies HTTP and --command implies stdio.

Notes

  • The runner always advertises the MCP Apps UI extension capability so servers do not hide their MCP Apps surface when custom client capabilities are provided.
  • Deprecated _meta["ui/resourceUri"] is accepted but reported as a warning.
  • Tool name SHOULD validations (length, character set, uniqueness) surface as warnings, not failures.
  • permissions are validated against the SEP-1865 object shape, for example geolocation: {} instead of booleans.
  • Exit codes are CI-friendly: 0 when all selected checks pass, 1 when any check fails, and 2 for invalid command usage or config files.