Understanding MCPServer Definitions in .mcp.json: Structure and Plugin Integration

MCPServer definitions in .mcp.json use a JSON schema with a top-level mcpServers object containing either command-based configurations (requiring command and args fields with optional env and tool_timeout_sec parameters) or HTTP-based configurations (requiring type: "http" and url fields), which are referenced by the plugin.json manifest and validated by the plugin-eval evaluator before runtime instantiation.

The openai/plugins repository enables developers to extend Codex functionality through plugins that expose MCP (Multi-Channel Protocol) servers. These servers are defined in a .mcp.json file located at the root of each plugin directory, creating a standardized bridge between static plugin manifests and dynamic execution environments.

Structure of MCPServer Definitions in .mcp.json

The .mcp.json file follows a strict schema that supports two distinct server types. Each server is identified by a unique key within the mcpServers object, allowing Codex to address specific endpoints by ID during plugin execution.

Top-Level Schema

Every .mcp.json file must contain a single mcpServers object. Each key within this object represents an arbitrary server ID (e.g., "cloudflare-api" or "openai-api-key-local-confirmation"), while the value defines the connection parameters for that specific server instance.

Command-Based Server Configuration

Command-based servers spawn local processes that implement the MCP protocol over STDIO. These definitions require specific fields:

  • command (string): The binary to execute (e.g., node, npx)
  • args (array): Command-line arguments passed to the binary
  • cwd (optional string): Working directory relative to plugin root
  • env (optional object): Additional environment variables
  • tool_timeout_sec (optional number): Execution timeout in seconds

For example, in plugins/openai-developers/.mcp.json, the configuration launches a Node.js script:

{
  "mcpServers": {
    "openai-api-key-local-confirmation": {
      "cwd": ".",
      "command": "node",
      "args": ["./mcp/server.mjs"]
    }
  }
}

HTTP-Based Server Configuration

HTTP-based servers connect to remote endpoints following the MCP JSON-RPC specification. These require:

  • type (string): Must be "http"
  • url (string): The endpoint URL
  • note (optional string): Human-readable description

The Cloudflare plugin in plugins/cloudflare/.mcp.json demonstrates this pattern:

{
  "mcpServers": {
    "cloudflare-api": {
      "type": "http",
      "url": "https://mcp.cloudflare.com/mcp",
      "note": "Official Cloudflare API MCP server."
    }
  }
}

How MCP Servers Integrate with Plugins

The integration follows a three-phase workflow involving manifest declaration, validation, and runtime execution.

Manifest Declaration in plugin.json

Each plugin declares its MCP servers in the plugin.json file located within the .codex-plugin directory. The mcpServers field must specify a relative path starting with ./ that points to the .mcp.json file:

{
  "mcpServers": "./.mcp.json"
}

Validation by plugin-eval

During the validation phase, the plugin-eval evaluator processes the manifest. According to the source code in plugins/plugin-eval/src/evaluators/plugin.js, the evaluator verifies that:

  1. The path is relative (starts with ./)
  2. The file exists at the resolved location against the plugin root
  3. The JSON syntax is valid

Runtime Loading and Execution

When Codex loads the plugin, it reads the .mcp.json configuration and instantiates MCP server instances for each entry:

  • Command-based: Codex spawns the process, connects stdin/stdout to the MCP JSON-RPC channel, and applies any specified environment variables or timeout settings.
  • HTTP-based: Codex establishes an HTTP POST-based RPC client pointed at the configured URL.

Plugin skills invoke these servers using the server ID:

await mcpClient.execute({
  serverId: "openai-api-key-local-confirmation",
  method: "createApiKey",
  params: { name: "my-plugin-key" }
});

Advanced Configuration Examples from the Repository

Timeout Configuration

The codex-security plugin in plugins/codex-security/.mcp.json demonstrates timeout handling with a 15-minute limit:

{
  "mcpServers": {
    "security-server": {
      "command": "node",
      "args": ["./mcp/server.mjs", "--stdio"],
      "tool_timeout_sec": 900
    }
  }
}

npx-Based Execution with Environment Variables

The build-ios-apps plugin in plugins/build-ios-apps/.mcp.json shows how to run npm packages with custom environment configuration:

{
  "mcpServers": {
    "xcodebuildmcp": {
      "command": "npx",
      "args": ["xcodebuildmcp"],
      "env": {
        "CUSTOM_VAR": "value"
      }
    }
  }
}

Summary

  • The .mcp.json file resides at the plugin root and defines MCP servers under a mcpServers object with unique server IDs as keys.
  • Command-based servers require command and args fields, with optional cwd, env, and tool_timeout_sec parameters for local STDIO process execution.
  • HTTP-based servers require type: "http" and a url field for connecting to remote JSON-RPC endpoints.
  • The plugin.json manifest references .mcp.json via a relative mcpServers path starting with ./.
  • The plugin-eval validator in plugins/plugin-eval/src/evaluators/plugin.js ensures the path is relative and the file exists before allowing plugin activation.
  • At runtime, Codex instantiates MCP clients that connect to either local STDIO processes or remote HTTP endpoints based on the configuration type.

Frequently Asked Questions

What file path must the mcpServers field use in plugin.json?

The mcpServers field in plugin.json must use a relative path starting with ./ (e.g., "./.mcp.json"). The validator in plugins/plugin-eval/src/evaluators/plugin.js explicitly checks for this prefix and resolves the path against the plugin root directory to ensure the file exists.

Can a plugin define multiple MCP servers in one .mcp.json file?

Yes. The mcpServers object accepts multiple keys, where each key represents a unique server ID. You can define both a local development server and a remote HTTP endpoint in the same file, and reference them separately by their IDs in your plugin skills or hooks.

How does Codex handle environment variables for command-based MCP servers?

Codex passes environment variables defined in the env object of a server configuration to the spawned process. These variables are merged with the existing environment, as demonstrated in configurations like plugins/build-ios-apps/.mcp.json, which sets custom variables for the npx execution context.

What is the difference between command-based and HTTP-based MCP servers?

Command-based servers spawn local processes that communicate over STDIO using the MCP JSON-RPC protocol, requiring command and args fields. HTTP-based servers connect to remote endpoints via HTTP POST requests, requiring type: "http" and a url field, and are useful for accessing external APIs without requiring local dependencies or process management.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →