通过两个实例构建自己的 MCP Server:
- 基于标准输入输出的轻量服务Stdio。
- 通过 HTTP SSE(Server-Sent Events)支持前端连接,实现更复杂的交互。
MCP 简介
MCP(Model Context Protocol)是一种协议标准,旨在为 LLM 提供更丰富、更结构化的上下文支持。它支持三种主要功能类型:
- Resources:公开数据,用于将信息加载到 LLM 的上下文中(可以将其视为 GET 端点)
- Tools:提供功能,供 LLM 调用的函数。
- Prompts:通过提示词定义交互模式(可重复使用的LLM交互模板)。
SDK封装好了协议内部细节(JSON-RPC 2.0),包括架构分层,开发者直接写一些业务代码就可以了。
https://github.com/modelcontextprotocol/typescript-sdk
示例一:基于 stdio 的 MCP Server
src/demo-stdio.js
这是一个最简版本的 MCP Server,通过标准输入输出(stdin/stdout)进行通信。
import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
// Create an MCP server
const server = new McpServer({
name: "Demo",
version: "1.0.0"
});
server.tool("add", 'Add two numbers', { a: z.number(), b: z.number() },
async ({ a, b }) => ({
content: [{ type: "text", text: String(a + b) }]
})
);
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
}
main()
这段代码中,tool() 声明了一个简单的加法功能,StdioServerTransport 处理 stdin/stdout 通信。
初始化依赖:
pnpm init
pnpm add zod
pnpm add @modelcontextprotocol/sdk
调试方法
如果写好了代码,怎么调试这个Server呢?官方提供了一个调试器:
npx @modelcontextprotocol/inspector
运行后,访问调试器页面:
Starting MCP inspector...
⚙️ Proxy server listening on localhost:6277
🔑 Session token: a45ed6e4cbe32b213673aa5ae189fd4639648f8a81ec80181c357177d3a00db4
Use this token to authenticate requests or set DANGEROUSLY_OMIT_AUTH=true to disable auth
🚀 MCP Inspector is up and running at:
http://localhost:6274
我的前端项目结构如下:
.
├── package.json
├── pnpm-lock.yaml
└── src
└── demo-stdio.js
基于你自己的位置调整:
- Command:
node - Arguments:
src/demo-stdio.js
配置session(从运行调试器日志里获取):
点击:Connect

可以看到已经调用成功。
示例二:基于 SSE 的 HTTP Server
创建文件 src/exchange.ts
import express from "express";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
import { z } from "zod";
const server = new McpServer({
name: "demo-sse",
version: "1.0.0"
});
server.tool("exchange", '人民币汇率换算', { rmb: z.number() },
async ({ rmb }) => {
// 使用固定汇率进行演示,实际应该调用汇率API
const usdRate = 0.14; // 1人民币约等于0.14美元
const hkdRate = 1.09; // 1人民币约等于1.09港币
const usd = (rmb * usdRate).toFixed(2);
const hkd = (rmb * hkdRate).toFixed(2);
return {
content: [{
type: "text",
text: `${rmb}人民币等于:\n${usd}美元\n${hkd}港币`
}]
}
},
);
const app = express();
const sessions: Record<string, { transport: SSEServerTransport; response: express.Response }> = {}
app.get("/sse", async (req, res) => {
console.log(`New SSE connection from ${req.ip}`);
const sseTransport = new SSEServerTransport("/messages", res);
const sessionId = sseTransport.sessionId;
if (sessionId) {
sessions[sessionId] = { transport: sseTransport, response: res }
}
await server.connect(sseTransport);
});
app.post("/messages", async (req, res) => {
const sessionId = req.query.sessionId as string;
const session = sessions[sessionId];
if (!session) {
res.status(404).send("Session not found");
return;
}
await session.transport.handlePostMessage(req, res);
});
app.listen(3001);
添加依赖
pnpm add express
pnpm add -D @types/express
- 这是 Express 框架的主包,实际运行服务所需要的。
@types/express:让 TypeScript 能识别 express 的类型,开发体验更好,也能避免类型相关的报错。
编译配置
安装 TypeScript(作为开发依赖):
pnpm add typescript -D
初始化 TypeScript,可以用下面命令生成:
pnpm exec tsc --init
修改生成的 tsconfig.json:
{
"compilerOptions": {
"target": "es2016",
"module": "commonjs",
"outDir": "./dist",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true
}
}
我修改了 "outDir": "./dist" 到 ./dist 目录。
编译代码:
pnpm exec tsc
把 src/exchange.ts 编译成 dist/exchange.js。
执行:
node dist/exchange.js
没有报错就是正常运行了。
访问地址:
控制台输出如下:
event: endpoint
data: /messages?sessionId=b42287de-fc9a-4626-bdea-47de5dc2aaa9
成功了!
另外
另外,我的package.json是下面的,供你参考:
{
"name": "mcp-demo",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "tsc",
"start": "node dist/exchange.js",
},
"keywords": [],
"author": "",
"license": "ISC",
"packageManager": "pnpm@10.8.1",
"dependencies": {
"@modelcontextprotocol/sdk": "^1.10.2",
"express": "^5.1.0",
"zod": "^3.24.3"
},
"devDependencies": {
"@types/express": "^5.0.1",
"ts-node": "^10.9.2"
}
}
如果你要放到其他地方运行,可能需要tsc换成tsup,tsup 可以把它打包成一个完整文件,在别的机器上跑起来不需要源码。
加入tsup命令:
pnpm add -D tsup
构建命令:
tsup src/exchange.ts --format cjs --out-dir dist --dts false
