The Model Context Protocol (MCP) has emerged as a defining connectivity standard for AI application development in 2025, adopted by Anthropic, OpenAI, Google DeepMind, and Microsoft within months of its release. For developers building AI-powered applications, MCP solves a fundamental connectivity problem: how to give large language models reliable, standardized access to external tools and data sources without writing one-off integrations for every combination of model and service. Understanding MCP, its architecture, and how to build with it is now a baseline requirement for anyone working in the agentic AI space.
Table of Contents
- What Is MCP (Model Context Protocol)?
- MCP Architecture: How It Actually Works
- Why MCP Matters for AI Development
- Building Your First MCP Server in Python
- MCP in Practice: Real-World Use Cases
- MCP Implementation Checklist
- Common Pitfalls and Best Practices
- What's Next for MCP
What Is MCP (Model Context Protocol)?
Model Context Protocol (MCP) is an open, vendor-neutral standard released by Anthropic that defines how AI models connect to external tools, databases, and APIs. It replaces custom point-to-point integrations with a single client-server protocol using JSON-RPC 2.0, enabling any MCP-compatible AI host to discover and invoke tools, read data resources, and use prompt templates exposed by lightweight MCP servers.
The Problem MCP Solves
Before MCP, connecting AI models to external tools and data sources meant dealing with the M×N integration problem. Every AI model that needed to interact with a database, a file system, a CRM, or any other external service required its own custom connector. Three models times ten tools? That forced teams to build and maintain thirty bespoke integrations. Developers coupled each integration tightly to a specific model's API and a specific tool's interface. When either side changed, the integration broke.
Anthropic's concept of "context starvation" compounded this fragility. Large language models are increasingly capable, but they remain isolated from the real-world data and systems they need to be genuinely useful. A model that cannot read a project's codebase, query a production database, or check a calendar is limited to operating on whatever text the user pastes into a prompt window. The gap between what models can reason about and what they can actually access has been the primary bottleneck for building practical AI applications.
The gap between what models can reason about and what they can actually access has been the primary bottleneck for building practical AI applications.
The USB-C Analogy Explained
The analogy Anthropic and the broader community have used is USB-C. Before USB-C, every device manufacturer shipped proprietary chargers and connectors. Users accumulated drawers full of incompatible cables. USB-C replaced that chaos with a single universal standard. MCP does the same for AI-tool connectivity. Instead of building custom API wrappers for every model-tool pair, developers expose their tools and data through MCP servers, and any MCP-compatible AI host can connect to them. One standardized protocol replaces hundreds of point-to-point integrations.
Origins and Adoption Timeline
Anthropic released MCP as an open-source protocol in November 2024. Although the initial release targeted Anthropic's own products, particularly Claude Desktop, Anthropic designed the specification to be vendor-neutral from the start. Adoption accelerated rapidly. By March 2025, OpenAI announced MCP support in its Agents SDK and ChatGPT desktop application. Google DeepMind followed by integrating MCP into the Gemini ecosystem. Microsoft added MCP support to Copilot Studio and its broader developer tooling, while major tool vendors and the open-source community began publishing MCP servers for everything from GitHub to Slack to PostgreSQL. As of mid-2025, MCP functions as the de facto connectivity standard for agentic AI applications.
Note: Specific vendor adoption timelines should be verified against official announcements; product versions and rollout dates may vary.
MCP Architecture: How It Actually Works
Core Components
MCP follows a client-server architecture with three distinct roles.
The host is the AI-facing application the user interacts with. Claude Desktop, an IDE like Cursor, or a custom-built AI application all serve as hosts. The host manages connections to one or more MCP servers and mediates between the user, the AI model, and the available tools.
Embedded within the host, the client handles protocol communication. Each client maintains a stateful, one-to-one connection with a single MCP server. A host can spawn multiple clients to connect to multiple servers simultaneously, but each client-server pair operates as an isolated session.
The server is a lightweight program that exposes specific capabilities via the MCP protocol. A server might provide access to a file system, wrap a REST API, or expose a database. The protocol constrains servers to be small and focused, each handling a well-defined set of functionality.
The Three Primitives
MCP defines three primitive types that servers can expose.
Tools are functions that the AI model can invoke: query a database, send an email, create a GitHub issue, call a weather API. Tools are model-controlled, meaning the AI model decides when and how to call them based on the user's request and the tool's description. Resources, by contrast, are data the model can read. File contents, database records, API responses, and configuration data all qualify. Resources are identified by URIs and are typically application-controlled, meaning the host or user determines when to include them in context.
Prompts are reusable prompt templates exposed by the server. They allow server developers to define structured interaction patterns, such as a multi-step workflow for code review or a templated query for a specific data source. Prompts are user-controlled, surfaced as options the user can select.
Communication Flow
MCP uses JSON-RPC 2.0 as its message format. When a client connects to a server, the two perform a capability negotiation during initialization, exchanging information about which primitives the server supports and which protocol features the client understands. After initialization, communication follows standard request/response patterns, with support for notifications (one-way messages that do not expect a reply).
For transport, MCP supports two primary modes. Local servers typically communicate via standard input/output (stdio), where the host spawns the server as a child process and communicates through stdin/stdout pipes. Remote servers use HTTP-based transports. The initial specification used Server-Sent Events (SSE) for server-to-client streaming over HTTP. The evolving specification is moving toward streamable HTTP as the preferred remote transport.
Why MCP Matters for AI Development
From Chatbots to Agentic AI
MCP is the infrastructure layer enabling the shift from passive chatbots to agentic AI systems. With tool access through MCP, AI models can act, not just respond. An AI agent connected to MCP servers for Google Calendar, a CRM like Salesforce, and an email service can autonomously read upcoming meetings, pull relevant customer data from the CRM, and draft a personalized follow-up email. Unlike RAG, which gives models read-only access to external data, MCP enables models to both read data and perform write operations across external systems.
The Ecosystem Effect
MCP's design creates composability that shows up in practice. Developers can mix and match servers from the growing community registry, combining a GitHub server, a Postgres server, and a Slack server into a single AI application without writing integration code. The security model recommends explicit user consent for tool invocations; enforcement is the responsibility of the host application, not the protocol itself, so developers should verify their host's consent implementation. Because MCP is vendor-neutral, organizations can swap AI models (from Claude to GPT to Gemini) without rewriting any of their tool integrations. The integration investment is decoupled from the model choice.
Because MCP is vendor-neutral, organizations can swap AI models (from Claude to GPT to Gemini) without rewriting any of their tool integrations. The integration investment is decoupled from the model choice.
Building Your First MCP Server in Python
Prerequisites and Setup
Building an MCP server requires Python 3.10 or later and the uv package manager for dependency management (alternatively, pip with a standard virtual environment will also work). The MCP Python SDK, published as mcp[cli], provides the high-level FastMCP API that handles protocol details and lets developers focus on defining tools, resources, and prompts.
To initialize a project and install the SDK:
# Create a new project directory
mkdir weather-mcp-server
cd weather-mcp-server
# Initialize a new Python project with uv, pinning the Python version
uv init --python 3.11
# Create the server file (uv init creates a default hello.py, which you can ignore or delete)
touch weather_server.py # On Windows PowerShell: New-Item weather_server.py
# Add the MCP SDK with CLI extras and httpx for HTTP requests, with version constraints
uv add "mcp[cli]>=1.0,<2.0" "httpx>=0.27,<1.0"
This creates a virtual environment, sets up the project structure, and installs the MCP Python SDK along with its command-line tools for testing and debugging.
Tip: Pin your SDK version (e.g., uv add "mcp[cli]==1.x.y") to ensure reproducible builds as the SDK evolves. Run uv pip show mcp to check the installed version.
Creating a Simple Tool Server
The FastMCP class provides a decorator-based API for defining MCP servers. The @mcp.tool() decorator registers a Python function as an MCP tool. The function's type hints define the tool's input schema, and its docstring becomes the tool description that the AI model uses to decide when and how to invoke the tool.
Here is a complete, runnable MCP server that exposes a single weather lookup tool:
# weather_server.py
import logging
import httpx
from mcp.server.fastmcp import FastMCP
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
# Initialize the MCP server with a descriptive name
mcp = FastMCP("weather")
BASE_URL = "https://api.open-meteo.com/v1/forecast"
@mcp.tool()
async def get_weather(latitude: float, longitude: float) -> str:
"""Get current weather conditions for a given latitude and longitude.
Args:
latitude: The latitude of the location (-90 to 90).
longitude: The longitude of the location (-180 to 180).
Returns:
A string describing current temperature and wind speed.
"""
if not (-90.0 <= latitude <= 90.0):
return f"Invalid latitude {latitude}: must be between -90 and 90."
if not (-180.0 <= longitude <= 180.0):
return f"Invalid longitude {longitude}: must be between -180 and 180."
logger.info("get_weather called: lat=%s lon=%s", latitude, longitude)
params = {
"latitude": latitude,
"longitude": longitude,
"current": "temperature_2m,wind_speed_10m",
}
async with httpx.AsyncClient(timeout=10.0) as client:
try:
response = await client.get(BASE_URL, params=params)
response.raise_for_status()
except httpx.HTTPStatusError as e:
logger.warning("HTTP error from weather API: %s", e.response.status_code)
return (
f"Weather API error: {e.response.status_code} "
f"— {e.response.text[:200]}"
)
except httpx.RequestError as e:
logger.error("Network error: %s: %s", type(e).__name__, e)
return f"Network error contacting weather API: {type(e).__name__}: {e}"
data = response.json()
current = data.get("current")
if not current:
logger.error("Unexpected API response structure: %s", data)
return "Weather API error: unexpected response structure."
temp = current.get("temperature_2m", "N/A")
wind = current.get("wind_speed_10m", "N/A")
return f"Temperature: {temp}°C, Wind speed: {wind} km/h"
if __name__ == "__main__":
mcp.run(transport="stdio")
The FastMCP class handles JSON-RPC serialization, capability negotiation, and transport management. The developer only needs to define the function, annotate its parameters with types, and write a clear docstring. The docstring is particularly important because it is the primary mechanism the AI model uses to understand what the tool does and when to invoke it.
Testing with Claude Desktop
To make this server available in Claude Desktop, add it to the Claude Desktop configuration file. On macOS, this file is located at ~/Library/Application Support/Claude/claude_desktop_config.json. On Windows, it is at %APPDATA%\Claude\claude_desktop_config.json (verify this path exists after installing Claude Desktop; the location may vary by version).
{
"mcpServers": {
"weather": {
"command": "uv",
"args": [
"run",
"--directory",
"/absolute/path/to/weather-mcp-server",
"--",
"python",
"weather_server.py"
]
}
}
}
Important: Replace /absolute/path/to/weather-mcp-server with the actual absolute path to your project directory (run pwd in the project directory on macOS/Linux to get it). The --directory path must point to the folder containing your pyproject.toml. On Windows, use forward slashes or escaped backslashes in the JSON path. The -- separator ensures uv run correctly delegates to the Python interpreter within the project's virtual environment.
After restarting Claude Desktop, the weather tool should appear in the list of available tools. Check the tools panel or server connection status in Claude Desktop settings to confirm the server is connected. Typing a natural language prompt like "What's the weather at latitude 51.5, longitude -0.12?" will cause Claude to invoke the get_weather tool, pass the coordinates, and return the formatted result.
Adding Resources and Prompts
A single MCP server can expose all three primitives. Extending the weather server to include a resource and a prompt template demonstrates the full breadth of MCP capabilities. Add the following to weather_server.py, between the get_weather function and the if __name__ == "__main__": block:
# Add these to weather_server.py, below the existing get_weather tool
# and above the if __name__ == "__main__": block
@mcp.resource("config://weather/settings")
async def get_settings() -> str:
"""Return the current weather server configuration."""
return (
f"API Base URL: {BASE_URL}
"
f"Supported parameters: latitude, longitude
"
f"Data source: Open-Meteo API (free, no key required)"
)
@mcp.prompt()
def weather_report(city_name: str) -> str:
"""Generate a prompt template for a detailed weather report.
Args:
city_name: The name of the city for the report.
"""
return (
f"Look up the coordinates for {city_name}, then use the "
f"get_weather tool to fetch current conditions. Provide a "
f"brief, friendly weather report suitable for a daily standup."
)
The @mcp.resource() decorator exposes a URI-addressable piece of data that the host application can pull into the model's context. Resource URIs (like config://weather/settings) are arbitrary identifiers chosen by the server developer; the host uses them as opaque keys to request data. The @mcp.prompt() decorator defines a reusable template that users can select to initiate a structured workflow. Note that FastMCP normalizes a plain str return from a prompt function into a structured PromptMessage; for full SDK portability, consult the SDK documentation for the structured return format. Together with tools, these three primitives cover the full range of model-data-action interactions.
MCP in Practice: Real-World Use Cases
Developer Tooling
IDE integration has been one of MCP's fastest-growing adoption vectors. Cursor and VS Code (via GitHub Copilot) support MCP, allowing AI assistants to access project files, run terminal commands, and interact with version control directly through the protocol. Claude Code, Anthropic's autonomous coding agent, uses MCP servers for filesystem access, Git operations, and terminal execution, enabling it to navigate codebases, make edits, and run tests without manual copy-paste workflows.
Enterprise Workflows
Enterprise adoption centers on connecting AI to operational systems. Pre-built MCP servers exist for PostgreSQL and MongoDB, allowing AI models to query databases with access controls scoped to the server's connection role (for example, a read-only database user with row-level security). CRM and ERP integration through MCP eliminates the need for custom middleware, with servers mediating between the AI model and systems like Salesforce or internal knowledge bases. The server enforces security controls, restricting what data the model can access and what actions it can perform.
Community Ecosystem
The MCP community registry hosts pre-built servers for GitHub, Slack, Google Drive, Notion, and dozens of other services. When evaluating third-party servers, developers should review the exposed tools and their descriptions, check the authentication mechanisms, and verify that the server follows the principle of least privilege by only exposing the operations genuinely needed.
MCP Implementation Checklist
Before You Build
- Identify the specific data sources and tools the AI application needs to access.
- Determine the transport type: local stdio for same-machine servers, remote SSE or streamable HTTP for networked deployments. Security warning: stdio servers run with the same OS permissions as the host application. Review server source code before adding any third-party stdio server, and prefer sandboxed environments for untrusted servers.
- Audit security requirements. Define what operations the model should be allowed to perform and what should require explicit user confirmation.
- Search the community registry for existing servers before building from scratch.
During Development
- Use the official SDK for the target language. SDKs are available for Python, TypeScript, Java, Kotlin, and C# (some SDKs are community-maintained; verify maturity and support status at the official MCP GitHub organization before adopting in production).
- Write clear, specific tool descriptions. The AI model relies on the docstring to select the right tool, so vague descriptions lead to incorrect tool selection. Add input validation for all tool parameters alongside meaningful error responses rather than silent exception swallowing.
- Test with the MCP Inspector, a standalone developer tool installable via
npx @modelcontextprotocol/inspector. Runnpx @modelcontextprotocol/inspector uv run python weather_server.pyfrom the project directory to interactively test your server. (Requires Node.js and npx to be installed.)
Before Deployment
- Implement authentication for any remote-facing server. The MCP working group is standardizing OAuth 2.1 as the authentication mechanism for production deployments; verify your SDK version includes a compliant auth implementation before relying on it.
- Set up logging and monitoring for all tool invocations. Configure rate limiting and timeout policies to prevent abuse and runaway requests.
- Document all exposed tools, resources, and prompts with their expected inputs and outputs.
- Validate the server against multiple host applications, not just one, to ensure protocol compliance.
Common Pitfalls and Best Practices
What to Watch Out For
Overly broad tool descriptions are the most common source of bugs. If a tool's docstring says "interact with the database" instead of "execute a read-only SQL SELECT query against the analytics database," the model selects the wrong tool or invokes it on incorrect inputs. Missing error handling leads to silent failures where the model receives no response and either hallucinates an answer or stalls. Exposing write operations (database mutations, file deletions, sending emails) without a confirmation flow is a security anti-pattern that can have irreversible consequences.
Exposing write operations (database mutations, file deletions, sending emails) without a confirmation flow is a security anti-pattern that can have irreversible consequences.
Optimization Tips
For datasets that exceed the model's context window or return responses larger than roughly 50 KB, use resource URIs instead of stuffing data into tool responses. This keeps context windows manageable and lets the host decide when to load the data. Prompt templates are valuable for complex, multi-step workflows where a structured starting point reduces model errors. Version MCP servers alongside API contracts (for example, embed a version string in the server's capability response) so that host applications can detect breaking changes during the initialization handshake.
What's Next for MCP
The MCP specification continues to evolve. Streamable HTTP is becoming the preferred remote transport; current SDK releases still support SSE, but the maintainers expect to phase it out as the spec matures. Meanwhile, the spec authors are formalizing OAuth 2.1 as the standard authentication mechanism for production remote servers. There is growing convergence between MCP, which handles model-to-tool communication, and agent-to-agent protocols like Google's A2A, which handles communication between autonomous agents. Cloud providers are beginning to build hosted MCP server marketplaces, positioning MCP as infrastructure rather than just a protocol. Based on adoption by OpenAI, Google, and Microsoft within the first six months of the spec's existence, investing in MCP fluency now tracks closely with where agentic AI development is heading.

