2026-07-19
Codex MCP Server Setup: Connect Skills to Live Tools
Connect Codex skills to an MCP server with scoped tools, safe approvals, authentication, dependency metadata, testing, and production troubleshooting.
Short answer: use a Codex skill to define the repeatable workflow and an MCP server to supply external tools or context. Keep those responsibilities separate. The skill should say when to call a tool, what evidence to collect, and when to stop. The MCP configuration should define how Codex reaches the server, which tools are visible, how authentication works, and which actions require approval.
This guide builds that boundary with a practical example: a repository support skill that can search internal engineering documentation and create a draft issue, but cannot edit arbitrary records or publish changes without a prompt. You will configure a server, limit the tool surface, declare the dependency, test read and write paths, and diagnose the failures that usually make an AI agent MCP server feel unreliable.
Contents
- Skills and MCP solve different problems
- Prerequisites
- Choose STDIO or Streamable HTTP
- Configure the MCP server in Codex
- Apply least-privilege tool policy
- Write the skill workflow
- Declare the MCP dependency
- Test the connection end to end
- Troubleshoot common failures
- Production checklist
Skills and MCP solve different problems
OpenAI describes skills as reusable workflow packages. A skill can contain instructions, scripts, references, and assets, and Codex loads the full SKILL.md only when the task matches. MCP is the integration layer. An MCP server can expose tools, resources, and prompts from systems outside the repository.
The clean architecture is simple:
- Skill: workflow order, input contract, decision rules, evidence, and stop conditions.
- MCP server: authenticated access to external capabilities and data.
- Codex configuration: transport, credentials, enabled tools, timeouts, and approval policy.
- Repository guidance: project-wide commands and conventions that belong in
AGENTS.md.
Do not put API tokens, raw HTTP calls, or service-specific authentication logic into SKILL.md. Do not put a long business workflow into an MCP server's tool descriptions. The server should expose narrow capabilities; the skill should compose them into a useful job.
Prerequisites
- A current Codex CLI, IDE extension, or ChatGPT desktop installation.
- A trusted repository if you plan to use project-scoped
.codex/config.toml. - An MCP server that supports STDIO or Streamable HTTP.
- One read-only tool suitable for a smoke test.
- A separate, narrow write tool if the workflow must create or update data.
- A disposable record or sandbox tenant for the first write-path test.
Start with a read-only workflow. A successful search or lookup proves transport, initialization, tool discovery, and result parsing without risking an external mutation. Add the write path only after the read path is stable.
Step 1: choose STDIO or Streamable HTTP
Codex supports two common MCP server shapes. Choose based on where the capability lives, not on which configuration looks shorter.
| Transport | Best fit | Operational trade-off |
|---|---|---|
| STDIO | Local developer tools, repository helpers, or a server distributed as a package | Codex starts the process; each machine needs the runtime and package |
| Streamable HTTP | Shared services, SaaS integrations, or centrally operated internal systems | The team must operate availability, TLS, authentication, and versioning |
Use STDIO for a local documentation index or a repository-aware helper. Use Streamable HTTP when many developers need the same managed service. Do not wrap a local command in a public HTTP endpoint merely to avoid installing a runtime, and do not copy a production bearer token into every laptop when OAuth is available.
Step 2: configure the server in Codex
Codex stores MCP settings in config.toml. User-wide settings normally live in ~/.codex/config.toml. A trusted repository can use .codex/config.toml when the server is genuinely project-specific.
STDIO example
[mcp_servers.engineering_docs]
command = "npx"
args = ["-y", "@example/engineering-docs-mcp@1.4.2"]
startup_timeout_sec = 20
tool_timeout_sec = 45
enabled = true
required = false
[mcp_servers.engineering_docs.env]
DOCS_ROOT = "/srv/engineering-docs"
Pin a reviewed package version for team or CI use. A floating @latest can change tool schemas without a repository diff. Set required = true only when Codex should fail startup if the server is unavailable; optional helpers usually should not block unrelated coding work.
Streamable HTTP example
[mcp_servers.issue_hub]
url = "https://mcp.example.com/mcp"
bearer_token_env_var = "ISSUE_HUB_MCP_TOKEN"
startup_timeout_sec = 20
tool_timeout_sec = 45
enabled = true
The config stores the environment variable name, not the secret value. Put the token in the approved secret store for the Codex host. For OAuth servers, use codex mcp login issue_hub and complete the provider's authorization flow instead of converting an OAuth integration into a long-lived shared token.
After changing MCP configuration, restart the relevant Codex client. Run codex mcp list or use /mcp in the terminal UI to confirm that the server initialized and whether authentication is required.
Step 3: expose only the tools the workflow needs
An MCP connection is not a reason to expose every server tool. Codex supports tool allowlists, denylists, default approval behavior, and per-tool approval overrides. Apply them in configuration even when the server also enforces authorization.
[mcp_servers.issue_hub]
url = "https://mcp.example.com/mcp"
bearer_token_env_var = "ISSUE_HUB_MCP_TOKEN"
enabled_tools = ["search_docs", "get_issue", "create_issue_draft"]
disabled_tools = ["delete_issue", "publish_issue"]
default_tools_approval_mode = "writes"
[mcp_servers.issue_hub.tools.search_docs]
approval_mode = "approve"
[mcp_servers.issue_hub.tools.create_issue_draft]
approval_mode = "prompt"
A denylist is applied after the allowlist, so it can remove a tool that appears in both. Use that behavior for emergency controls, not as a substitute for a small allowlist. The MCP server must still validate the caller, tenant, scopes, and arguments; client configuration reduces accidental exposure but is not the service's authorization boundary.
Step 4: write a skill that composes the tools
Create a repository skill under .agents/skills/issue-brief/. The skill should name the required outcome and tools without embedding service credentials or transport details.
---
name: issue-brief
description: Research an engineering problem and create a draft issue. Use for issue briefs and bug intake. Never publish, assign, or delete issues.
---
# Issue brief
1. Read the applicable AGENTS.md files.
2. Confirm the repository, component, and observed behavior.
3. Use search_docs for relevant runbooks and architecture notes.
4. Use get_issue to check for an existing matching issue.
5. Summarize evidence, reproduction steps, expected behavior, and risk.
6. Use create_issue_draft only after the user confirms the destination project.
7. Return the draft URL and list any missing evidence.
Stop if the MCP server is unavailable, authentication fails, the destination is ambiguous, or a matching issue already exists.
Never publish, assign, close, or delete an issue.
This workflow is reviewable without knowing whether the server uses STDIO, HTTP, OAuth, or a bearer token. It also remains useful if the team replaces the server implementation while preserving the tool contract.
Step 5: declare the MCP dependency
OpenAI recommends declaring MCP dependencies in agents/openai.yaml when a skill relies on a specific server. The metadata helps supported surfaces understand that the workflow is incomplete without the integration.
interface:
display_name: "Issue brief"
short_description: "Research a problem and create a draft issue"
dependencies:
tools:
- type: mcp
value: issue_hub
description: "Search engineering docs and create issue drafts"
Treat this as dependency metadata, not permission. The Codex host still needs a configured, enabled, authenticated server, and the tool policy still decides what is callable.
Step 6: validate the full path
Test the integration in layers. A single successful final prompt does not tell you which controls are working.
- Initialization: restart Codex and confirm the server appears in
codex mcp listor/mcp. - Discovery: verify that only the three allowed tools are visible.
- Read path: invoke the skill against a known document and compare the returned fact with the source.
- Duplicate path: use a problem that already has an issue; the skill should stop before creating another draft.
- Write approval: use a disposable project and confirm that
create_issue_draftprompts before execution. - Denied path: ask to delete or publish the issue; the tool should be unavailable or refused.
- Failure path: remove the token or stop the server; the skill should return a bounded blocker instead of inventing results.
Record the server version, tool schema version, request identifier, and resulting draft URL. Those artifacts make the workflow debuggable when a later package or server update changes behavior.
Common failures and what they mean
| Symptom | Likely cause | Fix |
|---|---|---|
| Server is missing after config changes | Client was not restarted, config is in the wrong scope, or the project is not trusted | Confirm the active config path, trust boundary, and restart the client |
| Startup timeout | Package install, runtime startup, DNS, or TLS is slow | Run the STDIO command directly or probe the HTTP endpoint; then set a measured timeout |
| Tools appear but calls fail | Authentication, scope, tenant, or schema mismatch | Inspect the server error and tool schema; re-authenticate without printing secrets |
| Skill does not trigger | The description is vague or the skill is in the wrong discovery path | Test explicit invocation, then tighten the description and confirm the skill location |
| Too many approval prompts | Read tools inherit a prompt-heavy default | Approve known read-only tools explicitly; keep writes on prompt or writes |
| A dangerous tool is still visible | The allowlist is too broad or the server exposes a second alias | Narrow enabled_tools, add an emergency deny, and remove the scope server-side |
| Results are plausible but wrong | The skill skipped source validation or the server returned stale data | Require source identifiers, timestamps, and a known-answer smoke test |
Do not fix an unreliable integration by granting more permissions. First separate transport, authentication, discovery, tool execution, workflow logic, and external side effects. Test the failing layer directly.
Production checklist
- The skill and MCP server have different, explicit responsibilities.
- The server transport matches the operating model: STDIO for local capability or Streamable HTTP for managed shared capability.
- Package versions or server API versions are pinned and reviewed.
- Secrets come from environment-backed or OAuth credential stores, not
SKILL.mdor committed config. enabled_toolscontains only the tools required by the workflow.- Consequential write tools require approval and server-side authorization.
- Timeouts are based on measured startup and tool latency.
- The skill declares the MCP dependency and safe stop conditions.
- Initialization, discovery, read, write, denial, duplicate, and failure paths are tested independently.
- Logs include request identifiers and outcomes without tokens or sensitive payloads.
- A server outage blocks only the dependent workflow, not unrelated Codex work, unless the integration is intentionally required.
Bottom line
A dependable Codex MCP setup is not “connect a server and hope the model chooses well.” It is a small contract across three layers: the skill defines the job, Codex configuration defines the accessible tool surface, and the server enforces authentication and authorization. Keep each layer narrow, test failures before production, and require human approval at consequential writes.
If you need this workflow to keep running on a persistent hosted agent rather than a developer laptop, GolemWorkers can provide the isolated runtime, scoped secrets, schedules, logs, and browser or terminal access around the same skill-and-tool contract.