Suppose an agent needs to read a calendar, send a message, query a database, and create a ticket. Without a shared interface, each connection needs its own wrapper and maintenance. The Model Context Protocol (MCP) gives AI applications a standard way to connect to external capabilities through reusable servers instead of rebuilding each integration for every agent. section 1.1.3 section 1.2
MCP is an open standard based on JSON-RPC 2.0, a format for requests and responses. Its three-part mental model is a client, an MCP server, and the service or resource behind that server. An agent can be the client; the server exposes a consistent interface without exposing its implementation. section 1.2 section 3.6 section 3.4.1
A server can expose three kinds of capability:
- Tools: actions the client can invoke, such as creating an issue or querying a database. section 3.6 section 3.1.5
- Resources: data or objects the client can access. section 3.6
- Prompts: reusable templates. section 3.6
To use a server, run it and register it with the agent. The agent discovers available tools and their descriptions with `list_tools`, chooses a suitable tool for its task, executes it, and uses the result to decide what to do next. Tool names, descriptions, parameter schemas, and return types form the contract; the server keeps the underlying code private. section 1.2 section 3.4.1
Move a tool behind a server
A small Python server can use `FastMCP` and `@mcp.tool()` to expose typed functions such as `record_event(entry: str) -> dict` and `load_journal() -> dict`. The agent registers the server rather than importing those functions. A Python agent can also launch a local MCP server as a subprocess over STDIO—even when that server is implemented in Node.js. section 3.4.1 section 3.3.1
Listing 3.9 06_mcp_time_travel_tracker.py
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("Time Travel Tracker")
_journal = [] #1
@mcp.tool() #2
def record_event(entry: str) -> dict:
"""Add a new travel event to the journal."""
_journal.append(entry)
print(f"Event recorded: {entry}")
return {"status": "recorded", "entry": entry}
@mcp.tool() #2
def load_journal() -> dict:
"""Load the current travel journal entries."""
print("Loading journal entries...")
return {"status": "loaded", "journal": "\n".join(_journal)}
if __name__ == "__main__":
mcp.run(transport="sse") #3
Inspect the complete FastMCP server: its decorated functions show what becomes discoverable, while its journal storage remains an implementation detail. section 3.4.1
Servers can run locally or remotely. STDIO supports subprocess connections; HTTP-based connections support services outside the agent process. Choose MCP when a capability belongs to another service or team, or should be shared across agents. For logic used only inside one agent’s Python process, a direct function call avoids an extra connection, latency, and server failure mode. Inspect a server’s tool schemas and outputs before wiring it into an agent. section 3.3 section 3.6













