Skip to content

[Tracking] Extensions capability UI + MCP Apps (io.modelcontextprotocol/ui) alignment #1633

Description

@cliffhall

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-28tool as Parameters<typeof getToolUiResourceUri>[0] (v1 Tool vs v2 Tool).
  • core/mcp/apps.ts:78-84UiMetaShape structural type standing in for ext-apps' McpUiToolMeta/McpUiResourceMeta (not importable under NodeNext).
  • clients/web/src/components/elements/AppRenderer/createAppBridgeFactory.ts:218-220client 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.

Metadata

Metadata

Assignees

Labels

v2Issues and PRs for v2

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions