ext-apps 2.0 and the 15 example server packages are built on the MCP
TypeScript SDK 2.0 split packages, so the stateless example mounts in
src/modules/example-apps now connect each server to
NodeStreamableHTTPServerTransport from @modelcontextprotocol/node; the
factory map is typed as the 2.0 McpServer. The rest of this host (OAuth,
the root /mcp handlers, Redis transport) stays on @modelcontextprotocol/sdk
1.29, which installs alongside the 2.0 packages. zod moves to 4 for the
whole tree: ext-apps 2.0 peers on ^4.2.0, sdk 1.29 accepts ^3.25 || ^4.0,
and the host already imports zod/v4. The hello-world View takes
CallToolResult from @modelcontextprotocol/client.
Bumps @modelcontextprotocol/ext-apps and the example server packages to
1.7.5. Notably picks up server-lazy-auth's larger consent-button touch
targets so the /lazy-auth flow is tappable on mobile
(modelcontextprotocol/ext-apps#714).
- Build the well-known rewrite regex from LAZY_AUTH_SLUG so it can't drift
from the mount path if the slug changes.
- Clarify in the docstring that an explicit PUBLIC_URL must include the
/lazy-auth mount path (the package advertises it verbatim).
- Tests: clear/restore ambient PUBLIC_URL around the integration server
(was a latent flake); add unit coverage for the PUBLIC_URL derivation
(trailing-slash strip, no-trailing-slash, explicit-wins, unset cases);
add a public tool-call success case and an invalid-token 401 case.
Mounts @modelcontextprotocol/server-lazy-auth as an additional example,
served at /lazy-auth/mcp alongside the other example MCP App servers.
Unlike the other examples (plain createServer() factories behind the
stateless handler), lazy-auth's value is its HTTP layer: public tools
work unauthenticated, protected tools answer 401 + WWW-Authenticate, and
a built-in mock OAuth authorization server completes the flow. So it
mounts its full Express app (createApp()) under /lazy-auth.
- New src/modules/example-apps/lazy-auth.ts mounts the app before the
host middleware and adds the RFC 8414/9728 path-insertion well-known
rewrite (/.well-known/oauth-authorization-server/lazy-auth -> into the
mount) that SDK clients require for discovery under a base path.
- PUBLIC_URL for the example is derived from this server's own BASE_URI,
so no extra deploy-time configuration is needed; an explicit PUBLIC_URL
still wins (e.g. a tunnel).
- Integration test covers the full flow: public initialize/tools/list,
401 on the protected tool, mount-prefixed discovery metadata, and the
PKCE -> token -> authed get_secret round trip.
ext-apps@1.7.x peers on @modelcontextprotocol/sdk ^1.29.0, which
required bumping the pinned sdk from 1.24.2 and adapting to its
StreamableHTTPServerTransport refactor:
- redisTransport: sessionId is now a readonly getter on the Node
wrapper; inject it (and _initialized) on the underlying web-standard
transport so resumed sessions validate. Also guard message.id which
is now optional on JSONRPCMessage.
- shttp.integration.test: handleRequest now routes through
@hono/node-server, so the mock IncomingMessage needs url/host/
rawHeaders/on/off/resume, and the session-id header now arrives via
writeHead instead of setHeader.
The stateless /:slug/mcp handler creates a fresh McpServer and
StreamableHTTPServerTransport on every request but never closed them,
leaking memory under load. Register a 'close' listener (fires on both
normal completion and client abort mid-SSE) to release them.
- Bump @modelcontextprotocol/ext-apps from ^1.1.0 to ^1.1.1
- Bump all @modelcontextprotocol/server-* packages from ^1.1.0 to ^1.1.1
- Add new @modelcontextprotocol/server-debug package at ^1.1.1
- Wire up debug server in example-apps module at /debug/mcp
Remove bearer auth middleware from all /:slug/mcp routes (pdf, map, etc.)
so they are publicly accessible without an OAuth token. The root /mcp
endpoint retains its existing bearer auth requirement.
https://claude.ai/code/session_019bG1wzY84JA7LbpkybddP9
- Update @modelcontextprotocol/ext-apps to ^1.0.1
- Update all @modelcontextprotocol/server-* packages to ^1.0.1
- Pin @modelcontextprotocol/sdk to 1.24.2 to avoid SDK upgrades from transitive deps
- Pin @types/express-serve-static-core to 5.1.0 for type compatibility
Claude-Generated-By: Claude Code (cli/claude-opus-4-5=100%)
Claude-Steers: 1
Claude-Permission-Prompts: 0
Claude-Escapes: 0
Add INFO-level logging to both the stateful SHTTP handler and the
stateless example-apps handler to show the full client capabilities
sent during MCP initialization, including any extensions like
io.modelcontextprotocol/ui.
This helps verify that clients are correctly sending UI extension
capabilities during the initialization handshake.
Remove trailing slash from baseUri before constructing example server
URLs to avoid URLs like "example.com//budget-allocator/mcp".
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Each MCP App example server now has a copy button that copies the
full URL (including domain) to clipboard for easy pasting into Claude.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The MCP server packages require Node 20.11+ due to use of
import.meta.filename. This .nvmrc ensures developers use the
correct Node version.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Address PR feedback:
- Remove session store and session management
- Use stateless mode (sessionIdGenerator: undefined)
- Each request creates a fresh server instance
- Remove user-controlled format string in error message
- Simplify handler logic significantly
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Wire up 13 MCP Apps servers from the @modelcontextprotocol/server-* packages:
- budget-allocator: Interactive budget allocation UI
- cohort-heatmap: Customer retention heatmap
- customer-segmentation: Scatter chart with clustering
- map: Interactive 3D globe viewer (CesiumJS)
- pdf: Interactive PDF viewer
- scenario-modeler: SaaS business projections dashboard
- shadertoy: Real-time GLSL shader renderer
- sheet-music: ABC notation to sheet music visualizer
- system-monitor: Real-time OS metrics display
- threejs: 3D scene renderer
- transcript: Live speech transcription
- video-resource: Binary video streaming via MCP resources
- wiki-explorer: Wikipedia link graph visualization
Each server is mounted at /{slug}/mcp and shares the same OAuth
authentication as the main MCP server.
Also updates the splash page to dynamically list all available
example servers.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Update @modelcontextprotocol/ext-apps to 0.4.0
- Use new nested format `_meta.ui.resourceUri` in tool definition
- Remove resourceUri from tool result (only needed in tool definition)
- Add example structuredContent and _meta in tool result for demo
Include the MCP Apps UI resource in the resources list so clients
can discover it via resources/list.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implements a simple MCP Apps tool that returns an interactive React UI:
- Add `mcp_apps_hello_world` tool with `_meta.ui/resourceUri` metadata
- Add resource handler for `ui://hello-world/app.html` returning HTML
- Create React app using `@modelcontextprotocol/ext-apps/react` hooks
- Add Vite build tooling to bundle React apps into single HTML files
The tool demonstrates the MCP Apps extension (SEP-1865) which allows
MCP servers to return interactive UI that runs in the client.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>