@langchain/mcp-adapters 库来调用 MCP 服务器上定义的工具。
快速入门
安装@langchain/mcp-adapters 库:
npm install @langchain/mcp-adapters
pnpm add @langchain/mcp-adapters
yarn add @langchain/mcp-adapters
bun add @langchain/mcp-adapters
@langchain/mcp-adapters 使智能体能够使用一个或多个 MCP 服务器上定义的工具。
MultiServerMCPClient 默认是无状态的。每次工具调用都会创建一个新的 MCP ClientSession,执行工具,然后清理。访问多个 MCP 服务器
import { MultiServerMCPClient } from "@langchain/mcp-adapters";
import { ChatAnthropic } from "@langchain/anthropic";
import { createAgent } from "langchain";
const client = new MultiServerMCPClient({
math: {
transport: "stdio", // 本地子进程通信
command: "node",
// 替换为你的 math_server.js 文件的绝对路径
args: ["/path/to/math_server.js"],
},
weather: {
transport: "http", // 基于 HTTP 的远程服务器
// 确保你的天气服务器在 8000 端口上启动
url: "http://localhost:8000/mcp",
},
});
const tools = await client.getTools();
const agent = createAgent({
model: "claude-sonnet-4-6",
tools,
});
const mathResponse = await agent.invoke({
messages: [{ role: "user", content: "what's (3 + 5) x 12?" }],
});
const weatherResponse = await agent.invoke({
messages: [{ role: "user", content: "what is the weather in nyc?" }],
});
自定义服务器
要创建你自己的 MCP 服务器,可以使用@modelcontextprotocol/sdk 库。该库提供了一种简单的方式来定义工具并将其作为服务器运行。
npm install @modelcontextprotocol/sdk
pnpm add @modelcontextprotocol/sdk
yarn add @modelcontextprotocol/sdk
bun add @modelcontextprotocol/sdk
数学服务器(stdio 传输)
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
CallToolRequestSchema,
ListToolsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
const server = new Server(
{
name: "math-server",
version: "0.1.0",
},
{
capabilities: {
tools: {},
},
}
);
server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [
{
name: "add",
description: "Add two numbers",
inputSchema: {
type: "object",
properties: {
a: {
type: "number",
description: "First number",
},
b: {
type: "number",
description: "Second number",
},
},
required: ["a", "b"],
},
},
{
name: "multiply",
description: "Multiply two numbers",
inputSchema: {
type: "object",
properties: {
a: {
type: "number",
description: "First number",
},
b: {
type: "number",
description: "Second number",
},
},
required: ["a", "b"],
},
},
],
};
});
server.setRequestHandler(CallToolRequestSchema, async (request) => {
switch (request.params.name) {
case "add": {
const { a, b } = request.params.arguments as { a: number; b: number };
return {
content: [
{
type: "text",
text: String(a + b),
},
],
};
}
case "multiply": {
const { a, b } = request.params.arguments as { a: number; b: number };
return {
content: [
{
type: "text",
text: String(a * b),
},
],
};
}
default:
throw new Error(`Unknown tool: ${request.params.name}`);
}
});
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("Math MCP server running on stdio");
}
main();
天气服务器(SSE 传输)
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
import {
CallToolRequestSchema,
ListToolsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
import express from "express";
const app = express();
app.use(express.json());
const server = new Server(
{
name: "weather-server",
version: "0.1.0",
},
{
capabilities: {
tools: {},
},
}
);
server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [
{
name: "get_weather",
description: "Get weather for location",
inputSchema: {
type: "object",
properties: {
location: {
type: "string",
description: "Location to get weather for",
},
},
required: ["location"],
},
},
],
};
});
server.setRequestHandler(CallToolRequestSchema, async (request) => {
switch (request.params.name) {
case "get_weather": {
const { location } = request.params.arguments as { location: string };
return {
content: [
{
type: "text",
text: `It's always sunny in ${location}`,
},
],
};
}
default:
throw new Error(`Unknown tool: ${request.params.name}`);
}
});
app.post("/mcp", async (req, res) => {
const transport = new SSEServerTransport("/mcp", res);
await server.connect(transport);
});
const PORT = process.env.PORT || 8000;
app.listen(PORT, () => {
console.log(`Weather MCP server running on port ${PORT}`);
});
传输机制
MCP 支持不同的客户端-服务器通信传输机制。HTTP
http 传输(也称为 streamable-http)使用 HTTP 请求进行客户端-服务器通信。更多详细信息,请参阅 MCP HTTP 传输规范。
对于你自己运行的服务器,请使用本地 URL;对于托管服务器,可以使用类似 LangChain 文档 MCP 服务器(https://docs.langchain.com/mcp)这样的公开 URL,该服务器无需 API 密钥。
import { MultiServerMCPClient } from "@langchain/mcp-adapters";
import { createAgent } from "langchain";
const client = new MultiServerMCPClient({
mcp: {
transport: "http",
// url: "http://localhost:8000/mcp", // 本地服务器
url: "https://docs.langchain.com/mcp", // 托管服务器
},
});
const tools = await client.getTools();
const agent = createAgent({ model: "openai:gpt-5.4", tools });
const response = await agent.invoke({
messages: [
{
role: "user",
content: "How do I connect LangChain to an MCP server over HTTP?",
},
],
});
传递请求头
认证
stdio
客户端作为子进程启动服务器,并通过标准输入/输出进行通信。最适合本地工具和简单配置。const client = new MultiServerMCPClient({
math: {
transport: "stdio",
command: "node",
args: ["/path/to/math_server.js"],
},
});
核心功能
工具
工具允许 MCP 服务器暴露可执行函数,LLM 可以调用这些函数来执行操作——例如查询数据库、调用 API 或与外部系统交互。LangChain 将 MCP 工具转换为 LangChain 工具,使其可以直接在任何 LangChain 智能体或工作流中使用。加载工具
使用client.getTools() 从 MCP 服务器检索工具并将其传递给你的智能体:
import { MultiServerMCPClient } from "@langchain/mcp-adapters";
import { createAgent } from "langchain";
const client = new MultiServerMCPClient({...});
const tools = await client.getTools();
const agent = createAgent({ model: "claude-sonnet-4-6", tools });
CallToolResult 的 isError: true)时,@langchain/mcp-adapters 会引发 ToolException。使用 try/catch 包装工具调用来处理这些错误。与 Python 适配器不同,TypeScript 适配器不会将错误作为失败的工具消息返回给模型。
多模态工具内容
MCP 工具可以在其响应中返回多模态内容(图像、文本等)。当 MCP 服务器返回包含多个部分的内容(例如,文本和图像)时,适配器会将它们转换为 LangChain 的标准内容块。你可以通过ToolMessage 上的 contentBlocks 属性访问标准化的表示:
import { createAgent } from "langchain";
async function accessMultimodalToolContent(): Promise<void> {
const { MultiServerMCPClient } = await import("@langchain/mcp-adapters");
const client = new MultiServerMCPClient({});
const tools = await client.getTools();
const agent = createAgent({ model: "google-genai:gemini-3.6-flash", tools });
const result = await agent.invoke({
messages: [
{ role: "user", content: "Take a screenshot of the current page" },
],
});
// 访问工具消息中的多模态内容
for (const message of result.messages) {
if (message.type === "tool") {
// 服务商原生格式的原始内容
console.log(`Raw content: ${message.content}`);
// 标准化的内容块
for (const block of message.contentBlocks) {
if (block.type === "text") {
console.log(`Text: ${block.text}`);
} else if (block.type === "image") {
console.log(`Image URL: ${block.url}`);
console.log(`Image base64: ${block.base64?.slice(0, 50)}...`);
}
}
}
}
}
import { createAgent } from "langchain";
async function accessMultimodalToolContent(): Promise<void> {
const { MultiServerMCPClient } = await import("@langchain/mcp-adapters");
const client = new MultiServerMCPClient({});
const tools = await client.getTools();
const agent = createAgent({ model: "openai:gpt-5.5", tools });
const result = await agent.invoke({
messages: [
{ role: "user", content: "Take a screenshot of the current page" },
],
});
// 访问工具消息中的多模态内容
for (const message of result.messages) {
if (message.type === "tool") {
// 服务商原生格式的原始内容
console.log(`Raw content: ${message.content}`);
// 标准化的内容块
for (const block of message.contentBlocks) {
if (block.type === "text") {
console.log(`Text: ${block.text}`);
} else if (block.type === "image") {
console.log(`Image URL: ${block.url}`);
console.log(`Image base64: ${block.base64?.slice(0, 50)}...`);
}
}
}
}
}
import { createAgent } from "langchain";
async function accessMultimodalToolContent(): Promise<void> {
const { MultiServerMCPClient } = await import("@langchain/mcp-adapters");
const client = new MultiServerMCPClient({});
const tools = await client.getTools();
const agent = createAgent({ model: "anthropic:claude-sonnet-4-6", tools });
const result = await agent.invoke({
messages: [
{ role: "user", content: "Take a screenshot of the current page" },
],
});
// 访问工具消息中的多模态内容
for (const message of result.messages) {
if (message.type === "tool") {
// 服务商原生格式的原始内容
console.log(`Raw content: ${message.content}`);
// 标准化的内容块
for (const block of message.contentBlocks) {
if (block.type === "text") {
console.log(`Text: ${block.text}`);
} else if (block.type === "image") {
console.log(`Image URL: ${block.url}`);
console.log(`Image base64: ${block.base64?.slice(0, 50)}...`);
}
}
}
}
}
import { createAgent } from "langchain";
async function accessMultimodalToolContent(): Promise<void> {
const { MultiServerMCPClient } = await import("@langchain/mcp-adapters");
const client = new MultiServerMCPClient({});
const tools = await client.getTools();
const agent = createAgent({ model: "openrouter:openrouter:z-ai/glm-5.2", tools });
const result = await agent.invoke({
messages: [
{ role: "user", content: "Take a screenshot of the current page" },
],
});
// 访问工具消息中的多模态内容
for (const message of result.messages) {
if (message.type === "tool") {
// 服务商原生格式的原始内容
console.log(`Raw content: ${message.content}`);
// 标准化的内容块
for (const block of message.contentBlocks) {
if (block.type === "text") {
console.log(`Text: ${block.text}`);
} else if (block.type === "image") {
console.log(`Image URL: ${block.url}`);
console.log(`Image base64: ${block.base64?.slice(0, 50)}...`);
}
}
}
}
}
import { createAgent } from "langchain";
async function accessMultimodalToolContent(): Promise<void> {
const { MultiServerMCPClient } = await import("@langchain/mcp-adapters");
const client = new MultiServerMCPClient({});
const tools = await client.getTools();
const agent = createAgent({ model: "fireworks:accounts/fireworks/models/glm-5p2", tools });
const result = await agent.invoke({
messages: [
{ role: "user", content: "Take a screenshot of the current page" },
],
});
// 访问工具消息中的多模态内容
for (const message of result.messages) {
if (message.type === "tool") {
// 服务商原生格式的原始内容
console.log(`Raw content: ${message.content}`);
// 标准化的内容块
for (const block of message.contentBlocks) {
if (block.type === "text") {
console.log(`Text: ${block.text}`);
} else if (block.type === "image") {
console.log(`Image URL: ${block.url}`);
console.log(`Image base64: ${block.base64?.slice(0, 50)}...`);
}
}
}
}
}
import { createAgent } from "langchain";
async function accessMultimodalToolContent(): Promise<void> {
const { MultiServerMCPClient } = await import("@langchain/mcp-adapters");
const client = new MultiServerMCPClient({});
const tools = await client.getTools();
const agent = createAgent({ model: "baseten:zai-org/GLM-5.2", tools });
const result = await agent.invoke({
messages: [
{ role: "user", content: "Take a screenshot of the current page" },
],
});
// 访问工具消息中的多模态内容
for (const message of result.messages) {
if (message.type === "tool") {
// 服务商原生格式的原始内容
console.log(`Raw content: ${message.content}`);
// 标准化的内容块
for (const block of message.contentBlocks) {
if (block.type === "text") {
console.log(`Text: ${block.text}`);
} else if (block.type === "image") {
console.log(`Image URL: ${block.url}`);
console.log(`Image base64: ${block.base64?.slice(0, 50)}...`);
}
}
}
}
}
import { createAgent } from "langchain";
async function accessMultimodalToolContent(): Promise<void> {
const { MultiServerMCPClient } = await import("@langchain/mcp-adapters");
const client = new MultiServerMCPClient({});
const tools = await client.getTools();
const agent = createAgent({ model: "ollama:north-mini-code-1.0", tools });
const result = await agent.invoke({
messages: [
{ role: "user", content: "Take a screenshot of the current page" },
],
});
// 访问工具消息中的多模态内容
for (const message of result.messages) {
if (message.type === "tool") {
// 服务商原生格式的原始内容
console.log(`Raw content: ${message.content}`);
// 标准化的内容块
for (const block of message.contentBlocks) {
if (block.type === "text") {
console.log(`Text: ${block.text}`);
} else if (block.type === "image") {
console.log(`Image URL: ${block.url}`);
console.log(`Image base64: ${block.base64?.slice(0, 50)}...`);
}
}
}
}
}
其他资源
Connect these docs to Claude, VSCode, and more via MCP for real-time answers.

