When to reach for it
- Tools and data sources need to be usable across different frameworks.
- Local or external systems must be connected.
- Context access should be standardized.
/pattern/mcp/
External resources and tools are made available via the Model Context Protocol as a standardized integration layer.
In practiceA coding assistant connects to a local filesystem server and a remote GitHub server through a single MCP transport layer, without custom integration code for each.
When to reach for it
When it backfires
The tradeoff
Broad interoperability is gained at the cost of additional operational and permission management overhead.
Picture a universal power socket. Before MCP, every tool an agent wanted to use had its own plug — a different SDK, schema, and auth model. Wiring N agents to M tools meant N×M custom integrations.
MCP collapses that to N + M. A tool author writes one server; an agent runtime ships one client. Any tool that speaks the protocol plugs into any agent that speaks it — no custom wiring. It is, in Anthropic's phrase, "a USB-C port for AI applications."
A standard protocol bridges host and tool server.
MCP follows a client–server architecture borrowed from the Language Server Protocol. A host runs one or more clients; each client holds a dedicated connection to one server. Messages are JSON-RPC 2.0, carried over stdio for local servers or streamable HTTP for remote ones.
initialize → capability negotiation → discovery → operation
The AI application the user actually touches — Claude Desktop, an IDE plugin, or your agent runtime. It owns the LLM, the conversation, and the decision to use a tool. It spins up clients as needed.
A connector living inside the host that maintains a 1:1 stateful session with exactly one server. It handles the handshake, relays requests, and keeps capabilities in sync.
A program — local or remote — that exposes capabilities over MCP. The tool author writes it once; any compliant client can then discover and invoke what it offers.
Executable functions the model can choose to call to take an action or fetch live data. Discovered via tools/list, invoked via tools/call.
Read-only context data identified by URI — files, rows, documents — that the host can pull into the model's context window without an action.
Reusable, parameterized templates the server offers — surfaced to the user as slash-commands or menu actions that pre-package a known workflow.
The connection runs both ways. A server can also call back into the host through sampling (ask the host's LLM to generate a completion), elicitation (ask the user for more input), and roots (learn which filesystem boundaries it's allowed to touch). That two-way capability is what separates MCP from a plain tool-calling API.
# server.py — expose a database as an MCP server
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("support-tickets")
@mcp.tool()
def query_tickets(sql: str) -> list[dict]:
"""Run a read-only SQL query against the tickets database."""
return db.execute(sql).fetchall()
@mcp.resource("postgres://schema/tickets")
def schema() -> str:
"""The tickets table schema, so the model can read column names."""
return open("schema.sql").read()
if __name__ == "__main__":
# stdio for local; switch to transport="streamable-http" for remote
mcp.run(transport="stdio")Two open protocols cross the boundary out of any single framework. MCP standardizes how an agent talks to a tool; A2A standardizes how an agent talks to another agent. You will often run both.
Teams expose internal databases via MCP without auth checks, treating the protocol layer as a security boundary.
Fix · Enforce auth at the MCP server layer, not just the transport. Audit every exposed resource for least-privilege access.
The MCP server changes its schema weekly. Client agents break because they pin to an outdated tool definition.
Fix · Version MCP schemas and support a compatibility window. Reject clients that don't declare a version header.
One client mounts a dozen servers; the model now sees 80 tools and picks the wrong one — or stalls choosing.
Fix · Mount only the servers a task needs. Scope tools per route and keep names and descriptions unambiguous.
Next pattern
Search patterns, frameworks, and pages.