mirror of
https://github.com/openai/codex.git
synced 2026-04-30 01:16:54 +00:00
- Split MCP runtime/server code out of `codex-core` into the new `codex-mcp` crate. New/moved public structs/types include `McpConfig`, `McpConnectionManager`, `ToolInfo`, `ToolPluginProvenance`, `CodexAppsToolsCacheKey`, and the `McpManager` API (`codex_mcp::mcp::McpManager` plus the `codex_core::mcp::McpManager` wrapper/shim). New/moved functions include `with_codex_apps_mcp`, `configured_mcp_servers`, `effective_mcp_servers`, `collect_mcp_snapshot`, `collect_mcp_snapshot_from_manager`, `qualified_mcp_tool_name_prefix`, and the MCP auth/skill-dependency helpers. Why: this creates a focused MCP crate boundary and shrinks `codex-core` without forcing every consumer to migrate in the same PR. - Move MCP server config schema and persistence into `codex-config`. New/moved structs/enums include `AppToolApproval`, `McpServerToolConfig`, `McpServerConfig`, `RawMcpServerConfig`, `McpServerTransportConfig`, `McpServerDisabledReason`, and `codex_config::ConfigEditsBuilder`. New/moved functions include `load_global_mcp_servers` and `ConfigEditsBuilder::replace_mcp_servers`/`apply`. Why: MCP TOML parsing/editing is config ownership, and this keeps config validation/round-tripping (including per-tool approval overrides and inline bearer-token rejection) in the config crate instead of `codex-core`. - Rewire `codex-core`, app-server, and plugin call sites onto the new crates. Updated `Config::to_mcp_config(&self, plugins_manager)`, `codex-rs/core/src/mcp.rs`, `codex-rs/core/src/connectors.rs`, `codex-rs/core/src/codex.rs`, `CodexMessageProcessor::list_mcp_server_status_task`, and `utils/plugins/src/mcp_connector.rs` to build/pass the new MCP config/runtime types. Why: plugin-provided MCP servers still merge with user-configured servers, and runtime auth (`CodexAuth`) is threaded into `with_codex_apps_mcp` / `collect_mcp_snapshot` explicitly so `McpConfig` stays config-only.
80 lines
2.2 KiB
Rust
80 lines
2.2 KiB
Rust
use super::*;
|
|
use crate::McpServerToolConfig;
|
|
use pretty_assertions::assert_eq;
|
|
use std::collections::HashMap;
|
|
use std::time::SystemTime;
|
|
use std::time::UNIX_EPOCH;
|
|
|
|
#[tokio::test]
|
|
async fn replace_mcp_servers_serializes_per_tool_approval_overrides() -> anyhow::Result<()> {
|
|
let unique_suffix = SystemTime::now().duration_since(UNIX_EPOCH)?.as_nanos();
|
|
let codex_home = std::env::temp_dir().join(format!(
|
|
"codex-config-mcp-edit-test-{}-{unique_suffix}",
|
|
std::process::id()
|
|
));
|
|
let servers = BTreeMap::from([(
|
|
"docs".to_string(),
|
|
McpServerConfig {
|
|
transport: McpServerTransportConfig::Stdio {
|
|
command: "docs-server".to_string(),
|
|
args: Vec::new(),
|
|
env: None,
|
|
env_vars: Vec::new(),
|
|
cwd: None,
|
|
},
|
|
enabled: true,
|
|
required: false,
|
|
disabled_reason: None,
|
|
startup_timeout_sec: None,
|
|
tool_timeout_sec: None,
|
|
enabled_tools: None,
|
|
disabled_tools: None,
|
|
scopes: None,
|
|
oauth_resource: None,
|
|
tools: HashMap::from([
|
|
(
|
|
"search".to_string(),
|
|
McpServerToolConfig {
|
|
approval_mode: Some(AppToolApproval::Approve),
|
|
},
|
|
),
|
|
(
|
|
"read".to_string(),
|
|
McpServerToolConfig {
|
|
approval_mode: Some(AppToolApproval::Prompt),
|
|
},
|
|
),
|
|
]),
|
|
},
|
|
)]);
|
|
|
|
ConfigEditsBuilder::new(&codex_home)
|
|
.replace_mcp_servers(&servers)
|
|
.apply()
|
|
.await?;
|
|
|
|
let config_path = codex_home.join(CONFIG_TOML_FILE);
|
|
let serialized = std::fs::read_to_string(&config_path)?;
|
|
assert_eq!(
|
|
serialized,
|
|
r#"[mcp_servers.docs]
|
|
command = "docs-server"
|
|
|
|
[mcp_servers.docs.tools]
|
|
|
|
[mcp_servers.docs.tools.read]
|
|
approval_mode = "prompt"
|
|
|
|
[mcp_servers.docs.tools.search]
|
|
approval_mode = "approve"
|
|
"#
|
|
);
|
|
|
|
let loaded = load_global_mcp_servers(&codex_home).await?;
|
|
assert_eq!(loaded, servers);
|
|
|
|
std::fs::remove_dir_all(&codex_home)?;
|
|
|
|
Ok(())
|
|
}
|