MCP is the protocol layer that connects external capability to an AI application, and for agent builders it has become the standard way to say "this agent can reach that system." The useful way to learn it is not from a setup tutorial but from its structure: an AI application acts as a host, the host creates one client per server it connects to, and each server exposes a small set of primitives. Understanding those primitives tells you what a server can read, what it can do, and therefore what you are agreeing to when you connect it. That is the audit question, and it comes before the installation question.
The structure below follows the official architecture overview, with the configuration side verified against the Codex manual. Check both against their current pages before you connect anything.
The participants, and why the distinction matters
The protocol defines three roles, and mixing them up is the most common source of confusion.
The host is the AI application itself, the thing that coordinates one or more clients. The client is a component inside the host that maintains a connection to one server and obtains context from it. The server is the program that provides that context. The rule that makes the architecture click: the host creates one client for each server it connects to, and each client keeps its own dedicated connection.
The official example is a good one. Visual Studio Code acts as an MCP host. When it connects to a remote server such as Sentry, its runtime instantiates a client for that connection. When it also connects to a local filesystem server, it instantiates an additional client for that connection. One application, several servers, one client each.
The second clarifying point is vocabulary. A server is called a server because of its role, not because of where it runs. The architecture page is explicit that a server refers to the program that serves context data regardless of location: one that runs on the same machine over the stdio transport is a local server, and one that runs on a platform over the Streamable HTTP transport is a remote server. The distinction that matters is the transport, and the risk profile follows it.
The two layers under the label
MCP is described as two layers, and the split explains why the same protocol works across very different deployments.
The data layer defines a JSON-RPC based protocol for client-server communication. It covers capability and version discovery, including the mandatory server/discover request, and the core primitives: tools, resources, prompts, and notifications. This is the layer that defines what can be shared and what can be asked for.
The transport layer defines the communication mechanisms and channels: connection establishment, message framing, and authorization. It is, in the documentation's framing, the outer layer that carries the inner one.
Because the data layer is independent of transport, switching from a local process to a remote endpoint does not change the protocol messages. The same requests and the same primitives arrive; only the pipe changes. That is convenient for portability, and it is also why "it uses the same protocol" says nothing about the security posture, which lives in the transport and in the permissions around it.
The primitives, and the audit priority they imply
Servers expose primitives, and the primitives differ in what they let an agent do. The official definitions are short and worth keeping exact.
Tools are executable functions that AI applications can invoke to perform actions, such as file operations, API calls, or database queries. This is the primitive with side effects, and it is the one that deserves the most scrutiny: a tool that can write, delete, send, or pay is a different risk class from one that only reads.
Resources are data sources that provide contextual information, such as file contents, database records, or API responses. Resources are about what the agent gets to see, so the audit question is scope: which directory, which table, which records.
Prompts are reusable templates that help structure interactions with language models, such as system prompts and few-shot examples. Prompts shape behavior, but they do not reach outside the conversation the way a tool call can.
Discovery works through the matching list methods, and execution through the tool call method, which is why listings can change at runtime: a server can add or remove tools, and clients are expected to rediscover rather than assume a fixed catalog. For an auditor, that has a direct consequence: what you reviewed on installation day is not necessarily what the server offers next month, so re-check after updates.
Transports, and the different risks they carry
The transport layer offers two mechanisms, and their risk profiles differ more than their message formats do. The distinction stdio vs Streamable HTTP is less about what travels than about where it travels.
Stdio transport uses standard input and output streams for direct process communication between local processes on the same machine, with no network overhead. Local servers on this transport typically serve a single client. The risk here is machine access: the server runs as a process on your machine and can reach whatever the process is permitted to reach.
Streamable HTTP transport uses HTTP POST for client-to-server messages, with optional Server-Sent Events for streaming, and enables remote server communication. It supports standard HTTP authentication methods including bearer tokens, API keys, and custom headers, and the protocol recommends using OAuth to obtain authentication tokens. The risk here shifts to credentials and data egress: which token the server receives, what scopes it carries, and what leaves your network on each call.
Neither transport is inherently the safe one. A local server with broad filesystem access can do more damage than a remote read-only endpoint, and a remote server with a broad OAuth scope can reach more of your data than a narrowly scoped local one. The audit is about the specific server, not the category.
What MCP does not do
The scope note in the official documentation is worth quoting because it prevents a common over-expectation: MCP focuses solely on the protocol for context exchange, and it does not dictate how AI applications use language models or manage the provided context.
In practical terms: connecting a server does not change how well the agent reasons; it changes what the agent can reach. The reasoning, prompting, and context management stay in the host application, and the quality of the outcome depends on those, not on the protocol. This article's neighbors make the point from other angles: the Agent Skills standard covers packaged procedural knowledge, and the two standards are complementary rather than competing.
Wiring one up in Codex, and where the approval lives
The configuration side is where auditing becomes concrete. In Codex, MCP servers are declared under [mcp_servers.<id>] in the config file. A local stdio server is described with command and args; a remote Streamable HTTP server uses url. The manual also documents identity.url for constraining which remote endpoint is allowed, scopes for the OAuth scopes to request, oauth.callback_port for the local callback listener, and env_http_headers for headers populated from environment variables.
The key that turns a connection into an enforceable policy is per-tool approval. The manual documents mcp_servers.<id>.tools.<tool>.approval_mode, with values including auto, prompt, writes, and approve, so a single high-risk tool can require approval while the rest of the server stays convenient. That is the difference between "we connected a server" and "we connected a server and decided what it may do without asking." Which configuration layer wins when the same setting appears in several places is covered in the config precedence guide, and the provider block in the same file is described in the custom provider guide.
A protocol detail worth checking before you copy a tutorial
The protocol is still moving, and one recent change affects older examples. The documentation states that client-side primitives are deprecated as of protocol version 2026-07-28, including Sampling, which let servers request language model completions from the client's application, and Logging, which let servers send log messages to clients. New implementations are directed to integrate with LLM provider APIs directly and to log to stderr or OpenTelemetry instead.
The practical instruction is simple: check which protocol version the tool you are configuring actually speaks, and treat tutorials that use deprecated primitives as historical. A server built around a deprecated client primitive may still run against an older host and fail against a newer one, which looks like a configuration mystery until you know the version story.
The audit checklist
- List every tool the server exposes, and mark the ones that write, delete, send, or pay.
- Check which resources it can read: directories, repositories, database ranges, or records.
- Trace where its credentials come from, and reduce them to the minimum that works.
- For local servers, confirm the command it runs and the paths it can reach.
- For remote servers, confirm the endpoint, the OAuth scopes, and what data leaves your network.
- Set an approval mode for high-risk tools instead of accepting the default for everything.
- In CI and other unattended environments, do not connect high-risk tools by default.
- Log tool calls and their outcomes, with the field discipline from the observability guide, and re-audit after server updates.
Two supporting habits make the checklist stick. Validate a server against a representative task before trusting it broadly, the same way the testing guide treats prompt and model changes. And when a server runs inside a pipeline, treat its permissions as part of the pipeline's attack surface, as the CI guide describes.
MCP is a connection standard, not a safety feature. It makes capability reachable; the audit decides how much of that reach you actually grant. Verify every key name and protocol behavior against the official pages current at build time.