mirror of
https://github.com/openai/codex.git
synced 2026-09-17 12:23:33 +00:00
## Why Standard MCP forms can require user-entered values even when tool permissions are otherwise auto-approved in full-access sessions. ## What changed - Recognize the `openai/standard-form-input` client extension and surface non-approval forms in full-access, user-initiated root threads. - Keep approval forms, automation and subagent threads, headless sessions, and clients without the capability on their existing decline or review paths. - Treat the capability as client-only so it is not advertised to MCP servers, and enable it after session startup so required servers cannot block startup waiting for form input. ## Testing Add unit and app-server coverage for accepted form round trips, declined cases, approval metadata safeguards, resumed threads, and extension filtering. GitOrigin-RevId: 053bfe397a5c79eceef90a81d13e2aca6353af43
43 lines
1.4 KiB
Rust
43 lines
1.4 KiB
Rust
use std::collections::HashMap;
|
|
|
|
use codex_protocol::mcp::ClientMcpExtensions;
|
|
use codex_protocol::mcp::MCP_APP_UI_EXTENSION_ID;
|
|
use codex_protocol::mcp::OPENAI_FORM_EXTENSION_ID;
|
|
use codex_protocol::mcp::OPENAI_STANDARD_FORM_INPUT_EXTENSION_ID;
|
|
use serde_json::Map;
|
|
use serde_json::Value;
|
|
|
|
/// Selects the MCP extensions Codex supports from those declared by the app-server host.
|
|
///
|
|
/// App-server clients may declare unrelated extensions. Codex retains only the
|
|
/// trusted extension namespaces it knows how to project downstream. The
|
|
/// legacy form capability is normalized into the same extension map.
|
|
pub fn client_mcp_extensions(
|
|
extensions: Option<&HashMap<String, Value>>,
|
|
legacy_openai_form_elicitation: bool,
|
|
) -> ClientMcpExtensions {
|
|
let mut selected = extensions
|
|
.into_iter()
|
|
.flat_map(HashMap::iter)
|
|
.filter(|(id, _)| {
|
|
matches!(
|
|
id.as_str(),
|
|
OPENAI_FORM_EXTENSION_ID
|
|
| OPENAI_STANDARD_FORM_INPUT_EXTENSION_ID
|
|
| MCP_APP_UI_EXTENSION_ID
|
|
)
|
|
})
|
|
.map(|(id, value)| (id.clone(), value.clone()))
|
|
.collect::<HashMap<_, _>>();
|
|
if legacy_openai_form_elicitation {
|
|
selected
|
|
.entry(OPENAI_FORM_EXTENSION_ID.to_string())
|
|
.or_insert_with(|| Value::Object(Map::new()));
|
|
}
|
|
ClientMcpExtensions::new(selected)
|
|
}
|
|
|
|
#[cfg(test)]
|
|
#[path = "client_capabilities_tests.rs"]
|
|
mod tests;
|