Flotilla
OfficialProvides tools for managing persistent tmux sessions on remote fleet hosts (session-start, session-list, session-output, session-send, session-kill), keeping long-running sessions alive across SSH disconnections and MCP server restarts.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Flotillarestart nginx on all web nodes, rolling two at a time"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Flotilla
多服务器 SSH MCP:让 AI 一次管理所有服务器
target 表达式 · rolling 执行带熔断 · 跨机比对 · 策略引擎 + 审批门 · 可篡改检测的审计日志
Flotilla 把"逐台 SSH 20 台机器"变成"声明一次意图,安全地执行"。它让 AI agent 通过 MCP 协议接管你的整个服务器舰队——但每一步都有策略引擎、审批门和审计链兜底。
你: "重启所有 web 节点的 myapp,rolling,一次两台"
│
▼
fleet-resolve 预演命中 → 策略引擎逐台过 → 审批门弹窗
│
▼
rolling 扇出(批次失败即熔断)→ 全程进哈希链审计日志目录
Related MCP server: sshops
为什么是 Flotilla
大多数 SSH MCP 工具解决的是"让 AI 操作一台服务器"。Flotilla 从第一天就是舰队视角设计的:
一次调用,命中整个舰队——target 表达式(
group:prod、tag:web !web-3、all)把一条命令扇出到 N 台机器执行有战术——并行求快、串行求稳、rolling + 熔断求安全:批次失败自动停,不会把好机器一起拖下水
比对是一等公民——
fleet-diff一条命令告诉你全舰队的版本/配置是否漂移安全不是开关是默认值——策略矩阵、审批门、哈希链审计全部默认开启,关掉要写进配置里
配置能集中管——放 Git 私有仓库,各端定时拉取 + 热重载,50 台机器改一处
功能亮点
🎯 Target 表达式寻址 —
group:prod !web-3、tag:web,tag:arm、all,先fleet-resolve预演再执行🚦 三种扇出策略 — 并行、串行、rolling(批次失败自动熔断,prod 破坏性操作默认 rolling)
🛡️ 六层安全模型 — 永禁清单、角色×层级矩阵、资源白名单、审批门(MCP elicitation 弹窗 + JIT 免批)、哈希链审计、命令配额
🤖 AI 辅助审批 — 破坏性命令触发审批时,本地 LLM 先生成风险评估卡(只做建议,永不做判决;提示注入防护内置)
🔍 跨机比对 —
fleet-diff比命令输出,fleet-diff-file按 sha256 比文件/目录📦 SFTP 批量分发/收集 —
fleet-push/fleet-pull,按机路径白名单🔁 服务器间直传 —
fleet-copy/fleet-sync:A→B 经控制机内存中转,服务器之间不用互通、不用互配 SSH 密钥🖥️ tmux 持久会话 — 断连不死,MCP server 重启也不死
🩺 零依赖体检 —
doctor一键全舰队 HEALTHY/WARN/CRIT⚙️ systemd 全家桶 — 服务状态、日志、启停重载,带服务白名单
🔄 YAML 工作流 — 多步骤编排、变量插值、失败回滚
➕ 一行加机器 —
fleet add --bootstrap一次性密码首连自动装公钥,新机器零准备入网;fleet-add探测主机、钉死 host key、热重载生效☁️ 配置集中管理 — 配置放 Git 私有仓库,各端定时拉取 + 热重载
🐳 Docker 双架构 — amd64 + arm64(树莓派友好),非 root 运行
安装与运行模式
做 Flotilla 的初衷就是「不想在多台服务器之间跳来跳去」——所以安装被压缩到一句命令:
curl -fsSL https://raw.githubusercontent.com/paipaiio/flotilla-mcp/main/deploy/bootstrap.sh -o bootstrap.sh
bash bootstrap.sh脚本自动识别系统环境(有 Docker 用 Docker,有 Node ≥ 20 用 Node,都没有就自动装 Docker), 然后引导入网第一台机器、生成 token、拉起服务——空白服务器到上线约 10 分钟。 重复执行是安全的:续走未完成的部分,不重复建容器/服务。
模式一:本地运行(自用首选)
装在自己的 MacBook / 工作机上,本地以 stdio 暴露 MCP,接进 Claude Code、Cursor 等 harness:
claude mcp add --transport stdio flotilla -- flotilla-mcp私钥和配置只存在你自己的机器上,信任边界最清晰;和 Claude Code 本地体验无缝——审批弹窗、 交互式确认全可用。
模式二:网站模式(团队 / 云端 agent)
部署到一台服务器,把整个舰队暴露为一个带 token 鉴权的 HTTPS MCP 端点。两个典型接法:
网站连接器:Grok 等平台的自定义 MCP 连接器,直接填 URL + token
聚合服务:Cloudflare 这类 MCP 聚合/代理服务背后挂它
bash bootstrap.sh # 同一脚本;装完把 127.0.0.1:PORT 反代到 Caddy/nginx(模板见 deploy/)fleet 随即成为 https://mcp.example.com/mcp。团队新机器入网只需一行
curl -fsSL https://mcp.example.com/join.sh | sudo sh -s -- --token <令牌>,
人和 agent 走同一个入口,同一套策略与审计。
28 个工具
工具 | 说明 |
| 一览服务器/分组/标签/层级/角色 |
| 预演 target 表达式,跑之前先看清命中哪些机器 |
| 加机器:探测(hostname/uid/tmux/host key)→ 钉 key → 追加配置 → 热重载 |
| 远程配置拉取(强制审批)/ 本地热重载 |
| 查看 / 一键清空活跃的 JIT 免批授权 |
工具 | 说明 |
| 白名单只读命令,并行扇出 |
| 任意命令,完整策略引擎 + 审批门 |
| sudo 提权;强制审批;密码走 env → stdin,不进 argv |
| 给数字 PID 发 INT/TERM/KILL/HUP,强制审批 |
工具 | 说明 |
| 一条只读命令跑全场,按相同输出分组 |
| 按 sha256 比对文件/目录,漂移、缺失、失败分组报告 |
| 负载、内存、磁盘、进程——零依赖探针 |
| 一键体检:每台 HEALTHY / WARN / CRIT |
| 限时跟踪 journal 或文件,本地 grep 过滤 |
工具 | 说明 |
| SFTP 批量分发 / 收集文件,多机默认 rolling |
| A→B 单文件直传:控制机内存中转,不落盘;两端过策略,跨 tier 强制审批 |
| A→B 目录同步(rsync 语义):sha256 增量,默认 dry-run, |
| 全舰队的 systemd 管理 |
工具 | 说明 |
| 断连不死的 tmux 持久会话 |
| YAML 工作流:有序步骤、插值、回滚 |
快速开始
安装
# npm(推荐)
npm install -g flotilla-mcp
# 或 Docker
docker pull ghcr.io/paipaiio/flotilla-mcp:latest
# 或源码
git clone https://github.com/paipaiio/flotilla-mcp.git && cd flotilla-mcp
pnpm install && pnpm build配置
零手动初始化:配置目录/文件不存在时 flotilla add 会自动创建(目录 700 / 文件 600),权限松了也会自动修好并提示。下面直接加机器即可:
逐台加机器(探测 + 钉 host key 一步到位,flotilla 是 npm 包自带的 CLI):
# 新机器还没装过公钥?一条命令入网(一次性密码首连 → 自动装公钥 → 之后全走密钥):
flotilla add web-1 --host 10.0.1.11 --user root --bootstrap --group prod --tags web
# 密码交互隐藏输入,或用 FLOTILLA_BOOTSTRAP_PASSWORD 环境变量传入(不进 shell 历史)。
# 默认生成舰队专用密钥 <配置目录>/fleet_ed25519;想复用已有私钥加 --key <path>。
# 机器上已有公钥时直接登记:
flotilla add web-1 --host 10.0.1.11 --user deploy --auth key --key ~/.ssh/id_ed25519 --group prod --tags web
# 自管本机(Gateway 宿主机自己):免密,公钥直接装本机 authorized_keys,啥都不用输:
flotilla add --local(默认读平台配置目录;自定义路径加 --config <path>。--bootstrap 只在 CLI 提供——密码不作为 MCP 工具参数传递。)
或手编(完整字段见 config.example.toml):
[defaults]
approvalMode = "ask-destructive" # auto | ask-destructive | ask-all | deny
commandQuotaPerDay = 500 # 滚动 24h 内命令类调用上限,0 = 不限;防 agent 失控死循环
[[servers]]
name = "web-1"
host = "10.0.1.11"
port = 22 # 非标配端口写这里
user = "deploy"
auth = "agent" # agent | key | password | certificate(密码从环境变量读,不落文件)
group = "prod" # 策略层级,缺省按名字推断,推断不出按最严的 prod
tags = ["web"]
[[servers]]
name = "db-1"
host = "10.0.2.11"
user = "deploy"
auth = "key"
keyRef = "~/.ssh/id_ed25519"
group = "prod"
via = "bastion" # 经跳板机(ProxyJump)接入 MCP 客户端
# Claude Code(npm 全局安装后直接用 flotilla-mcp 命令)
claude mcp add --transport stdio flotilla -- flotilla-mcp任何兼容 stdio 的 MCP 客户端同理:命令指向 flotilla-mcp(或源码安装的 packages/mcp-stdio/dist/index.js),传 --config <path> 或设 FLOTILLA_CONFIG。Codex 配置示例:
# ~/.codex/config.toml
[mcp_servers.flotilla]
command = "flotilla-mcp"HTTP Gateway(v2 首个切片)
同一套引擎常驻成 HTTP 服务:全部工具、策略引擎、配额、审计原样可用,传输层换成无状态 Streamable HTTP MCP。
# 无 token 直接拒绝启动——没认证的舰队网关 = 远程 root shell
export FLOTILLA_GATEWAY_TOKEN=$(openssl rand -hex 32)
flotilla-gateway --config ~/.config/flotilla/config.toml --host 127.0.0.1 --port 8080
# /mcp 每个请求都要 Bearer token;/healthz 开放给负载均衡探活
curl -s http://127.0.0.1:8080/healthz
curl -s -X POST http://127.0.0.1:8080/mcp \
-H "Authorization: Bearer $FLOTILLA_GATEWAY_TOKEN" \
-H 'Accept: application/json, text/event-stream' \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"curl","version":"1"}}}'默认只监听 127.0.0.1;要对局域网开放请放在反向代理 / TLS 之后。HTTP 客户端暂不支持交互式 elicitation:审批类操作会明确拒绝并提示用 confirm=true(若策略允许),缺失密码请走环境变量或 OS keychain。
一行入网(Tailscale 式):运营方签发一次性入网令牌,新机器自助完成入网——节点自装舰队公钥(密码不过线),网关回探 SSH 通过后原子写入配置并热重载:
# 运营方:签发令牌(仅显示一次,落盘的是 sha256 哈希)
curl -X POST http://127.0.0.1:8080/api/enroll/tokens \
-H "Authorization: Bearer $FLOTILLA_GATEWAY_TOKEN" \
-H 'Content-Type: application/json' -d '{"name":"rack-5"}'
# → {"token":"flt_…", …}
# 新机器(root 执行;首次在不信任网络可加 --fingerprint 钉住网关证书):
curl -fsSL http://127.0.0.1:8080/join.sh | sudo sh -s -- --token flt_…令牌支持 TTL / 次数上限 / 吊销(DELETE /api/enroll/tokens/<id>);回连地址取入网请求的 TCP 对端(要求网关能直连新机的 SSH,与全舰队一致)。
集中审计与合规导出:引擎的哈希链审计日志在网关侧汇聚,可同步到外部 sink,并按需导出报表:
# 审计 sink(可选,env 配置):转发到 webhook 或归档文件,失败只记日志不影响网关
FLOTILLA_AUDIT_WEBHOOK_URL=https://siem.internal/hook FLOTILLA_AUDIT_WEBHOOK_TOKEN=…
FLOTILLA_AUDIT_SINK_FILE=/mnt/audit/flotilla.jsonl
# 合规导出(运营方 Bearer,过滤器 AND 组合,CSV/JSON,默认最新在前、上限 1 万行)
curl -H "Authorization: Bearer $FLOTILLA_GATEWAY_TOKEN" \
"http://127.0.0.1:8080/api/audit/export?from=2026-09-01&host=web-1&outcome=failed&format=csv"Web 控制台:网关直接伺服一个零依赖的静态控制台(packages/gateway/console/,无构建步骤),浏览器打开 http://<gateway>/console/(/ 会 302 过去),输入 Bearer token 登录后即可用:总览(引擎健康 + 服务器清单)、命令执行(只读/带确认,走同一套策略引擎)、入网管理(签发/吊销令牌,显示一行入网命令)、审计(过滤 + CSV 导出)。静态文件不含任何秘密,所有 API 调用仍由服务端逐一鉴权——控制台没有新增攻击面。
MCP 聚合入口:一个 /mcp 端点不止挂舰队工具——用 JSON 配置把外部 MCP server(本地 stdio 命令或远程 HTTP 端点)挂载进来,工具以 <上游名>__<工具名> 前缀出现在同一个 tools/list 里,调用原样代理转发:
# upstreams.json:stdio 起本地命令,http 带鉴权头连远端
cat > upstreams.json <<'EOF'
[
{ "name": "fs", "transport": "stdio", "command": "npx", "args": ["-y", "@modelcontextprotocol/server-filesystem", "/srv"] },
{ "name": "peer", "transport": "http", "url": "http://10.0.0.9:8080/mcp",
"headers": { "Authorization": "Bearer <对方网关 token>" } }
]
EOF
flotilla-gateway --config fleet.toml --upstreams upstreams.json # 或 FLOTILLA_GATEWAY_UPSTREAMS
# 之后客户端就能看到 fs__read_file、peer__fleet-list …连接失败的上游不阻塞启动,在 /healthz 里显示 error 状态和原因。上游工具是运营方显式信任的"外来代码",不舰队策略引擎管辖(网关 Bearer 仍然兜底整面);参数以自由对象透传,上游自带的 schema 负责校验。
常驻部署(Docker 镜像 / systemd unit / Caddy + nginx TLS 模板)见 deploy/README.md;发布版网关镜像为 ghcr.io/paipaiio/flotilla-mcp-gateway。空白服务器冷启动、入网报错对照、反代必配头与重装清理清单见 deploy/TROUBLESHOOTING.md(按真实部署踩坑沉淀)。
开始使唤
"看下所有 prod 机器的磁盘" →
exec-read打group:prod"所有 web 节点的 nginx 版本一致吗?" →fleet-diff nginx -v打tag:web"prod 上重启 myapp,rolling,一次两台" →service-control自动带熔断
Target 表达式
web-1 单台
group:web-prod 配置的分组(或层级名:group:prod)
tag:web 按标签
all 全部
group:prod !web-3 排除
tag:web,tag:arm 并集
["web-1", "web-2"] 显式列表破坏性扇出之前,先 fleet-resolve 预演。
安全模型
六层纵深防御:
永禁清单 —
rm -rf /、curl | sh、写authorized_keys、fork 炸弹……对所有人拒绝,不可配置关闭角色 × 层级矩阵 —
viewer/operator/admin×prod/staging/dev。group缺省按名字推断,推断不出一律按最严的 prod资源白名单 — 按服务器的
scopes.paths/scopes.services/scopes.commands进一步收窄(只收窄,不放宽)审批门 — 破坏性/特权操作走 MCP elicitation 交互弹窗;
confirm标志默认 fail-closed(defaults.allowConfirmFlag = true或FLOTILLA_ALLOW_CONFIRM_FLAG=1才开启)。模型无法自我审批。弹窗可勾选「N 分钟内不再询问」生成 JIT grant(纯内存、重启即失效),fleet-grants随时查看/一键清空审计 — 每个决策和执行都落 JSONL,三层脱敏 + SHA-256 哈希链,篡改可检测
命令配额 —
defaults.commandQuotaPerDay限制滚动 24h 内命令类调用次数,状态落盘(重启不清零),防 agent 失控死循环
另外:
凭据永不进 argv、永不进日志:SSH agent → 密钥文件 → 环境变量(
FLOTILLA_<NAME>_PASSWORD/FLOTILLA_SUDO_PASSWORD……)→ OS 钥匙串(flotilla keychain set <name> [--sudo]存入,配置文件零敏感信息)主机密钥:进程内 TOFU,
trustedHostKey钉死跨重启;fleet-add首次接触即钉算法白名单默认开启(RFC 9142):禁 SHA-1(ssh-rsa/group1/hmac-sha1)和 CBC;老机器可用
allowLegacyAlgorithms = true单台豁免(建议升级 sshd)配置文件权限强制
0600;readOnly服务器拒绝一切写操作⚠️ 不要指向 root 账户。 用低权限账户 + NOPASSWD sudoers 白名单;不要在 prod 上开
approvalMode = "auto"
远程配置与热重载
服务器多了以后,把 config.toml 放进 Git 私有仓库,各端定时拉取:
[remote]
url = "https://raw.githubusercontent.com/<org>/<repo>/main/fleet.toml"
tokenEnv = "FLOTILLA_CONFIG_TOKEN" # GitHub PAT,走 Authorization: Bearer
refreshMs = 300000 # 每 5 分钟自动拉取+热重载;缺省只手动拉取 = 完整校验 → 旧文件时间戳备份 → 原子写入 → 热重载。坏负载永远不碰本地文件。日常改配置直接编辑本地文件也行——watcher 300ms 内自动生效。
Docker
docker run -i --rm \
-v ~/.config/flotilla/config.toml:/home/node/.config/flotilla/config.toml:ro \
-v ~/.ssh:/home/node/.ssh:ro \
ghcr.io/paipaiio/flotilla-mcp:latest非 root 运行,amd64 + arm64 双架构。
路线图
v1.0 ✅ — fleet-add、审计、远程配置拉取 + 热重载、双语 README、npm 发布、Docker、CI/CD
v1.x ✅ — 服务器间操作(fleet-copy / fleet-sync / 文件比对)、命令配额、JIT 审批授权、算法白名单(RFC 9142)、系统 keychain、
fleet add --bootstrap一键加机v2 ✅ 全部收官 — Gateway 常驻服务(无状态 HTTP MCP + Bearer 认证);常驻部署(Docker / systemd / TLS 模板);Tailscale 式一行入网;集中审计(sink 转发 + 合规导出);Web 控制台(/console/ 静态 SPA);MCP 聚合入口(单端点挂外部 MCP server);CA 证书认证(短寿用户证书 + fleet CA,见下文)
v3 设想 — 目标机轻量 agent、DAG 编排、团队协作
CA 证书认证(v2 收官切片)
第四种认证方式 auth = "certificate":不再把每台机器的公钥钉进 authorized_keys,而是由一把 fleet CA(ed25519,自动创建于 config 同目录的 fleet_ca / fleet_ca.pub)签短寿用户证书(默认 8 小时,certValiditySeconds 可调 300–604800 秒),目标机 sshd 只信任 CA 一行。
[[servers]]
name = "web-1"
host = "10.0.1.11"
user = "deploy"
auth = "certificate"
keyRef = "~/.ssh/id_ed25519" # 被认证的私钥;principals 自动 = user
certValiditySeconds = 3600 # 可选,默认 28800(8h);剩 1/4 寿命自动重签目标机一次性装机(把 CA 公钥装进 sshd 的 TrustedUserCAKeys,drop-in 到 sshd_config.d,幂等):
# 从 MCP 工具拿到命令后 root 执行;fleet onboard 的服务器可以直接用该工具
install -d -m 755 /etc/ssh/sshd_config.d && \
printf '%s\n' '<fleet_ca.pub 内容>' > /etc/ssh/flotilla-ca.pub && \
printf '%s\n' 'TrustedUserCAKeys /etc/ssh/flotilla-ca.pub' > /etc/ssh/sshd_config.d/60-flotilla-ca.conf && \
systemctl reload ssh工作原理一句话:ssh2 客户端协议无法直接出示 OpenSSH 证书,所以 flotilla 为每个 server 起了一个迷你 ssh-agent(进程内 UNIX socket,实现 OpenSSH agent 协议的 IDENTITIES/SIGN 两种请求),证书由它代持、签名用它背后的私钥——和 OpenSSH 本人用 agent 持证上场的机制完全一致。换来两个运维收益:证书泄露 8 小时后自动作废;吊销整支舰队的访问 = 在目标机上删一行 CA,而不是逐台翻 authorized_keys。
注意:enroll(一行入网)流程不变——先用 password/agent 认证把机器加进来,再执行上面的 CA 装机命令并切换 auth = "certificate"。CI 没有对真实 sshd 的端到端证书登录测试(环境没有 sshd 目标),证书正确性由 ssh-keygen -L 与验签测试保证。
贡献
私有打磨期暂不开放外部贡献。开源后:issue 提 bug / 需求,PR 请先开 issue 讨论方向。所有 PR 需要通过 CI(build + 460+ 测试 + Docker 构建)。
Star History
License
GNU Affero General Public License v3.0(见 LICENSE):
✅ 自由使用、修改、分发——包括企业内部生产使用
⚠️ Copyleft:分发或通过网络提供基于 Flotilla 的服务时,必须向用户公开完整源代码(AGPL 的网络条款)
💼 不想受 AGPL 约束(例如闭源商用)?提供商业授权——通过 GitHub 联系
This server cannot be deployed
Maintenance
Related MCP Connectors
- emisarOAuthdev.emisar
Let AI operate servers without SSH. Choose actions, approve risky changes, and audit every step.
Scoped, audited SSH exec, sessions, and SFTP on your saved servers without exposing credentials
Control plane for autonomous software labor. Agents claim objectives over MCP with audit trail.
Run commands and read/write files on your servers over Termalin's keyless tunnels (hosted MCP).
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceMCP server that enables AI agents to run fully interactive SSH sessions (via tmux) and execute commands like a human operator, with persistent sessions and multiple concurrent connections.6MIT
- AlicenseNot gradedqualityCmaintenanceA lightweight, zero-agent SSH operations tool that enables remote command execution, file transfer, and audit logging. It integrates as an MCP server for AI-driven infrastructure management.5 npmMIT
- AlicenseNot gradedqualityCmaintenanceAI-native SSH orchestration server enabling Claude or any MCP agent to execute commands, manage files, tunnels, and fleet operations across multiple hosts with security policies and audit logs.2Apache 2.0
- FlicenseNot gradedqualityAmaintenanceWeb-based SSH connection manager with an MCP server that enables AI agents to manage remote hosts via terminals, file transfers, and port forwarding, featuring human-in-the-loop approval for secure access.-