一、回顾:MCP 本质上是什么?

在开始之前,先快速回顾一下 MCP 的核心概念——如果你已经看过上一篇基础入门,这一节能帮你巩固;如果你是第一次接触,也能快速建立认知。

MCP(Model Context Protocol)本质上是 Tool(工具),只不过在 Tool 外面包了一层"进程"。

  • 普通的 Tool:在 Agent 进程内部执行,定义在同一个代码文件里,直接调用函数
  • MCP Tool:在独立的进程(MCP Server)中执行,Agent 通过协议和它通信

MCP Tool

stdio / HTTP
跨进程通信

执行

Agent 进程

子进程 / 远程服务

function queryUser()

普通 Tool

同进程函数调用

Agent 进程

function queryUser()

两种访问方式

方式 适用场景 配置写法
stdio 本地子进程,适合个人开发工具 { command: 'node', args: ['server.js'] }
HTTP 远程服务,适合团队共享、第三方服务 { url: 'https://xxx.com/mcp' }

有了这个基础,我们来看今天的重点——如何在实际项目中组合多个 MCP Server,让 AI 完成一条完整的工作流


二、应用场景:三个 MCP Server 协同工作

假设你有一个需求:查询北京南站附近的酒店,获取路线规划,把结果保存成 Markdown 文件

这需要三种能力:

  1. 🌍 地理信息查询 → 高德地图 MCP(HTTP 远程)
  2. 📂 文件读写 → FileSystem MCP(npx 本地子进程)
  3. 🌐 浏览器控制 → Chrome DevTools MCP(npx 本地子进程)

恰好,这三种能力都有现成的 MCP Server 可以直接用。这就是 MCP 生态最大的价值:任何人都可以开发基于 MCP 协议的 Server,然后其他人直接复用。

写入 .md 文件

浏览器展示

HTTP 远程

npx 子进程

npx 子进程
需 Chrome 调试模式

返回酒店数据

🧠 AI Agent(MCP Client)

大语言模型

Agent 循环调度

👤 用户提问
北京南站附近的酒店?

🌍 高德 MCP
maps_geo 地理编码
maps_around_search 周边搜索
maps_direction 路线规划

📂 Filesystem MCP
read_file 读文件
write_file 写文件
create_directory 建目录

🌐 Chrome DevTools MCP
navigate_page 打开页面
take_screenshot 截图
click 点击元素

📄 北京南站附近酒店及路线指南.md

🖥️ Chrome 浏览器

在这里插入图片描述

2.1 高德地图 MCP(HTTP 远程方式)

高德地图提供了官方的 MCP Server,通过 HTTP 暴露。这是典型的"远程 MCP"使用方式——你不需要下载任何代码,只要在配置里填入 URL 和 API Key 即可。

注册和获取 Key高德开放平台

提供的核心工具

工具名 功能 示例
maps_geo 地理编码(地址 → 经纬度) “北京南站” → 116.379, 39.865
maps_around_search 周边搜索(经纬度 + 关键词 → 结果列表) 附近 3km 内的酒店
maps_direction 路线规划(起点 → 终点) 北京南站 → 酒店的驾车/公交路线

💡 关键理解:高德 MCP Server 是部署在高德服务器上的,你的 Agent 通过 HTTP 请求去调用它。这和调一个普通 HTTP API 表面类似,但本质区别在于——MCP 返回的不是"业务数据",而是"Tool 定义 + 执行结果",Agent 能自动发现它有哪些工具、工具需要什么参数、然后自动调用。

2.2 Chrome DevTools MCP(npx 本地方式)

这个 MCP Server 让你能通过 AI 控制 Chrome 浏览器:打开网页、点击按钮、截屏、甚至修改页面标题。

前提条件:Chrome 需要以远程调试模式启动:

chrome --remote-debugging-port=9222

提供的核心工具

工具名 功能
navigate_page 导航到指定 URL
take_screenshot 截取页面截图
click 点击页面元素
evaluate_script 执行 JavaScript 代码
list_pages 列出当前打开的所有页面

2.3 FileSystem MCP(npx 本地方式)

这个 MCP Server 提供文件系统的读写能力,由 @modelcontextprotocol/server-filesystem 这个 npm 包提供。

关键配置:启动时必须指定允许访问的目录(安全限制),否则无法读写:

'filesystem': {
    command: 'npx',
    args: [
        '-y',
        '@modelcontextprotocol/server-filesystem',
        'D:\\workspace\\zmt_ai\\ai\\agent_in_action\\remote-mcp'  // 允许访问的目录
    ]
}

⚠️ 安全提示:FileSystem MCP 只能访问配置中指定的目录,不能随意访问系统任意路径。这是一个重要的安全边界——MCP Server 不能"越狱"访问你未授权的文件夹。


三、完整实战:一个 AI 工作流的诞生

现在把三个 MCP Server 组合起来,实现一个完整的 AI 工作流:查询酒店 → 路线规划 → 保存文档

3.1 完整代码(带详细注释)

// mcp-test.mjs —— 远程 MCP 多 Server 协同工作流
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';

// ==================== 1. 初始化 LLM ====================
const model = new ChatOpenAI({
    modelName: 'deepseek-v4-pro',
    apiKey: process.env.DEEPSEEK_API_KEY,
    temperature: 0,                              // 设为 0 确保结果稳定
    configuration: {
        baseURL: 'https://api.deepseek.com/v1',
    },
});

// ==================== 2. 配置多个 MCP Server ====================
const mcpClient = new MultiServerMCPClient({
    mcpServers: {
        // ① 高德地图 —— HTTP 远程方式
        'amap-mcp-streamableHTTP': {
            "url": "https://mcp.amap.com/mcp?key=你的高德APIkey"
        },
        // ② 自建用户查询 —— stdio 本地子进程
        'my-mcp-server': {
            command: "node",
            args: [
                // 你自己写的用户查询工具的路径
                'D:\\workspace\\zmt_ai\\ai\\agent_in_action\\mcp-demo\\src\\my-mcp-server.mjs'
            ]
        },
        // ③ 文件系统 —— npx 启动第三方 MCP Server
        'filesystem': {
            command: 'npx',
            args: [
                '-y',
                '@modelcontextprotocol/server-filesystem',
                'D:\\workspace\\zmt_ai\\ai\\agent_in_action\\remote-mcp'  // 白名单目录
            ]
        },
        // ④ Chrome DevTools —— 控制浏览器
        // 使用前需执行:chrome --remote-debugging-port=9222
        'chrome-devtools': {
            command: 'npx',
            args: [
                '-y',
                'chrome-devtools-mcp@latest',
            ]
        }
    }
});

// ==================== 3. 获取所有工具并绑定到模型 ====================
const tools = await mcpClient.getTools();
console.log(tools);  // 打印看看总共有哪些工具可用
const modelWithTools = model.bindTools(tools);

// ==================== 4. Agent 循环 ====================
async function runAgentWithTools(query, maxIterations = 30) {
    const messages = [new HumanMessage(query)];

    for (let i = 0; i < maxIterations; i++) {
        console.log(chalk.bgGreen(`${i + 1}轮对话`));

        // 4.1 让 LLM 思考下一步
        const response = await modelWithTools.invoke(messages);
        messages.push(response);

        // 4.2 如果 LLM 不再调用工具 → 说明已经得出最终答案
        if (!response.tool_calls || response.tool_calls.length === 0) {
            console.log(chalk.bgRed(`AI 回答:${response.content}`));
            return response.content;
        }

        // 4.3 打印本轮调用了哪些工具
        console.log(chalk.bgBlue(`工具调用: ${response.tool_calls.map(t => t.name).join(', ')}`));

        // 4.4 逐个执行工具,收集结果
        for (const toolCall of response.tool_calls) {
            const foundTool = tools.find(t => t.name === toolCall.name);
            if (foundTool) {
                // 执行工具(跨进程:stdio 或 HTTP)
                const toolResult = await foundTool.invoke(toolCall.args);

                // 解析工具返回的内容
                let contentStr;
                if (typeof toolResult === 'string') {
                    contentStr = toolResult;
                } else if (toolResult && toolResult.result) {
                    contentStr = toolResult.text;
                }

                // 将工具执行结果反馈给 LLM
                messages.push(new ToolMessage({
                    content: contentStr,
                    tool_call_id: toolCall.id
                }));
            }
        }
    }

    // 达到最大轮数仍无结果,返回最后一轮内容
    return messages[messages.length - 1].content;
}

// ==================== 5. 启动工作流 ====================
// 任务:查酒店 → 规划路线 → 保存 Markdown 文件
await runAgentWithTools(
    '北京南站附近的 2 个酒店,以及去的路线,路线规划生成文档保存到当前目录的一个 md 文件'
);

// 备选任务(需要 Chrome 调试模式):
// await runAgentWithTools(
//     '北京南站附近的酒店,最近的 3 个酒店,拿到酒店图片,打开浏览器,
//      展示每个酒店的图片,每个 tab 一个 url 展示,并且把那个页面标题改为酒店名'
// );

// ==================== 6. 关闭所有 MCP 连接 ====================
await mcpClient.close();

执行结果:
1.
在这里插入图片描述2.

3.2 代码执行流程图

当 AI 收到"查询北京南站附近的酒店并保存文档"这个任务时,内部发生了如下过程:

📂 FileSystem MCP 🌍 高德 MCP 🤖 DeepSeek 🧠 Agent 循环 👤 用户 📂 FileSystem MCP 🌍 高德 MCP 🤖 DeepSeek 🧠 Agent 循环 👤 用户 loop [第 1 轮:地理编码] loop [第 2 轮:周边搜索] loop [第 3 轮:路线规划] loop [第 4 轮:保存文件] "北京南站附近的2个酒店 + 路线 + 保存 md" HumanMessage(用户提问) tool_calls: [maps_geo("北京南站")] HTTP → maps_geo("北京南站") { 经纬度: 116.379, 39.865 } ToolMessage(经纬度结果) tool_calls: [maps_around_search(经纬度, "酒店")] HTTP → maps_around_search(...) [{ 全季酒店 }, { 如家酒店 }] ToolMessage(酒店列表) tool_calls: [maps_direction(北京南站, 全季酒店)] HTTP → maps_direction(...) { 距离: 2.3km, 驾车: 8分钟, 步行: 25分钟 } ToolMessage(路线结果) tool_calls: [write_file("北京南站附近酒店及路线指南.md", 文档内容)] stdio → write_file(path, content) 文件写入成功 ToolMessage(写入成功) ✅ 最终回复:"已完成!文档包含2个酒店及详细路线..." 显示结果

关键观察:AI 自动规划了 4 步操作(地理编码 → 周边搜索 → 路线规划 → 保存文件),每一步调用了不同的 MCP Server,完全无需人工干预。这就是 MCP 工作流的威力。


四、MCP 生态:最大的价值在于复用

4.1 核心认知转变

有了 MCP 协议之后,AI 工具开发发生了根本性的认知转变

之前(无 MCP) 之后(有 MCP)
每个项目自己写工具函数 直接引入现成的 MCP Server
Node.js 项目只能用 JS 工具 可以调用任何语言编写的 MCP Server
工具和 Agent 代码耦合 工具独立部署、独立升级
个人造轮子,质量参差不齐 社区共建,专业团队维护(如高德官方 MCP)

4.2 三种典型的 MCP Server 来源

③ 自己开发

my-mcp-server

stdio 本地运行
查询内部数据库

② npm 社区包

Filesystem MCP

npx 一键启动
@modelcontextprotocol/server-filesystem

Chrome DevTools MCP

npx 一键启动
chrome-devtools-mcp

① 第三方服务官方提供

高德地图 MCP

HTTP 远程
无需下载代码

4.3 各 Server 能力速查

MCP Server 通信方式 启动方式 核心能力
高德地图 HTTP 配置 URL 地理编码、周边搜索、路线规划
FileSystem stdio npx @modelcontextprotocol/server-filesystem 读写文件、创建目录、搜索文件
Chrome DevTools stdio npx chrome-devtools-mcp@latest 控制浏览器:导航、截图、点击、执行 JS
自建 Server stdio node my-server.js 查询内部数据库、调用内部 API 等

五、全文总结

远程 MCP 的核心思想就一句话:Tool 还是那个 Tool,但通过 MCP 协议,它可以从"项目里的一段代码"变成"一个独立、可复用、跨语言、跨网络的服务"。

本文展示了三种接入方式的实际应用:

  1. HTTP 远程(高德地图)—— 第三方服务直接提供 MCP URL,一行配置即可接入
  2. npx 本地包(FileSystem、Chrome DevTools)—— npm 社区提供的 MCP Server,一行命令即可启动
  3. 自建 stdio(my-mcp-server)—— 自己开发的 MCP Server,用 Node.js 编写,查询内部数据

当这些 Server 组合在一起时,AI Agent 就能完成一条完整的工作流——自动规划步骤、跨 Server 调用工具、最终交付结果。你只需要用自然语言描述需求。


六、核心知识点复盘

知识点 要点
MCP 本质 Tool + 进程包装,通过 stdio 或 HTTP 提供跨进程调用
stdio vs HTTP stdio 用于本地子进程,HTTP 用于远程服务
MultiServerMCPClient 可以同时配置多个 MCP Server,Agent 自动发现所有工具
高德 MCP HTTP 远程方式,提供地理编码、周边搜索、路线规划
FileSystem MCP 需要指定允许访问的目录(安全白名单)
Chrome DevTools MCP 需要 Chrome 以 --remote-debugging-port=9222 启动
MCP 生态价值 任何语言的工具都能封装成 MCP Server,跨项目、跨团队复用
Agent 循环 LLM 决定调用什么工具 → Agent 执行 → 结果反馈 → 循环,直到得出最终答案

七、常见问题与避坑指南

Q1:Tool names must be unique 错误

现象:启动时 DeepSeek API 返回 400 错误。

原因:多个 MCP Server 注册了同名工具。比如 filesystem 和自建的 my-mcp-server 都提供了 read_file 工具,绑定给 LLM 时名称冲突。

解决:只保留功能更全的那个 Server,或者修改其中一个 Server 注册的工具名。

Q2:Instances of "undefined" type are not supported 错误

现象:Agent 执行工具时报 schema 校验错误。

原因toolCall.arguments 从 LLM 返回时是 JSON 字符串(如 '{"userId":"001"}'),而 invoke() 期望接收 JS 对象(如 {userId: "001"})。

解决:调用前先做类型判断和转换:

const args = typeof toolCall.arguments === 'string'
    ? JSON.parse(toolCall.arguments)
    : toolCall.arguments;
const toolResult = await foundTool.invoke(args);

Q3:Chrome DevTools MCP 连接不上

现象getTools() 阶段一直卡住不返回。

原因:Chrome DevTools MCP 需要连接本地 Chrome 的调试端口。如果 Chrome 没有以 --remote-debugging-port=9222 参数启动,MCP Server 会一直等待连接。

解决

# Windows:先关闭所有 Chrome 窗口,然后用调试模式启动
chrome --remote-debugging-port=9222

# 如果暂时用不到,直接注释掉这个 Server 的配置即可

Q4:FileSystem MCP 无法写入文件

现象:工具返回权限错误。

原因:FileSystem MCP 只能访问启动时配置的"白名单目录",不能越界。

解决:检查 args 中指定的目录路径是否正确,确保目标文件在该目录下。

Q5:脚本执行完一直不退出

原因:通过 stdio 启动的子进程(MCP Server)没有被关闭。

解决:Agent 脚本末尾必须调用 await mcpClient.close(),这会关闭所有 stdio 连接并终止子进程。忘记这行代码会导致脚本"假死"。

Q6:如何获取高德地图 MCP 的 API Key?

访问 高德开放平台 注册账号 → 创建应用 → 选择"Web 服务" → 获取 Key。注意:高德 MCP 是 HTTP 远程服务,Key 会明文出现在 URL 中,不要把带 Key 的代码提交到公开仓库

💡 最佳实践:将 API Key 放在 .env 文件中,通过 process.env.AMAP_KEY 引用,并在 .gitignore 中添加 .env

Logo

欢迎加入 MCP 技术社区!与志同道合者携手前行,一同解锁 MCP 技术的无限可能!

更多推荐