Skip to content

feat: MCP App validator (library + CLI) — reference implementation for #673#722

Open
RyanAlberts wants to merge 2 commits into
modelcontextprotocol:mainfrom
RyanAlberts:validator-673
Open

feat: MCP App validator (library + CLI) — reference implementation for #673#722
RyanAlberts wants to merge 2 commits into
modelcontextprotocol:mainfrom
RyanAlberts:validator-673

Conversation

@RyanAlberts

Copy link
Copy Markdown

What

A working reference implementation of the official MCP App validator proposed in #673, opened as a draft to make that discussion concrete. Happy to restructure any part of it to maintainer preference (naming, location, scope).

New export @modelcontextprotocol/ext-apps/validator + mcp-app-validator bin:

  • Requirements catalogue (src/validator/rules.ts): every check is backed by a rule with a stable id (APP-001…), the normative MUST/SHOULD sentence it enforces, and the spec section — MUST → error, SHOULD → warning. The direction field (app/server/host) reserves the same id space for host-side rules, so the platform-conformance work in Set up public MCP Apps platform tests #674 and this validator can share one catalogue instead of drifting apart.
  • Static checks (no rendering): connects with the io.modelcontextprotocol/ui extension capability advertised, then validates tools/list / resources/list / resources/read: ui:// scheme, text/html;profile=mcp-app mimeType, text-or-blob content, HTML sanity, tool-referenced resources resolving, _meta.ui shapes via the SDK's generated Zod schemas, CSP origin well-formedness, visibility values, deprecated flat-key usage.
  • Behavioral checks: loads the app HTML under a minimal Playwright mock host speaking the postMessage JSON-RPC protocol; checks the ui/initialize handshake, appCapabilities presence, initialized notification, JSON-RPC well-formedness / known methods, size-changed emission, tools/list answered when the tools capability is declared, and display-mode discipline. Playwright is resolved lazily — static validation runs without it, and behavioral rules report themselves as skipped when it's absent.
  • CLI: mcp-app-validator <url> / --stdio <cmd…> / --html <file>, --json for CI, exit codes 0 (clean) / 1 (errors) / 2 (usage or connection failure).

Validation

  • bun test src: 298 pass (14 new validator tests using the existing McpServer + InMemoryTransport pattern)
  • Ran the CLI against all 22 Node example servers in this repo: all pass; pdf-server correctly draws the SHOULD-level APP-104 warning (no ui/notifications/size-changed observed)
  • Negative case: a non-app HTML document fails APP-100 with exit code 1

Open questions (mirrored on #673)

  1. Naming/placement: separate bin vs folding into a future create-mcp-app CLI (Add official CLI scaffolding tool for MCP Apps #354)?
  2. Should the behavioral harness exercise a real tool-call path via a --tool flag instead of a synthetic ui/notifications/tool-input?
  3. Ship a JSON catalogue export for Set up public MCP Apps platform tests #674/third-party harnesses now, or after rule ids stabilize?

Aware of the SDK v2 migration (#702/#710) — SDK contact is contained to two small modules, and I'm glad to rebase onto the v2 tree if preferred.

Refs #673

🤖 Generated with Claude Code

RyanAlberts and others added 2 commits July 20, 2026 20:05
…talogue

Adds @modelcontextprotocol/ext-apps/validator and a mcp-app-validator bin
implementing the official app validator proposed in modelcontextprotocol#673:

- rules.ts: machine-readable catalogue of app-side spec requirements
  (stable APP-NNN ids, MUST->error / SHOULD->warning severity, spec
  section + normative sentence per rule; direction field reserved for
  host-side rules per modelcontextprotocol#674)
- static.ts: no-render checks over tools/list, resources/list, and
  resources/read (ui:// scheme, mcp-app mimeType, text-or-blob content,
  HTML sanity, resource existence, _meta.ui shapes via the generated Zod
  schemas, CSP origin well-formedness, visibility values, deprecated
  flat-key usage)
- harness.ts: behavioral checks under a minimal Playwright mock host
  speaking the postMessage JSON-RPC protocol (initialize handshake,
  appCapabilities, initialized notification, JSON-RPC well-formedness,
  size-changed emission, tools/list answer when the tools capability is
  declared, display-mode discipline); playwright resolved lazily so
  static validation runs without it
- CLI: streamable-HTTP / --stdio / --html targets, pretty and --json
  reporters, exit codes 0/1/2

Validated against the in-repo examples: all Node example servers pass;
pdf-server correctly draws the APP-104 (size-changed) warning.

Refs modelcontextprotocol#673

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Add src/validator/index.ts to typedoc entryPoints; export the option and
  result types it references so the JSDoc validation check passes clean
- Add a "Validate against the specification" section to testing-mcp-apps.md

Refs modelcontextprotocol#673

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@RyanAlberts
RyanAlberts marked this pull request as ready for review July 21, 2026 04:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant