Skip to main content

matrixcode_core/mcp/
mod.rs

1//! MCP (Model Context Protocol) Integration
2//!
3//! 提供完整的 MCP 协议支持,允许连接任意 MCP 服务器并将其工具映射为内置工具。
4//!
5//! # 架构概览
6//!
7//! ```text
8//! ┌─────────────────────────────────────────────────────────────┐
9//! │  MatrixCode Agent                                           │
10//! │  ┌─────────────────────────────────────────────────────┐   │
11//! │  │  Tool System                                         │   │
12//! │  │  ┌─────────┐ ┌─────────┐ ┌───────────────────────┐ │   │
13//! │  │  │ Built-in│ │ CodeGraph│ │ MCP Tool Wrapper      │ │   │
14//! │  │  │ Tools   │ │ Tools    │ │ (Transparent Proxy)   │ │   │
15//! │  │  └─────────┘ └─────────┘ └───────────┬───────────┘ │   │
16//! │  └─────────────────────────────────────│───────────────┘   │
17//! └────────────────────────────────────────│───────────────────┘
18//!                                          │
19//! ┌─────────────────────────────────────────│───────────────────┐
20//! │  MCP Module                            │                    │
21//! │  ┌──────────────┐ ┌──────────────┐ ┌───┴───────┐           │
22//! │  │ Config       │ │ Transport    │ │ McpClient │           │
23//! │  │ (config.rs)  │ │ (transport.rs)│ │ (client.rs)│          │
24//! │  └──────────────┘ └──────────────┘ └─────┬─────┘           │
25//! └───────────────────────────────────────────│─────────────────┘
26//!                                            │ MCP Protocol
27//! ┌───────────────────────────────────────────│─────────────────┐
28//! │  External MCP Servers                     │                 │
29//! │  ┌─────────────┐ ┌─────────────┐ ┌───────┴───┐            │
30//! │  │ Playwright  │ │ Filesystem  │ │  Other    │            │
31//! │  │ MCP Server  │ │ MCP Server  │ │  MCP      │            │
32//! │  └─────────────┘ └─────────────┘ └───────────┘            │
33//! └─────────────────────────────────────────────────────────────┘
34//! ```
35//!
36//! # 快速开始
37//!
38//! ## 1. 配置 MCP 服务器
39//!
40//! 创建 `mcp.toml` 文件:
41//!
42//! ```toml
43//! [servers.playwright]
44//! command = "npx"
45//! args = ["-y", "@playwright/mcp@latest"]
46//!
47//! [servers.filesystem]
48//! command = "npx"
49//! args = ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/files"]
50//! ```
51//!
52//! ## 2. 连接并使用工具
53//!
54//! ```ignore
55//! use matrixcode_core::mcp::{McpConfig, McpToolManager};
56//!
57//! #[tokio::main]
58//! async fn main() -> anyhow::Result<()> {
59//!     // 加载配置
60//!     let config = McpConfig::from_file("mcp.toml")?;
61//!     
62//!     // 创建工具管理器
63//!     let manager = McpToolManager::new();
64//!     
65//!     // 连接所有服务器
66//!     for (key, server_config) in config.enabled_servers() {
67//!         let transport = server_config.to_transport_config()?;
68//!         let tools = manager.connect_server(&server_config.get_name(&key), transport).await?;
69//!         println!("Connected: {} tools", tools.len());
70//!     }
71//!     
72//!     // 获取所有工具
73//!     let tools = manager.get_tools().await;
74//!     
75//!     // 使用工具...
76//!     
77//!     // 关闭
78//!     manager.shutdown().await;
79//!     Ok(())
80//! }
81//! ```
82//!
83//! # 支持的传输方式
84//!
85//! - **Stdio**: 通过子进程 stdin/stdout 通信(推荐)
86//! - **SSE**: 通过 HTTP Server-Sent Events 通信(远程服务器)
87//!
88//! # 内置 MCP 配置
89//!
90//! 模块提供常用 MCP 服务器的预设配置:
91//!
92//! - `playwright_config()`: Playwright 浏览器自动化
93//! - `default_mcp_config()`: 常用配置组合
94
95pub mod types;
96pub mod transport;
97pub mod client;
98pub mod proxy;
99pub mod config;
100pub mod lazy;
101
102// Re-export main types
103pub use types::*;
104pub use transport::{Transport, TransportConfig, StdioTransport, SseTransport};
105pub use client::{McpClient, McpClientBuilder};
106pub use proxy::{McpToolWrapper, McpToolManager, connect_mcp_server, connect_mcp_servers_from_config};
107pub use config::{McpConfig, McpServerConfig, McpSettings, load_mcp_config, find_mcp_config};
108pub use lazy::{McpToolPlaceholder, McpToolRegistry, ServerStatus};
109
110// ============================================================================
111// Convenience Functions
112// ============================================================================
113
114/// 连接 Playwright MCP 服务器
115///
116/// # Example
117///
118/// ```ignore
119/// use matrixcode_core::mcp::connect_playwright;
120///
121/// #[tokio::main]
122/// async fn main() -> anyhow::Result<()> {
123///     let tools = connect_playwright().await?;
124///     println!("Playwright tools: {:?}", tools.iter().map(|t| t.definition().name).collect::<Vec<_>>());
125///     Ok(())
126/// }
127/// ```
128pub async fn connect_playwright() -> anyhow::Result<Vec<Box<dyn crate::tools::Tool>>> {
129    let config = config::playwright_config();
130    let (key, server) = config.enabled_servers()
131        .into_iter()
132        .next()
133        .ok_or_else(|| anyhow::anyhow!("No playwright config found"))?;
134    
135    let transport = server.to_transport_config()?;
136    connect_mcp_server(&server.get_name(&key), transport).await
137}
138
139/// 连接配置文件中的所有 MCP 服务器
140///
141/// 从当前目录或用户主目录查找 `mcp.toml` / `mcp.json` 配置文件,
142/// 并连接所有启用的 MCP 服务器。
143///
144/// # Example
145///
146/// ```ignore
147/// use matrixcode_core::mcp::connect_all_from_config;
148/// use std::path::Path;
149///
150/// #[tokio::main]
151/// async fn main() -> anyhow::Result<()> {
152///     let tools = connect_all_from_config(Path::new(".")).await?;
153///     println!("Total tools: {}", tools.len());
154///     Ok(())
155/// }
156/// ```
157pub async fn connect_all_from_config(
158    start_dir: &std::path::Path,
159) -> anyhow::Result<Vec<Box<dyn crate::tools::Tool>>> {
160    let config = load_mcp_config(start_dir);
161    let mut all_tools = Vec::new();
162    
163    for (key, server_config) in config.enabled_servers() {
164        match server_config.to_transport_config() {
165            Ok(transport) => {
166                let name = server_config.get_name(&key);
167                tracing::info!("Connecting to MCP server: {}", name);
168                
169                match connect_mcp_server(&name, transport).await {
170                    Ok(tools) => {
171                        tracing::info!("Connected to '{}' with {} tools", name, tools.len());
172                        all_tools.extend(tools);
173                    }
174                    Err(e) => {
175                        tracing::error!("Failed to connect to MCP server '{}': {}", name, e);
176                    }
177                }
178            }
179            Err(e) => {
180                tracing::error!("Invalid config for server '{}': {}", key, e);
181            }
182        }
183    }
184    
185    Ok(all_tools)
186}