Add single-server MCP status discovery with thread connection reuse (#48783)

## Why

Inspecting one MCP server should not require full-inventory discovery or a separate connection when a thread already has one.

## What changed

- Add optional `serverName` to `mcpServerStatus/list` and update generated schemas and bindings.
- With `threadId`, apply any pending runtime refresh and reuse the thread's current connection and tool catalog, waiting only for the selected server during discovery.
- Without `threadId`, create a discovery connection for only the selected server. Unknown names return an empty page; omitting `serverName` preserves full-inventory discovery.

## Testing

Add a regression test covering both status detail modes, checking that tool metadata is preserved and that status reads do not repeat `initialize` or `tools/list` requests.

GitOrigin-RevId: 1b361b67a993ab45cae493e88c146f50cfaf753a
This commit is contained in:
victor-openai
2026-09-27 21:07:54 +00:00
committed by copyberry
parent 21eb35513d
commit ea64727556
27 changed files with 389 additions and 112 deletions
+19 -4
View File
@@ -1,5 +1,6 @@
use super::mcp_refresh::McpRefreshInvalidationGuard;
use super::*;
use crate::environment_selection::TurnEnvironmentSnapshot;
use crate::environment_selection::combine_selected_capability_roots;
use codex_exec_server::ExecutorCapabilityDiscoveryCache;
use codex_exec_server::ExecutorCapabilityDiscoverySnapshot;
@@ -147,19 +148,33 @@ impl Session {
.project_selected_environment_mcp_servers(config, &environments, mcp_projection)
.await
.config;
let runtime_context = self.mcp_runtime_context(&environments, &host_fallback_cwd);
(mcp_config, runtime_context)
}
pub(crate) async fn current_mcp_runtime_context(&self) -> McpRuntimeContext {
let host_fallback_cwd = self.state.lock().await.session_configuration.cwd().clone();
let environments = self.services.turn_environments.snapshot().await;
self.mcp_runtime_context(&environments, &host_fallback_cwd)
}
fn mcp_runtime_context(
&self,
environments: &TurnEnvironmentSnapshot,
host_fallback_cwd: &std::path::Path,
) -> McpRuntimeContext {
let local_process_cwd = environments
.local_environment_cwd()
.map(|cwd| cwd.to_path_buf())
.unwrap_or_else(|| host_fallback_cwd.to_path_buf());
let runtime_context = McpRuntimeContext::new(
McpRuntimeContext::new(
self.services.turn_environments.environment_manager(),
local_process_cwd,
)
.with_selected_environments(
environment_selections.into(),
environments.all_selections().into(),
environments.ready_environment_handles(),
);
(mcp_config, runtime_context)
)
}
pub(crate) async fn runtime_mcp_servers(