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
What it checks
The current runner validates:- MCP Apps tools are present.
- Tool metadata uses valid
_meta.ui.resourceUriandvisibilityvalues. - Tool
inputSchemais a non-null JSON Schema object. - Listed UI resources use
ui://URIs andtext/html;profile=mcp-app. - Referenced UI resources can be fetched with
resources/read. - Resource contents provide exactly one HTML payload via
textorblob. _meta.ui.csp,permissions,domain, andprefersBorderuse valid shapes.
Example output
Suite runner
Useapps conformance-suite when you want a named CI matrix from a config file.
Example config:
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, optionalargs, optionalenv, and optionalcwd
Categories and check ids
Two categories are available:toolsresources
ui-tools-presentui-tool-metadata-validui-tool-input-schema-validui-listed-resources-validui-resources-readableui-resource-contents-validui-resource-meta-valid
--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
Usetools 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.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.
Outcomes: passed, failed, incomplete
A run reports one of three outcomes, andpassed is true only for the first:
Every skipped check carries a
skipReason:
not-applicable— the check cannot apply here (no MCP Apps tools discovered, no UI resources listed). These never hold a run back.could-not-run— the check applies but was never exercised (tools/list did not complete, connection failed). These make the runincomplete.
incompleteReason naming the checks that did not run and what to change; non-quiet runs also print it to stderr. For a suite, the exit code is the worst of all runs (failure outranks incomplete).
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 conventions (length, character set, uniqueness) are core MCP rules, so this suite does not check them. The protocol suite reports them on every tool as the advice item
readiness-tool-name-conventions, on protocol 2025-11-25 and later. permissionsare validated against the SEP-1865 object shape, for examplegeolocation: {}instead of booleans.- Exit codes are CI-friendly:
0when all selected checks pass,1when any check fails,2for invalid command usage or config files, and3when the run is incomplete because a selected check could not be run.
Related commands
- Server inspection for breadth-first connectivity and capability triage
- Tools, resources & prompts for direct connected checks
- Command reference for the full flag list

