openai/codex · error

Invalid MCP server name '{server_name}': must match pattern

Error message

Invalid MCP server name '{server_name}': must match pattern {pattern}

What it means

Before connecting, validate_mcp_server_name (called from start) checks the MCP server key against ^[a-zA-Z0-9_-]+$. Server names become tool namespaces, config keys and cache identifiers, so anything outside ASCII letters, digits, underscore and hyphen (spaces, dots, slashes, colons, unicode) is rejected at startup with the offending name and the exact pattern.

Source

Thrown at codex-rs/codex-mcp/src/rmcp_client.rs:861

                    "Environment variable {env_var} for MCP server '{server_name}' is empty"
                ))
            } else {
                Ok(Some(value))
            }
        }
        Err(env::VarError::NotPresent) => Err(anyhow!(
            "Environment variable {env_var} for MCP server '{server_name}' is not set"
        )),
        Err(env::VarError::NotUnicode(_)) => Err(anyhow!(
            "Environment variable {env_var} for MCP server '{server_name}' contains invalid Unicode"
        )),
    }
}

fn validate_mcp_server_name(server_name: &str) -> Result<()> {
    let re = regex_lite::Regex::new(r"^[a-zA-Z0-9_-]+$")?;
    if !re.is_match(server_name) {
        return Err(anyhow!(
            "Invalid MCP server name '{server_name}': must match pattern {pattern}",
            pattern = re.as_str()
        ));
    }
    Ok(())
}

#[instrument(level = "trace", skip_all, fields(server_name = %server_name))]
async fn start_server_task(
    server_name: String,
    client: Arc<RmcpClient>,
    params: StartServerTaskParams,
) -> Result<ManagedClient, StartupOutcomeError> {
    let StartServerTaskParams {
        is_codex_apps_mcp_server,
        startup_timeout,
        tx_event,
        elicitation_requests,

View on GitHub (pinned to 339751715c)

Solutions

  1. Rename the key to only [A-Za-z0-9_-], e.g. [mcp_servers.github_proxy] instead of [mcp_servers."github proxy"]
  2. Check the key for invisible leading/trailing whitespace or a BOM
  3. If the name is generated, slugify it before registering: replace separators with '-' and strip non-ASCII

Example fix

# before
[mcp_servers."github proxy"]
url = "https://mcp.github.com/api"

# after
[mcp_servers.github_proxy]
url = "https://mcp.github.com/api"
Defensive patterns

Strategy: validation

Validate before calling

// Validate before registering or writing config
fn is_valid_mcp_server_name(name: &str) -> bool {
    !name.is_empty()
        && name.bytes().all(|b| b.is_ascii_alphanumeric() || b == b'_' || b == b'-')
}

Type guard

pub fn is_valid_mcp_server_name(name: &str) -> bool {
    regex_lite::Regex::new(r"^[a-zA-Z0-9_-]+$").unwrap().is_match(name)
}

Prevention

When it happens

Trigger: config.toml keys like [mcp_servers."my server"], [mcp_servers.github/api], [mcp_servers."db.prod"] or unicode names; keys with leading/trailing whitespace from copy-paste; programmatically registered servers (app-server MCP APIs) whose ids were never slugified.

Common situations: Display names pasted as TOML keys; generated names containing '/', ':' or non-ASCII; renaming a server to a human-friendly label in config.

Related errors


AI-assisted analysis of openai/codex@339751715c (2026-08-25). Data as JSON: /api/errors/ccb809fb05453279. Report an issue: GitHub.