openai/codex · error · ExecutorPluginMcpProviderError

failed to parse MCP config for selected plugin `{plugin_id}`

Error message

failed to parse MCP config for selected plugin `{plugin_id}` at `{path}`: {source}

What it means

The MCP config contents (manifest-declared file, serialized inline object config, or default .mcp.json) failed to parse via parse_executor_plugin_mcp_config (serde_json). Distinct from per-server problems: malformed individual server entries are logged as warnings and skipped, so ParseConfig means the top-level document is not valid JSON or does not fit the expected config shape at all.

Source

Thrown at codex-rs/ext/mcp/src/executor_plugin/provider.rs:41

pub(super) enum ExecutorPluginMcpProviderError {
    #[error("failed to read MCP config for selected plugin `{plugin_id}` at `{path}`: {source}")]
    ReadConfig {
        plugin_id: String,
        path: PathUri,
        #[source]
        source: io::Error,
    },
    #[error(
        "failed to resolve MCP config path `{relative_path}` below selected plugin `{plugin_id}` at `{root}`: {source}"
    )]
    InvalidConfigPath {
        plugin_id: String,
        root: PathUri,
        relative_path: &'static str,
        #[source]
        source: PathUriParseError,
    },
    #[error("failed to parse MCP config for selected plugin `{plugin_id}` at `{path}`: {source}")]
    ParseConfig {
        plugin_id: String,
        path: PathUri,
        #[source]
        source: serde_json::Error,
    },
}

impl ExecutorPluginMcpProvider {
    /// Returns MCP servers declared by `plugin`, bound to its environment.
    #[tracing::instrument(name = "mcp.executor_plugin.servers.load", skip_all)]
    pub(super) async fn load(
        &self,
        plugin: &ResolvedExecutorPlugin,
    ) -> Result<Vec<(String, McpServerConfig)>, ExecutorPluginMcpProviderError> {
        let ResolvedPluginLocation::Environment { root, .. } = plugin.plugin().location();

        load_from_file_system(plugin.plugin(), root, plugin.file_system()).await

View on GitHub (pinned to 339751715c)

Solutions

  1. Validate with jq: jq . .mcp.json inside the plugin root.
  2. Compare against the executor-plugin MCP config shape (entries must map to McpServerConfig fields).
  3. Fix or remove the file — an absent default file is treated as no servers.
  4. Update plugin or host so both speak the same config schema.
Defensive patterns

Strategy: validation

Validate before calling

// In plugin CI: fail the build on a malformed MCP config
let raw = std::fs::read_to_string(plugin_root.join(".mcp.json"))?;
serde_json::from_str::<serde_json::Value>(&raw)?;

Prevention

When it happens

Trigger: .mcp.json containing invalid JSON, or a top-level structure whose entries do not deserialize into McpServerConfig (wrong field types for command/args/env).

Common situations: Copying a .mcp.json written for the Codex CLI's top-level config format into a plugin; comments or trailing commas; schema drift between plugin SDK and host.

Understand the failure class

Related errors


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