Blog
What is the Model Context Protocol (MCP)? Architecture, Primitives, and Security
Anthropic designed MCP to turn custom integrations into standard client-server connections, but standardising the wire does not make the boundary safe.
The Model Context Protocol (MCP) is an open standard created by Anthropic, and governed since December 2025 by the Linux Foundation's Agentic AI Foundation, that connects AI models to external tools, data sources, and workflows over a JSON-RPC 2.0 wire protocol. Often described as USB-C for AI applications, it replaces custom point-to-point code with three standardized server primitives: passive read-only resources, executable tools, and parameterized prompts. MCP uses a host-client-server architecture where the client application acts as a strict gatekeeper between the model and local servers. Because local MCP servers run as child processes with the user's filesystem permissions, security depends on explicit human approval loops, process isolation, and keeping credentials out of plain text configuration files.
The N x M integration problem and architecture
Before late 2024, connecting an AI model to an external system required custom glue code for every combination of client and tool.
If you had five agent runtimes and ten developer tools, supporting every pair required writing fifty separate adapters.
Anthropic open-sourced the Model Context Protocol to replace that matrix with a standard client-server architecture.
The pattern divides responsibilities into three distinct roles: hosts, clients, and servers.
The host is the outer application that users interact with, such as Claude Desktop or Forkbench.
The client lives inside the host and maintains a 1:1 connection with a specific server.
The server is a lightweight program that exposes local or remote data and functions through standardized interfaces.
Standardizing the protocol decouples model development from tool creation. An engineer can write a Postgres or GitHub MCP server once, and any compatible agent client can query it immediately.
The core primitives: resources, tools and prompts
A server exposes three primitives that cover how models consume context and execute operations. A fourth, sampling, is on its way out.
- Resources: passive data sources identified by URIs. They work like read-only GET endpoints that provide file contents, database schemas, or API logs without triggering side effects. Clients can subscribe to resource updates to receive notifications when data changes.
- Tools: executable functions that perform side-effecting operations. Each tool publishes an input schema using standard JSON Schema. The host presents these definitions to the model, and the model generates tool calls with specific arguments for the server to execute.
- Prompts: parameterized prompt templates managed by the server. They allow server authors to package reusable workflows, such as git commit review templates or database migration checks, which users can trigger directly.
- Sampling: a reverse channel where the server asks the host to run an LLM completion. The 2026-07-28 revision deprecated it, along with Roots and Logging; it still works during the deprecation window, but new servers are told to call an LLM provider API directly instead.
The wire protocol: JSON-RPC 2.0 and capability negotiation
MCP runs on JSON-RPC 2.0 over two transports: standard input and output (stdio) for local child processes, and Streamable HTTP for remote servers. The older HTTP+SSE transport has been deprecated since the 2025-03-26 revision.
Stdio is the default for local development tools. The host spawns the server as a subprocess and exchanges newline-delimited JSON messages across standard streams.
Until mid-2026 every session opened with an initialize request and an initialized notification. The 2026-07-28 revision removed that handshake and made the protocol stateless: every request now carries its protocol version and client capabilities in _meta, and servers must implement server/discover to advertise their versions, capabilities and identity up front.
Change notifications became opt-in at the same time. A client opens one subscriptions/listen stream naming the types it wants, such as toolsListChanged, and only then does the server push updates like notifications/tools/list_changed, so the client can refresh its registry without restarting the server process.
Security model: the host as gatekeeper and injection risks
The central security rule of MCP is that the model never talks directly to a server. The host application sits between them as a gatekeeper.
An MCP server returns schema definitions and raw data. The host decides what enters the model context, and the host prompts the human before running dangerous tools.
Removing human approval turns any autonomous tool call into an unreviewed action on your operating system.
The primary attack vector against MCP is indirect prompt injection through poisoned context.
If an MCP resource reads an untrusted pull request, an email, or a database record containing hidden instructions, those instructions enter the prompt context.
The model can be misled by the injected text into invoking destructive tools, such as deleting tables or exfiltrating data.
Treating resources as read-only does not eliminate this threat. A read operation can still load malicious instructions that compromise subsequent tool executions.
Multi-agent squads and secret sprawl in MCP configs
Running a single coding agent with local MCP servers is straightforward. Running a multi-agent squad multiplies the operational risks.
Most MCP setups store server configurations in plaintext JSON files on disk. These files typically contain hardcoded API tokens, database connection strings, and cloud credentials.
When you run several agents concurrently, every agent shell and any spawned tool can read those configuration files.
If one agent in the squad gets hijacked by a prompt injection attack, all credentials stored across your local MCP configs are exposed.
Passing secrets as raw environment variables creates the same vulnerability, because child processes inherit the parent environment by default.
The safer architecture separates credential storage from protocol configuration. Forkbench keeps secrets sealed in Vault under hardware-derived keys rather than writing them to disk.
When a command or server needs to call an external API, the credential is bound directly to the outbound request without exposing the raw secret to the agent prompt or configuration file.
Protocol limits and architectural trade-offs
Standardizing communication simplifies tool building, but it introduces distinct operational trade-offs.
Local stdio servers run as independent child processes for every client session. Running five parallel agents that each load heavy language server MCP tools consumes significant local memory and CPU.
Remote Streamable HTTP servers eliminate duplicate local processes, but they reintroduce network latency and require authentication layers that stdio avoids.
Sampling gave servers flexible access to intelligence but created potential recursion loops when a server-initiated prompt triggered secondary tool calls, one reason the 2026-07-28 revision deprecated it.
A protocol standardizes the shape of messages. It does not guarantee that a third-party server binary is safe to run on your Mac.
Related: Agent Client Protocol (ACP) and MCP: architectural differences, MCP server security risks: why secrets leak from config files, Sandboxing AI coding agents on macOS with Seatbelt, Agent-to-Agent Protocol (A2A) for multi-agent systems, Coordinating multi-agent squads on the Teamwork Board
Frequently asked
What is the difference between an MCP resource and an MCP tool?
As defined in the Model Context Protocol specification, a resource is a passive data feed that provides read-only context without side effects, identified by a URI. A tool is an executable function with a JSON schema that performs actions and modifies system state. Tools require execution permissions and human approval because they cause observable changes on the host.
Why does local MCP use stdio instead of localhost HTTP servers?
Stdio allows the host application to spawn the server directly as a child process without opening TCP ports or managing local SSL certificates. The host manages the process lifecycle directly through standard input and output streams using JSON-RPC 2.0. This avoids port conflicts when multiple agents or projects run at the same time.
How does indirect prompt injection affect MCP servers?
Indirect prompt injection occurs when an MCP resource or tool output loads untrusted data containing adversarial instructions (see trapdoor prompt attacks). When the model processes that data as context, it may follow attacker instructions to invoke other tools. The host should enforce human verification on sensitive actions and isolate the process using macOS Seatbelt.
What is MCP sampling and how does it work?
As specified in the Model Context Protocol specification, sampling allows an MCP server to request an LLM completion from the host client during an operation. The server can summarize logs or parse unstructured data without holding its own API keys. The host retains control over whether to grant the request and which model processes it. The 2026-07-28 revision deprecated sampling: it keeps working during the deprecation window, but new servers should call an LLM provider API directly.
Why is storing API keys in MCP configuration files dangerous?
Standard MCP configurations store environment variables and API keys as plaintext inside local JSON files (see MCP config security risks). Any process, script, or agent running in that environment can read those files. If an agent executes an arbitrary shell command or reads the filesystem, those stored credentials can be leaked upstream. Credential brokers like Forkbench Vault eliminate this risk by injecting keys directly into outbound requests.