MCP四层架构深度解析:解决AI Agent上下文记忆与工具调用难题

MCP 四层架构深度拆解:告别 Function Calling 的“单次调用”困境
想让你的 AI Agent 真正“记住”上下文,并能像调用本地函数一样安全、稳定地调用外部工具吗?
如果你正在开发复杂的 AI Agent,一定遇到过这些痛点:Function Calling 每次调用都是“一次性”的,缺乏状态管理;多工具集成时,上下文窗口被工具描述塞满;不同模型的 Function Calling 格式互不兼容,迁移成本巨大。Model Context Protocol (MCP) 正是为了解决这些问题而生的硬核协议。本文将首次系统披露其四层分层架构与 JSON-RPC 2.0 通信机制,并结合生产级开发实践,带你彻底搞懂 MCP 的技术突破。
一、MCP 不是另一个 Function Calling:四层架构解析
很多人将 MCP 简单理解为“更好的 Function Calling”,这是一个巨大的误解。Function Calling 是模型厂商定义的单次、无状态的函数调用接口,而 MCP 是一个完整的、有状态的客户端-服务器通信协议。它的核心是四层分层架构:
- 协议层 (Protocol Layer):基于 JSON-RPC 2.0,定义了
request、response、notification三种消息类型。这是通信的“语言规则”。 - 传输层 (Transport Layer):负责实际的数据传输。支持
stdio(标准输入输出,适合本地进程通信)和HTTP with SSE(服务器发送事件,适合远程服务)两种方式。 能力层 (Capability Layer):这是 MCP 的核心。它定义了 Server 可以提供的四大能力:
- Tools (工具):可执行的函数,如
read_file、query_database。 - Resources (资源):只读的数据源,如文件内容、数据库快照。
- Prompts (提示词模板):预定义的交互模板。
- Sampling (采样):允许 Server 请求 Client(即 AI 模型)进行一次推理,实现 Server 端的智能逻辑。
- Tools (工具):可执行的函数,如
- 会话层 (Session Layer):管理客户端与服务器之间的连接状态、能力协商和生命周期。这是实现“有状态”交互的关键。
关键区别:Function Calling 是“你问我答,答完即忘”。MCP 是“我们建立了一个持久连接,我知道你能做什么,你可以随时调用我(模型)的推理能力”。
二、通信机制实战:JSON-RPC 2.0 如何驱动一切
所有 MCP 通信都严格遵循 JSON-RPC 2.0 规范。我们通过一个生产级 FilesystemServer 的开发来透视其机制。
1. 初始化握手 (Handshake)
当客户端(如 Claude Desktop)连接到你的 MCP Server 时,首先进行能力协商:
// 客户端 -> 服务器
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"capabilities": {},
"clientInfo": { "name": "Claude", "version": "1.0" }
}
}
// 服务器 -> 客户端 (响应)
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"protocolVersion": "2024-11-05",
"capabilities": {
"tools": { "listChanged": true }, // 声明支持工具列表动态更新
"resources": { "subscribe": true } // 声明支持资源订阅
},
"serverInfo": { "name": "FilesystemServer", "version": "1.0" }
}
}2. 工具发现与调用
客户端会主动发现服务器提供了哪些工具:
// 客户端 -> 服务器:列出所有工具
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/list"
}
// 服务器 -> 客户端:返回工具列表
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"tools": [
{
"name": "read_file",
"description": "读取指定路径的文件内容",
"inputSchema": {
"type": "object",
"properties": {
"path": { "type": "string", "description": "文件路径" }
},
"required": ["path"]
}
}
// ... 其他工具定义
]
}
}当模型决定调用 read_file 工具时,客户端会发送一个 tools/call 请求。服务器执行后,返回结果。关键点:这个连接是持久的,服务器可以记住之前的调用状态(例如,记住用户的工作目录)。
三、MCP vs Function Calling vs Agent:一张对比表讲清关系
| 维度 | Function Calling | Agent (如 AutoGPT) | MCP |
|---|---|---|---|
| 本质 | 模型厂商定义的单次调用接口 | 基于 LLM 的自主决策循环框架 | 客户端与服务器间的有状态通信协议 |
| 状态 | 无状态,每次调用独立 | 有状态,依赖 Prompt 工程管理 | 有状态,由协议层和会话层保障 |
| 上下文 | 工具描述挤占上下文窗口 | 历史记录和工具描述都挤占窗口 | 工具描述在 Server 端,不占用模型上下文 |
| 集成 | 需为每个模型适配不同格式 | 框架耦合度高,难以标准化 | 一次开发,多端通用 (Claude, 龙虾, OpenClaw) |
| 安全性 | 调用逻辑在客户端,风险高 | 自主执行,风险不可控 | Server 掌控执行环境,可设权限沙箱 |
协同关系:一个强大的 AI Agent(如基于 LangChain 构建的),其底层可以使用 MCP 作为标准化的工具集成层。Agent 负责“决策循环”,MCP 负责“稳定、安全地执行工具调用并管理上下文”。
四、生产级开发:一个“数据库查询 MCP Server”的核心代码
下面是一个简化但生产可用的 MCP Server 核心片段(Node.js/TypeScript),用于安全地查询 PostgreSQL 数据库:

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 { Pool } from 'pg';
// 1. 初始化数据库连接池
const pool = new Pool({ connectionString: process.env.DATABASE_URL });
// 2. 创建 MCP Server 实例
const server = new Server(
{ name: "postgres-query-server", version: "1.0.0" },
{ capabilities: { tools: {} } }
);
// 3. 实现工具列表
server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [{
name: "query_database",
description: "执行只读 SQL 查询(仅支持 SELECT)",
inputSchema: {
type: "object",
properties: {
sql: { type: "string", description: "要执行的 SQL 查询语句" }
},
required: ["sql"]
}
}]
};
});
// 4. 实现工具调用逻辑(关键:安全与错误处理)
server.setRequestHandler(CallToolRequestSchema, async (request) => {
if (request.params.name === "query_database") {
const sql = request.params.arguments?.sql as string;
// 安全检查:强制只读
if (!sql.trim().toLowerCase().startsWith('select')) {
throw new Error("安全限制:仅允许执行 SELECT 查询");
}
try {
const result = await pool.query(sql);
// 返回结构化数据,便于模型理解
return {
content: [{
type: "text",
text: JSON.stringify({
rows: result.rows,
rowCount: result.rowCount,
fields: result.fields.map(f => f.name)
}, null, 2)
}]
};
} catch (error) {
throw new Error(`查询执行失败: ${(error as Error).message}`);
}
}
throw new Error(`未知工具: ${request.params.name}`);
});
// 5. 启动服务器
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("PostgreSQL MCP Server 已启动");
}
main().catch(console.error);部署步骤:
- 将上述代码保存为
server.ts。 npm init -y && npm install @modelcontextprotocol/sdk pg。- 编译:
npx tsc server.ts。 在 Claude Desktop 或龙虾客户端的配置文件中添加:
{ "mcpServers": { "postgres": { "command": "node", "args": ["server.js"], "env": { "DATABASE_URL": "postgresql://user:pass@localhost:5432/mydb" } } } }
五、硬技术突破:MCP 解决了什么根本问题?
- 上下文窗口解放:工具的详细描述(JSON Schema)存储在 MCP Server 端,仅在初始化时同步。模型只需知道工具名和简短描述,节省了 70% 以上的工具相关 Token 消耗。
- 状态持久化:Server 可以维护会话状态(如数据库连接、当前工作目录、API 限流计数器),实现真正的多轮工具交互。
- 安全沙箱:工具执行在独立的 Server 进程中,与主模型进程隔离。你可以轻松实现权限控制(如上面的只读 SQL 检查)、速率限制和审计日志。
- 生态统一:一次开发,即可在 Claude、龙虾 (yitb.com)、OpenClaw 等所有支持 MCP 的客户端中运行,彻底告别为每个平台重写插件的历史。
下一步行动
- 立即体验:在你的龙虾或 Claude Desktop 中,配置一个现成的 MCP Server(如官方提供的
filesystem或sqlite服务器),感受有状态工具调用的不同。 - 动手开发:复制上面的数据库查询 Server 代码,将其改为连接你自己的 MySQL 或 API,10 分钟内打造你的第一个私有化工具。
- 深入生态:访问龙虾官网的 MCP 生态板块,查看其他开发者发布的 Server,学习他们的架构设计,或者将你开发的 Server 发布到生态中。
MCP 不是未来,它已经是现在进行时。掌握它,你的 AI Agent 开发将进入一个全新的、工程化的阶段。