Commit cf89893
feat: add MCP Apps (SEP-1865) support (#1335)
* feat: add MCP Apps (SEP-1865) support
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>
* feat: add MCP Apps option to Python, Go, .NET, Rust SDKs
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>
* chore: prettier format mcpAppsSandbox files
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: sanitize CSP domain inputs in mcpAppsSandbox (SEP-1865)
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>
* docs: note runtime MCP_APPS gate on enableMcpApps across SDKs
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>
* feat: surface capabilities.ui.mcpApps and warn on silent drop
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>
* fix: ruff format + add mcp_apps field to Rust e2e UiCapabilities literal
- 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>
* fix: drop sessionId from MCP Apps warning to silence CodeQL clear-text-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>
* feat: add enableMcpApps support to Java SDK
Mirrors the MCP Apps (SEP-1865) opt-in already wired into Node, Python,
Go, .NET, and Rust:
- SessionConfig / ResumeSessionConfig: enableMcpApps field with
isEnableMcpApps / setEnableMcpApps accessors and copy() inclusion
- CreateSessionRequest / ResumeSessionRequest: requestMcpApps wire field
with getter/setter/clearer (Boolean nullable, matches requestElicitation)
- SessionUiCapabilities: mcpApps response field with getter/setter/clearer
- SessionRequestBuilder: wires config.isEnableMcpApps() -> requestMcpApps
on both create and resume paths
- CopilotClient: warnIfMcpAppsDropped helper logs when the consumer
requested the opt-in but the runtime did not advertise it back (runtime
silently drops the opt-in when its MCP_APPS feature flag /
COPILOT_MCP_APPS env override is unset)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* chore: address sanity-check findings
- Revert unintended java/mvnw mode change (644 -> 755) introduced in
the Java SDK commit; CI runs mvnw with explicit bash and doesn't
require the exec bit.
- Refresh Rust doc comments left stale after renaming request_mcp_apps
-> enable_mcp_apps on the user-facing API (session.rs warn helper
docstring + tracing message; UiCapabilities.mcp_apps cref).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* style: apply spotless formatting to Java MCP Apps additions
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Omit requestMcpApps from wire payload when disabled
Aligns Node.js and Python with Go/.NET/Java/Rust, which all omit the
field when the feature is not opted in. Previously these two SDKs
always sent requestMcpApps: false, cluttering protocol logs and
risking ambiguity if the protocol ever distinguishes 'not sent' from
'explicitly false'.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(mcp-apps): address high-priority review feedback
- nodejs: switch warnIfMcpAppsDropped from console.warn to
process.emitWarning with name McpAppsCapabilityDroppedWarning so
consumers can route/suppress it (--no-warnings,
process.on('warning', ...)) like any other Node deprecation warning.
- go: add TestCreateSessionRequest_RequestMcpApps /
TestResumeSessionRequest_RequestMcpApps mirroring the existing
RequestElicitation marshal/omit tests.
- rust: add session_config_enable_mcp_apps_sets_wire_flag_and_serializes
and resume_session_config_enable_mcp_apps_sets_wire_flag_and_serializes
to cover the opt-in path (config field -> wire flag -> requestMcpApps
in serialized JSON).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* docs(mcp-apps): address worth-doing review feedback
- python: add enable_mcp_apps entries to create_session and
resume_session docstring Args lists, describing the runtime gate and
the capabilities.ui.mcpApps detection mechanism.
- java: thread sessionId through warnIfMcpAppsDropped and include it in
the warning message, matching the Python/Go/.NET/Rust pattern for
multi-session debugging.
- nodejs/test: replace the 'see review feedback' marker in the
sandbox sanitization section header with a self-contained reference
to SEP-1865 \xc2\xa7Security Implications.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(go): route MCP Apps warning through log.Default() instead of os.Stderr
Writing directly to os.Stderr from library code is unsuppressible and
unroutable. Switch to log.Printf so consumers can call
log.Default().SetOutput(io.Discard) (or any other writer) to control the
warning. Default behavior is unchanged (log.Default() writes to stderr).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Revert mode change on .githooks/pre-commit
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: include session ID in warnIfMcpAppsDropped warning
Co-authored-by: mattdholloway <918573+mattdholloway@users.noreply.github.com>
* fix: include session ID in warnIfMcpAppsDropped warning
Co-authored-by: mattdholloway <918573+mattdholloway@users.noreply.github.com>
* remove nodejs specific mcp apps sandbox code
* fix: update session ID handling in MCP apps configuration
* refactor: remove MCP Apps warning handling from multiple clients
* style: remove unused SessionCapabilities import in Java client
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: address review feedback on MCP Apps PR
- Fix broken @link in Java SessionConfig (com.github.copilot.sdk.CopilotSession -> com.github.copilot.CopilotSession)
- Revert stray mode change on .githooks/pre-commit (100755 -> 100644)
- Rust: make enable_mcp_apps Option<bool> for consistency with sibling opt-ins (e.g. enable_config_discovery)
- Python: remove stray blank line after logger init in client.py
- Drop incorrect 'the SDK also logs a warning' wording from Python docstrings (the SDK no longer emits a warning; only the runtime does)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* docs: mark MCP Apps APIs as experimental
Mark the new SEP-1865 MCP Apps public APIs as experimental across .NET, Node, Python, Go and Rust SDKs, following each SDK's existing convention (e.g. canvas surface):
- .NET: [Experimental(Diagnostics.Experimental)] on SessionConfigBase.EnableMcpApps and SessionUiCapabilities.McpApps. No #pragma needed at internal call sites because GHCP001 is in the project's NoWarn.
- Node: @experimental JSDoc tag on SessionConfigBase.enableMcpApps and SessionCapabilities.ui.mcpApps.
- Python: **Experimental.** lead-in on enable_mcp_apps parameter docstrings (create_session, resume_session) and SessionUiCapabilities.mcpApps.
- Go: // Experimental: ... doc lines on SessionConfig.EnableMcpApps, ResumeSessionConfig.EnableMcpApps and UICapabilities.McpApps.
- Rust: **Experimental.** first paragraph on SessionConfig.enable_mcp_apps, ResumeSessionConfig.enable_mcp_apps, with_enable_mcp_apps (x2) and UiCapabilities.mcp_apps.
Java is intentionally skipped — the repo has no precedent for marking Java APIs as experimental, so introducing a convention here is out of scope for this commit.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* refactor(rust): drop skip_serializing_if from request_mcp_apps wire field
Match the surrounding request_* bool fields (request_user_input, request_permission, request_exit_plan_mode, request_auto_mode_switch, request_elicitation, hooks) which all serialize unconditionally. Snapshots don't capture these fields so there is no compatibility cost.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* style: spotless reflow on SessionConfig MCP Apps javadoc
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: copilot <copilot@github.com>
Co-authored-by: Steve Sanderson <SteveSandersonMS@users.noreply.github.com>1 parent 45aae2f commit cf89893
18 files changed
Lines changed: 478 additions & 0 deletions
File tree
- dotnet/src
- go
- java/src/main/java/com/github/copilot
- rpc
- nodejs/src
- python/copilot
- rust
- src
- tests/e2e
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
878 | 878 | | |
879 | 879 | | |
880 | 880 | | |
| 881 | + | |
881 | 882 | | |
882 | 883 | | |
883 | 884 | | |
| |||
1059 | 1060 | | |
1060 | 1061 | | |
1061 | 1062 | | |
| 1063 | + | |
1062 | 1064 | | |
1063 | 1065 | | |
1064 | 1066 | | |
| |||
2171 | 2173 | | |
2172 | 2174 | | |
2173 | 2175 | | |
| 2176 | + | |
2174 | 2177 | | |
2175 | 2178 | | |
2176 | 2179 | | |
| |||
2243 | 2246 | | |
2244 | 2247 | | |
2245 | 2248 | | |
| 2249 | + | |
2246 | 2250 | | |
2247 | 2251 | | |
2248 | 2252 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1130 | 1130 | | |
1131 | 1131 | | |
1132 | 1132 | | |
| 1133 | + | |
| 1134 | + | |
| 1135 | + | |
| 1136 | + | |
| 1137 | + | |
| 1138 | + | |
| 1139 | + | |
| 1140 | + | |
| 1141 | + | |
| 1142 | + | |
1133 | 1143 | | |
1134 | 1144 | | |
1135 | 1145 | | |
| |||
2346 | 2356 | | |
2347 | 2357 | | |
2348 | 2358 | | |
| 2359 | + | |
2349 | 2360 | | |
2350 | 2361 | | |
2351 | 2362 | | |
| |||
2507 | 2518 | | |
2508 | 2519 | | |
2509 | 2520 | | |
| 2521 | + | |
| 2522 | + | |
| 2523 | + | |
| 2524 | + | |
| 2525 | + | |
| 2526 | + | |
| 2527 | + | |
| 2528 | + | |
| 2529 | + | |
| 2530 | + | |
| 2531 | + | |
| 2532 | + | |
| 2533 | + | |
| 2534 | + | |
| 2535 | + | |
| 2536 | + | |
| 2537 | + | |
| 2538 | + | |
| 2539 | + | |
| 2540 | + | |
| 2541 | + | |
| 2542 | + | |
| 2543 | + | |
| 2544 | + | |
| 2545 | + | |
2510 | 2546 | | |
2511 | 2547 | | |
2512 | 2548 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
659 | 659 | | |
660 | 660 | | |
661 | 661 | | |
| 662 | + | |
| 663 | + | |
| 664 | + | |
662 | 665 | | |
663 | 666 | | |
664 | 667 | | |
| |||
985 | 988 | | |
986 | 989 | | |
987 | 990 | | |
| 991 | + | |
| 992 | + | |
| 993 | + | |
988 | 994 | | |
989 | 995 | | |
990 | 996 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
946 | 946 | | |
947 | 947 | | |
948 | 948 | | |
| 949 | + | |
| 950 | + | |
| 951 | + | |
| 952 | + | |
| 953 | + | |
| 954 | + | |
| 955 | + | |
| 956 | + | |
| 957 | + | |
| 958 | + | |
| 959 | + | |
| 960 | + | |
| 961 | + | |
| 962 | + | |
| 963 | + | |
| 964 | + | |
| 965 | + | |
| 966 | + | |
| 967 | + | |
| 968 | + | |
| 969 | + | |
| 970 | + | |
| 971 | + | |
| 972 | + | |
| 973 | + | |
| 974 | + | |
| 975 | + | |
| 976 | + | |
| 977 | + | |
| 978 | + | |
| 979 | + | |
| 980 | + | |
| 981 | + | |
| 982 | + | |
| 983 | + | |
| 984 | + | |
| 985 | + | |
| 986 | + | |
| 987 | + | |
| 988 | + | |
| 989 | + | |
| 990 | + | |
| 991 | + | |
| 992 | + | |
| 993 | + | |
| 994 | + | |
| 995 | + | |
| 996 | + | |
| 997 | + | |
| 998 | + | |
| 999 | + | |
| 1000 | + | |
| 1001 | + | |
| 1002 | + | |
| 1003 | + | |
| 1004 | + | |
| 1005 | + | |
| 1006 | + | |
| 1007 | + | |
949 | 1008 | | |
950 | 1009 | | |
951 | 1010 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
987 | 987 | | |
988 | 988 | | |
989 | 989 | | |
| 990 | + | |
| 991 | + | |
| 992 | + | |
| 993 | + | |
| 994 | + | |
| 995 | + | |
| 996 | + | |
| 997 | + | |
| 998 | + | |
| 999 | + | |
| 1000 | + | |
| 1001 | + | |
| 1002 | + | |
| 1003 | + | |
| 1004 | + | |
| 1005 | + | |
| 1006 | + | |
| 1007 | + | |
| 1008 | + | |
| 1009 | + | |
| 1010 | + | |
| 1011 | + | |
| 1012 | + | |
990 | 1013 | | |
991 | 1014 | | |
992 | 1015 | | |
| |||
1089 | 1112 | | |
1090 | 1113 | | |
1091 | 1114 | | |
| 1115 | + | |
| 1116 | + | |
| 1117 | + | |
| 1118 | + | |
| 1119 | + | |
| 1120 | + | |
| 1121 | + | |
| 1122 | + | |
| 1123 | + | |
1092 | 1124 | | |
1093 | 1125 | | |
1094 | 1126 | | |
| |||
1275 | 1307 | | |
1276 | 1308 | | |
1277 | 1309 | | |
| 1310 | + | |
| 1311 | + | |
| 1312 | + | |
| 1313 | + | |
| 1314 | + | |
| 1315 | + | |
1278 | 1316 | | |
1279 | 1317 | | |
1280 | 1318 | | |
| |||
1534 | 1572 | | |
1535 | 1573 | | |
1536 | 1574 | | |
| 1575 | + | |
1537 | 1576 | | |
1538 | 1577 | | |
1539 | 1578 | | |
| |||
1599 | 1638 | | |
1600 | 1639 | | |
1601 | 1640 | | |
| 1641 | + | |
1602 | 1642 | | |
1603 | 1643 | | |
1604 | 1644 | | |
| |||
Lines changed: 6 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
144 | 144 | | |
145 | 145 | | |
146 | 146 | | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
147 | 150 | | |
148 | 151 | | |
149 | 152 | | |
| |||
238 | 241 | | |
239 | 242 | | |
240 | 243 | | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
241 | 247 | | |
242 | 248 | | |
243 | 249 | | |
| |||
Lines changed: 18 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
114 | 114 | | |
115 | 115 | | |
116 | 116 | | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
117 | 120 | | |
118 | 121 | | |
119 | 122 | | |
| |||
503 | 506 | | |
504 | 507 | | |
505 | 508 | | |
| 509 | + | |
| 510 | + | |
| 511 | + | |
| 512 | + | |
| 513 | + | |
| 514 | + | |
| 515 | + | |
| 516 | + | |
| 517 | + | |
| 518 | + | |
| 519 | + | |
| 520 | + | |
| 521 | + | |
| 522 | + | |
| 523 | + | |
506 | 524 | | |
507 | 525 | | |
508 | 526 | | |
| |||
Lines changed: 27 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
74 | 74 | | |
75 | 75 | | |
76 | 76 | | |
| 77 | + | |
77 | 78 | | |
78 | 79 | | |
79 | 80 | | |
| |||
972 | 973 | | |
973 | 974 | | |
974 | 975 | | |
| 976 | + | |
| 977 | + | |
| 978 | + | |
| 979 | + | |
| 980 | + | |
| 981 | + | |
| 982 | + | |
| 983 | + | |
| 984 | + | |
| 985 | + | |
| 986 | + | |
| 987 | + | |
| 988 | + | |
| 989 | + | |
| 990 | + | |
| 991 | + | |
| 992 | + | |
| 993 | + | |
| 994 | + | |
| 995 | + | |
| 996 | + | |
| 997 | + | |
| 998 | + | |
| 999 | + | |
| 1000 | + | |
975 | 1001 | | |
976 | 1002 | | |
977 | 1003 | | |
| |||
1129 | 1155 | | |
1130 | 1156 | | |
1131 | 1157 | | |
| 1158 | + | |
1132 | 1159 | | |
1133 | 1160 | | |
1134 | 1161 | | |
| |||
Lines changed: 18 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
119 | 119 | | |
120 | 120 | | |
121 | 121 | | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
122 | 125 | | |
123 | 126 | | |
124 | 127 | | |
| |||
528 | 531 | | |
529 | 532 | | |
530 | 533 | | |
| 534 | + | |
| 535 | + | |
| 536 | + | |
| 537 | + | |
| 538 | + | |
| 539 | + | |
| 540 | + | |
| 541 | + | |
| 542 | + | |
| 543 | + | |
| 544 | + | |
| 545 | + | |
| 546 | + | |
| 547 | + | |
| 548 | + | |
531 | 549 | | |
532 | 550 | | |
533 | 551 | | |
| |||
0 commit comments