Skip to main content

agentic_evolve_mcp/protocol/
negotiation.rs

1//! MCP capability negotiation during initialization.
2
3use crate::types::{
4    ClientCapabilities, InitializeParams, InitializeResult, McpError, McpResult, MCP_VERSION,
5};
6
7/// Stored client capabilities after negotiation.
8#[derive(Debug, Clone, Default)]
9pub struct NegotiatedCapabilities {
10    /// The client's declared capabilities.
11    pub client: ClientCapabilities,
12    /// Whether the handshake is complete.
13    pub initialized: bool,
14}
15
16impl NegotiatedCapabilities {
17    /// Process an initialize request and return the result.
18    pub fn negotiate(&mut self, params: InitializeParams) -> McpResult<InitializeResult> {
19        // Verify protocol version compatibility
20        if params.protocol_version != MCP_VERSION {
21            tracing::warn!(
22                "Client requested protocol version {}, server supports {}. Proceeding with server version.",
23                params.protocol_version,
24                MCP_VERSION
25            );
26        }
27
28        self.client = params.capabilities;
29
30        tracing::info!(
31            "Initialized with client: {} v{}",
32            params.client_info.name,
33            params.client_info.version
34        );
35
36        Ok(InitializeResult::default_result())
37    }
38
39    /// Mark the handshake as complete (after receiving `initialized` notification).
40    pub fn mark_initialized(&mut self) -> McpResult<()> {
41        self.initialized = true;
42        tracing::info!("MCP handshake complete");
43        Ok(())
44    }
45
46    /// Check that the handshake is complete before processing requests.
47    #[allow(dead_code)]
48    pub fn ensure_initialized(&self) -> McpResult<()> {
49        if !self.initialized {
50            return Err(McpError::InvalidRequest(
51                "Server not yet initialized. Send 'initialize' first.".to_string(),
52            ));
53        }
54        Ok(())
55    }
56}