mistralrs_mcp/
lib.rs

1//! Model Context Protocol (MCP) Client Implementation
2//!
3//! This crate provides a comprehensive client implementation for the Model Context Protocol (MCP),
4//! enabling AI assistants to connect to and interact with external tools and resources through
5//! standardized server interfaces.
6//!
7//! # Overview
8//!
9//! The MCP client supports multiple transport protocols and provides automatic tool discovery,
10//! registration, and execution. It seamlessly integrates with tool calling systems,
11//! allowing MCP tools to be used alongside built-in tools.
12//!
13//! # Features
14//!
15//! - **Multiple Transport Protocols**: HTTP, WebSocket, and Process-based connections
16//! - **Automatic Tool Discovery**: Discovers and registers tools from connected MCP servers
17//! - **Bearer Token Authentication**: Supports authentication for secured MCP servers
18//! - **Concurrent Tool Execution**: Handles multiple tool calls efficiently
19//! - **Resource Access**: Access to MCP server resources like files and data
20//! - **Tool Naming Prefix**: Avoid conflicts with customizable tool name prefixes
21//!
22//! # Transport Protocols
23//!
24//! ## HTTP Transport
25//!
26//! For MCP servers accessible via HTTP endpoints with JSON-RPC over HTTP.
27//! Supports both regular JSON responses and Server-Sent Events (SSE).
28//!
29//! ## WebSocket Transport
30//!
31//! For real-time bidirectional communication with MCP servers over WebSocket.
32//! Ideal for interactive applications requiring low-latency tool calls.
33//!
34//! ## Process Transport
35//!
36//! For local MCP servers running as separate processes, communicating via stdin/stdout
37//! using JSON-RPC messages.
38//!
39//! # Example Usage
40//!
41//! ## Simple Configuration
42//!
43//! ```rust,no_run
44//! use mistralrs_mcp::{McpClientConfig, McpServerConfig, McpServerSource, McpClient};
45//!
46//! #[tokio::main]
47//! async fn main() -> anyhow::Result<()> {
48//!     // Simple configuration with minimal settings
49//!     // Most fields use sensible defaults (enabled=true, UUID for id/prefix, no timeouts)
50//!     let config = McpClientConfig {
51//!         servers: vec![
52//!             McpServerConfig {
53//!                 name: "Hugging Face MCP Server".to_string(),
54//!                 source: McpServerSource::Http {
55//!                     url: "https://hf.co/mcp".to_string(),
56//!                     ..Default::default()
57//!                 },
58//!                 bearer_token: Some("hf_xxx".to_string()),
59//!                 ..Default::default()
60//!             },
61//!         ],
62//!         ..Default::default()
63//!     };
64//!     
65//!     // Initialize MCP client
66//!     let mut client = McpClient::new(config);
67//!     client.initialize().await?;
68//!     
69//!     // Get tool callbacks for integration with model builder
70//!     let tool_callbacks = client.get_tool_callbacks_with_tools();
71//!     println!("Registered {} MCP tools", tool_callbacks.len());
72//!     
73//!     Ok(())
74//! }
75//! ```
76//!
77//! ## Advanced Configuration
78//!
79//! ```rust,no_run
80//! use mistralrs_mcp::{McpClientConfig, McpServerConfig, McpServerSource, McpClient};
81//! use std::collections::HashMap;
82//!
83//! #[tokio::main]
84//! async fn main() -> anyhow::Result<()> {
85//!     // Configure MCP client with multiple servers and custom settings
86//!     let config = McpClientConfig {
87//!         servers: vec![
88//!             // HTTP server with Bearer token
89//!             McpServerConfig {
90//!                 id: "web_search".to_string(),
91//!                 name: "Web Search MCP".to_string(),
92//!                 source: McpServerSource::Http {
93//!                     url: "https://api.example.com/mcp".to_string(),
94//!                     timeout_secs: Some(30),
95//!                     headers: None,
96//!                 },
97//!                 enabled: true,
98//!                 tool_prefix: Some("web".to_string()),
99//!                 resources: None,
100//!                 bearer_token: Some("your-api-token".to_string()),
101//!             },
102//!             // WebSocket server
103//!             McpServerConfig {
104//!                 id: "realtime_data".to_string(),
105//!                 name: "Real-time Data MCP".to_string(),
106//!                 source: McpServerSource::WebSocket {
107//!                     url: "wss://realtime.example.com/mcp".to_string(),
108//!                     timeout_secs: Some(60),
109//!                     headers: None,
110//!                 },
111//!                 enabled: true,
112//!                 tool_prefix: Some("rt".to_string()),
113//!                 resources: None,
114//!                 bearer_token: Some("ws-token".to_string()),
115//!             },
116//!             // Process-based server
117//!             McpServerConfig {
118//!                 id: "filesystem".to_string(),
119//!                 name: "Filesystem MCP".to_string(),
120//!                 source: McpServerSource::Process {
121//!                     command: "mcp-server-filesystem".to_string(),
122//!                     args: vec!["--root".to_string(), "/tmp".to_string()],
123//!                     work_dir: None,
124//!                     env: None,
125//!                 },
126//!                 enabled: true,
127//!                 tool_prefix: Some("fs".to_string()),
128//!                 resources: Some(vec!["file://**".to_string()]),
129//!                 bearer_token: None,
130//!             },
131//!         ],
132//!         auto_register_tools: true,
133//!         tool_timeout_secs: Some(30),
134//!         max_concurrent_calls: Some(5),
135//!     };
136//!     
137//!     // Initialize MCP client
138//!     let mut client = McpClient::new(config);
139//!     client.initialize().await?;
140//!     
141//!     // Get tool callbacks for integration with model builder
142//!     let tool_callbacks = client.get_tool_callbacks_with_tools();
143//!     println!("Registered {} MCP tools", tool_callbacks.len());
144//!     
145//!     Ok(())
146//! }
147//! ```
148
149pub mod client;
150pub mod tools;
151pub mod transport;
152pub mod types;
153
154pub use client::{McpClient, McpServerConnection};
155pub use tools::{CalledFunction, Function, Tool, ToolCallback, ToolCallbackWithTool, ToolType};
156pub use types::McpToolResult;
157
158use serde::{Deserialize, Serialize};
159use std::collections::HashMap;
160use uuid::Uuid;
161
162/// Supported MCP server transport sources
163///
164/// Defines the different ways to connect to MCP servers, each optimized for
165/// specific use cases and deployment scenarios.
166#[derive(Debug, Clone, Serialize, Deserialize)]
167#[serde(tag = "type")]
168pub enum McpServerSource {
169    /// HTTP-based MCP server using JSON-RPC over HTTP
170    ///
171    /// Best for: Public APIs, RESTful services, servers behind load balancers
172    /// Features: SSE support, standard HTTP semantics, easy debugging
173    Http {
174        /// Base URL of the MCP server (http:// or https://)
175        url: String,
176        /// Optional timeout in seconds for HTTP requests
177        /// Defaults to no timeout if not specified.
178        timeout_secs: Option<u64>,
179        /// Optional headers to include in requests (e.g., API keys, custom headers)
180        headers: Option<HashMap<String, String>>,
181    },
182    /// Local process-based MCP server using stdin/stdout communication
183    ///
184    /// Best for: Local tools, development servers, sandboxed environments
185    /// Features: Process isolation, no network overhead, easy deployment
186    Process {
187        /// Command to execute (e.g., "mcp-server-filesystem")
188        command: String,
189        /// Arguments to pass to the command
190        args: Vec<String>,
191        /// Optional working directory for the process
192        work_dir: Option<String>,
193        /// Optional environment variables for the process
194        env: Option<HashMap<String, String>>,
195    },
196    /// WebSocket-based MCP server for real-time bidirectional communication
197    ///
198    /// Best for: Interactive applications, real-time data, low-latency requirements
199    /// Features: Persistent connections, server-initiated notifications, minimal overhead
200    WebSocket {
201        /// WebSocket URL (ws:// or wss://)
202        url: String,
203        /// Optional timeout in seconds for connection establishment
204        /// Defaults to no timeout if not specified.
205        timeout_secs: Option<u64>,
206        /// Optional headers for the WebSocket handshake
207        headers: Option<HashMap<String, String>>,
208    },
209}
210
211/// Configuration for MCP client integration
212///
213/// This structure defines how the MCP client should connect to and manage
214/// multiple MCP servers, including authentication, tool registration, and
215/// execution policies.
216#[derive(Debug, Clone, Serialize, Deserialize)]
217pub struct McpClientConfig {
218    /// List of MCP servers to connect to
219    pub servers: Vec<McpServerConfig>,
220    /// Whether to automatically register discovered tools with the model
221    ///
222    /// When enabled, tools from MCP servers are automatically converted to
223    /// the internal Tool format and registered for automatic tool calling.
224    pub auto_register_tools: bool,
225    /// Timeout for individual tool execution in seconds
226    ///
227    /// Controls how long to wait for a tool call to complete before timing out.
228    /// Defaults to no timeout if not specified.
229    pub tool_timeout_secs: Option<u64>,
230    /// Maximum number of concurrent tool calls across all MCP servers
231    ///
232    /// Limits resource usage and prevents overwhelming servers with too many
233    /// simultaneous requests. Defaults to 1 if not specified.
234    pub max_concurrent_calls: Option<usize>,
235}
236
237/// Configuration for an individual MCP server
238///
239/// Defines connection parameters, authentication, and tool management
240/// settings for a single MCP server instance.
241#[derive(Debug, Clone, Serialize, Deserialize)]
242#[serde(default)]
243pub struct McpServerConfig {
244    /// Unique identifier for this server
245    ///
246    /// Used internally to track connections and route tool calls.
247    /// Must be unique across all servers in a single MCP client configuration.
248    /// Defaults to a UUID if not specified.
249    #[serde(default = "generate_uuid")]
250    pub id: String,
251    /// Human-readable name for this server
252    ///
253    /// Used for logging, debugging, and user-facing displays.
254    pub name: String,
255    /// Transport-specific connection configuration
256    pub source: McpServerSource,
257    /// Whether this server should be activated
258    ///
259    /// Disabled servers are ignored during client initialization.
260    /// Defaults to true if not specified.
261    #[serde(default = "default_true")]
262    pub enabled: bool,
263    /// Optional prefix to add to all tool names from this server
264    ///
265    /// Helps prevent naming conflicts when multiple servers provide
266    /// tools with similar names. For example, with prefix "web",
267    /// a tool named "search" becomes "web_search".
268    /// Defaults to a UUID-based prefix if not specified.
269    #[serde(default = "generate_uuid_prefix")]
270    pub tool_prefix: Option<String>,
271    /// Optional resource URI patterns this server provides
272    ///
273    /// Used for resource discovery and subscription.
274    /// Supports glob patterns like "file://**" for filesystem access.
275    pub resources: Option<Vec<String>>,
276    /// Optional Bearer token for authentication
277    ///
278    /// Automatically included as "Authorization: Bearer <token>" header
279    /// for HTTP and WebSocket connections. Process connections typically
280    /// don't require authentication tokens.
281    pub bearer_token: Option<String>,
282}
283
284/// Information about a tool discovered from an MCP server
285#[derive(Debug, Clone)]
286pub struct McpToolInfo {
287    /// Name of the tool as reported by the MCP server
288    pub name: String,
289    /// Optional human-readable description of what the tool does
290    pub description: Option<String>,
291    /// JSON schema describing the tool's input parameters
292    pub input_schema: serde_json::Value,
293    /// ID of the server this tool comes from
294    ///
295    /// Used to route tool calls to the correct MCP server connection.
296    pub server_id: String,
297    /// Display name of the server for logging and debugging
298    pub server_name: String,
299}
300
301impl Default for McpClientConfig {
302    fn default() -> Self {
303        Self {
304            servers: Vec::new(),
305            auto_register_tools: true,
306            tool_timeout_secs: None,
307            max_concurrent_calls: Some(1),
308        }
309    }
310}
311
312fn generate_uuid() -> String {
313    Uuid::new_v4().to_string()
314}
315
316fn default_true() -> bool {
317    true
318}
319
320fn generate_uuid_prefix() -> Option<String> {
321    Some(format!("mcp_{}", Uuid::new_v4().simple()))
322}
323
324impl Default for McpServerConfig {
325    fn default() -> Self {
326        Self {
327            id: generate_uuid(),
328            name: String::new(),
329            source: McpServerSource::Http {
330                url: String::new(),
331                timeout_secs: None,
332                headers: None,
333            },
334            enabled: true,
335            tool_prefix: generate_uuid_prefix(),
336            resources: None,
337            bearer_token: None,
338        }
339    }
340}