AI Engineering, Agent Frameworks12 min read

langchain-mcp-adapters: Fix ToolException Errors

Debug langchain-mcp-adapters ToolException errors fast. Causes, code fixes, and a checklist for connecting LangChain agents to MCP servers.

langchain-mcp-adapters: Fix ToolException Errors

langchain-mcp-adapters: Fixing ToolException Errors in LangChain MCP Integrations

TL;DR: A ToolException from langchain-mcp-adapters means the MCP tool was found and called, but the underlying MCP server returned an error result (isError: true) or the transport failed mid-call. The fix is almost always one of four things: a crashed or unreachable server process, an argument schema mismatch, a session that closed before the tool ran, or an unhandled exception inside the server's tool handler.

Key Takeaways

  • `ToolException` is raised by `langchain-mcp-adapters` when an MCP `tools/call` returns a result with `isError: true`, not when a tool is missing — a missing tool raises a different error during discovery.
  • The most common root cause is a stdio MCP server that exits or never starts, usually because of a wrong `command`, missing dependency, or an unset environment variable.
  • `MultiServerMCPClient.get_tools()` opens and closes a fresh session per call by default; calling a tool outside a live session is the second most frequent cause of confusing errors.
  • Argument schema mismatches — sending a string where the server expects an integer, or omitting a required field — surface as `ToolException` because the server rejects the call, not because LangChain validated it.
  • Setting `handle_tool_errors=False` and reading the raw MCP error payload is the single fastest way to turn an opaque `ToolException` into an actionable message.
  • Always pin `langchain-mcp-adapters` to a known version: the API changed meaningfully between the pre-1.0 `load_mcp_tools` helper and the `MultiServerMCPClient` released in the 0.1.x line.

What is langchain-mcp-adapters?

langchain-mcp-adapters is the official bridge between Model Context Protocol servers and the LangChain/LangGraph ecosystem. It does one job well: it connects to one or more MCP servers, calls tools/list to discover their tools, and wraps each remote tool as a native LangChain StructuredTool that an agent can invoke like any local Python function.

That wrapping is where ToolException enters the picture. When your LangGraph agent decides to call an MCP tool, the adapter issues a JSON-RPC tools/call request over the configured transport (stdio or streamable HTTP). If the server responds with a normal result, the adapter returns the text content to the model. If the server responds with isError: true, or the transport breaks before a response arrives, the adapter raises langchain_core.tools.ToolException.

A minimal, working setup looks like this:

If everything is wired correctly, the agent calls the multiply tool exposed by math_server.py and answers 84. If anything is wrong, you get a ToolException — and the message is often unhelpfully generic. The rest of this guide is about turning that generic message into a fix.

What does ToolException actually mean?

ToolException is not an MCP concept. It is a LangChain-level exception (langchain_core.tools.ToolException) that the adapter raises to signal "the tool ran but failed." This distinction matters because it tells you where to look.

There are three categories of failure, and only one of them is a true ToolException:

The key insight: by the time you see ToolException, the tool was found and called. The problem is downstream of discovery. So stop checking whether the tool exists — it does — and start checking what happens when it runs.

Cause 1: The MCP server process never started

This is the number-one cause of ToolException with stdio transport, and it is deceptively easy to miss because the error appears at call time, not at startup.

With stdio, langchain-mcp-adapters spawns your server as a child process using the command and args you provide. If that command is wrong, the process exits immediately. Discovery may even appear to succeed if the adapter caches an empty toolset, but the first real tools/call fails because there is nothing on the other end of the pipe.

Reproduce the failure mode deliberately:

The fixes, in order of reliability:

  1. Use an absolute path for `args`. The child process inherits the parent's working directory, which is rarely what you assume in a deployed app.
  2. Use `sys.executable` instead of a bare `"python"` so the server runs in the same interpreter/venv as your app:

  1. Run the server by hand first. Before debugging the adapter, confirm the server starts on its own:

  1. Pass environment variables explicitly. The spawned process does not automatically inherit every variable you expect — pass an `env` dict for anything the server needs (API keys, paths):

A missing env var that the server reads at import time will crash it before it can answer a single call — and the only symptom you ever see is ToolException at the agent layer.

Cause 2: Calling tools outside a live session

MultiServerMCPClient has two ways to get tools, and mixing them up produces errors that look like server failures but are actually lifecycle bugs.

await client.get_tools() (no arguments) opens a fresh, short-lived session per tool call. This is convenient and stateless, but it means each invocation re-spawns or re-connects the server. For stdio servers that are slow to boot, or HTTP servers behind a cold-start proxy, the repeated connect/disconnect cycle can race and surface as a ToolException with a closed-stream error underneath.

When you need a persistent session — for stateful servers, connection pooling, or performance — open one explicitly:

The classic mistake is loading tools inside the async with block, then storing them and invoking the agent after the block exits. The session is closed, the transport is gone, and the next tools/call raises ToolException. If your error stack mentions ClosedResourceError, anyio, or a closed memory stream, this is your bug.

Rule of thumb: use client.get_tools() for simple, stateless tools, and the explicit client.session(...) context manager only when you genuinely need persistence — and never let session-bound tools escape their async with scope.

Cause 3: Argument schema mismatches

LangChain does not deeply validate arguments against the MCP server's input schema before sending them — it trusts the model to produce arguments matching the tool's JSON schema. When the model gets it slightly wrong, the server rejects the call and you get ToolException.

Common variants:

  • Type coercion gaps. The model emits `"7"` (string) for a parameter the server typed as `integer`. Strict servers reject it.
  • Missing required fields. The tool schema marks `query` as required, but the model only sent `limit`.
  • Extra fields. Some servers run in strict mode and reject unknown properties.

Diagnose by inspecting the actual schema the adapter discovered:

If the schema looks correct but calls still fail, the fix usually lives on the server side: relax overly strict typing, add sensible coercion, or improve the tool's description so the model populates arguments correctly. A precise, example-rich tool description is one of the highest-leverage changes you can make — the model's argument quality is downstream of how well the tool describes itself.

Cause 4: Exceptions inside the server's tool handler

If your MCP server's tool function raises an unhandled exception, a well-behaved server converts it into an MCP error result (isError: true) — which the adapter faithfully re-raises as ToolException. The LangChain side is working correctly; the bug is in your tool code.

The fastest way to see the real error is to stop LangChain from swallowing it. By default, create_react_agent and tool wrappers may convert tool errors into a message fed back to the model. Disable that to surface the raw payload:

Then, on the server, make sure you are actually returning the error text rather than a stack-trace-free generic. With the FastMCP-style API:

When b == 0, the client receives isError: true with the message "Cannot divide by zero...", and langchain-mcp-adapters raises ToolException("Cannot divide by zero..."). Now the error tells you exactly what to fix.

A debugging checklist for ToolException

Work this list top to bottom — it is ordered by how often each cause appears in practice:

  1. Run the server standalone. `python server.py` or `npx ` directly. If it crashes, you found it.
  2. Use absolute paths and `sys.executable` for stdio commands.
  3. Pass required env vars explicitly via the `env` dict — never assume inheritance.
  4. Set `handle_tool_errors=False` to read the raw MCP error payload instead of a sanitized message.
  5. Confirm session lifetime. Are you invoking tools after the `client.session(...)` block exited? Move the call inside.
  6. Print `tool.args_schema` and compare to what the model is actually sending (LangSmith traces show the real arguments).
  7. Pin your versions. `pip show langchain-mcp-adapters` — confirm you are not mixing a tutorial written for the old `load_mcp_tools(session)` API with the newer `MultiServerMCPClient`.
  8. Check transport match. A server running streamable HTTP will never answer a client configured for `stdio`, and vice versa.

How does the API differ across versions?

A large share of langchain-mcp-adapters confusion comes from version drift. The library evolved quickly, and copy-pasted snippets from blog posts often target an API that no longer matches your installed version.

If you are following a guide that uses "transport": "sse" and it fails, switch the server and client to streamable_http, which is the supported HTTP transport in current releases. Mismatched transport names are a quiet but frequent source of connection-time ToolException.

For a deeper understanding of how MCP clients and servers negotiate capabilities — which underpins all of this — see our complete MCP protocol guide and our analysis of Cline's MCP specification adherence, which dissects the same tools/call lifecycle from the client's perspective.

FAQ

What is a ToolException in langchain-mcp-adapters?

A ToolException is a langchain_core.tools.ToolException raised when an MCP tool was successfully discovered and called, but the server returned an error result (isError: true) or the transport failed during the call. It signals a runtime failure during invocation, not a missing tool — a tool that does not exist fails during discovery instead.

Why does my MCP tool work standalone but raise ToolException in LangChain?

The most common reason is a session lifecycle bug: tools loaded inside a client.session(...) context manager are bound to that session and become invalid once the block exits. If you store the tools and invoke the agent afterward, the transport is already closed and the call raises ToolException. Keep all tool invocations inside the session's async with block, or use client.get_tools() for stateless, self-managed sessions.

How do I see the real error behind a ToolException?

Set handle_tool_errors = False on the wrapped tools so the adapter re-raises the underlying MCP error instead of returning a sanitized message to the model. Combine this with running the MCP server standalone (python server.py) to surface any startup traceback, and use LangSmith traces to inspect the exact arguments the model sent.

Does langchain-mcp-adapters validate tool arguments before calling the server?

No. The adapter trusts the model to produce arguments matching the tool's JSON input schema and forwards them to the server. If the model sends a wrong type, omits a required field, or adds unexpected fields, the server rejects the call and the adapter raises ToolException. Improving the tool's description and input schema is the most effective way to reduce these failures.

Subscribe to the newsletter

By subscribing, you agree to our Terms of Service and Privacy Policy.

About the Author

Aaron is an engineering leader, software architect, and founder with 18 years building distributed systems and cloud infrastructure. Now focused on LLM-powered platforms, agent orchestration, and production AI. He shares hands-on technical guides and framework comparisons at fp8.co.

Cite this Article

Aaron. "langchain-mcp-adapters: Fix ToolException Errors." fp8.co, June 3, 2026. https://fp8.co/articles/LangChain-MCP-Adapters-ToolException-Troubleshooting-Guide

Related Articles

MCP Explained: Complete Protocol Guide 2026

Master Model Context Protocol from architecture to implementation. Build MCP servers, understand the spec, and integrate with Claude Code and Cursor.

AI Development Tools, Model Context Protocol

AgentCore vs LangChain: 2026 Framework Guide

Compare AgentCore and LangChain for AI agents. Architecture, pricing, and deployment trade-offs explained with code.

AI Engineering, Agent Frameworks

How Cline Implements MCP: Source Code Breakdown (2026)

See exactly how Cline implements the Model Context Protocol — client architecture, tool discovery, and JSON-RPC, with real source code walkthroughs.

Agentic AI, MCP, Cline