A small but complete LangGraph ReAct agent whose tools are served over the Model Context Protocol (MCP). The agent is decoupled from its tools by the MCP boundary — the same pattern production agents use to integrate external tools and data sources.
┌─────────────────────────┐
HumanMessage ─▶ model ─┤ tools_condition │
▲ │ • tool calls? ─▶ tools ──┼─▶ (executes) ─┐
│ │ • else ─▶ END │ │
└────────────────┴──────────────────────────┘ ◀─────────────┘
▲
tools loaded over MCP (stdio)
│
┌──────────┴───────────┐
│ mcp_server.py │ add · multiply · search_notes
│ (FastMCP, stdio) │
└───────────────────────┘
- LangGraph: an explicit
StateGraphReAct loop (model → tools_condition → tools → model) instead of a black-box agent — every step is inspectable. Seegraph.py. - MCP: a
FastMCPserver exposing tools (mcp_server.py) and a client that adapts them into LangChain tools vialangchain-mcp-adapters(mcp_client.py). - Testing/CI: hermetic
pytestsuite that runs the full tool-calling loop with a scripted fake model — no API key, no network — wired to GitHub Actions (ci.yml). - Containerized: a
Dockerfilefor reproducible runs.
pip install -e ".[dev]"
pytest -qcp .env.example .env # set MODEL + provider key
pip install -e ".[google]" # or .[openai]
python main.pymain.py launches the MCP server, loads its tools over MCP, and runs the
LangGraph agent on: "Search your notes for what MCP is, then compute 21 * 2."
src/langgraph_mcp_agent/
tools.py # pure tool logic (shared by server + agent + tests)
mcp_server.py # FastMCP server (stdio) exposing the tools over MCP
mcp_client.py # load MCP tools as LangChain tools (langchain-mcp-adapters)
graph.py # LangGraph StateGraph ReAct agent
main.py # runnable demo (agent consumes tools via MCP)
tests/ # hermetic unit tests (no key)