Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions .github/workflows/npm-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -83,3 +83,47 @@ jobs:
- run: npm publish --provenance --access public ${{ steps.npm-tag.outputs.tag }}
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_SECRET }}

publish-examples:
runs-on: ubuntu-latest
if: github.event_name == 'release'
environment: Release
needs: [publish]

permissions:
contents: read
id-token: write

strategy:
fail-fast: false
matrix:
example:
- basic-server-react
- basic-server-vanillajs
- budget-allocator-server
- cohort-heatmap-server
- customer-segmentation-server
- scenario-modeler-server
- system-monitor-server
- threejs-server
- wiki-explorer-server

steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
with:
bun-version: latest
- uses: actions/setup-node@v4
with:
node-version: "22"
cache: npm
registry-url: "https://registry.npmjs.org"
- run: npm ci

- name: Build example
run: npm run build --workspace examples/${{ matrix.example }}

- name: Publish example
run: npm publish --workspace examples/${{ matrix.example }} --provenance --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_SECRET }}
14 changes: 13 additions & 1 deletion .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,16 @@ jobs:
cache: npm
- run: npm ci
- run: npm run build
- run: npx pkg-pr-new publish
- run: npm run examples:build
- run: |
npx pkg-pr-new publish \
. \
./examples/basic-server-react \
./examples/basic-server-vanillajs \
./examples/budget-allocator-server \
./examples/cohort-heatmap-server \
./examples/customer-segmentation-server \
./examples/scenario-modeler-server \
./examples/system-monitor-server \
./examples/threejs-server \
./examples/wiki-explorer-server
25 changes: 19 additions & 6 deletions examples/basic-server-preact/package.json
Original file line number Diff line number Diff line change
@@ -1,17 +1,30 @@
{
"name": "basic-server-preact",
"version": "1.0.0",
"private": true,
"name": "@modelcontextprotocol/server-basic-preact",
"version": "0.1.0",
"type": "module",
"description": "Basic MCP App Server example using Preact",
"repository": {
"type": "git",
"url": "https://github.com/modelcontextprotocol/ext-apps",
"directory": "examples/basic-server-preact"
},
"license": "MIT",
"main": "server.ts",
"files": [
"server.ts",
"server-utils.ts",
"dist"
],
"scripts": {
"build": "tsc --noEmit && cross-env INPUT=mcp-app.html vite build",
"watch": "cross-env INPUT=mcp-app.html vite build --watch",
"serve": "bun server.ts",
"start": "cross-env NODE_ENV=development npm run build && npm run serve",
"dev": "cross-env NODE_ENV=development concurrently 'npm run watch' 'npm run serve'"
"dev": "cross-env NODE_ENV=development concurrently 'npm run watch' 'npm run serve'",
"prepublishOnly": "npm run build"
},
"dependencies": {
"@modelcontextprotocol/ext-apps": "../..",
"@modelcontextprotocol/ext-apps": "^0.2.2",
"@modelcontextprotocol/sdk": "^1.24.0",
"preact": "^10.0.0",
"zod": "^4.1.13"
Expand All @@ -23,7 +36,7 @@
"@types/node": "^22.0.0",
"concurrently": "^9.2.1",
"cors": "^2.8.5",
"cross-env": "^7.0.3",
"cross-env": "^10.1.0",
"express": "^5.1.0",
"typescript": "^5.9.3",
"vite": "^6.0.0",
Expand Down
68 changes: 68 additions & 0 deletions examples/basic-server-preact/server-utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/**
* Shared utilities for running MCP servers with Streamable HTTP transport.
*/

import { createMcpExpressApp } from "@modelcontextprotocol/sdk/server/express.js";
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
import cors from "cors";
import type { Request, Response } from "express";

export interface ServerOptions {
port: number;
name?: string;
}

/**
* Starts an MCP server with Streamable HTTP transport in stateless mode.
*
* @param createServer - Factory function that creates a new McpServer instance per request.
* @param options - Server configuration options.
*/
export async function startServer(
createServer: () => McpServer,
options: ServerOptions,
): Promise<void> {
const { port, name = "MCP Server" } = options;

const app = createMcpExpressApp({ host: "0.0.0.0" });
app.use(cors());

app.all("/mcp", async (req: Request, res: Response) => {
const server = createServer();
const transport = new StreamableHTTPServerTransport({
sessionIdGenerator: undefined,
});

res.on("close", () => {
transport.close().catch(() => {});
server.close().catch(() => {});
});

try {
await server.connect(transport);
await transport.handleRequest(req, res, req.body);
} catch (error) {
console.error("MCP error:", error);
if (!res.headersSent) {
res.status(500).json({
jsonrpc: "2.0",
error: { code: -32603, message: "Internal server error" },
id: null,
});
}
}
});

const httpServer = app.listen(port, () => {
console.log(`${name} listening on http://localhost:${port}/mcp`);
});

const shutdown = () => {
console.log("\nShutting down...");
httpServer.close(() => process.exit(0));
};

process.on("SIGINT", shutdown);
process.on("SIGTERM", shutdown);
}
19 changes: 16 additions & 3 deletions examples/basic-server-preact/server.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { registerAppResource, registerAppTool, RESOURCE_MIME_TYPE } from "@modelcontextprotocol/ext-apps/server";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import type { CallToolResult, ReadResourceResult } from "@modelcontextprotocol/sdk/types.js";
import fs from "node:fs/promises";
import path from "node:path";
import { startServer } from "./src/server-utils.js";
import { registerAppTool, registerAppResource, RESOURCE_MIME_TYPE } from "@modelcontextprotocol/ext-apps/server";
import { startServer } from "./server-utils.js";

const DIST_DIR = path.join(import.meta.dirname, "dist");

Expand Down Expand Up @@ -55,4 +56,16 @@ function createServer(): McpServer {
return server;
}

startServer(createServer);
async function main() {
if (process.argv.includes("--stdio")) {
await createServer().connect(new StdioServerTransport());
} else {
const port = parseInt(process.env.PORT ?? "3001", 10);
await startServer(createServer, { port, name: "Basic MCP App Server (Preact)" });
}
}

main().catch((e) => {
console.error(e);
process.exit(1);
});
110 changes: 0 additions & 110 deletions examples/basic-server-preact/src/server-utils.ts

This file was deleted.

24 changes: 19 additions & 5 deletions examples/basic-server-react/package.json
Original file line number Diff line number Diff line change
@@ -1,17 +1,30 @@
{
"name": "basic-server-react",
"version": "1.0.0",
"private": true,
"name": "@modelcontextprotocol/server-basic-react",
"version": "0.1.0",
"type": "module",
"description": "Basic MCP App Server example using React",
"repository": {
"type": "git",
"url": "https://github.com/modelcontextprotocol/ext-apps",
"directory": "examples/basic-server-react"
},
"license": "MIT",
"main": "server.ts",
"files": [
"server.ts",
"server-utils.ts",
"dist"
],
"scripts": {
"build": "tsc --noEmit && cross-env INPUT=mcp-app.html vite build",
"watch": "cross-env INPUT=mcp-app.html vite build --watch",
"serve": "bun server.ts",
"start": "cross-env NODE_ENV=development npm run build && npm run serve",
"dev": "cross-env NODE_ENV=development concurrently 'npm run watch' 'npm run serve'"
"dev": "cross-env NODE_ENV=development concurrently 'npm run watch' 'npm run serve'",
"prepublishOnly": "npm run build"
},
"dependencies": {
"@modelcontextprotocol/ext-apps": "../..",
"@modelcontextprotocol/ext-apps": "^0.2.2",
"@modelcontextprotocol/sdk": "^1.24.0",
"react": "^19.2.0",
"react-dom": "^19.2.0",
Expand All @@ -26,6 +39,7 @@
"@vitejs/plugin-react": "^4.3.4",
"concurrently": "^9.2.1",
"cors": "^2.8.5",
"cross-env": "^10.1.0",
"express": "^5.1.0",
"typescript": "^5.9.3",
"vite": "^6.0.0",
Expand Down
Loading
Loading