在 AI 应用开发的蛮荒时代,如何让大语言模型(LLM)高效接入外部工具、数据库和 API,始终是一个让开发者头秃的核心挑战。

过去,我们不得不为每个模型、每个数据源编写特定的“胶水代码”。今天,模型上下文协议(Model Context Protocol, MCP) 的横空出世,就像为 AI 世界带来了 USB-C 接口——它标准化了连接,让一切变得即插即用。
在这里插入图片描述

而作为 AI 编排领域的王者,LangChain.js 推出的 MCP 适配器(MCP Adapters),则进一步降低了这种连接的门槛。本文将深入解析“LangChain + MCP”这一黄金组合,手把手带你构建下一代可扩展的 AI 应用。


一、 为什么我们需要 MCP?

在 MCP 出现之前,LLM 与工具的连接是 M x N 的复杂度问题:M 个模型需要适配 N 个不同的工具接口。

MCP 协议通过定义一套开放标准,将这一问题简化为 1 + 1

  1. 标准化消息格式:无论你是调用计算器还是查询数据库,请求都是统一的 CallToolRequest,读取资源都是 ReadResourceRequest
  2. 灵活的架构
    • Client (LangChain): AI 主机,负责决策。
    • Server (MCP): 工具提供方,负责执行。
    • Transport: 支持本地进程(Stdio)或远程服务(SSE),既安全又灵活。

简而言之,MCP 让你的后端服务变成了 AI 可以直接“理解”和“操作”的插件。

在这里插入图片描述

二、 服务端实战:构建一个标准的 MCP Server

在集成到 LangChain 之前,我们需要先有一个 MCP 服务器。这里我们使用 Express 和 MCP SDK 构建一个提供“数学计算能力”的远程服务器。

技术栈:Node.js, Express, @modelcontextprotocol/sdk, Zod

// server.ts
import express from "express";
import cors from "cors";
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";

const app = express();
app.use(cors());

// 1. 初始化 MCP Server 实例
// 这里定义了服务器的名称和版本,以及它具备的能力(这里是 tools)
const mcpServer = new Server(
  { name: "langchain-math-server", version: "1.0.0" },
  { capabilities: { tools: {} } }
);

// 2. 定义工具列表接口
// 当客户端询问“你有什么本事?”时,服务器通过这里回答
mcpServer.setRequestHandler(ListToolsRequestSchema, async () => {
  return {
    tools: [
      {
        name: "calculate_sum",
        description: "计算两个数字的和",
        inputSchema: {
          type: "object",
          properties: {
            a: { type: "number", description: "第一个数字" },
            b: { type: "number", description: "第二个数字" },
          },
          required: ["a", "b"],
        },
      },
    ],
  };
});

// 3. 定义工具执行逻辑
// 当客户端发令“执行 calculate_sum”时,这里处理逻辑
mcpServer.setRequestHandler(CallToolRequestSchema, async (request) => {
  if (request.params.name === "calculate_sum") {
    const args = request.params.arguments as { a: number; b: number };
    const sum = args.a + args.b;
    console.log(`[Server] Executing: ${args.a} + ${args.b} = ${sum}`);
    
    return {
      content: [{ type: "text", text: String(sum) }],
    };
  }
  throw new Error("Tool not found");
});

// 4. 配置 SSE (Server-Sent Events) 传输层
// 这一步至关重要,它允许服务器主动向 AI 客户端推送状态
let transport: SSEServerTransport | null = null;

app.get("/sse", async (req, res) => {
  console.log("-> New SSE connection");
  transport = new SSEServerTransport("/message", res);
  await mcpServer.connect(transport);
  
  req.on("close", () => {
    console.log("<- SSE connection closed");
    mcpServer.close();
  });
});

app.post("/message", async (req, res) => {
  if (!transport) return res.sendStatus(400);
  await transport.handlePostMessage(req, res);
});

const PORT = 3000;
app.listen(PORT, () => {
  console.log(`🚀 MCP Server running at http://localhost:${PORT}/sse`);
});

三、 客户端实战:LangChain.js 的两种接入方式

LangChain.js 提供了两种方式来接入 MCP。一种是了解原理的“硬核模式”,另一种是官方封装的“极简模式”。

方式 A:极简模式 (推荐)

——使用 @langchain/mcp-adapters

这是 LangChain 官方提供的适配器,它自动帮你完成了“连接 -> 获取工具列表 -> 转换为 LangChain Tool -> 绑定模型”的全过程。

// client-simple.ts
import { ChatOpenAI } from "@langchain/openai";
import { MultiServerMCPClient } from "@langchain/mcp-adapters";
import { createAgent } from "langchain"; // 或使用 createToolCallingAgent

async function main() {
  // 1. 初始化多服务器客户端
  // 你可以在这里同时连接 Math Server, Weather Server, Database Server...
  const client = new MultiServerMCPClient({
    "math-service": {
      transport: "sse", 
      url: "http://localhost:3000/sse",
    },
  });

  // 2. 自动获取并转换所有工具
  // 这一步最关键:Adapter 自动将 MCP 的 JSON Schema 转换为了 LangChain Tool
  const tools = await client.getTools();
  console.log(`Loaded ${tools.length} tools from MCP servers.`);

  // 3. 初始化模型 (兼容 OpenAI, DeepSeek, 豆包等)
  const model = new ChatOpenAI({
    temperature: 0,
    model: process.env.ARK_DOUBAO_MODEL || "gpt-4o", 
    configuration: { baseURL: process.env.ARK_DOUBAO_BASE_URL },
    apiKey: process.env.ARK_DOUBAO_API_KEY,
  });

  // 4. 像往常一样使用 Agent 或 bindTools
  const modelWithTools = model.bindTools(tools);
  
  const response = await modelWithTools.invoke([
    { role: "user", content: "计算 15 加 27 是多少?" }
  ]);

  console.log("\n🤖 AI Response:", response.content);
  // 查看工具调用参数
  console.log("🔧 Tool Calls:", response.tool_calls);
}

main().catch(console.error);

方式 B:底层原理 (硬核模式)

——手动封装 Tool

为了让你理解适配器到底做了什么,我们来看一下手动集成的代码。这一部分展示了如何将 MCP SDK 的 Client 手动包装成 DynamicStructuredTool

(注:如果你对底层实现不感兴趣,可以跳过此节直接看结论)

// client-complex.ts
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
import { ChatOpenAI } from "@langchain/openai";
import { DynamicStructuredTool } from "@langchain/core/tools";
import { z } from "zod";

async function main() {
  // 1. 手动建立 SSE 连接
  const transport = new SSEClientTransport(new URL("http://localhost:3000/sse"));
  const client = new Client({ name: "manual-client", version: "1.0" }, { capabilities: {} });
  await client.connect(transport);

  // 2. 获取原始工具列表
  const { tools: mcpTools } = await client.listTools();

  // 3. 手动映射:MCP Tool -> LangChain Tool
  // 注意:实际生产中需要编写通用的 Schema 转换器,这里为了演示使用了硬编码
  const langchainTools = mcpTools.map((mcpTool) => {
    return new DynamicStructuredTool({
      name: mcpTool.name,
      description: mcpTool.description || "",
      // 缺点:这里需要你根据 inputSchema 动态生成 Zod 对象,比较麻烦
      schema: z.object({
        a: z.number(),
        b: z.number(),
      }),
      func: async (input) => {
        // 转发调用给 MCP Client
        const result = await client.callTool({
          name: mcpTool.name,
          arguments: input,
        });
        return result.content[0].type === 'text' ? result.content[0].text : "Error";
      },
    });
  });

  // 4. 调用模型
  const model = new ChatOpenAI({ /* 配置同上 */ }).bindTools(langchainTools);
  const res = await model.invoke("100 加 200 等于几?");
  console.log(res.tool_calls);
}

四、 为什么你应该现在关注这个技术栈?

LangChain.js + MCP 不仅仅是代码层面的优化,它代表了 AI 应用架构的演进方向:

  1. AI 架构的前后端分离

    • 后端(MCP Server):专注于业务逻辑、数据安全和原子能力的封装。可以由专业的后端团队维护,无需关心 Prompt 或 Context window。
    • 前端(LangChain Client):专注于 Agent 编排、Prompt 优化和用户交互。
  2. 极高的复用性

    • 你编写的 MathServer,既可以被 LangChain 的 Web 应用调用,也可以直接安装到 Claude DesktopCursor IDE 中。编写一次,到处运行。
  3. 生态系统红利

    • 随着 MCP 生态壮大,未来你不再需要阅读 Notion、Slack 或 GitHub 的复杂 API 文档。只需要连接它们提供的标准 MCP Server,LangChain client.getTools() 就能直接获得所有能力。

五、 结语

LangChain.js 与 MCP 的结合,标志着 AI 应用开发正在从“手工作坊”走向“工业化组装”。

在这里插入图片描述

我们不再是构建孤岛式的 Chatbot,而是在构建一个互联互通的智能生态系统。如果你正在构建复杂的 AI Agent,强烈建议你审视现有的架构,尝试将通用的工具抽离成 MCP Server。

你会发现,路越走越宽。


参考资料

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐