MCP
Large language models can summarize, reason, and generate text, but their usefulness often depends on the data and actions available to them. Connecting an application directly to files, databases, APIs, or business systems usually requires custom integration code for every model and framework. Model Context Protocol (MCP) provides a common alternative: an open protocol that allows AI applications to discover and use external context and tools through a consistent interface.
Without a shared protocol, every AI application must understand the authentication rules, parameter formats, error handling, and response structures of each external system. MCP separates those concerns from the model itself.
A useful analogy is USB-C: instead of every device requiring a proprietary connector, a single standard defines how compatible components communicate. In the same way, MCP gives models, clients, and tool providers a shared contract.
The result is a more modular ecosystem:
- Tool developers can build capabilities once and expose them to multiple MCP-compatible applications.
- AI application developers can replace or add integrations without modifying the model.
- Organizations can standardize how connected systems exchange context and actions.
- Security and access controls can be implemented at the server boundary rather than inside every prompt.
MCP uses JSON-RPC 2.0 messages and supports local as well as remote services.
The Host, Client, and Server Model
MCP organizes communication around three roles:
- Host: The user-facing AI application, such as a chat client, coding assistant, IDE extension, or desktop agent. The host manages the overall interaction and decides when external capabilities are needed.
- Client: A connector created by the host for a particular server. It establishes the session, negotiates capabilities, sends requests, and routes messages.
- Server: A service that exposes specific context or functionality. Examples include filesystem access, database queries, Git operations, search services, and internal business APIs.
A host may connect to many servers, but it creates a separate client for each one. The client remains the bridge between the host and its corresponding server. This arrangement prevents the model or host from becoming tightly coupled to every individual integration.
How a Connection Works
A typical MCP session follows this sequence:
- The host launches or connects to an MCP server.
- The client and server exchange protocol versions and supported capabilities.
- The client discovers the resources, tools, and prompt templates offered by the server.
- The model interprets the user’s request and selects an appropriate capability.
- The host reviews and, when necessary, authorizes the requested operation.
- The server executes the operation and returns a structured result.
- The model uses that result to produce the final response.
This separation is important. The model does not need to know whether a tool runs in a local Python process, a cloud database, or a third-party API. It only needs to understand the capability advertised by the server.
Core Protocol Primitives
MCP describes server capabilities through several primitives.
Resources
Resources represent readable context, such as:
- Files or directories
- Database records
- API responses
- Application configuration
- Documentation and logs
Resources are commonly identified with URI-like names, for example config://app or file:///project/README.md. They provide information that can be placed into the model’s working context without treating the source as an executable action.
Tools
Tools are operations the model can request, such as searching the web, adding two numbers, creating a ticket, or querying a database. Each tool has a name, a description, and a defined input schema.
Tools resemble function calling, but MCP standardizes how they are discovered, described, and invoked. This makes a tool reusable across compatible hosts instead of binding it to one application’s internal function-calling system.
Prompts
Prompts are reusable templates for common tasks. A server might expose a prompt for code review, incident analysis, or generating a release summary. These templates help applications provide repeatable workflows while allowing the user to supply the relevant context.
Advanced Capabilities
MCP also defines optional features for more advanced interactions. Sampling lets a server request assistance from the host’s model during a task. Roots allow the client to declare filesystem boundaries or other locations that the server should use as a workspace.
These optional capabilities support richer agent workflows while preserving a clear distinction between required and negotiated features.
Local and Remote Transports
MCP supports different deployment models.
Standard I/O
With stdio, the client launches the server as a subprocess and communicates through standard input and output. This is often the simplest option for local tools, development environments, and scripts. Because no network port is exposed, the attack surface can remain small.
Streamable HTTP
For remote or shared deployments, MCP supports Streamable HTTP. It is suitable for cloud-hosted tools, organization-wide services, and environments that need centralized authentication, monitoring, or scaling. Secure remote deployments should use HTTPS, strong identity controls, and appropriate network restrictions.
Older implementations may also use HTTP with Server-Sent Events, but production designs should follow the transport supported by the deployed protocol version.
Regardless of transport, MCP messages use JSON-RPC 2.0. The same capability model therefore applies whether the server is local or hosted remotely.
Building a Small MCP Server
The following Python example uses FastMCP to expose one tool and one resource:
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("demo")
@mcp.tool()
def add(a: int, b: int) -> int:
"""Add two integers and return the result."""
return a + b
@mcp.resource("config://app")
def get_config() -> str:
return '{"environment": "development", "debug": true}'
if __name__ == "__main__":
mcp.run()
A compatible host can register the server with a configuration such as:
{
"mcpServers": {
"demo": {
"command": "python",
"args": ["server.py"]
}
}
}
After the server starts, the host discovers the add tool and the config://app resource. If a user asks what three plus five equals, the model can invoke the tool with the appropriate arguments, receive 8, and present the result in a natural response.
The example is intentionally small, but it demonstrates the key benefit: the server owns the tool implementation, while the host owns discovery and orchestration.
Security and Governance
Adding external tools gives a model influence beyond its original text-generation role. It also creates opportunities for unauthorized access, data leakage, and prompt injection. MCP servers should therefore be treated as privileged services.
Important practices include:
- Least privilege: Expose only the resources and operations required for a specific use case. Read-only access should be provided when writes are unnecessary.
- Explicit approval: Require user confirmation for sensitive actions such as deleting files, sending messages, executing commands, or changing production data.
- Strict input validation: Validate tool arguments, constrain accepted values, and never rely on the model alone to enforce authorization.
- Sandboxing: Run local servers in restricted environments with limited filesystem, network, and process access.
- Authentication and encryption: Protect remote servers with suitable identity controls, HTTPS, and TLS.
- Audit logging: Record the caller, requested operation, arguments, result, and relevant timestamps.
- Untrusted-content handling: Treat external documents, tool results, and API responses as data rather than instructions. They may contain attempts to manipulate the model.
- Version management: Use capability negotiation and compatible protocol versions to avoid silent behavior changes.
Tool design deserves particular attention. Descriptions should be precise, schemas should reject ambiguous input, and dangerous operations should be distinguishable from routine ones. A clear separation between reading data and changing state also makes approval policies easier to apply.
A Practical Path Forward
For a new project, begin with a small local server over stdio. Expose one narrowly scoped tool, inspect the messages it produces, and test how the host handles errors and user confirmation. Once the integration is stable, move shared or production workloads to a remote transport with full authentication, monitoring, and access controls.
MCP’s central promise is straightforward: models should not need a custom integration for every external capability. By standardizing discovery, invocation, and context exchange, MCP makes connected AI applications easier to build, govern, and reuse across the ecosystem.