MCP协议的扩展应用:从单一工具到多服务器集成
在上篇文章中,我们介绍了MCP(Model Context Protocol)协议的基本概念及其在LLM(大型语言模型)工具集成中的作用。MCP作为一种开源协议,由Anthropic贡献,帮助开发者规范工具的提供和调用,实现跨进程、跨语言的Agent系统。今天,我们进一步探讨MCP的进阶用法:多服务器集成。通过结合多个MCP服务器,我们可以让Agent处理更复杂的任务,如地图查询、文件系统操作和浏览器交互。这不仅放大LLM的"干活"能力,还能无缝融入实际应用场景。
回想MCP的核心:它统一了工具的通信协议,支持stdio和http等方式。扩展到多服务器时,我们可以使用MultiServerMCPClient来管理多个MCP实例。例如,集成第三方API如高德地图(amap-maps)、本地文件系统(filesystem)和Chrome开发工具(chrome-devtools)。这些服务器提供不同的工具集,让Agent能调用地图服务获取位置信息、操作文件保存结果,甚至控制浏览器展示视觉内容。这使得LLM从简单响应转向智能自动化。
为什么选择多服务器集成?单一MCP服务器可能局限于特定功能,而多服务器允许模块化扩展。举例来说,在查询"广州站附近的酒店"时,Agent可以先用地图工具获取酒店列表和路线,然后用文件工具保存文档,最后用浏览器工具展示酒店图片。这种链式调用体现了MCP的灵活性,避免了手动对接的复杂性。
多MCP服务器的配置与工具绑定
在开发多工具Agent时,首先需要配置MCP客户端。使用@langchain/mcp-adapters库的MultiServerMCPClient,可以指定多个服务器。每个服务器有不同的启动方式:远程URL、本地命令行等。这确保了工具的多样性。
例如,配置高德地图服务器使用http:
JavaScript
bash
"mcpServers": {
"amap-maps-streamableHTTP": {
"url": `https://mcp.amap.com/mcp?key=${process.env.AMAP_MAPS_API_KEY}`
}
}
这里,环境变量存储API密钥,确保安全。文件系统服务器用npx启动本地工具,指定工作目录:
JavaScript
perl
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"D:/lesson_zp/ai/agent/mcp_in_action"
]
}
Chrome开发工具服务器类似,用于浏览器自动化:
JavaScript
perl
"chorme-devtools": {
"command": "npx",
"args": [
"-y",
"chrome-devtools-mcp@latest"
]
}
启动客户端后,获取所有工具列表并绑定到LLM模型:
JavaScript
ini
const tools = await mcpClient.getTools();
const modelWithTools = model.bindTools(tools);
这让LLM能智能调用工具。模型使用ChatOpenAI,配置modelName、API密钥和baseURL,确保兼容自定义端点。
Agent运行流程:工具调用循环与结果处理
Agent的核心是处理用户查询的循环机制。初始化消息数组以HumanMessage开始,然后迭代调用模型,检查tool_calls。如果无调用,则返回最终内容;否则,执行工具并添加ToolMessage。
关键代码:
JavaScript
ini
async function runAgentWithTools(query, maxIterations = 30) {
const messages = [
new HumanMessage(query)
];
for (let i = 0; i < maxIterations; i++) {
console.log(chalk.bgGreen('⏳正在等待AI思考...'));
const response = await modelWithTools.invoke(messages);
messages.push(response);
if (!response.tool_calls || response.tool_calls.length === 0) {
console.log(`\n AI 最终回复:\n ${response.content}\n`);
return response.content;
}
console.log(chalk.bgBlue(`🔍 检测到 ${response.tool_calls.length} 个工具调用`));
console.log(chalk.bgBlue(`🔍 工具调用: ${response.tool_calls.map(t => t.name).join(', ')}`));
for (const toolCall of response.tool_calls) {
const foundTool = tools.find(t => t.name === toolCall.name);
if (foundTool) {
const toolResult = await foundTool.invoke(toolCall.args);
let contentStr;
if (typeof toolResult === 'string') {
contentStr = toolResult;
} else if (toolResult && toolResult.text) {
contentStr = toolResult.text;
}
messages.push(new ToolMessage({
content: contentStr,
tool_call_id: toolCall.id
}));
}
}
}
return messages[messages.length - 1].content;
}
这个循环限制在30次迭代,防止无限循环。工具结果处理考虑string或对象形式,确保兼容不同服务器输出。使用chalk库美化日志,提升开发体验。
实际示例:查询酒店并浏览器展示
现在,看一个完整示例:查询"广州站附近的3个酒店,拿到酒店的图片,展示浏览器,展示每个酒店的图片,每个tab一个url展示,并且那个页面标题改为酒店名"。注意,查询中有重复"附近的附近的",可能是笔误,可指正为"广州站附近的3个酒店"以优化清晰度。
运行:
JavaScript
javascript
await runAgentWithTools(`
广州站附近的附近的3个酒店,拿到酒店的图片,展示浏览器,展示每个酒店的图片,
每个tab一个url展示,并且那个页面标题改为酒店名
`);
Agent流程:
- LLM解析查询,调用amap-maps工具获取酒店列表(位置、名称、图片URL)。
- 对于每个酒店,调用chrome-devtools工具打开新tab,加载图片URL,并修改标题为酒店名。
- 如果需要保存路线,可调用filesystem工具生成MD文件(注释中示例)。
高德地图工具可能提供POI搜索、路线规划。浏览器工具允许自动化tab管理、标题修改。文件工具支持读写指定目录。
这个示例展示了MCP的多服务器协同:地图提供数据,浏览器处理展示,文件可选持久化。相比单一工具,Agent更智能,能链式执行复杂任务。
MCP在实际项目中的价值
多MCP集成让Agent适用于各种场景,如智能助手、自动化脚本。未来,随着更多官方服务器(如filesystem),开发者可轻松扩展。MCP的开源性鼓励社区贡献,规范工具生态。
通过以上代码,你可以快速构建类似系统。欢迎讨论你的应用!
完整代码示例:多MCP Agent实现
以下是完整代码,用于本地运行:
JavaScript
javascript
import 'dotenv/config';
import { MultiServerMCPClient } from '@langchain/mcp-adapters';
import { ChatOpenAI } from '@langchain/openai';
import chalk from 'chalk';
import {
HumanMessage,
SystemMessage,
ToolMessage
} from '@langchain/core/messages';
const mcpClient = new MultiServerMCPClient({
mcpServers: {
"amap-maps-streamableHTTP": {
"url": `https://mcp.amap.com/mcp?key=${process.env.AMAP_MAPS_API_KEY}`
},
// mcp 官方提供
"filesystem": {
"command" : "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"D:/lesson_zp/ai/agent/mcp_in_action"
]
},
"chorme-devtools": {
"command": "npx",
"args": [
"-y",
"chrome-devtools-mcp@latest"
]
}
}
})
const model = new ChatOpenAI({
modelName: process.env.MODEL_NAME,
openAIApiKey: process.env.OPENAI_API_KEY,
configuration: {
baseURL: process.env.OPENAI_API_BASE_URL,
}
})
const tools = await mcpClient.getTools();
const modelWithTools = model.bindTools(tools);
async function runAgentWithTools(query, maxIterations = 30) {
const messages = [
new HumanMessage(query)
];
for (let i = 0; i < maxIterations; i++) {
console.log(chalk.bgGreen('⏳正在等待AI思考...'));
const response = await modelWithTools.invoke(messages);
messages.push(response);
if (!response.tool_calls || response.tool_calls.length === 0) {
console.log(`\n AI 最终回复:\n ${response.content}\n`);
return response.content;
}
console.log(chalk.bgBlue(`🔍 检测到 ${response.tool_calls.length} 个工具调用`));
console.log(chalk.bgBlue(`🔍 工具调用: ${response.tool_calls.map(t => t.name).join(', ')}`));
for (const toolCall of response.tool_calls) {
const foundTool = tools.find(t => t.name === toolCall.name);
if (foundTool) {
const toolResult = await foundTool.invoke(toolCall.args);
let contentStr;
if (typeof toolResult === 'string') {
contentStr = toolResult;
} else if (toolResult && toolResult.text) {
contentStr = toolResult.text;
}
messages.push(new ToolMessage({
content: contentStr,
tool_call_id: toolCall.id
}));
}
}
}
return messages[messages.length - 1].content;
}
// await runAgentWithTools('广州站附近的酒店,以及去的路线');
// await runAgentWithTools(`广州站附近的2个酒店,以及去的路线,路线规划生成文档保存到
// D:\lesson_zp\ai\agent\mcp_in_action 的一个md 文件`);
await runAgentWithTools(`
广州站附近的附近的3个酒店,拿到酒店的图片,展示浏览器,展示每个酒店的图片,
每个tab一个url展示,并且那个页面标题改为酒店名
`)
await mcpClient.close();
这个代码演示了MCP的多面性。实际中,根据需求调整服务器和查询。
结语:MCP驱动的未来Agent
MCP协议通过多服务器集成,赋予LLM强大执行力。从地图到浏览器,Agent能处理现实任务。希望这篇文章启发你的开发实践!