Introduction: The Integration Dilemma
Picture a customer service AI system that has grown from a single chatbot into a small ecosystem of specialized agents:
- Product Query Agent: Answers questions about specs, pricing, inventory
- Order Processing Agent: Handles order status, returns, exchanges
- Policy Consultation Agent: Answers refund/membership policy questions
- Emotional Support Agent: Handles complaints and escalations
Every one of these agents needs access to the same underlying resource: a GraphRAG-based knowledge base containing product data, policies, and historical records.
Pain Points of Traditional Approaches
Without a shared protocol, each agent typically gets its own custom integration code to talk to GraphRAG. This creates three recurring problems:
1. Code Redundancy and Maintenance Nightmare
When the GraphRAG system upgrades (e.g., a new retrieval algorithm), every agent's integration code needs modification. Maintenance work grows with the number of agents.
2. High Cost of Model Switching
Switching an agent from GPT-4 to Claude often means rewriting integration code, since tool-calling conventions differ between model providers.
3. Complexity of Distributed Deployment
Different agents may run on different servers or in different languages. Without a shared protocol, each combination needs its own glue code.
MCP: A Standardized Protocol, Not Just a Framework
This is where Model Context Protocol (MCP) comes in. MCP is an open protocol released by Anthropic in November 2024 that standardizes how AI applications connect to external tools, data sources, and systems — often described as "USB-C for AI applications": one standard interface instead of custom integrations for every pair of systems.
The Real Architecture: Host, Client, Server
MCP defines three architectural roles, connected via JSON-RPC 2.0 messages:
- Host: The AI application the user interacts with (an agent system, an IDE, a chat client). The Host manages one or more Clients.
- Client: A connector living inside the Host, maintaining a 1:1 stateful connection to a single Server.
- Server: A program exposing capabilities — Tools, Resources, Prompts, and optionally Sampling requests — over the protocol.
Note: the LLM itself is not a protocol-level role. It's a component the Host uses internally to decide when and how to call the tools MCP exposes.
The Four Core Primitives
| Primitive | Description |
|---|---|
| Tools | Executable functions the model can invoke (e.g., graphrag_query) |
| Resources | Structured, addressable data (files, DB records, documents) the Host can read |
| Prompts | Reusable, parameterized prompt templates defined by the Server |
| Sampling | Allows a Server to request the Host perform an LLM completion on its behalf |
Most introductory tutorials only cover Tools. The other three primitives are what make MCP more than just a function-calling wrapper.
Example: Wrapping GraphRAG as an MCP Tool
1. Server-Side
MCP has two common Python entry points: mcp.server.fastmcp (bundled into the official SDK as FastMCP 1.0) and the standalone fastmcp package (FastMCP 2.x, actively maintained by Prefect, now the de facto standard powering the majority of MCP servers in the wild). The example below uses the standalone 2.x package:
from fastmcp import FastMCP
mcp = FastMCP("graphrag-server")
@mcp.tool()
async def graphrag_query(query: str, top_k: int = 5) -> list[dict]:
"""
Query relevant information using GraphRAG.
Args:
query: User's natural language query
top_k: Number of results to return
Returns:
List of retrieved results with title, content, and relevance score
"""
results = await graphrag_engine.search(query, top_k=top_k)
return results
if __name__ == "__main__":
mcp.run() # Defaults to stdio transport
Function docstrings and type hints are automatically converted into the tool's schema — no manual JSON schema writing required.
2. Client-Side
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
async def query_with_graphrag(user_question: str):
server_params = StdioServerParameters(
command="python",
args=["graphrag_server.py"]
)
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
tools = await session.list_tools()
# Note: this example hardcodes the tool call for brevity.
# In production, `tools` would be passed into the Host's LLM call,
# and the decision to invoke `graphrag_query` would be made by
# the model's own reasoning based on the user's question.
result = await session.call_tool(
"graphrag_query",
arguments={"query": user_question, "top_k": 5}
)
return result
This example uses stdio transport, suitable for local process communication. For distributed deployment, MCP also supports Streamable HTTP transport, allowing the Server to run as an independent network service.
What MCP Actually Changes
1. Develop Once, Use Everywhere
GraphRAG is wrapped as a single MCP Server. Any MCP-compliant Host can connect without custom integration code.
2. Model Independence
Tool discovery and invocation follow the same JSON-RPC schema regardless of which LLM the Host uses — switching providers doesn't require touching the Server.
3. Distributed Deployment
Via Streamable HTTP transport, the GraphRAG Server can run on a dedicated machine, serving multiple Hosts over the network.
4. Language Independence
Since the protocol is just JSON-RPC 2.0 over a transport layer, a Server written in Python can be called by a Host written in TypeScript, Go, or any language with an MCP SDK.
Conclusion
MCP isn't just a coding convenience — it's a protocol-level answer to a structural problem: as AI systems accumulate more tools and more models, ad-hoc integrations stop scaling. By standardizing the Host-Client-Server relationship and defining four clear primitive types, MCP lets teams build genuinely modular AI systems, where tools, data sources, and models can evolve independently of one another.
Top comments (0)