得一微PCIe Gen5 SSD主控亮相COMPUTEX 2026:AI存力架构赋能端侧AI应用
2026-07-13
2026-07-13 0
在前面的文章中,我们用 LangChain 的 tool() 函数注册了 read_file、execute_command 等工具。它们工作得很好,但有一个根本性局限——只能在同一个 Node.js 进程中运行。

这意味着:
MCP(Model Context Protocol) 正是为了解决这个问题而诞生的。它让 AI Agent 能够跨进程、跨语言地调用任何工具。
复制代码import { tool } from '@langchain/core/tools';const readFileTool = tool(
async ({ filePath }) => {
const content = await fs.readFile(filePath, 'utf-8');
return content;
},
{
name: 'read_file',
description: '读取文件内容',
schema: z.object({ filePath: z.string() })
}
);// 工具直接注册到模型
const modelWithTools = model.bindTools([readFileTool]);
| 问题 | 说明 |
|---|---|
| 项目绑定 | read_file 只能在当前 Node.js 项目中使用,换一个项目就得重写 |
| 语言绑定 | 只能用 JavaScript/TypeScript 编写,无法调用 Java/Python/Rust 工具 |
| 进程绑定 | 工具函数和 LLM 运行在同一个进程中,无法独立部署、独立扩展 |
复制代码LangChain Tool 的局限: Agent(Node.js 进程)
├── tool1: read_file ← 写死在代码里
├── tool2: write_file ← 写死在代码里
└── tool3: exec_command ← 写死在代码里 想加一个 Java 工具?→ 不行,进程语言是 Node.js
想在另一个项目复用?→ 不行,代码耦合在项目里
复制代码理想架构: AI Agent(任意语言/框架)
↓ MCP 协议
Tool A(Node.js)── 查询数据库
Tool B(Python)─── 数据分析
Tool C(Java)───── 调用内部 API
Tool D(Rust)───── 高性能计算 工具独立开发、独立部署、独立运行
Agent 通过统一协议调用,不关心工具用什么语言写的
复制代码MCP = Model Context Protocol(模型上下文协议)目标:标准化 LLM 与 Tool / Resource 之间的通信
本质:让 LLM 和 Tool 解耦
MCP 不是工具、不是框架、不是 SDK——它是一个通信协议,就像 HTTP 是浏览器和服务器之间的通信协议一样。
| 通信方式 | 适用场景 | 底层技术 |
|---|---|---|
| stdio | 本地跨进程调用 | 标准输入输出流(stdin/stdout) |
| HTTP/SSE | 远程跨进程调用 | 网络请求 |
复制代码AI Agent(父进程)
↓ spawn 启动子进程
MCP Server(子进程)
├── 通过 stdin 接收 Agent 的请求(JSON-RPC)
└── 通过 stdout 返回结果(JSON-RPC)
底层原理:当 Agent 启动一个 MCP Server 子进程时(类似 child_process.spawn),两者通过标准输入输出流通信。Agent 向子进程的 stdin 写入 JSON-RPC 消息,子进程处理后将结果写入 stdout。
复制代码AI Agent(客户端)
↓ HTTP 请求
远程 MCP Server(服务器)
├── 接收请求
├── 调用工具
└── 返回结果
笔记中有一个精准的区分:
| 维度 | fetch / HTTP API | MCP |
|---|---|---|
| 目的 | 获取数据(接口调用) | 扩展 Context(工具 + 资源) |
| 协议 | HTTP + REST | JSON-RPC over stdio/HTTP |
| 通信方向 | 单次请求-响应 | 持续的双向通信 |
| 能力 | 只能传数据 | 可以注册工具、暴露资源、持续交互 |
MCP 不是"调接口拿数据",而是"给模型装上新的能力"——它扩展的是 Context(上下文),让 LLM 能做的更多(Tool)、知道的更多(Resource)。
复制代码MCP 的本质 = 给 Model 扩展 Context Tool(工具) → 让 LLM 能做更多(读文件、查数据库、发邮件)
Resource(资源)→ 让 LLM 知道更多(内部文档、数据、配置)
复制代码my-mcp-server/
├── my-mcp-server.mjs # MCP Server 代码(45行)
├── package.json
└── .mcp.json # Claude Code 接入配置
my-mcp-server.mjs:
复制代码import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { z } from 'zod';// 模拟数据库(未来可替换为真实数据库)
const database = {
users: {
'001': { id: '001', name: '祖豪', email: '[email protected]', role: 'admin' },
'002': { id: '002', name: '光光', email: '[email protected]', role: 'user' },
'003': { id: '003', name: '小红', email: '[email protected]', role: 'user' },
}
};// 创建 MCP Server 实例
const server = new McpServer({
name: 'my-mcp-server',
version: '1.0.0'
});// 注册工具
server.registerTool('query_user', {
description: `查询数据库中的用户信息。输入用户ID,
返回该用户的详细信息(姓名、邮箱、角色)`,
inputSchema: {
userId: z.string().describe('用户ID, 例如:001, 002, 003')
}
}, async (userId) => {
const user = database.users[userId];
if (!user) {
return {
content: [
{ type: 'text', text: `用户 ID ${userId} 不存在。
可用的ID: 001, 002, 003`}
]
};
}
return {
content: [
{
type: 'text',
text: `用户 ${user.id} 的信息是:
姓名:${user.name}, 邮箱:${user.email}, 角色:${user.role}`
}
]
};
});// 启动 stdio 传输
const transport = new StdioServerTransport();
await server.connect(transport);
第一步:模拟数据库
复制代码const database = {
users: {
'001': { id: '001', name: '祖豪', email: '[email protected]', role: 'admin' },
// ...
}
};
这里用内存对象模拟数据库。实际项目中,可以替换为 MySQL、PostgreSQL、MongoDB 等真实数据库连接。MCP Server 的魅力就在于此——底层实现可以随意替换,对 Agent 来说接口不变。
第二步:注册工具(registerTool vs tool)
注意这里用的是 server.registerTool,不是 LangChain 的 tool():
| 对比项 | LangChain tool() | MCP server.registerTool() |
|---|---|---|
| 注册位置 | LangChain 模型绑定 | MCP Server 实例 |
| 调用方式 | 同进程函数调用 | 跨进程 JSON-RPC |
| 语言限制 | JavaScript only | 任何语言(有 MCP SDK 即可) |
| 复用性 | 项目内 | 跨项目 |
第三步:输入参数
复制代码inputSchema: {
userId: z.string().describe('用户ID, 例如:001, 002, 003')
}
Zod Schema 定义了工具接受的参数类型和描述。MCP SDK 会将其自动转换为 JSON Schema 发送给 LLM。
第四步:返回格式
复制代码return {
content: [
{ type: 'text', text: '...' }
]
};
MCP 标准返回格式:content 数组,每个元素包含 type 和 text(或 image)。
.mcp.json:
复制代码{
"mcpServers": {
"my-db": {
"type": "stdio",
"command": "node",
"args": ["/path/to/my-mcp-server.mjs"]
}
}
}
使用方式:
复制代码⟩ 使用 my-db 工具查询用户 001 的信息
Claude Code 会自动:
my-db MCP Client{ "userId": "001" } 复制代码LangChain Tool(同进程): ┌─────────────────────────────┐
│ Node.js 进程 │
│ │
│ LLM ←→ tool() ←→ 函数体 │
│ 全部在一个进程内 │
└─────────────────────────────┘
MCP Tool(跨进程): ┌─────────────────────┐ ┌─────────────────────┐
│ Agent 进程(Host) │ │ MCP Server 进程 │
│ │ │ │
│ LLM ←→ MCP Client │ ←──→ │ MCP Server ←→ 工具 │
│ │ stdio│ │
└─────────────────────┘ └─────────────────────┘
| 维度 | LangChain Tool | MCP Tool |
|---|---|---|
| 通信方式 | 同进程函数调用 | 跨进程 JSON-RPC |
| 语言支持 | JavaScript only | Node.js / Python / Java / Rust ... |
| 复用性 | 项目内绑定 | 跨项目、跨 Agent 复用 |
| 部署 | 随 Agent 一起部署 | 独立部署、独立运行 |
| 数据源 | 内存中的函数 | 任意(数据库、API、文件) |
| 适用场景 | 快速原型、简单工具 | 生产环境、复杂工具链 |
| 场景 | 推荐 |
|---|---|
| 项目 Demo / 快速验证 | LangChain tool() |
| 只需在本项目使用的简单工具 | LangChain tool() |
| 需要跨项目复用的工具 | MCP Server |
| 需要用其他语言编写的工具 | MCP Server |
| 需要独立部署的数据库/API 工具 | MCP Server |
| 多个 Agent 共享同一套工具 | MCP Server |
复制代码import mysql from 'mysql2/promise';const pool = mysql.createPool({
host: 'localhost',
user: 'root',
password: 'password',
database: 'my_app'
});server.registerTool('query_user', {
description: '查询 MySQL 数据库中的用户信息',
inputSchema: {
userId: z.string().describe('用户ID')
}
}, async (userId) => {
const [rows] = await pool.execute(
'SELECT id, name, email, role FROM users WHERE id = ?', [userId]
);
if (rows.length === 0) {
return { content: [{ type: 'text', text: `用户 ${userId} 不存在` }] };
}
const user = rows[0];
return {
content: [{
type: 'text',
text: `姓名:${user.name}, 邮箱:${user.email}, 角色:${user.role}`
}]
};
});
关键点:MCP Server 的接口(注册工具、返回格式)不变,只是底层实现从内存对象换成了 MySQL 连接。Agent 完全感知不到这个变化——这就是协议解耦的威力。
复制代码MCP 跨进程工具调用深度解析
├── LangChain Tool 的局限
│ ├── 项目绑定(只能在本项目用)
│ ├── 语言绑定(只能用 JS)
│ └── 进程绑定(和 LLM 在同一进程)
├── MCP 协议
│ ├── Model Context Protocol(模型上下文协议)
│ ├── 核心目标:LLM 与 Tool/Resource 解耦
│ ├── 两种通信方式
│ │ ├── stdio(本地跨进程:stdin/stdout)
│ │ └── HTTP/SSE(远程跨进程)
│ ├── MCP vs fetch(扩展 Context vs 获取数据)
│ └── MCP 本质:给 Model 扩展 Context
├── 实战:数据库查询 MCP Server
│ ├── 模拟数据库 → 可替换为 MySQL/PG
│ ├── server.registerTool() 注册工具
│ ├── Zod Schema 参数定义
│ ├── MCP 标准返回格式(content 数组)
│ └── .mcp.json 接入 Claude Code
├── LangChain Tool vs MCP Tool 对比
│ ├── 同进程 vs 跨进程
│ ├── JS only vs 多语言
│ └── 何时用哪种
└── 进阶方向
├── 替换为真实数据库(MySQL)
├── 添加更多工具(增删改查)
└── 多 Agent 共享同一 MCP Server
从 LangChain tool() 到 MCP server.registerTool(),表面上看只是换了一种注册方式,本质上是一次架构升级:
tool() 是进程内函数调用——简单直接,但受限于语言和项目registerTool() 是跨进程协议通信——复杂一些,但打破了所有边界理解了这个区别,你就理解了 MCP 的核心价值:让工具独立于 LLM,让能力可以被任何 Agent 复用。
参考与拓展阅读:
@modelcontextprotocol/sdk GitHub 仓库#MCP #Node.js #跨进程通信 #AIAgent #ToolCalling #掘金技术社区