2026年MCP协议实战指南:手把手教你构建个人AI助手(含完整代码)
前言
最近在团队里搞了一阵子 MCP(Model Context Protocol)集成,踩了不少坑,也积累了一些经验。今天把整个过程整理出来,希望能帮到正在折腾 AI Agent 开发的朋友。
说白了,MCP 就是让大模型能"动手干活"的标准协议。以前我们跟大模型聊天,它只能输出文字;有了 MCP,它能读文件、查数据库、调 API,甚至操控你的开发环境。

什么是MCP协议?
MCP(Model Context Protocol)是 Anthropic 在 2024 年底开源的一个协议标准。它的核心思路很简单:把大模型和外部工具之间的通信标准化。
你可以把它类比成 USB 接口——以前每种设备都有自己的专用接口,USB 出来之后统一了。MCP 干的就是这件事,只不过对象是 AI 模型和各种工具/数据源。
MCP 的三个核心概念
- Server(服务端):提供工具能力的一方,比如文件系统访问、数据库查询、API 调用等
- Client(客户端):发起请求的一方,通常是 AI 应用或 IDE
- Protocol(协议):定义了双方通信的 JSON-RPC 消息格式
// MCP 消息的基本结构
interface McpRequest {
jsonrpc: "2.0";
id: number;
method: string;
params?: Record<string, unknown>;
}
interface McpResponse {
jsonrpc: "2.0";
id: number;
result?: unknown;
error?: {
code: number;
message: string;
};
}
环境准备
动手之前,先把环境搭好:
| 依赖 | 版本要求 | 说明 |
|---|---|---|
| Node.js | ≥ 18.0 | 推荐 20 LTS |
| TypeScript | ≥ 5.0 | 类型安全 |
| @modelcontextprotocol/sdk | latest | 官方 SDK |
# 初始化项目
mkdir my-mcp-server && cd my-mcp-server
npm init -y
npm install @modelcontextprotocol/sdk zod
npm install -D typescript @types/node
# 初始化 TypeScript 配置
npx tsc --init

实战:从零构建一个文件系统 MCP Server
我们来做一个实际有用的东西——文件系统 MCP Server。它能让 AI 助手直接读写你本地的文件。
第一步:定义 Server 基础结构
// src/index.ts
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
CallToolRequestSchema,
ListToolsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
import * as fs from "fs/promises";
import * as path from "path";
const server = new Server(
{ name: "filesystem-server", version: "1.0.0" },
{ capabilities: { tools: {} } }
);
第二步:注册工具(Tools)
MCP 的核心就是工具注册。每个工具都有名称、描述和参数 schema:
// 列出所有可用工具
server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [
{
name: "read_file",
description: "读取指定路径的文件内容",
inputSchema: {
type: "object",
properties: {
path: { type: "string", description: "文件的绝对路径" }
},
required: ["path"]
}
},
{
name: "write_file",
description: "将内容写入指定路径的文件",
inputSchema: {
type: "object",
properties: {
path: { type: "string", description: "文件的绝对路径" },
content: { type: "string", description: "要写入的内容" }
},
required: ["path", "content"]
}
},
{
name: "list_directory",
description: "列出目录下的所有文件和子目录",
inputSchema: {
type: "object",
properties: {
path: { type: "string", description: "目录路径" }
},
required: ["path"]
}
}
]
}));
第三步:实现工具处理逻辑
// 处理工具调用
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
switch (name) {
case "read_file": {
const filePath = args.path as string;
const content = await fs.readFile(filePath, "utf-8");
return {
content: [{ type: "text", text: content }]
};
}
case "write_file": {
const filePath = args.path as string;
const content = args.content as string;
await fs.writeFile(filePath, content, "utf-8");
return {
content: [{ type: "text", text: `文件已写入: ${filePath}` }]
};
}
case "list_directory": {
const dirPath = args.path as string;
const entries = await fs.readdir(dirPath, { withFileTypes: true });
const listing = entries.map(e =>
`${e.isDirectory() ? "📁" : "📄"} ${e.name}`
).join("\n");
return {
content: [{ type: "text", text: listing }]
};
}
default:
throw new Error(`未知工具: ${name}`);
}
});
第四步:启动 Server
// 启动服务
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("MCP Server 已启动");
}
main().catch(console.error);
与 Claude Desktop 集成
Server 写好了,怎么用呢?最简单的方式是集成到 Claude Desktop。
编辑 claude_desktop_config.json:
{
"mcpServers": {
"filesystem": {
"command": "node",
"args": ["/path/to/my-mcp-server/dist/index.js"],
"env": {}
}
}
}
重启 Claude Desktop,你就能在对话中让它直接读写文件了。

踩坑记录
搞了一段时间,总结几个常见的坑:
坑1:stdio 通信缓冲问题
用 StdioServerTransport 的时候,如果你在 Server 代码里用了 console.log,会导致 JSON-RPC 消息解析失败。因为 stdout 是通信通道,任何非协议输出都会污染它。
// ❌ 错误:用 console.log
console.log("Server started");
// ✅ 正确:用 console.error
console.error("Server started");
坑2:工具参数类型不匹配
MCP 的工具参数 schema 用的是 JSON Schema,但 TypeScript 侧的类型推断有时候会对不上。建议用 zod 做一次额外的参数校验:
import { z } from "zod";
const ReadFileSchema = z.object({
path: z.string().min(1, "路径不能为空"),
});
// 在 handler 里校验
const parsed = ReadFileSchema.safeParse(args);
if (!parsed.success) {
return {
content: [{ type: "text", text: `参数错误: ${parsed.error.message}` }],
isError: true
};
}
坑3:Windows 路径兼容
Windows 上用反斜杠路径(C:\\Users\\...)在 JSON 传输时需要额外转义。建议统一用正斜杠或者 path.resolve() 处理。
常见问题 Q&A
Q1: MCP 和 Function Calling 有什么区别?
Function Calling 是各大模型厂商各自实现的,格式不统一。MCP 是一个开放标准,理论上任何支持 MCP 的客户端都能连上任何 MCP Server。就像 REST API 统一了 Web 服务一样。
Q2: MCP Server 能访问网络吗?
当然可以。你可以写一个 MCP Server 来封装任何 HTTP API,比如查天气、查股票、调用内部系统接口等。
Q3: 安全性怎么保证?
MCP Server 运行在本地,权限等同于当前用户。生产环境建议:限制可访问的目录范围、对写操作做确认、记录操作日志。
Q4: Python 能写 MCP Server 吗?
可以。官方有 Python SDK:pip install mpython。核心概念一样,只是语言不同。
总结
MCP 协议把 AI 模型和外部工具的连接标准化了,这对 Agent 开发来说是质的飞跃。从技术角度看,它的设计足够简洁(JSON-RPC over stdio/SSE),上手成本低;从生态角度看,已经有大量现成的 MCP Server 可以直接用。
如果你正在做 AI 应用开发,强烈建议现在就开始接触 MCP。等到 Agent 生态成熟的时候,这就是基本功了。
项目完整代码已上传 GitHub,需要的朋友可以在评论区留言。
更多推荐




所有评论(0)