Skip to content

spec(draft): add split display mode - #739

Open
caseprince wants to merge 1 commit into
modelcontextprotocol:mainfrom
caseprince:case/split-display-mode-prototype
Open

spec(draft): add split display mode#739
caseprince wants to merge 1 commit into
modelcontextprotocol:mainfrom
caseprince:case/split-display-mode-prototype

Conversation

@caseprince

@caseprince caseprince commented Aug 4, 2026

Copy link
Copy Markdown

Motivation and Context

Rich Interactive Views (spreadsheets, maps, dashboards, CAD viewers) scroll out of sight as a conversation continues, so users lose the UI they're actively working with. #684 asks for a pinned/split-screen presentation; #412 wants the same outcome via pip/side panels. The existing inline-alternative modes don't satisfy these use-cases: fullscreen hides the conversation, and pips floating overlay is too small for complex, information-dense visualizations or interfaces.

This is a runnable design prototype - happy to redirect it into an Extensions Track SEP if maintainers prefer.

Relates to #684, #412, and #430.

Proposed semantics

split: The View is displayed in a persistent, non-overlapping region while the host's primary conversational interface remains visible and interactive.

  • The host controls orientation, placement, dimensions, resizing, and how many split Views it permits.
  • Negotiation is unchanged: hosts that don't support split omit it from availableDisplayModes, and apps accept whatever mode the host returns.
  • Entering or leaving split SHOULD NOT recreate the View — it's a presentation change, and View state SHOULD survive the transition.
  • Out of scope: reusing Views across separate tool calls (that remains Re-usable views #430); each tool call still renders a new View instance.

Prototype Screenshot

Screenshot 2026-08-04 095702

Open question: how should a new display mode be introduced?

Adding a mode looks additive, but it raises two distinct compatibility questions with different roots:

  • App declaring split → older host. The 2026-01-26 spec defines the app's declared mode list as a fixed set of known values, so a host that checks strictly may reject the initialization request outright — hosts built on this SDK do. Independent implementations may be more lenient; failure isn't universal, but the spec permits it.
  • Host advertising split → older app. Here the spec is already forward-compatible (the host's advertised list is string[]), but the SDK restricts it to the known modes. Apps built with existing SDK releases therefore reject a spec-valid initialization response from any host advertising an unknown mode — even apps that never use display modes. (Reproduced with an in-memory host/app pair: connect() rejects during initialization.)

This PR also widens what the SDK accepts while LATEST_PROTOCOL_VERSION stays 2026-01-26, so two SDK releases claiming the same protocol version would disagree about which messages are valid — and with the current SDK, a version bump alone wouldn't fix the first direction, since messages are validated before the version is selected.

For maintainers: should new modes arrive via experimental capabilities or a new protocol version? Should the app's declared list also become forward-compatible? And — separately from split — should the SDK's host-advertised list be loosened to the string[] the spec already defines? Happy to rework this PR to whichever shape is preferred.

Changes

  • src/spec.types.ts: add "split" to McpUiDisplayMode; src/generated/* regenerated via npm run generate:schemas
  • specification/draft/apps.mdx: document the mode (dated stable spec untouched)
  • examples/debug-server: add a "Split" display-mode button
  • examples/basic-host: advertise split and dock the View in a resizable right-hand region; only the panel's className changes, so the iframe never remounts and View state survives inline ↔ split. Demonstrates one active split View; multi-view arbitration is not implemented
  • Tests: unit coverage for negotiation, plus an E2E spec driving debug-server inline → split → inline and asserting both surfaces stay visible, interactive, and non-overlapping, and that View state survives

Testing

  • npm run build, npm test (375 pass), npm run prettier, typedoc validation — all green
  • EXAMPLE=debug-server npx playwright test tests/e2e/display-mode-split.spec.ts
  • EXAMPLE=debug-server npx playwright test tests/e2e/servers.spec.ts ✅ (existing goldens still match)

To try it: npm start, pick Debug MCP App Server, Call Tool, then click Split. Drag the region's left edge to resize.

AI disclosure

Written primarily by Claude Code (Claude Fable 5) from my design direction and cross-checked with Codex (gpt-5.6-sol).
I reviewed the full diff and test results per the AI contribution policy.

🤖 Generated with Claude Code

@caseprince
caseprince force-pushed the case/split-display-mode-prototype branch 3 times, most recently from f5cb287 to a2a5f0d Compare August 4, 2026 14:43
Add a fourth McpUiDisplayMode, "split": the View is displayed in a
persistent, non-overlapping region while the host's primary
conversational interface remains visible and interactive. This keeps
interactive Views (spreadsheets, maps, dashboards) referenceable as the
conversation scrolls on, instead of losing them off-screen.

- spec.types.ts + draft spec: define "split" semantics and non-goals
- regenerate Zod/JSON schemas via `npm run generate:schemas`
- debug-server: add a "Split" display-mode control
- basic-host: advertise "split" and render the View in a resizable,
  docked region without remounting the iframe, so View state survives
  inline <-> split transitions
- unit + E2E coverage for negotiation and transitions

Prototype for modelcontextprotocol#684; relates to modelcontextprotocol#412 and modelcontextprotocol#430.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@caseprince
caseprince force-pushed the case/split-display-mode-prototype branch from a2a5f0d to a940210 Compare August 4, 2026 15:19
@caseprince
caseprince marked this pull request as ready for review August 4, 2026 18:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant