mirror of
https://github.com/openai/codex.git
synced 2026-11-10 08:43:33 +00:00
Give hosted Codex Apps an independent MCP protocol opt-in (#44318)
## Why Hosted Codex Apps shared the `mcp_2026_07_28` protocol setting with other MCP servers, preventing independent protocol selection. ## What changed - Add `features.codex_apps_mcp_2026_07_28`, disabled by default, for the host-owned HTTP `codex_apps` server. Enabling it attempts 2026-07-28 discovery with Legacy fallback. - Keep other servers, including third-party registrations with Apps-like names or URLs and local stdio servers, governed by `mcp_2026_07_28`. - Support the new flag through `experimentalFeature/enablement/set` and refresh protocol settings in existing sessions. Track protocol mode per server when deciding whether to reuse connections. ## Testing Add coverage for independent feature and protocol selection, hosted event-stream protocol selection, standalone Legacy defaults and discovery fallback, and runtime enablement refreshing an existing app-server thread. GitOrigin-RevId: 640e8e251f0c45e5f4829cc2b73c3082cf42f715
This commit is contained in:
1 parent
e1b23086ac
commit
eb680c0558
18 files changed
+431
-19
No files matched your search
@@ -7018,7 +7018,7 @@ async fn to_mcp_config_flows_mcp_tool_prefix_from_feature() -> std::io::Result<(
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn to_mcp_config_flows_mcp_2026_feature_from_config() -> std::io::Result<()> {
|
||||
async fn to_mcp_config_flows_independent_mcp_2026_features() -> std::io::Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
let mut config = Config::load_from_base_config_with_overrides(
|
||||
ConfigToml::default(),
|
||||
@@ -7030,13 +7030,42 @@ async fn to_mcp_config_flows_mcp_2026_feature_from_config() -> std::io::Result<(
|
||||
plugins_manager_for_config(&config, auth_manager_from_optional_auth(/*auth*/ None));
|
||||
|
||||
let mcp_config = config.to_mcp_config(&plugins_manager).await;
|
||||
assert_eq!(mcp_config.protocol_mode, codex_mcp::McpProtocolMode::Legacy);
|
||||
assert_eq!(
|
||||
(
|
||||
mcp_config.protocol_mode,
|
||||
mcp_config.host_owned_apps_protocol_mode,
|
||||
),
|
||||
(
|
||||
codex_mcp::McpProtocolMode::Legacy,
|
||||
codex_mcp::McpProtocolMode::Legacy,
|
||||
)
|
||||
);
|
||||
|
||||
let _ = config.features.enable(Feature::Mcp20260728);
|
||||
let mcp_config = config.to_mcp_config(&plugins_manager).await;
|
||||
assert_eq!(
|
||||
mcp_config.protocol_mode,
|
||||
codex_mcp::McpProtocolMode::V20260728
|
||||
(
|
||||
mcp_config.protocol_mode,
|
||||
mcp_config.host_owned_apps_protocol_mode,
|
||||
),
|
||||
(
|
||||
codex_mcp::McpProtocolMode::V20260728,
|
||||
codex_mcp::McpProtocolMode::Legacy,
|
||||
)
|
||||
);
|
||||
|
||||
let _ = config.features.disable(Feature::Mcp20260728);
|
||||
let _ = config.features.enable(Feature::CodexAppsMcp20260728);
|
||||
let mcp_config = config.to_mcp_config(&plugins_manager).await;
|
||||
assert_eq!(
|
||||
(
|
||||
mcp_config.protocol_mode,
|
||||
mcp_config.host_owned_apps_protocol_mode,
|
||||
),
|
||||
(
|
||||
codex_mcp::McpProtocolMode::Legacy,
|
||||
codex_mcp::McpProtocolMode::V20260728,
|
||||
)
|
||||
);
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -1792,6 +1792,11 @@ impl Config {
|
||||
Vec::new()
|
||||
},
|
||||
protocol_mode: self.mcp_protocol_mode(),
|
||||
host_owned_apps_protocol_mode: if self.features.enabled(Feature::CodexAppsMcp20260728) {
|
||||
McpProtocolMode::V20260728
|
||||
} else {
|
||||
McpProtocolMode::Legacy
|
||||
},
|
||||
client_elicitation_capability: if self.features.enabled(Feature::AuthElicitation) {
|
||||
ElicitationCapability::new()
|
||||
.with_form(FormElicitationCapability::new())
|
||||
|
||||
Reference in new issue
Block a user