Conversation
Make example MCP App servers publishable to npm under the @modelcontextprotocol scope: - server-basic-react - server-basic-vanillajs - server-budget-allocator - server-cohort-heatmap - server-customer-segmentation - server-scenario-modeler - server-system-monitor - server-threejs - server-wiki-explorer Changes: - Remove `private: true` from example package.json files - Add proper npm metadata (description, repository, license, files) - Update ext-apps dependency from relative to ^0.2.2 - Copy server-utils.ts into each package for standalone use - Add publish-examples job to npm-publish.yml workflow The examples will be published automatically when a GitHub release is created, after the main SDK package is published. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
@modelcontextprotocol/ext-apps
@modelcontextprotocol/server-basic-react
@modelcontextprotocol/server-basic-vanillajs
@modelcontextprotocol/server-budget-allocator
@modelcontextprotocol/server-cohort-heatmap
@modelcontextprotocol/server-customer-segmentation
@modelcontextprotocol/server-scenario-modeler
@modelcontextprotocol/server-system-monitor
@modelcontextprotocol/server-threejs
@modelcontextprotocol/server-wiki-explorer
commit: |
Resolve conflicts by: - Keep server-utils.ts next to server.ts (not in src/) - Simplify server-utils.ts to stateless HTTP only (no SSE) - Keep main() with explicit --stdio handling in server.ts - Add integration-server from main for E2E testing - Add npm start alias from main
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
ochafik
left a comment
There was a problem hiding this comment.
Thanks @jerome3o-anthropic !
Merged main and resolved conflicts. Key changes after #182:
- Reverted the server-utils.ts location back to next to server.ts (not in src/)
- Simplified server-utils.ts to stateless HTTP only (removed SSE legacy endpoints)
- Kept main() with explicit --stdio handling in each server.ts
@jonathanhefner I reverted the inline stdio handling in server-utils.ts from #182 — IMO argv checking doesn't belong in a shared helper. Each server's main()
should own that decision, keeping server-utils.ts focused on just the HTTP transport setup.
Update golden screenshots for basic-react and basic-vanillajs after the tool output was simplified from JSON to plain text in #182. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
In that case, why not make it boolean parameter? e.g.: startServer(createServer, process.argv.includes("--stdio"));
// or
startServer(createServer, { stdio: process.argv.includes("--stdio") }); |
| // Two-part registration: tool + resource, tied together by the resource URI. | ||
| const resourceUri = "ui://get-time/mcp-app.html"; | ||
|
|
||
| // Register a tool with UI metadata. When the host calls this tool, it reads | ||
| // `_meta[RESOURCE_URI_META_KEY]` to know which resource to fetch and render | ||
| // as an interactive UI. | ||
| registerAppTool(server, | ||
| "get-time", | ||
| { | ||
| title: "Get Time", | ||
| description: "Returns the current server time as an ISO 8601 string.", | ||
| description: "Returns the current server time.", | ||
| inputSchema: {}, | ||
| _meta: { [RESOURCE_URI_META_KEY]: resourceUri }, | ||
| }, | ||
| async (): Promise<CallToolResult> => { | ||
| const time = new Date().toISOString(); | ||
| return { content: [{ type: "text", text: time }] }; | ||
| return { content: [{ type: "text", text: new Date().toISOString() }] }; | ||
| }, | ||
| ); | ||
|
|
||
| // Register the resource, which returns the bundled HTML/JavaScript for the UI. |
There was a problem hiding this comment.
Since these are educational examples, I would like to preserve these comments.
There was a problem hiding this comment.
Did you mean restored in this PR or elsewhere? They still seem to be removed in the current diff for this PR.
| // Two-part registration: tool + resource, tied together by the resource URI. | ||
| const resourceUri = "ui://get-time/mcp-app.html"; | ||
|
|
||
| // Register a tool with UI metadata. When the host calls this tool, it reads | ||
| // `_meta[RESOURCE_URI_META_KEY]` to know which resource to fetch and render | ||
| // as an interactive UI. | ||
| // MCP Apps require two-part registration: a tool (what the LLM calls) and a | ||
| // resource (the UI it renders). The `_meta` field on the tool links to the | ||
| // resource URI, telling hosts which UI to display when the tool executes. | ||
| registerAppTool(server, | ||
| "get-time", | ||
| { | ||
| title: "Get Time", | ||
| description: "Returns the current server time as an ISO 8601 string.", | ||
| inputSchema: {}, | ||
| _meta: { [RESOURCE_URI_META_KEY]: resourceUri }, | ||
| _meta: { [RESOURCE_URI_META_KEY]: RESOURCE_URI }, | ||
| }, | ||
| async (): Promise<CallToolResult> => { | ||
| const time = new Date().toISOString(); | ||
| return { content: [{ type: "text", text: time }] }; | ||
| return { | ||
| content: [{ type: "text", text: JSON.stringify({ time }) }], | ||
| }; | ||
| }, | ||
| ); | ||
|
|
||
| // Register the resource, which returns the bundled HTML/JavaScript for the UI. | ||
| registerAppResource(server, | ||
| resourceUri, | ||
| resourceUri, | ||
| RESOURCE_URI, | ||
| RESOURCE_URI, | ||
| { mimeType: RESOURCE_MIME_TYPE }, | ||
| async (): Promise<ReadResourceResult> => { | ||
| const html = await fs.readFile(path.join(DIST_DIR, "mcp-app.html"), "utf-8"); | ||
|
|
||
| return { | ||
| contents: [ | ||
| { uri: resourceUri, mimeType: RESOURCE_MIME_TYPE, text: html }, | ||
| // Per the MCP App specification, "text/html;profile=mcp-app" signals | ||
| // to the Host that this resource is indeed for an MCP App UI. | ||
| { uri: RESOURCE_URI, mimeType: RESOURCE_MIME_TYPE, text: html }, |
There was a problem hiding this comment.
It looks like there was a bad rebase. This is reverting some of the changes I made in #182.
@jonathanhefner The signature would be awkard tbh... If we want to make it real clean, should probably look like: export type ServerOptions = {
name?: string;
} & (
| { type: 'streamable-http', port: number, path?: string } // default path is /mcp
| { type: 'stdio' }
);But then it's more syntax to instantiate it... Wdyt? |
I'm not sure I see the value in providing I also think overriding the Anyway, if you prefer to have separate functions, that's fine. I would suggest something like: process.argv.includes("--stdio") ?
startStdioServer(createServer) :
startHttpServer(createServer); You could add a port argument to |
…publishing pattern - Move server-utils.ts from src/ to root level - Add npm publishing metadata (scoped name, repository, license, files) - Change ext-apps dependency from local to versioned ^0.2.2 - Update server.ts to handle stdio mode inline
Added 'nasa-earth' option - NASA ISS Earth observations (6.4MB). Source: archive.org/details/NASA-Ultra-High-Definition (public domain)
Add publishing metadata for: - @modelcontextprotocol/server-basic-preact - @modelcontextprotocol/server-basic-solid - @modelcontextprotocol/server-basic-svelte - @modelcontextprotocol/server-basic-vue Changes: - Move server-utils.ts from src/ to root - Add npm publishing metadata - Update ext-apps dep to versioned ^0.2.2 - Add stdio mode support in main()
This fixes the Windows ARM64 CI build failure caused by npm's optional dependency bug. The package.json was missing this platform-specific rollup binding.
a3267bb to
061caa6
Compare
Merge latest changes from main including: - Vue, Svelte, Preact, and Solid basic server examples (#141) - safeAreaInsets support (#202) - E2E test fixes (#206) - npm publishing for examples (#184) - ui.resourceUri optional (#210) - Method names as consts (#192) - toolInfo.id optional (#216) - PostMessageTransport security fixes (#207, #208) - Server-utils.ts refactoring
PR modelcontextprotocol#184 accidentally removed/reverted educational comments from `basic-server-react` and `basic-server-vanillajs` that were established in PR modelcontextprotocol#182. This restores consistency with the other basic-server examples (Vue, Svelte, Preact, Solid). Changes: - Add back the three-comment pattern explaining two-part registration - Restore full tool description ("as an ISO 8601 string") - Change vanillajs to return plain text instead of JSON (matching modelcontextprotocol#182) - Use local `resourceUri` variable instead of top-level constant Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
PR modelcontextprotocol#184 accidentally removed/reverted educational comments from `basic-server-react` and `basic-server-vanillajs` that were established in PR modelcontextprotocol#182. This restores consistency with the other basic-server examples (Vue, Svelte, Preact, Solid). Changes: - Add back the three-comment pattern explaining two-part registration - Restore full tool description ("as an ISO 8601 string") - Change vanillajs to return plain text instead of JSON (matching modelcontextprotocol#182) - Use local `resourceUri` variable instead of top-level constant Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Summary
Make example MCP App servers publishable to npm under the
@modelcontextprotocolscope. This enables users to run examples directly vianpxwithout cloning the repo.New packages (15):
@modelcontextprotocol/server-basic-preact@modelcontextprotocol/server-basic-react@modelcontextprotocol/server-basic-solid@modelcontextprotocol/server-basic-svelte@modelcontextprotocol/server-basic-vanillajs@modelcontextprotocol/server-basic-vue@modelcontextprotocol/server-budget-allocator@modelcontextprotocol/server-cohort-heatmap@modelcontextprotocol/server-customer-segmentation@modelcontextprotocol/server-scenario-modeler@modelcontextprotocol/server-sheet-music@modelcontextprotocol/server-system-monitor@modelcontextprotocol/server-threejs@modelcontextprotocol/server-video-resource@modelcontextprotocol/server-wiki-explorerChanges:
private: truefrom example package.json files../..) to versioned (^0.2.2)server-utils.tsfromsrc/to package root for standalone use--stdioflag) to each serverpublish-examplesjob tonpm-publish.ymlworkflow (matrix-based, parallel)@rollup/rollup-win32-arm64-msvcto optionalDependenciesThe examples will be published automatically when a GitHub release is created.
Test plan
npm run examples:buildnpm publish --workspace examples/basic-server-react --dry-run🤖 Generated with Claude Code