How MCP Server Architecture Actually Works
The protocol that replaces custom connectors for every AI-tool pairing.

Before MCP, hooking N AI apps up to M external tools meant building a custom connector for every single pairing. Claude to GitHub, ChatGPT to Slack, Cursor to Postgres, Gemini to some internal API nobody outside the company has heard of. Each one bespoke, each one its own maintenance burden.
In practice, that meant duplicated glue code sitting in a dozen different repos, adapters that snapped the moment a vendor pushed an API update, and no shared way for a tool to describe itself so an AI could figure out how to use it. Developer time went into keeping integrations alive instead of building anything new. Per a TrueFoundry study, 70 to 95% of AI projects never make it to launch because of integration bottlenecks, with teams spending more hours on custom integration code than on the AI part of the project itself.
The math gets worse as an org grows, and this is the part most teams underestimate until it's already too late. Add one new model and one new tool, and the connector count doesn't grow by two, it grows by however many pairings that creates across everything already in place. N times M, not N plus M. A smarter connector just delays the same wall. Fixing it for good means a shared contract at the protocol layer instead, and MCP is the correct bet on what that contract should look like.
What MCP actually is and where it came from
MCP, short for Model Context Protocol, is an open standard that lets any AI application find and call external tools, pull external data, and load reusable prompts from independent servers, all through one message format built on JSON-RPC 2.0.
Think of it as gRPC and OpenAPI, but built for how LLMs actually call tools. Each external system sits behind an MCP server that normalizes requests and responses, so the model never has to learn Slack's API quirks versus GitHub's versus some internal tool's home-grown auth scheme. A closer comparison, for anyone who's worked in dev tooling, is the Language Server Protocol. LSP meant one editor could support dozens of languages without a custom plugin for each combination. MCP does the same job for AI agents and the systems they touch.
The governance history is worth knowing, especially for anyone building on this at a company. Anthropic put MCP out as an open-source protocol in November 2024. Then, in December 2025, Anthropic handed it over to the Agentic AI Foundation, a directed fund under the Linux Foundation co-founded by Anthropic, Block, and OpenAI. Handing MCP's status to neutral, community-run infrastructure rather than something one vendor controls is what gives companies with competing interests any reason to build on it at all.
The adoption numbers back this up. More than 10,000 active public MCP servers were reported at the time of the Linux Foundation donation. By March 2026, the SDKs were seeing over 97 million downloads a month and had passed 81,000 GitHub stars. Company-run MCP servers jumped from 425 to 1,412 between August 2025 and February 2026, a 232% increase, with monthly additions climbing from 56 to 301 over that stretch. The official registry lists over 9,400 available servers as of 2026, and the protocol is backed by OpenAI, Google, and most of the major IDEs. It is a bet on where things stand now. It's already running in production at a scale that makes the architecture worth learning in detail.
The three-component model: host, client, and server
MCP splits responsibility across three roles, not two, and skipping that distinction is how most explanations of this protocol go wrong.
The MCP host is the AI application itself, the thing a person actually opens: Claude Desktop, Cursor, a custom-built chatbot. It manages conversation state, decides when a tool call is needed, and routes results back to the user.
The MCP client lives inside the host and holds exactly one connection to exactly one MCP server. A host can run several clients at once, but each client-to-server relationship is strictly 1:1. Connection state, auth, and error handling all stay scoped to a single pair, so nothing bleeds across servers, which keeps the whole system predictable rather than limited.
The MCP server exposes tools, data, and prompts through a self-describing schema. In practice, these tend to be thin: a server wrapping a REST API often comes in under 200 lines of code.
The host handles starting and stopping clients, feeding conversation state to the model, and routing tool calls to the right server. The client handles the connection itself, authentication and credential flow, pulling tool metadata, and running the actual invocations. Credentials live in the server or the external service, never in the model's context window, and that detail carries real weight. The LLM only ever sees intents and handles, not raw API keys or tokens. That separation is deliberate, and it has real security consequences, covered further down.
The external service itself, GitHub, Postgres, a filesystem, a robotics controller, sits outside the protocol entirely. MCP doesn't touch the service. It normalizes the connection to it.
How the protocol actually communicates: JSON-RPC 2.0 and the three primitives
Every message between client and server rides on JSON-RPC 2.0. That choice keeps MCP language-agnostic and easy to debug, since anyone can read the raw JSON going back and forth.
A typical exchange runs through three phases. First, discovery: the server hands back an OpenAPI-style schema listing tool names, plain-language descriptions, parameter types, and usage examples. That schema gets folded into the agent's context or system prompt during initialization. Second, invocation: the client sends a structured call with an action name, its parameters, and a call ID for tracking, and the model generates that JSON itself based on the schema it just read. Third, result or error: the server sends back structured data tied to that call ID, with support for chunked streaming on jobs that take a while, like a sequence of progress events during a video transcription run.
Underneath all of that sit three primitives, the actual building blocks any MCP server can offer:
- Tools, executable actions the agent can call, basically function calls with their own parameter schema and description.
- Resources, structured data the agent can read directly, files, database rows, API responses, without needing a full tool call just to look something up.
- Prompts, reusable, parameterized templates the server hands out, a way of baking domain know-how into how the agent talks to a given system.
SDKs exist in TypeScript, Python, Go, Java, Kotlin, C# for.NET, Ruby, and PHP, plus a CLI shim for shell scripts, so wherever a developer already works, MCP meets them there.
Put together, tools, resources, and prompts move an agent from something that just answers questions into something that participates in a workflow: tools let it act, resources let it read, prompts let it reason the way a domain expert would.
Transport options and the 2026 shift to stateless architecture
As of the July 28, 2026 spec revision, MCP supports two transports. STDIO, standard input/output, is for local setups where client and server run in the same environment: lowest latency, no network hop, simplest to wire up. Streamable HTTP is for remote connections over standard HTTP, the transport that matters once a deployment goes to production across teams or into the cloud. An older HTTP+SSE transport was deprecated back in March 2025; teams still running it should know it's on its way out, though the spec still documents a backwards-compatibility path.
The bigger change in that July 2026 revision is that remote transport became stateless at the protocol level. Every request now carries its own protocol version and capabilities, and there's no protocol-level session to set up or babysit. Application-level state can still get tracked through explicit handles when it's actually needed, but the protocol itself stopped requiring it.
That matters more than it sounds like on paper. Running MCP at scale used to mean sticky routing or shared session state just to keep continuity across requests, even when the tools being exposed were themselves stateless. That's a lot of infrastructure complexity for something that, conceptually, shouldn't need it. With the stateless shift, MCP servers can sit behind a plain load balancer with no sticky routing at all. Horizontal scaling gets a lot less painful, and deployment complexity drops with it.
This got described as the biggest revision to the protocol since it launched, a real architectural shift aimed at making MCP hold up at enterprise scale, not a patch. Capacity planning, failure recovery, and deployment topology all got simpler to reason about under the new model.
Dynamic tool discovery and why it changes the integration model
Here's the actual departure from how integrations used to work. In a conventional setup, a developer hard-codes how an AI talks to each service ahead of time, writing the schema, the parameter format, and the invocation pattern by hand, then updating each by hand whenever something changes on the other end.
MCP flips that. An agent can connect to a tool it has never seen before and figure out how to use it, with zero code changes on the AI side, because the server describes its own capabilities the moment the connection opens.
The mechanics: when a client registers a new MCP server, it immediately asks for that server's capabilities, and the response comes back with tool names, descriptions, parameter schemas, and usage examples. The host folds that metadata into the agent's context or system prompt during initialization. From there, the agent reasons over the schema itself to decide whether and how to call the tool. No pre-training on that specific tool required, ever.
For a team, this changes what "onboarding a new use case" even means. Once a server's in place, adding a new chatbot, a new analytics workflow, a new automation, is a matter of defining new tools or resources, not rebuilding integration plumbing from the ground up.
But self-description isn't free, a tradeoff most demos never show you. Every tool schema injected at discovery eats into the context window before a single user query even runs. With five to seven servers connected, tool definitions alone can eat up 10 to 20% of the available context window. Push past that, and context bloat can climb to 20 to 50% of total capacity. Discovery buys flexibility, but flexibility at scale costs context, and that's one of the first real walls teams hit moving an MCP setup from a demo to something running in production.
How initialization, session flow, and tool invocation sequence together
Phase 1: initialization and capability registration. The host connects to whichever MCP servers are configured at startup. Each server responds with its capability metadata, tool names, descriptions, parameter schemas, resource lists, available prompt templates. That metadata gets folded into the agent's context or system prompt, so by the time a user types anything, the agent already knows what's available and how to call it.
Phase 2: user request and tool selection. A user sends a request into the host, which passes it along with the agent's context to the model. The model reasons over the tool schemas it has and, if the request calls for an external action, generates a structured tool-call in JSON. The host routes that call to the right MCP client, which forwards it to its server.
Phase 3: execution and response. The server takes the structured invocation, translates it into a native call against the actual external service, and sends back a structured result. For anything long-running, the server can emit progress events along the way, which the host can surface in the UI as it happens. The client passes the final result back to the host, which either feeds it into the model's next reasoning step or shows it straight to the user.
A few things stay true no matter where you are in that sequence. Credentials never pass through the context window; they stay put on the server or with the external service. The model only ever sees tool schemas and results, never raw API internals, because the server sits in between as a normalizing layer. And each client-server connection runs independently: if one server goes down, it doesn't take the others with it.
None of this changes based on transport. Whether the connection runs over STDIO or Streamable HTTP, the sequence plays out the same way. That's by design.
Where the architecture's security posture changes relative to traditional APIs
Traditional client-server apps run on a fixed call graph, built and reviewed ahead of time. MCP-powered systems don't work that way, and treating them like "APIs with extra steps" is the mistake that gets teams burned. Control flow gets decided at runtime, by whatever the agent's reasoning loop lands on in that moment.
That runtime flexibility is exactly what makes agents useful, and exactly what makes the risk model different. An agent can chain tool calls together, build arguments on the fly, and trigger server-side actions that reach into sensitive territory: filesystems, credentialed APIs, internal networks, downstream services beyond its explicit targets. A bug that would've stayed contained to a single request in a traditional API can now cascade across tools. Per arXiv:2603.10194 (March 2026), 191 of 222 open-source MCP server repositories examined, 86.0%, had at least one mapped security weakness. That number alone should end any debate over whether MCP servers need dedicated security review separate from normal API review.
Three attack surfaces show up here that traditional APIs simply don't carry in the same form.
Prompt injection escalation. A bad instruction hidden in a document, an email, or a webpage the agent processes can talk the model into calling a tool it had no business calling. The Supabase Cursor agent incident in July 2025 is the case study: a privileged agent got tricked into leaking sensitive credentials, because the malicious instruction rode in on content the agent was supposed to just read.
Tool schema poisoning. A bad MCP server can bury hidden instructions inside its own tool descriptions, the very metadata the agent trusts during discovery, and use that to redirect the agent's behavior. Researchers have demonstrated this working in practice: a malicious MCP server can quietly exfiltrate sensitive data through nothing more than a poisoned tool description.
Unauthenticated server exposure. CVE-2025-49596, rated 9.4 on CVSS, showed that unauthenticated MCP Inspector instances could be used to run arbitrary commands. No fancy exploit needed, just a server left open that shouldn't have been.
The excessive agency, granting an agent more functionality, permissions, or autonomy than a task requires, is widely recognized as one of the most serious risks in agentic AI deployments facing agentic systems. All of those root causes map directly onto how MCP gets deployed in practice, showing up as a server that exposes more than it needs to, a client granted more permission than the task calls for, and an agent trusted to decide more than it should. That's not unique to MCP. It's what happens any time a system hands runtime decision-making to something that reasons instead of following a fixed script. MCP just makes that tradeoff explicit, and that's exactly why it has to get designed around instead of assumed away.


