Special Topic · Inside OpenAI Codex

MCP comes in: the model sees translated names

When Codex takes an external MCP, tools pass a translation layer before the model sees them: prefix, sanitize, hash on collision. The skill catalog stays up; the body arrives only when named

THE QUESTION THIS PAGE ANSWERS

ANSWER FIRST

What is the key idea behind “MCP comes in: the model sees translated names”?

When Codex takes an external MCP, tools pass a translation layer before the model sees them: prefix, sanitize, hash on collision. The skill catalog stays up; the body arrives only when named

DECISION RULE

Follow the handoffs, not the demo. A system becomes dependable at the boundaries between model, tools, state, permissions, and people. Read each handoff as a place where you can observe, test, and recover.

TRY NEXT

Name the input, owner, approval, and recovery action for one automated step.

WATCH FOR

A successful run that cannot explain what happened or be safely repeated.

Course goalAfter this you can name three things. When Codex is the client, how an external tool becomes a model-visible name. When two shops collide after sanitizing, how they disambiguate. Why the skill catalog does not care whether MCP is alive.
Try it first · One shop comes in: how the name changes
One MCP server comes in: how a tool becomes a capability the model can see
Hookup scene
The two right-hand modes collide. Flip them and see who gets a hash after sanitizing.
Outside · raw tools/listIn the door 0
Nobody is hooked up yet.
In front of the model · translated namesVisible 0
The list is empty.
Logic trail · each animation step maps to a source span
  1. The connection set is published whole; existing bindings keep their own connectionruntime.rs L246
  2. Each shop’s tools/list is merged into one table, then handed to name translationtool_catalog.rs L153
  3. Give the namespace the historical prefix mcp__tools.rs L228
  4. Illegal characters become underscores; only letters, digits, and _ remainmcp/mod.rs L477
  5. Identical raw identities drop one copytools.rs L134
  6. After sanitizing, a namespace collision appends 12 SHA-1 hex digitstools.rs L166
  7. After sanitizing, a tool-name collision gets the same 12-digit hashtools.rs L193
  8. Over 128 bytes together, truncate then hash; protocol calls still use the original nametools.rs L226
Hit Play. Watch how a tool name becomes a capability the model can see after one shop hooks up.
Two layers of namesLeft is the protocol original; right is the translation the model sees. Calling back walks the left side, so a hash on the right does not send you into the wrong shop.
Hash only on collisionTwo clean shops get no suffix. The hyphen and tool-name modes only collide after sanitizing. The hash is disambiguation, not decoration.
Edit the second shop yourselfIn the hyphen mode, change the shop name to the same sanitized letters as the first shop, and you’ll see the namespace split apart.
Teaching sketch:The hash takes the first 12 hex digits; the algorithm is SHA-1. The demo uses a fixed teaching suffix. Line numbers map to openai/codex commit 4f39251a01.
Idea 1 · One list for the outside, another for the inside
What problem it solves

You write codex mcp-server into Cursor’s MCP config. Cursor is the client; Codex is the server. If this tools/list also hands out internal GitHub tools, one IDE call touches internal capability. The permission boundary grows from “call Codex once” into “call internal tools directly.”

What the idea is

The crate splits into two. mcp-server reads lines from stdin, one JSON per line. initialize only opens tools. tools/list hardcodes two names: codex and codex-reply. codex will start_thread; the nested thread starts its own McpRuntime. codex-mcp owns the connection set; tools from external servers get a separate catalog.

Source:codex-rs/mcp-server/src/lib.rs lines 131–152; codex-rs/mcp-server/src/codex_tool_runner.rs lines 66–90; codex-rs/codex-mcp/src/runtime.rs lines 88–98

Same JSON-RPC wire protocol; the processors are not the same. Early notes often draw them as two faces of one runtime. In the current source they do not even share a MessageProcessor.

Source:codex-rs/mcp-server/src/message_processor.rs lines 274–277; codex-rs/mcp-server/src/message_processor.rs lines 336–348

The door the IDE sees Cursor MCP client mcp-server codex · codex-reply nested thread One tools/call becomes one session External shops seen inside the session McpRuntime The connection set can be replaced whole GitHub mcp__github__* Docs mcp__docs__* Home-grown HTTP mcp__http__*
Teaching diagram:Above: two doors handed to the IDE. Below: the external tool catalog inside the session.
Why it lasts

Split the outward promise from inward capability — that is the usual gateway shape. In another language it is still two functions: hosted returns run / continue, external returns mcp__*. The IDE only sees the door; the session is where the external shops appear.

Idea 2 · What the model sees is a translated name
What problem it solves

Both shops report search; the prefix can still split them. One is basic-server, one is basic_server. After hyphens become underscores, the namespaces collide. The model sees two same-named tools and the next call does not know which shop to enter. The API also has a byte cap.

What the idea is

When a server hooks up, each shop’s tools/list is first merged into one table, then sent through normalize_tools_for_model_with_prefix. The order is a fixed four steps.

1. Prefix the namespace with mcp__.

2. Illegal characters become underscores; only letters, digits, and _ remain.

3. Identical raw identities drop one copy. If namespace or tool name still collide after sanitizing, append 12 SHA-1 hex digits.

4. Over 128 bytes together, truncate then hash. The original server_name and tool.name stay on ToolInfo; protocol calls use the original names.

Source:codex-rs/codex-mcp/src/tools.rs lines 105–117; codex-rs/codex-mcp/src/tools.rs lines 134–137; codex-rs/codex-mcp/src/tools.rs lines 166–194; codex-rs/codex-mcp/src/tools.rs lines 226–227; codex-rs/codex-mcp/src/mcp/mod.rs lines 477–485

Raw identity server + tool.name Sanitize mcp__ plus underscores Disambiguate Hash only after a collision In front of the model Unique and short enough Protocol calls still carry the original name The translation layer is only for the model to read; addressing still uses server_name and tool.name
Teaching pipeline:The name the model sees and the name you call back with are two layers.
The model sees a translation. Calling back walks the original name.
Why it lasts

The name the model sees and the name on the wire were always two layers. One is for humans and the API; one is for addressing. Hashing to disambiguate is the usual answer to collisions. The cap number may change; this translation layer will not.

Idea 3 · The catalog stays up; the body arrives when named
What problem it solves

If the catalog were filtered by MCP liveness, for those cold-start seconds the model would think the skill does not exist, then it would pop up next turn. Pouring the whole manual into every turn would also eat the context.

What the idea is

The mention mark is $. The catalog only looks at enabled and prompt_visible. When the user names it, or the task matches the description, this turn reads the SKILL.md body. A Guardian review session returns empty injection; a $skill in the parent transcript cannot trigger a new manual.

Source:codex-rs/skills/src/mentions.rs line 41; codex-rs/ext/skills/src/catalog.rs lines 261–263; codex-rs/core/src/session/turn.rs lines 766–770; codex-rs/core/src/session/turn.rs lines 808–817

If MCP is missing, ask a person. First-party and the feature flag on is what pops Install MCP servers. Approval Never skips silently. If the user picks Continue anyway, the catalog stays; the matching tools may still be unavailable.

Source:codex-rs/core/src/mcp_skill_dependencies.rs lines 47–60; codex-rs/core/src/mcp_skill_dependencies.rs lines 268–270

Why it lasts

Discovery and readiness are two facts. Give the index first, the full text on demand, and ask a person when a dependency is missing — do not wipe the entry from the catalog. Install or not is a config change; list or not is discovery.

Side-by-side · Another answer to the same question

DSH: only bridge tools, one plugin per server

DSH’s MCP client hardcodes the scope: connect one external server, register tools on ctx.tools, public name mcp__<serverName>__<rawName>. The clean case concatenates as-is. If characters or length were rewritten, append 12 SHA-256 hex digits. Cap is 64 characters. Uninstall disconnects, unregisters, and frees the namespace.

Source:packages/mcp/mcp-client/src/index.ts lines 1–14; packages/mcp/mcp-client/src/tools.ts lines 96–102

No elicitation, and it does not hand itself out as an MCP server. An external tool failure is still an ordinary tool failure. The hash length happens to be 12 too; the algorithm and join rules differ.

Checked against source · 2026-08-22 · DSH · MCP and extensions

Claude Code: a skill is a first-class tool

Claude Code gives the model a Skill tool. The model calls before it gets the body. A comment says only one skill runs at a time, because the tool expands the command into a full prompt.

Source:restored-src/src/tools/SkillTool/SkillTool.ts lines 331–344

An MCP prompt only enters the discovery list if it is marked loadedFrom === 'mcp' and type === 'prompt'. The direction flips: Codex skills need MCP; Claude Code MCP contributes skills. The trigger differs too. Codex scans $name and, on a hit, injects <skill> without a tool call.

Source:restored-src/src/tools/SkillTool/SkillTool.ts lines 81–94

Checked against source · 2026-08-22
Classroom Exercise
01

After sanitizing, who still knows this shop

basic-server reports lookup; basic_server reports query. Write the two namespaces the model sees, and say what still sends a call back into the right shop.

Then ask: flip approval to Never and type $deploy — is the skill catalog still there? Watch is_model_visible and should_install_mcp_dependencies.

Takeaway:Hand the outside only two doors; keep a separate external catalog inside. The model sees translated names; collisions get a hash; originals stay for the protocol. The skill catalog stays up, the body arrives when named, and a missing MCP asks a person.

The handoffs inside “Try it first · One shop comes in: how the name changes”

“You write codex mcp-server into Cursor’s MCP config.” shows that an Agent is not defined by the model alone. Each handoff between model, context, tools, state, permissions, and people affects both progress and recovery.

Write the state before adding capability

Starting from “The crate splits into two.”, split the workflow into starting state, next action, tool result, state update, and stop condition. Debugging then means finding the first lost piece of information or authority instead of saying vaguely that the model “got worse”.

  • The connection set is published whole; existing bindings keep their own connection runtime.rs L246
  • Each shop’s tools/list is merged into one table, then handed to name translation tool_catalog.rs L153
  • Give the namespace the historical prefix mcp__ tools.rs L228

A happy path is not reliability

Use “Then ask: flip approval to Never and type $deploy — is the skill catalog still there?” to replay one successful and one failed run. Record the context, tool result, and owner at each turn; the workflow is maintainable when a second person can follow it without the original builder.

From “Try it first · One shop comes in: how the name changes” to “Idea 1 · One list for the outside, another for the inside”

“Try it first · One shop comes in: how the name changes” grounds the problem in “One MCP server comes in: how a tool becomes a capability the model can see Play Step Reset Hookup scene Two clean shops Hyphen twins Tool-name twins The two right-hand modes collide. Flip them and see who gets…”. “Idea 1 · One list for the outside, another for the inside” then moves it toward “You write codex mcp-server into Cursor’s MCP config. Cursor is the client; Codex is the server. If this tools/list also hands out internal GitHub tools, one IDE call touches internal capability. The permission…”. Together, they show that the lesson is not just a conclusion to remember, but a claim with conditions.

Carry the judgment into the next situation

When analyzing an Agent, trace state, action, tool result, and next step in order. Each handoff should explain where information came from, who confirmed it, and where failure stops.

  • “Try it first · One shop comes in: how the name changes”: One MCP server comes in: how a tool becomes a capability the model can see Play Step Reset Hookup scene Two clean shops Hyphen twins Tool-name twins The two right-hand modes collide. Flip them and see who gets…
  • “Idea 1 · One list for the outside, another for the inside”: You write codex mcp-server into Cursor’s MCP config. Cursor is the client; Codex is the server. If this tools/list also hands out internal GitHub tools, one IDE call touches internal capability. The permission…
  • “The closing point”: Identical raw identities drop one copy tools.rs L134

The final “The closing point” brings the discussion to “Identical raw identities drop one copy tools.rs L134”. The useful thing to carry forward is knowing which judgments must be revisited when input, scale, or risk changes.

Mark as learned Your reading progress updates automatically
← PreviousNext →

Keep reading

The next useful article in the thread.

ARTICLE DISCUSSION

Leave one useful thought here.

Keep the idea that clicked, the question that stayed open, or a small note for the next learner.

Discussing MCP comes in: the model sees translated names Inside OpenAI Codex
3discussionsArticle discussion · synced with the Circle
View in the learning circle
AM
Asha MorganContent editor
INSIGHTField note

I turned one judgment from this article into a small experiment I could run today. Knowing what to observe next is more useful than simply remembering the conclusion.

ARTICLE DISCUSSION7 helpful
LH
Lin HarperIndie developer
INSIGHTInsight

After reading this, I first looked for the conditions behind the idea instead of copying the method into a project. That order made the later trade-offs much clearer.

ARTICLE DISCUSSION5 helpful
KM
Kiki MooreProduct operations
QUESTIONQuestion

When this judgment reaches real work, which constraint should be added first? I am curious which step matters most between reading and the first practical attempt.

ARTICLE DISCUSSION4 helpful