Tracking issue. The work is split across three phase issues (each a self-contained PR that holds the ≥90% gate — tests ship with every phase, not at the end):
Follow-up (separate, upstream-blocked): remove the ext-apps SDK-v1 shims once @modelcontextprotocol/ext-apps ships a v2 peer (ext-apps#702) — see the stopgap section below. File that issue when Phase 3 lands its ui-advertisement cast.
⚠️ There may be overlap with #1579 (the Apps re-implementation wave) — check before implementing.
Stack: SDK V2 + New Spec — 10 of 10 (small but high-leverage; needs era model from card 3).
Formalize Extensions in the UI and align the existing MCP Apps work with the standardized capabilities.extensions mechanism.
Scope
- Extensions capability plumbing: declare Inspector-advertised extensions via constructor capabilities; read the server's via
getServerCapabilities()?.extensions. Handle graceful degradation.
- Extensions UI (new, small): display the server's
extensions map in Connection Info, and let users toggle which extensions the Inspector advertises — servers legitimately change tool registration based on client-declared extensions, so this is a real debugging knob.
- Apps alignment: advertise
io.modelcontextprotocol/ui with mimeTypes through the now-formalized capabilities.extensions. Generalize the existing EMA advertisement pattern in inspectorClient.ts (capabilities.extensions["io.modelcontextprotocol/enterprise-managed-authorization"]) to a first-class extensions map. Track the ext-apps 2026-01-26 spec / AppBridge version (core/mcp/apps.ts uses @modelcontextprotocol/ext-apps).
Key files
core/mcp/inspectorClient.ts (client capabilities / EMA precedent), core/mcp/apps.ts, clients/web/src/components/groups/ConnectionInfoContent/*, AppsScreen/AppRenderer (version alignment only).
Acceptance (whole issue — met when all three phases land)
- Server
extensions map visible in Connection Info; advertised-extensions toggle works and demonstrably changes server tool registration.
io.modelcontextprotocol/ui advertised via capabilities.extensions.
npm run ci green.
Ref: specification/v2_new_spec_impact.md §6.1, §6.2, §8.3(extensions), §9.3(Apps/Extensions).
Implementation status analysis (2026-07-22)
Audited v2/main. No PR has implemented this issue — the pieces that exist were built by neighboring cards (#1626 era model, #1631 tasks extension), not #1633. Roughly one-third done. Breakdown against the three scope items and the acceptance criteria:
| Scope item |
Status |
Evidence |
Server extensions map in Connection Info |
🟡 Partial |
formatExtensions() at ConnectionInfoContent.tsx:134, rendered at 224–225 — but gated behind {discoverResult && (…)} (line 213), so it's modern-era only. Reads discoverResult.capabilities.extensions directly; the issue's getServerCapabilities()?.extensions path (which also covers a legacy server's initialize-result extensions) is not wired. |
| Advertised-extensions toggle (changes tool registration) |
🔴 Missing entirely |
No control in ServerSettingsForm.tsx (its fields: protocol era, log level, auto-refresh, paginated lists, network log size, cwd/env/headers/metadata, timeouts) and no Switch/onChange in ConnectionInfoContent.tsx. This is the core debugging knob the issue asks for. |
| Generalize EMA/tasks → first-class extensions map |
🔴 Missing |
inspectorClient.ts:597-612 still hardcodes exactly two entries: EMA (io.modelcontextprotocol/enterprise-managed-authorization, gated on options.oauth?.enterpriseManaged) and tasks (TASKS_EXTENSION_KEY = "io.modelcontextprotocol/tasks" from modernTaskSchemas.ts:24), each via a bespoke capabilities.extensions = { ...spread }. No map, no option surface. |
Advertise io.modelcontextprotocol/ui w/ mimeTypes |
🔴 Missing entirely |
grep for modelcontextprotocol/ui returns zero hits in core/ and clients/web/src/. core/mcp/apps.ts only reads tool/resource _meta.ui; it never advertises the ui extension. |
ext-apps 2026-01-26 / AppBridge version alignment |
🔴 Not started |
Installed @modelcontextprotocol/ext-apps is 1.7.4, peering on SDK ^1.29.0 (see stopgap section below). |
Biggest true gaps: the advertised-extensions toggle (the point of the issue) and the io.modelcontextprotocol/ui advertisement.
Implementation plan (split into the three phase issues)
Full per-phase scope/acceptance lives in each sub-issue; summary:
Each PR carries its own tests and must hold the ≥90% per-file gate — there is no separate test phase.
⚠️ Stopgap code required — ext-apps is still on TS SDK v1 (^1.29.0), we are on SDK v2 (2.0.0-beta.5)
@modelcontextprotocol/ext-apps@1.7.4 peers on @modelcontextprotocol/sdk: ^1.29.0, but this repo runs @modelcontextprotocol/{client,core,server}@2.0.0-beta.5. The v1↔v2 type/runtime gap is already bridged by shims in the current codebase, every one tagged TODO: drop when ext-apps#702 ships a v2 peer:
core/mcp/apps.ts:26-28 — tool as Parameters<typeof getToolUiResourceUri>[0] (v1 Tool vs v2 Tool).
core/mcp/apps.ts:78-84 — UiMetaShape structural type standing in for ext-apps' McpUiToolMeta/McpUiResourceMeta (not importable under NodeNext).
clients/web/src/components/elements/AppRenderer/createAppBridgeFactory.ts:218-220 — client as unknown as ConstructorParameters<typeof AppBridge>[0] and the Implementation cast.
core/mcp/inspectorClient.ts:1698-1725 — the getAppRendererClient() Proxy that translates ext-apps' v1 schema-first setNotificationHandler(schema, handler) into SDK v2's method-string form.
New shims Phase 3 will likely add (all discardable once ext-apps ships a v2 peer):
- The
io.modelcontextprotocol/ui advertisement almost certainly needs mimeTypes in the shape ext-apps/the 2026-01-26 spec expects, sourced against v1-typed constants — expect a cast at the advertisement boundary similar to the apps.ts ones.
- Any place we hand ext-apps a v2
capabilities/extensions object it types as v1 will need the same single-boundary cast pattern.
Action: because these are throwaway bridges, file a follow-up issue to remove all ext-apps SDK-v1 shims when the package migrates to SDK v2.x (upstream ext-apps#702). It should enumerate the four existing shim sites above plus any added by Phase 3, and be closeable by a single sweep once @modelcontextprotocol/ext-apps publishes a v2-peer release. Do not try to eliminate the shims within these phases — the upstream dependency blocks it.
Stack: SDK V2 + New Spec — 10 of 10 (small but high-leverage; needs era model from card 3).
Formalize Extensions in the UI and align the existing MCP Apps work with the standardized
capabilities.extensionsmechanism.Scope
getServerCapabilities()?.extensions. Handle graceful degradation.extensionsmap in Connection Info, and let users toggle which extensions the Inspector advertises — servers legitimately change tool registration based on client-declared extensions, so this is a real debugging knob.io.modelcontextprotocol/uiwithmimeTypesthrough the now-formalizedcapabilities.extensions. Generalize the existing EMA advertisement pattern ininspectorClient.ts(capabilities.extensions["io.modelcontextprotocol/enterprise-managed-authorization"]) to a first-class extensions map. Track the ext-apps2026-01-26spec /AppBridgeversion (core/mcp/apps.tsuses@modelcontextprotocol/ext-apps).Key files
core/mcp/inspectorClient.ts(client capabilities / EMA precedent),core/mcp/apps.ts,clients/web/src/components/groups/ConnectionInfoContent/*,AppsScreen/AppRenderer(version alignment only).Acceptance (whole issue — met when all three phases land)
extensionsmap visible in Connection Info; advertised-extensions toggle works and demonstrably changes server tool registration.io.modelcontextprotocol/uiadvertised viacapabilities.extensions.npm run cigreen.Ref:
specification/v2_new_spec_impact.md§6.1, §6.2, §8.3(extensions), §9.3(Apps/Extensions).Implementation status analysis (2026-07-22)
Audited
v2/main. No PR has implemented this issue — the pieces that exist were built by neighboring cards (#1626 era model, #1631 tasks extension), not #1633. Roughly one-third done. Breakdown against the three scope items and the acceptance criteria:extensionsmap in Connection InfoformatExtensions()atConnectionInfoContent.tsx:134, rendered at 224–225 — but gated behind{discoverResult && (…)}(line 213), so it's modern-era only. ReadsdiscoverResult.capabilities.extensionsdirectly; the issue'sgetServerCapabilities()?.extensionspath (which also covers a legacy server's initialize-result extensions) is not wired.ServerSettingsForm.tsx(its fields: protocol era, log level, auto-refresh, paginated lists, network log size, cwd/env/headers/metadata, timeouts) and noSwitch/onChangeinConnectionInfoContent.tsx. This is the core debugging knob the issue asks for.inspectorClient.ts:597-612still hardcodes exactly two entries: EMA (io.modelcontextprotocol/enterprise-managed-authorization, gated onoptions.oauth?.enterpriseManaged) and tasks (TASKS_EXTENSION_KEY = "io.modelcontextprotocol/tasks"frommodernTaskSchemas.ts:24), each via a bespokecapabilities.extensions = { ...spread }. No map, no option surface.io.modelcontextprotocol/uiw/mimeTypesgrepformodelcontextprotocol/uireturns zero hits incore/andclients/web/src/.core/mcp/apps.tsonly reads tool/resource_meta.ui; it never advertises theuiextension.2026-01-26/ AppBridge version alignment@modelcontextprotocol/ext-appsis 1.7.4, peering on SDK ^1.29.0 (see stopgap section below).Biggest true gaps: the advertised-extensions toggle (the point of the issue) and the
io.modelcontextprotocol/uiadvertisement.Implementation plan (split into the three phase issues)
Full per-phase scope/acceptance lives in each sub-issue; summary:
capabilities.extensionsspreads ininspectorClient.ts(~597-612) into one map built from a shared registry; keepthis.clientCapabilitiescomplete (read back at ~1811 for the modern per-request envelope); add anadvertisedExtensionsclient option.advertisedExtensionstoInspectorServerSettings(types.ts:614, omit-when-default persist), renderSwitches inServerSettingsForm, and add atest-servers/config whosetools/listchanges on a client-declared extension so the "demonstrably changes tool registration" criterion is exercised.getServerCapabilities()?.extensionsso legacy shows them too (currently modern-only), show the Inspector's own advertised extensions, and advertiseio.modelcontextprotocol/uiwithmimeTypes.Each PR carries its own tests and must hold the ≥90% per-file gate — there is no separate test phase.
^1.29.0), we are on SDK v2 (2.0.0-beta.5)@modelcontextprotocol/ext-apps@1.7.4peers on@modelcontextprotocol/sdk: ^1.29.0, but this repo runs@modelcontextprotocol/{client,core,server}@2.0.0-beta.5. The v1↔v2 type/runtime gap is already bridged by shims in the current codebase, every one taggedTODO: drop when ext-apps#702 ships a v2 peer:core/mcp/apps.ts:26-28—tool as Parameters<typeof getToolUiResourceUri>[0](v1Toolvs v2Tool).core/mcp/apps.ts:78-84—UiMetaShapestructural type standing in for ext-apps'McpUiToolMeta/McpUiResourceMeta(not importable under NodeNext).clients/web/src/components/elements/AppRenderer/createAppBridgeFactory.ts:218-220—client as unknown as ConstructorParameters<typeof AppBridge>[0]and theImplementationcast.core/mcp/inspectorClient.ts:1698-1725— thegetAppRendererClient()Proxy that translates ext-apps' v1 schema-firstsetNotificationHandler(schema, handler)into SDK v2's method-string form.New shims Phase 3 will likely add (all discardable once ext-apps ships a v2 peer):
io.modelcontextprotocol/uiadvertisement almost certainly needsmimeTypesin the shape ext-apps/the 2026-01-26 spec expects, sourced against v1-typed constants — expect a cast at the advertisement boundary similar to theapps.tsones.capabilities/extensionsobject it types as v1 will need the same single-boundary cast pattern.Action: because these are throwaway bridges, file a follow-up issue to remove all ext-apps SDK-v1 shims when the package migrates to SDK v2.x (upstream
ext-apps#702). It should enumerate the four existing shim sites above plus any added by Phase 3, and be closeable by a single sweep once@modelcontextprotocol/ext-appspublishes a v2-peer release. Do not try to eliminate the shims within these phases — the upstream dependency blocks it.