github langchain-ai/langchainjs @langchain/mcp-adapters@2.0.0

latest releases: @langchain/typesafe@0.0.2, @langchain/neo4j@0.1.23, @langchain/xai@1.4.16...
4 hours ago

Major Changes

  • #11767 56a7f0b Thanks @byhow! - This release moves to MCP SDK 2, supports modern and legacy MCP servers in the same adapter, and lets servers ask users for input through LangGraph interrupts. It also changes tool names, configuration, and tool results. If you are upgrading from 1.x, review the changes below before updating.

    See the migration guide for more information on migrating.

    Update your client code

    Use MCPAdapter for new code:

    1.x API Recommended API
    MultiServerMCPClient MCPAdapter
    mcpServers or a flat server map { servers: { ... } }
    getTools(...) listTools(...)
    initializeConnections() listToolsets()
    ClientConfig MCPAdapterConfig

    These older APIs still work but are deprecated. listTools() returns a flat list of executable LangChain tools; listToolsets() groups them by server. Read configuration from adapter.config.servers; the returned snapshot no longer has mcpServers, and changing it does not reconfigure the adapter.

    The adapter requires @langchain/core ^1.2.6 and @langchain/langgraph ^1.4.13. It includes the MCP SDK client. If you create an SDK client yourself for loadMcpTools, switch your client imports from @modelcontextprotocol/sdk to @modelcontextprotocol/client (or @modelcontextprotocol/client/stdio for the stdio transport). getClient() now returns an SDK 2 client. An SDK 2 Client negotiates only the legacy protocol by default; pass versionNegotiation: { mode: "auto" } when you construct it to reach modern servers.

    Tool names and configuration

    • Tool names now include the server name by default, including with the deprecated MultiServerMCPClient and with one server: search on a server named docs becomes docs__search. Update code, prompts, and saved examples that refer to tool names, or set prefixToolNameWithServerName: false to keep unprefixed names. Update interruptOn approval rules to the prefixed names; a rule for delete_repo no longer matches github__delete_repo. Server names aren't validated, so choose names your model provider accepts in tool names. The standalone loadMcpTools() helper keeps its previous default of false.
    • Duplicate tool names throw. With prefixToolNameWithServerName: false, listTools() and getTools() throw MCPClientError when two servers expose the same tool name, or when one server lists a name twice. Keep the prefix, or pick tools per server from listToolsets().
    • Configuration is validated with Zod 4. Unknown adapter and server options, options that don't apply to a server's mode or transport, conflicting transport settings, empty server maps, and setting both servers and mcpServers now throw, and loadMcpTools validates its options the same way. Remove useStandardContentBlocks, onRootsListChanged, onCancelled, and stdio encoding.
    • Move notification and progress callbacks into each server's configuration:
      onMessage, onProgress, onInitialized, onPromptsListChanged,
      onResourcesListChanged, onResourcesUpdated, and onToolsListChanged.
      beforeToolCall, afterToolCall, and onConnectionError remain top-level MCPAdapter options.

    Connections and authentication

    Each server negotiates its protocol independently. Omit mode to use "auto", set mode: "modern" to require the modern protocol, or set mode: "legacy" to skip probing a known legacy server.

    • Legacy connection options need mode: "legacy". This applies to onInitialized, onElicitation, automaticSSEFallback, and HTTP/SSE reconnect. HTTP connections in "auto" or "modern" mode no longer resume a dropped response stream. Use legacy mode if you depend on that behavior.
    • Some client methods are legacy-only. On a server that negotiates the modern protocol, setLoggingLevel() throws; set the server's logLevel instead. Modern servers reject resources/subscribe; list the URIs to watch in the server's resourceSubscriptions option and handle onResourcesUpdated.
    • SSE remains a legacy transport. It rejects mode: "modern", elicitation, and logLevel. The SSEConnection type now describes SSE only; use StreamableHTTPConnection for HTTP or Connection for any transport. Automatic HTTP-to-SSE fallback in "auto" mode is limited to HTTP 404 and 405.
    • authProvider accepts token providers as well as OAuth providers. Use { token, onUnauthorized? } for tokens your app manages. Once a provider has a token, it takes precedence over a configured Authorization header; until then, the configured header is sent. Complete OAuth redirects through the SDK's transport.finishAuth(params) using the same provider storage.
    • Authentication failures can recover. Discovery retries an authentication failure on the next call, including with onConnectionError: "ignore". Walk the error's cause chain for UnauthorizedError (now exported) or an HTTP 401 error: discovery wraps it in MCPClientError, twice when legacy mode falls back to SSE, and tool calls wrap it in ToolException.
    • Tool catalogs are kept separate for different headers and provider objects. Recreate the adapter if you switch accounts behind the same provider object. A method-level authProvider replaces the configured one, and method-level headers are added to each server's headers, where a configured header with the same name wins. Both apply to all of the adapter's HTTP/SSE servers, even when you select tools from just one server.

    See the connections guide and authentication guide.

    Servers can pause a run to ask for input

    Modern MCP elicitation is enabled by default. When a tool asks the user to fill in a form or visit a URL, the adapter pauses the run with a LangGraph interrupt. Use a checkpointer and resume with createMCPElicitationResume(interrupt, responses) inside a LangGraph Command. A tool needs a checkpointer only if it asks for input; otherwise direct invocation still works. Set elicitation: false on a server to opt out. Legacy servers can use the new per-server onElicitation callback with mode: "legacy".

    Resuming runs the tool again from the beginning, including beforeToolCall. Make sure repeating that work will not duplicate side effects. Answers must cover every request in the interrupt and match the requested form schema. Sampling and roots requests are not answered through these interrupts; they fail the tool call with a ToolException, even alongside an elicitation.

    Tool results and errors

    • Multimodal content uses standard LangChain blocks. Images and audio expose data and mimeType; resource links become file blocks with url, mimeType, and resource metadata. Update consumers of image_url, mime_type, or source_type. Blocks routed to the artifact keep their MCP format, including when passed to afterToolCall.
    • Structured output and protocol metadata stay in the artifact. Read structuredContent from the mcp_structured_content entry and _meta from mcp_meta. A single text block now becomes plain string content even when those fields are present, so they are no longer included in what the model sees. Original resource blocks and content metadata are retained in mcp_content entries when conversion would otherwise lose them.
    • Resource conversion no longer fetches URIs. Call readResource() explicitly when you need to fetch a resource. When routed to model content, embedded text resources become text blocks; embedded binary resources become image, audio, or file blocks according to their MIME type. readResource() preserves SDK metadata; narrow its results with "text" in content or "blob" in content.
    • Server-reported failures return an error message. When an MCP server returns a tool result with isError, the adapter returns a ToolMessage with status: "error" for an agent's tool call. Direct invocation with plain arguments still throws ToolException, with the MCP response in error.result.
    • Connection and validation failures still throw from the tool. Invoked directly, the tool raises the exception; in a createAgent agent, the default tool error handling turns it into a ToolMessage with status: "error". Read the exception's message for details; cause is not always set.
    • Hooks preserve ToolMessage and LangGraph Command results. They are no longer flattened or rejected. Hook state is now typed unknown; narrow it before use, and return an object when overriding arguments. The merged arguments are validated against the tool's input schema before the call is sent. afterToolCall receives successful results only.
    • Tool input schemas are no longer simplified. They reach the model as the server declares them. 1.x inlined $ref definitions, merged allOf, flattened anyOf and oneOf, and removed if/then/else, not, $schema, and unevaluatedProperties.

    Discovery, cleanup, and diagnostics

    • listTools([], { cacheMode: "refresh" }) refreshes discovery; cacheMode: "bypass" skips the cache. A failed refresh keeps previously returned tools usable.
    • Keep the adapter open while using its tools, then await close(). Closing stops active discovery and pending reconnects and clears connections and caches. You can reuse the adapter by discovering fresh tools afterwards.
    • listResources() and listResourceTemplates() now surface server errors; 1.x returned [] for a failing server and logged the error only under DEBUG. A server that does not implement resource-template listing still contributes [].
    • DEBUG=@langchain/mcp-adapters:* no longer emits logs; use onConnectionError and the per-server notification callbacks.
    • Exhausted background stdio restart attempts report through an onConnectionError callback. Errors thrown or rejected by an onProgress callback are now ignored.

Don't miss a new langchainjs release

NewReleases is sending notifications on new releases.