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 吧 👇

相关推荐
学究天人1 小时前
数学公理体系大全:第一章 命题逻辑:真值之舞
人工智能·算法·机器学习·数学建模·动态规划·图论·抽象代数
万亿少女的梦1681 小时前
基于Spring Boot、Vue.js和MySQL的超市管理系统设计与实现
java·vue.js·spring boot·mysql·管理系统
ylscode1 小时前
OpenAI GPT-5.6正式发布:三档模型Sol、Terra、Luna全面解析与性能实测
人工智能
2601_958352901 小时前
研发成本骤降95%:AP-0316 语音模组如何重塑硬件产品的商业逻辑
人工智能·语音识别·降噪处理·音频处理模块·硬件开发模块
土星云SaturnCloud1 小时前
边缘计算在储气库调峰智能管控中的应用:架构设计与技术解析
服务器·人工智能·ai·边缘计算
临风细雨2 小时前
从 Bun 的 Rust 重写,看 C# 如何重建 AI 基础设施层
人工智能·rust·c#
中微极客2 小时前
Seedance 2.5深度解析:30秒4K视频生成与50路多模态参考的工程实践
人工智能·音视频
weixin_446260852 小时前
SolarChain-Eval:面向去中心化能源市场的物理约束可信经济智能体评测基准
人工智能·去中心化·能源
C137的本贾尼2 小时前
第16章:下山,先学会怎么迈步——梯度下降
人工智能