Repository: https://github.com/doggy8088/mcp-cli Stars: 113 | Forks: 14 | Language: Rust | License: MIT npm: @willh/mcp-cli 最後更新: 2026-06-10
1. 專案概覽 (Project Overview)
1.1 什麼是 mcp-cli?
mcp-cli 是一套以 Rust 撰寫的輕量級 CLI (Command-Line Interface; 命令列介面) 工具與函式庫,專門用來與 MCP (Model Context Protocol; 模型上下文協定) 伺服器互動。
MCP 是一套讓 AI 模型透過標準化協定存取外部工具、API 與資料來源的開放標準。傳統做法是將所有 MCP tool schema 載入 AI 的 context window (上下文視窗),往往耗用數千 token。mcp-cli 採用「按需載入」的 CLI 模式,大幅降低 token 消耗,同時保留完整的 MCP 互動能力。
1.2 核心特色
| 特色 | 說明 |
|---|---|
| 輕量單一 Binary | 純 Rust 實作,零外部 runtime dependency (執行期依賴),編譯後為獨立執行檔 |
| Shell 友善 | call 指令輸出 JSON,可搭配 jq、pipe 與 shell script |
| Agent 導向 | 專為 AI coding agents (如 Gemini CLI、Claude Code) 設計 |
| 雙傳輸協定 | 同時支援 stdio (標準輸入輸出) 與 HTTP MCP 伺服器 |
| 連線池 Daemon | Lazy-spawn daemon 保留暖連線 (warm connection),預設 60 秒閒置逾時 |
| Tool 過濾 | 可透過 allowedTools / disabledTools 限制每個伺服器允許的工具 |
| Rust Library | 提供 McpClient API,可嵌入其他 Rust 應用程式 |
| 可操作錯誤訊息 | 所有錯誤包含結構化代碼、可用選項與修復建議 |
1.3 專案起源
此專案源自 Philipp Schmid 的 Bun/TypeScript mcp-cli,後由 Antigravity 完整改寫為高度最佳化的純 Rust 版本。目前由台灣知名技術社群貢獻者 Will 保哥 (doggy8088) 維護。
2. 核心架構 (Core Architecture)
2.1 模組架構總覽
mcp-cli 採用清晰的分層架構,將 CLI 界面、客戶端連線、設定管理與連線池 daemon 分離:
graph TB
subgraph "CLI 層 (main.rs)"
MAIN["main.rs
指令解析 + 路由"]
end
subgraph "指令層 (commands/)"
LIST["list.rs
列出所有 servers"]
INFO["info.rs
查看 server/tool 詳情"]
GREP["grep.rs
搜尋 tools"]
CALL["call.rs
呼叫 tool"]
end
subgraph "客戶端層 (client.rs)"
STDIO["StdioClient
stdio 傳輸"]
HTTP["HttpClient
HTTP/SSE 傳輸"]
CONN["McpConnection
統一連線介面"]
end
subgraph "基礎設施層"
CONFIG["config.rs
設定載入 + env 替換"]
DAEMON["daemon.rs
連線池 daemon"]
DCLIENT["daemon_client.rs
daemon IPC 客戶端"]
API["api.rs
McpClient 高階 API"]
ERRORS["errors.rs
結構化錯誤"]
OUTPUT["output.rs
格式化輸出"]
end
MAIN --> LIST & INFO & GREP & CALL
LIST & INFO & GREP & CALL --> CONN
CONN --> STDIO & HTTP
CONN --> DCLIENT
DCLIENT --> DAEMON
LIST & INFO & GREP & CALL --> CONFIG
API --> CONN & CONFIG
MAIN --> ERRORS
LIST & INFO & GREP & CALL --> OUTPUT
style MAIN fill:#4a90d9,color:#fff
style DAEMON fill:#e8a838,color:#fff
style API fill:#50c878,color:#fff
2.2 連線池 Daemon 機制
mcp-cli 最重要的架構設計是 lazy-spawn connection pooling daemon (延遲啟動連線池守護程序)。每個 MCP server 擁有獨立的 daemon,透過 Unix domain socket (Unix 域套接字) 進行 IPC (Inter-Process Communication; 行程間通訊):
sequenceDiagram
participant User as 使用者
participant CLI as mcp-cli
participant Socket as Unix Socket
/tmp/mcp-cli-{uid}/
participant Daemon as Daemon 程序
participant MCP as MCP Server
User->>CLI: mcp-cli call server tool '{}'
CLI->>Socket: 檢查 server.sock 是否存在?
alt Socket 不存在 (首次呼叫)
CLI->>Daemon: Fork 背景 daemon
Daemon->>MCP: 建立連線 (stdio/HTTP)
Daemon->>Socket: 建立 Unix socket
Daemon->>Daemon: 啟動 60s idle timer
CLI->>Socket: 連線到 socket
else Socket 已存在 (後續呼叫)
CLI->>Socket: 直接連線到 socket
end
CLI->>Daemon: 送出 JSON-RPC 請求
Daemon->>MCP: 轉發請求
MCP-->>Daemon: 回傳結果
Daemon-->>CLI: 回傳 JSON 結果
Daemon->>Daemon: 重置 idle timer
CLI-->>User: 輸出結果
Note over Daemon: 60 秒無請求後自動終止
2.3 設定檔解析順序
CLI 依以下順序尋找 mcp_servers.json 設定檔:
MCP_CONFIG_PATH環境變數-c/--config命令列參數./mcp_servers.json(當前目錄)~/.mcp_servers.json(家目錄)~/.config/mcp/mcp_servers.json(XDG 設定目錄)
2.4 錯誤處理機制
所有錯誤都透過 CliError 結構化表達,包含四個層級的資訊:
| 欄位 | 說明 | 範例 |
|---|---|---|
code | 錯誤分類代碼 | ClientError、ServerError、NetworkError、AuthError |
error_type | 錯誤類型字串 | AMBIGUOUS_COMMAND、SERVER_NOT_FOUND |
message | 人類可讀的錯誤描述 | Server "github" not found in config |
suggestion | 修復建議 | Use one of: mcp-cli info filesystem |
短暫性錯誤 (如 ECONNREFUSED、HTTP 502/503/504/429) 會自動以 exponential backoff (指數退避) 重試,預設最多 3 次。
3. 安裝與設定 (Installation & Setup)
3.1 安裝方式
有三種安裝方式可供選擇:
方式一:一鍵安裝腳本 (推薦)
1curl -fsSL https://raw.githubusercontent.com/doggy8088/mcp-cli/main/install.sh | bash
方式二:透過 Cargo 編譯安裝
1# 需要先安裝 Rust toolchain
2cargo install --git https://github.com/doggy8088/mcp-cli
方式三:透過 npm 安裝
1npm install -g @willh/mcp-cli
npm 套件是一層薄 wrapper,會從 GitHub Release 下載對應版本的原生 binary。
3.2 驗證安裝
1mcp-cli --version
2# 輸出: mcp-cli v0.1.1
3.3 建立設定檔
在專案目錄或 ~/.config/mcp/ 建立 mcp_servers.json:
1{
2 "mcpServers": {
3 "filesystem": {
4 "command": "npx",
5 "args": [
6 "-y",
7 "@modelcontextprotocol/server-filesystem",
8 "."
9 ]
10 },
11 "deepwiki": {
12 "url": "https://mcp.deepwiki.com/mcp"
13 }
14 }
15}
此設定檔格式完全相容 Claude Desktop、Gemini CLI 與 VS Code 的 MCP 設定。
3.4 設定檔進階功能
環境變數替換:在設定檔中使用 ${VAR_NAME} 語法,CLI 載入時會自動替換:
1{
2 "mcpServers": {
3 "github": {
4 "command": "npx",
5 "args": ["-y", "@modelcontextprotocol/server-github"],
6 "env": {
7 "GITHUB_TOKEN": "${GITHUB_TOKEN}"
8 }
9 }
10 }
11}
Tool 過濾:透過 allowedTools 與 disabledTools 控制可用工具:
1{
2 "mcpServers": {
3 "filesystem": {
4 "command": "npx",
5 "args": ["-y", "@modelcontextprotocol/server-filesystem", "."],
6 "allowedTools": ["read_*", "list_*"],
7 "disabledTools": ["delete_*"]
8 }
9 }
10}
disabledTools的優先順序高於allowedTools,支援 glob pattern (*、?)。
3.5 環境變數一覽
| 變數 | 說明 | 預設值 |
|---|---|---|
MCP_CONFIG_PATH | 設定檔路徑 | 無 |
MCP_DEBUG | 啟用 debug 輸出 | false |
MCP_TIMEOUT | Request timeout (秒) | 1800 (30 分鐘) |
MCP_CONCURRENCY | 平行處理的 servers 數量 | 5 |
MCP_MAX_RETRIES | 短暫錯誤的 retry 次數 | 3 |
MCP_RETRY_DELAY | Retry base delay (毫秒) | 1000 |
MCP_STRICT_ENV | ${VAR} 缺失時是否報錯 | true |
MCP_NO_DAEMON | 停用連線快取 | false |
MCP_DAEMON_TIMEOUT | Daemon idle timeout (秒) | 60 |
4. 使用方式與程式碼範例 (Usage & Code Examples)
4.1 指令總覽
1mcp-cli [options] 列出所有 servers 與 tools
2mcp-cli [options] info <server> 顯示 server 詳情
3mcp-cli [options] info <server> <tool> 顯示 tool schema
4mcp-cli [options] info <server>/<tool> 同上 (斜線分隔格式)
5mcp-cli [options] grep <pattern> 用 glob pattern 搜尋 tools
6mcp-cli [options] call <server> <tool> 呼叫 tool (無 args 時從 stdin 讀取)
7mcp-cli [options] call <server> <tool> <json> 使用 JSON arguments 呼叫 tool
| 選項 | 說明 |
|---|---|
-h, --help | 顯示說明 |
-v, --version | 顯示版本號 |
-d, --with-descriptions | 顯示 tool 描述 |
-c, --config <path> | 指定設定檔路徑 |
4.2 範例一:探索與查詢可用工具
這是最基本的工作流程,適合剛開始使用時了解有哪些 MCP server 與 tool 可用。
1# 步驟 1:列出所有 servers 與 tools
2$ mcp-cli
3github
4 • search_repositories
5 • get_file_contents
6 • create_or_update_file
7filesystem
8 • read_file
9 • write_file
10 • list_directory
11
12# 步驟 2:加上 -d 顯示每個 tool 的描述
13$ mcp-cli -d
14github
15 • search_repositories - Search for GitHub repositories
16 • get_file_contents - Get contents of a file or directory
17filesystem
18 • read_file - Read the contents of a file
19 • write_file - Write content to a file
20
21# 步驟 3:用 glob pattern 搜尋特定 tool
22$ mcp-cli grep "*file*"
23github/get_file_contents
24github/create_or_update_file
25filesystem/read_file
26filesystem/write_file
27
28# 步驟 4:查看特定 tool 的完整 schema
29$ mcp-cli info filesystem read_file
30Tool: read_file
31Server: filesystem
32
33Description:
34 Read the contents of a file
35
36Input Schema:
37 {
38 "type": "object",
39 "properties": {
40 "path": { "type": "string", "description": "Path to the file" }
41 },
42 "required": ["path"]
43 }
4.3 範例二:呼叫 Tool 並串接 Shell Pipeline
call 指令輸出原始 JSON,非常適合搭配 jq 與 shell 工具進行資料處理。
1# 基本呼叫:讀取檔案
2$ mcp-cli call filesystem read_file '{"path": "./README.md"}'
3
4# 搭配 jq 擷取特定欄位
5$ mcp-cli call github search_repositories '{"query": "mcp server", "per_page": 5}' \
6 | jq -r '.content[0].text | fromjson | .items[].html_url'
7
8# 從 stdin 讀取 JSON(避免 shell escaping 問題)
9$ echo '{"path": "./README.md"}' | mcp-cli call filesystem read_file
10
11# 使用 heredoc 處理含特殊字元的 JSON
12$ mcp-cli call server tool <<EOF
13{"content": "Text with 'single quotes' and \"double quotes\""}
14EOF
15
16# 進階串接:搜尋檔案後逐一讀取內容
17$ mcp-cli call filesystem search_files '{"path": ".", "pattern": "*.md"}' \
18 | jq -r '.content[0].text | split("\n")[]' \
19 | while read file; do
20 echo "=== $file ==="
21 mcp-cli call filesystem read_file "{\"path\": \"$file\"}" \
22 | jq -r '.content[0].text'
23 done
24
25# 條件式執行:先確認檔案存在再讀取
26$ mcp-cli call filesystem list_directory '{"path": "."}' \
27 | jq -e '.content[0].text | contains("README.md")' \
28 && mcp-cli call filesystem read_file '{"path": "./README.md"}'
29
30# 錯誤處理:在腳本中安全地呼叫 tool
31$ if result=$(mcp-cli call filesystem read_file '{"path": "./config.json"}' 2>/dev/null); then
32 echo "$result" | jq '.content[0].text | fromjson'
33 else
34 echo "File not found, using defaults"
35 fi
4.4 範例三:作為 Rust Library 嵌入使用
mcp-cli 也可以作為 Rust crate 在其他專案中使用。
在 Cargo.toml 加入依賴:
1[dependencies]
2mcp-cli = { git = "https://github.com/doggy8088/mcp-cli" }
使用 McpClient 高階 API:
1use mcp_cli::McpClient;
2
3#[tokio::main]
4async fn main() -> Result<(), mcp_cli::CliError> {
5 // 載入 mcp_servers.json 設定
6 let client = McpClient::load(None)?;
7
8 // 列出所有 server 名稱
9 for server in client.server_names() {
10 // 列出每個 server 的 tools
11 let tools = client.list_tools(&server).await?;
12 println!("{}: {} tools", server, tools.len());
13
14 // 顯示每個 tool 的名稱
15 for tool in &tools {
16 println!(" - {}", tool.name);
17 }
18 }
19
20 // 呼叫特定 tool
21 let result = client
22 .call_tool(
23 "filesystem",
24 "read_file",
25 serde_json::json!({ "path": "./README.md" }),
26 )
27 .await?;
28
29 // 格式化並輸出結果
30 println!("{}", mcp_cli::output::format_tool_result(&result));
31 Ok(())
32}
底層模組直接控制:
若需要更精細的控制,可直接使用底層模組:
1use mcp_cli::prelude::*;
2
3#[tokio::main]
4async fn main() -> Result<(), CliError> {
5 // 手動載入設定
6 let config = mcp_cli::config::load_config(Some("./my_config.json"))?;
7
8 // 取得特定 server 設定
9 let server_config = mcp_cli::config::get_server_config(&config, "filesystem")?;
10
11 // 手動建立連線
12 let connection = mcp_cli::client::get_connection("filesystem", &server_config).await?;
13
14 // 列出 tools
15 let tools = connection.list_tools().await?;
16 println!("Available tools: {:?}", tools);
17
18 // 呼叫 tool
19 let result = connection
20 .call_tool("read_file", serde_json::json!({"path": "."}))
21 .await?;
22
23 // 關閉連線
24 connection.close().await?;
25 Ok(())
26}
5. 技術細節深度解析 (Technical Deep Dive)
5.1 Rust 原始碼結構
1src/
2├── main.rs # CLI 進入點、指令解析、daemon 模式分支
3├── lib.rs # Library 公開介面 (re-exports + prelude)
4├── api.rs # McpClient 高階 API (library 使用者的主要介面)
5├── client.rs # StdioClient + HttpClient + McpConnection 統一介面
6├── config.rs # 設定檔載入、env 替換、tool filtering、hash 計算
7├── daemon.rs # 連線池 daemon 實作 (Unix socket listener)
8├── daemon_client.rs # Daemon IPC 客戶端 + orphan 清理
9├── errors.rs # CliError 結構化錯誤系統
10├── output.rs # ServerInfo / ToolInfo 格式化輸出
11└── commands/
12 ├── mod.rs # 指令模組匯出
13 ├── list.rs # `mcp-cli` (無子指令) — 列出所有 servers
14 ├── info.rs # `mcp-cli info` — 查看 server/tool 詳情
15 ├── grep.rs # `mcp-cli grep` — 搜尋 tools
16 └── call.rs # `mcp-cli call` — 呼叫 tool
5.2 雙傳輸協定 (Dual Transport)
mcp-cli 透過 ServerConfig enum (列舉) 支援兩種傳輸協定:
| 傳輸方式 | 設定格式 | 適用情境 |
|---|---|---|
| Stdio | "command": "npx", "args": [...] | 本地 MCP server (透過 subprocess 啟動) |
| HTTP | "url": "https://..." | 遠端 MCP server (HTTP + SSE 串流) |
Stdio 模式使用 JSON-RPC over stdin/stdout,透過 tokio::process::Command 非同步管理子程序。HTTP 模式使用 reqwest 搭配 Server-Sent Events (SSE; 伺服器推送事件) 串流接收回應。
5.3 Daemon 連線池設計
Daemon 機制是 mcp-cli 最核心的效能最佳化:
- 首次呼叫:CLI 偵測到
/tmp/mcp-cli-{uid}/server.sock不存在時,fork 自身為 daemon 模式 (--daemonflag) - Daemon 啟動:建立 MCP server 連線 + Unix socket listener + PID file (含 config hash)
- 後續呼叫:CLI 直接透過 Unix socket 與 daemon 通訊,跳過 MCP server 啟動延遲
- Config 偵測:若設定檔 hash 變更,daemon 會被 respawn
- Idle timeout:60 秒無請求後 daemon 自動終止,清理 socket + PID file
- Fallback:daemon spawn 逾時 (5 秒) 時,退回 direct connection
5.4 Tool Filtering 實作
Tool filtering 使用 glob-to-regex 轉換,支援 * (任意字元) 和 ? (單一字元):
1// 實際的 matching 邏輯 (簡化)
2fn matches_pattern(name: &str, pattern: &str) -> bool {
3 // 將 glob pattern 轉換為 regex
4 // "*" -> ".*", "?" -> "."
5 // Case-insensitive matching
6}
7
8fn is_tool_allowed(tool_name: &str, config: &ServerConfig) -> bool {
9 // 1. 先檢查 disabledTools -> 命中則 return false
10 // 2. 再檢查 allowedTools -> 有設定時必須命中才 return true
11 // 3. 兩者都未設定 -> return true (全部允許)
12}
5.5 編譯最佳化
Cargo.toml 中的 [profile.release] 設定了極致的 binary 最佳化:
1[profile.release]
2opt-level = 3 # 最高最佳化等級
3lto = true # Link-Time Optimization (連結期最佳化)
4codegen-units = 1 # 單一編譯單元 (更慢的編譯,更快的 binary)
5panic = "abort" # Panic 時直接 abort (減少 binary 大小)
6strip = true # 移除 debug symbols
這些設定讓最終 binary 體積小、啟動快,特別適合作為 CLI 工具使用。
5.6 指令歧義偵測
main.rs 中實作了智慧型指令歧義偵測。當使用者輸入 mcp-cli server tool (缺少子指令) 時,CLI 不會猜測意圖,而是明確回報:
1Error [AMBIGUOUS_COMMAND]: Ambiguous command: did you mean to call a tool or view info?
2 Details: Received: mcp-cli filesystem read_file
3 Suggestion: Use 'mcp-cli call filesystem read_file' to execute,
4 or 'mcp-cli info filesystem read_file' to view schema
同時也會偵測常見的錯誤子指令 (如 run、execute、list、get) 並提供正確的替代建議。
6. 與生態系的關係 (Ecosystem Relationships)
6.1 MCP 生態系定位
graph LR
subgraph "AI Agents"
CC["Claude Code"]
GC["Gemini CLI"]
OC["OpenCode"]
CUR["Cursor"]
end
subgraph "MCP 存取方式"
NATIVE["原生 MCP SDK
(載入全部 schema)"]
MCPCLI["mcp-cli
(按需 CLI 存取)"]
end
subgraph "MCP Servers"
FS["filesystem
檔案系統"]
GH["github
GitHub API"]
DW["deepwiki
技術文件"]
DB["sqlite
資料庫"]
CUSTOM["自訂 server"]
end
CC --> NATIVE & MCPCLI
GC --> MCPCLI
OC --> MCPCLI
CUR --> NATIVE
NATIVE --> FS & GH & DW & DB & CUSTOM
MCPCLI --> FS & GH & DW & DB & CUSTOM
style MCPCLI fill:#e8a838,color:#fff,stroke:#d4942e
style NATIVE fill:#ccc,color:#333
6.2 與原生 MCP SDK 的比較
| 面向 | 原生 MCP SDK | mcp-cli |
|---|---|---|
| Token 消耗 | 高 (載入全部 tool schema) | 低 (按需查詢) |
| 啟動速度 | 每次都需初始化連線 | Daemon 暖連線 |
| 整合方式 | 程式庫嵌入 | CLI + Shell pipeline |
| 適用場景 | 內建 MCP 支援的 IDE | 任何支援 shell 的 agent |
| 組合彈性 | 受限於 SDK API | 可搭配任何 Unix 工具 |
6.3 與其他 AI Agent 工具的整合
方式一:System Prompt 整合
將 mcp-cli 的使用說明加入 AI agent 的 system prompt,讓 agent 透過 shell 呼叫 MCP tool。
方式二:SKILL.md Agent Skill
對支援 Agent Skills 的工具 (如 Gemini CLI、Claude Code),可直接使用 repo 中的 SKILL.md 作為技能文件。
6.4 設定檔相容性
mcp_servers.json 的格式完全相容以下工具:
- Claude Desktop (
claude_desktop_config.json的mcpServers段落) - Gemini CLI
- VS Code MCP 擴充功能
- 其他遵循 MCP 標準設定格式的工具
7. 優缺點分析 (Strengths & Limitations)
7.1 優點
| 面向 | 詳細說明 |
|---|---|
| 效能 | Rust 原生編譯 + release 最佳化 (LTO + strip),啟動與執行速度極快 |
| Token 節省 | 按需載入 tool schema,不需將全部 schema 塞入 context window |
| 零依賴 | 單一 binary,不需要 Node.js、Python 或其他 runtime |
| Shell 整合 | JSON 輸出 + pipe 友善,可無縫融入 Unix 工具鏈 |
| 連線池 | Daemon 機制避免重複啟動 MCP server,大幅降低延遲 |
| 錯誤訊息品質 | 結構化錯誤 + 修復建議,對人類與 AI agent 都友善 |
| Tool 過濾 | 可精確控制每個 server 暴露的工具,提升安全性 |
| 設定相容 | 與 Claude Desktop、Gemini CLI 等主流工具共用設定檔 |
| 雙用途 | 同時提供 CLI binary 與 Rust library API |
7.2 限制
| 面向 | 詳細說明 |
|---|---|
| 平台支援 | Daemon 使用 Unix domain socket,Windows 支援需要額外處理 |
| 學習曲線 | 需要理解 MCP 協定基本概念 |
| 無 GUI | 純 CLI 工具,沒有圖形介面或 TUI |
| 版本尚早 | v0.1.1,API 可能在後續版本有 breaking changes |
| 僅限 MCP | 專為 MCP 設計,無法直接用於其他 RPC 協定 |
| Daemon 清理 | 異常終止時可能留下 orphaned socket 需手動清理 |
7.3 適用場景
最適合:
- AI coding agent 需要存取 MCP server 但想節省 token
- 需要在 shell script 中自動化 MCP 操作
- 在 CI/CD pipeline (持續整合/持續部署流水線) 中操作 MCP 工具
- 多個 agent 或工具需要共享 MCP 連線池
不太適合:
- 需要即時 streaming UI 的應用程式
- 需要在瀏覽器中直接使用 MCP 的場景
- 只使用單一 IDE (已內建 MCP 支援) 的開發者
7.4 總結
mcp-cli 是一個設計精良的 Rust CLI 工具,巧妙地解決了 AI agent 使用 MCP 時的 token 消耗問題。透過連線池 daemon、按需載入與 shell 友善的設計,讓任何支援 shell 的 AI agent 都能高效存取 MCP 工具生態系。對於在多個 AI agent 間共享 MCP 設定、或需要在自動化腳本中操作 MCP 的場景,mcp-cli 是目前最佳的解決方案之一。
Comments