codex-mcp/src/server.rs
115 lines
use std::collections::HashMap;use codex_config::AppToolApproval;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>),}/// MCP server after 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(crate) fn launch(&self) -> &McpServerLaunch { &self.launch } pub fn configured_config(&self) -> Option<&McpServerConfig> { match &self.launch { McpServerLaunch::Configured(config) => Some(config.as_ref()), } } pub fn enabled(&self) -> bool { match &self.launch { McpServerLaunch::Configured(config) => config.enabled, } } pub fn required(&self) -> bool { match &self.launch { McpServerLaunch::Configured(config) => config.required, } }}/// Transport origin retained for metrics and diagnostics after server launch.#[derive(Debug, Clone, PartialEq, Eq)]pub(crate) enum McpServerOrigin { Stdio, StreamableHttp(String),}impl McpServerOrigin { pub fn as_str(&self) -> &str { match self { 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, pub default_tools_approval_mode: Option<AppToolApproval>, pub tool_approval_modes: HashMap<String, AppToolApproval>,}impl McpServerMetadata { pub fn tool_approval_mode(&self, tool_name: &str) -> AppToolApproval { self.tool_approval_modes .get(tool_name) .copied() .or(self.default_tools_approval_mode) .unwrap_or_default() }}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, default_tools_approval_mode: config.default_tools_approval_mode, tool_approval_modes: config .tools .iter() .filter_map(|(name, config)| { config .approval_mode .map(|approval_mode| (name.clone(), approval_mode)) }) .collect(), }, } }}