MCP 协议实战:从零搭建一个 MCP 服务器(Node.js 版)

MCP 协议实战:从零搭建一个 MCP 服务器(Node.js 版)

一、背景

说实话,MCP(Model Context Protocol)最近是真的火。Anthropic 搞出来这个协议之后,各种 AI 工具都在接入。说白了,MCP 就是一套标准接口,让 AI 模型能直接调用外部工具、读取文件、查数据库------不再局限在聊天框里。

但我发现一个问题:网上聊 MCP 概念的文章很多,真正教你手写一个 MCP 服务器的,真没几个。今天就来填这个坑,从零开始搭一个 MCP 服务器,附带完整的 TypeScript 代码。

二、MCP 是个啥

先简单说下 MCP 的核心概念。它本质上就是一个 JSON-RPC 协议,定义了三种角色:

  • Host:发起请求的一方(比如 Claude Desktop、Cursor)
  • Client:在 Host 内部和 Server 建立连接
  • Server:提供工具、资源、提示的服务端

MCP 支持两种传输方式:stdio (通过标准输入输出通信)和 SSE(通过 HTTP 流式通信)。我们今天用 stdio 方式,因为本地开发最方便。

三、环境准备

需要的东西很少:

  • Node.js 18+
  • npm 或 yarn
  • 一个支持 MCP 的客户端(比如 Claude Desktop)

四、项目初始化

直接开干:

bash 复制代码
mkdir mcp-demo-server
cd mcp-demo-server
npm init -y
npm install @modelcontextprotocol/sdk zod
npm install -D typescript @types/node tsx

这里的关键依赖是 @modelcontextprotocol/sdk,Anthropic 官方提供的 TypeScript SDK。我们直接用 tsx 来运行,省去编译步骤。

五、写一个 MCP 服务器

创建 src/index.ts

typescript 复制代码
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
  CallToolRequestSchema,
  ListToolsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";

// 1. 创建服务器实例
const server = new Server(
  {
    name: "mcp-demo-server",
    version: "1.0.0",
  },
  {
    capabilities: {
      tools: {},
    },
  }
);

说白了这个代码就是注册一个 MCP 服务器,告诉客户端我叫什么名字、有什么能力。

注册工具列表

MCP 客户端会先问服务器"你有什么工具",所以我们要实现 ListTools 请求:

typescript 复制代码
server.setRequestHandler(ListToolsRequestSchema, async () => {
  return {
    tools: [
      {
        name: "calculate",
        description: "执行数学计算",
        inputSchema: {
          type: "object",
          properties: {
            expression: {
              type: "string",
              description: "数学表达式,如 1 + 2 * 3",
            },
          },
          required: ["expression"],
        },
      },
      {
        name: "get_weather",
        description: "获取指定城市的天气",
        inputSchema: {
          type: "object",
          properties: {
            city: {
              type: "string",
              description: "城市名称",
            },
          },
          required: ["city"],
        },
      },
    ],
  };
});

实现工具调用

当客户端调某个工具时,会触发 CallTool 请求:

typescript 复制代码
server.setRequestHandler(CallToolRequestSchema, async (request) => {
  const { name, arguments: args } = request.params;

  switch (name) {
    case "calculate": {
      const expression = String(args?.expression || "");
      try {
        // 安全起见,用 mathjs 之类的库,这里用 Function 做演示
        const result = new Function(`return (${expression})`)();
        return {
          content: [{ type: "text", text: String(result) }],
        };
      } catch (e) {
        return {
          content: [{ type: "text", text: `计算错误: ${e}` }],
          isError: true,
        };
      }
    }

    case "get_weather": {
      const city = String(args?.city || "");
      // 这里本该调用天气 API,但为了演示直接返回模拟数据
      return {
        content: [
          {
            type: "text",
            text: `${city} 今天天气:晴,温度 28°C,湿度 65%`,
          },
        ],
      };
    }

    default:
      throw new Error("未知工具: " + name);
  }
});

启动服务器

typescript 复制代码
async function main() {
  const transport = new StdioServerTransport();
  await server.connect(transport);
  console.error("MCP 服务器已启动");
}

main().catch(console.error);

六、配置客户端

用 Claude Desktop 连接时,需要在 claude_desktop_config.json 中添加:

json 复制代码
{
  "mcpServers": {
    "mcp-demo": {
      "command": "npx",
      "args": ["tsx", "src/index.ts"]
    }
  }
}

重启 Claude Desktop,就能看到两个新工具了。

七、踩坑记录

说几个坑:

  1. SDK 版本问题 - 最新版 SDK 用 @modelcontextprotocol/sdk,别用旧版的 mcp-sdk。引入路径要写全 /index.js,不然会报模块找不到。

  2. stdio 方式别用 console.log - MCP 用 stdio 通信,如果代码里用了 console.log,会污染通信流。统一用 console.error 或专门的 logger。

  3. zod 校验 - 推荐用 zod 做输入参数校验,避免客户端传了非法参数导致服务器崩溃。

八、总结

说实话,MCP 的入门门槛比我想象的低很多。核心代码就几十行,跑通 stdio 通信之后,后面加工具就跟写 API 接口一样简单。

回顾一下我们今天做了什么:

  1. 创建了一个 MCP 服务器项目
  2. 注册了两个工具(计算器和天气查询)
  3. 用 stdio 方式启动
  4. 配置了 Claude Desktop 客户端

下一步可以试试 SSE 方式------支持远程连接,更适合生产环境部署。或者用 Python 的 SDK 再写一遍,对比一下两种语言的差异。

代码已上传到 github.com/xxx/mcp-demo-server,有用的话点个 star 吧 👇

相关推荐
梦想的颜色8 小时前
【AI速览】2026年 9月 GPT‑6 Astra 深度解析:Agent 时代的前沿旗舰,能力、成本、落地痛点与选型判断
人工智能·openai·agent·astra·vibecoding·大模型测评·gpt6
向星而行_star8 小时前
# OpenAI 发布 GPT Image 2.5:生成提速 50%,还能“指哪改哪“,AI 生图进入修图时代
人工智能·gpt·openai·gpt6·image2.5·星途ai
ofoxcoding9 小时前
GPT Image 2.5 API 实战:Python 调用实现图片生成与编辑
人工智能·python·gpt·ai
来让爷抱一个9 小时前
2026 语义缓存实战:把命中契约写进SPEC,MonkeyCode 云端跑通
人工智能·机器学习·缓存
俊哥V9 小时前
AI 今日研究简报 · 2026-09-09
人工智能·ai
张小姐的猫9 小时前
【AI大模型接入SDK】 —— Gemini接入封装
android·数据结构·数据库·c++·人工智能·python
时空节拍AI数字人9 小时前
AI 数字人为什么需要“3D”?2D 不够用吗
人工智能·网络协议·tcp/ip·3d·信息可视化
米小虾9 小时前
4-bit 量化"几乎无损"?把它放进 Agent 循环里再试一次
人工智能·agent
陈皮糖..9 小时前
从零搭建一个简易 AI 运维问答机器人(RAG + LangChain + Streamlit)
运维·人工智能·ai·langchain·机器人