The LangChainAdapter converts MCP tools into DynamicStructuredTool instances from @langchain/core. The resulting array is compatible with any LangChain agent constructor that accepts a tools parameter, including createReactAgent from LangGraph.
Installation
npm install @mcp-ts/sdk @langchain/core zod
pnpm add @mcp-ts/sdk @langchain/core zod
yarn add @mcp-ts/sdk @langchain/core zod
zod is a required peer dependency. The adapter uses it to convert MCP JSON Schema definitions into Zod schemas that LangChain expects.
Quick start
import { MultiSessionClient } from '@mcp-ts/sdk/server';
import { LangChainAdapter } from '@mcp-ts/sdk/adapters/langchain';
const client = new MultiSessionClient('user_123');
await client.connect();
const tools = await LangChainAdapter.getTools(client);
API reference
new LangChainAdapter(client, options?)
Creates an adapter instance. Dependencies (@langchain/core and zod) are loaded lazily on the first call to getTools().
| Parameter | Type | Description |
|---|
client | MCPClient | MultiSessionClient | The MCP client to source tools from. |
options | LangChainAdapterOptions | Optional configuration (see below). |
Fetches the tool list from all connected MCP servers and returns a Promise<StructuredTool[]>. Each tool is an instance of DynamicStructuredTool with:
name — <prefix>_<toolName> (e.g., abcd1234_web_search)
description — the MCP tool’s description
schema — a Zod schema derived from the tool’s JSON Schema input definition
func — an async function that calls client.callTool(toolName, args)
When the underlying client is not connected, getTools() returns an empty array [] instead of throwing.
A convenience wrapper that creates a LangChainAdapter and immediately calls getTools().
const tools = await LangChainAdapter.getTools(client, { simplifyErrors: true });
LangChainAdapterOptions
| Field | Type | Default | Description |
|---|
prefix | string | Server ID (8 chars) | Namespace prefix prepended to every tool name. |
simplifyErrors | boolean | false | When true, catches errors in func and returns "Error: <message>" as a string instead of throwing. Useful when you want the LLM to see the error and recover. |
toolRouter | ToolRouter | — | Use a ToolRouter for intelligent tool filtering. Exposes only meta-tools to reduce context usage. |
Complete agent example
The following example wires MCP tools into a LangGraph ReAct agent and runs a query.
import { MultiSessionClient } from '@mcp-ts/sdk/server';
import { LangChainAdapter } from '@mcp-ts/sdk/adapters/langchain';
import { createReactAgent } from '@langchain/langgraph/prebuilt';
import { ChatOpenAI } from '@langchain/openai';
import { HumanMessage } from '@langchain/core/messages';
const client = new MultiSessionClient('user_123');
await client.connect();
const tools = await LangChainAdapter.getTools(client);
const llm = new ChatOpenAI({
model: 'gpt-4o',
temperature: 0,
});
const agent = createReactAgent({ llm, tools });
const result = await agent.invoke({
messages: [new HumanMessage('Find the latest changelog for TypeScript 5.5')],
});
console.log(result.messages.at(-1)?.content);
Simplified error messages
By default, errors thrown inside a tool’s func propagate as exceptions and can interrupt agent execution. Set simplifyErrors: true to catch errors and return them as plain strings — the LLM can then read the error and decide how to proceed.
const tools = await LangChainAdapter.getTools(client, { simplifyErrors: true });
// On error, func returns: "Error: connection timeout" instead of throwing
Enable simplifyErrors when building multi-step agents where a single tool failure should not abort the entire chain. The LLM will see the error message and can try an alternative approach.
Tool names follow the pattern <prefix>_<toolName>. The prefix defaults to the first eight characters of the server ID with hyphens removed.
abcd1234_web_search
abcd1234_read_file
Pass an explicit prefix to control the namespace:
const tools = await LangChainAdapter.getTools(client, { prefix: 'search' });
// search_web_search, search_read_file, …
Using with MultiSessionClient
When you pass a MultiSessionClient, the adapter fetches tools from every connected server concurrently and returns a flat array. Servers that fail to respond are logged and skipped.
import { MultiSessionClient } from '@mcp-ts/sdk/server';
import { LangChainAdapter } from '@mcp-ts/sdk/adapters/langchain';
const client = new MultiSessionClient('user_123');
await client.connect();
// Fetches tools from all connected servers in parallel
const tools = await LangChainAdapter.getTools(client);
Reducing context with ToolRouter
Supply a ToolRouter to expose only meta-tools when you have a large number of MCP tools and want to reduce the prompt size.
import { LangChainAdapter } from '@mcp-ts/sdk/adapters/langchain';
import { ToolRouter } from '@mcp-ts/sdk/shared';
const router = new ToolRouter(client, { strategy: 'search' });
const tools = await LangChainAdapter.getTools(client, { toolRouter: router });