Command Palette

Search for a command to run...

UnylyUnyly
Весь каталог

Apps Doctor

БесплатноНе проверен

Why your MCP App renders blank: checks a remote MCP server's ui:// views (tool link, MIME type, CSP, the ui/initialize bridge, ui.domain) for Claude, ChatGPT an

GitHubEmbed

Описание

Why your MCP App renders blank: checks a remote MCP server's ui:// views (tool link, MIME type, CSP, the ui/initialize bridge, ui.domain) for Claude, ChatGPT and any MCP Apps host, plus ChatGPT's directory review, says whose it is and the fix, and previews the view sandboxed.

README

Why your MCP App renders blank.

npx --allow-git=root github:agentwares/mcp-apps-doctor https://your-server.example/mcp

It opens a remote MCP server the way an MCP Apps host does — Claude, ChatGPT, VS Code — with no credential and without calling a tool, reads each tool's ui:// view, and prints:

  • the first step that stops the view rendering: the tool's link, the resource, its MIME type, what its HTML loads against the CSP the host builds, the ui/initialize bridge, ui.domain;
  • whose it is: the server, or a known host bug, with the issue;
  • the fix, citing the MCP Apps spec (SEP-1865) or the host's own documentation, with the date it was read;
  • a verdict per host — any MCP Apps host, Claude, ChatGPT — and for ChatGPT's directory review, judged from each one's published pages and the issues filed against it. No host is run.

--preview preview.html also writes a page that renders each view in your browser, sandboxed, the way a host frames it — so you see the blank screen before a user does. It works against http://localhost too, for a server you are building.

The same check is a web page, /apps?url=, with the preview built in, and an MCP tool, mcp_liveness_check_apps on https://agentwares-mcp-liveness.vercel.app/mcp.

What it checks, in the order a host meets it

  1. The session. It opens as a dual-era host (server/discover at 2026-07-28, then initialize, through the same handshake every agentwares client uses) and declares the MCP Apps extension, io.modelcontextprotocol/ui with text/html;profile=mcp-app: SEP-1865 says servers SHOULD check that before registering UI tools, so a client that does not declare it may see text-only tools. A 401 stops here: check the sign-in with mcp-oauth-doctor.
  2. The link. tools/list: each tool's _meta.ui.resourceUri (the standard key), the deprecated flat _meta["ui/resourceUri"], or ChatGPT's _meta["openai/outputTemplate"] alias, which Claude and other hosts do not read. URIs must start with ui://; visibility must leave a tool the model can call.
  3. The view. resources/read for each linked URI (a host fetches it that way; it need not be in resources/list): it answers, the MIME type is exactly text/html;profile=mcp-app (not text/html, not the Apps SDK's old text/html+skybridge), and there is HTML in text or blob.
  4. What the HTML loads. Scripts, styles, images, fonts and frames from an origin _meta.ui.csp does not declare are refused by the host's CSP ("Refused to load the script"); relative URLs resolve to the host's sandbox, not your server. Both are the usual blank screen.
  5. The bridge. The view must send ui/initialize (the ext-apps SDK's app.connect()): Claude shows the frame only after that handshake. A view that reads only window.openai renders in ChatGPT alone.
  6. ui.domain, per host. Claude accepts exactly {hash}.claudemcpcontent.com, the SHA-256 of the connector URL as entered, and refuses anything else ("Invalid ui.domain format", "ui.domain mismatch"); the doctor computes the value for your URL. ChatGPT's review requires an https origin of your own. One fixed value cannot satisfy both.
  7. CORS, only when a view calls your server's own origin directly: one preflight from the view's sandbox origin.
  8. ChatGPT's directory review, from what its tool scan imports: explicit readOnlyHint, destructiveHint and openWorldHint on every tool (annotations_required), descriptions, a public https endpoint that is not a tunnel, the /.well-known/openai-apps-challenge file (domain_verification_required), frame domains to explain, screenshots or none.

Host bugs that blank a correct view are listed when they could apply — Claude Desktop dropping structuredContent from tool results (ext-apps#696), claude.ai ignoring resourceDomains (ext-apps#761) — labelled observed in, with the date the issue was opened.

Options

--json            the full report as JSON (schema mcp-apps-doctor/1), with `next` and `also`
--host <id>       judge for one host only: spec, claude, chatgpt, chatgpt-directory
--preview <file>  also write an HTML page that renders each view, sandboxed

Exit code 1 when the view renders in no host, there is no UI, or nothing could be read (a sign-in, no answer); 0 when it renders. With --host, 1 only when it is blank for that host. 2 for a usage error. Every error has a code, cause, fix and retryable.

The preview

The page frames each view in <iframe sandbox="allow-scripts"> — an opaque origin, so the view cannot read the page around it, its cookies or storage, open pop-ups, submit forms or navigate — under the CSP SEP-1865 has a host build from _meta.ui.csp. The page plays the host side: it answers ui/initialize, sends ui/notifications/tool-input with empty arguments, follows ui/notifications/size-changed, and refuses every other request. It calls no tool, so no tool result arrives unless you paste one into the box under the frame. It tells you whether the view connected and the height it asked for: no handshake after five seconds, or 0 px, is the invisible app.

A recorded run

Recorded with pnpm --filter mcp-apps-doctor record (scripts/record.mjs): our own two servers, live, then two synthetic broken servers served on 127.0.0.1 for the recording, labelled as such. Our servers have no UI, and the run shows what OpenAI's review would flag on them.

## Our own server, live (2026-10-09)

$ npx --allow-git=root github:agentwares/mcp-apps-doctor https://agentwares-mcp-liveness.vercel.app/mcp
mcp-apps-doctor 0.1.0
https://agentwares-mcp-liveness.vercel.app/mcp · 2026-10-09 05:03 UTC · 1.2 s
Discovery only: no credential sent, no tool called. Declared as an MCP Apps host.

It answers and lists 4 tools, but no tool links a UI and no ui:// resource is declared: hosts
show every tool as text. For ChatGPT's directory review, 1 to fix: tool-annotations.

Checks, in the order a host meets them
  ok    Opens a session as an MCP Apps host                   server/discover at 2026-07-28, mcp-liveness 0.3.0; declared io.modelcontextprotocol/ui.
  ok    Lists its tools                                       4 tools, 0 linking a UI.
  ok    A public, stable https endpoint                       https://agentwares-mcp-liveness.vercel.app; note the origin cannot change after publishing.
  ok    Every tool has a description                          4 tools.
  FAIL  Every tool sets readOnlyHint, destructiveHint and o…  4 of 4 tools leave a hint unset: `mcp_liveness_check` (destructiveHint); `mcp_liveness_explain_outcomes` (destructi…
  info  Serves the domain-verification file                   https://agentwares-mcp-liveness.vercel.app/.well-known/openai-apps-challenge → 404. Before Verify Domain, host the …
  info  Screenshots at submission                             No tool links a UI template, so attach no screenshots (screenshots_not_allowed).

First broken step: Every tool sets readOnlyHint, destructiveHint and openWorldHint
  whose: the server; breaks it for chatgpt-directory
  what:  4 of 4 tools leave a hint unset: `mcp_liveness_check` (destructiveHint);
         `mcp_liveness_explain_outcomes` (destructiveHint); `mcp_liveness_drift`
         (destructiveHint); `mcp_liveness_check_auth` (destructiveHint). OpenAI's submission
         refuses this as annotations_required.
  fix:   Set all three to explicit true/false in each tool's annotations, by what the tool does
         (read-only, irreversible, open-world), then rescan in the portal.
  source: OpenAI plugin submission errors, read 2026-10-08: https://developers.openai.com/plugins/deploy/submission-errors
  about "annotations_required": https://agentwares-mcp-liveness.vercel.app/apps/annotations-required?ref=mcp-apps-doctor

Hosts (judged from each one's published pages and the issues filed against it; no host was run)
  ChatGPT directory review  BLOCKED   Every tool sets readOnlyHint, destructiveHint and openWorldHint

Re-check this server every hour and email me when it breaks: agentcheck's free watch, no account —
  it emails when the server stops answering or its tool list changes (it does not re-read the views).
  https://agentwares-agentcheck.vercel.app/watch?target=https%3A%2F%2Fagentwares-mcp-liveness.vercel.app%2Fmcp&ref=mcp-apps-doctor
Nightly, with history: mcpcheck Server Pro diffs the server's tool catalog every night — removed
  tools, tightened schemas, changed descriptions — with the client-compat matrix, OAuth conformance
  and 90 days of history; $49 a server a month, first run free. It does not re-run these MCP Apps
  checks. https://agentwares-agentcheck.vercel.app/mcpcheck?ref=mcp-apps-doctor
(exit 1)

## Our own server, live (2026-10-09)

$ npx --allow-git=root github:agentwares/mcp-apps-doctor https://agentwares-agentcheck.vercel.app/api/mcp
mcp-apps-doctor 0.1.0
https://agentwares-agentcheck.vercel.app/api/mcp · 2026-10-09 05:03 UTC · 0.8 s
Discovery only: no credential sent, no tool called. Declared as an MCP Apps host.

It answers and lists 10 tools, but no tool links a UI and no ui:// resource is declared: hosts
show every tool as text. For ChatGPT's directory review, 1 to fix: tool-annotations.

Checks, in the order a host meets them
  ok    Opens a session as an MCP Apps host                   server/discover at 2026-07-28, agentcheck 0.1.1; declared io.modelcontextprotocol/ui.
  ok    Lists its tools                                       10 tools, 0 linking a UI.
  ok    A public, stable https endpoint                       https://agentwares-agentcheck.vercel.app; note the origin cannot change after publishing.
  ok    Every tool has a description                          10 tools.
  FAIL  Every tool sets readOnlyHint, destructiveHint and o…  10 of 10 tools leave a hint unset: `agentcheck_get_status` (destructiveHint); `agentcheck_get_pricing` (destructive…
  info  Serves the domain-verification file                   https://agentwares-agentcheck.vercel.app/.well-known/openai-apps-challenge → 404. Before Verify Domain, host the to…
  info  Screenshots at submission                             No tool links a UI template, so attach no screenshots (screenshots_not_allowed).

First broken step: Every tool sets readOnlyHint, destructiveHint and openWorldHint
  whose: the server; breaks it for chatgpt-directory
  what:  10 of 10 tools leave a hint unset: `agentcheck_get_status` (destructiveHint);
         `agentcheck_get_pricing` (destructiveHint); `agentcheck_model_retirements`
         (destructiveHint); `agentcheck_api_sunsets` (destructiveHint);
         `agentcheck_create_target` (destructiveHint); …. OpenAI's submission refuses this as
         annotations_required.
  fix:   Set all three to explicit true/false in each tool's annotations, by what the tool does
         (read-only, irreversible, open-world), then rescan in the portal.
  source: OpenAI plugin submission errors, read 2026-10-08: https://developers.openai.com/plugins/deploy/submission-errors
  about "annotations_required": https://agentwares-mcp-liveness.vercel.app/apps/annotations-required?ref=mcp-apps-doctor

Hosts (judged from each one's published pages and the issues filed against it; no host was run)
  ChatGPT directory review  BLOCKED   Every tool sets readOnlyHint, destructiveHint and openWorldHint

Re-check this server every hour and email me when it breaks: agentcheck's free watch, no account —
  it emails when the server stops answering or its tool list changes (it does not re-read the views).
  https://agentwares-agentcheck.vercel.app/watch?target=https%3A%2F%2Fagentwares-agentcheck.vercel.app%2Fapi%2Fmcp&ref=mcp-apps-doctor
Nightly, with history: mcpcheck Server Pro diffs the server's tool catalog every night — removed
  tools, tightened schemas, changed descriptions — with the client-compat matrix, OAuth conformance
  and 90 days of history; $49 a server a month, first run free. It does not re-run these MCP Apps
  checks. https://agentwares-agentcheck.vercel.app/mcpcheck?ref=mcp-apps-doctor
(exit 1)

## SYNTHETIC broken server ("not-found": the tool links a ui:// URI the server does not serve), served on 127.0.0.1 for this recording — not anyone's real server

$ npx --allow-git=root github:agentwares/mcp-apps-doctor http://127.0.0.1:61295/mcp
mcp-apps-doctor 0.1.0
http://127.0.0.1:61295/mcp · 2026-10-09 05:03 UTC · 0.0 s
Discovery only: no credential sent, no tool called. Declared as an MCP Apps host.

The view renders in no host. First broken step: resources/read returns the view
(ui://board/view.html). For ChatGPT's directory review, 2 to fix: resource-domain-chatgpt,
endpoint-public.

Checks, in the order a host meets them
  ok    Opens a session as an MCP Apps host                   server/discover at 2026-07-28, synthetic-not-found 1.0.0; declared io.modelcontextprotocol/ui.
  ok    Lists its tools                                       2 tools, 1 linking a UI.
  ok    Declares io.modelcontextprotocol/ui                   In its capabilities.extensions.
  ui://board/view.html
    FAIL  resources/read returns the view                     resources/read ui://board/view.html (linked by `show_board`) failed: JSON-RPC error -32602: Resource not found: ui:…
  ui://board/view-v2.html
    ok    resources/read returns the view                     ui://board/view-v2.html (no tool links it).
    ok    MIME type is text/html;profile=mcp-app              As the spec requires.
    ok    Declares every origin it loads from                 Every external origin it loads is in _meta.ui.csp.
    ok    Connects to the host                                It sends ui/initialize.
    ok    ui.domain suits Claude                              No ui.domain: Claude serves the view from a per-conversation sandbox origin.
    warn  ui.domain is set for ChatGPT's review               No ui.domain (or openai/widgetDomain) is served to this client. OpenAI's reference makes it required when submittin…
  FAIL  A public, stable https endpoint                       127.0.0.1 is a local address; OpenAI reviews only a public https endpoint.
  ok    Every tool has a description                          2 tools.
  ok    Every tool sets readOnlyHint, destructiveHint and o…  All three on every tool.
  info  Screenshots at submission                             The scan will report a UI template, so screenshots are allowed: one PNG or JPEG per starter prompt, exactly 706 px …

First broken step: resources/read returns the view (ui://board/view.html)
  whose: the server; breaks it for spec, claude, chatgpt
  what:  resources/read ui://board/view.html (linked by `show_board`) failed: JSON-RPC error
         -32602: Resource not found: ui://board/view.html. A host fetches the view with
         resources/read and shows nothing when it fails.
  fix:   Register a resource at exactly ui://board/view.html (same string as the tool's
         _meta.ui.resourceUri) and answer resources/read for it. It need not appear in
         resources/list.
  source: MCP Apps spec 2026-01-26, Resource Discovery, read 2026-10-08: https://github.com/modelcontextprotocol/ext-apps/blob/main/specification/2026-01-26/apps.mdx#resource-discovery
  about "Resource not found: ui://": https://agentwares-mcp-liveness.vercel.app/apps/resource-not-found-ui?ref=mcp-apps-doctor

Also worth fixing
  - ui.domain is set for ChatGPT's review [ui://board/view-v2.html]: Serve ChatGPT _meta.ui.domain = an https origin of your own, unique to this app, on the
    content item — and not to Claude, which refuses that format.

Hosts (judged from each one's published pages and the issues filed against it; no host was run)
  MCP Apps hosts (SEP-1865)    BLANK     resources/read returns the view (ui://board/view.html)
  Claude (claude.ai, Desktop)  BLANK     resources/read returns the view (ui://board/view.html)
  ChatGPT                      BLANK     resources/read returns the view (ui://board/view.html)
  ChatGPT directory review     BLOCKED   A public, stable https endpoint

If it still renders blank in one host: known host bugs (observed)
  - Observed: Claude Desktop delivered ui/notifications/tool-result without structuredContent,
    so a view that reads only structuredContent renders nothing. Read `content` as a fallback.
    observed in modelcontextprotocol/ext-apps#696, opened 2026-07-07: https://github.com/modelcontextprotocol/ext-apps/issues/696

Once it is deployed, re-check it every hour and email me when it breaks: agentcheck's free watch, no
  account — it emails when the server stops answering or its tool list changes (it does not re-read
  the views). https://agentwares-agentcheck.vercel.app/watch?ref=mcp-apps-doctor
Nightly, with history: mcpcheck Server Pro diffs the server's tool catalog every night — removed
  tools, tightened schemas, changed descriptions — with the client-compat matrix, OAuth conformance
  and 90 days of history; $49 a server a month, first run free. It does not re-run these MCP Apps
  checks. https://agentwares-agentcheck.vercel.app/mcpcheck?ref=mcp-apps-doctor
(exit 1)

## SYNTHETIC broken server ("skybridge": an Apps SDK app from before MCP Apps, built for ChatGPT only), served on 127.0.0.1 for this recording — not anyone's real server

$ npx --allow-git=root github:agentwares/mcp-apps-doctor http://127.0.0.1:61295/mcp
mcp-apps-doctor 0.1.0
http://127.0.0.1:61295/mcp · 2026-10-09 05:03 UTC · 0.0 s
Discovery only: no credential sent, no tool called. Declared as an MCP Apps host.

It renders, but not everywhere: blank or refused in MCP Apps hosts (SEP-1865), Claude
(claude.ai, Desktop). For ChatGPT's directory review, 1 to fix: endpoint-public.

Checks, in the order a host meets them
  ok    Opens a session as an MCP Apps host                   server/discover at 2026-07-28, synthetic-skybridge 1.0.0; declared io.modelcontextprotocol/ui.
  ok    Lists its tools                                       2 tools, 1 linking a UI.
  ok    Declares io.modelcontextprotocol/ui                   In its capabilities.extensions.
  FAIL  Links its UI by the standard key [show_board]         `show_board` links `ui://board/view.html` only by _meta["openai/outputTemplate"], ChatGPT's alias. Claude and other…
  ui://board/view.html
    ok    resources/read returns the view                     ui://board/view.html (linked by `show_board`).
    FAIL  MIME type is text/html;profile=mcp-app              It is text/html+skybridge, the Apps SDK's type before MCP Apps. Claude and other MCP Apps hosts render only text/ht…
    warn  MIME type is the one ChatGPT documents              ChatGPT's troubleshooting page asks for text/html;profile=mcp-app; whether it still renders text/html+skybridge is …
    FAIL  Declares every origin it loads from                 It loads from `https://cdn.example-assets.dev`, which _meta.ui.csp does not declare (resourceDomains). Hosts build …
    warn  Connects to the host                                It reads only window.openai, ChatGPT's compatibility bridge; Claude and other MCP Apps hosts talk ui/initialize ove…
    warn  Declares its CSP under _meta.ui.csp                 Its CSP is only under _meta["openai/widgetCSP"], ChatGPT's legacy key; Claude and other MCP Apps hosts read _meta.u…
    FAIL  ui.domain suits Claude                              ui.domain is "https://board.example.com". Claude accepts only {hash}.claudemcpcontent.com and refuses anything else…
    ok    ui.domain is set for ChatGPT's review               https://board.example.com.
  FAIL  A public, stable https endpoint                       127.0.0.1 is a local address; OpenAI reviews only a public https endpoint.
  ok    Every tool has a description                          2 tools.
  ok    Every tool sets readOnlyHint, destructiveHint and o…  All three on every tool.
  info  Screenshots at submission                             The scan will report a UI template, so screenshots are allowed: one PNG or JPEG per starter prompt, exactly 706 px …

First broken step: Links its UI by the standard key (show_board)
  whose: the server; breaks it for spec, claude
  what:  `show_board` links `ui://board/view.html` only by _meta["openai/outputTemplate"],
         ChatGPT's alias. Claude and other MCP Apps hosts read _meta.ui.resourceUri and show it
         as a tool with no UI.
  fix:   Set _meta.ui.resourceUri = "ui://board/view.html" on `show_board` (keep the alias if you
         like; ChatGPT reads both).
  source: OpenAI, Add UI to your MCP server, read 2026-10-08: https://developers.openai.com/plugins/build/chatgpt-ui
  about "Tool has no UI": https://agentwares-mcp-liveness.vercel.app/apps/tool-has-no-ui?ref=mcp-apps-doctor

Also worth fixing
  - MIME type is the one ChatGPT documents [ui://board/view.html]: Return mimeType "text/html;profile=mcp-app".
  - Connects to the host [ui://board/view.html]: Use the MCP Apps bridge (ext-apps App.connect(); tool results via ontoolresult) and keep
    window.openai only for ChatGPT-only extras, feature-detected.
  - Declares its CSP under _meta.ui.csp [ui://board/view.html]: Copy connect_domains → connectDomains, resource_domains → resourceDomains, frame_domains →
    frameDomains into _meta.ui.csp (keep redirect_domains under openai/widgetCSP; ChatGPT
    still needs it there).

Hosts (judged from each one's published pages and the issues filed against it; no host was run)
  MCP Apps hosts (SEP-1865)    BLANK     Links its UI by the standard key (show_board)
  Claude (claude.ai, Desktop)  BLANK     Links its UI by the standard key (show_board)
  ChatGPT                      at risk   MIME type is the one ChatGPT documents (ui://board/view.html)
  ChatGPT directory review     BLOCKED   A public, stable https endpoint

Once it is deployed, re-check it every hour and email me when it breaks: agentcheck's free watch, no
  account — it emails when the server stops answering or its tool list changes (it does not re-read
  the views). https://agentwares-agentcheck.vercel.app/watch?ref=mcp-apps-doctor
Nightly, with history: mcpcheck Server Pro diffs the server's tool catalog every night — removed
  tools, tightened schemas, changed descriptions — with the client-compat matrix, OAuth conformance
  and 90 days of history; $49 a server a month, first run free. It does not re-run these MCP Apps
  checks. https://agentwares-agentcheck.vercel.app/mcpcheck?ref=mcp-apps-doctor
(exit 0)

What it will not do

It never sends a credential and never calls a tool. It sends the handshake, tools/list, resources/list and resources/read (at most five pages of each list and eight views), and at most three requests for public documents on the same origin: the protected-resource metadata when a tool declares an oauth2 security scheme, OpenAI's domain-verification file, and one CORS preflight when a view calls the server's own origin. Every request has a ten-second timeout and the run a 45-second budget; nothing is retried. No telemetry: the CLI talks to your server and nothing else.

Error messages people paste

Each has a page with what it means, its three common causes and how to tell them apart:

Sources, read 8 October 2026

Observed (issues, dated by when they were opened): ext-apps#615 (16 Apr 2026), #671 (27 May), #696 (7 Jul), #761 (28 Aug); Doist/todoist-mcp#432 (2 Apr); laravel/mcp#218 (18 May); alpic-ai/skybridge#630 (30 Mar); openai/openai-apps-sdk-examples#225 (6 Jul); the OpenAI community thread on "Failed to fetch template" (16 Jun).

Keep checking

Its last lines offer agentcheck's free watch, which re-checks the server every hour and emails when it stops answering or its tool list changes (it does not re-read the views), and mcpcheck Server Pro, which diffs the tool catalog every night with 90 days of history ($49 a server a month). Neither re-runs these MCP Apps checks.

Library

npm install mcp-apps-doctor   # once npm serves it; until then, npx from GitHub as above
import { diagnose } from "mcp-apps-doctor";
const report = await diagnose("https://your-server.example/mcp");

The library is Web-standard (fetch, crypto.subtle), so it runs on Node 20+, Workers and Vercel Functions.

MIT © agentwares contributors.

from github.com/ubukhari/mcp-apps-doctor

Установка Apps Doctor

У этого сервера нет опубликованного пакета — он собирается из исходников. Открой репозиторий и следуй инструкции в README.

▸ github.com/ubukhari/mcp-apps-doctor

FAQ

Apps Doctor MCP бесплатный?

Да, Apps Doctor MCP бесплатный — установка в пару кликов через Unyly без оплаты.

Нужен ли API-ключ для Apps Doctor?

Нет, Apps Doctor работает без API-ключей и переменных окружения.

Apps Doctor — hosted или self-hosted?

Self-hosted: сервер запускается локально на твоей машине командой из раздела установки.

Как установить Apps Doctor в Claude Desktop, Claude Code или Cursor?

Открой Apps Doctor на unyly.org, выбери вкладку своего клиента (Claude Desktop, Claude Code, Cursor) и нажми Install — конфиг сгенерируется автоматически, без правки JSON.

Похожие MCP

Compare Apps Doctor with

Не уверен что выбрать?

Найди свой стек за 60 секунд

Автор?

Embed-бейдж для README

Похожее

Все в категории development