SSH只读MCP服务器

一个安全的模型上下文协议(MCP)服务器,支持远程SSH命令执行并严格强制执行只读模式,适用于安全地委托SSH访问同时防止意外或恶意的写入操作。

  • by kunwarmahen
  • Python
  • 本地部署
  • 1 星标
  • 更新于
在 GitHub 查看 kunwarmahen/ssh-mcp-server

使用说明

SSH 只读 MCP 服务器

一个安全的模型上下文协议(MCP)服务器,支持远程SSH命令执行,并严格实施只读策略。非常适合在安全地将SSH访问权限委托给Claude的同时,防止意外或恶意的写入操作。

特点/特性

✅ 只读命令强制执行 – 仅允许安全的、只读命令
✅ SSH 连接池 – 支持多个同时连接
✅ 命令验证 – 阻止危险模式和写入操作
✅ 多播发现 – 在网络上自动广播以便轻松发现
✅ 灵活运输 – 标准I/O(Stdio)、HTTP或可流式传输的HTTP模式
✅ 全面日志记录 – 完整的审计追踪记录 ssh_mcp.log
✅(这个符号通常表示“正确”、“确认”或“完成”的意思,但具体含义可能根据上下文有所不同) 环境配置 – 可通过.env文件完全配置

安装

先决条件

  • Python 3.8及以上版本
  • uv 包管理器

设置

# Clone or create project directory
mkdir ssh-mcp-server
cd ssh-mcp-server

# Initialize uv project (if needed)
uv init

# Install dependencies
uv pip install fastmcp paramiko python-dotenv

或者使用 pyproject.toml:

[project]
name = "ssh-mcp-server"
version = "0.1.0"
dependencies = [
    "fastmcp>=0.1.0",
    "paramiko>=3.0.0",
    "python-dotenv>=1.0.0",
]

然后安装:

uv sync

配置

创建一个 .env 项目根目录中的文件:

# Transport mode: stdio (default), http, or streamable-http
MCP_TRANSPORT=stdio

# Server identification
MCP_SERVER_NAME=SSH Read-Only MCP Server

# HTTP mode settings (if using http/streamable-http)
MCP_HOST=0.0.0.0
MCP_PORT=3000

# Multicast discovery
MCP_ENABLE_BROADCAST=true
MCP_BROADCAST_INTERVAL=30

环境变量

变量 默认值 描述
MCP_TRANSPORT stdio 通信传输: stdio, http,或者 streamable-http
MCP_SERVER_NAME SSH Read-Only MCP Server 服务器的显示名称
MCP_HOST 0.0.0.0 HTTP模式下的绑定地址
MCP_PORT 3000 HTTP模式的端口
MCP_ENABLE_BROADCAST true 启用多播发现公告
MCP_BROADCAST_INTERVAL 30 广播公告之间的间隔时间(秒)

使用方法

启动服务器

标准I/O模式(默认):

uv run ssh_readonly_fastmcp_mcast.py

使用多播发现的HTTP模式:

MCP_TRANSPORT=http MCP_PORT=3000 uv run ssh_readonly_fastmcp_mcast.py

非广播模式下的HTTP:

MCP_ENABLE_BROADCAST=false MCP_TRANSPORT=http MCP_PORT=3000 uv run ssh_readonly_fastmcp_mcast.py

可用工具

1. ssh_connect

建立与远程机器的SSH连接。

参数:

  • host (必填)– 远程主机IP或主机名
  • username (必填)– SSH 用户名
  • port (可选,默认:22)– SSH 端口
  • key_filename (可选)– 私钥文件路径(推荐)
  • password (可选)– SSH 密码(备用)

示例:

Connect to 192.168.1.100 as user 'admin' with private key
host: 192.168.1.100
username: admin
key_filename: /home/user/.ssh/id_rsa

2. ssh_execute

在连接的远程机器上执行只读命令。

参数:

  • host (必需)– 远程主机(必须先连接)
  • username (必填)– SSH 用户名
  • command (必需)– 执行只读命令
  • port (可选,默认:22)– SSH 端口

示例:

Run 'ls -la /home' on connected server
host: 192.168.1.100
username: admin
command: ls -la /home

3. ssh_disconnect

关闭SSH连接。

参数:

  • host (必填)– 远程主机
  • username (必填)– SSH 用户名
  • port (可选,默认值:22)– SSH 端口

4. ssh_list_connections

查看所有活动的SSH连接。

参数: 无

5. ssh_get_allowed_commands

获取允许的只读命令列表。

参数: 无

允许的命令

服务器允许以下只读操作:

  • 文件操作: cat, ls, file, head, tail, find, locate
  • 系统信息: ps, top, df, du, free, uname, hostname, uptime
  • 网络: netstat, ss, ifconfig, ip, curl, wget, dig, nslookup, ping, traceroute
  • 流程管理: lsof, systemctl, service
  • 文本处理: grep, awk, sed, wc
  • 并且还有许多只读实用程序

阻塞操作: rm, mv, cp, chmod, chown, mkdir, touch, kill, shutdown, reboot, sudo以及任何写入/修改命令。

多播发现

当以启用广播的HTTP模式运行时,服务器会在多播组中宣布自己的存在:

  • 地址: 239.255.255.250
  • 端口: 5353
  • 间隔: 可配置(默认:30秒)

发现公告包括:

  • 服务器UUID
  • 服务器名称
  • 本地IP和端口
  • 运输类型
  • 协议版本

记录日志

所有活动均被记录到 ssh_mcp.log:

2025-10-17 10:30:45,123 [INFO] ssh_mcp - Starting MCP server with transport=http
2025-10-17 10:30:46,456 [INFO] ssh_mcp - Starting multicast broadcaster on 239.255.255.250:5353
2025-10-17 10:30:47,789 [INFO] ssh_mcp - Successfully connected to admin@192.168.1.100:22

安全考虑事项

🔒(锁形符号,通常表示安全、保密或锁定的状态) 只读强制执行:

  • 仅允许白名单中的命令
  • 危险模式(管道、重定向、子shell)被阻止
  • 在命令级别上阻止写操作

⏱️(这个符号本身没有直接对应的中文翻译,它通常表示时间或倒计时,可以意译为“倒计时”或根据上下文具体解释为“时间紧迫”等。在这里,我将其意译为“时间紧迫”以表达其含义。) 超时设置:

  • 每条命令30秒的执行超时时间
  • 防止挂起命令阻塞服务器

🔐 表示“锁”或“密码保护”的符号。 认证:

  • 建议使用SSH密钥认证而非密码
  • 密码仅存储在内存中,从不持久化保存

📋 表格/清单 审计轨迹/审计路径

  • 所有连接和命令都被记录下来
  • 评论 ssh_mcp.log 用于安全审计

故障排除

连接被拒绝

Error: Connection failed: [Errno 111] Connection refused
  • 验证远程主机是否可达: ping <host>
  • 检查远程机器上的SSH是否正在运行
  • 验证端口号(默认22)

认证失败

Error: Connection failed: Authentication failed
  • 验证用户名是否正确
  • 对于密钥认证:检查密钥文件路径和权限(chmod 600)
  • 对于密码认证:验证凭据
  • 确保SSH公钥在远程服务器上已授权~/.ssh/authorized_keys)

命令不允许

Error: Command not allowed for security reasons
  • 该命令包含被阻止的模式或不在允许列表中
  • 使用 ssh_get_allowed_commands 查看允许的命令
  • 对于写操作,请直接使用SSH代替

广播无法正常工作

  • 验证 MCP_ENABLE_BROADCAST=true
  • 检查网络是否支持多播(大多数企业网络会阻止多播)
  • 验证防火墙是否允许在5353端口上使用UDP
  • 检查 ssh_mcp.log 对于广播错误

发展

在调试模式下运行

DEBUG=true uv run ssh_readonly_fastmcp_mcast.py

测试

# Test connection
uv run -c "from ssh_readonly_fastmcp_mcast import is_command_safe; print(is_command_safe('ls -la'))"

# Should print: True

# Test blocked command
uv run -c "from ssh_readonly_fastmcp_mcast import is_command_safe; print(is_command_safe('rm -rf /'))"

# Should print: False

项目结构

ssh-mcp-server/
├── ssh_readonly_fastmcp_mcast.py    # Main server implementation
├── .env                        # Configuration file
├── .env.example               # Configuration template
├── ssh_mcp.log                # Server logs (auto-generated)
├── pyproject.toml             # Project metadata
└── README.md                  # This file

API响应格式

所有工具均返回一致的JSON响应:

成功:

{
  "status": "success",
  "host": "192.168.1.100",
  "command": "ls -la /home",
  "exit_code": 0,
  "output": "total 24\ndrwxr-xr-x 3 root root 4096...",
  "error": null
}

错误:

{
  "status": "error",
  "message": "Command not allowed for security reasons",
  "reason": "Only read-only commands are permitted"
}

许可证

麻省理工学院(MIT)

做出贡献

欢迎投稿!请确保:

  • 所有更改均保持只读强制执行
  • 代码已正确记录
  • 安全验证测试通过

支持

对于问题或疑问:

  1. 检查 ssh_mcp.log 查看错误详情
  2. 查看故障排除部分
  3. 验证环境配置
  4. 检查与远程主机的网络连接