OpenAI Codex · MCP와 Skills

MCP가 들어오면, 모델은 번역된 이름을 봅니다

외부 server의 도구는 모델 눈에 들어가기 전 번역층을 지납니다. skill 목록은 항상 있고, MCP가 없으면 사람에게 따로 묻습니다.

강의 목표읽고 나면 세 가지를 말할 수 있어요. Codex가 client일 때 외부 도구가 어떻게 모델이 보는 이름이 되는지. 두 가게가 세척 뒤 이름이 부딪히면 어떻게 가리는지. skill 목록이 왜 MCP가 살아 있는지를 보지 않는지.
먼저 해보기 · 가게 하나가 들어오면 이름이 어떻게 바뀌나
MCP server 하나가 들어오면, 도구가 모델이 보는 능력이 되는 길
접속 장면
오른쪽 두 칸은 이름이 부딪힙니다. 바꿔 보고, 세척 뒤에 누가 해시를 받는지 보세요.
문밖 · 원본 tools/list입장 0
아직 아무도 안 붙었어요.
모델 눈앞 · 번역된 이름보임 0
목록이 비어 있어요.
로직 궤적 · 애니메이션 각 단계가 소스의 어느 구간에 대응하는지
  1. 연결 집합을 통째로 배포하고, 이미 있는 binding은 자기 연결을 계속 씁니다runtime.rs L246
  2. 각 가게의 tools/list를 한 표로 모은 뒤 이름 번역에 넘깁니다tool_catalog.rs L153
  3. 네임스페이스에 역사 접두사 mcp__를 붙입니다tools.rs L228
  4. 잘못된 문자는 밑줄로 씻고, 글자·숫자·밑줄만 남깁니다mcp/mod.rs L477
  5. 완전히 같은 원본 신원은 한 부를 버립니다tools.rs L134
  6. 세척 뒤 네임스페이스가 부딪히면 끝에 SHA-1 12자리를 붙입니다tools.rs L166
  7. 세척 뒤 도구 이름이 부딪혀도 같은 12자리 해시를 붙입니다tools.rs L193
  8. 합쳐 128바이트를 넘으면 잘라 내고 다시 해시하며, 프로토콜 호출은 원본 이름을 씁니다tools.rs L226
재생을 눌러 보세요. 가게 하나가 붙은 뒤 도구 이름이 모델이 보는 능력이 되는 길을 보여 줍니다.
이름 두 층왼쪽은 프로토콜 원본 이름, 오른쪽은 모델이 보는 번역입니다. 되부를 때는 왼쪽으로 가서, 오른쪽에 해시가 붙었다고 다른 가게로 들어가지 않아요.
부딪혀야 해시깨끗한 두 가게에는 접미사가 안 붙습니다. 하이픈과 도구 이름 칸은 세척 뒤에야 부딪히고, 해시는 장식이 아니라 가림이에요.
둘째 가게를 직접 고치기하이픈 칸에서 가게 이름을 첫째 가게의 세척 뒤 글자와 같게 바꾸면, 네임스페이스가 갈라지는 게 보입니다.
수업용 도해:해시는 앞 12자리이고 알고리즘은 SHA-1이며, 데모는 고정된 수업용 접미사를 씁니다. 행 번호는 openai/codex 저장소 commit 4f39251a01에 대응합니다.
아이디어 1 · 밖에는 목록 하나, 안에는 다른 하나
어떤 문제를 푸는가

codex mcp-server를 Cursor MCP 설정에 넣습니다. Cursor가 client, Codex가 server예요. 이번 tools/list가 내부 GitHub 도구까지 내주면, IDE가 한 번 호출해 내부 능력에 닿습니다. 권한 경계가 “Codex를 한 번 부르기”에서 “내부 도구를 직접 부르기”로 넓어져요.

아이디어는 무엇인가

crate가 두 벌로 갈라집니다. mcp-server는 stdin에서 한 줄에 JSON 하나를 읽어요. initialize는 tools만 엽니다. tools/list는 이름 둘을 박아 둡니다. codexcodex-reply. codexstart_thread하고, nested thread가 자기 McpRuntime을 또 띄웁니다. codex-mcp가 연결 집합을 맡고, 외부 server 도구는 목록을 따로 만듭니다.

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

같은 JSON-RPC 선 프로토콜이지만 처리기는 다릅니다. 초기 자료는 종종 한 runtime의 두 얼굴로 그렸어요. 지금 소스에서는 MessageProcessor조차 공유하지 않습니다.

출처:codex-rs/mcp-server/src/message_processor.rs 274–277행; codex-rs/mcp-server/src/message_processor.rs 336–348행

IDE가 보는 입구 Cursor MCP client mcp-server codex · codex-reply nested thread tools/call 한 번이 세션 하나가 됩니다 세션 안에서 보이는 외부 가게 McpRuntime 연결 집합을 통째로 replace할 수 있어요 GitHub mcp__github__* Docs mcp__docs__* 직접 만든 HTTP mcp__http__*
수업용 구조도:위는 IDE에 넘기는 입구 둘, 아래는 세션 안의 외부 도구 목록입니다.
왜 오래가는가

밖으로 한 약속과 안의 능력을 갈라놓는 것이 게이트웨이의 흔한 모양입니다. 언어를 바꿔도 함수는 둘이에요. hosted는 run / continue를, external은 mcp__*를 돌립니다. IDE는 입구만 보고, 세션 안에서야 외부 가게가 보입니다.

아이디어 2 · 모델이 보는 것은 번역된 이름입니다
어떤 문제를 푸는가

두 가게가 모두 search를 내밀면 접두사로 아직 갈라집니다. 한쪽은 basic-server, 한쪽은 basic_server인데, 하이픈을 밑줄로 씻으면 네임스페이스가 부딪혀요. 모델이 같은 이름 도구 둘을 보면 다음 호출이 어느 가게로 갈지 모릅니다. API에는 바이트 상한도 있어요.

아이디어는 무엇인가

server가 붙으면 각 가게의 tools/list를 먼저 한 표로 모은 뒤 normalize_tools_for_model_with_prefix를 탑니다. 순서는 고정된 네 걸음이에요.

1. 네임스페이스에 mcp__ 접두사를 붙입니다.

2. 잘못된 문자는 밑줄로 씻고, 글자·숫자·_만 남깁니다.

3. 완전히 같은 원본 신원은 한 부를 버립니다. 세척 뒤 네임스페이스나 도구 이름이 또 부딪히면 끝에 SHA-1 12자리를 붙입니다.

4. 합쳐 128바이트를 넘으면 잘라 내고 다시 해시합니다. 원본 server_nametool.nameToolInfo에 남고, 프로토콜 호출은 원본 이름을 씁니다.

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

원본 신원 server + tool.name 세척 mcp__와 밑줄 가림 부딪힌 뒤에 해시 모델 눈앞 유일하고 충분히 짧음 프로토콜 호출은 원본 이름을 달고 갑니다 번역층은 모델이 보게만 하고, 주소는 여전히 server_name과 tool.name으로 갑니다
수업용 파이프라인:모델이 보는 이름과 되부를 때 쓰는 이름은 두 층입니다.
모델이 보는 것은 번역이고, 되부를 때는 원본 이름으로 갑니다.
왜 오래가는가

모델이 보는 이름과 프로토콜 이름은 원래 두 층입니다. 한 층은 사람이 읽고 API가 쓰고, 한 층은 주소를 찾습니다. 해시로 가리는 것은 이름 충돌의 흔한 답이에요. 상한 숫자는 바뀔 수 있지만, 이 번역층은 안 바뀝니다.

아이디어 3 · 목록은 항상 있고, 이름을 불러야 본문이 옵니다
어떤 문제를 푸는가

MCP가 살아 있는지로 목록을 걸러면, 콜드 스타트 몇 초 동안 모델은 skill이 없다고 생각하고, 다음 라운드에 갑자기 나타납니다. 설명서를 매 라운드에 통째로 넣으면 컨텍스트도 다 먹혀요.

아이디어는 무엇인가

호명 기호는 $입니다. 목록은 enabledprompt_visible만 봅니다. 사용자가 이름을 부르거나 과제와 설명이 맞을 때, 이번 라운드가 SKILL.md 본문을 읽어요. Guardian 심사 세션은 빈 주입을 바로 돌리고, 부모 transcript의 $skill은 새 설명서를 다시 트리거하지 못합니다.

출처:codex-rs/skills/src/mentions.rs 41행; codex-rs/ext/skills/src/catalog.rs 261–263행; codex-rs/core/src/session/turn.rs 766–770행; codex-rs/core/src/session/turn.rs 808–817행

MCP가 없으면 사람에게 따로 묻습니다. first-party이고 기능 스위치가 켜져야 Install MCP servers가 뜹니다. 승인이 Never면 조용히 건너뛰어요. 사용자가 Continue anyway를 골라도 목록은 남고, 해당 도구는 여전히 못 쓸 수 있습니다.

출처:codex-rs/core/src/mcp_skill_dependencies.rs 47–60행; codex-rs/core/src/mcp_skill_dependencies.rs 268–270행

왜 오래가는가

발견과 준비는 다른 일입니다. 색인을 먼저 주고, 전문은 필요할 때 주며, 의존성이 없으면 사람에게 묻고, 목록에서 항목을 지우지 마세요. 설치 여부는 설정 변경이고, 올릴지 여부는 발견입니다.

가로 비교 · 같은 문제에 대한 다른 답

DSH: tools만 다리 놓고, 플러그인 하나가 server 한 대

DSH MCP 클라이언트는 범위를 박아 둡니다. 외부 server 한 대에 연결하고, 도구를 ctx.tools에 등록하며, 공개 이름은 mcp__<serverName>__<rawName>예요. 깨끗한 경우는 그대로 이어 붙입니다. 문자나 길이가 바뀌었으면 끝에 SHA-256 12자리를 붙입니다. 상한은 64자. 제거하면 끊고, 등록을 지우고, 네임스페이스를 놓습니다.

출처:packages/mcp/mcp-client/src/index.ts 1–14행; packages/mcp/mcp-client/src/tools.ts 96–102행

elicitation도 없고, 자신을 MCP server로 내주지도 않습니다. 외부 도구 실패는 평범한 tool 실패로 처리해요. 해시 길이가 우연히 12로 같지만, 알고리즘과 이어 붙이는 규칙은 다릅니다.

소스 대조 완료 · 2026-08-22 · DSH · MCP와 확장

Claude Code: skill이 일급 tool입니다

Claude Code는 모델에게 Skill tool을 줍니다. 모델이 call해야 본문을 받아요. 주석은 한 번에 skill 하나만 달린다고 적습니다. tool이 명령을 프롬프트 전체로 펼치거든요.

출처:restored-src/src/tools/SkillTool/SkillTool.ts 331–344행

MCP 위 prompt는 loadedFrom === 'mcp'이고 type === 'prompt'여야 발견 목록에 들어갑니다. 방향이 반대예요. Codex는 skill이 MCP를 필요하고, Claude Code는 MCP가 skill을 보탭니다. 트리거도 다릅니다. Codex는 $name을 훑고 맞으면 <skill>를 주입하며, tool call을 한 번 거치지 않아요.

출처:restored-src/src/tools/SkillTool/SkillTool.ts 81–94행

소스 대조 완료 · 2026-08-22
수업 실습
01

세척 뒤에 누가 이 가게를 알아보나

basic-serverlookup을, basic_serverquery를 냅니다. 모델이 보는 네임스페이스 둘을 쓰고, 되부를 때 무엇으로 바른 가게에 들어가는지 말하세요.

한 가지 더: 승인을 Never로 바꾸고 $deploy를 칠 때 skill 목록이 아직 있나요. 관찰 점은 is_model_visibleshould_install_mcp_dependencies입니다.

Takeaway:밖에는 입구 둘만 주고, 안에는 외부 목록을 따로 둡니다. 모델이 보는 것은 번역된 이름이고, 부딪히면 해시하며, 원본 이름은 프로토콜에 남깁니다. skill 목록은 항상 있고, 이름을 불러야 본문이 오며, MCP가 없으면 사람에게 따로 묻습니다.