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 client;
96pub mod config;
97pub mod lazy;
98pub mod proxy;
99pub mod transport;
100pub mod types;
101
102// Re-export main types
103pub use client::{McpClient, McpClientBuilder};
104pub use config::{McpConfig, McpServerConfig, McpSettings, find_mcp_config, load_mcp_config};
105pub use lazy::{McpToolPlaceholder, McpToolRegistry, ServerStatus};
106pub use proxy::{
107    McpToolManager, McpToolWrapper, connect_mcp_server, connect_mcp_servers_from_config,
108};
109pub use transport::{SseTransport, StdioTransport, Transport, TransportConfig};
110pub use types::*;
111
112// ============================================================================
113// Convenience Functions
114// ============================================================================
115
116/// 连接 Playwright MCP 服务器
117///
118/// # Example
119///
120/// ```ignore
121/// use matrixcode_core::mcp::connect_playwright;
122///
123/// #[tokio::main]
124/// async fn main() -> anyhow::Result<()> {
125///     let tools = connect_playwright().await?;
126///     println!("Playwright tools: {:?}", tools.iter().map(|t| t.definition().name).collect::<Vec<_>>());
127///     Ok(())
128/// }
129/// ```
130pub async fn connect_playwright() -> anyhow::Result<Vec<Box<dyn crate::tools::Tool>>> {
131    let config = config::playwright_config();
132    let (key, server) = config
133        .enabled_servers()
134        .into_iter()
135        .next()
136        .ok_or_else(|| anyhow::anyhow!("No playwright config found"))?;
137
138    let transport = server.to_transport_config()?;
139    connect_mcp_server(&server.get_name(&key), transport).await
140}
141
142/// 连接配置文件中的所有 MCP 服务器
143///
144/// 从当前目录或用户主目录查找 `mcp.toml` / `mcp.json` 配置文件,
145/// 并连接所有启用的 MCP 服务器。
146///
147/// # Example
148///
149/// ```ignore
150/// use matrixcode_core::mcp::connect_all_from_config;
151/// use std::path::Path;
152///
153/// #[tokio::main]
154/// async fn main() -> anyhow::Result<()> {
155///     let tools = connect_all_from_config(Path::new(".")).await?;
156///     println!("Total tools: {}", tools.len());
157///     Ok(())
158/// }
159/// ```
160pub async fn connect_all_from_config(
161    start_dir: &std::path::Path,
162) -> anyhow::Result<Vec<Box<dyn crate::tools::Tool>>> {
163    let config = load_mcp_config(start_dir);
164    let mut all_tools = Vec::new();
165
166    for (key, server_config) in config.enabled_servers() {
167        match server_config.to_transport_config() {
168            Ok(transport) => {
169                let name = server_config.get_name(&key);
170                tracing::info!("Connecting to MCP server: {}", name);
171
172                match connect_mcp_server(&name, transport).await {
173                    Ok(tools) => {
174                        tracing::info!("Connected to '{}' with {} tools", name, tools.len());
175                        all_tools.extend(tools);
176                    }
177                    Err(e) => {
178                        tracing::error!("Failed to connect to MCP server '{}': {}", name, e);
179                    }
180                }
181            }
182            Err(e) => {
183                tracing::error!("Invalid config for server '{}': {}", key, e);
184            }
185        }
186    }
187
188    Ok(all_tools)
189}