diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 37936222..2813b2dd 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -40,6 +40,465 @@ Or build and run examples: npm run examples:start ``` +### With MCP Clients + +To use these examples with MCP clients that support the stdio transport (such as Claude Desktop or VS Code), add this MCP server configuration to your client's settings: + +
+MCP client configuration for all examples (using stdio) + +```json +{ + "mcpServers": { + "basic-react": { + "command": "npx", + "args": [ + "-y", + "--silent", + "--registry=https://registry.npmjs.org/", + "@modelcontextprotocol/server-basic-react", + "--stdio" + ] + }, + "basic-vanillajs": { + "command": "npx", + "args": [ + "-y", + "--silent", + "--registry=https://registry.npmjs.org/", + "@modelcontextprotocol/server-basic-vanillajs", + "--stdio" + ] + }, + "basic-vue": { + "command": "npx", + "args": [ + "-y", + "--silent", + "--registry=https://registry.npmjs.org/", + "@modelcontextprotocol/server-basic-vue", + "--stdio" + ] + }, + "basic-svelte": { + "command": "npx", + "args": [ + "-y", + "--silent", + "--registry=https://registry.npmjs.org/", + "@modelcontextprotocol/server-basic-svelte", + "--stdio" + ] + }, + "basic-preact": { + "command": "npx", + "args": [ + "-y", + "--silent", + "--registry=https://registry.npmjs.org/", + "@modelcontextprotocol/server-basic-preact", + "--stdio" + ] + }, + "basic-solid": { + "command": "npx", + "args": [ + "-y", + "--silent", + "--registry=https://registry.npmjs.org/", + "@modelcontextprotocol/server-basic-solid", + "--stdio" + ] + }, + "budget-allocator": { + "command": "npx", + "args": [ + "-y", + "--silent", + "--registry=https://registry.npmjs.org/", + "@modelcontextprotocol/server-budget-allocator", + "--stdio" + ] + }, + "cohort-heatmap": { + "command": "npx", + "args": [ + "-y", + "--silent", + "--registry=https://registry.npmjs.org/", + "@modelcontextprotocol/server-cohort-heatmap", + "--stdio" + ] + }, + "customer-segmentation": { + "command": "npx", + "args": [ + "-y", + "--silent", + "--registry=https://registry.npmjs.org/", + "@modelcontextprotocol/server-customer-segmentation", + "--stdio" + ] + }, + "map": { + "command": "npx", + "args": [ + "-y", + "--silent", + "--registry=https://registry.npmjs.org/", + "@modelcontextprotocol/server-map", + "--stdio" + ] + }, + "pdf": { + "command": "npx", + "args": [ + "-y", + "--silent", + "--registry=https://registry.npmjs.org/", + "@modelcontextprotocol/server-pdf", + "--stdio" + ] + }, + "scenario-modeler": { + "command": "npx", + "args": [ + "-y", + "--silent", + "--registry=https://registry.npmjs.org/", + "@modelcontextprotocol/server-scenario-modeler", + "--stdio" + ] + }, + "shadertoy": { + "command": "npx", + "args": [ + "-y", + "--silent", + "--registry=https://registry.npmjs.org/", + "@modelcontextprotocol/server-shadertoy", + "--stdio" + ] + }, + "sheet-music": { + "command": "npx", + "args": [ + "-y", + "--silent", + "--registry=https://registry.npmjs.org/", + "@modelcontextprotocol/server-sheet-music", + "--stdio" + ] + }, + "system-monitor": { + "command": "npx", + "args": [ + "-y", + "--silent", + "--registry=https://registry.npmjs.org/", + "@modelcontextprotocol/server-system-monitor", + "--stdio" + ] + }, + "threejs": { + "command": "npx", + "args": [ + "-y", + "--silent", + "--registry=https://registry.npmjs.org/", + "@modelcontextprotocol/server-threejs", + "--stdio" + ] + }, + "transcript": { + "command": "npx", + "args": [ + "-y", + "--silent", + "--registry=https://registry.npmjs.org/", + "@modelcontextprotocol/server-transcript", + "--stdio" + ] + }, + "video-resource": { + "command": "npx", + "args": [ + "-y", + "--silent", + "--registry=https://registry.npmjs.org/", + "@modelcontextprotocol/server-video-resource", + "--stdio" + ] + }, + "wiki-explorer": { + "command": "npx", + "args": [ + "-y", + "--silent", + "--registry=https://registry.npmjs.org/", + "@modelcontextprotocol/server-wiki-explorer", + "--stdio" + ] + }, + "qr": { + "command": "uv", + "args": [ + "run", + "/path/to/ext-apps/examples/qr-server/server.py", + "--stdio" + ] + }, + "say": { + "command": "uv", + "args": [ + "run", + "--default-index", + "https://pypi.org/simple", + "https://raw.githubusercontent.com/modelcontextprotocol/ext-apps/refs/heads/main/examples/say-server/server.py", + "--stdio" + ] + } + } +} +``` + +
+ +> [!NOTE] +> The `qr` server requires cloning the repository first. See [qr-server README](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/qr-server) for details. + +### Local Development + +To test local modifications with MCP clients, first clone and install the repository: + +```bash +git clone https://github.com/modelcontextprotocol/ext-apps.git +cd ext-apps +npm install +``` + +Then configure your MCP client to build and run the local server. Replace `~/code/ext-apps` with your actual clone path. + +Most example servers have a `start:stdio` script that builds and launches in stdio mode. Use `npm --silent run start:stdio` for these: + +
+MCP client configuration for local development (all examples) + +```json +{ + "mcpServers": { + "basic-react": { + "command": "npm", + "args": [ + "--silent", + "--prefix", + "~/code/ext-apps/examples/basic-server-react", + "run", + "start:stdio" + ] + }, + "basic-vanillajs": { + "command": "npm", + "args": [ + "--silent", + "--prefix", + "~/code/ext-apps/examples/basic-server-vanillajs", + "run", + "start:stdio" + ] + }, + "basic-vue": { + "command": "npm", + "args": [ + "--silent", + "--prefix", + "~/code/ext-apps/examples/basic-server-vue", + "run", + "start:stdio" + ] + }, + "basic-svelte": { + "command": "npm", + "args": [ + "--silent", + "--prefix", + "~/code/ext-apps/examples/basic-server-svelte", + "run", + "start:stdio" + ] + }, + "basic-preact": { + "command": "npm", + "args": [ + "--silent", + "--prefix", + "~/code/ext-apps/examples/basic-server-preact", + "run", + "start:stdio" + ] + }, + "basic-solid": { + "command": "npm", + "args": [ + "--silent", + "--prefix", + "~/code/ext-apps/examples/basic-server-solid", + "run", + "start:stdio" + ] + }, + "budget-allocator": { + "command": "npm", + "args": [ + "--silent", + "--prefix", + "~/code/ext-apps/examples/budget-allocator-server", + "run", + "start:stdio" + ] + }, + "cohort-heatmap": { + "command": "npm", + "args": [ + "--silent", + "--prefix", + "~/code/ext-apps/examples/cohort-heatmap-server", + "run", + "start:stdio" + ] + }, + "customer-segmentation": { + "command": "npm", + "args": [ + "--silent", + "--prefix", + "~/code/ext-apps/examples/customer-segmentation-server", + "run", + "start:stdio" + ] + }, + "map": { + "command": "npm", + "args": [ + "--silent", + "--prefix", + "~/code/ext-apps/examples/map-server", + "run", + "start:stdio" + ] + }, + "pdf": { + "command": "npm", + "args": [ + "--silent", + "--prefix", + "~/code/ext-apps/examples/pdf-server", + "run", + "start:stdio" + ] + }, + "scenario-modeler": { + "command": "npm", + "args": [ + "--silent", + "--prefix", + "~/code/ext-apps/examples/scenario-modeler-server", + "run", + "start:stdio" + ] + }, + "shadertoy": { + "command": "npm", + "args": [ + "--silent", + "--prefix", + "~/code/ext-apps/examples/shadertoy-server", + "run", + "start:stdio" + ] + }, + "sheet-music": { + "command": "npm", + "args": [ + "--silent", + "--prefix", + "~/code/ext-apps/examples/sheet-music-server", + "run", + "start:stdio" + ] + }, + "system-monitor": { + "command": "npm", + "args": [ + "--silent", + "--prefix", + "~/code/ext-apps/examples/system-monitor-server", + "run", + "start:stdio" + ] + }, + "threejs": { + "command": "npm", + "args": [ + "--silent", + "--prefix", + "~/code/ext-apps/examples/threejs-server", + "run", + "start:stdio" + ] + }, + "transcript": { + "command": "npm", + "args": [ + "--silent", + "--prefix", + "~/code/ext-apps/examples/transcript-server", + "run", + "start:stdio" + ] + }, + "video-resource": { + "command": "npm", + "args": [ + "--silent", + "--prefix", + "~/code/ext-apps/examples/video-resource-server", + "run", + "start:stdio" + ] + }, + "wiki-explorer": { + "command": "npm", + "args": [ + "--silent", + "--prefix", + "~/code/ext-apps/examples/wiki-explorer-server", + "run", + "start:stdio" + ] + }, + "qr": { + "command": "bash", + "args": [ + "-c", + "uv run ~/code/ext-apps/examples/qr-server/server.py --stdio" + ] + }, + "say": { + "command": "bash", + "args": [ + "-c", + "uv run --index https://pypi.org/simple ~/code/ext-apps/examples/say-server/server.py --stdio" + ] + } + } +} +``` + +
+ +This configuration rebuilds each server on launch, ensuring your local changes are picked up. + ## Testing ### Unit Tests diff --git a/examples/basic-server-preact/package.json b/examples/basic-server-preact/package.json index 166b75f8..32fb1a00 100644 --- a/examples/basic-server-preact/package.json +++ b/examples/basic-server-preact/package.json @@ -17,7 +17,9 @@ "build": "tsc --noEmit && cross-env INPUT=mcp-app.html vite build && tsc -p tsconfig.server.json && bun build server.ts --outdir dist --target node && bun build main.ts --outfile dist/index.js --target node --external \"./server.js\" --banner \"#!/usr/bin/env node\"", "watch": "cross-env INPUT=mcp-app.html vite build --watch", "serve": "bun --watch main.ts", + "serve:stdio": "bun main.ts --stdio", "start": "cross-env NODE_ENV=development npm run build && npm run serve", + "start:stdio": "cross-env NODE_ENV=development npm run build 1>&2 && npm run serve:stdio", "dev": "cross-env NODE_ENV=development concurrently \"npm run watch\" \"npm run serve\"", "prepublishOnly": "npm run build" }, diff --git a/examples/basic-server-react/package.json b/examples/basic-server-react/package.json index 0df22017..9732266d 100644 --- a/examples/basic-server-react/package.json +++ b/examples/basic-server-react/package.json @@ -27,7 +27,9 @@ "build": "tsc --noEmit && cross-env INPUT=mcp-app.html vite build && tsc -p tsconfig.server.json && bun build server.ts --outdir dist --target node && bun build main.ts --outfile dist/index.js --target node --external \"./server.js\" --banner \"#!/usr/bin/env node\"", "watch": "cross-env INPUT=mcp-app.html vite build --watch", "serve": "bun --watch main.ts", + "serve:stdio": "bun main.ts --stdio", "start": "cross-env NODE_ENV=development npm run build && npm run serve", + "start:stdio": "cross-env NODE_ENV=development npm run build 1>&2 && npm run serve:stdio", "dev": "cross-env NODE_ENV=development concurrently \"npm run watch\" \"npm run serve\"", "prepublishOnly": "npm run build" }, diff --git a/examples/basic-server-solid/package.json b/examples/basic-server-solid/package.json index b8115cbb..d31b8e3f 100644 --- a/examples/basic-server-solid/package.json +++ b/examples/basic-server-solid/package.json @@ -17,7 +17,9 @@ "build": "tsc --noEmit && cross-env INPUT=mcp-app.html vite build && tsc -p tsconfig.server.json && bun build server.ts --outdir dist --target node && bun build main.ts --outfile dist/index.js --target node --external \"./server.js\" --banner \"#!/usr/bin/env node\"", "watch": "cross-env INPUT=mcp-app.html vite build --watch", "serve": "bun --watch main.ts", + "serve:stdio": "bun main.ts --stdio", "start": "cross-env NODE_ENV=development npm run build && npm run serve", + "start:stdio": "cross-env NODE_ENV=development npm run build 1>&2 && npm run serve:stdio", "dev": "cross-env NODE_ENV=development concurrently \"npm run watch\" \"npm run serve\"", "prepublishOnly": "npm run build" }, diff --git a/examples/basic-server-svelte/package.json b/examples/basic-server-svelte/package.json index 2f6a7b66..2f57cfca 100644 --- a/examples/basic-server-svelte/package.json +++ b/examples/basic-server-svelte/package.json @@ -17,7 +17,9 @@ "build": "tsc --noEmit && cross-env INPUT=mcp-app.html vite build && tsc -p tsconfig.server.json && bun build server.ts --outdir dist --target node && bun build main.ts --outfile dist/index.js --target node --external \"./server.js\" --banner \"#!/usr/bin/env node\"", "watch": "cross-env INPUT=mcp-app.html vite build --watch", "serve": "bun --watch main.ts", + "serve:stdio": "bun main.ts --stdio", "start": "cross-env NODE_ENV=development npm run build && npm run serve", + "start:stdio": "cross-env NODE_ENV=development npm run build 1>&2 && npm run serve:stdio", "dev": "cross-env NODE_ENV=development concurrently \"npm run watch\" \"npm run serve\"", "prepublishOnly": "npm run build" }, diff --git a/examples/basic-server-vanillajs/package.json b/examples/basic-server-vanillajs/package.json index 44d3fdb2..eb0b24a2 100644 --- a/examples/basic-server-vanillajs/package.json +++ b/examples/basic-server-vanillajs/package.json @@ -17,7 +17,9 @@ "build": "tsc --noEmit && cross-env INPUT=mcp-app.html vite build && tsc -p tsconfig.server.json && bun build server.ts --outdir dist --target node && bun build main.ts --outfile dist/index.js --target node --external \"./server.js\" --banner \"#!/usr/bin/env node\"", "watch": "cross-env INPUT=mcp-app.html vite build --watch", "serve": "bun --watch main.ts", + "serve:stdio": "bun main.ts --stdio", "start": "cross-env NODE_ENV=development npm run build && npm run serve", + "start:stdio": "cross-env NODE_ENV=development npm run build 1>&2 && npm run serve:stdio", "dev": "cross-env NODE_ENV=development concurrently \"npm run watch\" \"npm run serve\"", "prepublishOnly": "npm run build" }, diff --git a/examples/basic-server-vue/package.json b/examples/basic-server-vue/package.json index e77102b5..ea7e2b41 100644 --- a/examples/basic-server-vue/package.json +++ b/examples/basic-server-vue/package.json @@ -17,7 +17,9 @@ "build": "tsc --noEmit && cross-env INPUT=mcp-app.html vite build && tsc -p tsconfig.server.json && bun build server.ts --outdir dist --target node && bun build main.ts --outfile dist/index.js --target node --external \"./server.js\" --banner \"#!/usr/bin/env node\"", "watch": "cross-env INPUT=mcp-app.html vite build --watch", "serve": "bun --watch main.ts", + "serve:stdio": "bun main.ts --stdio", "start": "cross-env NODE_ENV=development npm run build && npm run serve", + "start:stdio": "cross-env NODE_ENV=development npm run build 1>&2 && npm run serve:stdio", "dev": "cross-env NODE_ENV=development concurrently \"npm run watch\" \"npm run serve\"", "prepublishOnly": "npm run build" }, diff --git a/examples/debug-server/package.json b/examples/debug-server/package.json index ec2a644a..7f36b3a2 100644 --- a/examples/debug-server/package.json +++ b/examples/debug-server/package.json @@ -27,7 +27,9 @@ "build": "tsc --noEmit && cross-env INPUT=mcp-app.html vite build && tsc -p tsconfig.server.json && bun build server.ts --outdir dist --target node && bun build main.ts --outfile dist/index.js --target node --external \"./server.js\" --banner \"#!/usr/bin/env node\"", "watch": "cross-env INPUT=mcp-app.html vite build --watch", "serve": "bun --watch main.ts", + "serve:stdio": "bun main.ts --stdio", "start": "cross-env NODE_ENV=development npm run build && npm run serve", + "start:stdio": "cross-env NODE_ENV=development npm run build 1>&2 && npm run serve:stdio", "dev": "cross-env NODE_ENV=development concurrently \"npm run watch\" \"npm run serve\"", "prepublishOnly": "npm run build" }, diff --git a/examples/sheet-music-server/package.json b/examples/sheet-music-server/package.json index 54ea185e..d7a45a29 100644 --- a/examples/sheet-music-server/package.json +++ b/examples/sheet-music-server/package.json @@ -17,7 +17,9 @@ "build": "tsc --noEmit && cross-env INPUT=mcp-app.html vite build && tsc -p tsconfig.server.json && bun build server.ts --outdir dist --target node && bun build main.ts --outfile dist/index.js --target node --external \"./server.js\" --banner \"#!/usr/bin/env node\"", "watch": "cross-env INPUT=mcp-app.html vite build --watch", "serve": "bun --watch main.ts", + "serve:stdio": "bun main.ts --stdio", "start": "cross-env NODE_ENV=development npm run build && npm run serve", + "start:stdio": "cross-env NODE_ENV=development npm run build 1>&2 && npm run serve:stdio", "dev": "cross-env NODE_ENV=development concurrently \"npm run watch\" \"npm run serve\"", "prepublishOnly": "npm run build" }, diff --git a/examples/transcript-server/package.json b/examples/transcript-server/package.json index e72c109c..c9202857 100644 --- a/examples/transcript-server/package.json +++ b/examples/transcript-server/package.json @@ -17,7 +17,9 @@ "build": "tsc --noEmit && cross-env INPUT=mcp-app.html vite build && tsc -p tsconfig.server.json && bun build server.ts --outdir dist --target node && bun build main.ts --outfile dist/index.js --target node --external \"./server.js\" --banner \"#!/usr/bin/env node\"", "watch": "cross-env INPUT=mcp-app.html vite build --watch", "serve": "bun --watch main.ts", + "serve:stdio": "bun main.ts --stdio", "start": "cross-env NODE_ENV=development npm run build && npm run serve", + "start:stdio": "cross-env NODE_ENV=development npm run build 1>&2 && npm run serve:stdio", "dev": "cross-env NODE_ENV=development concurrently \"npm run watch\" \"npm run serve\"", "prepublishOnly": "npm run build" }, diff --git a/examples/video-resource-server/package.json b/examples/video-resource-server/package.json index cf641323..77c34a0e 100644 --- a/examples/video-resource-server/package.json +++ b/examples/video-resource-server/package.json @@ -17,7 +17,9 @@ "build": "tsc --noEmit && cross-env INPUT=mcp-app.html vite build && tsc -p tsconfig.server.json && bun build server.ts --outdir dist --target node && bun build main.ts --outfile dist/index.js --target node --external \"./server.js\" --banner \"#!/usr/bin/env node\"", "watch": "cross-env INPUT=mcp-app.html vite build --watch", "serve": "bun --watch main.ts", + "serve:stdio": "bun main.ts --stdio", "start": "cross-env NODE_ENV=development npm run build && npm run serve", + "start:stdio": "cross-env NODE_ENV=development npm run build 1>&2 && npm run serve:stdio", "dev": "cross-env NODE_ENV=development concurrently \"npm run watch\" \"npm run serve\"", "prepublishOnly": "npm run build" },