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

Automatic Configuration

When baseUrl is set (via MCPServer constructor or MCP_URL environment variable), mcp-use automatically configures CSP:
const server = new MCPServer({
  name: "my-server",
  version: "1.0.0",
  baseUrl: process.env.MCP_URL, // Required for production
});
This ensures:
  • Widget URLs use the correct domain
  • CSP includes your server domain
  • Works behind proxies and custom domains
The server origin is auto-injected into each widget’s connectDomains, resourceDomains, and baseUriDomains—you don’t need to add it manually.

Per-Widget Configuration

For widgets that need additional domains (APIs, CDNs, etc.), configure CSP in your widget metadata.

MCP Apps (all compatible clients, ChatGPT, Claude etc..)

With type: "mcpApps", use camelCase in metadata.csp:
export const widgetMetadata: WidgetMetadata = {
  description: "Display weather",
  props: propSchema,
  metadata: {
    csp: {
      connectDomains: ["https://api.weather.com"],
      resourceDomains: ["https://cdn.weather.com"],
      baseUriDomains: ["https://myserver.com"],
      frameDomains: ["https://trusted-embed.com"],
      redirectDomains: ["https://oauth.provider.com"],
    },
  },
};

Apps SDK Format (ChatGPT only - DEPRECATED)

With type: "appsSdk", use snake_case in appsSdkMetadata["openai/widgetCSP"]:
export const appsSdkMetadata = {
  "openai/widgetCSP": {
    connect_domains: ["https://api.weather.com"],
    resource_domains: ["https://cdn.weather.com"],
    frame_domains: ["https://trusted-embed.com"],
    redirect_domains: ["https://oauth.provider.com"],
  },
};

Field Reference

MCP Apps (camelCase)Apps SDK (snake_case)Description
connectDomainsconnect_domainsDomains for fetch, XHR, WebSocket
resourceDomainsresource_domainsDomains for scripts, styles, images
baseUriDomainsbase_uri_domainsDomains for base URI (MCP Apps)
frameDomainsframe_domainsDomains for iframe embeds
redirectDomainsredirect_domainsDomains for redirects (ChatGPT-specific)
scriptDirectivesscript_directivesCustom script CSP directives, not all clients support this (e.g. ChatGPT)
styleDirectivesstyle_directivesCustom style CSP directives
Your CSP domains are merged with your server’s base URL automatically. For ChatGPT, OpenAI’s required domains (*.oaistatic.com, etc.) are also added. For MCP Apps clients, only the domains you declare are used.

Environment Variables

# Base URL — auto-included in widget CSP
MCP_URL=https://myserver.com

# Additional domains (comma-separated) — appended to widget CSP
CSP_URLS=https://api.example.com,https://cdn.example.com
  • MCP_URL: Base URL for widget assets and public files. Also used by the server to configure CSP.
  • CSP_URLS: (Optional) Additional domains to whitelist. Supports comma-separated list. Required for static deployments where widget assets are served from different domains.

Static Deployments

When widgets are served from static storage (e.g., Supabase Storage) while the MCP server runs elsewhere, set:
  • MCP_URL: Where widget assets are stored
  • MCP_SERVER_URL: Where the MCP server runs (for API calls)
  • CSP_URLS: Domains for storage and API access (e.g., https://YOUR_PROJECT.supabase.co)
See Supabase deployment for a complete setup.
Alternative: Instead of the global CSP_URLS environment variable, configure CSP per-widget in metadata.csp

Inspector Debugging

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

Next Steps