fix(mcp): stdio/unix transports skip initialize handshake (#890) (#935)

fixes #890

  - Always call initialize() before list_tools()/call_tool(), removing
    the session_manager.is_some() guard that caused stdio/unix clients
    to skip the MCP protocol handshake entirely
  - Add local AtomicBool flag for idempotent initialization when no
    session manager is present
  - Fire-and-forget JSON-RPC notifications (id=None) in stdio/unix
    transports instead of registering a pending response that would
    block for 30s waiting on a reply that never comes
  - Fix mcp test panic on stdio/unix servers by using
    create_client_from_config() instead of new_with_config() which
    asserts HTTP-only transport
This commit is contained in:
Reid
2026-03-11 16:46:40 -07:00
committed by GitHub
parent 6321bb4688
commit c8cac0925d
4 changed files with 138 additions and 22 deletions
+14 -4
View File
@@ -12,9 +12,10 @@ use crate::config::Config;
use crate::db::Database;
use crate::secrets::SecretsStore;
use crate::tools::mcp::{
McpClient, McpServerConfig, McpSessionManager, OAuthConfig,
McpClient, McpProcessManager, McpServerConfig, McpSessionManager, OAuthConfig,
auth::{authorize_mcp_server, is_authenticated},
config::{self, EffectiveTransport, McpServersFile},
factory::create_client_from_config,
};
/// Arguments for the `mcp add` subcommand.
@@ -494,7 +495,7 @@ async fn test_server(name: String, user_id: String) -> anyhow::Result<()> {
let client = if has_tokens {
// We have stored tokens, use authenticated client
McpClient::new_authenticated(server.clone(), session_manager, secrets, user_id)
McpClient::new_authenticated(server.clone(), session_manager.clone(), secrets, user_id)
} else if server.requires_auth() {
// OAuth configured but no tokens - need to authenticate
println!();
@@ -505,8 +506,17 @@ async fn test_server(name: String, user_id: String) -> anyhow::Result<()> {
println!();
return Ok(());
} else {
// No OAuth and no tokens - try unauthenticated
McpClient::new_with_config(server.clone())
// Use the factory to dispatch on transport type (HTTP, stdio, unix)
let process_manager = Arc::new(McpProcessManager::new());
create_client_from_config(
server.clone(),
&session_manager,
&process_manager,
None,
"default",
)
.await
.map_err(|e| anyhow::anyhow!("{}", e))?
};
// Test connection