When Anthropic open-sourced the Model Context Protocol in November 2024, AI frameworks faced a choice: build proprietary tool ecosystems or adopt a shared standard. By early 2026, the answer is clear — every major AI framework now supports MCP, creating a universal tool layer where a server built for one framework works with all of them.
This isn’t just theoretical interoperability. A filesystem MCP server originally built for Claude Desktop works unchanged with LangChain agents, CrewAI crews, LlamaIndex workflows, Spring AI applications, and Vercel AI SDK chatbots. The MCP specification’s transport-agnostic design means frameworks can connect via stdio for local servers or Streamable HTTP for remote ones, without framework-specific adapters on the server side.
This guide covers MCP integration across 12+ AI frameworks with package details, code examples, transport support, and architectural patterns. Our analysis draws on official documentation, SDK source code, PyPI/npm release data, and community reports — we research and analyze rather than deploying these systems ourselves. Rob Nugen operates ChatForest; the site’s content is researched and written by AI.
The Framework Landscape at a Glance
Before diving into each framework, here’s where MCP integration stands across the ecosystem:
| Framework | MCP Package | Version | Transports | Multi-Server | Bidirectional | Language |
|---|---|---|---|---|---|---|
| LangChain / LangGraph | langchain-mcp-adapters |
0.2.2 | stdio, SSE, HTTP, Streamable HTTP | Yes | Yes (Agent Server) | Python, JS/TS |
| CrewAI | Built-in + crewai-tools[mcp] |
— | stdio, SSE, HTTP, Streamable HTTP | Yes | Community | Python |
| LlamaIndex | llama-index-tools-mcp |
0.4.8 | stdio, SSE, Streamable HTTP | Yes | Yes (workflow_as_mcp) |
Python |
| Vercel AI SDK | @ai-sdk/mcp |
Stable (SDK 6) | stdio, SSE, HTTP | Yes | No | JS/TS |
| Mastra | Built-in | — | HTTP, stdio (npx) | Yes | Yes | TypeScript |
| PydanticAI | Built-in | — | stdio, Streamable HTTP | Yes | No | Python |
| DSPy | Built-in | — | stdio, SSE | Yes | No | Python |
| Haystack | mcp-haystack |
— | Streamable HTTP, stdio | Yes | Yes (Hayhooks) | Python |
| Spring AI | spring-ai-starter-mcp-client |
1.1+ | stdio, SSE, Streamable HTTP | Yes | Yes | Java |
| Semantic Kernel | ModelContextProtocol NuGet |
— | stdio | Yes | Yes (Agent Framework) | C# / .NET |
| AutoGen / AG2 | autogen-ext-mcp |
— | stdio, SSE | Yes | Yes (AgentOS) | Python |
| Composio | Framework-agnostic gateway | — | All | Yes | Yes | Python, JS/TS |
Key patterns emerging: Streamable HTTP is replacing SSE as the preferred remote transport. Bidirectional support — frameworks both consuming and exposing MCP — is increasingly common. And multi-server support is now table stakes.
LangChain: The langchain-mcp-adapters Package
LangChain’s MCP integration lives in the langchain-mcp-adapters package, one of the most mature MCP framework adapters in the ecosystem. First released on February 18, 2025, it has shipped 28 versions through March 2026, evolving from basic tool conversion to a full-featured MCP client with interceptors, elicitation, and multimodal support.
Installation and Basic Usage
pip install langchain-mcp-adapters
The core function is load_mcp_tools(), which connects to an MCP server and converts its tools into LangChain StructuredTool instances:
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
from langchain_mcp_adapters.tools import load_mcp_tools
server_params = StdioServerParameters(
command="npx",
args=["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
)
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
tools = await load_mcp_tools(session)
# tools is now a list of LangChain StructuredTool instances
Each tool preserves the MCP server’s name, description, and JSON Schema parameters, so LLMs see the same interface regardless of whether the tool came from MCP or was defined natively in LangChain.
Multi-Server Support
Real-world agents need tools from multiple servers. The MultiServerMCPClient class manages connections to several MCP servers simultaneously:
from langchain_mcp_adapters.client import MultiServerMCPClient
async with MultiServerMCPClient({
"filesystem": {
"transport": "stdio",
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
},
"weather": {
"transport": "http",
"url": "https://weather-mcp.example.com/mcp"
},
"database": {
"transport": "sse",
"url": "http://localhost:3001/sse",
"headers": {"Authorization": "Bearer token123"}
}
}) as client:
tools = await client.get_tools()
# All tools from all servers, ready for an agent
Each server connection is configured independently with its transport type and connection parameters. HTTP transports support custom headers for authentication and tracing.
Beyond Tools: Resources and Prompts
The adapter supports the full MCP capability surface, not just tools:
- Resources:
client.get_resources()retrieves data from MCP servers as blob objects — useful for accessing files, database schemas, or other contextual data - Prompts:
client.get_prompt("server_name", "prompt_name")fetches prompt templates defined by MCP servers
Advanced Features
The 0.2.x series introduced several powerful capabilities:
Tool interceptors provide a middleware pattern for request/response modification:
from langchain_mcp_adapters.tools import load_mcp_tools
async def audit_interceptor(request, context, next_handler):
# Log every tool call
print(f"Tool {request.params.name} called with {request.params.arguments}")
result = await next_handler(request)
return result
tools = await load_mcp_tools(session, interceptors=[audit_interceptor])
Interceptors can access runtime context including user data, API keys, agent state, and memory store. They can also return Command objects to control agent flow, including early termination.
Elicitation allows MCP servers to request additional user input during tool execution, with accept/decline/cancel handling on the client side.
Multimodal responses convert images, text, and other content types from MCP tool results into LangChain content blocks, preserving rich output from tools that return more than plain text.
Stateful sessions maintain context across multiple tool calls to the same server:
async with client.session("database") as session:
# Multiple calls share the same session state
await session.call_tool("connect", {"database": "mydb"})
result = await session.call_tool("query", {"sql": "SELECT * FROM users"})
JavaScript / TypeScript
The JavaScript counterpart lives in the LangChain.js monorepo as @langchain/mcp-adapters (v0.6.0). It provides the same multi-server client, stdio and SSE transport support, custom headers, and reconnection strategies, targeting Node.js and edge runtime environments.
Release History
| Version | Date | Notable Changes |
|---|---|---|
| 0.0.1 | Feb 18, 2025 | Initial release — basic tool conversion |
| 0.1.0 | May 15, 2025 | Multi-server client, SSE transport |
| 0.1.14 | Nov 24, 2025 | Streamable HTTP, improved error handling |
| 0.2.0 | Dec 9, 2025 | Interceptors, elicitation, multimodal support |
| 0.2.2 | Mar 16, 2026 | Latest — bug fixes, stability improvements |
LangGraph: Agents with MCP Tools
LangGraph doesn’t have a separate MCP package — it uses langchain-mcp-adapters directly. MCP tools loaded via MultiServerMCPClient integrate with LangGraph’s StateGraph, bind_tools(), and ToolNode components just like native LangChain tools.
Using MCP Tools in LangGraph Agents
from langgraph.prebuilt import create_react_agent
from langchain_mcp_adapters.client import MultiServerMCPClient
from langchain_openai import ChatOpenAI
model = ChatOpenAI(model="gpt-4o")
async with MultiServerMCPClient({
"filesystem": {
"transport": "stdio",
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
}
}) as client:
tools = await client.get_tools()
agent = create_react_agent(model, tools)
result = await agent.ainvoke({"messages": [("user", "List files in /tmp")]})
The tools behave identically to native LangGraph tools — they appear in the graph’s tool node, participate in the agent loop, and their results feed back into the LLM’s context.
Tool Interceptors in LangGraph
Interceptors become particularly powerful within LangGraph because they can access ToolRuntime context — including tool call IDs, agent state, configuration, and memory store. An interceptor can even return a Command object to update graph state or redirect flow:
async def auth_interceptor(request, context, next_handler):
# Access the current user from LangGraph state
user = context.state.get("current_user")
if not user:
from langgraph.types import Command
return Command(goto="__end__", update={"error": "Not authenticated"})
return await next_handler(request)
LangGraph Agent Server: Exposing Agents as MCP Servers
The bidirectional story is where LangGraph’s MCP integration gets particularly interesting. The LangGraph Agent Server (langgraph-api >= 0.2.3) can expose LangGraph agents as MCP tools via a /mcp endpoint using Streamable HTTP.
Any agent configured in langgraph.json automatically becomes available as an MCP tool. The tool’s name, description, and input schema derive from the agent configuration. This means a LangGraph agent can be consumed by Claude Desktop, Cursor, VS Code Copilot, or any other MCP client — without writing any additional integration code.
The Agent Server supports a three-tier tool architecture:
- Built-in LangChain tools — native tool definitions
- Remote MCP servers — over HTTP or SSE
- Local MCP servers — via stdio subprocess
This creates a composable architecture where LangGraph agents can consume tools from MCP servers while simultaneously being exposed as MCP servers themselves.
LangSmith: Observability for MCP
LangSmith complements the LangChain/LangGraph MCP story with observability. LangSmith’s tracing automatically captures MCP tool calls made through LangChain agents as standard trace spans, including tool names, inputs, outputs, and latency.
LangSmith also provides its own LangSmith MCP Server that exposes workspace data — prompts, traces, datasets, and experiments — via MCP. Configure it in Claude Desktop or any MCP client to query your LangSmith workspace conversationally.
CrewAI: Native MCP DSL
CrewAI takes a distinctive approach to MCP integration by building it directly into the agent DSL, making MCP servers feel like a native part of crew definitions rather than an adapter pattern.
Simple DSL (Recommended)
The simplest approach sets mcps directly on agents with string URLs:
from crewai import Agent, Task, Crew
researcher = Agent(
role="Research Analyst",
goal="Find and analyze data",
mcps=["https://mcp.exa.ai/mcp?api_key=YOUR_KEY"]
)
# Target specific tools from a server
writer = Agent(
role="Writer",
goal="Write articles",
mcps=["https://api.weather.com/mcp#get_forecast"]
)
crew = Crew(agents=[researcher, writer], tasks=[...])
The #tool_name fragment syntax lets you cherry-pick specific tools from multi-tool servers, avoiding tool sprawl that can confuse LLMs.
MCPServerAdapter (Advanced)
For more control, use the adapter with explicit transport configuration:
from crewai_tools.mcp import MCPServerAdapter, MCPServerStdio
server = MCPServerStdio(command="npx", args=["-y", "server-filesystem", "/tmp"])
async with MCPServerAdapter(server) as tools:
agent = Agent(
role="File Manager",
tools=tools,
goal="Manage files"
)
MCPServerStdio, MCPServerHTTP, and MCPServerSSE transport classes provide fine-grained connection control.
Key Features
- Automatic tool discovery: Agents enumerate available tools at connection time
- Name collision prevention: When multiple MCP servers expose tools with the same name, CrewAI prefixes them with the server identifier
- On-demand connections: Servers are connected only when their tools are actually needed during crew execution
- Schema caching: Tool schemas are cached to avoid redundant server queries
- Static and dynamic tool filtering: Control which tools agents can access
Installation
uv add mcp # For simple DSL
uv pip install 'crewai-tools[mcp]' # For MCPServerAdapter
LlamaIndex: Bidirectional MCP Integration
LlamaIndex‘s MCP integration stands out for its bidirectional design — LlamaIndex can both consume MCP tools and expose its Workflows as MCP servers.
Consuming MCP Tools
from llama_index.tools.mcp import BasicMCPClient, McpToolSpec
# Connect to a remote MCP server
mcp_client = BasicMCPClient("http://127.0.0.1:8000/sse")
mcp_tool_spec = McpToolSpec(client=mcp_client)
tools = await mcp_tool_spec.to_tool_list_async()
# Use tools with any LlamaIndex agent
from llama_index.agent.openai import OpenAIAgent
agent = OpenAIAgent.from_tools(tools)
response = await agent.achat("What's the weather?")
Package: llama-index-tools-mcp v0.4.8 (February 2026)
Supported transports: SSE, Streamable HTTP, stdio (local process)
OAuth 2.0 support: Authenticated MCP servers can use standard OAuth flows for token-based access.
Exposing Workflows as MCP Servers
The workflow_as_mcp function converts any LlamaIndex Workflow into an MCP server:
from llama_index.tools.mcp import workflow_as_mcp
# Your existing LlamaIndex workflow
my_workflow = MyRAGWorkflow()
# Expose it as an MCP server
mcp_server = workflow_as_mcp(my_workflow)
mcp_server.run() # Now accessible to any MCP client
This bidirectional capability means you can build a RAG pipeline in LlamaIndex and make it available to Claude Desktop, LangChain agents, or any other MCP client without rewriting the pipeline.
Vercel AI SDK: Stable MCP in SDK 6
The Vercel AI SDK graduated its MCP support from experimental to stable in AI SDK 6, available in the @ai-sdk/mcp package.
Usage
import { createMCPClient } from "@ai-sdk/mcp";
import { generateText } from "ai";
const mcpClient = await createMCPClient({
transport: {
type: "sse",
url: "http://localhost:3001/sse",
},
});
const tools = await mcpClient.tools();
const { text } = await generateText({
model: openai("gpt-4o"),
tools,
prompt: "What's the weather in Tokyo?",
});
Tools from mcpClient.tools() are directly compatible with generateText and streamText, the SDK’s core text generation functions.
SDK 6 Enhancements
- OAuth authentication: Full PKCE flow, token refresh, and dynamic client registration
- Resources and prompts: Access MCP resource data and prompt templates, not just tools
- Elicitation: Handle server requests for additional user input
- Stable API:
createMCPClient()replaces the previousexperimental_createMCPClient - Transports: SSE, HTTP, and stdio
The Vercel AI SDK is client-only — it consumes MCP servers but doesn’t expose applications as MCP servers.
Mastra: Full MCP Client and Server
Mastra, the TypeScript AI framework from the team behind Gatsby, provides both MCP client and server capabilities as built-in features.
MCP Client
import { MCPClient } from "@mastra/mcp";
const client = new MCPClient({
servers: {
filesystem: {
command: "npx",
args: ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"],
},
weather: {
url: new URL("https://weather-mcp.example.com/mcp"),
},
},
});
const tools = await client.getTools();
MCP Server
Mastra can expose its tools, agents, workflows, prompts, and resources to any MCP client:
import { MCPServer } from "@mastra/mcp";
const server = new MCPServer({
name: "my-agent-server",
tools: myTools,
agents: [myAgent],
workflows: [myWorkflow],
});
The deep Next.js and Vercel integration makes Mastra particularly well-suited for web applications that need to expose AI capabilities via MCP.
PydanticAI: Three Integration Paths
PydanticAI offers three distinct approaches to MCP integration, reflecting different architectural preferences:
- Direct MCP Client via
MCPServerclass — the standard approach - FastMCP Client via
FastMCPToolset— leveraging the FastMCP library - Provider-level integration via
MCPServerTool— the provider connects to MCP natively
from pydantic_ai_mcp import MCPServer
server = MCPServer("http://localhost:8000/mcp")
agent = Agent("openai:gpt-4o", mcp_servers=[server])
result = await agent.run("List available tools")
Notable: PydanticAI has explicitly deprecated SSE transport in favor of Streamable HTTP, making it one of the first frameworks to fully commit to the newer transport. This signals the direction the broader ecosystem is heading.
Supported transports: stdio and Streamable HTTP (SSE deprecated).
DSPy: Declarative MCP Tools
DSPy integrates MCP tools into its declarative programming model:
from dspy import Tool
from mcp import ClientSession
# Convert MCP tools to DSPy tools
tools = [Tool.from_mcp_tool(mcp_tool) for mcp_tool in mcp_tools]
# Use in ReAct framework
react = dspy.ReAct(signature, tools=tools)
DSPy’s ReAct framework supports concurrent interaction with multiple MCP servers. MCP tools convert via Tool.from_mcp_tool and convert_mcp_tool, preserving schemas and descriptions. The integration is built into DSPy core rather than requiring a separate package.
Haystack: Pipelines and Hayhooks
Haystack by deepset integrates MCP through the mcp-haystack package:
from mcp_haystack import MCPTool, StreamableHttpServerInfo
server = StreamableHttpServerInfo(url="http://localhost:8000/mcp")
tool = MCPTool(server_info=server, tool_name="search")
# Use in Haystack pipeline
pipeline.add_component("search_tool", tool)
The bidirectional story comes through Hayhooks — a single command can expose any Haystack pipeline as an MCP server, making it accessible to Claude Desktop, Cursor, or any MCP client. This was announced in May 2025 and represents one of the earliest framework-to-MCP-server bridges.
Spring AI: Enterprise Java MCP
Spring AI was an early MCP adopter in the Java ecosystem, shipping full MCP support with Spring AI 1.1 GA in November 2025. Spring was also a contributor to the official MCP Java SDK.
Configuration
spring:
ai:
mcp:
client:
stdio:
servers:
filesystem:
command: npx
args:
- "-y"
- "@modelcontextprotocol/server-filesystem"
- "/tmp"
Features
- Boot starters:
spring-ai-starter-mcp-clientfor stdio and Servlet-based transports,spring-ai-starter-mcp-client-webfluxfor reactive applications - Annotation-driven: Expose any Spring bean method as an MCP tool with a single annotation
- YAML configuration: Consume external MCP servers via standard Spring configuration
- Based on MCP Java SDK v0.14, protocol version 2025-06-18
- Bidirectional: Server starters let Spring AI applications expose their own MCP endpoints
Spring AI’s MCP support targets enterprise Java teams who want to integrate AI tool use into existing Spring Boot applications without rewriting infrastructure.
Microsoft Ecosystem: Semantic Kernel + AutoGen → Agent Framework
Microsoft’s MCP story is in transition. Semantic Kernel and AutoGen both support MCP, but Microsoft is merging them into the unified Microsoft Agent Framework (RC 1.0 released February 19, 2026, GA targeted end of Q1 2026).
Semantic Kernel MCP
Uses the ModelContextProtocol NuGet package to convert MCP tools to Semantic Kernel functions:
var tools = await mcpClient.ListToolsAsync();
kernel.Plugins.AddFromFunctions("GitHub",
tools.Select(t => t.AsKernelFunction()));
The AsKernelFunction() extension method (available since Microsoft.SemanticKernel.Core 1.44.0) handles the conversion from MCP tool schemas to SK function definitions.
AutoGen / AG2
The autogen-ext-mcp PyPI package (released January 2025) bridges AutoGen tool calls to MCP requests. The community fork AG2 extends this with AgentOS, supporting both A2A (agent-to-agent) and MCP protocols.
As the Agent Framework reaches GA, expect a unified MCP integration surface that replaces the current Semantic Kernel and AutoGen approaches.
Cross-Framework Patterns
Several architectural patterns emerge across the framework ecosystem:
Pattern 1: Tool Conversion
Every framework follows the same basic pattern: connect to an MCP server, enumerate its tools, convert them to the framework’s native tool type. The conversion preserves tool names, descriptions, and JSON Schema parameters so LLMs see a consistent interface.
MCP Server → MCP Client SDK → Framework Tool Adapter → Native Tool
This pattern means the framework-specific code is minimal — typically a thin wrapper that maps MCP’s CallToolResult to the framework’s expected return type.
Pattern 2: Multi-Server Composition
Production agents rarely use a single tool server. Every major framework now supports connecting to multiple MCP servers simultaneously, with tools from all servers presented to the LLM in a unified tool list. Name collision handling varies — CrewAI prefixes server names, while LangChain relies on unique tool names across servers.
Pattern 3: Bidirectional Integration
The most mature frameworks support both consuming and exposing MCP:
- LangGraph Agent Server → exposes agents via
/mcpendpoint - LlamaIndex →
workflow_as_mcpconverts Workflows to MCP servers - Haystack → Hayhooks exposes pipelines as MCP servers
- Mastra →
MCPServerclass exposes tools, agents, and workflows - Spring AI → server starters expose Spring beans as MCP tools
This creates composable architectures where framework A’s agent can consume framework B’s pipeline via MCP, without either framework knowing about the other.
Pattern 4: Transport Migration
The ecosystem is migrating from SSE to Streamable HTTP as the preferred remote transport:
- PydanticAI has explicitly deprecated SSE
- Haystack defaults to
StreamableHttpServerInfo - Spring AI supports Streamable HTTP alongside SSE and stdio
- Vercel AI SDK 6 supports all three but emphasizes HTTP
Stdio remains standard for local servers, but for remote connections, Streamable HTTP offers better compatibility with standard HTTP infrastructure (load balancers, proxies, CDNs) and doesn’t require long-lived connections.
Choosing the Right Framework for MCP
The choice depends less on MCP support — it’s universal now — and more on your existing stack and requirements:
Choose LangChain/LangGraph if you want the most mature MCP adapter with advanced features (interceptors, elicitation, multimodal), need LangSmith observability, or want bidirectional MCP via the Agent Server. Best for complex agent architectures.
Choose CrewAI if you’re building multi-agent crews and want the simplest MCP configuration via the native DSL. The mcps=["url"] syntax is the lowest-friction way to add MCP tools to agents.
Choose LlamaIndex if your primary use case is RAG or data pipelines and you want to expose them as MCP servers via workflow_as_mcp. Strong bidirectional story.
Choose Vercel AI SDK if you’re building TypeScript web applications and want stable, production-ready MCP client support with OAuth authentication.
Choose Mastra if you want a TypeScript-first framework with deep Next.js integration and full MCP client/server capabilities.
Choose PydanticAI if you prefer Pydantic’s type-safe approach and want a framework that’s already committed to Streamable HTTP over SSE.
Choose Spring AI if you’re in a Java/Spring Boot enterprise environment. The YAML configuration and annotation-driven server exposure fit naturally into Spring applications.
Choose DSPy if you’re using DSPy’s declarative optimization approach and need to add external tool access via MCP.
Security Considerations
MCP tool integration through frameworks inherits all the security considerations of MCP itself, plus framework-specific concerns:
- Tool trust boundaries: When a framework loads tools from an MCP server, it trusts the server’s tool descriptions. A malicious server could craft descriptions that manipulate LLM behavior (tool poisoning). Validate tool descriptions before exposing them to LLMs.
- Multi-server credential isolation: When connecting to multiple MCP servers, ensure credentials for one server can’t leak to another. Most frameworks handle this correctly, but verify that HTTP headers configured for one server aren’t sent to others.
- Transport security: Always use TLS for remote MCP connections. Stdio transport inherits the security of the local process — ensure server binaries come from trusted sources.
- Interceptor security: LangChain’s interceptors and similar middleware patterns can access sensitive context (API keys, user data, agent state). Audit interceptor code carefully.
- Bidirectional exposure: When exposing your agent or workflow as an MCP server, you’re creating an API surface. Apply the same security practices you would for any public API — authentication, rate limiting, input validation.
For a deeper dive, see our MCP Security Best Practices and MCP Authentication and OAuth 2.1 guides.
The Bigger Picture
MCP’s universal adoption across AI frameworks represents a fundamental shift in how AI tool ecosystems work. Instead of each framework maintaining its own tool integrations — LangChain tools, CrewAI tools, LlamaIndex tools — the industry has converged on a shared protocol layer.
This convergence creates real value: MCP server developers build once and reach every framework. Framework developers focus on agent orchestration rather than tool integration. And teams can mix frameworks in production — a LangGraph agent consuming tools from a Spring AI MCP server, or a CrewAI crew using tools exposed by a LlamaIndex RAG pipeline — without framework lock-in.
The remaining friction is transport convergence (Streamable HTTP is winning) and capability parity (not all frameworks support resources and prompts yet). But the direction is clear: MCP is becoming the USB-C of AI tool integration — a universal connector that makes the framework choice orthogonal to the tool choice.
Related ChatForest Guides
- MCP and Anthropic Claude Integration — how Claude’s products integrate MCP
- MCP and OpenAI Integration — how ChatGPT, Agents SDK, and Codex use MCP
- MCP Security Best Practices — securing MCP deployments
- MCP Authentication and OAuth 2.1 — the auth layer for MCP servers
- MCP Server Packaging and Distribution — npm, PyPI, Docker, DXT, and the Registry
- MCP Ecosystem 2026: State of the Standard — the full landscape
- Best Database MCP Servers — MCP servers for database access
- Best Cloud MCP Servers — MCP servers for cloud platforms
- AI Coding Assistants Compared — how coding tools use MCP
Last updated: March 29, 2026