Model Context Protocol (MCP) Architecture
The Model Context Protocol (MCP) is an open standard that enables AI applications (hosts) to seamlessly and securely interact with external data sources, enterprise tools, and execution environments. This note deconstructs the MCP architecture from first principles—starting from a naive point-to-point model and progressively building up to the decoupled, multi-layered production architecture comprising Hosts, Clients, Servers, Primitives, the JSON-RPC 2.0 Data Layer, and STDIO/HTTP-SSE Transport Layers.
1. The Simplest Mental Model: Host and Server
At its absolute foundational level, the Model Context Protocol ecosystem consists of two core entities: a Host and a Server.
The Host
The Host is the front-facing AI application or chatbot interface that directly interacts with the end-user.
- Core Responsibilities: Captures user prompts, manages conversational state, and queries an underlying Large Language Model (LLM) such as OpenAI GPT-4, Anthropic Claude, or Google Gemini.
- Form Factors: Can be off-the-shelf software (e.g., Claude Desktop, Cursor IDE) or a custom-built AI agent framework (e.g., built using LangGraph or AutoGen).
The Server
The Server is a specialized, lightweight application that exposes specific capabilities, context, or tools to execute targeted tasks.
- Examples:
- GitHub Server: Exposes tools to read repositories, check pull requests, or list open issues.
- Slack Server: Exposes capabilities to read messages or post alerts to specific channels.
- Google Drive Server: Exposes capabilities to search, read, or manipulate cloud documents.
Naive Execution Flow
- User Prompt: The user asks the Host: "Are there any new commits on the GitHub repository?"
- LLM Evaluation: The Host forwards the prompt to the LLM. The LLM determines that the answer is missing from its parametric training data and identifies that an external tool is required.
- Tool Resolution: The Host queries the GitHub Server for recent commit details.
- Server Execution: The GitHub Server queries the target repository and returns raw commit data to the Host.
- Final Generation: The Host passes the retrieved commit data back to the LLM, which synthesizes a natural language response for the user.
2. Introducing the Helper: The MCP Client
While the simplified Host-to-Server model provides intuitive understanding, direct communication between a Host and a Server introduces structural flaws. In production MCP architecture, a Host never communicates directly with a Server. Instead, communication is brokered by an intermediate entity called the MCP Client.
The Role of the MCP Client
The MCP Client acts as a protocol-aware adapter inside the Host application. It speaks the native MCP language that Servers understand, handling low-level protocol serialization, deserialization, and message formatting.
- High-Level Abstraction: The Host passes high-level intent to the Client (e.g., "Find recent commits").
- Protocol Translation: The Client translates high-level intent into structured, MCP-compliant protocol requests, sends them to the Server, parses structured responses, and translates them back into a format digestible by the Host.
The 1:1 Client-Server Relationship
In MCP architecture, the relationship between an MCP Client and an MCP Server is strictly one-to-one (1:1). A single MCP Client instance connects exclusively to a single MCP Server instance.
If a Host needs to interact with three different services (e.g., GitHub, Slack, and Google Drive), the Host must instantiate three separate MCP Clients, each maintaining a dedicated channel to its respective Server.
Real-Life Analogy: The Smartphone & SIM Card
To visualize this relationship, consider a mobile phone system:
Real-Life Analogy
- The Smartphone = The Host (The user interface device).
- The SIM Card = The MCP Client (The adapter speaking the carrier protocol).
- The Cellular Network (Airtel/Jio/Vodafone) = The MCP Server (The external service provider).
A smartphone cannot connect directly to a cellular network wire-free without an interface; it requires a SIM card. If you want your phone to connect to three distinct mobile networks simultaneously, your phone must host three distinct SIM cards (or eSIM profiles). Each SIM card maintains a dedicated 1:1 connection with its specific cellular network.
3. Core Architectural Benefits: Decoupling and Scalability
Separating the Host, Client, and Server into isolated modules yields two primary system architecture design benefits:
1. Decoupling (Separation of Concerns & Safety)
Each Client-Server pair operates in complete isolation. The GitHub communication pipeline has zero visibility into or dependencies on the Slack or Google Drive pipelines.
- Fault Tolerance: If the GitHub Server crashes or encounters network failure, the Slack and Google Drive pipelines remain unaffected and operational.
- Parallel Execution: Because communication channels are isolated, the Host can dispatch asynchronous tasks across multiple Clients concurrently, executing actions in parallel rather than serially.
2. Infinite Scalability
The Host framework remains completely agnostic to the inner workings of external services. To add integration with a new enterprise tool (e.g., Jira or Postgres), developers simply deploy a new MCP Server and configure the Host to instantiate an accompanying MCP Client. The core Host logic requires zero modification.
4. Server Offerings: The Three MCP Primitives
MCP defines three foundational building blocks—known as Primitives—that an MCP Server can expose to the Host.
1. Tools (Executable Actions)
Tools represent executable capabilities or functions that the LLM can invoke to perform side-effects or fetch dynamic external data.
- Characteristics: Dynamic, executable, parameter-driven.
- Examples:
- GitHub Server:
create_issue(title, body),get_commit_history(repo, branch). - Google Drive Server:
search_files(query),create_folder(folder_name).
- GitHub Server:
2. Resources (Readable Context)
Resources represent passive, structured data sources exposed by the Server that the LLM can read as ambient context.
- Characteristics: Read-only, static or semi-static reference data.
- Examples:
- GitHub Server: The content of a repository's
README.mdfile. - Database Server: A database schema definition or configuration file.
- GitHub Server: The content of a repository's
Key Distinction (Tools vs. Resources): If the requested data is dynamic and requires function execution with parameters (e.g., getting current open issue count), it is exposed as a Tool. If it is static context meant for reading (e.g., a documentation file or log file), it is exposed as a Resource.
3. Prompts (Predefined Context Templates)
Prompts are predefined, reusable interaction templates hosted on the Server that guide the LLM's behavior when interacting with specific tools or resources.
- Problem Solved: Unguided LLMs often generate vague or unstructured calls (e.g., creating a GitHub issue with just a title and no reproduction steps).
- How it Works: The Server exposes a prompt template (e.g.,
issue_report_prompt) specifying mandatory structural guidelines (System Instructions: "Always mandate Title, Steps to Reproduce, Expected Behavior, Actual Behavior, and Environment details"). When selected, the Host uses this template to shape the user's raw input before invocation.
5. Standard Primitives Operations and Methods
MCP formalizes how Clients interact with Primitives through standardized protocol operations.
6. The Data Layer: Mechanics of JSON-RPC 2.0
The Data Layer defines the formal language, grammar, and payload syntax used by MCP Clients and Servers to communicate.
Core Specification: MCP mandates JSON-RPC 2.0 as the foundational standard for its Data Layer.
What is Remote Procedure Call (RPC)?
A Remote Procedure Call allows a local program to execute a function/procedure on a remote computer across a network as if it were a local function call, abstracting away low-level network serialization.
Anatomy of JSON-RPC 2.0 Payloads in MCP
1. Request Payload (tools/list)
Sent by the Client to discover Server tools:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list",
"params": {}
}
2. Success Response Payload (tools/list)
Returned by the Server providing the tools array:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"tools": [
{
"name": "list_issues",
"description": "Lists open repository issues",
"inputSchema": {
"type": "object",
"properties": {
"repo": { "type": "string" }
},
"required": ["repo"]
}
}
]
}
}
3. Execution Request Payload (tools/call)
Sent by the Client to run a tool:
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "list_issues",
"arguments": {
"repo": "campusx/mcp-demo"
}
}
}
4. Execution Response Payload (tools/call)
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"content": [
{
"type": "text",
"text": "Issue #101: Login button failing on OS X Chrome."
}
]
}
}
5. Notification Payload (Fire-and-Forget)
Unlike standard Requests, Notifications do not contain an id field. They tell the receiving party that an event occurred without expecting a reply.
{
"jsonrpc": "2.0",
"method": "notifications/resources/updated",
"params": {
"uri": "file:///docs/README.md"
}
}
6. Error Response Payload
Standardized JSON-RPC error structures allow clean exception handling:
{
"jsonrpc": "2.0",
"id": 3,
"error": {
"code": -32602,
"message": "Invalid params: Missing required field 'repo'."
}
}
7. Request Batching
JSON-RPC supports bundling multiple operations into a single array payload to reduce round-trip overhead:
[
{ "jsonrpc": "2.0", "id": 10, "method": "tools/call", "params": { "name": "list_issues" } },
{ "jsonrpc": "2.0", "id": 11, "method": "tools/call", "params": { "name": "list_pulls" } }
]
7. Strategic Rationale: Why JSON-RPC 2.0 over REST APIs?
A common architectural question arises: Why did the creators of MCP choose JSON-RPC 2.0 instead of industry-standard REST APIs over HTTP?
REST API Paradigm (Verb & Resource-centric)
HTTP GET /api/v1/repos/campusx/issues
HTTP POST /api/v1/repos/campusx/issues
JSON-RPC 2.0 Paradigm (Procedure-centric)
Payload: { "method": "tools/call", "params": { "name": "list_issues" } }
Five primary factors justify choosing JSON-RPC 2.0 for agentic tool use:
- Lightweight & Low Overhead: REST mandates HTTP verbs, URL path parsing, and heavy HTTP headers. JSON-RPC requests are pure, minimal JSON text strings that can be serialized/deserialized rapidly without web server overhead.
- Bi-directional Communication: REST is strictly single-directional (Client requests, Server responds). JSON-RPC supports bi-directional interaction—allowing a Server to initiate requests or ask for clarifications back from the Host/Client.
- Transport Agnosticism: REST is bound strictly to HTTP/S. JSON-RPC is agnostic to the transport layer; it functions identically over raw Standard Input/Output (
STDIO), WebSockets, IPC pipes, or HTTP. - Native Request Batching: JSON-RPC allows batching arbitrary heterogenous commands (
tools/list,resources/read) in a single payload vector natively, whereas REST requires custom endpoint wrappers. - Native Notification Semantics: JSON-RPC formally supports fire-and-forget notifications (by omitting the
"id"key), matching real-time agentic state updates cleanly without creating artificial dummy HTTP responses.
8. The Transport Layer: Local vs. Remote Servers
While the Data Layer handles what message is written (JSON-RPC), the Transport Layer defines how the message physically moves between the MCP Client and MCP Server.
Local Servers vs. Remote Servers
Local Server
- Definition: An MCP Server running as a process on the exact same local physical machine as the Host application.
- Example: A File System Server or SQLite Server reading local drives.
- Transport: STDIO (Standard Input/Output).
Remote Server
- Definition: An MCP Server hosted externally across a network or cloud infrastructure.
- Example: A GitHub Cloud Server or Jira Enterprise Server.
- Transport: HTTP + SSE (Server-Sent Events).
9. Deep Dive into Local Transport: STDIO
Standard Input/Output (STDIO) is the mandatory transport protocol for local MCP servers.
Standard I/O Streams Overview
Every operating system process inherently possesses standard stream pipes:
stdin(Standard Input): Stream through which a process reads incoming data.stdout(Standard Output): Stream through which a process writes outgoing data.
The 3-Step STDIO Process Lifecycle
- Sub-Process Launch: The Host launches the local Server executable as a child sub-process on the local machine. This creates a direct Parent-Child process hierarchy.
- Pipe Binding: The Host claims direct control over the child process's
stdinandstdoutfile descriptors. - Message Passing:
- To send a request, the Client writes the JSON-RPC string directly into the child process's
stdin. - The child process executes the procedure and writes its JSON-RPC response directly out to its
stdout. - The Client reads the
stdoutpipe, completing the round-trip.
- To send a request, the Client writes the JSON-RPC string directly into the child process's
Terminal Demonstration Analogy
Consider running a simple interactive Python script via CLI:
$ python3 hello.py
Enter your name: Nitish
Hello Nitish
In this terminal interaction:
- The Terminal acts as the Host.
- The
hello.pyfile acts as the Server sub-process. - Passing
"Nitish"usesstdin. - Receiving
"Hello Nitish"usesstdout.
Advantages of STDIO Transport
- Blazing Fast: Operates directly via shared OS memory pipes without network socket overhead.
- Air-Gapped Security: Opens zero network ports on the local host machine, eliminating network attack vectors.
- Universal Language Compatibility: Virtually every programming language natively supports
stdinandstdout.
10. Deep Dive into Remote Transport: HTTP + SSE
When the MCP Server resides on a remote network or cloud infrastructure, STDIO cannot be used because process hierarchy across machines does not exist. MCP addresses this by using HTTP combined with Server-Sent Events (SSE).
How HTTP + SSE Functions in MCP
- Connection Initialization (SSE Endpoint): The MCP Client issues an
HTTP GETrequest to the server's/sseendpoint. The Server opens a long-lived HTTP connection streaming withContent-Type: text/event-stream. - Session Assignment: The Server responds via SSE with an event containing a dedicated endpoint URI for sending messages (e.g.,
/message?sessionId=abc12345). - Command Transmission: The Client posts JSON-RPC payloads as standard
HTTP POSTrequests targeting the session endpoint URI. - Streaming Response: Rather than returning a single monolithic payload, the Server pushes incremental stream chunks back to the Client over the open SSE connection.
Core Benefits of HTTP + SSE
- Real-Time Streaming: Enables LLMs to stream tool results token-by-token or push real-time agent status indicators to the user.
- Enterprise Authentication: Fully supports enterprise security layers (OAuth2, Bearer tokens, custom headers, and API keys).
- Ideal for Long-Running Tasks: Allows long-running AI agent functions to emit updates continuously over time without encountering HTTP connection timeouts.
11. End-to-End Architectural Synthesis
Putting every layer together reveals the complete Model Context Protocol ecosystem:
Complete End-to-End Interaction Walkthrough
- User Query: User submits a complex prompt to the Host.
- Context Determination: The Host consults the LLM. The LLM inspects available primitives exposed across connected MCP Clients.
- Primitive Selection: The LLM calls a tool exposed by the remote GitHub Server (
create_issue). - Prompt Template Fetch: Host accesses the
prompts/getprocedure from the Server to structure the input cleanly according to mandatory repository rules. - Request Generation: MCP Client 2 serializes the payload into a
JSON-RPC 2.0request object:{"jsonrpc": "2.0", "id": 42, "method": "tools/call", "params": {...}} - Transport Transmission: The request is transmitted over an
HTTP POSTrequest to the Remote MCP Server session URI. - Execution & Response: The Remote Server processes the request against the GitHub API, constructs a
JSON-RPC 2.0response, and streams the output back over the openSSEchannel to MCP Client 2. - UI Rendering: MCP Client 2 passes the unmarshalled response back to the Host, which feeds it to the LLM to format the final textual message to the user.
12. Complete Architectural Summary Matrix
Summary and Key Takeaways
- Decoupled Architecture: MCP replaces monolithic tool integrations with a cleanly decoupled Host-Client-Server pattern, ensuring system fault tolerance and scaling capabilities.
- Strict 1:1 Client-Server Mapping: Hosts interact with external services via MCP Clients. Each Client instance maintains an isolated 1:1 connection with exactly one Server instance.
- Three Server Primitives: MCP Servers expose capabilities through Tools (executable functions), Resources (readable static context), and Prompts (predefined template guidelines).
- JSON-RPC 2.0 Data Layer: All MCP interactions use JSON-RPC 2.0, providing lightweight, transport-agnostic, bi-directional, procedure-based message semantics that natively support request batching and fire-and-forget notifications.
- Dual Transport Modes: MCP dynamically uses STDIO for zero-latency, secure local machine sub-processes and HTTP + SSE for remote streaming cloud integrations.
- Transport Agnosticism: Because JSON-RPC 2.0 is transport-agnostic, changing the underlying transport layer from STDIO to HTTP/SSE requires zero modification to the high-level Data Layer message schema.