- 什么是mcp(modelcontextprotocol)
- mcp和manus的关系
- function calling
- mcp server
- mcp client
- 结语
1. 什么是MCP(Model Context Protocol)?
Model Context Protocol(模型上下文协议)是由Anthropic于2024年11月推出的开放标准,旨在建立大型语言模型(LLM)与外部数据源/工具间的统一通信协议。其核心价值在于:
- 协议标准化:定义LLM与外部系统交互的通用接口规范
- 上下文管理:支持动态维护对话/会话上下文状态
- 工具集成:通过声明式API集成数据库、API服务、业务系统等
- 性能优化:支持异步调用、批量处理等高级特性
与传统手工编写prompt的方式相比,MCP通过结构化协议实现:上下文状态自动管理(减少token浪费)、工具发现机制(动态加载功能)、错误重试策略(提升可靠性)等优势。
2. MCP和Manus的关系
Manus是首个将MCP协议成功商业化的AI应用平台(2025年初推出),其爆火直接推动了MCP的普及。二者的关系表现为:
- 技术验证:Manus验证了MCP在大规模商业场景中的可行性
- 生态共建:Manus贡献了20+官方适配器(数据库/云服务等)
- 协议演进:Manus的实战经验反哺MCP协议迭代(如新增流式响应支持)
- 市场教育:通过Manus的案例展示,企业更易理解MCP的价值
3. Function Calling的演进
MCP对传统Function Call机制的增强:
特性 | 传统方式 | MCP方案 |
---|---|---|
调用方式 | 同步单次调用 | 支持异步/批量调用 |
错误处理 | 简单重试 | 策略化重试+熔断机制 |
工具发现 | 静态预定义 | 动态注册/版本管理 |
权限控制 | 应用层实现 | 协议级OAuth2.0集成 |
监控指标 | 自定义埋点 | 标准化遥测数据输出 |
示例:通过MCP批量处理10个API调用,系统会自动优化为并行执行+统一结果聚合。
4. MCP Server
javascript
#!/usr/bin/env node
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 { JSDOM } from "jsdom";
const server = new Server(
{
name: "example-server",
version: "1.0.0",
},
{
capabilities: {
tools: {},
},
}
);
const WEATHER_TOOL = {
name: "weather_search",
description: "Can be used to query the weather",
inputSchema: {
type: "object",
properties: {
province: {
type: "string",
description: "Check the weather in the province",
},
city: {
type: "string",
description: "Check the weather for city",
},
},
required: ["query"],
},
};
const WIKI_TOOL = {
name: "wiki_search",
description: "It can be used to query the knowledge of a single keyword",
inputSchema: {
type: "object",
properties: {
query: {
type: "string",
description: "Query information",
},
},
required: ["query"],
},
};
server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [WEATHER_TOOL, WIKI_TOOL],
}));
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
let res;
switch (name) {
case "weather_search":
const { province, city } = args;
res = await fetch(`https://uapis.cn/api/weather?name=${city}`);
const data = await res.json();
if (data.code !== 200) {
return {
content: [
{ type: "text", text: `查询天气失败,错误码:${data.code}` },
],
isError: true,
};
}
return {
content: [{ type: "text", text: `查询到天气:${JSON.toString(data)}` }],
isError: false,
};
case "wiki_search":
if (!args.query) {
return {
content: [
{ type: "text", text: "The query parameter query is missing" },
],
isError: true,
};
}
const { query } = args;
res = await fetch(`https://baike.baidu.com/item/${query}`);
const info = await res.text();
return {
content: [{ type: "text", text: extractTextFromClasses(info) }],
isError: false,
};
}
});
function extractTextFromClasses(htmlStr) {
const classPrefix = "mainContent_";
// 创建一个新的 JSDOM 实例
const dom = new JSDOM(htmlStr);
// 获取 window 对象,以便访问 document
const { window } = dom;
// 使用 document.querySelectorAll 来选择所有匹配的元素
const elements = window.document.querySelectorAll(
`[class^="${classPrefix}"]`
);
let allText = "";
elements.forEach((element) => {
// 使用 element.textContent 来获取元素及其所有子节点的文本内容
allText += element.textContent.trim() + "\n";
});
return allText.trim(); // 返回所有文本内容,并去除末尾的换行符
}
async function runServer() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("MCP Server running on stdio");
}
runServer().catch((error) => {
console.error("Fatal error running server:", error);
process.exit(1);
});
关键组件:
- 天气查询:支持模型在线查询天气
- wiki查询:支持模型在线提取知识
5. MCP Client
- langchainjs+mcp-client实现ReAct Agent基本结构
javascript
import { HumanMessage, ToolMessage } from "@langchain/core/messages";
import { tool } from "@langchain/core/tools";
import { ChatOpenAI } from "@langchain/openai";
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
import { config } from "dotenv";
// 加载环境变量
config();
// 确保设置了百炼API密钥
if (!process.env.DASHSCOPE_API_KEY) {
console.error("错误: 请在.env文件中设置DASHSCOPE_API_KEY环境变量");
process.exit(1);
}
// 创建阿里通义千问模型实例
const llm = new ChatOpenAI({
apiKey: process.env.DASHSCOPE_API_KEY,
modelName: "qwen-plus", // 可以根据需要选择不同的模型
configuration: {
baseURL: "https://dashscope.aliyuncs.com/compatible-mode/v1",
},
});
const transport = new StdioClientTransport({
command: "node",
args: ["mcp-server.js"],
});
const client = new Client(
{
name: "example-client",
version: "1.0.0",
},
{
capabilities: {
tools: {},
},
}
);
async function main() {
await client.connect(transport);
const tools = await client.listTools();
console.log("工具集", tools.tools);
const mTools =tools.tools.map((tl) =>
tool(
async (toolInput) => {
const result = await client.callTool({
name: tl.name,
arguments: toolInput,
});
return result.content;
},
{
...tl,
schema: tl.inputSchema,
}
)
);
const toolMap = new Map(mTools.map((t) => [t.name, t]));
const llmWithTools = llm.bind({
tools: mTools,
});
const messages = [new HumanMessage("查询下山东省济南市的天气")];
let response = await llmWithTools.invoke(messages);
messages.push(response);
while (response.tool_calls && response.tool_calls.length > 0) {
console.log("工具被调用:", JSON.stringify(response.tool_calls, null, 2));
for (const toolCall of response.tool_calls) {
const toolResult = await toolMap.get(toolCall.name).call(toolCall.args);
console.log("工具结果: ", toolResult);
messages.push(
new ToolMessage({
content: toolResult,
tool_call_id: toolCall.id,
})
);
}
console.log("将工具结果发送回模型...");
response = await llmWithTools.invoke(messages);
messages.push(response);
}
console.log("最终模型回答:", response.content);
}
main()
- 响应结果
shell
demo % node mcp
node mcp
MCP Server running on stdio
工具集 [
{
name: 'weather_search',
description: 'Can be used to query the weather',
inputSchema: { type: 'object', properties: [Object], required: [Array] }
},
{
name: 'wiki_search',
description: 'It can be used to query the knowledge of a single keyword',
inputSchema: { type: 'object', properties: [Object], required: [Array] }
}
]
工具被调用: [
{
"name": "weather_search",
"args": {
"city": "济南市",
"province": "山东省"
},
"type": "tool_call",
"id": "call_d43959bd6cbd40c880d976"
}
]
工具结果: [ { type: 'text', text: '查询到天气:[object JSON]' } ]
将工具结果发送回模型...
最终模型回答: 山东省济南市的天气情况如下:
- 温度:20℃
- 天气状况:多云
- 风速:微风
- 空气湿度:69%
- 以上案例仓库地址
6. 结语
MCP正在重塑LLM应用开发范式,其价值已在金融、电商、IoT等领域得到验证。未来mcp生态的构建可能成为大模型落地的重要一环。