SSH协议服务器

SSH MCP Server是一款为AI代理提供安全SSH远程访问的协议服务器,支持连接池、密钥认证、SFTP文件操作和SSH隧道等功能。

  • by n0madic
  • Go
  • 本地部署
  • 3 星标
  • 更新于
在 GitHub 查看 n0madic/ssh-mcp

使用说明

SSH MCP服务器

一种模型上下文协议(MCP)服务器,为AI代理提供对远程主机的安全SSH访问。支持连接池、基于密钥和密码的身份验证、sudo、通过SFTP的文件操作、SSH隧道(本地端口转发)、命令过滤、速率限制、输出截断和优雅关闭。

特性

  • SSH连接池 --重用连接、故障时自动重新连接、空闲清理、远程操作系统和shell的自动检测
  • 认证 --明确的 key_path 首先,然后是ssh代理,然后是自动发现 ~/.ssh/id_* 密钥(当没有代理时),然后是密码;自动 ~/.ssh/config 别名解析
  • 命令执行 --支持sudo、工作目录、超时、优雅终止(SIGTERM→ SIGKILL),ANSI剥离
  • SFTP文件操作 --上传/下载文件和目录,读取具有行偏移/限制的文件,编辑文件(替换/修补/创建),使用目录列表显示文件信息, ~ 路径扩展
  • 交互式PTY终端 --缓冲PTY会话,用于交互式程序(vim、htop、REPL)、对话框和实时输出(选择加入 --enable-terminal)
  • ssh隧道 --本地端口转发(localhost:port→ remote:通过SSH端口)用于访问数据库、API和web服务器等远程服务(选择加入 --enable-tunnels)
  • 输出截断 --可配置的每流输出大小限制(--max-output-size)防止LLM上下文溢出
  • 安全 --host/command allowlist/denylist(regex+CIDR),每台主机速率限制,路径遍历保护,文件名长度验证
  • 运输 --stdio(默认)和流式HTTP(localhost 仅)
  • 优雅关闭 --关闭SIGINT/SIGTERM上的所有隧道、SSH连接和终端会话

安装

go install github.com/n0madic/ssh-mcp@latest

或者从源代码构建:

git clone https://github.com/n0madic/ssh-mcp.git
cd ssh-mcp
go build -o ssh-mcp .

用法

标准传输(默认)

./ssh-mcp

HTTP传输

./ssh-mcp --enable-http
# Listens on localhost:8081/mcp

两种运输方式

./ssh-mcp --enable-http
# Stdio + HTTP on localhost:8081/mcp

仅限HTTP(无stdio)

./ssh-mcp --enable-http --disable-stdio

CLI标志

标志 环境变量 默认值 描述
--enable-http MCP_SSH_ENABLE_HTTP false 启用HTTP传输
--http-port MCP_SSH_HTTP_PORT 8081 HTTP传输端口
--disable-stdio MCP_SSH_DISABLE_STDIO false 禁用stdio传输
--no-verify-host-key MCP_SSH_NO_VERIFY_HOST_KEY false 禁用主机密钥验证
--known-hosts MCP_SSH_KNOWN_HOSTS ~/.ssh/known_hosts known_hosts文件的路径
--ssh-config MCP_SSH_CONFIG ~/.ssh/config SSH配置文件的路径
--enable-sudo MCP_SSH_ENABLE_SUDO false 允许执行sudo
--command-timeout MCP_SSH_COMMAND_TIMEOUT 60s 命令执行超时
--host-allowlist MCP_SSH_HOST_ALLOWLIST (空) 主机分配列表(可以多次指定)
--host-denylist MCP_SSH_HOST_DENYLIST (空) 主机denylist(可以多次指定)
--command-allowlist MCP_SSH_COMMAND_ALLOWLIST (空) 命令allowlist正则表达式(可以多次指定)
--command-denylist MCP_SSH_COMMAND_DENYLIST (空) 命令denylist正则表达式(可以多次指定)
--rate-limit MCP_SSH_RATE_LIMIT 60 速率限制(每台主机每分钟请求数)
--rate-limit-file-ops MCP_SSH_RATE_LIMIT_FILE_OPS false 对SFTP文件操作应用速率限制
--local-base-dir MCP_SSH_LOCAL_BASE_DIR (空) 将本地文件操作限制到此目录
--max-file-size MCP_SSH_MAX_FILE_SIZE 0 读取操作的最大文件大小(0=无限制)
--max-connections MCP_SSH_MAX_CONNECTIONS 0 最大并发SSH连接数(0=无限制)
--http-token MCP_SSH_HTTP_TOKEN (空) HTTP传输身份验证的承载令牌
--disable-tools MCP_SSH_DISABLE_TOOLS (空) 禁用特定工具(可以多次指定)
--enable-terminal MCP_SSH_ENABLE_TERMINAL false 允许交互式PTY终端会话(ssh_open_terminal)
--max-terminals MCP_SSH_MAX_TERMINALS 0 最大并发PTY终端会话数(0=无限制)
--max-output-size MCP_SSH_MAX_OUTPUT_SIZE 0 执行/终端结果的每个流的最大输出大小(字节)(0=无限制)
--enable-tunnels MCP_SSH_ENABLE_TUNNELS false 允许创建SSH隧道(ssh_tunnel_create)
--max-tunnels MCP_SSH_MAX_TUNNELS 0 最大并发SSH隧道数(0=无限制)
--version -- -- 显示版本并退出

优先: CLI标志>环境变量>默认值。

例子

仅允许特定主机(正则表达式模式):

./ssh-mcp --host-allowlist "192.168.1.*" --host-allowlist "10.0.0.*"

允许按CIDR范围设置主机:

./ssh-mcp --host-allowlist "10.0.0.0/8" --host-allowlist "192.168.0.0/16"

阻止危险命令(多个标志):

./ssh-mcp --command-denylist "rm\s+-rf.*" --command-denylist "shutdown.*" --command-denylist "reboot.*"

注: 命令/主机过滤器模式通过以下方式自动锚定 ^ 和 $ 用于完整字符串匹配。使用 .* 对于子字符串匹配(例如。, rm\s+-rf.* 火柴 rm -rf / 但是 rm 独自一人无法匹配 format).主机模式还支持CIDR表示法(例如。, 10.0.0.0/8)--CIDR模式会自动检测,并通过IP范围而不是正则表达式进行匹配。

使用环境变量(逗号分隔):

export MCP_SSH_HOST_ALLOWLIST="host1.example.com,host2.example.com,host3.example.com"
export MCP_SSH_COMMAND_DENYLIST="rm\s+-rf.*,shutdown.*,reboot.*"
export MCP_SSH_ENABLE_SUDO=true
./ssh-mcp

将本地文件操作限制到目录:

./ssh-mcp --local-base-dir /tmp/ssh-workspace

启用带有承载令牌身份验证的HTTP传输:

./ssh-mcp --enable-http --http-token "my-secret-token"

限制并发连接和文件大小:

./ssh-mcp --max-connections 5 --max-file-size 10485760

限制输出大小以防止LLM上下文溢出:

./ssh-mcp --max-output-size 65536

限制并发SSH隧道:

./ssh-mcp --max-tunnels 5

禁用特定工具(多个标志):

./ssh-mcp --disable-tools ssh_execute --disable-tools ssh_edit_file

通过环境变量禁用工具:

export MCP_SSH_DISABLE_TOOLS="ssh_execute,ssh_edit_file"
./ssh-mcp

MCP工具

ssh-connect

通过SSH连接到远程主机。

最小(来自ssh代理或 ~/.ssh/id_*):

{
  "host": "example.com"
}

完整格式--用户、密码、端口内联:

{
  "host": "admin:secret@example.com:2222"
}

显式参数(覆盖内联值):

{
  "host": "example.com",
  "port": 2222,
  "user": "admin",
  "key_path": "~/.ssh/id_ed25519"
}

SSH配置别名(从以下位置自动解析 ~/.ssh/config):

{
  "host": "my-server"
}

SSH配置别名会自动解析,不需要额外的标志。显式参数(port、user、key_path)覆盖配置中的值。

退货 session_id 与其他工具一起使用。还可以自动检测远程操作系统、体系结构和shell。

ssh执行

在远程主机上执行命令。超时时,首先发送SIGTERM(5秒宽限期),然后发送SIGKILL,并返回部分stdout/stderr和 [TIMEOUT] stderr中的标记。

{
  "session_id": "admin@example.com:22",
  "command": "ls -la /var/log",
  "timeout": 30,
  "sudo": true,
  "sudo_password": "secret",
  "working_dir": "/home/admin"
}

ssh断开连接

断开SSH会话。

{
  "session_id": "admin@example.com:22"
}

ssh_list_sessions

列出所有活动的SSH会话及其连接详细信息、统计信息、活动终端会话和活动隧道(不需要参数)。

ssh上传

通过SFTP将本地文件或目录上传到远程主机。自动检测本地路径是文件还是目录。保留文件权限和目录结构。支持 ~ 用于远程主目录。

上传文件:

{
  "session_id": "admin@example.com:22",
  "local_path": "/tmp/config.yaml",
  "remote_path": "~/config.yaml"
}

上传目录(递归):

{
  "session_id": "admin@example.com:22",
  "local_path": "/tmp/myapp",
  "remote_path": "/opt/myapp"
}

ssh下载

通过SFTP从远程主机下载文件或目录。自动检测远程路径是文件还是目录。保留文件权限和目录结构。支持 ~ 用于远程主目录。

下载文件:

{
  "session_id": "admin@example.com:22",
  "remote_path": "~/app.log",
  "local_path": "/tmp/app.log"
}

下载目录(递归):

{
  "session_id": "admin@example.com:22",
  "remote_path": "/opt/myapp",
  "local_path": "/tmp/myapp-backup"
}

ssh_edit_file

编辑远程主机上的文件。两种模式:

更换模式 (默认)--完整内容替换或新文件创建:

{
  "session_id": "admin@example.com:22",
  "remote_path": "/etc/myapp/config.yaml",
  "mode": "replace",
  "content": "new file content here",
  "backup": true
}

补丁模式 --查找并替换:

{
  "session_id": "admin@example.com:22",
  "remote_path": "/etc/myapp/config.yaml",
  "mode": "patch",
  "old_string": "old_value",
  "new_string": "new_value",
  "backup": true
}

ssh_read_file

使用可选的行偏移和限制从远程主机读取文件。返回带有行号的内容(如 cat -n).支持 ~ 主目录。

读取整个文件:

{
  "session_id": "admin@example.com:22",
  "remote_path": "~/app.log"
}

带偏移和限制读取(分页):

{
  "session_id": "admin@example.com:22",
  "remote_path": "/var/log/syslog",
  "offset": 100,
  "limit": 50
}

读取最大文件大小限制:

{
  "session_id": "admin@example.com:22",
  "remote_path": "~/large-file.csv",
  "max_size": 1048576
}

返回文件内容,包括行号、总行数、文件大小以及显示的行数。


交互式PTY终端工具

这四个工具为交互式程序提供缓冲PTY访问。需要 --enable-terminal.

典型工作流程:

ssh_open_terminal   →  opens shell, returns terminal_id + initial prompt
ssh_send_input      →  write text or keystrokes, get new output
ssh_read_output     →  poll for new output without writing
ssh_close_terminal  →  close the session

活动终端也列在 ssh_list_sessions 输出。

ssh开放终端

打开PTY终端会话。需要 --enable-terminal 在服务器上标记。

{
  "session_id": "admin@example.com:22",
  "cols": 120,
  "rows": 50,
  "term_type": "xterm-256color",
  "wait_ms": 500,
  "protect_exit": true
}

退货 terminal_id 以及初始shell输出(提示符)。 cols/rows/term_type/wait_ms/protect_exit 是可选的。

protect_exit (默认为true)覆盖shell的 exit 命令没有op功能,所以很意外 exit 代理无法终止会话。使用 ssh_close_terminal 明确终止会话。子shell(sudo、python、ssh到另一个主机)不受影响。自动禁用Windows主机。

ssh_send_input

将文本或特殊按键发送到终端并读取新输出。

发送命令:

{
  "terminal_id": "term-1",
  "text": "ls -la\n",
  "wait_ms": 300
}

发送特殊密钥:

{
  "terminal_id": "term-1",
  "special_key": "CTRL_C"
}

支持的特殊密钥: CTRL_C, CTRL_D, CTRL_Z, ESC, TAB, BACKSPACE, ENTER, ARROW_UP, ARROW_DOWN, ARROW_LEFT, ARROW_RIGHT.

使用 \n 对于换行符和 \r 返回车厢 text.正是其中之一 text 或 special_key 必须提供-设置两者都是错误的。

ssh_read_output

读取上次读取后的缓冲输出,不写入任何内容。

{
  "terminal_id": "term-1",
  "wait_ms": 1000,
  "limit": 100
}
  • wait_ms --等待新数据最多N毫秒(默认0=立即返回)。
  • limit --每次调用返回的最大完整行数(默认值0=返回所有内容)。剩余的线路保留在缓冲区中,以备后续调用。响应包括 lines (计数返回)和 has_more (如果缓冲了更多行,则为true);当有更多输出待处理时,文本响应还会附加一个标记行。

ssh_close_terminal

关闭PTY终端会话。

{
  "terminal_id": "term-1"
}

SSH隧道工具

这三个工具通过SSH连接提供本地端口转发。可用于访问无法直接访问的远程数据库、web服务器或API。需要 --enable-tunnels.

典型工作流程:

ssh_tunnel_create  →  binds local port, forwards to remote address
ssh_tunnel_list    →  show active tunnels
ssh_tunnel_close   →  stop forwarding and release the port

活动隧道也列在 ssh_list_sessions 输出。当父SSH会话断开连接时,隧道会自动关闭。

ssh_tunnel_create

创建本地端口转发隧道。

自动分配本地端口:

{
  "session_id": "admin@example.com:22",
  "remote_addr": "localhost:5432",
  "local_port": 0
}

特定本地端口:

{
  "session_id": "admin@example.com:22",
  "remote_addr": "10.0.0.5:3306",
  "local_port": 13306
}

退货 tunnel_id、绑定的本地地址和端口以及远程地址。

ssh_tunnel_list

列出所有活动隧道。可选地按会话ID进行筛选。

{
  "session_id": "admin@example.com:22"
}

ssh-tunnel_close

关闭活动隧道。

{
  "tunnel_id": "admin@example.com:22-1"
}

Codex配置

使用CLI添加到Codex:

codex mcp add ssh \
  --env SSH_AUTH_SOCK="$SSH_AUTH_SOCK" \
  -- /path/to/ssh-mcp --enable-terminal

验证已保存的配置:

codex mcp get ssh

对于受密码保护的SSH密钥, ssh-mcp 必须能够使用您的 ssh代理。它本身不会提示输入私钥密码。如果Codex开始 ssh-mcp 没有工作 SSH_AUTH_SOCK, ssh_connect 可以在任何之前失败 尝试网络连接:

connect failed: auth config: no authentication methods available

在添加MCP服务器之前,请确保已加载密钥:

ssh-add -l

在macOS上,将密钥加载到代理中并将密码存储在Keychain中:

/usr/bin/ssh-add --apple-use-keychain ~/.ssh/id_rsa

如果 SSH_AUTH_SOCK 重新启动后或重新启动终端后的更改,更新 通过运行Codex MCP条目 codex mcp add 再次使用当前值。 现有的食品法典委员会会议可能会保留已经开始的 ssh-mcp 过程与 旧环境;重新启动Codex或删除过时的 ssh-mcp 处理后 更改配置。

手动等效 ~/.codex/config.toml:

[mcp_servers.ssh]
command = "/path/to/ssh-mcp"
args = ["--enable-terminal"]

[mcp_servers.ssh.env]
SSH_AUTH_SOCK = "/var/run/com.apple.launchd.XYZ/Listeners"

Claude代码配置

使用CLI添加到Claude代码中:

claude mcp add --transport stdio --scope user ssh -- /path/to/ssh-mcp --no-verify-host-key

或手动编辑 ~/.claude.json:

{
  "mcpServers": {
    "ssh": {
      "type": "stdio",
      "command": "/path/to/ssh-mcp",
      "args": ["--no-verify-host-key"]
    }
  }
}

Claude桌面配置

添加到您的Claude桌面配置(~/Library/Application Support/Claude/claude_desktop_config.json):

标准运输

{
  "mcpServers": {
    "ssh": {
      "command": "/path/to/ssh-mcp",
      "args": ["--enable-sudo", "--no-verify-host-key"]
    }
  }
}

HTTP传输

手动启动服务器:

./ssh-mcp --enable-http --disable-stdio

然后配置Claude Desktop以在以下位置使用HTTP端点 http://localhost:8081/mcp.

安全

  • HTTP传输仅限于本地主机 --HTTP服务器绑定到 localhost (硬编码,不可配置)
  • HTTP认证 --HTTP传输的可选承载令牌身份验证(--http-token);恒定时间比较
  • HTTP服务器强化 — ReadHeaderTimeout 和 IdleTimeout 设置为防止斯洛洛里斯式攻击
  • 主机密钥验证 --默认情况下使用启用 ~/.ssh/known_hosts;如果文件丢失,则失败并显示明显错误(没有静默降级到不安全模式)
  • 默认情况下禁用Sudo --必须明确启用 --enable-sudo
  • 默认情况下禁用交互式终端 --PTY会话绕过命令过滤器;必须明确启用 --enable-terminal
  • 默认情况下禁用SSH隧道 --隧道创建必须明确启用 --enable-tunnels
  • 主机过滤 --支持正则表达式和CIDR的allowlist/denylist;丹尼斯主义者优先;正则表达式模式会自动锚定以进行完整字符串匹配;CIDR模式(例如。, 10.0.0.0/8)按IP范围匹配;不区分大小写的主机匹配
  • 命令过滤 --支持正则表达式的allowlist/denylist;丹尼斯主义者优先;模式是自动锚定的;filter在原始命令上运行(在cd/sudo preend之前);错误消息不公开筛选器模式
  • 本地路径限制 — --local-base-dir 将所有本地文件操作(上传/下载)限制到特定目录
  • 路径遍历保护 --拒绝路径 .. 路径段或空字节(本地和远程);基于段的检查允许以下名称 foo..bar
  • 文件名验证 --拒绝长度超过255个字符、包含控制字符(包括DEL和Unicode Cc)或路径分隔符的文件名
  • 速率限制 --具有自动陈旧条目清理功能的每主机令牌桶速率限制器;可选地应用于SFTP文件操作(--rate-limit-file-ops)
  • 连接池限制 — --max-connections 限制并发SSH连接的数量
  • 文件大小限制 — --max-file-size 限制远程文件读取操作以防止内存耗尽
  • 输出截断 — --max-output-size 限制执行和终端工具中的每个流输出大小,以防止LLM上下文溢出;UTF-8安全截断避免了分割多字节字符
  • 隧道池限制 — --max-tunnels 限制并发SSH隧道的数量
  • 无凭据持久性 --密码不存储在连接池中;只有SSH客户端配置(具有基于密钥的身份验证方法)保留用于自动重新连接
  • 远程路径扩展 — ~ 扩展到远程服务器上的用户主目录

发展

# Build
go build ./...

# Run unit tests
go test ./internal/...

# Run E2E tests (requires Docker)
go test -v -timeout 120s ./e2e/...

# Run all tests
go test ./...

# Vet
go vet ./...

许可证

MIT许可证。看 许可证 了解详情。