feat(protocols): MCP tool adapter + Tauri commands + initialize bug fix
Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled

S6 MCP Protocol:
- Fix McpTransport::initialize() — store actual server capabilities instead
  of discarding them and storing empty ServerCapabilities::default()
- Add send_notification() method to McpTransport for JSON-RPC notifications
- Send notifications/initialized after MCP handshake (spec requirement)
- Add McpToolAdapter: bridges MCP server tools into the tool execution path
- Add McpServiceManager: lifecycle management for MCP server connections
- Add 4 Tauri commands: mcp_start_service, mcp_stop_service,
  mcp_list_services, mcp_call_tool
- Register zclaw-protocols dependency in desktop Cargo.toml

New files:
- crates/zclaw-protocols/src/mcp_tool_adapter.rs (153 lines)
- desktop/src-tauri/src/kernel_commands/mcp.rs (145 lines)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
iven
2026-04-03 22:07:35 +08:00
parent cc26797faf
commit 943afe3b6b
7 changed files with 352 additions and 4 deletions

View File

@@ -176,11 +176,41 @@ impl McpTransport {
self.start().await?;
let request = InitializeRequest::default();
let _: InitializeResult = self.send_request("initialize", Some(&request)).await?;
let init_result: InitializeResult = self.send_request("initialize", Some(&request)).await?;
// Store capabilities
// Store actual server capabilities (not empty defaults)
let mut capabilities = self.capabilities.lock().await;
*capabilities = Some(ServerCapabilities::default());
*capabilities = Some(init_result.capabilities);
drop(capabilities);
// Send initialized notification (required by MCP spec)
self.send_notification(&InitializedNotification::new()).await?;
debug!(
server = %init_result.server_info.name,
version = %init_result.server_info.version,
protocol = %init_result.protocol_version,
"MCP server initialized"
);
Ok(())
}
/// Send JSON-RPC notification (no response expected)
async fn send_notification(&self, notification: &impl serde::Serialize) -> Result<()> {
let line = serde_json::to_string(notification)
.map_err(|e| ZclawError::McpError(format!("Failed to serialize notification: {}", e)))?;
let mut stdin_guard = self.stdin.lock().await;
let stdin = stdin_guard.as_mut()
.ok_or_else(|| ZclawError::McpError("Transport not started".to_string()))?;
stdin.write_all(line.as_bytes())
.map_err(|e| ZclawError::McpError(format!("Failed to write notification: {}", e)))?;
stdin.write_all(b"\n")
.map_err(|e| ZclawError::McpError(format!("Failed to write newline: {}", e)))?;
stdin.flush()
.map_err(|e| ZclawError::McpError(format!("Failed to flush notification: {}", e)))?;
Ok(())
}