SSH会话管理服务

SSH-MCP是一款为AI代理提供持久SSH会话管理的服务,支持工作目录跟踪和跨命令状态保持,适用于远程服务器管理和自动化运维场景。

  • by Harsh-2002
  • Go
  • 本地部署
  • 5 星标
  • 更新于
在 GitHub 查看 Harsh-2002/SSH-MCP

使用说明

SSH-MCP

为任何AI代理提供安全、持久的SSH访问您的基础设施。

问题

AI代理是无状态的。每次工具调用都是一次新的执行——没有工作目录,没有连接重用,没有会话内存。当代理需要调试生产服务器时,它不能 cd 进入一个目录,运行一个命令,读取输出,然后在同一上下文中运行另一个命令。传统方法为每个命令启动一个新的SSH连接,失去所有状态。

解决方案

SSH-MCP位于人工智能代理和远程基础设施之间,作为 持久SSH会话管理器 这说明 模型上下文协议它通过工作目录跟踪保持长期的SSH连接,因此代理与远程服务器的交互方式与人类在终端中的交互方式相同。

┌──────────────┐                         ┌──────────────────────────────────┐
│              │    MCP Protocol         │          SSH-MCP Server          │
│   AI Agent   │◄──────────────────────► │                                  │
│              │    stdio / HTTP+SSE     │  ┌────────────────────────────┐  │
│  Claude      │                         │  │       Session Pool         │  │
│  Cursor      │                         │  │                            │  │
│  Any MCP     │                         │  │  Session A ─► SSH Manager  │──┼──► Server 1
│  Client      │                         │  │  Session B ─► SSH Manager  │──┼──► Server 2
│              │                         │  │  Session C ─► SSH Manager  │──┼──► Bastion ─► Server 3
└──────────────┘                         │  └────────────────────────────┘  │
                                         └──────────────────────────────────┘

每个会话都有自己的隔离SSH连接管理器。跨工具调用的连接持续存在。工作目录在命令之间进行跟踪。文件通过SFTP流式传输。一个二进制文件,零运行时依赖关系。

快速开始

Docker(推荐)

docker run -v ssh-keys:/data -p 8000:8000 firstfinger/ssh-mcp:latest

来源

go build -o ssh-mcp ./cmd/server
./ssh-mcp

macOS启动代理(开发)

看 scripts/macos/README.md 用于持久后台服务设置。

然后将MCP客户端指向配置的端点(默认 http://127.0.0.1:8000/mcp).

配置

标志 环境 默认值 描述
-mode SSH_MCP_MODE http 运输: stdio 或 http
-port PORT 8000 HTTP侦听端口
-global SSH_MCP_GLOBAL false 在所有会话中共享一个SSH管理器

SSH密钥 在第一次连接时自动生成Ed25519:

  • 发展: ./data/id_ed25519
  • 生产(Docker): /data/id_ed25519 (装入卷)

运作原理

会话隔离

每个MCP客户端都有一个隔离的SSH连接池。根据部署情况,有三种模式:

┌─ Session Pool ────────────────────────────────────────────────┐
│                                                               │
│  Per-session (default)                                        │
│  Each MCP session gets a UUIDv7 ID and its own SSH manager    │
│                                                               │
│  Header-based (X-Session-Key)                                 │
│  Sticky routing for load balancers — sessions survive         │
│  MCP reconnects as long as the header stays the same          │
│                                                               │
│  Global (-global flag)                                        │
│  Single shared manager — for single-user / local use          │
│                                                               │
└───────────────────────────────────────────────────────────────┘

基于标头的会话在5分钟不活动后过期。MCP会话结束时,每个会话池都会被销毁。

连接生命周期

connect(host, user)          Creates SSH client, tracks as "primary"
connect(host2, user, alias)  Creates second client with alias
run(command)                 Executes on primary, tracks CWD
run(command, target=alias)   Executes on aliased connection
read/write/edit(path)        SFTP operations on target
disconnect()                 Closes all connections in session

工作目录持续存在 run 电话-- cd /tmp && pwd 紧随其后 ls 将列出 /tmp这是与无状态执行的关键区别。

跳转主机隧道

Agent ──► SSH-MCP ──► Bastion ──► Internal Server
                      (via)

connect(bastion, admin, alias="jump")
connect(internal-host, admin, via="jump")

第二个连接隧道穿过第一个。代理不需要知道网络拓扑。

工具

按领域组织的43个工具。五人 核心工具 (connect, disconnect, run, read, write)是基础——其他一切都是一个更高级的包装器,它构造shell命令并调用相同的SSH执行路径。

核心

工具 它做什么
connect 打开SSH连接(密码、密钥或自动生成的密钥)
disconnect 关闭一个或所有连接
run 使用CWD跟踪和可配置超时执行命令
identity 获取服务器的公钥 authorized_keys
info 远程操作系统、内核、主机名

文件

工具 它做什么
read 通过SFTP读取文件(上限10MB)
write 通过SFTP写入文件——写入前验证语法
edit 类似Sed的操作:替换、正则表达式、插入、追加、删除
validate 服务器端语法检查(JSON、YAML、TOML、XML、INI、Dockerfile、ENV)
list_dir 包含元数据的目录列表
sync 在两个远程主机之间流式传输文件

验证在MCP服务器上的Go中运行——否 jq, python3,或 xmllint 远程主机上需要。

系统监控

usage ps logs journal_read dmesg_read diagnose_system list_services

码头工人

docker_ps docker_logs docker_op docker_ip docker_find_by_ip docker_networks docker_cp_from docker_cp_to

数据库

db_query db_schema list_db_containers

网络与搜索

net_stat search_files search_text package_manage

VoIP/SIP/RTP

voip_discover_containers voip_sip_capture voip_call_flow voip_registrations voip_call_stats voip_extract_sdp voip_packet_check voip_network_capture voip_rtp_capture voip_network_diagnostics

例子

连接并运行命令:

{"tool": "connect", "arguments": {"host": "10.0.0.1", "username": "admin"}}
{"tool": "run", "arguments": {"command": "hostname && uptime"}}
{"tool": "read", "arguments": {"path": "/etc/hostname"}}

跳转主机:

{"tool": "connect", "arguments": {"host": "bastion.example.com", "username": "admin", "alias": "bastion"}}
{"tool": "connect", "arguments": {"host": "10.0.0.50", "username": "admin", "via": "bastion"}}

编辑配置文件:

{"tool": "edit", "arguments": {"path": "/etc/nginx/nginx.conf", "old_text": "worker_connections 512", "new_text": "worker_connections 1024"}}

主机之间的同步:

{"tool": "connect", "arguments": {"host": "server-a", "username": "admin", "alias": "A"}}
{"tool": "connect", "arguments": {"host": "server-b", "username": "admin", "alias": "B"}}
{"tool": "sync", "arguments": {"source_node": "A", "source_path": "/data/dump.sql", "dest_node": "B", "dest_path": "/data/dump.sql"}}

建筑

cmd/server/main.go          Entry point, HTTP/stdio transport, session hooks
internal/ssh/
  ├── pool.go                Session pool — isolation, cleanup, header routing
  ├── manager.go             Per-session connection manager — connect, execute, SFTP
  ├── client.go              SSH client — CWD tracking, output caps, reconnection
  └── keys.go                Ed25519 key generation and loading
internal/tools/
  ├── core.go                connect, disconnect, run, identity, info
  ├── files.go               read, write, edit, validate, list_dir, sync
  ├── monitoring.go          usage, ps, logs, journal, dmesg, diagnose, services
  ├── docker.go              Container management tools
  ├── network.go             net_stat, search, packages
  ├── voip.go                SIP/RTP capture and analysis
  └── utils.go               Shell quoting, sed escaping, input sanitization

设计决策

  • 符合POSIX标准的命令 --所有shell命令都可以在Linux、macOS和BSD上运行。GNU特定标志(sed -i, ps --sort, /proc/*)用便携式替代品代替。
  • 壳牌到处报价 --所有用户输入都通过 shellQuote() 在到达外壳之前。Sed操作对模式、文字和替换使用单独的转义函数。
  • 无路径限制 --文件访问遵循SSH用户的操作系统权限。没有破坏现实世界DevOps工作流程的人工沙盒。
  • 服务器端验证 --文件语法在MCP服务器上的Go中进行验证,而不是通过远程主机上的工具进行验证。
  • 输出上限 --stdout的上限为10MB,stderr为1MB,文件读取为10MB。防止失控命令导致内存耗尽。
  • 使用回退重新连接 --丢失的SSH连接会在5秒的冷却后自动重新连接,以避免损坏主机。

部署

生产检查表

  • TLS:在反向代理后运行或使用HTTPS终止
  • 网络:限制访问专用网络或VPN
  • 验证:验证 X-Session-Key 使用授权密钥
  • 卷:在以下位置装载持久存储 /data 用于SSH密钥

端点

POST/GET http://host:port/mcp
Header:   X-Session-Key: <your-session-key>

负载均衡

在上使用一致哈希 X-Session-Key 用于跨多个实例的粘性路由。

许可证

麻省理工学院