Skip to main content
Content Security Policy (CSP) controls which domains your views can fetch from, load scripts/styles from, and embed. Views run in sandboxed iframes, so CSP must explicitly allow any external resources.

Server and asset origins

Set MCP_URL to your server’s public origin (OAuth resource URL, API calls, CSP connectDomains):
Set MCP_ASSETS_URL when view JS/CSS and public/ files are served from a different prefix (CDN, Supabase Storage):
When MCP_ASSETS_URL is unset, assets use the same origin as MCP_URL (or the request origin behind a proxy). At mcp-use build, MCP_ASSETS_URL rewrites manifest paths to full https:// URLs for static upload workflows.

Separate the UI origin from the MCP endpoint

Set view.domain to the dedicated HTTPS origin you want ChatGPT to use, such as https://wavebyvento.com. The MCP endpoint is the URL clients connect to, such as https://wave-by-vento.run.mcp-use.com/mcp. These values serve different purposes.
Add the corresponding views/wave/view.tsx as described in MCP Apps. On resources/read, mcp-use emits host-specific _meta.ui.domain: Claude hashes the full endpoint, including /mcp, not the website origin or MCP_ASSETS_URL. This follows Claude’s domain handling contract. ChatGPT expects a dedicated origin; openai/widgetDomain is a compatibility alias for ui.domain, not a way to repair a conflicting value. See the OpenAI resource metadata reference.

Endpoint resolution and migration

  • An origin-only MCP_URL combines with the server’s basePath (default /mcp).
  • For View domain resolution, an MCP_URL with a path is treated as the full endpoint and hashed verbatim, including a trailing slash or query. With OAuth, keep MCP_URL origin-only: OAuth configuration separately requires an origin and appends basePath.
  • Without a valid MCP_URL, View reads use the request path and query with the forwarded origin, or the request origin when forwarded headers are absent. Configure MCP_URL when a proxy hides or rewrites the public path; only trust forwarded headers set by your proxy.
  • Older HTTP(S) view.domain values containing /mcp or another path are normalized to their origin. Set the intended UI origin explicitly when it differs from the endpoint origin.
  • Existing computed *.claudemcpcontent.com values remain unchanged for compatibility. They are Claude-specific and unsuitable for ChatGPT. Replace them with an HTTPS UI origin to use automatic host conversion.
  • An omitted view.domain keeps the host default. If no HTTP request or MCP_URL is available, Claude falls back to hashing the authored domain; configure the public endpoint for that case.
The SDK identifies Claude by its advertised client name, with a User-Agent fallback when no client name is available. Unknown clients receive the UI origin. Domain normalization is not submission validation: use an HTTPS origin for ChatGPT and verify resource reads in each target host before submitting.

Preserve generated resource metadata

Remove custom response helpers that overwrite _meta.ui.domain after next(). The SDK applies Claude’s conversion before response middleware receives the result; a later overwrite replaces the generated value. Keep unrelated additions and preserve existing ui fields when merging metadata. Configure the domain through view.domain. Tool definition _meta and tool result _meta do not configure the View resource domain. Generated View resources emit ui.domain without an openai/widgetDomain alias. Manually registered resources and custom middleware remain author-controlled; if you emit both keys for ChatGPT, keep them consistent. Resource listings show the UI origin; Claude conversion happens on reads. view.csp.frameDomains separately allows nested iframes inside the View. It does not select the View’s sandbox origin, identify the MCP endpoint, or fix domain validation. Declare it only when the View embeds another page. ChatGPT applies additional review to nested frames.

CSP merge order

On each resources/read, the framework merges CSP in this order (high → low priority):
  1. Author view.csp on the bound tool
  2. CSP_*_DOMAINS env vars (per category) or the CSP_URLS shortcut
  3. MCP auto-append: MCP_URL → connectDomains; assets origin → resourceDomains
CSP_URLS and per-category env vars rank above MCP auto-append. Duplicate origins keep the higher-priority entry’s position.

Add domains for one view

Declare CSP on the tool’s view: config:
MCP Apps CSP fields: connectDomains, resourceDomains, frameDomains, baseUriDomains.

Global CSP env vars

Use CSP_URLS when every view needs the same extra domains (shortcut for all four categories):
Override one category without affecting others:

Static deployments

When assets live on static storage and the MCP server runs elsewhere:

Verify CSP

The mcp-use Inspector provides a CSP Mode Toggle for testing:
  • Permissive: Relaxed CSP for debugging
  • Widget-Declared: Enforces the view’s declared CSP (production-like)
CSP violations are logged in the console. Use Widget-Declared mode to catch CSP issues before production deployment.

Next Steps