“Invalid ui.domain format”
The view's _meta.ui.domain is not of the one form Claude accepts, `{hash}.claudemcpcontent.com`, so Claude refuses to render it. The three common causes: (1) It is an https origin, set for ChatGPT, whose review requires an origin of your own: ChatGPT and Claude read the same field in different formats. To tell: The doctor fails at resource-domain-claude with the https value, and passes resource-domain-chatgpt. (2) It is a bare host name or another provider's sandbox domain, from a framework default or a copied example. To tell: The doctor fails at resource-domain-claude and prints the value next to the one Claude expects for your URL. (3) The connector is a local stdio server, which has no URL to hash, so no ui.domain can be valid for Claude. To tell: The doctor cannot reach a stdio server; remove the field for local connectors, or deploy it as a remote one. One command shows which: npx --allow-git=root github:agentwares/mcp-apps-doctor https://your-server.example/mcp --host claude.
Check your server now
npx --allow-git=root github:agentwares/mcp-apps-doctor https://your-server.example/mcp --host claude
Discovery only: no credential, no tool called. It prints the first broken step, whose it is, and the fix with its source, and shows the view in a sandboxed preview.
Who prints it
Claude (claude.ai and Claude Desktop), in full: `Invalid ui.domain format: expected "{hash}.claudemcpcontent.com", got "…"`, sometimes behind an "Unable to reach <app>" banner.
The three causes, and how to tell them apart
- Cause 1. It is an https origin, set for ChatGPT, whose review requires an origin of your own: ChatGPT and Claude read the same field in different formats.
The check flags it atresource-domain-claude. The doctor fails at resource-domain-claude with the https value, and passes resource-domain-chatgpt. - Cause 2. It is a bare host name or another provider's sandbox domain, from a framework default or a copied example.
The check flags it atresource-domain-claude. The doctor fails at resource-domain-claude and prints the value next to the one Claude expects for your URL. - Cause 3. The connector is a local stdio server, which has no URL to hash, so no ui.domain can be valid for Claude.
The check cannot see this one from outside: it happens inside the host or the portal. The doctor cannot reach a stdio server; remove the field for local connectors, or deploy it as a remote one.
Sources and public reports
- "ui.domain validation fails": the value must be exactly {hash}.claudemcpcontent.com [source: Claude, Troubleshoot MCP Apps, read 8 October 2026]
- ui.domain set to "https://ai.todoist.net" blocked the widget in claude.ai [observed in Doist/todoist-mcp#432, opened 2 April 2026]
- a custom domain ("mydomain") from the framework's MCP Apps support was refused [observed in laravel/mcp#218, opened 18 May 2026]
Keep checking
Other messages
- “MCP App renders blank”
- “Resource not found: ui://”
- “Tool has no UI”
- “ui.domain mismatch”
- “Refused to load the script”
- “annotations_required”
- “domain_verification_required”
- “frame_domain_explanation_required”
- “screenshots_not_allowed”
- “Failed to fetch template”
Written 8 October 2026 from the sources above. The MCP Apps check · MCP Liveness · Terms · Privacy