Model Context Protocol (MCP) With LangGraph Agent

In AI applications, LLMs need to interact with various tools and data sources to fetch information and perform tasks. However, connecting LLMs to these external services has always been a challenge. Without a standardized approach, integration becomes complex and time-consuming, often requiring custom implementations that can lead to compatibility and scalability issues.
The Model Context Protocol (MCP) solves this by providing a universal interface between LLMs and the tools they need. It establishes a common pattern for data access and tool execution, allowing LLMs to interact with multiple services in a structured and efficient way without requiring custom code for each new tool.
In this post, we’ll understand what MCP is, how it works, and why it’s important. We will also see how to integrate MCP with a LangGraph Agent.
Now let’s start with the core concept of Model Context Protocol (MCP).
What is MCP?
MCP is an open standard for connecting AI applications to external tools and data. Think of it as a universal adapter or “USB-C port” for AI applications. Instead of writing one-off integrations for every API or database, developers can expose resources as MCP servers, and MCP clients can connect to any of these servers through a standardized interface. In simpler terms, an MCP server is a lightweight program offering a specific capability like a plugin.

MCP follows a client-server architecture, where MCP servers expose tools (functions) along with their input/output schemas, and MCP clients discover and invoke these tools when needed. Communication happens through standardized transports such as Standard I/O (stdio) for local processes and Server-Sent Events (SSE) for web-based communication.
Why MCP Matters
MCP makes it easier for LLMs to connect with tools by providing a single, standardized interface. Instead of writing custom integrations for every tool, developers can build an MCP-compatible tool once, and it will work with any AI application that supports MCP (like Claude, Cursor, or LangGraph agents).
This is crucial for agentic AI, where AI agents perform multi-step reasoning and call on tools autonomously. For example, when an AI agent needs a specific tool (e.g., “search the web” or “query a database”), it calls the appropriate MCP server. The server processes the request and returns structured results, which the agent can then use in its reasoning process. This approach enables AI agents to dynamically integrate with tools, making them more modular and extensible.
Now that we understand the MCP conceptually, let’s see it in action through a practical project. We will build an agent that connects to the YouTube Transcript MCP Server and Web Search MCP Server using MultiServerMCPClient
(from the langchain-mcp-adapters
library) and then interacts with them through a unified interface.
For the complete code, check out this GitHub repository.
Project Structure
Before setting up the servers and the agent, let’s understand the project structure. The project consists of multiple MCP servers and a client-side AI agent, as you can see below:
langgraph_mcp/
│-- agent.py # The AI agent that connects to MCP servers
│-- servers/ # Directory for MCP servers
│ ├── tavily.py # Web search MCP server (uses Tavily API)
│ ├── yt_transcript.py # YouTube Transcript MCP server
│-- .env # Environment file to store API keys
│-- requirements.txt # Dependencies
Installation
1. Clone the Repository
To get started, first, clone the project repository and go to the langgraph-mcp folder:
git clone https://github.com/your-repo/langgraph-mcp.git
cd langgraph-mcp
2. Install Dependencies
Then, install all the required dependencies by running the following code:
pip install -r requirements.txt
3. Set Up API Keys
After that, add your Tavily and Open AI keys to a .env
file:
TAVILY_API_KEY=<your-tavily-api-key>
OPENAI_API_KEY=<your-openai-api-key>
Setting Up MCP Servers
Each MCP server is a standalone Python script that runs as a separate process. The FastMCP class (from the mcp.server.fastmcp
module) simplifies the process of defining MCP tools using Python functions.
1. Web Search MCP Server (Tavily)
This server allows the AI agent to perform real-time web searches using the Tavily API. It helps answer queries that require up-to-date information from the internet.
import os
import httpx
from dotenv import load_dotenv
from mcp.server.fastmcp import FastMCP
# Load environment variables
load_dotenv()
# Initialize FastMCP
mcp = FastMCP("tavily_search")
# Tavily API details
TAVILY_API_KEY = os.getenv("TAVILY_API_KEY")
TAVILY_SEARCH_URL = "https://api.tavily.com/search"
async def search_tavily(query: str) -> dict:
"""Performs a Tavily web search and returns 5 results."""
if not TAVILY_API_KEY:
return {"error": "Tavily API key is missing. Set it in your .env file."}
payload = {
"query": query,
"topic": "general",
"search_depth": "basic",
"chunks_per_source": 3,
"max_results": 5, # Fixed
"time_range": None,
"days": 3,
"include_answer": True,
"include_raw_content": False,
"include_images": False,
"include_image_descriptions": False,
"include_domains": [],
"exclude_domains": []
}
headers = {
"Authorization": f"Bearer {TAVILY_API_KEY}",
"Content-Type": "application/json"
}
async with httpx.AsyncClient() as client:
response = await client.post(TAVILY_SEARCH_URL, json=payload, headers=headers, timeout=30.0)
response.raise_for_status()
return response.json()
@mcp.tool()
async def get_tavily_results(query: str):
"""Fetches Tavily search results for a given query."""
results = await search_tavily(query)
if isinstance(results, dict):
return {"results": results.get("results", [])} # Ensure always returning a dictionary
else:
return {"error": "Unexpected Tavily response format"}
if __name__ == "__main__":
mcp.run(transport="stdio")
2. YouTube Transcript MCP Server
This server fetches YouTube video transcripts using the youtube-transcript-api
Python package. The agent can summarize or analyze video content based on the transcripts.
import re
from mcp.server.fastmcp import FastMCP
from youtube_transcript_api import YouTubeTranscriptApi
mcp = FastMCP("youtube_transcript")
@mcp.tool()
def get_youtube_transcript(url: str) -> dict:
"""Fetches transcript from a given YouTube URL."""
video_id_match = re.search(r"(?:v=|\/)([0-9A-Za-z_-]{11}).*", url)
if not video_id_match:
return {"error": "Invalid YouTube URL"}
video_id = video_id_match.group(1)
try:
transcript = YouTubeTranscriptApi.get_transcript(video_id)
transcript_text = "\n".join([entry["text"] for entry in transcript])
return {"transcript": transcript_text}
except Exception as e:
return {"error": str(e)}
if __name__ == "__main__":
mcp.run(transport="stdio")
Connecting the Servers to the Agent via the MCP Client
To connect the MCP servers to our AI agent, we will use the MultiServerMCPClient class from langchain-mcp-adapters
to manage multiple server connections. Then, we will use LangGraph to create a ReAct agent that can utilize these tools efficiently, as you see below:
import asyncio
from langchain_mcp_adapters.client import MultiServerMCPClient
from langgraph.prebuilt import create_react_agent
from langchain_core.messages import SystemMessage, HumanMessage
from langchain_openai import ChatOpenAI
from dotenv import load_dotenv
load_dotenv()
# Example query
# "What is weather in newyork"
# "What is FastMCP?"
# "summarize this youtube video in 50 words, here is a video link: https://www.youtube.com/watch?v=2f3K43FHRKo"
query = input("Query:")
# Define llm
model = ChatOpenAI(model="gpt-4o")
# Define MCP servers
async def run_agent():
async with MultiServerMCPClient(
{
"tavily": {
"command": "python",
"args": ["servers/tavily.py"],
"transport": "stdio",
},
"youtube_transcript": {
"command": "python",
"args": ["servers/yt_transcript.py"],
"transport": "stdio",
},
"math": {
"command": "python",
"args": ["servers/math_server.py"],
"transport": "stdio",
},
# "weather": {
# "url": "http://localhost:8000/sse", # start your weather server on port 8000
# "transport": "sse",
# }
}
) as client:
# Load available tools
tools = client.get_tools()
agent = create_react_agent(model, tools)
# Add system message
system_message = SystemMessage(content=(
"You have access to multiple tools that can help answer queries. "
"Use them dynamically and efficiently based on the user's request. "
))
# Process the query
agent_response = await agent.ainvoke({"messages": [system_message, HumanMessage(content=query)]})
# # Print each message for debugging
# for m in agent_response["messages"]:
# m.pretty_print()
return agent_response["messages"][-1].content
# Run the agent
if __name__ == "__main__":
response = asyncio.run(run_agent())
print("\nFinal Response:", response)
Once everything is set up, simply run the agent.py
script to launch the AI agent and ask your query, as you can see in the demo:
python agent.py

That’s it! We have successfully built an MCP-powered AI agent that integrates multiple external tools.
Conclusion
The Model Context Protocol (MCP) is transforming how AI applications interact with external tools and data. By providing a standard interface, MCP eliminates the need for custom integrations and enables AI agents to be extensible and context-aware.
In this blog, we explored what MCP is, how it works, and why it matters. We also built a practical AI agent that connects to YouTube Transcript and Web Search MCP servers, allowing it to fetch video transcripts and perform web searches. Using MultiServerMCPClient and LangGraph, we showed how an AI agent can use multiple tools through a single interface.
MCP makes AI systems more flexible, scalable, and capable of handling complex tasks. Whether you’re building a personal AI assistant or a multi-agent system, MCP provides the foundation to integrate new tools easily.