Skip to content

Connect the exchange-rate API as an MCP server

A few of your transactions are in euros and pounds, stored at whatever rate you eyeballed when you entered them. The monthly report treats those numbers as gospel, so your real spend is off by however much the rate has drifted. The fix is obvious - convert at the actual rate - but Codex can’t do it, because the rate lives at an external HTTP API the agent has no way to call. It can reason about currency all day; it just can’t fetch the number.

That gap is the exact signal for an MCP server. The Model Context Protocol is an open standard for connecting an agent to an external tool or data source; an MCP server is one such connection. Wire the rate API up as a server and Codex gets a new tool - convert one currency to another - that it reaches for on its own, the way it already reaches for shell or file edits. The API stops being something you look up and paste in, and becomes something the agent touches directly.

Codex configures MCP servers in config.toml, under a [mcp_servers.<name>] table. The common shape is a stdio server - a process Codex spawns on your machine and talks to over stdin/stdout. You give it a command and its args:

# ~/.codex/config.toml (or .codex/config.toml in the repo)
[mcp_servers.fx]
command = "npx"
args = ["-y", "your-exchange-rate-mcp-server", "--api-url", "https://<your-rate-api-endpoint>"]

Use the real package and endpoint your rate provider publishes - the values above are placeholders, not a server that exists. The table name (fx here) becomes the prefix on every tool the server exposes, so the model sees something like fx.convert and never collides with another server’s tools.

Servers that live out on the network are reached as a remote server instead, by giving a url in place of command/args. The transport is chosen by which key is present; the official syntax for both shapes, plus auth via named environment variables rather than secrets pasted into the file, is on the Codex MCP docs.

You don’t have to hand-edit the file. The codex mcp subcommand manages servers from the CLI:

codex mcp add fx -- npx -y your-exchange-rate-mcp-server --api-url https://<your-rate-api-endpoint>
codex mcp list # what's registered, connected, or failed
codex mcp get fx # inspect one server
codex mcp remove fx

Read the add form carefully: the bare -- separates the server name from the command Codex will spawn. Everything before it is the name; everything after is the process. Inside a session, /mcp shows the same connection status without leaving the agent.

Now you ask Codex to use it - and on a fresh budgetcli setup, it fails:

> recompute the EUR and GBP transactions at the current rate
● fx.convert { from: "EUR", to: "USD", amount: 4200 }
✗ network error: connection refused
The rate server is registered but I can't reach the network to
call it - the sandbox is blocking the outbound request.

Nothing is wrong with the server. This is the same wall you met back in approvals & sandbox: in workspace-write, network access is off by default. A stdio MCP server runs as a child process inside that sandbox, so when it tries to reach the rate API, the sandbox refuses the connection - exactly as it would refuse the agent’s own curl.

The fix is the one from that chapter: enable network for this workspace deliberately, knowing what you’re opening.

[sandbox_workspace_write]
network_access = true

This is worth sitting with rather than reflexively flipping on. Registering an MCP server does not by itself grant the agent the network - the sandbox still governs reach. That separation is a feature: you decide, per project, whether the convenience of a live API is worth the wider blast radius, instead of a connection silently becoming a hole. For budgetcli, a single read-only rate lookup is an easy yes - but it’s you saying yes, not the server assuming it.

With the network open, the same request goes through, and the copy-paste loop collapses:

> recompute the EUR and GBP transactions at the current rate
● fx.convert { from: "EUR", to: "USD", amount: 4200 }
→ 4557
● fx.convert { from: "GBP", to: "USD", amount: 1899 }
→ 2402
Converted both at the live rate and stored the results as integer
cents, per the AGENTS.md money rule. The March report total drops
by $38 once the stale rates are replaced.

Notice what changed. You asked one question in plain language; Codex called the rate tool twice on its own, applied the cents-not-floats rule from AGENTS.md without being reminded, and reasoned across the result. Nothing was pasted. A live external system is now part of the agent’s working context.

One discipline before you add more servers: every connected server injects its full tool description into context at session start, whether or not you use it. Two or three useful servers cost little; a dozen “might need it someday” servers spend your context budget on capability descriptions before you’ve typed a word. Connect for a concrete gap - the rate API is one - not on spec. Here’s that discipline as a meter - mount and unmount servers and watch what each one costs before your first message:

82k of 200k (41%) spent before your first message
Built-in tools (12k, fixed)MCP tool schemas (70k)

Tool counts and schema sizes are illustrative (~600–800 tokens per tool definition). The shape is the point: every registered server is paid for in window space whether the session uses it or not.

MCP runs the other way too. Everything above pointed Codex outward - it became a client of the rate API. But Codex can itself stand up as a server, exposing its own ability to run a coding task as a tool that some other program calls. The wiring is symmetric; only the direction of the arrow changes.

You make Codex a server with one command:

codex mcp-server

Note the hyphen - it’s codex mcp-server, the inverse of the codex mcp subcommand you used to manage servers above. It runs Codex over stdio, waiting for an MCP client to connect and drive it. The exact handshake and the tools it exposes are on the Codex CLI reference.

For most of your week on budgetcli, it isn’t. You sit at the Codex TUI and Codex is the thing in charge - it’s the host, reaching out to servers like the rate API. Running Codex as a server inverts that: now Codex is the tool, and something else owns the loop. That’s the right shape in a narrow set of cases:

  • Another agent orchestrates, Codex executes. A larger automation - a different agent, or a script you’ve built - owns the high-level plan and wants to hand off a concrete coding task: “regenerate the March report in budgetcli and commit it.” It calls Codex as a server, Codex does the focused work in the repo, and hands back the result. The outer system never has to reimplement what Codex already does well.
  • You want Codex’s repo-scoped work as a callable capability, not an interactive session. Anything that can speak MCP - including agents built on other stacks - can then treat “do a coding task in this repo” as one more tool alongside its others.

The thing to hold onto is that serving Codex is a delegation pattern, not a default. When Codex serves, the caller decides how much rope it gets - the same approval and sandbox dials from the approvals chapter still apply to the work Codex does on the other end of that connection. A server invocation that runs with wide-open approvals on your real budgetcli repo is exactly as dangerous as it sounds, and now there’s no human watching the TUI to catch it. Scope it the way you’d scope any unattended run.

For the work in this course you’ll stay the host - Codex reaching out, not being reached. But knowing the protocol is bidirectional matters the moment you start chaining agents together, which is squarely where the automation chapter heads.

That covers reach in both directions. The other half of this chapter is the opposite instinct: not widening what the agent can do, but drawing a hard line it can’t cross. That’s a hook.