mirror of
https://github.com/openai/codex.git
synced 2026-05-17 09:43:19 +00:00
## DISCLAIMER This is experimental and no production service must rely on this ## Why Built-in MCPs are product-owned runtime capabilities, but they were previously flattened into the same config-backed stdio path as user-configured servers. That made them depend on a hidden `codex builtin-mcp` re-exec path, exposed them through config-oriented CLI flows, and erased distinctions the runtime needs to preserve—most notably whether an MCP call should count as external context for memory-mode pollution. ## What changed - Model product-owned built-ins separately from config-backed MCP servers via `BuiltinMcpServer` and `EffectiveMcpServer`. - Launch built-ins in process through a reusable async transport instead of the hidden `builtin-mcp` stdio subcommand. - Keep config-oriented CLI operations such as `codex mcp list/get/login/logout` scoped to configured servers, while merging built-ins only into the effective runtime server set. - Retain server metadata after launch so parallel-tool support and context classification come from the live server set; built-in `memories` is now classified as local Codex state rather than external context. ## Test plan - `cargo test -p codex-mcp` - `cargo test -p codex-core --test suite builtin_memories_mcp_call_does_not_mark_thread_memory_mode_polluted_when_configured` --------- Co-authored-by: Codex <noreply@openai.com>
109 lines
3.2 KiB
Rust
109 lines
3.2 KiB
Rust
use codex_builtin_mcps::BuiltinMcpServer;
|
|
use codex_config::McpServerConfig;
|
|
use codex_config::McpServerTransportConfig;
|
|
|
|
/// The runtime launch strategy for an effective MCP server.
|
|
#[derive(Debug, Clone)]
|
|
pub(crate) enum McpServerLaunch {
|
|
Configured(Box<McpServerConfig>),
|
|
Builtin(BuiltinMcpServer),
|
|
}
|
|
|
|
/// MCP server after product-owned runtime additions have been applied.
|
|
#[derive(Debug, Clone)]
|
|
pub struct EffectiveMcpServer {
|
|
launch: McpServerLaunch,
|
|
}
|
|
|
|
impl EffectiveMcpServer {
|
|
pub fn configured(config: McpServerConfig) -> Self {
|
|
Self {
|
|
launch: McpServerLaunch::Configured(Box::new(config)),
|
|
}
|
|
}
|
|
|
|
pub fn builtin(server: BuiltinMcpServer) -> Self {
|
|
Self {
|
|
launch: McpServerLaunch::Builtin(server),
|
|
}
|
|
}
|
|
|
|
pub(crate) fn launch(&self) -> &McpServerLaunch {
|
|
&self.launch
|
|
}
|
|
|
|
pub fn configured_config(&self) -> Option<&McpServerConfig> {
|
|
match &self.launch {
|
|
McpServerLaunch::Configured(config) => Some(config.as_ref()),
|
|
McpServerLaunch::Builtin(_) => None,
|
|
}
|
|
}
|
|
|
|
pub fn enabled(&self) -> bool {
|
|
match &self.launch {
|
|
McpServerLaunch::Configured(config) => config.enabled,
|
|
McpServerLaunch::Builtin(_) => true,
|
|
}
|
|
}
|
|
|
|
pub fn required(&self) -> bool {
|
|
match &self.launch {
|
|
McpServerLaunch::Configured(config) => config.required,
|
|
McpServerLaunch::Builtin(_) => false,
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Transport origin retained for metrics and diagnostics after server launch.
|
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
pub(crate) enum McpServerOrigin {
|
|
InProcess,
|
|
Stdio,
|
|
StreamableHttp(String),
|
|
}
|
|
|
|
impl McpServerOrigin {
|
|
pub fn as_str(&self) -> &str {
|
|
match self {
|
|
Self::InProcess => "in_process",
|
|
Self::Stdio => "stdio",
|
|
Self::StreamableHttp(origin) => origin,
|
|
}
|
|
}
|
|
|
|
fn from_transport(transport: &McpServerTransportConfig) -> Option<Self> {
|
|
match transport {
|
|
McpServerTransportConfig::StreamableHttp { url, .. } => {
|
|
let parsed = url::Url::parse(url).ok()?;
|
|
Some(Self::StreamableHttp(parsed.origin().ascii_serialization()))
|
|
}
|
|
McpServerTransportConfig::Stdio { .. } => Some(Self::Stdio),
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Semantic metadata that must survive after the server is launched.
|
|
#[derive(Debug, Clone)]
|
|
pub(crate) struct McpServerMetadata {
|
|
pub pollutes_memory: bool,
|
|
pub origin: Option<McpServerOrigin>,
|
|
pub supports_parallel_tool_calls: bool,
|
|
}
|
|
|
|
impl From<&EffectiveMcpServer> for McpServerMetadata {
|
|
fn from(server: &EffectiveMcpServer) -> Self {
|
|
match server.launch() {
|
|
McpServerLaunch::Configured(config) => Self {
|
|
pollutes_memory: true,
|
|
origin: McpServerOrigin::from_transport(&config.transport),
|
|
supports_parallel_tool_calls: config.supports_parallel_tool_calls,
|
|
},
|
|
McpServerLaunch::Builtin(server) => Self {
|
|
pollutes_memory: server.pollutes_memory(),
|
|
origin: Some(McpServerOrigin::InProcess),
|
|
supports_parallel_tool_calls: server.supports_parallel_tool_calls(),
|
|
},
|
|
}
|
|
}
|
|
}
|