mirror of
https://github.com/openai/codex.git
synced 2026-10-29 19:08:43 +00:00
Use issuing-step context for Guardian MCP elicitation reviews (#51067)
## Why MCP elicitation reviews used turn-start context, which could omit remote environments that became ready before the tool invocation and use stale environment permissions. ## What changed Capture the issuing step's Guardian review context with each live MCP invocation and reuse it for elicitation reviews. Fall back to turn context when no matching live invocation is available, and preserve the captured context for in-flight actions. ## Testing Extend the deferred-executor regression test to cover MCP elicitations, checking that Guardian receives the newly ready remote environment and its denied paths, excludes stale local denied paths, and returns the denial to the parent model. GitOrigin-RevId: 0cc58b8f30543a9af87d53e1a90f574a8e6a2f84
This commit is contained in:
@@ -255,8 +255,12 @@ pub(crate) async fn handle_mcp_tool_call(
|
||||
.unwrap_or_else(|| JsonValue::Object(serde_json::Map::new())),
|
||||
};
|
||||
}
|
||||
let _approval_metadata =
|
||||
sess.register_mcp_tool_approval_metadata(&call_id, &invocation, metadata.clone());
|
||||
let _approval_metadata = sess.register_mcp_tool_approval_metadata(
|
||||
&call_id,
|
||||
&invocation,
|
||||
metadata.clone(),
|
||||
GuardianReviewContext::from(step_context),
|
||||
);
|
||||
notify_mcp_tool_call_started(
|
||||
sess.as_ref(),
|
||||
turn_context.as_ref(),
|
||||
@@ -1189,20 +1193,29 @@ pub(crate) struct McpToolApprovalMetadata {
|
||||
openai_file_input_optional_fields: Option<HashMap<String, Vec<String>>>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct McpToolApprovalContext {
|
||||
pub(crate) invocation: Option<McpInvocation>,
|
||||
pub(crate) metadata: McpToolApprovalMetadata,
|
||||
pub(crate) review_context: GuardianReviewContext,
|
||||
}
|
||||
|
||||
impl Session {
|
||||
fn register_mcp_tool_approval_metadata(
|
||||
&self,
|
||||
call_id: &str,
|
||||
invocation: &McpInvocation,
|
||||
metadata: McpToolApprovalMetadata,
|
||||
) -> Arc<(Option<McpInvocation>, McpToolApprovalMetadata)> {
|
||||
review_context: GuardianReviewContext,
|
||||
) -> Arc<McpToolApprovalContext> {
|
||||
let key = (invocation.server.clone(), call_id.to_string());
|
||||
let metadata = Arc::new((
|
||||
(invocation.server == CODEX_APPS_MCP_SERVER_NAME
|
||||
let metadata = Arc::new(McpToolApprovalContext {
|
||||
invocation: (invocation.server == CODEX_APPS_MCP_SERVER_NAME
|
||||
|| is_node_repl_backed_server(&invocation.server))
|
||||
.then(|| invocation.clone()),
|
||||
metadata,
|
||||
));
|
||||
review_context,
|
||||
});
|
||||
let mut registry = self
|
||||
.mcp_tool_approval_metadata
|
||||
.lock()
|
||||
@@ -1218,7 +1231,7 @@ impl Session {
|
||||
&self,
|
||||
server: &str,
|
||||
call_id: &str,
|
||||
) -> Option<(Option<McpInvocation>, McpToolApprovalMetadata)> {
|
||||
) -> Option<McpToolApprovalContext> {
|
||||
self.mcp_tool_approval_metadata
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner)
|
||||
@@ -1627,7 +1640,7 @@ pub(crate) async fn request_mcp_tool_user_approval(
|
||||
let (request_dispatched, decision) = if tool_call_mcp_elicitation_enabled {
|
||||
let link_id = sess
|
||||
.mcp_tool_approval_metadata(server, id)
|
||||
.and_then(|(_, metadata)| metadata.link_id);
|
||||
.and_then(|context| context.metadata.link_id);
|
||||
let metadata = McpToolApprovalMetadata {
|
||||
annotations: None,
|
||||
connector_id: connector_id.clone(),
|
||||
|
||||
Reference in New Issue
Block a user