feat: add MCP Apps (SEP-1865) support#1335
Draft
mattdholloway wants to merge 14 commits into
Draft
Conversation
Author
|
@copilot resolve the merge conflicts in this pull request |
Copilot stopped work on behalf of
mattdholloway due to an error
May 19, 2026 16:07
Adds opt-in 'enableMcpApps' session capability that advertises the
'extensions.io.modelcontextprotocol/ui' extension to MCP servers and
exposes 'session.rpc.mcp.apps.*' JSON-RPC methods.
Node SDK gains two pure helpers for hosts rendering 'ui://' MCP App
bundles in iframes:
- buildMcpAppsCspHeader — constructs the Content-Security-Policy header
per SEP-1865 §UI Resource Format + §Security Implications, including
the restrictive default ('connect-src none') when '_meta.ui.csp' is
absent and constructed defaults ('connect-src self', etc.) when it is
declared.
- buildMcpAppsAllowAttribute — maps '_meta.ui.permissions' to the iframe
'allow' attribute (Permission Policy).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
5f12d41 to
0827b5a
Compare
This comment has been minimized.
This comment has been minimized.
Contributor
There was a problem hiding this comment.
Generated by SDK Consistency Review Agent for issue #1335 · ● 793.2K
Copilot stopped work on behalf of
mattdholloway due to an error
May 20, 2026 09:40
Mirror nodejs enableMcpApps across the other four SDKs so hosts using them can opt into MCP Apps (SEP-1865) UI passthrough by sending requestMcpApps on session.create / session.resume. - python: enable_mcp_apps kwarg on create_session / resume_session - go: EnableMcpApps field on SessionConfig / ResumeSessionConfig - dotnet: EnableMcpApps property on SessionConfig / ResumeSessionConfig - rust: request_mcp_apps field + with_request_mcp_apps builder Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This comment has been minimized.
This comment has been minimized.
Port the CSP directive injection defense from copilot-agent-runtime PR #7605 into the SDK. Without sanitization, an MCP server returning `frameDomains: ['evil.com; form-action *']` could break out of one CSP directive and inject sibling directives (CSP first-occurrence rule then lets an earlier injected `script-src *` win). Each server-supplied entry is now: - rejected if it contains CSP metacharacters ([;,\\s'"\\\\]) - accepted verbatim for the bare-scheme allowlist (data:, blob:, mediastream:, filesystem:) - otherwise parsed via URL and canonicalized to its origin; opaque origins (where `URL.origin` is the literal string 'null') are dropped Adds 10 sanitization tests mirroring runtime PR coverage. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Reflect the runtime-side gate added in copilot-agent-runtime PR #7605: requestMcpApps is now honored server-side only when the MCP_APPS feature flag or COPILOT_MCP_APPS=true env override is set; otherwise the opt-in is silently dropped (the runtime logs a warning, but the SDK consumer sees nothing). Update the JSDoc / docstrings on Node, Go, .NET, and Rust to document this and to point at capabilities.ui.mcpApps on the create/resume response as the way to detect the silent drop. Also adds the diagnose method to the enumerated mcp.apps.* RPCs. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This comment has been minimized.
This comment has been minimized.
Expose the runtime's response capability so consumers can detect when their enableMcpApps opt-in was silently dropped by the runtime gate (MCP_APPS feature flag / COPILOT_MCP_APPS env override unset). For each SDK: - Add mcpApps?: bool to the SessionUiCapabilities type - After session.create / session.resume, if the consumer requested the opt-in but capabilities.ui.mcpApps is not true on the response, log a warning (console.warn / logger.warning / slog / tracing::warn / fmt.Fprintf(os.Stderr, ...)) so the silent drop is discoverable. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This comment has been minimized.
This comment has been minimized.
- python: ruff format reflowed the new _warn_if_mcp_apps_dropped helper - rust: tests/e2e/elicitation.rs constructs UiCapabilities as a struct literal; the new mcp_apps field made it non-exhaustive Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This comment has been minimized.
This comment has been minimized.
…t-logging CodeQL flags any value flowing from process.env as sensitive via taint analysis (joinSession() reads process.env.SESSION_ID which propagates to resumeSession's sessionId argument). The session ID is a UUID and not actually sensitive, but the alert noise is not worth it -- the warning is per-call so the consumer already knows which session triggered it. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Author
|
@copilot resolve the merge conflicts in this pull request |
Copilot stopped work on behalf of
mattdholloway due to an error
May 21, 2026 11:45
# Conflicts: # dotnet/src/Types.cs
This comment has been minimized.
This comment has been minimized.
# Conflicts: # go/types.go # nodejs/src/client.ts # nodejs/src/types.ts
Contributor
Cross-SDK Consistency ReviewSummary: This PR adds ✅ SDKs Updated
❌ Java SDK — Missing
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds opt-in MCP Apps (SEP-1865) support to the SDK.
What
enableMcpAppssession capability (SessionConfig+ResumeSessionConfig). Whentrue, the runtime advertises theextensions.io.modelcontextprotocol/uiextension to MCP servers and exposes thesession.rpc.mcp.apps.{listTools,callTool,readResource,setHostContext,getHostContext}JSON-RPC methods. Defaults tofalseso hosts without an iframe renderer don't accidentally register UI-enabled tool variants they can't display.ui://MCP App bundles in iframes:buildMcpAppsCspHeader(csp)— builds theContent-Security-Policyheader per SEP-1865 §UI Resource Format + §Security Implications. Emits the restrictive default (connect-src 'none') when_meta.ui.cspis absent, and the constructed default (connect-src 'self'+ declared domains, etc.) when it is declared (even with empty arrays).buildMcpAppsAllowAttribute(permissions)— maps_meta.ui.permissionsto the iframeallowattribute (Permission Policy), including the hyphenatedclipboard-writename.sequenceDiagram autonumber participant Host as Host App participant SDK as Copilot SDK participant Sandbox as mcpAppsSandbox helpers participant Conn as JSON-RPC Connection participant Runtime as Copilot Runtime participant Iframe as ui iframe Note over Host,Runtime: 1. Opt-in via SDK config Host->>SDK: createSession({ enableMcpApps: true }) SDK->>Conn: session.create { ..., requestMcpApps: true } Conn->>Runtime: JSON-RPC request Runtime-->>Conn: CreateSessionResponse Conn-->>SDK: response SDK-->>Host: CopilotSession Note over Runtime,Host: 2. Tool execution events forwarded unchanged Runtime-->>Conn: tool.execution_complete { uiResource, toolDescription._meta.ui } Conn-->>SDK: SessionEvent (untyped pass-through) SDK-->>Host: onEvent(event) Note over Host,Iframe: 3. Host builds sandboxed iframe using SDK helpers Host->>Sandbox: buildMcpAppsCspHeader(uiResource._meta.ui.csp) Sandbox-->>Host: CSP header value Host->>Sandbox: buildMcpAppsAllowAttribute(uiResource._meta.ui.permissions) Sandbox-->>Host: allow attribute value Host->>Iframe: render with CSP + allow + uiResource Note over Iframe,Runtime: 4. App-to-server RPCs (no typed SDK surface) Iframe->>Host: postMessage RPC Host->>Conn: raw JSON-RPC: session.rpc.mcp.apps.{listTools|callTool|readResource} Conn->>Runtime: forwarded Runtime-->>Conn: result (+ optional ephemeral mcp_app.tool_call_complete event) Conn-->>SDK: SessionEvent (untyped pass-through, callTool only) SDK-->>Host: onEvent(event) Conn-->>Host: RPC response Host-->>Iframe: postMessage response Note over Host,Runtime: 5. Resume preserves opt-in Host->>SDK: resumeSession({ enableMcpApps: true }) SDK->>Conn: session.resume { ..., requestMcpApps: true }Closes https://github.com/github/copilot-mcp-core/issues/1715
Depends on https://github.com/github/copilot-agent-runtime/pull/7605