一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

用 Node.js 从零实现 MCP Server:接入 Copilot 调用四则运算工具

时间:2026-09-17 09:40:01 编辑:袖梨 来源:一聚教程网

当 AI 编程助手需要访问自定义能力时,单靠提示词并不能完成真实的函数执行,工具还需要通过统一方式暴露给宿主应用。以一个加减乘除计算器为例,可以把 MCP 的协议角色、工具注册、stdio 通信和 Copilot 接入串成一条清晰链路,同时避开输出污染与错误返回等常见问题。

本文从「MCP 是什么」讲起,然后手写一个只做加减乘除的 MCP Server(Node.js 实现),最后把它接到 VS Code 的 GitHub Copilot Chat 里,用自然语言让 AI 调用我们自己的工具。

一、MCP 是什么

MCP(Model Context Protocol,模型上下文协议) 是一套开放协议,用来标准化 AI 应用外部工具 / 数据 / 服务 之间的连接方式。

一句话理解:

MCP 就像是 AI 世界的 USB-C 接口。以前每接一个工具就要写一套专用适配代码,现在大家都按同一个协议说话,插上就能用。

在 MCP 出现之前,如果你有 N 个 AI 应用(VS Code、Claude Desktop、Cursor、自研 Agent…)和 M 个工具(GitHub、数据库、文件系统、内部 API…),理论上需要写 N × M 份适配代码:

        AI 应用            工具
      ┌─────────┐      ┌─────────┐
      │ VS Code │──────│ GitHub  │
      ├─────────┤      ├─────────┤
      │ Claude  │──────│ MySQL   │
      ├─────────┤      ├─────────┤
      │ Cursor  │──────│ 内部 API │
      └─────────┘      └─────────┘
        N 个               M 个
        连线条数 = N × M

有了 MCP 之后,工具只需按 MCP 协议暴露一次能力,所有支持 MCP 的 AI 应用都能接入,连线条数从 N × M 变成 N + M

        AI 应用        MCP 协议       MCP Server
      ┌─────────┐                   ┌─────────┐
      │ VS Code │──┐             ┌──│ GitHub  │
      ├─────────┤  │             │  ├─────────┤
      │ Claude  │──┼── MCP ──────┼──│ MySQL   │
      ├─────────┤  │             │  ├─────────┤
      │ Cursor  │──┘             └──│ 内部 API |
      └─────────┘                   └─────────┘
                连线条数 = N + M

MCP 的适用范围

MCP 只专注于「上下文交换」这一件事:

  • 它规定 AI 应用和 MCP Server 之间如何通信
  • 规定 AI 应用该怎么使用大模型;
  • 规定 AI 应用该如何管理拿到的上下文。

二、MCP 的核心概念

2.1 三个参与者

MCP 采用 客户端-服务器(Client-Server)架构

  • MCP Host(宿主):AI 应用本身,比如 VS Code、Claude Desktop、Claude Code。它负责协调管理一个或多个 MCP Client。
  • MCP Client(客户端):Host 内部为每一个 MCP Server 创建的连接对象,负责维护与某个 Server 的专用连接
  • MCP Server(服务器):真正提供上下文与能力的程序,可以跑在本地,也可以跑在远端。

pic31.png

注意:MCP Server 指的是「提供上下文数据的程序」,和它跑在哪里无关

  • 跑在本机、通过 stdio 通信的,叫 本地 MCP Server
  • 跑在云上、通过 Streamable HTTP 通信的,叫 远程 MCP Server

stdio 是 standard input/output(标准输入/输出)的缩写,也就是键盘输入、控制台输出。可以实现跨进程通信。

2.2 服务器能提供的三类能力

MCP Server 可以对外提供三种基础能力(Primitives):

能力说明典型用途
ToolsAI 可调用的可执行函数(需要用户授权)查数据库、调 API、做计算、写文件
Resources只读的上下文数据源文件内容、数据库记录、接口返回
Prompts预置的提示词模板代码审查模板、周报生成模板

本文的实战只用到 Tools,因为计算器就是典型的「可执行函数」。

2.3 两个协议层

MCP 把协议分成两层,理解这两层基本就理解了 MCP 的全貌:

MCP
├── 数据层(Data Layer)      → 「传什么」
│   └── 基于 JSON-RPC 2.0:能力发现、版本协商、Tools / Resources / Prompts / 通知
│
└── 传输层(Transport Layer)  → 「怎么传」
    ├── stdio:标准输入输出,进程间通信,本地部署,延迟最低
    └── Streamable HTTP:HTTP POST(可选 SSE 流式),本地或远程部署,支持 OAuth 等鉴权

无论用哪种传输方式,消息本身都统一是 JSON-RPC 2.0 格式。SDK 已经帮我们把这一层封装好了,日常开发基本只需要关心「注册了什么工具」。

JSON-RPC 是一种基于 JSON 格式的远程过程调用协议,让客户端可以通过发送 JSON 请求来调用远程服务器上的方法并获取结果。

2.4 MCP 和 Function Calling 有什么区别

很多人会把两者搞混,实际关系是:

维度Function CallingMCP
是什么大模型的一种能力(输出「调用哪个函数」)一套协议(规定 AI 应用如何连接外部工具/数据)
解决问题模型如何决定调用工具工具如何被标准化地接入各种各样的 AI 应用
代码写在哪写在 AI 应用内部写在独立的 Server 进程里,可复用
关系MCP 是“工具的插座”,Function Calling 是“模型伸出手去插”的那个动作

简单说:MCP 让工具变成可复用的标准件,Function Calling 让模型有能力去使用这些标准件。

三、环境准备

构建 MCP 需要用到官方提供的 SDK 。本文使用 TypeScript 语言版本的 SDK 。需要 Node.js >= 20

官方 TypeScript/Node SDK(v2)要求 Node.js >= 20

关于包名,需要注意版本差异:

版本包名说明
v1@modelcontextprotocol/sdk早期单体包,网上大部分教程用的是它
v2@modelcontextprotocol/server当前稳定版,实现 2026-07-28 版 MCP 规范

本文使用 v2 的 @modelcontextprotocol/server(服务端包已经拆成独立包,客户端是 @modelcontextprotocol/client)。

四、用 Node.js 实现加减乘除 MCP Server

4.1 初始化项目

mkdir mcp-calculator
cd mcp-calculator
npm init -y

# 安装依赖:MCP 服务端 SDK + zod(用于声明工具入参的类型)
npm install @modelcontextprotocol/server zod

修改 package.json,加上 ESM 支持(SDK 是纯 ESM 包):

{
  "name": "mcp-calculator",
  "version": "1.0.0",
  "type": "module",
  "main": "calculator-server.js",
  "scripts": {
    "start": "node calculator-server.js"
  }
}

4.2 编写 Server 代码

新建 calculator-server.js

import { McpServer } from "@modelcontextprotocol/server";
import { StdioServerTransport } from "@modelcontextprotocol/server/stdio";
import { z } from "zod";

// 1. 创建 MCP Server 实例,name/version 会通过 initialize 响应暴露给客户端
const server = new McpServer({ name: "calculator", version: "1.0.0" });

// 2. 抽一个公共的入参 schema:a、b 都是数字
const binaryInput = z.object({
  a: z.number().describe("第一个操作数"),
  b: z.number().describe("第二个操作数"),
});

// 3. 抽一个统一的返回格式:MCP 工具必须返回 content 数组
const text = (t) => ({ content: [{ type: "text", text: String(t) }] });

// 4. 注册加法工具
server.registerTool(
  "add",
  {
    title: "加法",
    description: "计算两个数字的和 a + b",
    inputSchema: binaryInput,
  },
  async ({ a, b }) => text(a + b)
);

// 5. 注册减法工具
server.registerTool(
  "subtract",
  {
    title: "减法",
    description: "计算两个数字的差 a - b",
    inputSchema: binaryInput,
  },
  async ({ a, b }) => text(a - b)
);

// 6. 注册乘法工具
server.registerTool(
  "multiply",
  {
    title: "乘法",
    description: "计算两个数字的积 a * b",
    inputSchema: binaryInput,
  },
  async ({ a, b }) => text(a * b)
);

// 7. 注册除法工具(需要处理除零)
server.registerTool(
  "divide",
  {
    title: "除法",
    description: "计算两个数字的商 a / b,b 不能为 0",
    inputSchema: binaryInput,
  },
  async ({ a, b }) => {
    if (b === 0) {
      return {
        content: [{ type: "text", text: "错误:除数不能为 0" }],
        isError: true,
      };
    }
    return text(a / b);
  }
);

// 8. 使用 stdio 传输启动服务
const transport = new StdioServerTransport();
await server.connect(transport);

// 注意:stdio 场景下日志必须走 stderr,绝不能 console.log
console.error("Calculator MCP Server running on stdio");

4.3 关键点说明

1)registerTool(name, config, callback) 的签名

server.registerTool(
  "工具名(模型看到的函数名)",
  {
    title: "给用户看的标题",
    description: "给模型看的说明 —— 这段文字直接决定模型会不会用、用对不用对",
    inputSchema: z.object({ ... }),   // 入参类型,SDK 会转成 JSON Schema
    outputSchema: z.object({ ... }),  // 可选:声明返回值结构
  },
  async (args, ctx) => {
    return { content: [{ type: "text", text: "..." }] };
  },
);

2)description 比代码更重要

模型只能通过 name + description + inputSchema 来判断该不该调用这个工具。所以:

  • description: "计算" —— 模型不知道算加还是减;
  • description: "计算两个数字的商 a / b,b 不能为 0" —— 意图清晰,参数含义明确。

3)stdio 场景下绝对不能 console.log

stdio 传输是用 标准输出 来传 JSON-RPC 消息的。你 console.log 一句日志,就会把 JSON-RPC 报文污染掉,连接直接断开。

console.log("server started"); // ❌ 会破坏 stdio 通信
console.error("server started"); // ✅ 写 stderr,安全

4)错误要用 isError 标记,而不是抛异常

抛异常会让整个请求失败,而 isError: true 会把错误信息作为工具结果交给模型,模型可以据此自我修正(比如「除数不能为 0」它会解释给用户听)。

4.4 运行一下

node calculator-server.js

因为 stdio 服务在等 JSON-RPC 报文,终端里看起来「卡住不动」是正常的。要真正验证,用官方调试工具 MCP Inspector:

npx @modelcontextprotocol/inspector node $(pwd)/calculator-server.js

打开它给出的地址后,可以看到 Web 界面:

pic25.png

  1. Connect
  2. 切到 Tools 标签,点 List Tools,能看到 add / subtract / multiply / divide 四个工具;
  3. 输入 a=6, b=7 运行 multiply,返回 42

pic26.png

五、在 VS Code GitHub Copilot 中使用该 Server

步骤 1:配置 mcp.json

VS Code 通过 mcp.json 管理 MCP Server,有两个位置:

  • 工作区级.vscode/mcp.json(推荐,可以提交到 git 共享给团队)
  • 用户级:命令面板执行 MCP: Open User Configuration(所有工作区可用)

mcp-calculator 目录下新建 .vscode/mcp.json

{
  "servers": {
    "calculator": {
      "type": "stdio",
      "command": "node",
      "args": ["${workspaceFolder}/calculator-server.js"]
    }
  }
}

字段说明(stdio 类型):

字段必填说明
typestdio(本地)/ httpsse(远程)
command启动命令,必须在 PATH 中或写全路径
args传给命令的参数数组

${workspaceFolder} 要输入真实的文件目录路径。

步骤 2:启动 Server

配置保存后,mcp.json 里对应 server 上方会出现 启动 的 CodeLens,点击 启动

启动后,VS Code 会连接进程并发现该 Server 暴露的工具

也可以用命令面板:MCP: List Servers → 选中 calculator → 启动服务器。

步骤 3:在 Copilot Chat 中启用工具

  1. 打开 Chat 视图(⌃⌘I);
  2. 把对话模式切换到 Agent
  3. 点击输入框的 Configure Tools(配置工具) 按钮,展开后能看到 calculator 这个 MCP Server 下的四个工具;

pic28.png

  1. 勾选(或全部勾选)add / subtract / multiply / divide

pic29.png

步骤 4:用自然语言验证

在 Agent 模式下依次输入:

帮我算一下 (128 * 37) - 456 等于多少?

pic27.png

上述 mcp server 的源码已上传 github 仓库:github.com/Panda-plus5…

六、小结

  1. MCP 是一套协议,解决的是 AI 应用与外部工具/数据之间的标准化连接问题,把 N × M 的适配爆炸变成 N + M
  2. Host / Client / Server 三个角色分工明确;Server 提供 Tools / Resources / Prompts 三类能力;传输层可选 stdio(本地)或 Streamable HTTP(远程)。
  3. 用 v2 的 @modelcontextprotocol/server 写一个 MCP Server 只需要三步:建实例 → registerTool 注册工具 → connect(StdioServerTransport)
  4. 想要模型「用对」工具,重点在于打磨 工具名 + description + inputSchema,而不是工具内部逻辑多复杂。
  5. 在 VS Code 中接入只需一份 .vscode/mcp.json:配置 → 启动 → Agent 模式下勾选工具 → 用自然语言提问。

七、参考链接

  • MCP 官方文档:modelcontextprotocol.io
  • MCP 规范(2026-07-28):modelcontextprotocol.io/specificati…
  • TypeScript SDK 源码:github.com/modelcontex…
  • MCP 官方 Server 参考实现:github.com/modelcontex…
  • MCP Inspector(调试工具):github.com/modelcontex…
  • VS Code 官方文档《Add and manage MCP servers in VS Code》:code.visualstudio.com/docs/agent-…
  • VS Code MCP 配置参考:code.visualstudio.com/docs/agents…

热门栏目