mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08: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>
102 lines
2.8 KiB
Rust
102 lines
2.8 KiB
Rust
//! Built-in MCP servers shipped with Codex.
|
|
//!
|
|
//! This crate owns the catalog of product-owned MCP servers and the small
|
|
//! amount of server-specific dispatch needed to run them. Runtime placement is
|
|
//! chosen by `codex-mcp`; built-ins should not be flattened into user-facing
|
|
//! MCP server config just to make them launchable.
|
|
|
|
use std::path::Path;
|
|
|
|
use tokio::io::AsyncRead;
|
|
use tokio::io::AsyncWrite;
|
|
|
|
pub const MEMORIES_MCP_SERVER_NAME: &str = "memories";
|
|
|
|
/// Product-owned MCP servers that Codex can provide without user config.
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
|
pub enum BuiltinMcpServer {
|
|
Memories,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Copy)]
|
|
struct BuiltinMcpServerMetadata {
|
|
name: &'static str,
|
|
supports_parallel_tool_calls: bool,
|
|
pollutes_memory: bool,
|
|
}
|
|
|
|
impl BuiltinMcpServer {
|
|
const fn metadata(self) -> BuiltinMcpServerMetadata {
|
|
match self {
|
|
Self::Memories => BuiltinMcpServerMetadata {
|
|
name: MEMORIES_MCP_SERVER_NAME,
|
|
supports_parallel_tool_calls: true,
|
|
pollutes_memory: false,
|
|
},
|
|
}
|
|
}
|
|
|
|
pub const fn name(self) -> &'static str {
|
|
self.metadata().name
|
|
}
|
|
|
|
pub const fn supports_parallel_tool_calls(self) -> bool {
|
|
self.metadata().supports_parallel_tool_calls
|
|
}
|
|
|
|
pub const fn pollutes_memory(self) -> bool {
|
|
self.metadata().pollutes_memory
|
|
}
|
|
|
|
pub async fn serve<T>(self, codex_home: &Path, transport: T) -> anyhow::Result<()>
|
|
where
|
|
T: AsyncRead + AsyncWrite + Send + 'static,
|
|
{
|
|
match self {
|
|
Self::Memories => {
|
|
let codex_home = codex_utils_absolute_path::AbsolutePathBuf::try_from(codex_home)?;
|
|
codex_memories_mcp::run_server(&codex_home, transport).await
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, Copy)]
|
|
pub struct BuiltinMcpServerOptions {
|
|
pub memories_enabled: bool,
|
|
}
|
|
|
|
pub fn enabled_builtin_mcp_servers(options: BuiltinMcpServerOptions) -> Vec<BuiltinMcpServer> {
|
|
let mut servers = Vec::new();
|
|
if options.memories_enabled {
|
|
servers.push(BuiltinMcpServer::Memories);
|
|
}
|
|
servers
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
use pretty_assertions::assert_eq;
|
|
|
|
#[test]
|
|
fn enabled_builtin_mcp_servers_adds_memories_when_enabled() {
|
|
assert_eq!(
|
|
enabled_builtin_mcp_servers(BuiltinMcpServerOptions {
|
|
memories_enabled: true,
|
|
}),
|
|
vec![BuiltinMcpServer::Memories]
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn enabled_builtin_mcp_servers_omits_memories_when_disabled() {
|
|
assert_eq!(
|
|
enabled_builtin_mcp_servers(BuiltinMcpServerOptions {
|
|
memories_enabled: false,
|
|
}),
|
|
Vec::<BuiltinMcpServer>::new()
|
|
);
|
|
}
|
|
}
|