🚀 SSH 聯絡 MCP 服務器
SSH 聯絡 MCP 服務器藉助模型上下文協議(MCP)實現有狀態的 SSH 連接和命令執行,為用戶提供了一種高效、穩定的 SSH 操作方式。
✨ 主要特性
| 特性 |
描述 |
| 🔄 有狀態會話 |
核心特性:在 MCP 工具調用之間保留 shell 狀態(當前目錄、環境變量、工作目錄)。每個命令都在同一個持久 shell 會話中運行,支持多步驟工作流。 |
| 🔌 MCP 服務器模式 |
與 Cursor/Claude Desktop 集成,實現由 AI 輔助的有狀態命令執行的 SSH 操作。 |
| ⚙️ SSH 配置支持 |
使用 ~/.ssh/config 進行主機別名和連接參數配置。 |
| 🔐 直接連接 |
無需 SSH 配置,直接使用用戶、主機名、密碼和端口進行連接。 |
| 💻 獨立 CLI 模式 |
提供交互式終端,用於調試和測試(詳見下文)。 |
📦 安裝指南
預構建二進制文件
從 發佈頁面 下載適用於您平臺的最新版本。
可用平臺:
- macOS(Intel x86_64、Apple Silicon aarch64)
- Linux(x86_64、aarch64)
- Windows(x86_64)
curl -LO https://github.com/Citizen4our/ssh-liaison-mcp/releases/latest/download/ssh-liaison-mcp-aarch64-apple-darwin.tar.gz
tar -xzf ssh-liaison-mcp-aarch64-apple-darwin.tar.gz
curl -LO https://github.com/Citizen4our/ssh-liaison-mcp/releases/latest/download/ssh-liaison-mcp-x86_64-apple-darwin.tar.gz
tar -xzf ssh-liaison-mcp-x86_64-apple-darwin.tar.gz
curl -LO https://github.com/Citizen4our/ssh-liaison-mcp/releases/latest/download/ssh-liaison-mcp-x86_64-unknown-linux-gnu.tar.gz
tar -xzf ssh-liaison-mcp-x86_64-unknown-linux-gnu.tar.gz
從源代碼構建
git clone https://github.com/Citizen4our/ssh-liaison-mcp.git
cd ssh-liaison-mcp
cargo build --release
二進制文件將位於 target/release/ssh-liaison-mcp。
🚀 快速開始
MCP 服務器模式(主要用例)
此服務器的主要特性是 有狀態的 SSH 會話 —— 每個 SSH 連接都維護一個持久的 shell 會話,在 MCP 工具調用之間保留狀態(當前目錄、環境變量等)。這使得命令可以相互依賴,實現自然的多步驟工作流。
有狀態會話的工作原理
當您通過 ssh_connect 連接到主機時,會建立一個持久的 shell 會話。該主機的所有後續 ssh_run_command 調用都在 同一個 shell 會話 中執行,這意味著:
- 當前目錄得以保留:如果您在一個命令中執行
cd /var/log,下一個命令將從 /var/log 開始執行。
- 環境變量持久化:使用
export 設置的變量在後續命令中仍然可用。
- shell 狀態得以維護:歷史記錄、別名和其他 shell 狀態在調用之間保持不變。
- 高效性:無需為每個命令重新連接或重新建立上下文。
示例工作流:
1. ssh_connect("production") → 建立持久 shell 會話
2. ssh_run_command("production", "cd /var/log") → 更改目錄
3. ssh_run_command("production", "pwd") → 返回 "/var/log"(狀態已保留!)
4. ssh_run_command("production", "ls -la") → 列出 /var/log 中的文件
對於 Cursor IDE
- 構建二進制文件:
cargo build --release
- 添加到 Cursor 設置(
~/.cursor/mcp.json 或 Cursor 設置界面):
{
"mcpServers": {
"ssh-liaison": {
"command": "/absolute/path/to/ssh-liaison-mcp",
"args": ["serve"]
}
}
}
- 重啟 Cursor
對於 Claude Desktop
- 構建二進制文件:
cargo build --release
- 添加到 Claude Desktop 配置(macOS 上為
~/Library/Application Support/Claude/claude_desktop_config.json):
{
"mcpServers": {
"ssh-liaison": {
"command": "/absolute/path/to/ssh-liaison-mcp",
"args": ["serve"]
}
}
}
- 重啟 Claude Desktop
舊版直接連接模式
為了向後兼容:
cargo run -- connect <user> <host> [--port <port>]
🔧 技術細節
SSH 配置
服務器從 ~/.ssh/config 讀取主機別名。這是推薦的連接方式,因為它集中管理了連接設置。
示例 SSH 配置
# 簡單主機別名
Host rpi
HostName 192.168.1.100
User pi
Port 22
IdentityFile ~/.ssh/id_ed25519
# 帶有自定義端口的生產服務器
Host production
HostName prod.example.com
User deploy
Port 2222
IdentityFile ~/.ssh/deploy_key
# 開發服務器
Host dev
HostName dev.example.com
User developer
IdentityFile ~/.ssh/id_rsa
MCP 工具
作為 MCP 服務器運行時,可使用以下工具:
| 工具 |
描述 |
參數 |
| ssh_connect |
連接到遠程 SSH 服務器並建立一個 持久的 shell 會話。該會話在後續命令調用之間保持狀態。 |
host_alias(字符串) - SSH 配置中定義的主機別名 |
| ssh_connect_direct |
直接使用用戶、主機名/IP、可選密碼和可選端口連接到遠程 SSH 服務器。建立一個 持久的 shell 會話,在後續命令調用之間保持狀態。身份驗證首先嚐試 SSH 密鑰,然後在提供密碼且 SSH 密鑰驗證失敗時使用密碼。 |
host_alias(字符串) - 用於標識此連接的主機別名,user(字符串) - SSH 用戶名,hostname(字符串) - 主機名或 IP 地址,password(字符串,可選) - SSH 密碼(如果 SSH 密鑰驗證失敗或不可用),port(整數,可選) - SSH 端口(默認:22) |
| ssh_run_command |
在連接的主機上的 同一個持久 shell 會話 中執行命令。當前目錄、環境變量和 shell 狀態從之前的命令中保留。 |
host(字符串) - 主機別名,command(字符串) - 要執行的命令 |
| ssh_read_log |
使用持久的 shell 會話從日誌文件中讀取最後 N 行。 |
host(字符串) - 主機別名,file_path(字符串) - 日誌文件的路徑,lines(整數) - 要讀取的行數 |
重要注意事項:
- 有狀態:同一主機的所有命令都在同一個持久 shell 會話中運行。
- 連接方法:
- 使用
ssh_connect 進行基於 SSH 配置的連接(需要 ~/.ssh/config)。
- 使用
ssh_connect_direct 進行無需 SSH 配置的直接連接。
- 身份驗證順序(對於
ssh_connect_direct):
- SSH 密鑰(SSH 代理,然後是常見密鑰文件)
- 密碼(如果提供且 SSH 密鑰驗證失敗)
- 會話持久性:一旦連接,會話將保持活動狀態,直到 MCP 服務器重啟或顯式斷開連接。
- 安全性:
ssh_connect_direct 中的密碼通過 SSH 協議安全傳輸(加密)。在可用時,首選 SSH 密鑰身份驗證。
MCP 模式的示例提示
MCP 服務器配置完成後,您可以要求 AI 助手執行 SSH 操作:
示例 1:
用戶:連接到 rpi 並顯示當前目錄和磁盤使用情況
AI 響應:
我將連接到 rpi 併為您檢查當前目錄和磁盤使用情況。
[正在連接到 rpi...]
當前目錄:/home/pi
磁盤使用情況:
Filesystem Size Used Avail Use% Mounted on
/dev/root 15G 5.2G 8.8G 38% /
/dev/mmcblk0p1 253M 49M 204M 20% /boot
示例 2:
用戶:連接到 production 並讀取 /var/log/nginx/error.log 的最後 50 行
AI 響應:
我將連接到 production 並讀取 nginx 錯誤日誌的最後 50 行。
[正在連接到 production...]
/var/log/nginx/error.log 的最後 50 行:
2024-01-15 10:23:45 [error] 12345#0: *123 connect() failed (111: Connection refused)
2024-01-15 10:24:12 [error] 12345#0: *124 upstream timed out
...
示例 3:
用戶:以用戶 pi 身份直接連接到 192.168.88.63 並顯示磁盤使用情況
AI 響應:
我將以用戶 pi 身份直接連接到 192.168.88.63 並檢查磁盤使用情況。
[正在使用 SSH 密鑰連接到 192.168.88.63...]
磁盤使用情況:
Filesystem Size Used Avail Use% Mounted on
/dev/root 15G 5.2G 8.8G 38% /
/dev/mmcblk0p1 253M 49M 204M 20% /boot
示例 3b(帶密碼):
用戶:以用戶 admin 身份使用密碼 mypass123 連接到 192.168.88.63 並檢查系統運行時間
AI 響應:
我將以用戶 admin 身份連接到 192.168.88.63 並檢查系統運行時間。
[正在連接到 192.168.88.63...]
[SSH 密鑰身份驗證失敗,嘗試使用密碼...]
系統運行時間:5 天 12 小時 30 分鐘
示例 4:
用戶:檢查 dev 服務器的系統運行時間和內存使用情況
AI 響應:
我將檢查 dev 服務器的系統運行時間和內存使用情況。
[正在連接到 dev...]
系統運行時間:15 天 3 小時 22 分鐘
內存使用情況:
total used free shared buff/cache available
Mem: 7.8G 2.1G 3.2G 128M 2.5G 5.4G
Swap: 2.0G 0B 2.0G
示例 5:
用戶:顯示正在運行的進程並檢查 production 上的 nginx 服務是否正在運行
AI 響應:
我將檢查正在運行的進程並驗證 production 上的 nginx 是否正在運行。
[正在連接到 production...]
Nginx 服務狀態:active (running)
按 CPU 使用率排序的前幾個進程:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1234 nginx 20 0 123456 4567 1234 S 2.3 0.1 0:05:23 nginx
5678 app 20 0 234567 8901 2345 S 1.8 0.2 0:12:45 app
...
有狀態會話示例
此示例演示了命令之間狀態的保留:
用戶:連接到 rpi,導航到 /var/log,並顯示 syslog 的最後 10 行
AI 響應:
我將連接到 rpi,導航到 /var/log,並顯示 syslog 的最後 10 行。
[正在連接到 rpi...]
[正在更改目錄到 /var/log...]
syslog 的最後 10 行:
Jan 15 10:23:45 rpi systemd[1]: Started Network Manager.
Jan 15 10:24:12 rpi sshd[1234]: Accepted publickey for pi from 192.168.1.50
...
幕後發生的事情:
ssh_connect("rpi") - 建立持久的 shell 會話
ssh_run_command("rpi", "cd /var/log") - 更改目錄(狀態已保存)
ssh_run_command("rpi", "tail -n 10 syslog") - 從 /var/log 執行(狀態已保留!)
第二個命令自動從 /var/log 開始執行,因為 shell 狀態從上一個命令中得到了保留。
獨立 CLI 模式(用於調試)
交互式終端模式,用於測試和調試。對於排查連接問題或手動測試命令很有用。
連接方法
1. 使用 SSH 配置別名
cargo run -- cli --host rpi
./target/release/ssh-liaison-mcp cli --host rpi
2. 通過命令行直接連接
cargo run -- cli --user pi --hostname 192.168.1.100
cargo run -- cli --user pi --hostname 192.168.1.100 --port 2222
cargo run -- cli --user pi --hostname 192.168.1.100 --password mypassword
cargo run -- cli --user pi --hostname 192.168.1.1