Deep Dive: How does MCP actually work under the hood?
In the age of Large Language Models (LLMs), the gap between reasoning and execution has become a central challenge. An LLM can deduce the steps needed to fix a bug in a codebase or deploy an application, but without a structured, reliable means of interacting with the real world, it remains a spectator.
This communication challenge is solved by the Model Context Protocol (MCP), also known as the Agent Protocol. MCP is not just a standard API; it’s a fully realized client/server architecture designed to be the glue that connects the abstract intelligence of an LLM to the concrete capabilities of the environment. It transforms passive instruction into execution.
This in-depth exploration will dissect the architectural roles, the standardized communication language, the three core context primitives, and the bi-directional flow that constitutes the MCP architecture.
Host, Client, and Server
The MCP architecture is built upon a separation of concerns involving three primary roles. This separation ensures that a single AI can coordinate with multiple distinct, specialized systems simultaneously.
MCP Host
The Host is the application housing the actual intelligence (the LLM). It is the agent’s brain, responsible for interpreting the user’s goal and translating it into a sequence of actionable steps.
- Role: The Host analyzes user input, reasons over the available context (the data retrieved from the servers), decides which action is needed next, and then directs the Client to execute that action on the appropriate Server.
- Focus: By offloading domain complexity to the Servers, the Host remains focused on high-level planning and synthesizing information.
MCP Client
The Client is the intermediary that bridges the Host and the Server. For every Server the Host needs to connect to (e.g., one for code, one for files, one for documentation), the Host initiates a dedicated MCP Client.
- Role: The Client handles all the low-level networking, maintains a persistent TCP connection, serializes and deserializes the protocol messages, and tracks the session state. It ensures reliable data exchange without burdening the Host's core reasoning loops.
MCP Server
The Server is the authoritative source of truth and capability for a specific domain. It’s typically a standalone process that encapsulates the logic for interacting with a particular environment, such as a file system, a database, or an API.
- Role: The Server is responsible for safe, secure, and accurate execution within its domain. For example, a "Code Execution Server" hosts a secure shell environment, managing access control and preventing unauthorized operations. It holds the "tools" and "resources" that the AI needs.
- Decoupling: The Server is completely model-agnostic. It doesn't contain the LLM itself; it only knows how to perform its specialized tasks. This allows for lightweight, secure, and highly optimized server implementations.

MCP Communication
All communication within MCP is standardized using JSON-RPC 2.0. There are two supported transportation methods between the Client and Server.
- Structure (JSON-RPC): JSON-RPC enforces a clear messaging format: a Request (a method call to be executed remotely), a Response (the result of that execution), and a Notification (a message where no response is expected). This structure makes the communication highly machine-readable, robust against errors, and easy to parse by any programming language.
JSON-RPC over TCP (Streamable HTTP)
- Reliability (TCP): The choice of TCP is fundamental. In agentic work, every packet is critical. TCP guarantees that data arrives in order and without corruption, which is non-negotiable for deterministic outcomes.
JSON-RPC over STDIO (Standard Input/Output)
- Simplicity: STDIO provides a consistent, high-level way for a program to interact with its local environment. By co-locating the Client and Server on the same system and leveraging STDIO for communication, this removes the network (and network problems) from the picture.

MCP Client-Server Initialization
The conversation doesn't start with action. It starts with mutual understanding.
- Handshaking: A connection begins with the Client informing the Server of its intent (e.g., initiating a "Play" state).
- Capability Negotiation: The Client sends a
clientInfoobject, and the Server sends aserverInfoobject. These packets declare what features and primitives each party supports. This vital step prevents the AI from attempting to call a method or primitive that the specific Server doesn't support, ensuring compatibility and efficiency from the start.


The Three Primitives
MCP formalizes all possible interactions into three core Primitives. These are the standardized data types that allow any Host to use any Server, creating a universal language for AI agents.
Tools (do something)
Tools represent the executable functions or procedures that enable the agent to perform actions, such as changing the environment.
| Action Type | Method | Purpose |
|---|---|---|
| Discovery | tools/list |
Returns a list of all available tool methods on a server |
| Execution | tools/call |
Executes a specific tool method with given arguments |
Tool(s) Discovery
{
"jsonrpc": "2.0",
"method": "tools/list",
"params": {},
"id": 101
}Client request
{
"jsonrpc": "2.0",
"result": {
"tools": [
{
"name": "shell/execute",
"title": "Execute Shell Command",
"description": "Runs a command in the isolated shell environment. Accepts a 'command' string argument. Returns 'stdout', 'stderr', and 'exit_code'."
}
]
},
"id": 101
}Server response
Example: Executing a Test Suite
Imagine an AI Host debugging a failing application.
Host's Plan: "I need to reproduce the bug by running the existing test suite."
Client Request: The Client constructs a JSON-RPC request to the Code Execution Server.
{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "shell/execute",
"arguments": { "command": "npm test" }
},
"id": 101 // Unique request ID
}
Server Response: The Server executes the command in its secure sandbox and returns the stdout/stderr.
{
"jsonrpc": "2.0",
"result": {
"exit_code": 1,
"stdout": "Test suite failed: 1 assertion failed.",
"stderr": "AssertionError: expected '4' but got '5'"
},
"id": 101
}
The Host receives this structured data and feeds it back into the LLM as context for the next step: "The test failed because 4 was expected but 5 was returned."
Resources (give me information)
Resources are the passive, contextual data objects that the agent can retrieve and synthesize. They provide the necessary information for grounding the LLM’s reasoning in the real world.
| Action Type | Method | Purpose |
|---|---|---|
| Discovery | resources/list |
Returns a hierarchical list of available data points (files, links, schemas, etc) |
| Execution | resources/get |
Retrieves the full content of a specified resource |
Resource(s) Discovery
{
"jsonrpc": "2.0",
"method": "resources/list",
"params": {
"path": "workspace/"
},
"id": 201
}Client request
{
"jsonrpc": "2.0",
"result": {
"resources": [
{
"name": "workspace/config.yaml",
"type": "file",
"size": 1024,
"description": "Project database connectivity."
}
]
},
"id": 201
}Server response
Example: Analyzing Configuration
Continuing from the above tools/call response, the AI, having seen the test fail, decides it needs to check the configuration.
Host's Reasoning: "The error might be a config setting. I need to read config.yaml."
Client Request: The Client requests the content from the File System Server.
{
"jsonrpc": "2.0",
"method": "resources/get",
"params": {
"name": "workspace/config.yaml"
},
"id": 102
}
Server Response: The Server retrieves the file content and returns it as a string.
{
"jsonrpc": "2.0",
"result": {
"content": "database_url: 'production'\nport: 8080\nmax_threads: 4"
},
"id": 102
}
The Host/LLM now has the file content directly in its context window to analyze for potential issues.
Prompts (how should the AI prompt be shaped?)
Prompts are standardized templates or structural guidance provided by the Server. They are not data to be processed, but scaffolding for the interaction itself. They ensure that an agent interacting with a specialized server uses the correct tone, format, or persona.
Prompt Discovery
{
"jsonrpc": "2.0",
"id": 1,
"method": "prompts/list",
"params": {
"cursor": "optional-cursor-value"
}
}Client request
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"prompts": [
{
"name": "security_review_persona",
"title": "Request Code Review",
"description": "Asks the LLM to analyze code and look for SQL injection vulnerabilities",
"arguments": [
{
"name": "code",
"description": "The code to review",
"required": true
}
]
}
],
"nextCursor": "next-page-cursor"
}
}Server response
Example: A Security Review Server might expose a prompts/security_review_persona resource. When retrieved, the Host injects this text into the LLM's system message: "You are a senior security auditor. Your job is to find SQL injection vulnerabilities. Be concise and use OWASP terminology."
{
"jsonrpc": "2.0",
"id": 2,
"method": "prompts/get",
"params": {
"name": "security_review_persona",
"arguments": {
"code": "def hello():\n print('world')"
}
}
}Client request
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"description": "Code review prompt",
"messages": [
{
"role": "user",
"content": {
"type": "text",
"text": "You are a senior security auditor. Your job is to find SQL injection vulnerabilities. Be concise and use OWASP terminology. Please review this Python code:\ndef hello():\n print('world')"
}
}
]
}
}Server response
Bi-Directional Communication: Server Calls the Host
In a major departure from traditional client-server models, MCP is bi-directional. This means the Server is not just a passive executor; it can initiate requests back to the Client/Host. This capability is important because the intelligence (Host) is separate from the execution environment (Server).
The Server can request two key actions from the Host-side LLM:
Sampling (sampling/complete): Extending AI to the MCP Server
This enables the MCP Server to leverage the general intelligence of the Host's LLM without requiring the integration of its own separate LLM library.
Example: Server-Side Log Summarization
Server’s Task: A Log Analysis Server collects 1,000 lines of complex, raw log data. It is not an LLM, but it needs a quick summary.
Server Request (to Client): The Server sends the logs back to the Host with a request for completion.
{
"jsonrpc": "2.0",
"method": "sampling/complete",
"params": {
"prompt": "Summarize the attached raw logs (1000 lines) to identify the single most probable root cause of the system crash. Output a brief JSON object: {\"cause\": \"...\"}"
},
"id": 201
}
Host/LLM Response (to Server): The Host’s LLM processes the data and returns a highly structured summary directly to the Server.
{
"jsonrpc": "2.0",
"result": {
"completion": "{\"cause\": \"Uncaught exception in Thread-5, due to a file handle leak in the data processing pipeline.\"}"
},
"id": 201
}
The Server can now use the summary to complete its task.
Elicitation (elicitation/request): User-In-The-Loop
This enables the Server to pause execution and request immediate clarification or confirmation directly from the end-user, routing the message through the Host's UI. This is non-negotiable for safety and critical operational decisions.
This allows MCP to bring the user into the execution loop (User-In-The-Loop) rather than just being an observer, only involved in the case of errors or failures (User-On-The-Loop).
Example: Critical Confirmation
Server’s Concern: A Database Server receives an AI request to perform a non-reversible DROP TABLE operation on a production database.
Server Request (to Client): The Server enforces a safety check and requests user confirmation.
{
"jsonrpc": "2.0",
"method": "elicitation/request",
"params": {
"text": "SECURITY ALERT: AI requested to delete table 'customer_records'. This action is irreversible. Confirm with 'YES' or cancel with 'NO':"
},
"id": 202
}
User/Host Response (to Server): The Host displays the alert, and the user enters "NO." The Client sends the response back to the Server.
{
"jsonrpc": "2.0",
"result": {
"response": "NO"
},
"id": 202
}
The Server receives the cancellation and safely aborts the dangerous command, preventing a catastrophic error.
The Blueprint for Autonomous Agents
The Model Context Protocol is an early solution to scaling agents and connecting them to the real world. By mandating a separation of concerns between the Host (reasoning) and the Server (execution), it enables complexity to be managed simply. By defining Tools for action and Resources for context, it provides a universal API for interacting with environments. And by embracing bi-directionality, it facilitates the interaction necessary for truly autonomous agents.