diff --git a/codex-rs/codex-mcp/src/lib.rs b/codex-rs/codex-mcp/src/lib.rs index bfbe1c60f8..28674c8b35 100644 --- a/codex-rs/codex-mcp/src/lib.rs +++ b/codex-rs/codex-mcp/src/lib.rs @@ -1,6 +1,7 @@ pub(crate) mod mcp; pub(crate) mod mcp_connection_manager; pub(crate) mod mcp_tool_names; +mod tool_catalog; pub use mcp::CODEX_APPS_MCP_SERVER_NAME; pub use mcp::McpAuthStatusEntry; @@ -44,3 +45,7 @@ pub use mcp_connection_manager::ToolInfo; pub use mcp_connection_manager::codex_apps_tools_cache_key; pub use mcp_connection_manager::declared_openai_file_input_param_names; pub use mcp_connection_manager::filter_non_codex_apps_mcp_tools_only; +pub use tool_catalog::McpToolCatalog; +pub use tool_catalog::McpToolCatalogMerge; +pub use tool_catalog::McpToolCatalogSnapshot; +pub use tool_catalog::McpToolCatalogUpdate; diff --git a/codex-rs/core/src/mcp_tool_catalog.rs b/codex-rs/codex-mcp/src/tool_catalog.rs similarity index 88% rename from codex-rs/core/src/mcp_tool_catalog.rs rename to codex-rs/codex-mcp/src/tool_catalog.rs index 0e7350994a..f0dda2467e 100644 --- a/codex-rs/core/src/mcp_tool_catalog.rs +++ b/codex-rs/codex-mcp/src/tool_catalog.rs @@ -1,36 +1,37 @@ use std::collections::HashMap; -use codex_mcp::ToolInfo; -use codex_protocol::protocol::AdvertisedMcpToolCatalog; -use codex_protocol::protocol::AdvertisedMcpToolInfo; +use codex_protocol::mcp::AdvertisedMcpToolCatalog; +use codex_protocol::mcp::AdvertisedMcpToolInfo; use tracing::warn; +use crate::mcp_connection_manager::ToolInfo; + #[derive(Debug, Default)] -pub(crate) struct McpToolCatalog { +pub struct McpToolCatalog { has_servers: bool, tools: HashMap, } #[derive(Debug)] -pub(crate) struct McpToolCatalogUpdate { - pub(crate) has_servers: bool, - pub(crate) tools: HashMap, +pub struct McpToolCatalogUpdate { + pub has_servers: bool, + pub tools: HashMap, } #[derive(Debug)] -pub(crate) struct McpToolCatalogSnapshot { - pub(crate) has_servers: bool, - pub(crate) tools: HashMap, +pub struct McpToolCatalogSnapshot { + pub has_servers: bool, + pub tools: HashMap, } #[derive(Debug)] -pub(crate) struct McpToolCatalogMerge { - pub(crate) snapshot: McpToolCatalogSnapshot, - pub(crate) changed: bool, +pub struct McpToolCatalogMerge { + pub snapshot: McpToolCatalogSnapshot, + pub changed: bool, } impl McpToolCatalog { - pub(crate) fn merge(&mut self, update: McpToolCatalogUpdate) -> McpToolCatalogMerge { + pub fn merge(&mut self, update: McpToolCatalogUpdate) -> McpToolCatalogMerge { let McpToolCatalogUpdate { has_servers, tools } = update; let mut changed = false; if has_servers && !self.has_servers { @@ -49,21 +50,21 @@ impl McpToolCatalog { } } - pub(crate) fn snapshot(&self) -> McpToolCatalogSnapshot { + pub fn snapshot(&self) -> McpToolCatalogSnapshot { McpToolCatalogSnapshot { has_servers: self.has_servers, tools: self.tools.clone(), } } - pub(crate) fn resolve(&self, name: &str, namespace: Option<&str>) -> Option { + pub fn resolve(&self, name: &str, namespace: Option<&str>) -> Option { let qualified_name = qualified_mcp_tool_name(name, namespace); self.tools.get(&qualified_name).cloned() } } impl McpToolCatalogUpdate { - pub(crate) fn from_advertised(catalog: AdvertisedMcpToolCatalog) -> Self { + pub fn from_advertised(catalog: AdvertisedMcpToolCatalog) -> Self { let tools = catalog .tools .into_iter() @@ -85,7 +86,7 @@ impl McpToolCatalogUpdate { } impl McpToolCatalogSnapshot { - pub(crate) fn to_advertised(&self) -> Option { + pub fn to_advertised(&self) -> Option { if !self.has_servers && self.tools.is_empty() { return None; } diff --git a/codex-rs/core/src/codex.rs b/codex-rs/core/src/codex.rs index ecc24011e4..15b219f8c9 100644 --- a/codex-rs/core/src/codex.rs +++ b/codex-rs/core/src/codex.rs @@ -77,6 +77,8 @@ use codex_login::CodexAuth; use codex_login::auth_env_telemetry::collect_auth_env_telemetry; use codex_login::default_client::originator; use codex_mcp::McpConnectionManager; +use codex_mcp::McpToolCatalogSnapshot; +use codex_mcp::McpToolCatalogUpdate; use codex_mcp::SandboxState; use codex_mcp::ToolInfo; use codex_mcp::codex_apps_tools_cache_key; @@ -277,8 +279,6 @@ use crate::injection::tool_kind_for_path; use crate::instructions::UserInstructions; use crate::mcp::McpManager; use crate::mcp_skill_dependencies::maybe_prompt_and_install_mcp_dependencies; -use crate::mcp_tool_catalog::McpToolCatalogSnapshot; -use crate::mcp_tool_catalog::McpToolCatalogUpdate; use crate::memories; use crate::mentions::build_connector_slug_counts; use crate::mentions::build_skill_name_counts; diff --git a/codex-rs/core/src/codex_tests.rs b/codex-rs/core/src/codex_tests.rs index 72cb371704..ce14934a2b 100644 --- a/codex-rs/core/src/codex_tests.rs +++ b/codex-rs/core/src/codex_tests.rs @@ -10,8 +10,6 @@ use crate::config_loader::RequirementSource; use crate::config_loader::Sourced; use crate::exec::ExecCapturePolicy; use crate::function_tool::FunctionCallError; -use crate::mcp_tool_catalog::McpToolCatalog; -use crate::mcp_tool_catalog::McpToolCatalogUpdate; use crate::mcp_tool_exposure::DIRECT_MCP_TOOL_EXPOSURE_THRESHOLD; use crate::mcp_tool_exposure::build_mcp_tool_exposure; use crate::shell::default_user_shell; @@ -20,6 +18,8 @@ use crate::tools::format_exec_output_str; use codex_features::Features; use codex_login::CodexAuth; use codex_mcp::CODEX_APPS_MCP_SERVER_NAME; +use codex_mcp::McpToolCatalog; +use codex_mcp::McpToolCatalogUpdate; use codex_mcp::ToolInfo; use codex_model_provider_info::ModelProviderInfo; use codex_models_manager::bundled_models_response; diff --git a/codex-rs/core/src/lib.rs b/codex-rs/core/src/lib.rs index 34323a18a9..5e62199d2d 100644 --- a/codex-rs/core/src/lib.rs +++ b/codex-rs/core/src/lib.rs @@ -46,7 +46,6 @@ pub use landlock::spawn_command_under_linux_sandbox; pub(crate) mod mcp; mod mcp_skill_dependencies; mod mcp_tool_approval_templates; -mod mcp_tool_catalog; mod mcp_tool_exposure; mod network_policy_decision; pub(crate) mod network_proxy_loader; diff --git a/codex-rs/core/src/state/session.rs b/codex-rs/core/src/state/session.rs index 561b380024..a6edd5494d 100644 --- a/codex-rs/core/src/state/session.rs +++ b/codex-rs/core/src/state/session.rs @@ -9,10 +9,10 @@ use std::collections::HashSet; use crate::codex::PreviousTurnSettings; use crate::codex::SessionConfiguration; use crate::context_manager::ContextManager; -use crate::mcp_tool_catalog::McpToolCatalog; -use crate::mcp_tool_catalog::McpToolCatalogMerge; -use crate::mcp_tool_catalog::McpToolCatalogUpdate; use crate::session_startup_prewarm::SessionStartupPrewarmHandle; +use codex_mcp::McpToolCatalog; +use codex_mcp::McpToolCatalogMerge; +use codex_mcp::McpToolCatalogUpdate; use codex_mcp::ToolInfo; use codex_protocol::protocol::RateLimitSnapshot; use codex_protocol::protocol::TokenUsage; diff --git a/codex-rs/protocol/src/mcp.rs b/codex-rs/protocol/src/mcp.rs index f6e69743b9..a62a651792 100644 --- a/codex-rs/protocol/src/mcp.rs +++ b/codex-rs/protocol/src/mcp.rs @@ -3,9 +3,12 @@ //! //! We intentionally keep these types TS/JSON-schema friendly (via `ts-rs` and //! `schemars`) so they can be embedded in Codex's own protocol structures. +use std::collections::HashMap; + use schemars::JsonSchema; use serde::Deserialize; use serde::Serialize; +use serde_json::Value; use ts_rs::TS; /// ID of a request, which can be either a string or an integer. @@ -52,6 +55,43 @@ pub struct Tool { pub meta: Option, } +#[derive(Serialize, Deserialize, Debug, Clone, JsonSchema, TS)] +#[serde(rename_all = "camelCase")] +#[ts(rename_all = "camelCase")] +pub struct AdvertisedMcpToolCatalog { + pub has_servers: bool, + pub tools: HashMap, +} + +#[derive(Serialize, Deserialize, Debug, Clone, JsonSchema, TS)] +#[serde(rename_all = "camelCase")] +#[ts(rename_all = "camelCase")] +pub struct AdvertisedMcpToolInfo { + /// Raw MCP server name used for routing the tool call. + pub server_name: String, + /// Model-visible tool name used in Responses API tool declarations. + pub callable_name: String, + /// Model-visible namespace used for deferred tool loading. + pub callable_namespace: String, + /// Instructions from the MCP server initialize result. + #[serde(default, skip_serializing_if = "Option::is_none")] + #[ts(optional)] + pub server_instructions: Option, + /// Serialized raw MCP tool definition used to rebuild model-visible schemas on resume. + pub tool: Value, + #[serde(default, skip_serializing_if = "Option::is_none")] + #[ts(optional)] + pub connector_id: Option, + #[serde(default, skip_serializing_if = "Option::is_none")] + #[ts(optional)] + pub connector_name: Option, + #[serde(default)] + pub plugin_display_names: Vec, + #[serde(default, skip_serializing_if = "Option::is_none")] + #[ts(optional)] + pub connector_description: Option, +} + /// A known resource that the server is capable of reading. #[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema, TS)] #[serde(rename_all = "camelCase")] diff --git a/codex-rs/protocol/src/protocol.rs b/codex-rs/protocol/src/protocol.rs index fa309b9039..4debed61ba 100644 --- a/codex-rs/protocol/src/protocol.rs +++ b/codex-rs/protocol/src/protocol.rs @@ -28,6 +28,7 @@ use crate::dynamic_tools::DynamicToolCallRequest; use crate::dynamic_tools::DynamicToolResponse; use crate::dynamic_tools::DynamicToolSpec; use crate::items::TurnItem; +use crate::mcp::AdvertisedMcpToolCatalog; use crate::mcp::CallToolResult; use crate::mcp::RequestId; use crate::mcp::Resource as McpResource; @@ -2773,43 +2774,6 @@ pub struct SessionMetaLine { pub git: Option, } -#[derive(Serialize, Deserialize, Debug, Clone, JsonSchema, TS)] -#[serde(rename_all = "camelCase")] -#[ts(rename_all = "camelCase")] -pub struct AdvertisedMcpToolCatalog { - pub has_servers: bool, - pub tools: HashMap, -} - -#[derive(Serialize, Deserialize, Debug, Clone, JsonSchema, TS)] -#[serde(rename_all = "camelCase")] -#[ts(rename_all = "camelCase")] -pub struct AdvertisedMcpToolInfo { - /// Raw MCP server name used for routing the tool call. - pub server_name: String, - /// Model-visible tool name used in Responses API tool declarations. - pub callable_name: String, - /// Model-visible namespace used for deferred tool loading. - pub callable_namespace: String, - /// Instructions from the MCP server initialize result. - #[serde(default, skip_serializing_if = "Option::is_none")] - #[ts(optional)] - pub server_instructions: Option, - /// Serialized raw MCP tool definition used to rebuild model-visible schemas on resume. - pub tool: Value, - #[serde(default, skip_serializing_if = "Option::is_none")] - #[ts(optional)] - pub connector_id: Option, - #[serde(default, skip_serializing_if = "Option::is_none")] - #[ts(optional)] - pub connector_name: Option, - #[serde(default)] - pub plugin_display_names: Vec, - #[serde(default, skip_serializing_if = "Option::is_none")] - #[ts(optional)] - pub connector_description: Option, -} - #[derive(Serialize, Deserialize, Debug, Clone, JsonSchema, TS)] #[serde(tag = "type", content = "payload", rename_all = "snake_case")] pub enum RolloutItem {