AI Agent Framework + MCP Integration Nanny Level Tutorial: Build an agent from scratch that can call external tools
🛒 For developers, a one-stop introductory tutorial from environment preparation, MCP Server writing to LangGraph joint debugging.
Tutorial Objectives
This tutorial will take you to build an AI Agent from scratch that can call external tools: first use Python to write a tool service (MCP Server) that complies with MCP standards, and then use LangGraph to connect it to a conversational agent. After learning, you will not only be able to run through the examples, but also encapsulate the API of your own system into a tool to connect to the Agent.
Preparation Checklist
- [ ] An internet-enabled development machine (macOS/Linux/Windows is acceptable), Python 3.10 and above.
- [ ] Install uv (recommended, used to manage Python environment and dependencies):
curl -LsSf https://astral.sh/uv/install.sh | sh, thensource ~/.zshrc. - [ ] An available LLM API Key (OpenAI / Anthropic / domestic large models are acceptable, this tutorial uses the OpenAI compatible interface as an example).
- [ ] Prepare a "real tool" example: This tutorial uses "read local file" as the tool, you can also change it to weather API or database query.
- [ ] (Optional) Install the MCP Inspector visual debugging tool.
Version tips: MCP SDK and LangGraph iterate quickly. The version numbers in the following commands are subject to the official real-time page; when the installation fails, give priority to the prompts in the error report.
Step one: Create project and virtual environment
mkdir mcp-agent-demo && cd mcp-agent-demo
uv init --python 3.11
uv add "mcp[cli]" langgraph langchain-openai python-dotenv
Note: uv init will generate pyproject.toml and main.py; mcp[cli] provides MCP runtime and debugging commands.
Step 2: Write the first MCP Server
Create server.py to implement a tool for "reading local file contents":
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("file-reader")
@mcp.tool()
def read_file(path: str) -> str:
"""Read the contents of the text file at the specified path. Used to demonstrate the Agent calling external tools."""
try:
with open(path, "r", encoding="utf-8") as f:
return f.read(2000)
except Exception as e:
return f"Read failed: {e}"
if __name__ == "__main__":
mcp.run()
Key point: @mcp.tool() decorator registers a normal function as a tool, and the function parameters and documentation string will automatically generate a tool schema for the model to see - The description must be written clearly so that the model knows when to call it.
Step 3: Verify Server with MCP Inspector
uv run mcp dev server.py
Open http://localhost:6274 in the browser and in the Inspector:
- Select the
read_filetool. - Enter the parameter
{"path": "README.md"}(create a README.md in the project first). - Click Call, and the file content should be returned on the right.
This step can confirm that "the tool itself is available" and isolate problems at the model level first.
Step 4: Build Agent with LangGraph and connect to MCP tool
Create agent.py:
import asyncio
from langchain_openai import ChatOpenAI
from langgraph.prebuilt import create_react_agent
from langchain_mcp_adapters.client import MultiServerMCPClient
async def main():
async with MultiServerMCPClient(
{"file-reader": {"command": "uv", "args": ["run", "server.py"], "transport": "stdio"}}
) as client:
tools = client.get_tools()
model = ChatOpenAI(model="gpt-4o-mini", temperature=0)
agent = create_react_agent(model, tools)
result = await agent.ainvoke({"messages": [("user", "Please read the README.md in the project and summarize the first three lines")]})
print(result["messages"][-1].content)
if __name__ == "__main__":
asyncio.run(main())
Run:
export OPENAI_API_KEY="Your Key"
uv run python agent.py
Expected output: The model first calls the read_file tool to read the file, and then gives a summary based on the returned content - this is a complete "Agent → MCP → real tool" link.
Step 5: Connect to a real business tool (example: query SQLite)
Extend server.py with a "query database" tool:
import sqlite3
@mcp.tool()
def query_sqlite(db_path: str, sql: str) -> str:
"""Execute a read-only SELECT query against a SQLite database and return the results."""
if not sql.strip().lower().startswith("select"):
return "Only SELECT queries allowed"
conn = sqlite3.connect(db_path)
try:
rows = conn.execute(sql).fetchmany(10)
return "\n".join(str(r) for r in rows)
except Exception as e:
return f"Query failed: {e}"
finally:
conn.close()
When implemented in an enterprise, replacing this read-only query with "internal API encapsulation with permission verification" is the minimum form of a production-level tool.
Step 6: Configuration, logs and common errors
- Log: Add
verbose=TruetoChatOpenAIand agent inagent.pyto observe the tool calls at each step. - Timeout: The timeout for MCP tool calls can be configured on the client to avoid Agent getting stuck.
- Common error reporting and handling:
| Error phenomenon | Possible reasons | Treatment |
|---|---|---|
connection refused |
The server has not been started or the stdio path is incorrect | Use uv run mcp dev server.py to verify first |
| The model does not call the tool | The tool description is unclear or the model is too weak | Rewrite the tool description and replace it with a stronger model |
Tool not found |
MCP client failed to register tool | Check get_tools() return list |
| Chinese garbled characters | Encoding issues | Unified file reading and writing encoding="utf-8" |
Verification method
- Tool layer verification: MCP Inspector tests each tool individually.
- Link verification: Let the Agent complete 3 different tasks to confirm that the tool is selected correctly every time.
- Regression verification: Consolidate the use case into a script and rerun it after modification.
Frequently Asked Questions (FAQ)
-
Does MCP have to use Python?
no. The official SDK supports Python and TypeScript, and the Node environment uses
@modelcontextprotocol/sdk. -
Can I use this tutorial if I don’t have a local GPU?
able. The LLM in this tutorial uses API, only large model inference requires computing power, and only lightweight tool services are run locally.
-
What should I do if the Agent never calls the tool?
First check whether the tool description contains the trigger condition of "when to call", secondly confirm that the model has function calling capabilities, and finally use a simpler prompt to test.
-
How to deploy MCP Server in production environment?
Server can be deployed as an independent process/container, using streamable HTTP transport instead of stdio, and accessing unified authentication.
-
Will multiple tools interfere with each other?
Each tool has an independent namespace and schema. As long as the description is clear and permissions are minimized, there will usually be no interference; it is recommended to limit the flow in high-concurrency scenarios.
Advancement and Expansion
- Multi-Agent orchestration: Use LangGraph's state machine to split "planning-execution-review" into multiple roles.
- MCP Registry: Build an internal tool registration center to unify versions and permissions.
- Evaluation set: Precipitate business use cases into automated regression to prevent behavioral drift.
- Privatization: Replace LLM with a local deployment model (such as Ollama) to achieve full-link intranet operation.
User Reviews