你有没有想过一个问题:为什么 ChatGPT 能帮你写代码,却不能帮你查一下数据库里有多少用户?
答案很简单——它没有权限,也没有通道。
AI 模型再聪明,也只能在"沙盒"里运转。它看不到你的文件系统,摸不到你的 API,更不知道你的 PostgreSQL 里存了什么。
MCP(Model Context Protocol)就是解决这个问题的。
它是 Anthropic 在 2024 年底提出的开放协议,目标只有一个:给 AI 一个标准化的方式来调用外部工具和读取外部数据。你可以把它理解成 AI 时代的 USB-C 接口——不管是 Claude、ChatGPT 还是 Gemini,只要支持 MCP,就能用同一套标准连接你的服务。
截至 2026 年初,Anthropic、OpenAI、Microsoft 都已宣布支持 MCP。这不再是某一家的私有协议,而是行业共识。
学会写 MCP Server,意味着你的任何服务——数据库、内部 API、文件系统、甚至硬件设备——都能被 AI 直接调用。
这篇教程,就是带你从零开始写一个。
前置准备
在动手之前,确认你的机器上有以下工具:
- Node.js 18+(推荐 20 LTS)
- TypeScript(本教程使用 TS,但纯 JS 也能跑)
- 一个终端(macOS Terminal、Windows PowerShell、VS Code 内置终端都行)
- Claude Desktop 或 Claude Code(用于最终测试)
如果你还没安装 Node.js,去 nodejs.org 下载 LTS 版本,一路 Next 就行。
Step 1:初始化项目
打开终端,创建一个新目录并初始化:
mkdir my-mcp-server && cd my-mcp-server
npm init -y
npm install @modelcontextprotocol/sdk zod
npm install -D typescript @types/node
npx tsc --init
这五行做了什么:
- 创建项目目录并进入
- 初始化
package.json - 安装 MCP SDK(核心库)和 Zod(参数校验)
- 安装 TypeScript 和 Node 类型定义(开发依赖)
- 生成
tsconfig.json
接下来修改 tsconfig.json,确保以下配置正确:
{
"compilerOptions": {
"target": "ES2022",
"module": "Node16",
"moduleResolution": "Node16",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true
},
"include": ["src/**/*"]
}
再修改 package.json,添加两行:
{
"type": "module",
"scripts": {
"build": "tsc",
"start": "node dist/index.js"
}
}
"type": "module"很关键。MCP SDK 使用 ESM 模块,没有这行会报ERR_REQUIRE_ESM错误。这是新手最常踩的第一个坑。
Step 2:理解 MCP 的三个核心概念
在写代码之前,先搞清楚 MCP 的三个原语(Primitives)。不需要记住所有细节,理解类比就够了:
1. Tools — AI 可以调用的"函数"
类比:遥控器上的按钮。按一下"查询用户",就执行一次查询。
Tools 是最常用的能力。AI 看到你注册的工具列表和描述后,会自主判断什么时候该调用哪个工具、传什么参数。
2. Resources — AI 可以读取的"数据源"
类比:书架上的书。AI 知道有哪些书,需要的时候去翻。
Resources 是只读的数据,比如配置文件、数据库 Schema、系统状态。AI 可以主动请求读取。
3. Prompts — 预设的对话模板
类比:常用话术手册。“遇到客户投诉,先说 XX,再说 XX。”
Prompts 提供结构化的对话模板,引导 AI 按特定流程处理问题。
本教程聚焦 Tools,因为它是 90% 场景的核心。掌握了 Tools,Resources 和 Prompts 的写法大同小异。
Step 3:写你的第一个 MCP Server
创建 src/index.ts 文件:
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
// 1. 创建 MCP Server 实例
const server = new McpServer({
name: "my-first-mcp",
version: "1.0.0",
});
// 2. 注册一个简单工具:获取当前时间
server.tool(
"get_current_time", // 工具名称(AI 用这个来调用)
"获取当前的日期和时间", // 工具描述(AI 根据这个判断何时使用)
{}, // 参数定义(这个工具不需要参数)
async () => {
return {
content: [{
type: "text",
text: new Date().toLocaleString("zh-CN", { timeZone: "Asia/Shanghai" })
}]
};
}
);
// 3. 注册一个带参数的工具:计算 BMI
server.tool(
"calculate_bmi",
"根据身高体重计算 BMI 指数",
{
height: z.number().describe("身高(厘米)"),
weight: z.number().describe("体重(公斤)"),
},
async ({ height, weight }) => {
const heightM = height / 100;
const bmi = weight / (heightM * heightM);
let category = "";
if (bmi < 18.5) category = "偏瘦";
else if (bmi < 24) category = "正常";
else if (bmi < 28) category = "偏胖";
else category = "肥胖";
return {
content: [{
type: "text",
text: `BMI: ${bmi.toFixed(1)},分类: ${category}`
}]
};
}
);
// 4. 启动服务器
const transport = new StdioServerTransport();
await server.connect(transport);
逐段解释:
第 1 段:创建实例。 name 和 version 是必填项,客户端用它们来识别你的 Server。
第 2 段:注册 get_current_time 工具。 这是一个零参数工具——AI 调用它不需要传任何东西,直接返回当前时间。注意返回值的格式:必须是 { content: [{ type: "text", text: "..." }] }。这是 MCP 协议规定的标准格式。
第 3 段:注册 calculate_bmi 工具。 这个工具需要两个参数:height 和 weight。参数用 Zod Schema 定义,AI 会根据 .describe() 里的描述来理解每个参数的含义。
第 4 段:启动。 StdioServerTransport 意味着 Server 通过标准输入/输出(stdin/stdout)和客户端通信。这是本地运行 MCP Server 的标准方式。
注意:MCP SDK 的 API 在持续演进。从 v2 版本开始,官方推荐使用
server.registerTool()替代server.tool(),配置通过对象传入。但server.tool()在当前版本仍然可用,且语法更简洁,适合入门学习。
Step 4:编译和测试
编译 TypeScript:
npm run build
如果没有报错,dist/ 目录下会生成 index.js。
你可以先用命令行快速验证 Server 能否启动:
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}' | node dist/index.js
如果看到一段 JSON 响应(包含 serverInfo),说明 Server 运行正常。
如果报错
Cannot find module,检查package.json里有没有"type": "module"。这是最常见的问题。
Step 5:连接到 Claude Desktop
MCP Server 本身只是一个程序。要让 AI 用上它,需要在客户端配置。
以 Claude Desktop 为例,编辑配置文件:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
添加以下内容:
{
"mcpServers": {
"my-first-mcp": {
"command": "node",
"args": ["/你的绝对路径/my-mcp-server/dist/index.js"]
}
}
}
务必使用绝对路径。 相对路径在 Claude Desktop 中不可靠。
保存后重启 Claude Desktop。如果配置正确,你会在对话界面看到一个工具图标(锤子或扳手),点击可以看到 get_current_time 和 calculate_bmi 两个工具。
现在试着对 Claude 说:“现在几点了?” 或者 “帮我算一下 BMI,我身高 175cm,体重 70kg”。
Claude 会自动识别意图,调用你的 MCP Server,然后把结果整合到回答中。
如果你用的是 Claude Code,配置更简单。在项目根目录创建 .mcp.json:
{
"mcpServers": {
"my-first-mcp": {
"command": "node",
"args": ["dist/index.js"]
}
}
}
启动 Claude Code 后,它会自动加载这个 Server。
Step 6:进阶 — 连接数据库
到这里,你已经能写一个基础的 MCP Server 了。但真正有价值的场景是让 AI 操作你的数据。
下面展示如何添加一个查询 SQLite 的工具。先安装依赖:
npm install better-sqlite3
npm install -D @types/better-sqlite3
然后在 src/index.ts 中添加:
import Database from "better-sqlite3";
server.tool(
"query_users",
"查询用户表中的数据",
{
limit: z.number().optional().default(10).describe("返回数量限制"),
},
async ({ limit }) => {
const db = new Database("./users.db");
const rows = db.prepare("SELECT * FROM users LIMIT ?").all(limit);
db.close();
return {
content: [{ type: "text", text: JSON.stringify(rows, null, 2) }]
};
}
);
这段代码做了什么:
- 打开当前目录下的
users.db文件 - 执行
SELECT * FROM users查询,限制返回条数 - 将结果序列化为 JSON 返回给 AI
AI 拿到原始数据后,会自动进行分析、汇总、对比——这才是 MCP 的威力所在。你不需要写任何可视化逻辑或报表页面,AI 就是你的"数据分析师"。
安全提醒:上面的示例用了只读查询。在生产环境中,一定要对 SQL 做白名单校验或限制为只读模式(
new Database("./users.db", { readonly: true })),防止 AI 误执行 DELETE 或 DROP。
Step 7:发布到 npm(可选)
如果你想让别人也能用你的 MCP Server,可以发布到 npm。
在 package.json 中添加:
{
"name": "mcp-server-my-tool",
"bin": {
"mcp-server-my-tool": "dist/index.js"
},
"files": ["dist"]
}
在 dist/index.js 文件顶部确保有 shebang:
#!/usr/bin/env node
然后:
npm login
npm publish
发布后,别人就可以这样使用:
npx mcp-server-my-tool
常见问题
Q: MCP Server 崩溃了怎么办?
查看 stderr 输出。MCP 的通信走 stdout,而错误信息走 stderr。如果你在 Claude Desktop 中遇到问题,可以在终端手动运行 node dist/index.js,看有没有报错。Claude Desktop 的日志目录在 ~/Library/Logs/Claude/ 下。
Q: Claude 看不到我的工具?
三个排查步骤:(1) 确认配置文件中的路径是绝对路径;(2) 确认 npm run build 编译成功;(3) 完全退出 Claude Desktop 后重新打开(不是关窗口,是 Quit)。
Q: 能同时运行多个 MCP Server 吗?
可以。在配置文件的 mcpServers 对象中添加多个条目即可。每个 Server 都是独立进程,互不干扰。
Q: 除了 stdio,还有别的通信方式吗?
有。MCP SDK 还支持 Streamable HTTP 传输,适合远程部署的场景。本地开发用 stdio 就够了。
下一步
你已经掌握了 MCP Server 的核心开发流程。接下来可以探索:
- 官方文档:modelcontextprotocol.io — 协议规范和 SDK 参考
- 社区 Server 列表:github.com/punkpeye/awesome-mcp-servers — 数百个现成的 MCP Server,涵盖数据库、API、文件系统、浏览器控制等
- 给自己的 API 写适配层:你公司内部有 REST API?花 30 分钟给它套一层 MCP,就能让 AI 直接调用。这是最有实战价值的练习
MCP 的核心思想并不复杂:定义工具、描述参数、返回结果。 剩下的——什么时候调用、传什么参数、怎么组合多个工具的输出——全部交给 AI 来决策。
你要做的,就是把你的能力"暴露"出去。AI 会自己想办法用好它。
本文由 AIEII 编辑部撰写。如果你觉得这篇文章有价值,欢迎分享给你的朋友。