Improve documentation for CSP and permissions types

Add detailed JSDoc comments to `McpUiResourceCsp`, `McpUiResourcePermissions`,
and `McpUiResourceMeta` interfaces:

- Document CSP directive mappings for `connectDomains`, `resourceDomains`,
  `frameDomains`, and `baseUriDomains`
- Add usage examples showing typical domain patterns
- Clarify Permission Policy mappings for `camera`, `microphone`, `geolocation`,
  and `clipboardWrite`
- Explain `domain` field's host-dependent behavior with concrete examples
- Document `prefersBorder` semantics including true/false/omitted behavior

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Jonathan Hefner 2026-01-30 11:30:44 -06:00
commit c02eb4d006
No known key found for this signature in database
GPG key ID: 0DA40AFD21043691
3 changed files with 293 additions and 82 deletions

View file

@ -134,25 +134,25 @@
"type": "object", "type": "object",
"properties": { "properties": {
"camera": { "camera": {
"description": "Request camera access (Permission Policy `camera` feature).", "description": "Request camera access.\n\nMaps to Permission Policy `camera` feature.",
"type": "object", "type": "object",
"properties": {}, "properties": {},
"additionalProperties": false "additionalProperties": false
}, },
"microphone": { "microphone": {
"description": "Request microphone access (Permission Policy `microphone` feature).", "description": "Request microphone access.\n\nMaps to Permission Policy `microphone` feature.",
"type": "object", "type": "object",
"properties": {}, "properties": {},
"additionalProperties": false "additionalProperties": false
}, },
"geolocation": { "geolocation": {
"description": "Request geolocation access (Permission Policy `geolocation` feature).", "description": "Request geolocation access.\n\nMaps to Permission Policy `geolocation` feature.",
"type": "object", "type": "object",
"properties": {}, "properties": {},
"additionalProperties": false "additionalProperties": false
}, },
"clipboardWrite": { "clipboardWrite": {
"description": "Request clipboard write access (Permission Policy `clipboard-write` feature).", "description": "Request clipboard write access.\n\nMaps to Permission Policy `clipboard-write` feature.",
"type": "object", "type": "object",
"properties": {}, "properties": {},
"additionalProperties": false "additionalProperties": false
@ -165,28 +165,28 @@
"type": "object", "type": "object",
"properties": { "properties": {
"connectDomains": { "connectDomains": {
"description": "Origins for network requests (fetch/XHR/WebSocket).", "description": "Origins for network requests (fetch/XHR/WebSocket).\n\n- Maps to CSP `connect-src` directive\n- Empty or omitted → no external connections (secure default)",
"type": "array", "type": "array",
"items": { "items": {
"type": "string" "type": "string"
} }
}, },
"resourceDomains": { "resourceDomains": {
"description": "Origins for static resources (scripts, images, styles, fonts).", "description": "Origins for static resources (images, scripts, stylesheets, fonts, media).\n\n- Maps to CSP `img-src`, `script-src`, `style-src`, `font-src`, `media-src` directives\n- Wildcard subdomains supported: `https://*.example.com`\n- Empty or omitted → no external resources (secure default)",
"type": "array", "type": "array",
"items": { "items": {
"type": "string" "type": "string"
} }
}, },
"frameDomains": { "frameDomains": {
"description": "Origins for nested iframes (frame-src directive).", "description": "Origins for nested iframes.\n\n- Maps to CSP `frame-src` directive\n- Empty or omitted → no nested iframes allowed (`frame-src 'none'`)",
"type": "array", "type": "array",
"items": { "items": {
"type": "string" "type": "string"
} }
}, },
"baseUriDomains": { "baseUriDomains": {
"description": "Allowed base URIs for the document (base-uri directive).", "description": "Allowed base URIs for the document.\n\n- Maps to CSP `base-uri` directive\n- Empty or omitted → only same origin allowed (`base-uri 'self'`)",
"type": "array", "type": "array",
"items": { "items": {
"type": "string" "type": "string"
@ -2480,25 +2480,25 @@
"type": "object", "type": "object",
"properties": { "properties": {
"camera": { "camera": {
"description": "Request camera access (Permission Policy `camera` feature).", "description": "Request camera access.\n\nMaps to Permission Policy `camera` feature.",
"type": "object", "type": "object",
"properties": {}, "properties": {},
"additionalProperties": false "additionalProperties": false
}, },
"microphone": { "microphone": {
"description": "Request microphone access (Permission Policy `microphone` feature).", "description": "Request microphone access.\n\nMaps to Permission Policy `microphone` feature.",
"type": "object", "type": "object",
"properties": {}, "properties": {},
"additionalProperties": false "additionalProperties": false
}, },
"geolocation": { "geolocation": {
"description": "Request geolocation access (Permission Policy `geolocation` feature).", "description": "Request geolocation access.\n\nMaps to Permission Policy `geolocation` feature.",
"type": "object", "type": "object",
"properties": {}, "properties": {},
"additionalProperties": false "additionalProperties": false
}, },
"clipboardWrite": { "clipboardWrite": {
"description": "Request clipboard write access (Permission Policy `clipboard-write` feature).", "description": "Request clipboard write access.\n\nMaps to Permission Policy `clipboard-write` feature.",
"type": "object", "type": "object",
"properties": {}, "properties": {},
"additionalProperties": false "additionalProperties": false
@ -2511,28 +2511,28 @@
"type": "object", "type": "object",
"properties": { "properties": {
"connectDomains": { "connectDomains": {
"description": "Origins for network requests (fetch/XHR/WebSocket).", "description": "Origins for network requests (fetch/XHR/WebSocket).\n\n- Maps to CSP `connect-src` directive\n- Empty or omitted → no external connections (secure default)",
"type": "array", "type": "array",
"items": { "items": {
"type": "string" "type": "string"
} }
}, },
"resourceDomains": { "resourceDomains": {
"description": "Origins for static resources (scripts, images, styles, fonts).", "description": "Origins for static resources (images, scripts, stylesheets, fonts, media).\n\n- Maps to CSP `img-src`, `script-src`, `style-src`, `font-src`, `media-src` directives\n- Wildcard subdomains supported: `https://*.example.com`\n- Empty or omitted → no external resources (secure default)",
"type": "array", "type": "array",
"items": { "items": {
"type": "string" "type": "string"
} }
}, },
"frameDomains": { "frameDomains": {
"description": "Origins for nested iframes (frame-src directive).", "description": "Origins for nested iframes.\n\n- Maps to CSP `frame-src` directive\n- Empty or omitted → no nested iframes allowed (`frame-src 'none'`)",
"type": "array", "type": "array",
"items": { "items": {
"type": "string" "type": "string"
} }
}, },
"baseUriDomains": { "baseUriDomains": {
"description": "Allowed base URIs for the document (base-uri directive).", "description": "Allowed base URIs for the document.\n\n- Maps to CSP `base-uri` directive\n- Empty or omitted → only same origin allowed (`base-uri 'self'`)",
"type": "array", "type": "array",
"items": { "items": {
"type": "string" "type": "string"
@ -3874,28 +3874,28 @@
"type": "object", "type": "object",
"properties": { "properties": {
"connectDomains": { "connectDomains": {
"description": "Origins for network requests (fetch/XHR/WebSocket).", "description": "Origins for network requests (fetch/XHR/WebSocket).\n\n- Maps to CSP `connect-src` directive\n- Empty or omitted → no external connections (secure default)",
"type": "array", "type": "array",
"items": { "items": {
"type": "string" "type": "string"
} }
}, },
"resourceDomains": { "resourceDomains": {
"description": "Origins for static resources (scripts, images, styles, fonts).", "description": "Origins for static resources (images, scripts, stylesheets, fonts, media).\n\n- Maps to CSP `img-src`, `script-src`, `style-src`, `font-src`, `media-src` directives\n- Wildcard subdomains supported: `https://*.example.com`\n- Empty or omitted → no external resources (secure default)",
"type": "array", "type": "array",
"items": { "items": {
"type": "string" "type": "string"
} }
}, },
"frameDomains": { "frameDomains": {
"description": "Origins for nested iframes (frame-src directive).", "description": "Origins for nested iframes.\n\n- Maps to CSP `frame-src` directive\n- Empty or omitted → no nested iframes allowed (`frame-src 'none'`)",
"type": "array", "type": "array",
"items": { "items": {
"type": "string" "type": "string"
} }
}, },
"baseUriDomains": { "baseUriDomains": {
"description": "Allowed base URIs for the document (base-uri directive).", "description": "Allowed base URIs for the document.\n\n- Maps to CSP `base-uri` directive\n- Empty or omitted → only same origin allowed (`base-uri 'self'`)",
"type": "array", "type": "array",
"items": { "items": {
"type": "string" "type": "string"
@ -3909,32 +3909,32 @@
"type": "object", "type": "object",
"properties": { "properties": {
"csp": { "csp": {
"description": "Content Security Policy configuration.", "description": "Content Security Policy configuration for UI resources.",
"type": "object", "type": "object",
"properties": { "properties": {
"connectDomains": { "connectDomains": {
"description": "Origins for network requests (fetch/XHR/WebSocket).", "description": "Origins for network requests (fetch/XHR/WebSocket).\n\n- Maps to CSP `connect-src` directive\n- Empty or omitted → no external connections (secure default)",
"type": "array", "type": "array",
"items": { "items": {
"type": "string" "type": "string"
} }
}, },
"resourceDomains": { "resourceDomains": {
"description": "Origins for static resources (scripts, images, styles, fonts).", "description": "Origins for static resources (images, scripts, stylesheets, fonts, media).\n\n- Maps to CSP `img-src`, `script-src`, `style-src`, `font-src`, `media-src` directives\n- Wildcard subdomains supported: `https://*.example.com`\n- Empty or omitted → no external resources (secure default)",
"type": "array", "type": "array",
"items": { "items": {
"type": "string" "type": "string"
} }
}, },
"frameDomains": { "frameDomains": {
"description": "Origins for nested iframes (frame-src directive).", "description": "Origins for nested iframes.\n\n- Maps to CSP `frame-src` directive\n- Empty or omitted → no nested iframes allowed (`frame-src 'none'`)",
"type": "array", "type": "array",
"items": { "items": {
"type": "string" "type": "string"
} }
}, },
"baseUriDomains": { "baseUriDomains": {
"description": "Allowed base URIs for the document (base-uri directive).", "description": "Allowed base URIs for the document.\n\n- Maps to CSP `base-uri` directive\n- Empty or omitted → only same origin allowed (`base-uri 'self'`)",
"type": "array", "type": "array",
"items": { "items": {
"type": "string" "type": "string"
@ -3944,29 +3944,29 @@
"additionalProperties": false "additionalProperties": false
}, },
"permissions": { "permissions": {
"description": "Sandbox permissions requested by the UI.", "description": "Sandbox permissions requested by the UI resource.",
"type": "object", "type": "object",
"properties": { "properties": {
"camera": { "camera": {
"description": "Request camera access (Permission Policy `camera` feature).", "description": "Request camera access.\n\nMaps to Permission Policy `camera` feature.",
"type": "object", "type": "object",
"properties": {}, "properties": {},
"additionalProperties": false "additionalProperties": false
}, },
"microphone": { "microphone": {
"description": "Request microphone access (Permission Policy `microphone` feature).", "description": "Request microphone access.\n\nMaps to Permission Policy `microphone` feature.",
"type": "object", "type": "object",
"properties": {}, "properties": {},
"additionalProperties": false "additionalProperties": false
}, },
"geolocation": { "geolocation": {
"description": "Request geolocation access (Permission Policy `geolocation` feature).", "description": "Request geolocation access.\n\nMaps to Permission Policy `geolocation` feature.",
"type": "object", "type": "object",
"properties": {}, "properties": {},
"additionalProperties": false "additionalProperties": false
}, },
"clipboardWrite": { "clipboardWrite": {
"description": "Request clipboard write access (Permission Policy `clipboard-write` feature).", "description": "Request clipboard write access.\n\nMaps to Permission Policy `clipboard-write` feature.",
"type": "object", "type": "object",
"properties": {}, "properties": {},
"additionalProperties": false "additionalProperties": false
@ -3975,11 +3975,11 @@
"additionalProperties": false "additionalProperties": false
}, },
"domain": { "domain": {
"description": "Dedicated origin for view sandbox.", "description": "Dedicated origin for view sandbox.\n\nUseful when views need stable, dedicated origins for OAuth callbacks, CORS policies, or API key allowlists.\n\n**Host-dependent:** The format and validation rules for this field are determined by each host. Servers MUST consult host-specific documentation for the expected domain format. Common patterns include:\n- Hash-based subdomains (e.g., `{hash}.claudemcpcontent.com`)\n- URL-derived subdomains (e.g., `www-example-com.oaiusercontent.com`)\n\nIf omitted, host uses default sandbox origin (typically per-conversation).",
"type": "string" "type": "string"
}, },
"prefersBorder": { "prefersBorder": {
"description": "Visual boundary preference - true if UI prefers a visible border.", "description": "Visual boundary preference - true if view prefers a visible border.\n\nBoolean requesting whether a visible border and background is provided by the host. Specifying an explicit value for this is recommended because hosts' defaults may vary.\n\n- `true`: request visible border + background\n- `false`: request no visible border + background\n- omitted: host decides border",
"type": "boolean" "type": "boolean"
} }
}, },
@ -3990,25 +3990,25 @@
"type": "object", "type": "object",
"properties": { "properties": {
"camera": { "camera": {
"description": "Request camera access (Permission Policy `camera` feature).", "description": "Request camera access.\n\nMaps to Permission Policy `camera` feature.",
"type": "object", "type": "object",
"properties": {}, "properties": {},
"additionalProperties": false "additionalProperties": false
}, },
"microphone": { "microphone": {
"description": "Request microphone access (Permission Policy `microphone` feature).", "description": "Request microphone access.\n\nMaps to Permission Policy `microphone` feature.",
"type": "object", "type": "object",
"properties": {}, "properties": {},
"additionalProperties": false "additionalProperties": false
}, },
"geolocation": { "geolocation": {
"description": "Request geolocation access (Permission Policy `geolocation` feature).", "description": "Request geolocation access.\n\nMaps to Permission Policy `geolocation` feature.",
"type": "object", "type": "object",
"properties": {}, "properties": {},
"additionalProperties": false "additionalProperties": false
}, },
"clipboardWrite": { "clipboardWrite": {
"description": "Request clipboard write access (Permission Policy `clipboard-write` feature).", "description": "Request clipboard write access.\n\nMaps to Permission Policy `clipboard-write` feature.",
"type": "object", "type": "object",
"properties": {}, "properties": {},
"additionalProperties": false "additionalProperties": false
@ -4082,28 +4082,28 @@
"type": "object", "type": "object",
"properties": { "properties": {
"connectDomains": { "connectDomains": {
"description": "Origins for network requests (fetch/XHR/WebSocket).", "description": "Origins for network requests (fetch/XHR/WebSocket).\n\n- Maps to CSP `connect-src` directive\n- Empty or omitted → no external connections (secure default)",
"type": "array", "type": "array",
"items": { "items": {
"type": "string" "type": "string"
} }
}, },
"resourceDomains": { "resourceDomains": {
"description": "Origins for static resources (scripts, images, styles, fonts).", "description": "Origins for static resources (images, scripts, stylesheets, fonts, media).\n\n- Maps to CSP `img-src`, `script-src`, `style-src`, `font-src`, `media-src` directives\n- Wildcard subdomains supported: `https://*.example.com`\n- Empty or omitted → no external resources (secure default)",
"type": "array", "type": "array",
"items": { "items": {
"type": "string" "type": "string"
} }
}, },
"frameDomains": { "frameDomains": {
"description": "Origins for nested iframes (frame-src directive).", "description": "Origins for nested iframes.\n\n- Maps to CSP `frame-src` directive\n- Empty or omitted → no nested iframes allowed (`frame-src 'none'`)",
"type": "array", "type": "array",
"items": { "items": {
"type": "string" "type": "string"
} }
}, },
"baseUriDomains": { "baseUriDomains": {
"description": "Allowed base URIs for the document (base-uri directive).", "description": "Allowed base URIs for the document.\n\n- Maps to CSP `base-uri` directive\n- Empty or omitted → only same origin allowed (`base-uri 'self'`)",
"type": "array", "type": "array",
"items": { "items": {
"type": "string" "type": "string"
@ -4117,25 +4117,25 @@
"type": "object", "type": "object",
"properties": { "properties": {
"camera": { "camera": {
"description": "Request camera access (Permission Policy `camera` feature).", "description": "Request camera access.\n\nMaps to Permission Policy `camera` feature.",
"type": "object", "type": "object",
"properties": {}, "properties": {},
"additionalProperties": false "additionalProperties": false
}, },
"microphone": { "microphone": {
"description": "Request microphone access (Permission Policy `microphone` feature).", "description": "Request microphone access.\n\nMaps to Permission Policy `microphone` feature.",
"type": "object", "type": "object",
"properties": {}, "properties": {},
"additionalProperties": false "additionalProperties": false
}, },
"geolocation": { "geolocation": {
"description": "Request geolocation access (Permission Policy `geolocation` feature).", "description": "Request geolocation access.\n\nMaps to Permission Policy `geolocation` feature.",
"type": "object", "type": "object",
"properties": {}, "properties": {},
"additionalProperties": false "additionalProperties": false
}, },
"clipboardWrite": { "clipboardWrite": {
"description": "Request clipboard write access (Permission Policy `clipboard-write` feature).", "description": "Request clipboard write access.\n\nMaps to Permission Policy `clipboard-write` feature.",
"type": "object", "type": "object",
"properties": {}, "properties": {},
"additionalProperties": false "additionalProperties": false

163
src/generated/schema.ts generated
View file

@ -187,61 +187,138 @@ export const McpUiSandboxProxyReadyNotificationSchema = z.object({
/** /**
* @description Content Security Policy configuration for UI resources. * @description Content Security Policy configuration for UI resources.
*
* Servers declare which external origins their UI needs to access.
* Hosts use this to enforce appropriate CSP headers.
*
* > [!IMPORTANT]
* > MCP App HTML runs in a sandboxed iframe with no same-origin server.
* > **All** origins must be declared—including where your bundled JS/CSS is
* > served from (`localhost` in dev, your CDN in production).
*/ */
export const McpUiResourceCspSchema = z.object({ export const McpUiResourceCspSchema = z.object({
/** @description Origins for network requests (fetch/XHR/WebSocket). */ /**
* @description Origins for network requests (fetch/XHR/WebSocket).
*
* - Maps to CSP `connect-src` directive
* - Empty or omitted → no external connections (secure default)
*
* @example
* ```ts
* ["https://api.weather.com", "wss://realtime.service.com"]
* ```
*/
connectDomains: z connectDomains: z
.array(z.string()) .array(z.string())
.optional() .optional()
.describe("Origins for network requests (fetch/XHR/WebSocket)."), .describe(
/** @description Origins for static resources (scripts, images, styles, fonts). */ "Origins for network requests (fetch/XHR/WebSocket).\n\n- Maps to CSP `connect-src` directive\n- Empty or omitted \u2192 no external connections (secure default)",
),
/**
* @description Origins for static resources (images, scripts, stylesheets, fonts, media).
*
* - Maps to CSP `img-src`, `script-src`, `style-src`, `font-src`, `media-src` directives
* - Wildcard subdomains supported: `https://*.example.com`
* - Empty or omitted → no external resources (secure default)
*
* @example
* ```ts
* ["https://cdn.jsdelivr.net", "https://*.cloudflare.com"]
* ```
*/
resourceDomains: z resourceDomains: z
.array(z.string()) .array(z.string())
.optional() .optional()
.describe("Origins for static resources (scripts, images, styles, fonts)."), .describe(
/** @description Origins for nested iframes (frame-src directive). */ "Origins for static resources (images, scripts, stylesheets, fonts, media).\n\n- Maps to CSP `img-src`, `script-src`, `style-src`, `font-src`, `media-src` directives\n- Wildcard subdomains supported: `https://*.example.com`\n- Empty or omitted \u2192 no external resources (secure default)",
),
/**
* @description Origins for nested iframes.
*
* - Maps to CSP `frame-src` directive
* - Empty or omitted → no nested iframes allowed (`frame-src 'none'`)
*
* @example
* ```ts
* ["https://www.youtube.com", "https://player.vimeo.com"]
* ```
*/
frameDomains: z frameDomains: z
.array(z.string()) .array(z.string())
.optional() .optional()
.describe("Origins for nested iframes (frame-src directive)."), .describe(
/** @description Allowed base URIs for the document (base-uri directive). */ "Origins for nested iframes.\n\n- Maps to CSP `frame-src` directive\n- Empty or omitted \u2192 no nested iframes allowed (`frame-src 'none'`)",
),
/**
* @description Allowed base URIs for the document.
*
* - Maps to CSP `base-uri` directive
* - Empty or omitted → only same origin allowed (`base-uri 'self'`)
*
* @example
* ```ts
* ["https://cdn.example.com"]
* ```
*/
baseUriDomains: z baseUriDomains: z
.array(z.string()) .array(z.string())
.optional() .optional()
.describe("Allowed base URIs for the document (base-uri directive)."), .describe(
"Allowed base URIs for the document.\n\n- Maps to CSP `base-uri` directive\n- Empty or omitted \u2192 only same origin allowed (`base-uri 'self'`)",
),
}); });
/** /**
* @description Sandbox permissions requested by the UI resource. * @description Sandbox permissions requested by the UI resource.
*
* Servers declare which browser capabilities their UI needs.
* Hosts MAY honor these by setting appropriate iframe `allow` attributes. * Hosts MAY honor these by setting appropriate iframe `allow` attributes.
* Apps SHOULD NOT assume permissions are granted; use JS feature detection as fallback. * Apps SHOULD NOT assume permissions are granted; use JS feature detection as fallback.
*/ */
export const McpUiResourcePermissionsSchema = z.object({ export const McpUiResourcePermissionsSchema = z.object({
/** @description Request camera access (Permission Policy `camera` feature). */ /**
* @description Request camera access.
*
* Maps to Permission Policy `camera` feature.
*/
camera: z camera: z
.object({}) .object({})
.optional() .optional()
.describe("Request camera access (Permission Policy `camera` feature)."), .describe(
/** @description Request microphone access (Permission Policy `microphone` feature). */ "Request camera access.\n\nMaps to Permission Policy `camera` feature.",
),
/**
* @description Request microphone access.
*
* Maps to Permission Policy `microphone` feature.
*/
microphone: z microphone: z
.object({}) .object({})
.optional() .optional()
.describe( .describe(
"Request microphone access (Permission Policy `microphone` feature).", "Request microphone access.\n\nMaps to Permission Policy `microphone` feature.",
), ),
/** @description Request geolocation access (Permission Policy `geolocation` feature). */ /**
* @description Request geolocation access.
*
* Maps to Permission Policy `geolocation` feature.
*/
geolocation: z geolocation: z
.object({}) .object({})
.optional() .optional()
.describe( .describe(
"Request geolocation access (Permission Policy `geolocation` feature).", "Request geolocation access.\n\nMaps to Permission Policy `geolocation` feature.",
), ),
/** @description Request clipboard write access (Permission Policy `clipboard-write` feature). */ /**
* @description Request clipboard write access.
*
* Maps to Permission Policy `clipboard-write` feature.
*/
clipboardWrite: z clipboardWrite: z
.object({}) .object({})
.optional() .optional()
.describe( .describe(
"Request clipboard write access (Permission Policy `clipboard-write` feature).", "Request clipboard write access.\n\nMaps to Permission Policy `clipboard-write` feature.",
), ),
}); });
@ -490,22 +567,55 @@ export const McpUiInitializedNotificationSchema = z.object({
* @description UI Resource metadata for security and rendering configuration. * @description UI Resource metadata for security and rendering configuration.
*/ */
export const McpUiResourceMetaSchema = z.object({ export const McpUiResourceMetaSchema = z.object({
/** @description Content Security Policy configuration. */ /** @description Content Security Policy configuration for UI resources. */
csp: McpUiResourceCspSchema.optional().describe( csp: McpUiResourceCspSchema.optional().describe(
"Content Security Policy configuration.", "Content Security Policy configuration for UI resources.",
), ),
/** @description Sandbox permissions requested by the UI. */ /** @description Sandbox permissions requested by the UI resource. */
permissions: McpUiResourcePermissionsSchema.optional().describe( permissions: McpUiResourcePermissionsSchema.optional().describe(
"Sandbox permissions requested by the UI.", "Sandbox permissions requested by the UI resource.",
), ),
/** @description Dedicated origin for view sandbox. */ /**
domain: z.string().optional().describe("Dedicated origin for view sandbox."), * @description Dedicated origin for view sandbox.
/** @description Visual boundary preference - true if UI prefers a visible border. */ *
* Useful when views need stable, dedicated origins for OAuth callbacks, CORS policies, or API key allowlists.
*
* **Host-dependent:** The format and validation rules for this field are determined by each host. Servers MUST consult host-specific documentation for the expected domain format. Common patterns include:
* - Hash-based subdomains (e.g., `{hash}.claudemcpcontent.com`)
* - URL-derived subdomains (e.g., `www-example-com.oaiusercontent.com`)
*
* If omitted, host uses default sandbox origin (typically per-conversation).
*
* @example
* ```ts
* "a904794854a047f6.claudemcpcontent.com"
* ```
*
* @example
* ```ts
* "www-example-com.oaiusercontent.com"
* ```
*/
domain: z
.string()
.optional()
.describe(
"Dedicated origin for view sandbox.\n\nUseful when views need stable, dedicated origins for OAuth callbacks, CORS policies, or API key allowlists.\n\n**Host-dependent:** The format and validation rules for this field are determined by each host. Servers MUST consult host-specific documentation for the expected domain format. Common patterns include:\n- Hash-based subdomains (e.g., `{hash}.claudemcpcontent.com`)\n- URL-derived subdomains (e.g., `www-example-com.oaiusercontent.com`)\n\nIf omitted, host uses default sandbox origin (typically per-conversation).",
),
/**
* @description Visual boundary preference - true if view prefers a visible border.
*
* Boolean requesting whether a visible border and background is provided by the host. Specifying an explicit value for this is recommended because hosts' defaults may vary.
*
* - `true`: request visible border + background
* - `false`: request no visible border + background
* - omitted: host decides border
*/
prefersBorder: z prefersBorder: z
.boolean() .boolean()
.optional() .optional()
.describe( .describe(
"Visual boundary preference - true if UI prefers a visible border.", "Visual boundary preference - true if view prefers a visible border.\n\nBoolean requesting whether a visible border and background is provided by the host. Specifying an explicit value for this is recommended because hosts' defaults may vary.\n\n- `true`: request visible border + background\n- `false`: request no visible border + background\n- omitted: host decides border",
), ),
}); });
@ -551,7 +661,10 @@ export const McpUiToolMetaSchema = z.object({
* URI of the UI resource to display for this tool, if any. * URI of the UI resource to display for this tool, if any.
* This is converted to `_meta["ui/resourceUri"]`. * This is converted to `_meta["ui/resourceUri"]`.
* *
* @example "ui://weather/view.html" * @example
* ```ts
* "ui://weather/view.html"
* ```
*/ */
resourceUri: z.string().optional(), resourceUri: z.string().optional(),
/** /**

View file

@ -538,31 +538,98 @@ export interface McpUiInitializedNotification {
/** /**
* @description Content Security Policy configuration for UI resources. * @description Content Security Policy configuration for UI resources.
*
* Servers declare which external origins their UI needs to access.
* Hosts use this to enforce appropriate CSP headers.
*
* > [!IMPORTANT]
* > MCP App HTML runs in a sandboxed iframe with no same-origin server.
* > **All** origins must be declared—including where your bundled JS/CSS is
* > served from (`localhost` in dev, your CDN in production).
*/ */
export interface McpUiResourceCsp { export interface McpUiResourceCsp {
/** @description Origins for network requests (fetch/XHR/WebSocket). */ /**
* @description Origins for network requests (fetch/XHR/WebSocket).
*
* - Maps to CSP `connect-src` directive
* - Empty or omitted → no external connections (secure default)
*
* @example
* ```ts
* ["https://api.weather.com", "wss://realtime.service.com"]
* ```
*/
connectDomains?: string[]; connectDomains?: string[];
/** @description Origins for static resources (scripts, images, styles, fonts). */ /**
* @description Origins for static resources (images, scripts, stylesheets, fonts, media).
*
* - Maps to CSP `img-src`, `script-src`, `style-src`, `font-src`, `media-src` directives
* - Wildcard subdomains supported: `https://*.example.com`
* - Empty or omitted → no external resources (secure default)
*
* @example
* ```ts
* ["https://cdn.jsdelivr.net", "https://*.cloudflare.com"]
* ```
*/
resourceDomains?: string[]; resourceDomains?: string[];
/** @description Origins for nested iframes (frame-src directive). */ /**
* @description Origins for nested iframes.
*
* - Maps to CSP `frame-src` directive
* - Empty or omitted → no nested iframes allowed (`frame-src 'none'`)
*
* @example
* ```ts
* ["https://www.youtube.com", "https://player.vimeo.com"]
* ```
*/
frameDomains?: string[]; frameDomains?: string[];
/** @description Allowed base URIs for the document (base-uri directive). */ /**
* @description Allowed base URIs for the document.
*
* - Maps to CSP `base-uri` directive
* - Empty or omitted → only same origin allowed (`base-uri 'self'`)
*
* @example
* ```ts
* ["https://cdn.example.com"]
* ```
*/
baseUriDomains?: string[]; baseUriDomains?: string[];
} }
/** /**
* @description Sandbox permissions requested by the UI resource. * @description Sandbox permissions requested by the UI resource.
*
* Servers declare which browser capabilities their UI needs.
* Hosts MAY honor these by setting appropriate iframe `allow` attributes. * Hosts MAY honor these by setting appropriate iframe `allow` attributes.
* Apps SHOULD NOT assume permissions are granted; use JS feature detection as fallback. * Apps SHOULD NOT assume permissions are granted; use JS feature detection as fallback.
*/ */
export interface McpUiResourcePermissions { export interface McpUiResourcePermissions {
/** @description Request camera access (Permission Policy `camera` feature). */ /**
* @description Request camera access.
*
* Maps to Permission Policy `camera` feature.
*/
camera?: {}; camera?: {};
/** @description Request microphone access (Permission Policy `microphone` feature). */ /**
* @description Request microphone access.
*
* Maps to Permission Policy `microphone` feature.
*/
microphone?: {}; microphone?: {};
/** @description Request geolocation access (Permission Policy `geolocation` feature). */ /**
* @description Request geolocation access.
*
* Maps to Permission Policy `geolocation` feature.
*/
geolocation?: {}; geolocation?: {};
/** @description Request clipboard write access (Permission Policy `clipboard-write` feature). */ /**
* @description Request clipboard write access.
*
* Maps to Permission Policy `clipboard-write` feature.
*/
clipboardWrite?: {}; clipboardWrite?: {};
} }
@ -570,13 +637,41 @@ export interface McpUiResourcePermissions {
* @description UI Resource metadata for security and rendering configuration. * @description UI Resource metadata for security and rendering configuration.
*/ */
export interface McpUiResourceMeta { export interface McpUiResourceMeta {
/** @description Content Security Policy configuration. */ /** @description Content Security Policy configuration for UI resources. */
csp?: McpUiResourceCsp; csp?: McpUiResourceCsp;
/** @description Sandbox permissions requested by the UI. */ /** @description Sandbox permissions requested by the UI resource. */
permissions?: McpUiResourcePermissions; permissions?: McpUiResourcePermissions;
/** @description Dedicated origin for view sandbox. */ /**
* @description Dedicated origin for view sandbox.
*
* Useful when views need stable, dedicated origins for OAuth callbacks, CORS policies, or API key allowlists.
*
* **Host-dependent:** The format and validation rules for this field are determined by each host. Servers MUST consult host-specific documentation for the expected domain format. Common patterns include:
* - Hash-based subdomains (e.g., `{hash}.claudemcpcontent.com`)
* - URL-derived subdomains (e.g., `www-example-com.oaiusercontent.com`)
*
* If omitted, host uses default sandbox origin (typically per-conversation).
*
* @example
* ```ts
* "a904794854a047f6.claudemcpcontent.com"
* ```
*
* @example
* ```ts
* "www-example-com.oaiusercontent.com"
* ```
*/
domain?: string; domain?: string;
/** @description Visual boundary preference - true if UI prefers a visible border. */ /**
* @description Visual boundary preference - true if view prefers a visible border.
*
* Boolean requesting whether a visible border and background is provided by the host. Specifying an explicit value for this is recommended because hosts' defaults may vary.
*
* - `true`: request visible border + background
* - `false`: request no visible border + background
* - omitted: host decides border
*/
prefersBorder?: boolean; prefersBorder?: boolean;
} }
@ -621,7 +716,10 @@ export interface McpUiToolMeta {
* URI of the UI resource to display for this tool, if any. * URI of the UI resource to display for this tool, if any.
* This is converted to `_meta["ui/resourceUri"]`. * This is converted to `_meta["ui/resourceUri"]`.
* *
* @example "ui://weather/view.html" * @example
* ```ts
* "ui://weather/view.html"
* ```
*/ */
resourceUri?: string; resourceUri?: string;
/** /**