Follow Discord
Sweep 25 Sep 2026 · 19:33Z Build v2.1.283 504 read Stable v2.1.274 Latest v2.1.283 Next v2.1.283 Feeds RSS JSON llms.txt llms-full.txt Unofficial
One change · claude-docs

Troubleshoot MCP Apps changedconnectors/building/mcp-apps/troubleshooting

Nearest release: v2.1.283, published under an hour after upstream edited the page. Shown because the two are within 24 hours of each other. Nothing here says the release caused the edit.

Upstream edited this page at 25 Sep 2026 18:00 UTC, give or take a minute or two: the time comes from Anthropic’s own sitemap rather than from a commit. This site recorded the change at 25 Sep 2026 18:07 UTC.

Upstream edited
Recorded here
Lines+55added
Lines−31removed
From line 1 where the diff opens
First seen 14 Aug 2026 this site's first read of the page
Recorded edits2to this page, all time

# Troubleshoot MCP Apps ## Open developer tools ### Claude Desktop ## Fix common problems ### Tool call appears but the app is invisible #### Missing `app.connect()` call #### Iframe has zero height ### App doesn't render when tool results are large ### Assets or API requests fail only on iOS ### `ui.domain` validation fails ## Next steps # Troubleshooting MCP Apps ## Using developer tools ### Desktop ## Problem: Tool call appears but the app is invisible ### Missing `app.connect()` call ### Iframe has zero height ## Problem: App doesn't render when tool results are large ## Problem: Assets or API requests fail only on iOS ## Problem: ui.domain validation fails

The whole hunk

from line 1, old and new numbered
/
lines
from line 1
1# Troubleshooting MCP Apps
1# Troubleshoot MCP Apps
22 
3> Debug and resolve common issues with MCP Apps
3> Debug MCP Apps in Claude with developer tools on desktop and iOS, and fix invisible apps, large tool results, iOS-only request failures, and ui.domain errors.
44 
5## Using developer tools
5When an MCP App doesn't render or load correctly in Claude, the tool call usually still appears in the conversation, and the cause is in how the app connects, sizes itself, receives its data, or loads its assets. This page is for developers debugging their own MCP App. [Open the developer tools](#open-developer-tools) in Claude Desktop or on iOS to inspect the app's iframe, then match what you see against the [common problems](#fix-common-problems).
66 
7### Desktop
7## Open developer tools
88 
9Claude Desktop and the Claude iOS app both let you inspect a running MCP App with browser developer tools.
10 
11### Claude Desktop
12 
913Claude Desktop's Developer Tools can help you debug MCP Apps. To use them:
1014 
111. Open **Help > Troubleshooting** and click **Enable Developer Mode**. A new **Developer** menu appears in the menu bar.
122. Open Developer Tools by pressing `Cmd+Option+I` (Mac) or `Ctrl+Shift+I` (Windows)
133. Inspect the tool call element and look for an iframe nested inside another iframe. Your app will be loaded as the content of the inner iframe.
15<Steps>
16 <Step title="Enable Developer Mode">
17 Open **Help > Troubleshooting** and click **Enable Developer Mode**. A new **Developer** menu appears in the menu bar.
18 </Step>
1419 
20 <Step title="Open Developer Tools">
21 Open Developer Tools by pressing `Cmd+Option+I` on Mac or `Ctrl+Shift+I` on Windows.
22 </Step>
23 
24 <Step title="Find your app's iframe">
25 Inspect the tool call element and look for an iframe nested inside another iframe. Your app is loaded as the content of the inner iframe.
26 </Step>
27</Steps>
28 
1529<Tip>From the **Developer** menu, select **Reload MCP Configuration** after editing your `claude_desktop_config.json` to apply changes without restarting.</Tip>
1630 
1731### iOS
1832 
19On iOS, the Claude app renders your MCP app inside a `WKWebView`. You can inspect it from a connected Mac using Safari's Web Inspector—see Apple's guide to [inspecting iOS](https://developer.apple.com/documentation/safari-developer-tools/inspecting-ios) for setup. Once connected, the Claude web view appears under your device in Safari's **Develop** menu, and you can use the console, network panel, and element inspector just as you would on desktop.
33On iOS, the Claude app renders your MCP App inside a `WKWebView`. You can inspect it from a connected Mac using Safari's Web Inspector. Follow Apple's guide to [inspecting iOS](https://developer.apple.com/documentation/safari-developer-tools/inspecting-ios) for setup. Once connected, the Claude web view appears under your device in Safari's **Develop** menu, and you can use the console, network panel, and element inspector as you would on desktop.
2034 
21## Problem: Tool call appears but the app is invisible
35## Fix common problems
2236 
23This is the most common issue when developing MCP Apps. Check these two causes:
37These are the problems developers hit most often when an MCP App doesn't render or load correctly in Claude, each with its cause and fix.
2438 
25### Missing `app.connect()` call
39### Tool call appears but the app is invisible
2640 
27Your app must call [`app.connect()`](https://modelcontextprotocol.github.io/ext-apps/api/classes/app.App.html#connect) (Vanilla JS) or [`useApp()`](https://modelcontextprotocol.github.io/ext-apps/api/functions/_modelcontextprotocol_ext-apps_react.useApp.html) (React) to establish communication with Claude Desktop.
41An invisible app under a visible tool call is the most common issue when developing MCP Apps. The cause is usually a missing `app.connect()` call or an iframe with zero height.
2842 
43#### Missing `app.connect()` call
44 
45Your app must call [`app.connect()`](https://modelcontextprotocol.github.io/ext-apps/api/classes/app.App.html#connect) in vanilla JS or [`useApp()`](https://modelcontextprotocol.github.io/ext-apps/api/functions/_modelcontextprotocol_ext-apps_react.useApp.html) in React to establish communication with Claude Desktop. Register your handlers before connecting:
46 
2947<CodeGroup>
3048 ```javascript Vanilla JS theme={null}
3149 import { App } from "@modelcontextprotocol/ext-apps";
from line 76
5876 ```
5977</CodeGroup>
6078 
61<Warning>Event handlers like `app.ontoolinput` and `app.ontoolresult` won't be invoked until the app is connected.</Warning>
79<Warning>Event handlers like `app.ontoolinput` and `app.ontoolresult` aren't invoked until the app is connected.</Warning>
6280 
63### Iframe has zero height
81#### Iframe has zero height
6482 
6583Your app needs a non-zero height to be visible. A zero height can occur if:
6684 
from line 87
6987 
7088Check that your root element has explicit dimensions or content that gives it height.
7189 
72## Problem: App doesn't render when tool results are large
90### App doesn't render when tool results are large
7391 
74When a tool result exceeds approximately 150,000 characters and Claude's code execution sandbox is active, the result is written to the sandbox filesystem instead of being passed inline to the conversation. Your app receives a pointer to the stored file rather than the structured content it needs, so it never hydrates.
92When a tool result exceeds approximately 150,000 characters and Claude's code execution sandbox is active, Claude writes the result to the sandbox filesystem instead of passing it inline to the conversation. Your app receives a pointer to the stored file rather than the structured content it needs, so it never hydrates.
7593 
76<Note>This \~150,000-character threshold is specific to Claude.ai and Claude Desktop. Claude Code uses a separate 25,000-token default limit configurable via `MAX_MCP_OUTPUT_TOKENS`.</Note>
94<Note>This \~150,000-character threshold is specific to claude.ai and Claude Desktop. Claude Code uses a separate 25,000-token default limit, configurable through `MAX_MCP_OUTPUT_TOKENS`.</Note>
7795 
78To avoid this, keep initial tool result payloads lean:
96To stay under the threshold, keep initial tool result payloads lean:
7997 
80* **Paginate large results.** Return a summary or the first page of data, and let the user request more through follow-up interactions.
81* **Fetch details on demand.** Use app-initiated tool calls to load additional data from within your widget as the user explores, rather than returning everything upfront.
82* **Defer heavy content.** If your data includes large blobs—full document text, base64-encoded images, extensive logs—return identifiers or previews in the initial result and provide a separate tool to retrieve the full content when needed.
98* **Paginate large results**: return a summary or the first page of data, and let the user request more through follow-up interactions
99* **Fetch details on demand**: use app-initiated tool calls to load additional data from within your widget as the user explores, rather than returning everything upfront
100* **Defer heavy content**: if your data includes large blobs such as full document text, base64-encoded images, or extensive logs, return identifiers or previews in the initial result and provide a separate tool to retrieve the full content when needed
83101 
84## Problem: Assets or API requests fail only on iOS
102### Assets or API requests fail only on iOS
85103 
86104If your app loads on desktop and web but fails to fetch scripts, images, or API data on iOS, check whether your server, CDN, or WAF is gating access on the `Referer` header.
87105 
88WebKit on iOS—both Safari and in the Claude iOS app—omits the `Referer` header on cross-origin subresource requests as part of its tracking prevention (WebKit bugs [206521](https://bugs.webkit.org/show_bug.cgi?id=206521) and [179053](https://bugs.webkit.org/show_bug.cgi?id=179053#c8)). A server that requires a `Referer` to allow the request will reject iOS traffic even though the same app works elsewhere.
106WebKit on iOS, in both Safari and the Claude iOS app, omits the `Referer` header on cross-origin subresource requests as part of its tracking prevention, per WebKit bugs [206521](https://bugs.webkit.org/show_bug.cgi?id=206521) and [179053](https://bugs.webkit.org/show_bug.cgi?id=179053#c8). A server that requires a `Referer` to allow the request rejects iOS traffic even though the same app works elsewhere.
89107 
90**Fix:** Allowlist on the `Origin` header instead, which WebKit does send. Requests from your app carry an `Origin` of `{hash}.claudemcpcontent.com`—see [Domain handling](/docs/connectors/building/mcp-apps/cross-compatibility#domain-handling) to compute the hash for your server URL. Configure your infrastructure to allow requests whose `Origin` matches `*.claudemcpcontent.com` and return a corresponding `Access-Control-Allow-Origin` header.
108To fix the iOS failures, allowlist on the `Origin` header instead of `Referer`, because WebKit does send `Origin`. Requests from your app carry an `Origin` of `{hash}.claudemcpcontent.com`, and [Set `ui.domain` for Claude](/docs/connectors/building/mcp-apps/getting-started#set-ui-domain-for-claude) shows how to compute the hash for your server URL. Configure your infrastructure to allow requests whose `Origin` matches `*.claudemcpcontent.com` and return a corresponding `Access-Control-Allow-Origin` header.
91109 
92<Note>This applies to requests your app makes directly from the user's device—loading bundles, images, or calling your own API from client-side code. MCP tool calls are proxied through Claude's backend and egress from Anthropic's published IP ranges, not the user's device.</Note>
110<Note>The missing `Referer` header affects requests your app makes directly from the user's device, such as loading bundles and images or calling your own API from client-side code. MCP tool calls are proxied through Claude's backend and egress from Anthropic's published IP ranges, not the user's device.</Note>
93111 
94## Problem: ui.domain validation fails
112### `ui.domain` validation fails
95113 
96Setting [`_meta.ui.domain`](https://modelcontextprotocol.github.io/ext-apps/api/interfaces/app.McpUiResourceMeta.html#domain) on your resource opts your app into a stable sandbox origin, which you need if your app runs its own OAuth flow. Claude validates the value against your connector URL and shows an `Invalid ui.domain format` or `ui.domain mismatch` error instead of rendering the app when validation fails.
114Setting [`_meta.ui.domain`](https://modelcontextprotocol.github.io/ext-apps/api/interfaces/app.McpUiResourceMeta.html#domain) on your resource opts your app into a stable sandbox origin, which you need if your app runs its own OAuth flow. Claude validates the value against your connector URL, and when validation fails it shows an `Invalid ui.domain format` or `ui.domain mismatch` error instead of rendering the app.
97115 
98116The value must be exactly `{hash}.claudemcpcontent.com`, where `{hash}` is the first 32 hexadecimal characters of the SHA-256 digest of your full connector URL. Compute it by running this command with your own URL:
99117 
from line 119
101119node -e 'const yourServerUrl = "https://example.com/mcp"; console.log(require("crypto").createHash("sha256").update(yourServerUrl).digest("hex").slice(0,32) + ".claudemcpcontent.com")'
102120```
103121 
104Common causes of a mismatch:
122A mismatch usually has one of these causes:
105123 
106* **The URL you hashed differs from the URL Claude connects to.** The hash covers the full URL string including scheme, path, and any trailing slash, so `https://example.com/mcp` and `https://example.com/mcp/` produce different values. Hash the exact URL configured in **Customize > Connectors**.
107* **The connector is local (stdio).** Local connectors have no URL to hash, so `ui.domain` is not available for them. Remove the field, or deploy the server as a remote connector to use a stable origin.
124* **The URL you hashed differs from the URL Claude connects to**: the hash covers the full URL string including scheme, path, and any trailing slash, so `https://example.com/mcp` and `https://example.com/mcp/` produce different values. Hash the exact URL configured in **Customize > Connectors**
125* **The connector is a local stdio server**: local connectors have no URL to hash, so `ui.domain` isn't available for them. Remove the field, or deploy the server as a remote connector to use a stable origin
108126 
109See [Domain handling](/docs/connectors/building/mcp-apps/cross-compatibility#domain-handling) for how the origin is used across platforms.
127[Set `ui.domain` for Claude](/docs/connectors/building/mcp-apps/getting-started#set-ui-domain-for-claude) explains how the origin is used across platforms.
128 
129## Next steps
130 
131* [Set `ui.domain` for Claude](/docs/connectors/building/mcp-apps/getting-started#set-ui-domain-for-claude): compute the sandbox origin Claude expects for your app
132* [Design guidelines](/docs/connectors/building/mcp-apps/design-guidelines#mobile-guidelines): mobile layout, safe areas, and sizing rules that prevent clipped or invisible content
133* [Get started with MCP Apps](/docs/connectors/building/mcp-apps/getting-started#build-your-own-mcp-app): SDK quickstart, examples, and agent skills
110134 
Feedback