This page documents the codex mcp subcommands that allow users to manage Model Context Protocol (MCP) server configurations from the command line. These commands provide a convenient interface for adding, removing, listing, and authenticating with MCP servers without manually editing configuration files.
For information about the MCP server configuration structure and connection lifecycle, see MCP Server Configuration and MCP Connection Manager. For details on OAuth implementation, see OAuth Authentication for MCP.
The MCP CLI commands are implemented as subcommands under codex mcp. All commands operate on the global MCP server configuration stored in ~/.codex/config.toml (or $CODEX_HOME/config.toml).
Available Commands:
list — Display all configured MCP servers with their statusget <name> — Show detailed configuration for a specific serveradd <name> — Add a new MCP server configurationremove <name> — Delete an MCP server configurationlogin <name> — Authenticate with an MCP server via OAuthlogout <name> — Remove stored OAuth credentialsSources: codex-rs/cli/src/mcp_cmd.rs23-47
Diagram: MCP Command Dispatch Flow
The McpCli struct serves as the entry point, delegating to dedicated handler functions for each subcommand. Read operations (list, get) load the full Config to access merged configuration from all layers, while write operations (add, remove) directly manipulate the global MCP servers map via ConfigEditsBuilder.
Sources: codex-rs/cli/src/mcp_cmd.rs30-37 codex-rs/cli/src/mcp_cmd.rs151-180
The list command displays all configured MCP servers. It supports both human-readable table output and JSON format via the --json flag.
The command groups servers by transport type (stdio vs streamable-http) and displays them in separate tables:
Stdio Servers Table:
| Column | Description |
|---|---|
| Name | Server identifier |
| Command | Executable or script path |
| Args | Command-line arguments |
| Env | Environment variables (inline and from env_vars) |
| Cwd | Working directory |
| Status | enabled or disabled: <reason> |
| Auth | OAuth status: authenticated, unauthenticated, unsupported |
Streamable HTTP Servers Table:
| Column | Description |
|---|---|
| Name | Server identifier |
| Url | HTTP endpoint URL |
| Bearer Token Env Var | Environment variable containing token |
| Status | enabled or disabled: <reason> |
| Auth | OAuth status |
Environment variables are displayed with their values masked (e.g., TOKEN=*****) for security. Variables listed in env_vars are shown as VAR_NAME=***** even if not set, indicating they will be propagated from the parent environment if available.
Sources: codex-rs/cli/src/mcp_cmd.rs395-643 codex-rs/cli/tests/mcp_list.rs20-139
With --json, the command outputs an array of server configurations with full details:
Sources: codex-rs/cli/src/mcp_cmd.rs411-468
The list command calls compute_auth_statuses() to determine OAuth status for each server. This function:
McpAuthStatus:
Authenticated — Valid credentials existUnauthenticated — OAuth supported but no credentialsUnsupported — Transport doesn't support OAuth (stdio)Sources: codex-rs/cli/src/mcp_cmd.rs405-409
The get command displays detailed configuration for a single MCP server.
For enabled servers, get displays a detailed breakdown:
docs
enabled: true
enabled_tools: tool1, tool2
disabled_tools: tool3
transport: stdio
command: docs-server
args: --port 4000
cwd: /path/to/workspace
env: TOKEN=*****, APP_TOKEN=*****
startup_timeout_sec: 10.0
tool_timeout_sec: 60.0
remove: codex mcp remove docs
For disabled servers, it shows a single line with the reason:
docs (disabled: org policy)
Sources: codex-rs/cli/src/mcp_cmd.rs645-802
The JSON format mirrors the structure in the list command but for a single server. Environment variables and headers are shown with their actual values (not masked) in JSON output.
Sources: codex-rs/cli/src/mcp_cmd.rs657-701
The add command creates a new MCP server configuration. It supports two transport types: stdio (for local executables) and streamable-http (for remote HTTP servers).
Stdio transport:
Streamable HTTP transport:
The AddArgs struct defines the argument structure:
| Argument | Type | Description |
|---|---|---|
name | String | Server identifier (must match ^[a-zA-Z0-9_-]+$) |
--env | KEY=VALUE pairs | Environment variables for stdio servers |
command | Trailing args | Executable and arguments after -- |
--url | String | HTTP endpoint for streamable-http servers |
--bearer-token-env-var | String | Environment variable containing auth token |
The command uses ArgGroup to ensure exactly one transport type is specified.
Sources: codex-rs/cli/src/mcp_cmd.rs66-127
Diagram: Add Command Execution Flow
Sources: codex-rs/cli/src/mcp_cmd.rs183-287
After adding a streamable-http server, the add command automatically checks for OAuth support:
oauth_login_support() to probe the server's /oauth/start endpointperform_oauth_login()codex mcp login <name> to login"This eliminates the need for a separate login step in most cases.
Sources: codex-rs/cli/src/mcp_cmd.rs265-284
Server names must conform to ^[a-zA-Z0-9_-]+$. The validate_server_name() function enforces this to ensure:
mcp__<server>__<tool>)Sources: codex-rs/cli/src/mcp_cmd.rs819-830
The add command supports two ways to pass environment variables to stdio servers:
--env KEY=VALUE): Values are stored directly in the config fileThe --env flag uses parse_env_pair() to split KEY=VALUE strings, validating that both parts are non-empty.
Sources: codex-rs/cli/src/mcp_cmd.rs204-223 codex-rs/cli/src/mcp_cmd.rs804-816
The remove command deletes an MCP server configuration from the global config file.
mcp_servers map from ~/.codex/config.tomlConfigEditsBuilderIf the server doesn't exist, the command succeeds with a message rather than failing. This makes remove idempotent.
Sources: codex-rs/cli/src/mcp_cmd.rs289-320
Note: Removing a server does not delete stored OAuth credentials. Use codex mcp logout <name> first to clean up credentials.
The login command authenticates with an MCP server using OAuth 2.0. It only works with streamable-http servers that expose OAuth endpoints.
Diagram: OAuth Login Command Flow
Sources: codex-rs/cli/src/mcp_cmd.rs322-363
OAuth scopes can be specified in two ways:
--scopes read:repos,write:issues (comma-separated)scopes = ["read:repos", "write:issues"] in the server entryIf --scopes is provided, it overrides the config. If neither is set, an empty scope list is used (server-dependent default).
Sources: codex-rs/cli/src/mcp_cmd.rs346-349
The perform_oauth_login() function (from codex-rmcp-client) spawns a temporary HTTP server to receive the OAuth callback:
{bind_host}:{port} where:
bind_host is 127.0.0.1 for localhost callbacks, 0.0.0.0 for external callbacksport is from mcp_oauth_callback_port config (default: random available port via :0)redirect_uri from mcp_oauth_callback_url config or defaults to http://127.0.0.1:{port}/callbackOAuthState::start_authorization() with scopes and redirect URI/callback)OAuthState::handle_callback()mcp_oauth_credentials_store_modeThe callback server uses tiny_http::Server and runs in a blocking thread spawned by spawn_callback_server(). The OAuth flow uses the rmcp crate's OAuthState state machine to manage the authorization process.
Sources: codex-rs/rmcp-client/src/perform_oauth_login.rs298-358 codex-rs/rmcp-client/src/perform_oauth_login.rs108-146 codex-rs/cli/src/mcp_cmd.rs351-361
The logout command removes stored OAuth credentials for an MCP server.
streamable_http transportdelete_oauth_tokens() to remove credentials from storageThe function returns Ok(true) if credentials existed and were deleted, Ok(false) if no credentials were found. Both cases are treated as success.
Sources: codex-rs/cli/src/mcp_cmd.rs365-393
Storage Locations:
~/.codex/.credentials/{server_name}.jsonThe storage mode is controlled by the mcp_oauth_credentials_store_mode config option.
Sources: codex-rs/cli/src/mcp_cmd.rs386
All write operations (add, remove) use the ConfigEditsBuilder API to safely modify the global configuration file.
Diagram: Configuration Update Pipeline
The ConfigEditsBuilder::replace_mcp_servers() method:
mcp_servers map to TOML[mcp_servers] tableThis ensures that concurrent edits or parse errors don't corrupt the config.
Sources: codex-rs/cli/src/mcp_cmd.rs257-261 codex-rs/cli/src/mcp_cmd.rs306-310
Each server entry is a McpServerConfig:
| Field | Type | Description |
|---|---|---|
transport | McpServerTransportConfig | stdio or streamable_http details |
enabled | bool | Whether to load server on startup |
required | bool | Session fails if startup fails |
disabled_reason | Option<String> | Human-readable disable reason |
startup_timeout_sec | Option<Duration> | Override default 10s timeout |
tool_timeout_sec | Option<Duration> | Override default 60s timeout |
enabled_tools | Option<Vec<String>> | Allowlist (none = all allowed) |
disabled_tools | Option<Vec<String>> | Blocklist |
scopes | Option<Vec<String>> | Default OAuth scopes |
Sources: codex-rs/cli/src/mcp_cmd.rs243-253
The mcp_oauth_credentials_store_mode config option controls where OAuth tokens are persisted. The implementation is in codex-rmcp-client crate.
The Auto mode (default) attempts to use the platform keyring and falls back to file storage if the keyring is unavailable or returns an error. The Keyring mode fails immediately if keyring access is not available.
Sources: codex-rs/rmcp-client/src/oauth.rs67-79
Location: $CODEX_HOME/.credentials/{server_key}.json
The server_key is computed as sha256(server_name + url) to create a unique identifier for each server configuration.
Format (StoredOAuthTokens struct):
Permissions: The file is created with 0600 (owner read/write only) for security.
Sources: codex-rs/rmcp-client/src/oauth.rs56-64 codex-rs/rmcp-client/src/oauth.rs285-289
Uses platform-specific secure storage via the keyring crate:
security framework, apple-native feature)wincred API, windows-native feature)linux-native-async-persistent feature)Service name: Codex MCP Credentials (constant KEYRING_SERVICE)
Account name: {server_key} (computed from server name + URL)
Password: JSON-serialized StoredOAuthTokens object
The keyring store operations are implemented in codex-keyring-store crate, which wraps the keyring crate with async support.
Sources: codex-rs/rmcp-client/src/oauth.rs53 codex-rs/rmcp-client/src/oauth.rs152-168 codex-rs/rmcp-client/Cargo.toml63-74
The default mode is Auto, which provides the best security (keyring) when available while ensuring the CLI remains functional on systems where keyring access fails. The fallback chain is:
~/.codex/.credentials/{server_key}.jsonDuring reads, Auto mode first checks the keyring, then falls back to file storage if keyring access fails.
Sources: codex-rs/rmcp-client/src/oauth.rs136-150 codex-rs/rmcp-client/src/oauth.rs215-229
| Error | Command | Cause |
|---|---|---|
| "invalid server name" | add, remove, login, logout | Name contains invalid characters |
| "No MCP server named 'X' found" | get, login, logout | Server not in config |
| "OAuth login is only supported for streamable HTTP servers" | login | Attempted OAuth with stdio server |
| "Environment variable {var} for MCP server '{name}' is not set" | Runtime (not CLI) | Missing required env var |
| "exactly one of --command or --url must be provided" | add | Missing or conflicting transport args |
Sources: codex-rs/cli/src/mcp_cmd.rs819-830 codex-rs/cli/src/mcp_cmd.rs332-344
All commands validate CliConfigOverrides (from --config-file or -c flags) before executing. This ensures that any user-provided overrides are syntactically valid, even though they're not applied during MCP command execution.
Sources: codex-rs/cli/src/mcp_cmd.rs185-190
The list command uses a simple ASCII table format with dynamically calculated column widths:
Sensitive values (environment variables, tokens) are masked with ***** in human-readable output but shown in full in JSON mode.
Sources: codex-rs/cli/src/mcp_cmd.rs538-640
The format_env_display() utility (from codex_utils_cli) combines inline env and env_vars into a single display string:
TOKEN=*****, APP_TOKEN=*****, WORKSPACE_ID=*****
If both are empty, displays - for clarity.
Sources: codex-rs/cli/src/mcp_cmd.rs492 codex-rs/cli/src/mcp_cmd.rs752
The MCP CLI commands have comprehensive integration tests that verify:
Tests use tempfile::TempDir to isolate $CODEX_HOME and avoid polluting the user's real config.
Sources: codex-rs/cli/tests/mcp_list.rs codex-rs/cli/tests/mcp_add_remove.rs
Refresh this wiki