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}