MCP 进阶实战:用 LangChain 将 MCP 工具集成到你的 AI Agent 程序


一、为什么要把 MCP 集成到自己的程序里?

在上一篇文章中,我们通过 Cursor / Trae 的配置文件加载 MCP Server,让 AI 编程助手拥有了查询用户信息的能力。这种方式非常适合交互式编程场景

但如果你正在开发一个:

  • 后台自动化处理任务
  • 企业微信 / 钉钉机器人
  • 数据报表生成服务
  • 内部运维 Agent

你会发现,你需要的不是让 Cursor 去调工具,而是让你自己写的 Node.js / Python 程序去调度大模型 + 调用 MCP 工具

这时候,@langchain/mcp-adapters 就派上用场了。


二、核心组件:MCP 三者关系再梳理

结合我们之前的 readme.md 内容,先来一张关系图:

角色说明示例
MCP Host发起对话、承载 Agent 逻辑的宿主程序Cursor、Trae、你写的 LangChain 应用
MCP Client与 MCP Server 通信,管理工具列表MultiServerMCPClient
MCP Server提供具体工具 / 资源 / 提示词的执行容器my-mcp-server.mjs
┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│   MCP Host      │────▶│  MCP Client     │────▶│  MCP Server     │
│ (你的 LangChain │     │ (适配器)         │     │ (工具容器)       │
│  应用程序)       │◀────│                 │◀────│                 │
└─────────────────┘     └─────────────────┘     └─────────────────┘

工作流程回顾:

  1. Host 启动时,Client 与 Server 建立连接(Stdio / HTTP)
  2. Client 向 Server 发起 initialize 请求,获取所有工具列表及详细 schema
  3. Host 收到用户任务,大模型判断需要调用某个工具
  4. Client 将调用请求转发给 Server
  5. Server 执行工具函数,返回结构化结果
  6. Host 将结果以 ToolMessage 形式喂回大模型,继续对话

三、环境准备与依赖安装

我们要在已有 MCP Server 的基础上,新建一个 LangChain 应用来调用它。

# 进入你的项目目录(例如 ai/agent/mini-cursor/mcp/)
cd mcp-tool

# 安装所需依赖
npm install @langchain/mcp-adapters @langchain/openai @langchain/core dotenv chalk zod

依赖说明:

  • @langchain/mcp-adapters:官方 MCP 与 LangChain 之间的桥接器
  • @langchain/openai:调用 OpenAI 兼容接口的大模型
  • chalk:美化终端输出(可选)
  • dotenv:加载 .env 环境变量

在项目根目录创建 .env 文件,填入你的大模型配置:

MODEL_NAME=gpt-4o-mini
OPENAI_API_KEY=sk-xxxxxx
OPENAI_BASE_URL=

四、编写 MCP Agent 主程序

创建一个新文件 agent.mjs,内容如下(已包含详细注释):

import 'dotenv/config';
import { MultiServerMCPClient } from '@langchain/mcp-adapters';
import { ChatOpenAI } from '@langchain/openai';
import { HumanMessage, ToolMessage } from '@langchain/core/messages';
import chalk from 'chalk';

// ---------- 1. 初始化大模型 ----------
const model = new ChatOpenAI({
    modelName: process.env.MODEL_NAME,
    apiKey: process.env.OPENAI_API_KEY,
    configuration: {
        baseURL: process.env.OPENAI_BASE_URL,
    }
});

// ---------- 2. 创建 MCP 客户端,连接我们之前写的 Server ----------
const mcpClient = new MultiServerMCPClient({
    mcpServers: {
        'my-mcp-server': {
            command: 'node',
            args: ['C:/Users/29031/Desktop/workspace/lesson_zp/ai/agent/mini-cursor/mcp/mcp-tool/my-mcp-server.mjs'],
        },
    },
});

// ---------- 3. 获取 MCP Server 中的所有工具 ----------
const tools = await mcpClient.getTools();
console.log(chalk.green(' 已加载 MCP 工具列表:'), tools.map(t => t.name));

// 将工具绑定到大模型上(让模型知道它可以调用哪些工具)
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} 轮思考...`));
        
        // 调用大模型,它会返回一个 AI 消息,可能包含 tool_calls
        const response = await modelWithTools.invoke(messages);
        messages.push(response);

        // 如果模型没有要求调用工具,说明对话结束,返回最终答案
        if (!response.tool_calls || response.tool_calls.length === 0) {
            console.log(chalk.bgWhite.black(' 最终回复:'));
            return response.content;
        }

        // 模型要求调用工具,我们逐一执行
        console.log(chalk.bgBlue(` 检测到 ${response.tool_calls.length} 个工具调用:`));
        for (const toolCall of response.tool_calls) {
            console.log(chalk.blue(`   → 调用工具:${toolCall.name},参数:${JSON.stringify(toolCall.args)}`));
            
            // 从 MCP 工具列表中找到对应的工具实例
            const foundTool = tools.find(t => t.name === toolCall.name);
            if (foundTool) {
                // 执行工具,获得结果
                const toolResult = await foundTool.invoke(toolCall.args);
                
                // 将工具执行结果包装成 ToolMessage,加回对话历史
                messages.push(new ToolMessage({
                    content: toolResult,
                    tool_call_id: toolCall.id
                }));
                
                console.log(chalk.gray(`   ← 工具返回:${toolResult.substring(0, 100)}...`));
            } else {
                console.log(chalk.red(`    未找到工具 ${toolCall.name}`));
            }
        }
    }
    
    return '已达到最大迭代次数,对话终止。';
}

// ---------- 5. 执行一个实际任务 ----------
const result = await runAgentWithTools("查一下用户 002 的信息");
console.log(chalk.yellow('n 最终结果:n'), result);

// ---------- 6. 关闭 MCP 客户端连接 ----------
await mcpClient.close();

代码关键点解析

代码段作用
MultiServerMCPClient管理多个 MCP Server 的连接,内部会自动处理 Stdio 子进程的启动与通信。
mcpClient.getTools()获取所有 Server 提供的工具列表,这些工具的 schema 已经自动转换为 LangChain 能识别的格式
model.bindTools(tools)将工具列表告知大模型,后续对话中模型会在需要时返回 tool_calls
ToolMessageLangChain 中专门用于携带工具执行结果的消息类型,必须与对应的 tool_call_id 绑定。
循环调用Agent 的核心逻辑:模型输出工具调用 → 执行工具 → 将结果喂回模型 → 继续,直到模型不再要求调用工具。

五、运行测试

在终端执行:

node agent.mjs

你将看到类似如下的输出:

 已加载 MCP 工具列表: [ 'query-user' ]
⏳ 第 1 轮思考...
 检测到 1 个工具调用:
   → 调用工具:query-user,参数:{"userId":"002"}
   ← 工具返回:用户信息:
- ID: 002
- 姓名: 李四
- 邮箱: lisi@example.com
- 角色: user...
⏳ 第 2 轮思考...
 最终回复:
用户 002 的信息如下:
姓名:李四,邮箱:lisi@example.com,角色:user。

 最终结果:
 用户 002 的信息如下:
姓名:李四,邮箱:lisi@example.com,角色:user

至此,你已经成功将 MCP 工具无缝集成到自己的 LangChain 程序中!

如图


六、进阶:为 MCP Server 添加“资源”(Resource)

MCP 协议不仅支持 Tool(工具),还支持 Resource(资源)Prompt(提示模板)

在我们的 my-mcp-server.mjs 中,我们已经添加了一个资源:

server.registerResource('使用指南', 'docs://guide', {
   description: 'MCP Server 使用指南',
   mimeType: 'text/plain',
},
async () => {
    return {
      contents: [{
        uri: 'docs://guide',
        mimeType: 'text/plain',
        text: `MCP Server 使用指南...`,
      }]
    };
});

资源的使用方式:

在 LangChain 中,你可以通过 mcpClient.getResources() 获取所有资源,然后通过 mcpClient.readResource(uri) 读取内容。这使得大模型可以在对话中主动查阅你提供的“知识库”。


七、为什么说 MCP 是“可拔插”的工具生态?

从上面的实践可以看出,MultiServerMCPClient 通过一个统一的配置对象,就能启动并管理多个 MCP Server。

  • 你想添加一个 Python 写的图像处理 MCP Server?只需在 mcpServers 里加一项配置。
  • 你想调用公司内部 Java 写的工单查询 MCP 服务?配置 HTTP 地址即可。
  • 你想临时禁用某个工具?注释掉对应配置即可。

这种 “配置即集成” 的模式,让 Agent 的能力扩展变得前所未有的简单。MCP 真正实现了大模型应用层的 Lego 化


如果这篇文章对你有帮助,欢迎点赞、收藏。有任何疑问或想了解的内容,欢迎在评论区留言!

本站提供的所有下载资源均来自互联网,仅提供学习交流使用,版权归原作者所有。如需商业使用,请联系原作者获得授权。 如您发现有涉嫌侵权的内容,请联系我们 邮箱:alixiixcom@163.com