Skip to content

Commit 8392619

Browse files
committed
refactor: update new framework examples to publishing pattern
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()
1 parent 011f6e3 commit 8392619

17 files changed

Lines changed: 448 additions & 580 deletions

File tree

examples/basic-server-preact/package.json

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,30 @@
11
{
2-
"name": "basic-server-preact",
3-
"version": "1.0.0",
4-
"private": true,
2+
"name": "@modelcontextprotocol/server-basic-preact",
3+
"version": "0.1.0",
54
"type": "module",
5+
"description": "Basic MCP App Server example using Preact",
6+
"repository": {
7+
"type": "git",
8+
"url": "https://github.com/modelcontextprotocol/ext-apps",
9+
"directory": "examples/basic-server-preact"
10+
},
11+
"license": "MIT",
12+
"main": "server.ts",
13+
"files": [
14+
"server.ts",
15+
"server-utils.ts",
16+
"dist"
17+
],
618
"scripts": {
719
"build": "tsc --noEmit && cross-env INPUT=mcp-app.html vite build",
820
"watch": "cross-env INPUT=mcp-app.html vite build --watch",
921
"serve": "bun server.ts",
1022
"start": "cross-env NODE_ENV=development npm run build && npm run serve",
11-
"dev": "cross-env NODE_ENV=development concurrently 'npm run watch' 'npm run serve'"
23+
"dev": "cross-env NODE_ENV=development concurrently 'npm run watch' 'npm run serve'",
24+
"prepublishOnly": "npm run build"
1225
},
1326
"dependencies": {
14-
"@modelcontextprotocol/ext-apps": "../..",
27+
"@modelcontextprotocol/ext-apps": "^0.2.2",
1528
"@modelcontextprotocol/sdk": "^1.24.0",
1629
"preact": "^10.0.0",
1730
"zod": "^4.1.13"
@@ -23,7 +36,7 @@
2336
"@types/node": "^22.0.0",
2437
"concurrently": "^9.2.1",
2538
"cors": "^2.8.5",
26-
"cross-env": "^7.0.3",
39+
"cross-env": "^10.1.0",
2740
"express": "^5.1.0",
2841
"typescript": "^5.9.3",
2942
"vite": "^6.0.0",
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/**
2+
* Shared utilities for running MCP servers with Streamable HTTP transport.
3+
*/
4+
5+
import { createMcpExpressApp } from "@modelcontextprotocol/sdk/server/express.js";
6+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
7+
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
8+
import cors from "cors";
9+
import type { Request, Response } from "express";
10+
11+
export interface ServerOptions {
12+
port: number;
13+
name?: string;
14+
}
15+
16+
/**
17+
* Starts an MCP server with Streamable HTTP transport in stateless mode.
18+
*
19+
* @param createServer - Factory function that creates a new McpServer instance per request.
20+
* @param options - Server configuration options.
21+
*/
22+
export async function startServer(
23+
createServer: () => McpServer,
24+
options: ServerOptions,
25+
): Promise<void> {
26+
const { port, name = "MCP Server" } = options;
27+
28+
const app = createMcpExpressApp({ host: "0.0.0.0" });
29+
app.use(cors());
30+
31+
app.all("/mcp", async (req: Request, res: Response) => {
32+
const server = createServer();
33+
const transport = new StreamableHTTPServerTransport({
34+
sessionIdGenerator: undefined,
35+
});
36+
37+
res.on("close", () => {
38+
transport.close().catch(() => {});
39+
server.close().catch(() => {});
40+
});
41+
42+
try {
43+
await server.connect(transport);
44+
await transport.handleRequest(req, res, req.body);
45+
} catch (error) {
46+
console.error("MCP error:", error);
47+
if (!res.headersSent) {
48+
res.status(500).json({
49+
jsonrpc: "2.0",
50+
error: { code: -32603, message: "Internal server error" },
51+
id: null,
52+
});
53+
}
54+
}
55+
});
56+
57+
const httpServer = app.listen(port, () => {
58+
console.log(`${name} listening on http://localhost:${port}/mcp`);
59+
});
60+
61+
const shutdown = () => {
62+
console.log("\nShutting down...");
63+
httpServer.close(() => process.exit(0));
64+
};
65+
66+
process.on("SIGINT", shutdown);
67+
process.on("SIGTERM", shutdown);
68+
}

examples/basic-server-preact/server.ts

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
import { registerAppResource, registerAppTool, RESOURCE_MIME_TYPE } from "@modelcontextprotocol/ext-apps/server";
21
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
33
import type { CallToolResult, ReadResourceResult } from "@modelcontextprotocol/sdk/types.js";
44
import fs from "node:fs/promises";
55
import path from "node:path";
6-
import { startServer } from "./src/server-utils.js";
6+
import { registerAppTool, registerAppResource, RESOURCE_MIME_TYPE } from "@modelcontextprotocol/ext-apps/server";
7+
import { startServer } from "./server-utils.js";
78

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

@@ -55,4 +56,16 @@ function createServer(): McpServer {
5556
return server;
5657
}
5758

58-
startServer(createServer);
59+
async function main() {
60+
if (process.argv.includes("--stdio")) {
61+
await createServer().connect(new StdioServerTransport());
62+
} else {
63+
const port = parseInt(process.env.PORT ?? "3001", 10);
64+
await startServer(createServer, { port, name: "Basic MCP App Server (Preact)" });
65+
}
66+
}
67+
68+
main().catch((e) => {
69+
console.error(e);
70+
process.exit(1);
71+
});

examples/basic-server-preact/src/server-utils.ts

Lines changed: 0 additions & 110 deletions
This file was deleted.

examples/basic-server-solid/package.json

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,30 @@
11
{
2-
"name": "basic-server-solid",
3-
"version": "1.0.0",
4-
"private": true,
2+
"name": "@modelcontextprotocol/server-basic-solid",
3+
"version": "0.1.0",
54
"type": "module",
5+
"description": "Basic MCP App Server example using Solid",
6+
"repository": {
7+
"type": "git",
8+
"url": "https://github.com/modelcontextprotocol/ext-apps",
9+
"directory": "examples/basic-server-solid"
10+
},
11+
"license": "MIT",
12+
"main": "server.ts",
13+
"files": [
14+
"server.ts",
15+
"server-utils.ts",
16+
"dist"
17+
],
618
"scripts": {
719
"build": "tsc --noEmit && cross-env INPUT=mcp-app.html vite build",
820
"watch": "cross-env INPUT=mcp-app.html vite build --watch",
921
"serve": "bun server.ts",
1022
"start": "cross-env NODE_ENV=development npm run build && npm run serve",
11-
"dev": "cross-env NODE_ENV=development concurrently 'npm run watch' 'npm run serve'"
23+
"dev": "cross-env NODE_ENV=development concurrently 'npm run watch' 'npm run serve'",
24+
"prepublishOnly": "npm run build"
1225
},
1326
"dependencies": {
14-
"@modelcontextprotocol/ext-apps": "../..",
27+
"@modelcontextprotocol/ext-apps": "^0.2.2",
1528
"@modelcontextprotocol/sdk": "^1.24.0",
1629
"solid-js": "^1.9.0",
1730
"zod": "^4.1.13"
@@ -22,7 +35,7 @@
2235
"@types/node": "^22.0.0",
2336
"concurrently": "^9.2.1",
2437
"cors": "^2.8.5",
25-
"cross-env": "^7.0.3",
38+
"cross-env": "^10.1.0",
2639
"express": "^5.1.0",
2740
"typescript": "^5.9.3",
2841
"vite": "^6.0.0",
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/**
2+
* Shared utilities for running MCP servers with Streamable HTTP transport.
3+
*/
4+
5+
import { createMcpExpressApp } from "@modelcontextprotocol/sdk/server/express.js";
6+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
7+
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
8+
import cors from "cors";
9+
import type { Request, Response } from "express";
10+
11+
export interface ServerOptions {
12+
port: number;
13+
name?: string;
14+
}
15+
16+
/**
17+
* Starts an MCP server with Streamable HTTP transport in stateless mode.
18+
*
19+
* @param createServer - Factory function that creates a new McpServer instance per request.
20+
* @param options - Server configuration options.
21+
*/
22+
export async function startServer(
23+
createServer: () => McpServer,
24+
options: ServerOptions,
25+
): Promise<void> {
26+
const { port, name = "MCP Server" } = options;
27+
28+
const app = createMcpExpressApp({ host: "0.0.0.0" });
29+
app.use(cors());
30+
31+
app.all("/mcp", async (req: Request, res: Response) => {
32+
const server = createServer();
33+
const transport = new StreamableHTTPServerTransport({
34+
sessionIdGenerator: undefined,
35+
});
36+
37+
res.on("close", () => {
38+
transport.close().catch(() => {});
39+
server.close().catch(() => {});
40+
});
41+
42+
try {
43+
await server.connect(transport);
44+
await transport.handleRequest(req, res, req.body);
45+
} catch (error) {
46+
console.error("MCP error:", error);
47+
if (!res.headersSent) {
48+
res.status(500).json({
49+
jsonrpc: "2.0",
50+
error: { code: -32603, message: "Internal server error" },
51+
id: null,
52+
});
53+
}
54+
}
55+
});
56+
57+
const httpServer = app.listen(port, () => {
58+
console.log(`${name} listening on http://localhost:${port}/mcp`);
59+
});
60+
61+
const shutdown = () => {
62+
console.log("\nShutting down...");
63+
httpServer.close(() => process.exit(0));
64+
};
65+
66+
process.on("SIGINT", shutdown);
67+
process.on("SIGTERM", shutdown);
68+
}

0 commit comments

Comments
 (0)