mirror of
https://github.com/openai/codex.git
synced 2026-04-28 08:34:54 +00:00
165 lines
6.0 KiB
Markdown
165 lines
6.0 KiB
Markdown
# PR #2720: support separate mcp server configs per profile
|
|
|
|
- URL: https://github.com/openai/codex/pull/2720
|
|
- Author: nornagon-openai
|
|
- Created: 2025-08-26 16:48:02 UTC
|
|
- Updated: 2025-08-29 02:48:35 UTC
|
|
- Changes: +48/-2, Files changed: 4, Commits: 4
|
|
|
|
## Description
|
|
|
|
I want to be able to configure MCP servers on a per-profile basis, so I can configure e.g. an "ops" profile that has access to various analysis MCPs.
|
|
|
|
## Full Diff
|
|
|
|
```diff
|
|
diff --git a/codex-rs/config.md b/codex-rs/config.md
|
|
index af51df4197..3ffe7f9f73 100644
|
|
--- a/codex-rs/config.md
|
|
+++ b/codex-rs/config.md
|
|
@@ -3,4 +3,4 @@
|
|
This file has moved. Please see the latest configuration documentation here:
|
|
|
|
- Full config docs: [docs/config.md](../docs/config.md)
|
|
-- MCP servers section: [docs/config.md#mcp_servers](../docs/config.md#mcp_servers)
|
|
\ No newline at end of file
|
|
+- MCP servers section: [docs/config.md#mcp_servers](../docs/config.md#mcp_servers)
|
|
diff --git a/codex-rs/core/src/config.rs b/codex-rs/core/src/config.rs
|
|
index 9b8f288cf3..e3fa3cd408 100644
|
|
--- a/codex-rs/core/src/config.rs
|
|
+++ b/codex-rs/core/src/config.rs
|
|
@@ -760,7 +760,23 @@ impl Config {
|
|
notify: cfg.notify,
|
|
user_instructions,
|
|
base_instructions,
|
|
- mcp_servers: cfg.mcp_servers,
|
|
+ // Merge top-level and per-profile MCP servers.
|
|
+ // Defaults: inherit globals unless explicitly disabled; on key
|
|
+ // conflicts, profile entries take precedence.
|
|
+ mcp_servers: {
|
|
+ let inherit = config_profile.inherit_global_mcp_servers.unwrap_or(true);
|
|
+ let mut merged = if inherit {
|
|
+ cfg.mcp_servers
|
|
+ } else {
|
|
+ Default::default()
|
|
+ };
|
|
+ if let Some(profile_servers) = config_profile.mcp_servers {
|
|
+ for (k, v) in profile_servers {
|
|
+ merged.insert(k, v);
|
|
+ }
|
|
+ }
|
|
+ merged
|
|
+ },
|
|
model_providers,
|
|
project_doc_max_bytes: cfg.project_doc_max_bytes.unwrap_or(PROJECT_DOC_MAX_BYTES),
|
|
codex_home,
|
|
diff --git a/codex-rs/core/src/config_profile.rs b/codex-rs/core/src/config_profile.rs
|
|
index 54869919fb..11f73eefd2 100644
|
|
--- a/codex-rs/core/src/config_profile.rs
|
|
+++ b/codex-rs/core/src/config_profile.rs
|
|
@@ -1,6 +1,8 @@
|
|
use serde::Deserialize;
|
|
+use std::collections::HashMap;
|
|
use std::path::PathBuf;
|
|
|
|
+use crate::config_types::McpServerConfig;
|
|
use crate::config_types::Verbosity;
|
|
use crate::protocol::AskForApproval;
|
|
use codex_protocol::config_types::ReasoningEffort;
|
|
@@ -21,4 +23,14 @@ pub struct ConfigProfile {
|
|
pub model_verbosity: Option<Verbosity>,
|
|
pub chatgpt_base_url: Option<String>,
|
|
pub experimental_instructions_file: Option<PathBuf>,
|
|
+
|
|
+ /// Per-profile MCP server definitions. When present, these entries are
|
|
+ /// merged with the top-level `mcp_servers` map. On key conflicts, the
|
|
+ /// profile entries take precedence. To opt out of inheriting global
|
|
+ /// servers, set `inherit_global_mcp_servers` to `false`.
|
|
+ pub mcp_servers: Option<HashMap<String, McpServerConfig>>,
|
|
+
|
|
+ /// Whether this profile should inherit the top-level `mcp_servers`.
|
|
+ /// Defaults to `true` when not specified.
|
|
+ pub inherit_global_mcp_servers: Option<bool>,
|
|
}
|
|
diff --git a/docs/config.md b/docs/config.md
|
|
index 7d0bd7d2b8..2823665bd0 100644
|
|
--- a/docs/config.md
|
|
+++ b/docs/config.md
|
|
@@ -362,6 +362,24 @@ args = ["-y", "mcp-server"]
|
|
env = { "API_KEY" = "value" }
|
|
```
|
|
|
|
+### Per-profile MCP servers
|
|
+
|
|
+You can scope MCP servers to a specific profile and optionally inherit the global set. Profile entries override globals on key conflicts.
|
|
+
|
|
+```toml
|
|
+# Global servers (available to all profiles unless opted out)
|
|
+[mcp_servers.some_server]
|
|
+command = "some_server"
|
|
+
|
|
+# Profile-specific MCP server
|
|
+[profiles.ops.mcp_servers.analysis]
|
|
+command = "ops_mcp"
|
|
+
|
|
+# You can disable inheriting the global MCP servers in a specific profile
|
|
+[profiles.minimal]
|
|
+inherit_global_mcp_servers = false # only profile servers (none defined => none)
|
|
+```
|
|
+
|
|
## disable_response_storage
|
|
|
|
Currently, customers whose accounts are set to use Zero Data Retention (ZDR) must set `disable_response_storage` to `true` so that Codex uses an alternative to the Responses API that works with ZDR:
|
|
```
|
|
|
|
## Review Comments
|
|
|
|
### docs/config.md
|
|
|
|
- Created: 2025-08-28 17:47:40 UTC | Link: https://github.com/openai/codex/pull/2720#discussion_r2308133509
|
|
|
|
```diff
|
|
@@ -362,6 +362,24 @@ args = ["-y", "mcp-server"]
|
|
env = { "API_KEY" = "value" }
|
|
```
|
|
|
|
+### Per-profile MCP servers
|
|
+
|
|
+You can scope MCP servers to a specific profile and optionally inherit the global set. Profile entries override globals on key conflicts.
|
|
+
|
|
+```toml
|
|
+# Global servers (available to all profiles unless opted out)
|
|
+[mcp_servers.some_server]
|
|
+command = "some_server"
|
|
+
|
|
+# Profile-specific MCP server
|
|
+[profiles.ops.analysis]
|
|
+command = "ops_mcp"
|
|
```
|
|
|
|
> I'm a little confused: I feel like we should let people define MCP servers and then a profile should be able to be specify the list of MCP servers (by id) that should be enabled for that profile.
|
|
>
|
|
> Though I guess the question is: how do you define an MCP server that you don't want enabled in the default profile, but you do in other profiles that name it explicitly? We could add an option `disable_in_default_profile` for an individual MCP server, I suppose?
|
|
|
|
- Created: 2025-08-28 18:04:05 UTC | Link: https://github.com/openai/codex/pull/2720#discussion_r2308170622
|
|
|
|
```diff
|
|
@@ -362,6 +362,24 @@ args = ["-y", "mcp-server"]
|
|
env = { "API_KEY" = "value" }
|
|
```
|
|
|
|
+### Per-profile MCP servers
|
|
+
|
|
+You can scope MCP servers to a specific profile and optionally inherit the global set. Profile entries override globals on key conflicts.
|
|
+
|
|
+```toml
|
|
+# Global servers (available to all profiles unless opted out)
|
|
+[mcp_servers.some_server]
|
|
+command = "some_server"
|
|
+
|
|
+# Profile-specific MCP server
|
|
+[profiles.ops.analysis]
|
|
+command = "ops_mcp"
|
|
```
|
|
|
|
> Can we support both modalities? |