You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
InspectorClient advertised io.modelcontextprotocol/ui by default in every client. The CLI and TUI cannot render an MCP App, yet they told servers they could — and servers use that advertisement to decide whether to return an App.
Change
core/mcp/extensions.ts: the UI registry entry is marked requiresAppRenderer. A new shared helper, isAdvertisedByDefault(ext, rendersApps), resolves the default: an entry that requires a renderer defaults off unless the client can render Apps. buildClientExtensions uses it, and an explicit advertisedExtensions override still wins. Tasks and Skills are unaffected.
InspectorClientOptions.rendersApps: new option, default false. Supplying an appElicitation renderer implies it, since that is already a claim to host an App.
Web: claims Apps rendering only when the backend supplied a sandbox URL, using the same confirmed-sandbox signal appElicitation already keys on (rendersApps: sandboxUrlRef.current !== undefined). With a sandbox, which is the normal setup, behavior is unchanged. Without one, the UI extension is no longer advertised by default.
Web Server Settings: App passes the same sandbox signal (rendersApps) through ServerSettingsModal to ServerSettingsForm, and both use isAdvertisedByDefault. So the MCP Apps UI checkbox shows what the client will actually declare (unchecked by default with no sandbox), and checking it with no sandbox saves a real true override instead of dropping it as "back to the default".
TUI: passes nothing, so it no longer claims the extension.
CLI: no longer claims it by default and gains an explicit opt-in, --advertise-apps, for probing a server that only exposes its App tools to a client that advertises App support (the issue's "explicit opt-in flag"). It is rejected on the commands that never connect (--list-stored-auth, --print-handoff, servers/list, servers/show), like --strict and --verify. It is documented in the CLI README next to --app-info.
Tests
extensions.test.ts: existing cases now pass rendersApps: true. New cases cover the non-rendering default (UI omitted), rendersApps: false, the explicit override, that Tasks and Skills are not gated, and isAdvertisedByDefault over the whole registry.
inspectorClient-app-elicitation.test.ts: a client with no renderer advertises no UI extension; rendersApps: true advertises the MIME type alone; an override turns it on.
useConnectionLifecycle.test.tsx: the UI extension is advertised with a sandbox and absent without one.
ServerSettingsForm.test.tsx / ServerSettingsModal.test.tsx: the checkbox state for both values of rendersApps, an explicit override shown with no renderer, and the modal saving {ui: true} with no renderer.
CLI app-info.test.ts: end to end against an HTTP test server that gates a tool on io.modelcontextprotocol/ui. The tool is absent by default and present with --advertise-apps, and the flag is rejected on all four paths that never connect.
Each fix was mutation-checked: reverting it fails its new tests. npm run local:gate passes.
Screenshots: none. The only visible web change is the MCP Apps UI checkbox starting unchecked when the backend supplies no sandbox URL; with a sandbox, the UI looks the same as before.
…nders Apps (#2403)
InspectorClient advertised io.modelcontextprotocol/ui by default in every
client, so the CLI and TUI told servers they support MCP Apps although they
cannot render one. The UI registry entry now requires an App renderer: its
default applies only when the new `rendersApps` option is set (or an
app-elicitation renderer is supplied). The web client sets it; the CLI and
TUI no longer claim the extension. An explicit advertisedExtensions override
still wins, and the CLI exposes it as `--advertise-apps` for probing servers
that gate App tools on the advertisement.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
…#2471 review)
Web set rendersApps unconditionally, so with no sandbox URL — where the
Apps screen reports that MCP Apps cannot run — it still advertised the UI
extension. Gate it on the confirmed sandbox URL, as appElicitation already
is. A Server Settings override can still force the extension on.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
Advertise App rendering only when a sandbox URL is available — accepted. It is a gap in what this PR added: web now claims Apps rendering only with a confirmed sandbox URL, matching the adjacent appElicitation gate. Covered by new assertions in useConnectionLifecycle.test.tsx (mutation-checked).
Suppressed comments: none. local:gate green on the fix.
Reject --advertise-apps on commands without MCP connections
clients/cli/src/cli.ts:770
--advertise-apps is accepted on the no-connection paths (--list-stored-auth, --print-handoff, servers/list, and servers/show), where parseArgs returns before callMethod, so the flag is silently ignored despite a successful command. This parser consistently rejects inert flags before those returns (cli.ts:943-974; see the corresponding short-circuit tests). Add an early validation that rejects --advertise-apps for commands that do not initialize an MCP connection.
…apps (#2471 review)
The Server Settings form resolved the UI extension's checkbox from the raw
registry default, so with no sandbox it showed "advertised" although the
client no longer declares it — and the modal's reconverge-to-default logic
made a true override impossible to save. Both now use the shared
isAdvertisedByDefault(ext, rendersApps), fed from App's sandbox URL.
The CLI rejected other connection-only flags ahead of its short-circuit
paths but accepted --advertise-apps there and ignored it; it is now
rejected on --list-stored-auth, --print-handoff and servers/list|show.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
Copilot round 2: 2 findings, both accepted and fixed in 2ebadf4. local:gate is green.
Server Settings checkbox ignores renderer-aware advertised default (inline): accepted. My round-1 change caused it. The toggle and the modal's override handling now share isAdvertisedByDefault with the builder, and App passes in whether the sandbox is available. Correction to my round-1 reply: I said a Server Settings override could still force the extension on when no sandbox is available. Before this fix it could not, because re-checking the box was treated as a return to the default and the override was dropped. It can now.
Reject --advertise-apps on commands without MCP connections (listed under "Previously missed", which has no thread): accepted. The flag is now rejected before the short-circuit returns (--list-stored-auth, --print-handoff, servers/list, servers/show), the same way --strict and --verify already are. This is covered by an it.each over all four paths; disabling the check fails all 4.
Screenshots: the only visible web change is the MCP Apps UI checkbox starting unchecked when the backend supplies no sandbox URL. The normal configuration looks the same as before, so I've left screenshots out.
Copilot round 3: approval recommended. The one new finding (the PR description was out of date) is fixed: the description now covers the sandbox-gated web behavior and all added tests. The other open item, the Server Settings checkbox, was fixed in 2ebadf4 and answered in its thread. No suppressed comments.
Review loop closed: this round held no code findings, and only the PR description changed since it ran, so another round would re-review unchanged code.
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
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.
Closes #2403
Problem
InspectorClientadvertisedio.modelcontextprotocol/uiby default in every client. The CLI and TUI cannot render an MCP App, yet they told servers they could — and servers use that advertisement to decide whether to return an App.Change
core/mcp/extensions.ts: the UI registry entry is markedrequiresAppRenderer. A new shared helper,isAdvertisedByDefault(ext, rendersApps), resolves the default: an entry that requires a renderer defaults off unless the client can render Apps.buildClientExtensionsuses it, and an explicitadvertisedExtensionsoverride still wins. Tasks and Skills are unaffected.InspectorClientOptions.rendersApps: new option, default false. Supplying anappElicitationrenderer implies it, since that is already a claim to host an App.appElicitationalready keys on (rendersApps: sandboxUrlRef.current !== undefined). With a sandbox, which is the normal setup, behavior is unchanged. Without one, the UI extension is no longer advertised by default.Apppasses the same sandbox signal (rendersApps) throughServerSettingsModaltoServerSettingsForm, and both useisAdvertisedByDefault. So the MCP Apps UI checkbox shows what the client will actually declare (unchecked by default with no sandbox), and checking it with no sandbox saves a realtrueoverride instead of dropping it as "back to the default".--advertise-apps, for probing a server that only exposes its App tools to a client that advertises App support (the issue's "explicit opt-in flag"). It is rejected on the commands that never connect (--list-stored-auth,--print-handoff,servers/list,servers/show), like--strictand--verify. It is documented in the CLI README next to--app-info.Tests
extensions.test.ts: existing cases now passrendersApps: true. New cases cover the non-rendering default (UI omitted),rendersApps: false, the explicit override, that Tasks and Skills are not gated, andisAdvertisedByDefaultover the whole registry.inspectorClient-app-elicitation.test.ts: a client with no renderer advertises no UI extension;rendersApps: trueadvertises the MIME type alone; an override turns it on.useConnectionLifecycle.test.tsx: the UI extension is advertised with a sandbox and absent without one.ServerSettingsForm.test.tsx/ServerSettingsModal.test.tsx: the checkbox state for both values ofrendersApps, an explicit override shown with no renderer, and the modal saving{ui: true}with no renderer.app-info.test.ts: end to end against an HTTP test server that gates a tool onio.modelcontextprotocol/ui. The tool is absent by default and present with--advertise-apps, and the flag is rejected on all four paths that never connect.Each fix was mutation-checked: reverting it fails its new tests.
npm run local:gatepasses.Screenshots: none. The only visible web change is the MCP Apps UI checkbox starting unchecked when the backend supplies no sandbox URL; with a sandbox, the UI looks the same as before.
🤖 Generated with Claude Code