layout: default
title: "Bridging Legacies: Implementing langchain-mcp-adapters for Multi-Server Routing"
date: 2024-05-28
---
# Bridging Legacies: Implementing langchain-mcp-adapters for Multi-Server Routing
You’re building a smart assistant. It needs to query a legacy inventory database, pull documentation from an internal wiki, and ask a weather API whether your warehouse roof will leak tonight. Each of those systems speaks a different language, lives on a different server, and expects a different handshake.
This is the integration nightmare that `langchain-mcp-adapters` solves. In this tutorial, you’ll learn exactly what `langchain-mcp-adapters` is, how `MultiServerMCPClient` orchestrates chaos into order, what **Interceptors** are and why they matter, how **Multimodal Tool Content** handles images and text together, what **Stateful Client Sessions** mean for real conversations, and how **Unified Tool Routing** lets your app call the right tool without caring which server owns it. By the end, you’ll have a concrete pattern to bridge legacy systems into modern AI workflows.
---
<figure class="post-hero-image">
<img class="post-hero" src="/assets/images/posts/2026-05-21-bridging-legacies-implementing-langchain-mcp-adapters-for-multi-server-routing.jpg" alt="Hero image for Bridging Legacies: Implementing langchain-mcp-adapters for Multi-Server Routing" loading="lazy">
<figcaption>Architecture diagram generated by [Google Gemini 3.1 Flash Image](https://ai.google.dev)</figcaption>
</figure>
## What is `langchain-mcp-adapters`?
**Plain-English definition:** A library that lets LangChain agents talk to Model Context Protocol (MCP) servers. MCP is a standard way for AI models to call tools hosted on remote servers.
**How it works:** MCP servers expose tools (functions, APIs, databases) as resources an AI can invoke. `langchain-mcp-adapters` translates LangChain’s tool-calling interface into MCP’s protocol and vice versa. Think of it as a universal remote that works with any TV, regardless of brand.
**Real-world analogy:** You walk into a hotel. You want to order room service, control the thermostat, and book a spa appointment. Each service has its own phone number. A concierge takes your single request and routes it to the right person. That concierge is `langchain-mcp-adapters`.
**Code snippet:**
```python
from langchain_mcp_adapters.client import MultiServerMCPClient
from langchain.agents import AgentExecutor, create_openai_functions_agent
# The adapter wraps the MCP client logic
# Under the hood, it creates a LangChain tool for each MCP tool discovered
# No manual translation required
MultiServerMCPClient: The Maestro
Plain-English definition: A client that connects to multiple MCP servers simultaneously, discovers their tools, and presents them as a single unified list to your LangChain agent.
How it works: You give MultiServerMCPClient a dictionary mapping server names to connection details (URLs, credentials). It opens a WebSocket connection to each server, asks “what tools do you have?”, and registers every tool it finds. The agent then calls tools by name, but the client routes the call to the correct server.
Real-world analogy: Your phone has one contact list but can call landlines, mobiles, and international numbers. You just say “Call Sarah.” The phone knows Sarah’s number type and routes accordingly.
Code example:
client = MultiServerMCPClient({
"weather": {"url": "ws://weather-server:8000/mcp"},
"inventory": {"url": "ws://legacy-db:9000/mcp"}
})
# After connection, client.tools holds all tools from both servers
agent = create_openai_functions_agent(llm, client.tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=client.tools)
result = agent_executor.invoke({"input": "Check inventory for umbrellas"})
# The agent calls "search_inventory" — MultiServerMCPClient routes it to the inventory server
Non-obvious insight: If two servers expose a tool with the same name, MultiServerMCPClient will overwrite one. Always prefix tool names in your MCP server configuration or handle conflicts in the adapter.
Interceptors: The Middleware You Didn’t Know You Needed
Plain-English definition: Functions that sit between your agent and the MCP server, modifying requests or responses before they reach their destination.
How it works: When your agent calls a tool, the call passes through an interceptor chain. Each interceptor can log, validate, modify, or even reject the request. Similarly, responses flow back through interceptors for post-processing. It’s like a pipeline for tool calls.
Real-world analogy: Airport security. Passengers (tool calls) queue up. Each checkpoint (interceptor) checks something: ID, ticket, luggage. If a passenger fails, they’re turned away. If they pass all checkpoints, they board the plane (reach the server).
Code example:
from langchain_mcp_adapters.interceptors import ToolInterceptor
class AuthInterceptor(ToolInterceptor):
def pre_call(self, tool_name, args, config):
# Add authentication token to every call
args["api_key"] = config.get("api_key")
return args
def post_call(self, tool_name, result):
# Log response
print(f"Tool {tool_name} returned: {result}")
return result
client.add_interceptor(AuthInterceptor())
Gotcha: Interceptors run in order. If you add multiple, they execute sequentially. A slow interceptor can bottleneck your entire pipeline.
Multimodal Tool Content: When Text Isn’t Enough
Plain-English definition: The ability for tools to accept and return content that includes images, audio, or structured data alongside text.
How it works: MCP defines content types (like text, image, or blob). When a tool returns an image, the adapter encodes it as a base64 string with a MIME type. LangChain agents that support multimodal models can then pass that content back into the model for interpretation.
Real-world analogy: A recipe card. It has text instructions (text) and a photo of the finished dish (image). Both are part of the same response. You can read the steps and look at the picture.
Code example:
# Server returns tool result with image
{
"tool_name": "get_product_photo",
"content": [
{"type": "text", "text": "Product: Umbrella XL"},
{"type": "image", "source": {"data": "<base64>", "mime_type": "image/jpeg"}}
]
}
# In your agent, the multimodal model sees both
result = agent_executor.invoke({"input": "Show me the umbrella photo"})
# The agent can describe the image or use it for vision tasks
Non-obvious insight: Not all models support multimodal input. If your LLM only accepts text, image content will be ignored or cause an error. Always check your model’s capabilities before relying on multimodal tools.
Stateful Client Sessions: Remembering What Happened
Plain-English definition: A session that maintains state across multiple tool calls, so the server remembers previous interactions.
How it works: Instead of each tool call being independent, MultiServerMCPClient can open a persistent session (WebSocket) per server. The server tracks conversation state, variables, or authentication within that session. When the session ends, the state is lost.
Real-world analogy: A restaurant table. You start with an empty table. The waiter writes your starter order (first tool call). They don’t forget it when you order mains (second call). At the end, the bill (session summary) includes everything.
Code example:
# Session is maintained automatically with the connection
with MultiServerMCPClient({
"chat": {"url": "ws://chat-server:8080/mcp", "session": True}
}) as client:
# First call sets context
client.call_tool("set_context", {"user": "alice", "level": "premium"})
# Second call uses that context
result = client.call_tool("get_discount", {"product": "umbrella"})
# Server knows Alice is premium, applies discount
Gotcha: If the connection drops, the session state is lost. Implement reconnection logic with session restoration if that’s critical.
Unified Tool Routing: One API, Many Backends
Plain-English definition: A single interface that maps tool names to server-specific implementations. The agent doesn’t know or care which server handles the call.
How it works: After discovering all tools from all connected servers, the adapter creates a routing table. When a tool is called, the adapter looks up the server address from the table and forwards the request. This decouples tool logic from server location.
Real-world analogy: A call center. You dial one number. The system routes you to sales, support, or billing based on your menu choice (the tool name). You don’t need to know which building the agent sits in.
Code example:
client = MultiServerMCPClient({
"weather": {"url": "ws://weather:8000"},
"inventory": {"url": "ws://inventory:9000"},
"wiki": {"url": "ws://wiki:7000"}
})
# After connection, client.tools merges all tools
# Agent calls "check_weather" -> routed to weather server
# Agent calls "search_wiki" -> routed to wiki server
# The agent doesn't know about servers at all — just tools
Comparison Table: How These Concepts Relate
| Concept | What It Does | Why You Need It | Analogy |
|---|---|---|---|
langchain-mcp-adapters |
Translates between LangChain and MCP server protocols | Lets your AI talk to any MCP server | Universal remote |
MultiServerMCPClient |
Connects to many MCP servers at once | One client to rule them all | Maestro conducting an orchestra |
| Interceptors | Modify tool calls/responses in a pipeline | Add auth, logging, validation | Airport security |
| Multimodal Tool Content | Handles images/audio alongside text | Pass visuals to your AI model | Recipe card with photos |
| Stateful Client Sessions | Maintains context across tool calls | Remember who the user is | Restaurant table |
| Unified Tool Routing | Hides server complexity from the agent | Single API for many backends | Call center routing |
Key Takeaways
langchain-mcp-adaptersbridges your LangChain agent to any MCP server without custom coding.MultiServerMCPClientdiscovers and merges tools from many servers into one list.- Interceptors let you inject logic before or after tool calls — perfect for security and monitoring.
- Multimodal Tool Content enriches responses with images, but verify your model supports it.
- Stateful Client Sessions keep context alive; reconnect logic is essential for reliability.
- Unified Tool Routing frees your agent from knowing server details — it just calls tools by name.
So why should you care? You have legacy systems that your AI needs to talk to. Instead of rewriting them or building brittle point-to-point integrations, langchain-mcp-adapters gives you a clean, maintainable pattern that scales as you add more servers. It turns chaos into a single API.
Conclusion: Go try it. Connect your LangChain agent to two different MCP servers today. You’ll be shocked how little code it takes. Your legacy systems have been waiting for this — and now your AI can finally understand them.
Comments