# ssh-client **Repository Path**: andq/ssh-client ## Basic Information - **Project Name**: ssh-client - **Description**: 非专业纯AI开发项目,目的实现适合自己常用习惯的客户端工具 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-08-27 - **Last Updated**: 2026-09-23 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # SSH MCP 服务器 通过 [MCP(Model Context Protocol)](https://modelcontextprotocol.io) 对外暴露 SSH 远程操作能力,让 MCP 客户端(如支持 MCP 的 IDE、Claude Desktop 等)能够连接多台 Linux 服务器、查看远端目录、读取远端文件/日志、搜索文件内容,并在严格权限控制下执行受限命令(服务更新)。 本实现基于 **Python**,技术栈:`mcp`(官方 SDK)、`paramiko`(同步 SSH)、`sqlite3`(标准库)。 ## 功能概览 - **多服务器登记管理**:将 SSH 服务器连接信息持久化到本地 SQLite,支持密码或私钥两种认证方式。 - **远端只读操作**:列出目录、读取文件(支持行区间)、读取日志末尾 N 行、按文件名 glob 递归查找、按内容正则搜索。 - **本地读取**:读取本地文件(可用 `SSH_MCP_LOCAL_ROOT` 限定允许读取的目录)。 - **受限写命令**:默认拒绝执行任意命令,仅当服务器开启 `allow_command` 且命令/工作目录限定在 `allowed_write_dir` 内时才执行,并记录写操作历史。 - **操作记忆**:远端操作记录并持久化到 SQLite,可随时通过 `query_memory` 查询。 - **两种上传方式**:SFTP 上传(`upload_remote_file`,文本/base64)与系统 scp 上传(`scp_upload_remote_file`,调用本机 `scp` 命令)。 ## 目录结构 项目按服务拆分目录,根目录不直接存放业务源码: | 目录 | 说明 | | --- | --- | | `client/` | **客户端服务**:Tauri 2 + Rust 桌面应用(`client/src-tauri/`) | | `frontend/` | **前端服务**:Vue 3 + Vite(源码 `frontend/src/`,构建产物 `frontend/dist/`) | | `py_ssh_mcp/` | **MCP 服务**:Python 实现(含 `MCP配置说明.md`、`requirements.txt`、`qoder-mcp-config.json`) | | `database/` | **数据库**:SQLite 数据文件(`ssh_mcp.db`) | | `doc/` | **文档**:项目架构与工程说明 | MCP 服务模块(`.venv` 虚拟环境位于 `py_ssh_mcp\.venv`,供 MCP 服务使用): | 文件 | 说明 | | --- | --- | | `py_ssh_mcp/config.py` | 环境变量配置与默认值 | | `py_ssh_mcp/db.py` | SQLite 存储层(服务器表 + 操作历史表) | | `py_ssh_mcp/ssh_client.py` | SSH 连接层(连接缓存、命令执行、只读操作、SFTP 上传、命令安全校验) | | `py_ssh_mcp/scp_client.py` | SCP 传输层(基于系统 scp 命令的上传) | | `py_ssh_mcp/ssh_mcp_server.py` | MCP 服务器与全部工具定义,暴露 `mcp` 实例 | ## 安装 MCP 服务依赖(Python): ```bash pip install -r py_ssh_mcp/requirements.txt ``` 依赖(见 `py_ssh_mcp/requirements.txt`):`mcp>=1.0`、`paramiko>=3.0`。 前端依赖: ```bash cd frontend && npm install ``` ## 启动 ### MCP 服务(stdio) ```bash py_ssh_mcp\.venv\Scripts\python.exe py_ssh_mcp\ssh_mcp_server.py --transport stdio ``` 也可用 HTTP transport:`py_ssh_mcp\.venv\Scripts\python.exe py_ssh_mcp\ssh_mcp_server.py --transport http`。 若在代码中复用,可从 `py_ssh_mcp` 目录执行 `from ssh_mcp_server import mcp` 获取 MCP 实例。 ### 前端服务(开发) ```bash cd frontend && npm run dev # http://localhost:1420 ``` ### 客户端服务(Tauri 桌面应用) ```bash cd client/src-tauri && cargo tauri dev # 自动启动前端 dev server 并打开桌面窗口 ``` ## 环境变量(可选) | 环境变量 | 默认值 | 说明 | | --- | --- | --- | | `SSH_MCP_DB_PATH` | `./database/ssh_mcp.db` | SQLite 数据库文件路径(相对运行时的 cwd) | | `SSH_MCP_LOCAL_ROOT` | 空(不限制) | 允许 `read_local_file` 读取的本地根目录 | | `SSH_MCP_CONNECT_TIMEOUT` | `15` | 全局 SSH 连接超时(秒),服务器可单独覆盖 | | `SSH_MCP_SCP_BINARY` | `scp` | scp 可执行文件路径 | | `SSH_MCP_SSHPASS_BINARY` | `sshpass` | sshpass 可执行文件路径(password 认证时使用) | | `SSH_MCP_SCP_TIMEOUT` | `60` | scp 上传整体超时(秒) | | `SSH_MCP_SCP_STRICT_HOST_KEY` | `no` | scp 主机指纹校验策略(`yes`/`no`) | ## 登记服务器 通过 MCP 工具 `add_server` 登记,例如密码认证: ```text add_server( name="web-01", host="1.2.3.4", port=22, username="deploy", auth_method="password", password="******" ) ``` 私钥认证: ```text add_server( name="web-01", host="1.2.3.4", port=22, username="deploy", auth_method="key", private_key_path="/home/user/.ssh/id_rsa" ) ``` > **提示**:`list_servers` 不会返回 `password` 与 `private_key_path`,避免泄露敏感信息。 如需允许受限写命令,登记时设置 `allow_command=true` 并指定 `allowed_write_dir`(例如 `/var/www/myapp`)。 ## 作为 MCP 服务器配置到客户端(stdio) 以 Claude Desktop 为例,在客户端配置文件中加入: ```json { "mcpServers": { "ssh-mcp": { "command": "python", "args": ["/abs/path/to/py_ssh_mcp/ssh_mcp_server.py"] } } } ``` ## 桌面客户端(Tauri) 前端(Vue 3 + Vite)与客户端(Tauri 2 + Rust)分别位于 `frontend/` 与 `client/src-tauri/`, 通过 Tauri IPC 通信,不依赖 MCP SDK。桌面客户端自带独立的 SSH 实现与 SQLite 数据库(存放在系统应用数据目录)。 - **服务器管理**:列出 / 新增 / 编辑 / 删除服务器、测试连接。 - **文件浏览**:浏览远程目录、读取文件/日志、按文件名/内容搜索。 - **命令终端**:受限命令执行(仅对开启 `allow_command` 且配置 `allowed_write_dir` 的服务器开放)。 - **操作记忆**:查询历史操作记录。 Tauri 相关配置见 `client/src-tauri/tauri.conf.json`(前端产物目录指向 `frontend/dist`,开发端口 1420)。 ## 工具说明 | 工具 | 说明 | | --- | --- | | `list_servers()` | 列出所有服务器(不含密码/私钥) | | `add_server(name, host, port, username, auth_method, ...)` | 登记服务器 | | `remove_server(name)` | 删除服务器 | | `list_remote_directory(server_name, path)` | 列出远端目录 | | `read_remote_file(server_name, path, start_line?, end_line?)` | 读取远端文件(支持行区间) | | `tail_remote_log(server_name, path, lines?)` | 读远端日志末尾 N 行 | | `search_remote_files(server_name, root, pattern)` | 按文件名 glob 递归查找 | | `search_remote_content(server_name, path_or_root, pattern)` | 按内容正则搜索匹配行 | | `read_local_file(path)` | 读取本地文件(受 `SSH_MCP_LOCAL_ROOT` 约束) | | `execute_remote_command(server_name, command, workdir?, timeout?)` | 受限执行远端命令(需开启 `allow_command`) | | `scp_upload_remote_file(server_name, local_path, remote_path, recursive?, timeout?)` | 通过系统 scp 命令上传本地文件/目录 | | `query_memory(limit?)` | 查询操作历史记忆 | ## 安全说明 - **命令默认关闭**:`execute_remote_command` 默认拒绝执行,必须显式开启 `allow_command=true` 且指定 `allowed_write_dir`。 - **目录限定**:即便开启,命令也必须以 `allowed_write_dir` 内路径作为工作目录(`workdir`),并拒绝含路径逃逸元字符的命令,超出限定目录即拒绝执行。 - **敏感信息保护**:`list_servers` 不返回密码与私钥路径。 - **scp 上传约束**:`scp_upload_remote_file` 本地源路径受 `SSH_MCP_LOCAL_ROOT` 约束;依赖系统的 `scp`/`sshpass` 二进制,password 认证需安装 `sshpass`,或改用 key 认证。 - **连接复用**:SSH 连接按 `host:port:username` 缓存复用,连接异常时自动清理缓存。 - **明文存储提醒**:demo 简化实现中服务器密码以明文写入 SQLite,生产环境应使用加密传输与机密管理方案。