MCP is USB for AI
Before USB, every peripheral spoke a different language. Printers needed parallel ports, mice needed PS/2 connectors, modems needed serial. Then one protocol unified them all: Universal Serial Bus. Plug anything in. It just works.
MCP — the Model Context Protocol — does the same thing for AI agents. It is JSON-RPC 2.0 over stdio. Client asks, server responds. That is the entire specification. No custom adapters, no bespoke integrations, no vendor lock-in.
✗ Without MCP
- Shell commands only
- File read/write
- Patch application
- Hard-coded tools
- No external services
✓ With MCP
- GitHub / GitLab APIs
- Jira / Linear / Notion
- Slack / Discord
- CI/CD pipelines
- Deploy to any platform
- Custom internal tools
- Databases, caches, queues
Key insight: MCP turns Codex from a tool that can only talk to your filesystem into a tool that can talk to anything. One protocol. Any server. Infinite possibilities.
Codex as MCP Client
Codex implements the MCP client side through the rmcp_client crate — a Rust implementation of the Model Context Protocol. The initialization sequence is precise and deterministic:
Architecture: The MCP Pipeline
Each MCP server runs as a separate child process communicating over stdio. This means a crashing server cannot take down Codex. It also means servers can be written in any language — TypeScript, Python, Go, Rust — as long as they speak JSON-RPC 2.0.
Connector Management
MCP server connections are configured in ~/.codex/config.toml. The ConnectorManager handles the lifecycle of every server process, including discovery, caching, and authentication.
Caching (1hr TTL)
Tool discovery results are cached for one hour. After TTL expires, Codex re-queries each server's tool list. This balances freshness with startup speed.
OAuth Handling
ConnectorManager stores OAuth tokens and handles refresh flows transparently. Servers receive fresh tokens on each call without manual re-authentication.
The Skills System
Skills are another axis of extensibility. While MCP servers provide tools (functions Claude can call), skills provide knowledge (instructions injected into the system prompt). Two types exist:
⚙ System Skills
- Embedded in the binary
- Installed via
install_system_skills - Fingerprinted for integrity
- Core capabilities (git, test, etc.)
- Cannot be modified by users
📦 User Skills
- Located in
~/.codex/skills/ - Discovered by Skills Manager
- Written as YAML or TOML
- Custom workflows and prompts
- Hot-reloaded on change
How injection works: The Skills Manager discovers all matching skills, serializes them as YAML/TOML blocks, and injects them directly into Claude's system prompt. Claude sees them as additional instructions, not as tools.
Shell-Tool-MCP Internals
The shell tool — Codex's primary built-in tool — is more sophisticated than it appears. Under the hood, it uses patched Bash binaries compiled for multiple platforms, with an execution interception layer.
Patched Bash Binaries
Codex ships with pre-compiled Bash binaries for darwin-arm64, darwin-x64, linux-arm64, and linux-x64. These are patched versions of Bash that integrate with the execution wrapper system.
Rules Files
Rules files define what each binary can do at three levels:
allow
Command runs immediately without user confirmation. Used for safe, read-only operations like ls, cat, grep.
prompt
Requires explicit user approval before running. Used for write operations like git commit, npm install.
forbidden
Blocked entirely. Cannot run under any circumstances. Used for destructive operations like rm -rf /, :(){ :|:& };:
Complete Tool Call Flow
Every tool invocation follows a precise seven-step pipeline. Watch each step light up to trace a complete call from user input to returned result:
User Sends Message
"Create a Jira ticket for the login bug with priority High"
Claude Generates tool_use
Claude sees Jira tools in context, emits: {"tool": "jira_create_issue", "args": {...}}
Codex Receives & Routes
The tool call is intercepted. Codex looks up which MCP server registered jira_create_issue.
RMcpClient Forwards Call
JSON-RPC message is written to the Jira server's stdin pipe. {"jsonrpc":"2.0","method":"tools/call",...}
MCP Server Executes
The Jira MCP server authenticates, calls the Jira REST API, creates the ticket, receives JIRA-1234.
Result Returns via stdio
Server writes JSON-RPC response to stdout: {"result": {"key":"JIRA-1234","url":"..."}}
Claude Reads Result
The tool result is injected back into the conversation. Claude responds: "Created JIRA-1234 with priority High."
Building Your Own MCP Server
The power of MCP is that anyone can write a server. Here is a minimal Jira connector in TypeScript:
The Ecosystem Vision
Security: The Rules Gauntlet
Extensibility without security is a vulnerability. Every tool call in Codex passes through five layers of defense before execution. Fail any layer, and the call is blocked.
Rules Files
Per-binary allow/prompt/forbidden rules. Loaded from .codex/rules/ and evaluated against the command's executable path and arguments.
Process Sandboxing
MCP servers run as isolated child processes. macOS Seatbelt and Linux seccomp profiles restrict filesystem and network access per-server.
Approval Workflows
Commands classified as "prompt" require explicit user confirmation in the TUI. The flow pauses and waits for [y/n] before proceeding.
Audit Logging
Every tool call is logged with timestamp, arguments, result, and duration. The audit trail is append-only and cannot be modified by the agent.
Token Management
OAuth tokens and API keys are stored in the system keychain, never in environment variables. Tokens are scoped to specific servers and auto-expire.
Defense in depth: These five layers work independently. Even if an attacker compromises one layer (e.g., injects a malicious MCP server), the remaining four layers (sandboxing, approval, audit, token scoping) contain the blast radius.