Three months into production, the agent harness I’d built for a mid-size SaaS company was held together by twelve custom integration shims, four internal abstraction layers, and a Slack thread titled “why does the Jira tool keep returning stale tokens.” Every time the team wanted to add a new data source, we were writing bespoke glue code — parsing new schemas, negotiating auth flows, normalizing response shapes before the model ever saw them. The problem was not the AI. The problem was the integration layer.
That problem now has a name — and a standard. Model Context Protocol (MCP) is an open protocol, initially released by Anthropic in November 2024, that defines how AI agents connect to external tools, data sources, and APIs in a consistent, composable way. It is not marketing. It is a specification — and if you are building production agent harnesses today, the architectural decisions you make around MCP will shape your system’s maintainability and reliability for years.
This article covers what MCP actually is at the protocol level, the architectural problems it solves, how to reason about it in production systems, and where it still falls short.
What Model Context Protocol actually is
MCP is a client-server protocol built on JSON-RPC 2.0. At its core, it defines a standard contract between three parties:
- MCP Hosts: the AI application runtime (Claude Desktop, Cursor, your custom agent harness)
- MCP Clients: the protocol-layer component inside the host that manages connections to servers
- MCP Servers: lightweight processes that expose capabilities to the AI model
Servers expose three primitive types:
- Resources — data the model can read (files, database records, API responses, live system state)
- Tools — functions the model can invoke (create a ticket, run a query, send a message)
- Prompts — reusable prompt templates the host can surface to users
The transport layer supports two modes: stdio for local subprocess communication and Server-Sent Events (SSE) over HTTP for remote servers. That distinction matters in production: local servers run in the same process environment as your agent, while remote servers introduce network latency, authentication surface, and failure modes that require explicit handling.
The protocol is stateful. MCP maintains a session lifecycle — initialization, capability negotiation, and teardown — which is a meaningful departure from the stateless function-calling patterns most practitioners are used to. That statefulness enables richer interactions (server-side streaming, notifications, progress reporting) but it also means you need to reason about connection state, reconnection logic, and what happens when a server crashes mid-task.
The integration problem MCP is designed to solve
Before MCP, every AI agent integration was bespoke. If you wanted your agent to read from GitHub, write to Notion, query a Postgres database, and check a Salesforce record, you wrote four separate adapters. Each adapter negotiated its own auth, normalized its own response format, handled its own error taxonomy, and maintained its own retry logic. You also re-implemented all of that every time you switched LLM providers.
Consider what this looks like at scale. A team at a B2B SaaS company I worked with ran an internal agent that had integrations with Jira, Confluence, GitHub, Datadog, and their internal deployment API. Total bespoke integration code: approximately 4,200 lines across five separate modules. When they migrated from one model provider to another, the integration layer had to be almost entirely rewritten — not because the capabilities changed, but because the tool-calling schemas were provider-specific.
MCP addresses this with a single observation: the integration contract should be defined once, by the tool provider, not reimplemented by every application developer. When a Postgres MCP server exposes a query tool, any MCP-compatible host can call it with the same schema, the same error handling expectations, and the same lifecycle behavior. The application developer stops writing adapters and starts composing servers.
This is the same insight that made REST broadly successful — not that it is technically superior to alternatives, but that a shared convention reduces the coordination cost of integration dramatically.
MCP architecture patterns in production
Local server deployment
The simplest MCP deployment runs servers as local subprocesses, communicating over stdio. This pattern works well for development and for tools that need direct access to the local environment — reading files, running shell commands, interacting with local databases.
In production, local servers share the trust boundary of the host process. If your agent runs in a container, local MCP servers run in that same container. This simplifies secrets management (environment variables are available without additional plumbing) but it means a compromised MCP server has access to the full process environment. For high-sensitivity deployments, evaluate what each server actually needs access to and apply the same least-privilege thinking you would to any process running in your environment.
Remote server deployment
Remote MCP servers communicate over HTTP/SSE and can be operated independently of the host application. This pattern enables team-shared infrastructure: a single Postgres MCP server deployed as a service, accessed by multiple agent harnesses across an organization, with centralized access control and audit logging.
The architectural trade-off is real. Remote servers introduce network latency that compounds for multi-step tool calls — a five-step agent workflow that makes two tool calls per step now has ten network round-trips on the critical path. In a well-tested production system I observed, switching from local to remote MCP servers added 340ms of median latency per tool invocation. For synchronous, latency-sensitive workflows, that is significant. For asynchronous background tasks, it is not.
Remote servers also expose a new failure domain. Your agent harness now has a dependency on external service availability. MCP does not currently define a standard reconnection protocol — reconnection behavior is implementation-specific. Build reconnection and circuit-breaking logic explicitly, not as an afterthought.
Multi-server composition
MCP hosts can connect to multiple servers simultaneously, and this is where the protocol’s composability becomes tangible. An agent harness with connections to a GitHub server, a Jira server, and an internal deployment server can orchestrate cross-system workflows — reading a PR, creating a ticket, triggering a deploy — without any of those servers knowing about each other.
This composability is a double-edged pattern. It enables genuine capability expansion, but it also means the model’s effective capability surface grows with every server you add. A model connected to 15 servers has access to hundreds of tools. Tool selection accuracy degrades as the available tool count increases — several published benchmarks show meaningful accuracy drops above 50-100 available tools, though the precise threshold is model-dependent and improving rapidly.
The practical mitigation: scope server connections to the task. An agent running a code review workflow does not need the customer database server in its context. Build your harness to connect servers dynamically based on task type, not statically at initialization.
MCP versus function calling: the architectural distinction
MCP is frequently compared to function calling (or tool use), and the comparison creates confusion because they operate at different architectural layers.
Function calling is a model capability — the LLM’s ability to emit structured output indicating it wants to invoke a function, with arguments. Function calling is provider-specific: OpenAI, Anthropic, Google, and others each define their own schema formats, capability flags, and streaming behaviors. If you use function calling directly, you are coupled to a specific provider’s API contract.
MCP is an integration protocol — it defines how tools are discovered, invoked, and monitored in a provider-agnostic way. An MCP client can call MCP tools using whatever underlying mechanism the LLM provider requires. The model capability layer (function calling) sits beneath the protocol layer (MCP), not instead of it.
The practical implication: MCP does not replace function calling. It wraps it. MCP clients translate the protocol’s tool invocation format into whatever the target LLM expects. This is precisely what enables portability — switch from Claude to GPT-4 to Gemini, and your MCP servers do not change. Only the client’s translation layer changes.
Where function calling remains the right direct abstraction: simple, single-LLM applications with one or two tools, where the overhead of running MCP server processes is not justified by the integration complexity. MCP earns its overhead when you have multiple tools, multiple LLM providers, or multiple teams sharing tool infrastructure.
Reliability engineering for MCP in production
Building reliable production systems on MCP requires treating each server as a first-class dependency, not a utility.
Observability
MCP sessions emit lifecycle events — initialization, tool invocations, errors, termination — that should flow into your existing observability stack. At minimum, instrument: session establishment time, tool invocation latency by server and tool name, error rates by error type, and session reconnection frequency. Without this, you will diagnose MCP failures by reading model outputs, which is slow and unreliable.
The MCP specification does not mandate a logging format. Instrument at the client layer so you capture data regardless of which servers you are running.
Failure modes
MCP introduces failure modes that do not exist in direct API integrations:
- Server process crashes: Local servers can crash without the host receiving a clean error signal. Implement health checks and automatic restart with exponential backoff.
- Partial tool execution: A tool invocation may start, perform side effects, and then fail before returning. MCP does not provide built-in idempotency guarantees. For tools that modify external state, implement idempotency keys at the tool level.
- Schema drift: MCP servers that evolve their tool schemas can silently break clients expecting older schemas. Version your server APIs and implement schema validation at the client on startup, not at invocation time.
- Context window pollution: Large resource responses returned to the model consume context window. A file server returning 50KB of log content in response to a broad query can degrade model performance on subsequent steps. Implement response size limits and pagination in server implementations.
Security surface
MCP servers execute with the permissions of their host process. A maliciously crafted MCP server — or a legitimate server with a prompt injection vulnerability — can instruct the model to invoke other tools with attacker-controlled arguments. This is the “confused deputy” problem applied to AI agents.
Mitigations in current production practice: run MCP servers in isolated processes with explicit capability grants, validate tool arguments against expected schemas before execution (not just trusting the model’s output), and implement human-in-the-loop confirmation for any tool that mutates state in a high-consequence system. The MCP specification is developing more formal security guidance, but the ecosystem has outpaced the specification here. Treat each server you deploy as an application with its own security boundary, not a trusted internal function.
The MCP ecosystem in 2025 and 2026
The MCP ecosystem has expanded faster than most protocol ecosystems at comparable maturity. As of late 2025, the official MCP registry lists over 1,000 community-maintained servers covering databases (Postgres, SQLite, MongoDB), developer tools (GitHub, GitLab, Jira, Linear), productivity suites (Google Drive, Notion, Slack), cloud providers (AWS, GCP), and observability platforms (Datadog, Grafana, Sentry).
Major IDE vendors have adopted MCP. Cursor, Zed, and several JetBrains products ship with MCP client support. Claude Desktop uses MCP as its primary tool integration mechanism. This adoption creates a network effect that is not present with custom integration approaches — a server built for Claude Desktop works immediately in Cursor, in a custom harness, in any MCP-compatible host.
The specification itself is still maturing. Version 2024-11-05, the initial public release, established the core primitives. Subsequent revisions have addressed streaming tool results, root URI negotiation for resource servers, and improved error handling specifications. The pace of specification evolution means production implementations should track spec changes and test for behavioral drift when upgrading SDK versions.
Worth watching: the emerging work on multi-agent MCP patterns, where one agent acts as an MCP server for another. This enables hierarchical agent architectures where a coordinator agent delegates to specialist agents through the standard MCP interface — the same protocol that connects agents to tools connects agents to each other. This is an architectural pattern with significant implications for harness engineering, though the operational complexity of orchestrating multiple agent-as-server deployments in production is not yet well-understood. Expect significant practitioner knowledge to accumulate here through 2026.
Where MCP still falls short
Honest assessment matters more than enthusiasm for a protocol that is two years old.
Standardized authentication is absent from the core spec. Each server implementation handles auth differently. This means you cannot assume an MCP server you pick up from the community handles secrets safely, rotates tokens correctly, or supports your organization’s SSO flow. Audit auth implementations in any server you run in production.
Discovery is immature. Finding and evaluating available servers is still largely manual. The registry exists, but tooling for evaluating server reliability, security posture, and schema quality is nascent. Treat community MCP servers the way you would a third-party npm package — audit before you deploy.
Testing standards do not exist. There is no MCP testing framework analogous to what exists for REST APIs. Testing a server currently means writing custom harness code that instantiates an MCP client, connects to the server, and exercises its tool schemas. This is tractable but not standardized. Contract testing frameworks for MCP are an open engineering gap.
Concurrency semantics are underspecified. The specification does not define behavior when multiple concurrent tool invocations target the same server. Server implementations handle this inconsistently. For tools that access shared state — a database, a file system — undefined concurrency semantics are a production risk.
Building on MCP: the practitioner’s starting point
If you are evaluating MCP for a production agent harness, the entry path is straightforward. The official SDKs for Python and TypeScript are stable and well-maintained. Start with a local server implementation using stdio transport, exposing one or two tools against an internal data source. Instrument the client to emit session and invocation telemetry to your existing monitoring stack. Run it in a staging environment with synthetic load before promoting to production.
The key architectural decision is whether to use existing community servers or build your own. For common integrations (GitHub, Postgres, Slack), the community servers are production-grade for most use cases. For internal systems, proprietary APIs, or tools with specific security requirements, building your own server against the TypeScript or Python SDK typically takes one to three days for a well-scoped tool surface.
The harness pattern that is proving most reliable in production: treat MCP servers as microservices. Deploy them separately from your agent host. Version their APIs. Monitor them independently. Give them their own on-call runbooks. The protocol is a standard, but each server is an operational dependency you own.
For a deeper look at how the 6-step agent harness pattern maps to MCP server design, see our guide to production AI agent architectures. For the security surface in more detail, the agent harness security model covers the confused deputy problem and mitigation patterns in full.
What MCP changes about how we build agents
The teams doing the most sophisticated agent engineering right now are treating MCP as infrastructure — the same way they treat their message bus or their service mesh. It is not the application. It is the substrate that makes the application composable.
That framing clarifies what MCP does and does not solve. It does not solve the hard problems in agent engineering: reasoning quality, planning under uncertainty, handling ambiguous tool outputs, detecting when an agent has gone off-task. Those remain model and harness problems. What MCP solves is the mechanical problem of integration — the 4,200 lines of adapter code that have to be rewritten every time the tool surface or the LLM changes.
That is a real problem. Solving it is a meaningful advance. The agent harness engineering discipline is young enough that clearing mechanical obstacles — standardizing integration contracts, reducing adapter code, enabling composable tool ecosystems — frees practitioners to focus on the genuinely hard architectural and reliability problems that do not yet have good answers.
MCP is not the future of AI agent integration because it is perfect. It is the future because it is the standard the ecosystem is converging on, the trade-offs are tractable, and the alternative is writing more shims.
Ready to put MCP into practice in your agent harness? The harness-engineering. ai practitioner library covers production deployment patterns, observability instrumentation, and security configurations for MCP-based systems. Subscribe to get new guides as they publish.
Dr. Sarah Chen is a Principal Engineer focused on production AI agent systems and harness architecture. She has built and operated agent harnesses at scale across SaaS, fintech, and infrastructure domains.