Avoid blocking turns on optional MCP startup (#35742)

## Why

A pending optional MCP server can delay the first model request even when the
turn does not need that server.

## What changed

- Give optional MCP servers a shared one-second startup grace, then omit servers
  that are still pending from the captured tool catalog.
- Continue waiting when the turn explicitly requires a server through a plugin,
  skill dependency, or `mcp://` mention, and preserve this behavior for input
  received between sampling steps.
- Route direct resource requests to the live connection set when a pending
  server was omitted from the binding, while keeping all-server resource
  discovery non-blocking.

## Testing

- Cover the shared grace period and resource behavior for pending optional
  servers.
- Verify plugin, plugin-skill, and direct MCP mentions wait for startup.
- Verify an Apps-enabled turn proceeds without tools from an unrelated pending
  optional server.

GitOrigin-RevId: b5f895c5a5362fe73f7d33250367662d4a217e4d
This commit is contained in:
jif authored and copyberry committed 2026-07-28 09:32:48 +00:00
1 parent 8e271dc02b
commit d9e1c9cd55
12 files changed
+519 -58

No files matched your search

+7 -1
View File
@@ -260,6 +260,7 @@ impl Session {
self: &Arc<Self>,
turn_context: &TurnContext,
selected_capability_roots: &[ResolvedSelectedCapabilityRoot],
required_servers: &[String],
) -> Arc<codex_mcp::McpBinding> {
let ready_selected_capability_roots =
Self::ready_selected_capability_roots(selected_capability_roots);
@@ -272,7 +273,12 @@ impl Session {
self.mark_mcp_runtime_dirty();
}
self.refresh_mcp_if_dirty().await;
if let Some(binding) = self.services.mcp_runtime.current_binding().await {
if let Some(binding) = self
.services
.mcp_runtime
.current_binding_with_required_servers(required_servers)
.await
{
return binding;
}
let config = Arc::new(self.runtime_mcp_config(&turn_context.config).await);