Files
codex/codex-rs/ext/mcp/src/lib.rs
T
Evan Fannin ae0ecd7484 Add a manager for MCP event streams (#41906)
## What changed

- Add `McpEventStreamManager` to own event stream workers by thread and subscription.
- Wait for activation before completing a start, tag updates with a stream attempt ID, and keep active streams alive independently of their originating runtime.
- Support cancellation and shutdown without depending on output queue capacity, and close streams when MCP access changes or an event server is removed.
- Reconnect reloaded threads to surviving streams so server removal still cancels them.

## Testing

Add coverage for activation, replacement attempts, task reloads, cancellation before activation, full output queues, access changes, and shutdown.

GitOrigin-RevId: b7156bbe62f9375b2138eb62868f052124e2a884
2026-08-31 20:31:29 +00:00

69 lines
2.2 KiB
Rust

use codex_core::config::Config;
use codex_extension_api::ExtensionFuture;
use codex_extension_api::ExtensionRegistryBuilder;
use codex_extension_api::McpServerContribution;
use codex_extension_api::McpServerContributionContext;
use codex_extension_api::McpServerContributor;
use codex_mcp::CODEX_APPS_MCP_SERVER_NAME;
use codex_mcp::hosted_plugin_runtime_mcp_server_config;
#[cfg(test)]
#[path = "event_stream_tests.rs"]
mod event_stream_tests;
mod executor_plugin;
mod stream_manager;
pub use stream_manager::McpEventStreamManager;
pub use stream_manager::McpEventStreamUpdate;
#[cfg(test)]
#[path = "stream_manager_tests.rs"]
mod stream_manager_tests;
struct HostedPluginRuntimeExtension;
impl McpServerContributor<Config> for HostedPluginRuntimeExtension {
fn id(&self) -> &'static str {
"hosted_plugin_runtime"
}
fn contribute<'a>(
&'a self,
context: McpServerContributionContext<'a, Config>,
) -> ExtensionFuture<'a, Vec<McpServerContribution>> {
Box::pin(async move {
let config = context.config();
let name = CODEX_APPS_MCP_SERVER_NAME.to_string();
if !config.features.enabled(codex_features::Feature::Apps) {
return vec![McpServerContribution::Remove { name }];
}
vec![McpServerContribution::HostedApps {
config: Box::new(hosted_plugin_runtime_mcp_server_config(
&config.chatgpt_base_url,
config.apps_mcp_product_sku.as_deref(),
context.originator(),
)),
}]
})
}
}
pub fn install(builder: &mut ExtensionRegistryBuilder<Config>) {
builder.mcp_server_contributor(std::sync::Arc::new(HostedPluginRuntimeExtension));
}
/// Installs discovery for MCP servers declared by thread-selected executor plugins.
pub fn install_executor_plugins(
builder: &mut ExtensionRegistryBuilder<Config>,
environment_manager: std::sync::Arc<codex_exec_server::EnvironmentManager>,
) {
builder.mcp_server_contributor(std::sync::Arc::new(
executor_plugin::SelectedExecutorPluginMcpContributor::new(environment_manager),
));
}
#[cfg(test)]
#[path = "lib_tests.rs"]
mod tests;