Skip to content

feat(mcp): support MCP 2026-07-28 and MCP Apps in daemon WebShell #8968

Open

Description

@samuelhsin

What would you like to be added?

Please add first-class support for the MCP 2026-07-28 core specification and MCP Apps, with qwen daemon / qwen serve WebShell as the primary UI host.

Scope

1. MCP 2026-07-28 core client

  • Migrate Qwen Code's MCP client from SDK v1 to the official TypeScript SDK v2.
  • Support the stateless core: no required initialize / initialized exchange or Mcp-Session-Id, optional server/discover, and per-request client identity/capabilities in _meta.
  • Send the required MCP-Protocol-Version, Mcp-Method, and Mcp-Name HTTP headers.
  • Honor cache hints such as ttlMs and cacheScope on list/read results.
  • Support Multi Round-Trip Requests (MRTR): handle resultType: "input_required", collect user input/approval, and retry the original call with inputResponses.
  • Preserve compatibility with existing MCP servers during the migration where the SDK supports it.

2. MCP Apps host in daemon WebShell

  • Advertise the io.modelcontextprotocol/ui extension capability.
  • Preserve MCP tool UI metadata from tools/list, especially _meta.ui.resourceUri (plus the deprecated flat key during the compatibility window).
  • Fetch and validate ui:// resources, including text/html;profile=mcp-app.
  • Render Apps inline in a sandboxed iframe and enforce the resource's _meta.ui.csp and requested permissions.
  • Integrate the host-side AppBridge / postMessage protocol.
  • Forward tool input, partial input, result, cancellation, host context, theme, locale, styles, and size/lifecycle notifications to the App.
  • Handle App requests such as tools/call, ui/message, ui/update-model-context, open-link/download, and display-mode requests through the existing daemon permission boundary.
  • Carry App metadata and lifecycle state through daemon/WebShell event types so reload, resume, cancellation, and multi-workspace sessions remain correct.
  • Keep progressive fallback behavior: TUI, headless, ACP, and clients without UI support should still receive text/structured tool results.

Acceptance criteria

  1. Qwen Code can connect to a server that only speaks MCP 2026-07-28 and successfully discover/list/call tools without a protocol session.
  2. The daemon WebShell renders an official MCP Apps example such as @modelcontextprotocol/server-cohort-heatmap inline.
  3. The rendered App can call another MCP tool and send ui/update-model-context back to the host.
  4. An MRTR input_required response is surfaced in WebShell, and approval retries the original tool call with inputResponses.
  5. Theme/locale/context updates, resize, cancellation, teardown, reload, and session resume are covered.
  6. CSP, iframe sandboxing, tool permission checks, and untrusted HTML isolation have focused security tests.
  7. Legacy MCP tool-only servers continue to work.

Why is this needed?

MCP 2026-07-28 is now the current specification and is a breaking protocol update: it introduces a stateless core, header-based routing, MRTR, cacheable list results, and a formal extensions framework. MCP Apps is one of the official extensions in that framework.

Current Qwen Code main is not compatible yet:

  • packages/core/package.json still depends on @modelcontextprotocol/sdk ^1.30.0, while the 2026-07-28 support is delivered by SDK v2.
  • MCP discovery re-reads tools/list only to preserve tool annotations; it does not retain _meta.ui.resourceUri.
  • MCP tool results are transformed into a limited set of GenAI parts, so App-specific metadata/lifecycle information is not carried to a UI host.
  • WebShell tool message types carry ordinary content/diff/terminal data but no MCP App descriptor or lifecycle state.
  • WebShell has a static sandboxed HTML artifact preview, but it has no AppBridge, MCP Apps capability negotiation, or bidirectional host/App channel.

As a result, a 2026-07-28-only MCP server cannot be used correctly, and UI-enabled MCP tools cannot render or interact inside daemon WebShell.

Daemon WebShell is the most useful Qwen Code surface for MCP Apps because it already provides a browser UI, approvals, persistent sessions, workspace routing, and sandboxed HTML rendering. Data-heavy tools especially benefit from inline tables, charts, drill-down, reconciliation, and approval forms instead of reducing everything to text.

Additional context

References

I searched existing Qwen Code issues for MCP Apps, MCP UI, 2026-07-28, stateless MCP, and SDK v2 before filing this request and did not find an equivalent issue.

Activity

  1. samuelhsin commented on Aug 12, 2026

    @samuelhsin
    CollaboratorAuthor

    Ecosystem update (verified 2026-08-12)

    One important versioning correction: MCP Apps did not start with Core 2026-07-28. The first official MCP Apps extension specification is versioned 2026-01-26. It negotiates the io.modelcontextprotocol/ui extension through the legacy initialize flow; its example even uses Core protocolVersion: "2024-11-05". Core 2026-07-28 later formalized extension negotiation as part of the new stateless protocol. Therefore Core support and Apps Host support are two independent compatibility axes.

    Product / surface Core 2026-07-28 MCP Apps Host
    Codex 0.147.0 ✅ Opt-in support announced, including paginated discovery and MRTR ⚠️ Codex Desktop has an enable_mcp_apps feature under development and disabled by default; CLI/TUI is not a visual iframe host
    Claude Code 2.1.227 ✅ Present in the official release artifact (server/discover, MRTR input_required, and legacy fallback) ❌ Claude Code is not listed as an Apps host and its artifact contains no Apps UI/AppBridge markers
    Claude web / Desktop — ✅ Listed by the official MCP Apps docs as supported clients
    Qoder CLI 1.1.19 ❌ Latest official artifact still uses legacy initialization; no 2026-07-28 / server/discover markers ❌ No io.modelcontextprotocol/ui, ui://, or AppBridge markers
    Gemini CLI 0.54.4 ❌ Latest official package still uses the legacy flow ❌ No Apps host markers
    Qwen Code 0.21.10 / daemon WebShell ❌ Current core package still depends on @modelcontextprotocol/sdk ^1.30.0 ❌ WebShell can preview ordinary HTML artifacts in an iframe, but it does not implement Apps capability negotiation, ui:// resource loading, MCP AppBridge/postMessage, or Apps lifecycle/state propagation

    The official Apps overview currently also lists VS Code GitHub Copilot, Microsoft 365 Copilot, Goose, Postman, MCPJam, and Archestra.AI as supported Apps clients. This shows that MCP Apps already has a multi-client ecosystem independent of Core 2026-07-28.

    This issue should therefore keep two explicitly separate deliverables:

    1. Core 2026 compatibility: SDK v2/stateless discovery, headers, MRTR, cache hints, and legacy fallback.
    2. MCP Apps Host in daemon WebShell: advertise io.modelcontextprotocol/ui; preserve _meta.ui.resourceUri; load ui:// + text/html;profile=mcp-app; render through the existing sandbox iframe; implement the host-side AppBridge, CSP/permissions, tool-call proxy, lifecycle, reload/resume, and fallback behavior.

    References:

  2. yiliang114 commented on Sep 24, 2026

    @yiliang114
    Collaborator

    Status re-checked against current main (ca8146a). Leaving this open because some items remain.

    Resolved / no longer applicable

    Still open

    • MRTR (input_required / inputResponses) and ui/update-model-context (acceptance items 3 and 4): no occurrences on main.
    • HTTP/SSE transports still use the legacy handshake.
  3. BigDaddy1337 commented on Oct 18, 2026

    @BigDaddy1337
    Contributor

    Concrete repro of the MCP Apps / deferred-form gap from a Desktop (Web Shell) session, desktop-v0.25.2 runtime:

    • The GitHub MCP server defers its write tools to an interactive form: pkg/github/ui_capability.go → shouldDeferToForm() returns true when the client advertises the io.modelcontextprotocol/ui capability, and the handler then returns the "An interactive form has been shown to the user ... the issue has NOT been created yet" stub without making the API call (pkg/github/issues.go, pkg/github/pullrequests.go).
    • The shipped Desktop runtime does advertise that capability: the io.modelcontextprotocol/ui and mcp_app strings are present in the bundled chunks of desktop-v0.25.2.
    • Web Shell has an Apps host at packages/web-shell/client/components/messages/McpApp.tsx, but it mounts the iframe only when the tool display carries an object with type: 'mcp_app' and a non-empty html (plus serverName, resourceUri, fallbackText, toolResult, toolArguments); otherwise it renders fallbackText.
    • Observed: issue_write returned the deferred-form stub as a tool error with plain text and no mcp_app display. Nothing rendered, the write silently never happened, and there is no way for the user to complete or cancel it.

    So the failure mode is a silent dead end rather than a visible "form could not be rendered": advertising io.modelcontextprotocol/ui makes servers route writes to a form the host never mounts, and neither the model nor the user gets an actionable error. Rendering fallbackText (or explicitly declining the deferral) would at least surface the state.

    This sits on the same surface as the MRTR input_required work in scope item 1 / acceptance criterion 4 — flagging the display-less deferral case so the surfacing path can cover it too.

  4. Paraphern commented on Oct 22, 2026

    @Paraphern

    The capability matrix above is also why one pin per server isn't enough: as @BigDaddy1337's repro shows, the GitHub server serves a different surface when the client advertises io.modelcontextprotocol/ui — write tools deferred to forms. Capability-dependent surfaces need capability-aware pinning: pin what a client of your shape negotiates, re-diff after any runtime/Desktop update, and the regression shows up as contract drift instead of a mystery behavior change.

    We built the adjacent case into our CLI (rugsnare): scan --chameleon re-lists one server as claude-desktop/cursor/openai-mcp and fails when the surfaces differ per client. The capability axis is the same mechanism one layer over.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions