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:
- The path is relative (starts with
./) - The file exists at the resolved location against the plugin root
- 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.jsonfile resides at the plugin root and defines MCP servers under amcpServersobject with unique server IDs as keys. - Command-based servers require
commandandargsfields, with optionalcwd,env, andtool_timeout_secparameters for local STDIO process execution. - HTTP-based servers require
type: "http"and aurlfield for connecting to remote JSON-RPC endpoints. - The
plugin.jsonmanifest references.mcp.jsonvia a relativemcpServerspath starting with./. - The
plugin-evalvalidator inplugins/plugin-eval/src/evaluators/plugin.jsensures 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →