1. 引言:为什么需要MCP?

在AI Agent(智能体)开发领域,工具调用(Tool Calling)是连接大语言模型与现实世界的关键桥梁。然而,传统的工具集成方式往往面临以下挑战:

  • 厂商锁定:不同AI平台(如OpenAI、Anthropic、Google)的工具调用API互不兼容。
  • 开发复杂:为每个Agent重复定义工具接口、编写适配代码。
  • 部署困难:工具与Agent强耦合,难以独立更新和扩展。

Model Context Protocol(MCP)正是为解决这些问题而生。它是由Anthropic主导的开源协议,旨在为AI模型提供标准化的工具调用和上下文管理接口。通过MCP,开发者可以:

  • 一次定义工具,多处使用(跨平台、跨模型)。
  • 将工具作为独立服务运行,实现解耦和弹性扩展。
  • 利用丰富的开源工具生态,快速构建功能强大的Agent。

本文将带你从零开始,通过实战项目搭建一个基于MCP的完整AI Agent工具链。

2. MCP核心概念与架构

2.1 协议三层架构

MCP协议采用清晰的三层架构:

  1. 客户端(Client):通常是AI模型或应用(如Claude Desktop、Cursor),负责发起工具调用请求。
  2. 服务器(Server):工具提供方,实现具体的工具逻辑并通过MCP协议暴露接口。
  3. 传输层(Transport):支持Stdio(标准输入输出)和SSE(Server-Sent Events)两种通信方式。

这种架构使得工具开发与AI应用完全解耦。

2.2 核心资源类型

MCP定义了四种核心资源类型:

  • 工具(Tools):可执行的操作,如查询天气、发送邮件、执行代码。
  • 提示词模板(Prompts):预定义的提示词片段,支持参数化。
  • 资源(Resources):只读数据源,如文档、API文档、数据库schema。
  • 采样器(Samplers):用于控制模型生成行为的配置。

3. 环境准备与项目初始化

3.1 开发环境要求

  • Node.js 18+ 或 Python 3.9+
  • npm/pip 包管理器
  • 代码编辑器(推荐VS Code)
  • Claude Desktop(用于测试MCP工具)

3.2 初始化Node.js MCP服务器项目

# 创建项目目录
mkdir mcp-weather-server
cd mcp-weather-server
初始化npm项目
npm init -y
安装MCP SDK
npm install @modelcontextprotocol/sdk
安装依赖
npm install axios dotenv

3.3 项目结构规划

mcp-weather-server/
├── src/
│   ├── server.js          # MCP服务器主文件
│   ├── tools/             # 工具实现
│   │   └── weather.js     # 天气查询工具
│   └── config.js          # 配置文件
├── package.json
├── .env.example          # 环境变量示例
└── README.md

4. 实战一:构建天气查询MCP工具

4.1 创建MCP服务器

src/server.js中创建基础MCP服务器:

import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { 
  CallToolRequestSchema,
  ListToolsRequestSchema 
} from "@modelcontextprotocol/sdk/types.js";
// 创建MCP服务器实例
const server = new Server(
{
name: "weather-mcp-server",
version: "1.0.0",
},
{
capabilities: {
tools: {}, // 声明支持工具功能
},
}
);
// 注册工具列表处理器
server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [
{
name: "get_weather",
description: "获取指定城市的当前天气信息",
inputSchema: {
type: "object",
properties: {
city: {
type: "string",
description: "城市名称,如:北京、上海、New York"
},
units: {
type: "string",
enum: ["metric", "imperial"],
description: "温度单位:metric(摄氏度) 或 imperial(华氏度)",
default: "metric"
}
},
required: ["city"]
}
}
]
};
});
// 启动服务器(使用Stdio传输)
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("Weather MCP Server started");

4.2 实现天气查询工具逻辑

创建src/tools/weather.js

import axios from "axios";
import dotenv from "dotenv";
dotenv.config();
// 使用OpenWeatherMap API(需要注册获取API Key)
const OPENWEATHER_API_KEY = process.env.OPENWEATHER_API_KEY;
const BASE_URL = "https://api.openweathermap.org/data/2.5/weather";
export async function getWeather(city, units = "metric") {
try {
const response = await axios.get(BASE_URL, {
params: {
q: city,
appid: OPENWEATHER_API_KEY,
units: units,
lang: "zh_cn"
}
});
const data = response.data;
return {
  city: data.name,
  country: data.sys.country,
  temperature: data.main.temp,
  feels_like: data.main.feels_like,
  humidity: data.main.humidity,
  pressure: data.main.pressure,
  weather: data.weather[0].description,
  wind_speed: data.wind.speed,
  wind_deg: data.wind.deg,
  icon: data.weather[0].icon,
  units: units === "metric" ? "°C" : "°F"
};
} catch (error) {
if (error.response?.status === 404) {
throw new Error(城市 "${city}" 未找到,请检查城市名称拼写);
}
if (error.response?.status === 401) {
throw new Error("API密钥无效,请检查OPENWEATHER_API_KEY配置");
}
throw new Error(天气查询失败: ${error.message});
}
}

4.3 注册工具调用处理器

server.js中添加工具调用处理:

import { getWeather } from "./tools/weather.js";
// 注册工具调用处理器
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
if (name === "get_weather") {
try {
const { city, units = "metric" } = args;
const weatherData = await getWeather(city, units);
  return {
    content: [
      {
        type: "text",
        text: `## ${weatherData.city}, ${weatherData.country} 天气\n` +
              `- **温度**: ${weatherData.temperature}${weatherData.units} (体感 ${weatherData.feels_like}${weatherData.units})\n` +
              `- **天气状况**: ${weatherData.weather}\n` +
              `- **湿度**: ${weatherData.humidity}%\n` +
              `- **气压**: ${weatherData.pressure} hPa\n` +
              `- **风速**: ${weatherData.wind_speed} m/s, 风向 ${weatherData.wind_deg}°`
      }
    ]
  };
} catch (error) {
  return {
    content: [
      {
        type: "text",
        text: `❌ 天气查询失败: ${error.message}`
      }
    ],
    isError: true
  };
}
}
return {
content: [
{
type: "text",
text: 未知工具: ${name}
}
],
isError: true
};
});

5. 实战二:配置与测试MCP工具

5.1 配置Claude Desktop使用MCP工具

创建Claude Desktop配置文件(macOS路径:~/Library/Application Support/Claude/claude_desktop_config.json):

{
  "mcpServers": {
    "weather": {
      "command": "node",
      "args": ["/path/to/your/mcp-weather-server/src/server.js"],
      "env": {
        "OPENWEATHER_API_KEY": "your_api_key_here"
      }
    }
  }
}

5.2 启动与验证

# 1. 启动MCP服务器(开发模式)
node src/server.js
2. 重启Claude Desktop
3. 在Claude中测试工具调用:
"查询北京今天的天气"

5.3 测试结果示例

成功调用后,Claude会返回格式化的天气信息:

Claude回复:我使用天气查询工具获取了北京的天气信息:

## 北京, CN 天气
- 温度: 15°C (体感 14°C)
- 天气状况: 晴
- 湿度: 45%
- 气压: 1015 hPa
- 风速: 3.2 m/s, 风向 180°

6. 进阶:构建工具链与管理多个MCP服务器

6.1 创建工具链管理器

对于需要多个MCP服务器的复杂场景,可以创建统一的管理器:

// mcp-manager.js
import { spawn } from 'child_process';
import fs from 'fs';
import path from 'path';
class MCPManager {
constructor(configPath) {
this.config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
this.servers = new Map();
}
async startAll() {
for (const [name, serverConfig] of Object.entries(this.config.mcpServers)) {
await this.startServer(name, serverConfig);
}
}
async startServer(name, config) {
return new Promise((resolve, reject) => {
const env = { ...process.env, ...config.env };
const serverProcess = spawn(config.command, config.args, { env });
  this.servers.set(name, serverProcess);
serverProcess.stderr.on('data', (data) => {
console.log([${name}] ${data.toString()});
});
serverProcess.on('close', (code) => {
console.log([${name}] 进程退出,代码: ${code});
this.servers.delete(name);
});
// 等待服务器就绪信号
setTimeout(() => {
console.log(✅ MCP服务器 "${name}" 已启动);
resolve();
}, 1000);
});
}
}
// 使用示例
const manager = new MCPManager('./mcp-config.json');
await manager.startAll();

6.2 常用MCP服务器推荐

服务器 功能 语言 GitHub仓库
filesystem 文件系统操作 TypeScript modelcontextprotocol/servers
postgres PostgreSQL数据库操作 TypeScript modelcontextprotocol/servers
github GitHub API集成 TypeScript modelcontextprotocol/servers
brave-search Brave搜索 Python modelcontextprotocol/servers

7. 生产环境部署与优化

7.1 安全性考虑

  • API密钥管理:使用环境变量或密钥管理服务,避免硬编码。
  • 输入验证:对所有工具参数进行严格的验证和清理。
  • 速率限制:实现请求限流,防止滥用。
  • 错误处理:避免泄露敏感信息在错误消息中。

7.2 性能优化

  • 连接池:对于数据库类工具,使用连接池减少开销。
  • 缓存策略:对频繁查询的数据添加缓存层。
  • 异步处理:耗时的操作使用异步模式,不阻塞主线程。
  • 健康检查:实现/health端点供监控系统使用。

7.3 容器化部署

创建Dockerfile

FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY src/ ./src/
USER node
EXPOSE 3000
CMD ["node", "src/server.js"]

8. 总结与展望

8.1 核心收获

通过本实战项目,我们掌握了:

  1. MCP协议的基本架构和工作原理
  2. 如何从零开发一个MCP服务器
  3. 在Claude Desktop中集成和使用自定义工具
  4. 构建可扩展的MCP工具链

8.2 MCP生态展望

MCP协议正在快速发展,未来可能的方向包括:

  • 更丰富的工具市场:像npm、PyPI一样的MCP工具仓库
  • 可视化工具编排:拖拽式配置复杂的工作流
  • 跨平台标准化:成为所有AI助手的事实标准工具协议
  • 企业级特性:审计日志、权限管理、SLA保障

8.3 下一步学习建议

  1. 阅读MCP官方文档深入了解协议细节
  2. 探索官方服务器示例学习更多工具模式
  3. 尝试将现有API服务封装为MCP工具
  4. 参与MCP社区,贡献自己的工具实现

MCP协议为AI Agent开发带来了真正的标准化和模块化。通过将工具开发与AI应用解耦,它让开发者能够专注于构建有价值的工具,而不必担心平台兼容性问题。随着生态的成熟,我们有望看到一个更加开放、互操作的AI工具未来。

Logo

中国智能体开发者社区,聚焦智能体与大模型开发,提供前沿资讯、实用工具链、开源项目及行业案例。通过技术沙龙、开发者大赛等活动,促进经验交流与协作,助力开发者快速构建创新智能应用。

更多推荐