mirror of
https://github.com/openai/codex.git
synced 2026-11-13 14:46:14 +00:00
Centralize thread MCP state in McpRuntime (#34930)
## What changed - Make `McpRuntime` own the published MCP configuration, connections, elicitation routing, and selected capability roots for a thread. - Capture immutable MCP bindings for model steps and tool calls so in-flight work keeps a consistent connection set and approval authority while refreshed state is published atomically. - Mark MCP state dirty when relevant configuration, plugins, environments, authentication, or elicitation capabilities change, then rebuild it before the next sampling request or out-of-band MCP operation. - Separate config reloads from server invalidation: `ReloadMcpConfig` applies resolved MCP inputs, while `RefreshMcpServers` requests reinitialization from the thread's latest state. ## Testing - Cover refreshed state visibility for existing turns, stable step bindings, current approval authority, cancelled refresh retries, resource-client reconciliation, and Apps recovery between sampling requests. GitOrigin-RevId: 59eabb1aa8dc083426bd18ef4d3630508f376401
This commit is contained in:
1 parent
39a2438d16
commit
e497325a6a
54 files changed
+1792
-2038
No files matched your search
@@ -6,6 +6,7 @@ use std::sync::atomic::Ordering;
|
||||
|
||||
use codex_config::AppToolApproval;
|
||||
use codex_config::Constrained;
|
||||
use codex_config::types::ApprovalsReviewer;
|
||||
use codex_protocol::mcp::McpServerInfo;
|
||||
use codex_protocol::models::PermissionProfile;
|
||||
use codex_protocol::protocol::AskForApproval;
|
||||
@@ -97,15 +98,20 @@ async fn test_step(
|
||||
SERVER_NAME.to_string(),
|
||||
Arc::clone(&managed_client),
|
||||
)])));
|
||||
let connections = Arc::new(McpConnectionSet::new_uninitialized_with_permission_profile(
|
||||
&Constrained::allow_any(AskForApproval::OnRequest),
|
||||
&PermissionProfile::default(),
|
||||
/*prefix_mcp_tool_names*/ true,
|
||||
));
|
||||
let connections = Arc::new(McpConnectionSet::empty(/*prefix_mcp_tool_names*/ true));
|
||||
let tool_catalog_revision = Arc::new(tokio::sync::RwLock::new(0));
|
||||
let mut config = crate::mcp::tests::test_mcp_config(std::env::temp_dir());
|
||||
if label == "old" {
|
||||
config.approval_policy = Constrained::allow_any(AskForApproval::Never);
|
||||
config.permission_profile = PermissionProfile::Disabled;
|
||||
} else {
|
||||
config.approvals_reviewer = ApprovalsReviewer::AutoReview;
|
||||
}
|
||||
let config = Arc::new(config);
|
||||
let prepared = PreparedMcpCall::new(
|
||||
Arc::clone(&connections),
|
||||
managed_client,
|
||||
Arc::clone(&config),
|
||||
/*catalog_revision*/ 0,
|
||||
Arc::clone(&tool_catalog_revision),
|
||||
tool.clone(),
|
||||
@@ -128,7 +134,7 @@ async fn test_step(
|
||||
step: Arc::new(McpBinding::new(
|
||||
connections,
|
||||
clients,
|
||||
Arc::new(crate::mcp::tests::test_mcp_config(std::env::temp_dir())),
|
||||
config,
|
||||
/*plugins_available*/ false,
|
||||
vec![tool],
|
||||
calls,
|
||||
@@ -206,6 +212,25 @@ async fn prepared_call_keeps_captured_connection_and_authority_after_refresh() -
|
||||
);
|
||||
assert!(Arc::ptr_eq(&old_call.client.client, &old.client));
|
||||
assert!(!Arc::ptr_eq(&old.client, &new.client));
|
||||
assert_eq!(
|
||||
(
|
||||
old_call.config().approval_policy.value(),
|
||||
&old_call.config().permission_profile,
|
||||
old_call.config().approvals_reviewer,
|
||||
),
|
||||
(
|
||||
AskForApproval::Never,
|
||||
&PermissionProfile::Disabled,
|
||||
ApprovalsReviewer::User,
|
||||
)
|
||||
);
|
||||
assert_eq!(
|
||||
(
|
||||
new_call.config().approval_policy.value(),
|
||||
new_call.config().approvals_reviewer,
|
||||
),
|
||||
(AskForApproval::OnRequest, ApprovalsReviewer::AutoReview)
|
||||
);
|
||||
|
||||
drop(old.step);
|
||||
assert!(
|
||||
|
||||
Reference in new issue
Block a user