Skip to content

Commit f95bfa9

Browse files
connor4312eli-w-king
authored andcommitted
mcp: adopt ext-apps#158 (#287134)
Additional sandbox negotiation options Refs modelcontextprotocol/ext-apps#158
1 parent 649c715 commit f95bfa9

2 files changed

Lines changed: 89 additions & 12 deletions

File tree

src/vs/workbench/contrib/chat/browser/widget/chatContentParts/toolInvocationParts/chatMcpAppModel.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ export class ChatMcpAppModel extends Disposable {
6262
/** Whether ui/initialize has been called and capabilities announced */
6363
private _announcedCapabilities = false;
6464

65+
/** Latest CSP used for the frame */
66+
private _latestCsp: McpApps.McpUiResourceCsp | undefined = undefined;
67+
6568
/** Current height of the webview */
6669
private _height: number = 300;
6770

@@ -216,6 +219,7 @@ export class ChatMcpAppModel extends Disposable {
216219

217220
// Reset the state
218221
this._announcedCapabilities = false;
222+
this._latestCsp = resourceContent.csp;
219223

220224
// Set the HTML content
221225
this._webview.setHtml(htmlWithCsp);
@@ -257,9 +261,9 @@ export class ChatMcpAppModel extends Disposable {
257261
img-src 'self' data: ${cleanDomains(csp?.resourceDomains)};
258262
font-src 'self' ${cleanDomains(csp?.resourceDomains)};
259263
media-src 'self' data: ${cleanDomains(csp?.resourceDomains)};
260-
frame-src 'none';
264+
frame-src ${cleanDomains(csp?.frameDomains) || `'none'`};
261265
object-src 'none';
262-
base-uri 'self';
266+
base-uri ${cleanDomains(csp?.baseUriDomains) || `'none'`};
263267
`;
264268

265269
const cspTag = `<meta http-equiv="Content-Security-Policy" content="${cspContent}">`;
@@ -468,6 +472,10 @@ export class ChatMcpAppModel extends Disposable {
468472
serverTools: { listChanged: true },
469473
serverResources: { listChanged: true },
470474
logging: {},
475+
sandbox: {
476+
csp: this._latestCsp,
477+
permissions: { clipboardWrite: true },
478+
},
471479
},
472480
hostContext: this.hostContext.get(),
473481
} satisfies Required<McpApps.McpUiInitializeResult>;

src/vs/workbench/contrib/mcp/common/modelContextProtocolApps.ts

Lines changed: 79 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ export namespace McpApps {
6161
* ⚠️ Do not edit within `namespace` manually except to update schema versions ⚠️
6262
*/
6363
export namespace McpApps {
64-
/*
64+
/**
6565
* Current protocol version supported by this SDK.
6666
*
6767
* The SDK automatically handles version negotiation during initialization.
@@ -262,12 +262,9 @@ export namespace McpApps {
262262
/** @description Optional override for the inner iframe's sandbox attribute. */
263263
sandbox?: string;
264264
/** @description CSP configuration from resource metadata. */
265-
csp?: {
266-
/** @description Origins for network requests (fetch/XHR/WebSocket). */
267-
connectDomains?: string[];
268-
/** @description Origins for static resources (scripts, images, styles, fonts). */
269-
resourceDomains?: string[];
270-
};
265+
csp?: McpUiResourceCsp;
266+
/** @description Sandbox permissions from resource metadata. */
267+
permissions?: McpUiResourcePermissions;
271268
};
272269
}
273270

@@ -356,7 +353,7 @@ export namespace McpApps {
356353
/** @description Metadata of the tool call that instantiated this App. */
357354
toolInfo?: {
358355
/** @description JSON-RPC id of the tools/call request. */
359-
id: RequestId;
356+
id?: RequestId;
360357
/** @description Tool definition including name, inputSchema, etc. */
361358
tool: Tool;
362359
};
@@ -471,6 +468,13 @@ export namespace McpApps {
471468
};
472469
/** @description Host accepts log messages. */
473470
logging?: {};
471+
/** @description Sandbox configuration applied by the host. */
472+
sandbox?: {
473+
/** @description Permissions granted by the host (camera, microphone, geolocation). */
474+
permissions?: McpUiResourcePermissions;
475+
/** @description CSP domains approved by the host. */
476+
csp?: McpUiResourceCsp;
477+
};
474478
}
475479

476480
/**
@@ -540,6 +544,26 @@ export namespace McpApps {
540544
connectDomains?: string[];
541545
/** @description Origins for static resources (scripts, images, styles, fonts). */
542546
resourceDomains?: string[];
547+
/** @description Origins for nested iframes (frame-src directive). */
548+
frameDomains?: string[];
549+
/** @description Allowed base URIs for the document (base-uri directive). */
550+
baseUriDomains?: string[];
551+
}
552+
553+
/**
554+
* @description Sandbox permissions requested by the UI resource.
555+
* Hosts MAY honor these by setting appropriate iframe `allow` attributes.
556+
* Apps SHOULD NOT assume permissions are granted; use JS feature detection as fallback.
557+
*/
558+
export interface McpUiResourcePermissions {
559+
/** @description Request camera access (Permission Policy `camera` feature). */
560+
camera?: {};
561+
/** @description Request microphone access (Permission Policy `microphone` feature). */
562+
microphone?: {};
563+
/** @description Request geolocation access (Permission Policy `geolocation` feature). */
564+
geolocation?: {};
565+
/** @description Request clipboard write access (Permission Policy `clipboard-write` feature). */
566+
clipboardWrite?: {};
543567
}
544568

545569
/**
@@ -548,6 +572,8 @@ export namespace McpApps {
548572
export interface McpUiResourceMeta {
549573
/** @description Content Security Policy configuration. */
550574
csp?: McpUiResourceCsp;
575+
/** @description Sandbox permissions requested by the UI. */
576+
permissions?: McpUiResourcePermissions;
551577
/** @description Dedicated origin for widget sandbox. */
552578
domain?: string;
553579
/** @description Visual boundary preference - true if UI prefers a visible border. */
@@ -592,17 +618,60 @@ export namespace McpApps {
592618
*/
593619
export interface McpUiToolMeta {
594620
/**
595-
* URI of the UI resource to display for this tool.
621+
* URI of the UI resource to display for this tool, if any.
596622
* This is converted to `_meta["ui/resourceUri"]`.
597623
*
598624
* @example "ui://weather/widget.html"
599625
*/
600-
resourceUri: string;
626+
resourceUri?: string;
601627
/**
602628
* @description Who can access this tool. Default: ["model", "app"]
603629
* - "model": Tool visible to and callable by the agent
604630
* - "app": Tool callable by the app from this server only
605631
*/
606632
visibility?: McpUiToolVisibility[];
607633
}
634+
635+
/**
636+
* Method string constants for MCP Apps protocol messages.
637+
*
638+
* These constants provide a type-safe way to check message methods without
639+
* accessing internal Zod schema properties. External libraries should use
640+
* these constants instead of accessing `schema.shape.method._def.values[0]`.
641+
*
642+
* @example
643+
* ```typescript
644+
* import { SANDBOX_PROXY_READY_METHOD } from '@modelcontextprotocol/ext-apps';
645+
*
646+
* if (event.data.method === SANDBOX_PROXY_READY_METHOD) {
647+
* // Handle sandbox proxy ready notification
648+
* }
649+
* ```
650+
*/
651+
export const OPEN_LINK_METHOD: McpUiOpenLinkRequest["method"] = "ui/open-link";
652+
export const MESSAGE_METHOD: McpUiMessageRequest["method"] = "ui/message";
653+
export const SANDBOX_PROXY_READY_METHOD: McpUiSandboxProxyReadyNotification["method"] =
654+
"ui/notifications/sandbox-proxy-ready";
655+
export const SANDBOX_RESOURCE_READY_METHOD: McpUiSandboxResourceReadyNotification["method"] =
656+
"ui/notifications/sandbox-resource-ready";
657+
export const SIZE_CHANGED_METHOD: McpUiSizeChangedNotification["method"] =
658+
"ui/notifications/size-changed";
659+
export const TOOL_INPUT_METHOD: McpUiToolInputNotification["method"] =
660+
"ui/notifications/tool-input";
661+
export const TOOL_INPUT_PARTIAL_METHOD: McpUiToolInputPartialNotification["method"] =
662+
"ui/notifications/tool-input-partial";
663+
export const TOOL_RESULT_METHOD: McpUiToolResultNotification["method"] =
664+
"ui/notifications/tool-result";
665+
export const TOOL_CANCELLED_METHOD: McpUiToolCancelledNotification["method"] =
666+
"ui/notifications/tool-cancelled";
667+
export const HOST_CONTEXT_CHANGED_METHOD: McpUiHostContextChangedNotification["method"] =
668+
"ui/notifications/host-context-changed";
669+
export const RESOURCE_TEARDOWN_METHOD: McpUiResourceTeardownRequest["method"] =
670+
"ui/resource-teardown";
671+
export const INITIALIZE_METHOD: McpUiInitializeRequest["method"] =
672+
"ui/initialize";
673+
export const INITIALIZED_METHOD: McpUiInitializedNotification["method"] =
674+
"ui/notifications/initialized";
675+
export const REQUEST_DISPLAY_MODE_METHOD: McpUiRequestDisplayModeRequest["method"] =
676+
"ui/request-display-mode";
608677
}

0 commit comments

Comments
 (0)