OpenAI with MCP (Model Context Protocol)
MCP is the open standard that lets any AI app plug into external tools and data through reusable servers — the same servers work across vendors. This chapter is the OpenAI counterpart to the Claude-with-MCP lesson: what MCP is, how Codex consumes MCP servers, and when to reach for MCP versus hand-wiring function calls.
Learning objectives
- Explain what MCP is and the integration problem it solves.
- Describe the architecture: servers, clients, and transports.
- Wire an MCP server into Codex via
~/.codex/config.toml. - Decide between MCP and raw function-calling for a given need.
- Reason about trust and security when adding third-party servers.
1 · What MCP is & the problem it solves essential
Here's the mess MCP was invented to clean up. Before it, every AI app wired up every tool by hand: your agent needed custom glue code to read files, another chunk for GitHub, another for your database — and the next app re-wrote all of it from scratch, in its own incompatible way. N apps times M tools meant N×M bespoke integrations, each one a little snowflake nobody else could reuse.
The Model Context Protocol (MCP) is a single open standard — originally from Anthropic, now broadly adopted across the industry — that turns that N×M mess into N+M. A tool is exposed once as an MCP server (a filesystem server, a GitHub server, a Postgres server), and any MCP-aware client — Codex, Claude, an IDE — can use it without custom glue. The analogy that sticks: MCP is the USB-C of AI tools. Before USB-C, every device had its own charger; after, one port fits everything. MCP is that universal port between AI apps and the tools/data they need.
The common mistake is assuming MCP is an OpenAI thing or an Anthropic thing you have to pick sides on. It isn't — it's a shared protocol. A server someone wrote for Claude works for Codex unchanged. That portability is the whole point, and it's why learning MCP once pays off across every vendor you'll ever use.
- The left column is MCP clients — the AI apps (Codex, Claude, your IDE) that want to use tools.
- The right column is MCP servers — each wraps a capability (files, GitHub, a database) and exposes it in the standard shape.
- The middle box is the protocol itself: because everything speaks it, any client connects to any server — the arrows cross freely.
In short: write (or install) a server once, and every MCP-aware client can use it — that reuse is the entire value proposition.
2 · Architecture: servers, clients, transports essential
MCP has three moving parts. A server exposes capabilities — most importantly tools (functions the model can call), plus resources (data it can read) and prompts (reusable templates). A client is the AI app (here, Codex) that connects to servers and makes their capabilities available to the model. And a transport is how the two talk: stdio (the client launches the server as a local subprocess and talks over standard input/output — the common local case) or HTTP/SSE (a remote server over the network).
The mental model: an MCP server is a little adapter that knows how to do one category of thing and announces its tools in a standard way. When Codex starts, it launches or connects to the servers you configured, asks each "what can you do?", and folds those tools into what the model can call — no per-tool code on your side.
3 · Wiring an MCP server into Codex intermediate
This is the concrete payoff — three lines of config and your agent gains a whole toolset. Codex reads MCP server definitions from ~/.codex/config.toml. Each server is a [mcp_servers.<name>] table with the command to launch it and its args. On startup Codex runs that command, speaks MCP to the resulting process over stdio, and exposes its tools to the model.
~/.codex/config.toml# a filesystem server — lets the agent read/write a specific dir
[mcp_servers.filesystem]
command = "npx"
args = ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/project"]
# a GitHub server — issues, PRs, repo search
[mcp_servers.github]
command = "npx"
args = ["-y", "@modelcontextprotocol/server-github"]
- Each
[mcp_servers.<name>]table names one server (filesystem,github) and tells Codex how to launch it. command+argsare the literal process invocation — herenpxfetches and runs a published MCP server package over stdio.- When Codex starts, it launches each server, asks what tools it exposes, and makes them available to the model — you wrote no tool code, just this config.
Try this: add just the filesystem server, launch codex, and ask it to summarize the files in the directory — it'll use the server's tools rather than raw shell access. Scope the path tightly; the server can only reach what you point it at.
config.toml.4 · What a server exposes: tools, resources, prompts advanced
A server's tools are the headline — callable functions with a name, description, and JSON-schema arguments, exactly the shape the model needs to decide when to call them. But MCP standardizes two more things worth knowing. Resources are readable data the server offers (files, records, documents) that the client can pull into context. Prompts are reusable, parameterized templates the server ships so a client can offer "canned" expert workflows without you writing the prompt.
Why this matters: because all three are described in a standard way, the client can discover them at connect time. The model doesn't need you to hard-code "this server has a search_issues tool" — it asks the server and finds out. That discovery is what makes MCP servers drop-in: install one, and its tools simply appear.
5 · MCP vs raw function-calling advanced
You've already seen tools the hard way. In the OpenAI API chapter (ox2) you hand-wrote a tool: a flat {"type":"function",…} dict, a dispatch function, the function_call → function_call_output loop. That's the right tool for a bespoke capability unique to your app. MCP is for the reusable ones. The two aren't rivals — they're different layers.
The decision rule: hand-wire a function call when the tool is specific to your product (your pricing logic, your internal API) and lives inside your codebase anyway. Reach for an MCP server when the capability is general and reusable (filesystem, GitHub, Postgres, Slack) — someone has likely already written and hardened the server, and you get it across every client with zero glue. Under the hood an MCP tool still surfaces to the model as a callable tool; MCP just standardizes the server side so you're not re-implementing the same integration in every app.
| Use… | When |
|---|---|
| Raw function-calling (ox2) | The tool is bespoke to your app — your logic, your internal API, in your codebase. |
| An MCP server | The capability is general and reusable (files, GitHub, DB) — install a hardened server, reuse across clients. |
6 · Trust & security professional
An MCP server is third-party code you're giving your agent permission to run. That's powerful and it's a real attack surface. A malicious or compromised server could exfiltrate data it's granted access to, or return tool descriptions crafted to manipulate the model (a prompt-injection vector). The same discipline from the Codex safety model (ox3) applies: least privilege and review.
Concretely: install servers only from sources you trust; scope each server to the minimum it needs (point the filesystem server at one project directory, not your home folder); keep tokens and secrets in environment variables, never in config.toml; and remember that Codex's sandbox and approval dials still bound what any MCP-provided tool can ultimately do. MCP widens what your agent can reach — your sandbox and approvals decide what it's allowed to.
7 · The ecosystem & portability tech-lead
The strategic reason to adopt MCP is portability. Because the protocol is vendor-neutral, the servers your team builds or adopts aren't locked to one model provider. The same filesystem, database, and internal-API servers work whether a given workflow runs on Codex, on Claude, or in an IDE — which means your tool investment survives a model-vendor switch. That's a genuine architectural hedge in a fast-moving market.
For a team, the move is to treat MCP servers as shared infrastructure: a vetted internal registry of servers (with scoped credentials and pinned versions) that any approved client can consume, rather than each project re-wiring its own tool glue. You build the integration once, harden it once, and every agent — regardless of vendor — benefits. That's the same N+M win from section 1, applied to your own organization.
🪜 Practice ladder beginner → industry
- Beginner: explain, in one sentence each, what an MCP server, client, and transport are.
- Easy: add a filesystem MCP server to
~/.codex/config.tomlscoped to one directory. - Core: ask Codex a task that uses the server's tools and confirm it discovered them automatically.
- Stretch: add a second server (e.g. GitHub) and have the agent use both in one task.
- Hard: take a bespoke tool you hand-wired in ox2 and decide — with reasons — whether it should become an MCP server.
- Industry: sketch a team MCP policy: a vetted server registry, scoped credentials, version pinning, and how it composes with ox3's sandbox/approval dials.
✓ Checkpoint — you can move on when you can…
- Explain what MCP is and the N×M→N+M problem it solves.
- Describe servers, clients, and the stdio vs HTTP transports.
- Wire an MCP server into Codex via
config.toml. - Choose between MCP and raw function-calling, and reason about server trust.
Knowledge check check yourself
How does OpenAI's Codex CLI connect to an MCP server, and why is MCP described as vendor-neutral?
Show answer
~/.codex/config.toml — each is a [mcp_servers.<name>] table with a command and args that Codex runs to launch the server (usually over stdio). MCP is vendor-neutral because it's an open standard: the same server works unchanged across clients (Codex, Claude, IDEs), so a tool written once is reusable everywhere — the N+M win.When should you reach for an MCP server versus hand-wiring a function call, and what's the main security concern?