MSAW

MSAW

Manages multiple SSH servers through a local workspace with MCP tools, executing commands and transferring files securely with credential isolation.

Category
访问服务器

README

<div align="center"> <img src="./docs/assets/msaw-banner.svg" width="920" alt="MSAW - Multi SSH Agent Workspace"> </div>

<div align="center"> <h1>MSAW</h1> <p><strong>面向 AI Agent 的本地多 SSH 控制面与共同工作区。</strong></p> <p><a href="./README.md">简体中文</a> · <a href="./README.en.md">English</a></p> </div>

MSAW 让 Codex 等 Agent 通过 MCP 同时操作多台 SSH 主机,并用本地 .msaw/shared 在不同 VPS 之间流转文件。主机库存、凭据、隔离初始化和全局权限由本地用户控制,不进入 Agent 的能力范围。

安全模型

边界 默认行为
Linux 日常身份 可一键创建 msaw-agent 系统用户,无密码、无 sudo,只拥有指定工作区
管理员身份 root/admin 凭据仅用于隔离初始化和用户授予的全局模式
全局模式 只能通过 Web UI/CLI 开启;开启后永久有效,直到用户手动关闭
主机库存 MCP 默认只读;添加和删除只能在 Web UI/CLI 完成
凭据存储 Windows DPAPI、macOS Keychain、Linux Secret Service;不可用时回退 RSA-OAEP 加密文件
私钥口令 通过 SSH_ASKPASS 传给 OpenSSH,不放进进程 argv
Web UI 默认只绑定 loopback;写操作校验 HttpOnly 会话 cookie 和同源 Origin
远程 Web 必须同时使用 --allow-remote 和 Bearer Token
文件传输 自动探测 rsync,支持 --partial;不可用时回退 SCP
MCP 协议 使用官方 Python MCP SDK 处理 stdio、schema、协商和取消

隔离用户依赖 Linux 文件权限,不是 chroot 或容器。它会阻止 Agent 读取 /etc/shadow、修改系统文件或使用 sudo,但仍能读取系统本来允许普通用户读取的内容。

工作方式

flowchart LR
    Agent["Codex / Agent"] -->|Official MCP SDK + stdio| MCP["MSAW MCP"]
    UI["Web UI / CLI"] --> Control["Local control plane"]
    MCP --> Control
    Control -->|OpenSSH| A["VPS A"]
    Control -->|OpenSSH| B["VPS B"]
    A -->|rsync / SCP| Shared[".msaw/shared"]
    Shared -->|rsync / SCP| B
    Vault["DPAPI / Keychain / Secret Service"] --> Control

安装

需要 Python 3.10+、OpenSSH 客户端和 Git。rsync 可选。

git clone https://github.com/LusiyAvA/msaw.git
cd msaw
python -m venv .venv
.\.venv\Scripts\python -m pip install -e .
.\.venv\Scripts\msaw init
.\.venv\Scripts\msaw ensure

打开 http://127.0.0.1:8765。Web UI 会实时显示主机、共享文件和操作状态。

Linux/macOS:

python3 -m venv .venv
.venv/bin/python -m pip install -e .
.venv/bin/msaw init
.venv/bin/msaw ensure

添加与隔离主机

Web UI 支持系统 OpenSSH、保存私钥和保存密码三种认证方式。点击“保存并测试连接”后会明确显示成功或失败;首次连接 Linux 管理员账号时,可保持“初始化 msaw-agent 隔离用户”选中。

CLI 使用系统 SSH 配置:

msaw host add prod-a --host example.com --user root --auth-method system
msaw test prod-a
msaw host isolate prod-a

保存私钥:

msaw host add prod-a --host example.com --user root `
  --auth-method key --private-key-file .\id_ed25519

命令行密码和口令可能进入 Shell 历史,保存凭据时优先使用 Web UI。

隔离初始化完成后:

  • 日常 workspace 操作使用 msaw-agent 专用 SSH key。
  • 原 root/admin 认证被保留为管理员凭据。
  • 新身份会再次执行 SSH 连接测试,成功后才切换主机配置。
  • 初始化失败不会切换日常身份,也不会保留无效凭据引用。
  • 已存在的同名 Linux 用户不会被复用;请在 Web UI 或 --user 中选择新的专用用户名。
  • 工作区必须位于隔离用户家目录、/srv、/opt/msaw 或 /var/lib/msaw 下的专用目录。
  • 初始化只修改工作区目录本身,不递归修改其中已有文件的所有权。
  • 管理员可以是 root,也可以是支持 sudo -n 的普通云主机账号。

全局权限

全局模式开关位于每台主机卡片上。普通开启永久有效,直到用户手动关闭:

msaw host mode prod-a --enable
msaw host mode prod-a --disable

临时授权必须显式选择,到期后自动关闭:

msaw host mode prod-a --enable --temporary --lease-minutes 30

MCP schema 不包含任何修改全局模式的字段或工具。

共同工作区

msaw pull prod-a releases/app.tar.gz --shared-path releases/app.tar.gz
msaw push prod-b releases/app.tar.gz --remote-path releases/app.tar.gz
msaw transfer prod-a prod-b releases/app.tar.gz
msaw transfer prod-a prod-b releases/app.tar.gz --keep-transfer-copy

transfer 仍通过本地共享区中转。传输成功后默认删除临时副本;失败时会保留现场,显式使用 --keep-transfer-copy 可保留成功传输的副本。双方支持 rsync 时自动使用增量和断点续传,否则自动使用 SCP。

接入 Codex

config.toml 建议直接指向项目虚拟环境,避免 Codex 启动时依赖已运行的 Web 服务:

[mcp_servers.msaw]
command = "<path-to-msaw>/.venv/Scripts/python.exe"
args = ["-m", "multi_ssh_workspace.cli", "mcp"]
cwd = "<path-to-msaw>"
startup_timeout_sec = 30
tool_timeout_sec = 180
required = true

[mcp_servers.msaw.env]
MSAW_HOME = "<path-to-msaw>"
PYTHONPATH = "<path-to-msaw>/src"
PYTHONDONTWRITEBYTECODE = "1"

Linux/macOS 将 command 改为 <path-to-msaw>/.venv/bin/python。

MCP 启动时会自动确认并按需启动本地控制服务。Agent 应按以下顺序工作:

hosts_list -> host_test -> host_exec / shared transfer

MCP 工具

默认暴露 9 个工具:

分组 工具
主机只读 hosts_list, host_test
多机执行 host_exec
共同工作区 shared_list, shared_read, shared_write
文件流转 host_pull_to_shared, host_push_from_shared
结果读取 result_read

host_exec 使用统一的多目标接口:

{
  "targets": ["prod-a", "prod-b"],
  "command": "uname -a",
  "timeout": 60,
  "concurrency": 4
}

单主机也使用长度为 1 的 targets,一次最多 16 台。默认每台最多返回最有价值输出流的 10 行、1500 字符,并且整个响应不超过 8000 字符和 120 行;失败主机优先于成功主机保留详情。完整细节保存在当前 MCP 会话。

只有本地用户开启库存修改后,MCP 才额外暴露 host_upsert 和 host_remove:

msaw settings inventory --allow
msaw settings inventory --deny

即使启用,这两个工具也不能接收凭据、修改认证方式或开启全局模式。修改设置后需要让 MCP 客户端重新连接。

长输出与取消

普通长结果会返回首部、尾部和 output_ref。批量执行受每台和全局双层预算约束,未展示内容进入结果缓存。

{
  "output_ref": "<output-ref>",
  "mode": "incremental",
  "max_chars": 8000
}
  • incremental 只返回此前从未交付给 Agent 的内容。
  • full 返回带明确标识的完整结果,允许重复先前内容。
  • 常规工具也可传 full_output: true 直接请求全量。
  • 缓存仅存在于当前 MCP 进程,最多保留最近 32 条结果。

SSH、SCP 和 rsync 都通过异步子进程执行。MCP cancel 会立即终止同一请求下的全部进程;2 秒内未退出则强制结束。

Web 访问

本地模式:

msaw serve --host 127.0.0.1 --port 8765

MSAW 拒绝直接监听非 loopback 地址。远程访问必须通过本机 HTTPS 反向代理,并从环境变量或权限受限的文件提供 Bearer Token:

$env:MSAW_BEARER_TOKEN = "<token>"
msaw serve --host 127.0.0.1 --port 8765 --allow-remote

msaw serve --host 127.0.0.1 --port 8765 --allow-remote --bearer-token-file .\.msaw\web-token

反向代理必须传递 X-Forwarded-Proto: https。远程 Web UI 使用 Bearer Token 换取 Secure、SameSite、HttpOnly 会话 cookie;Token 不进入 URL 或进程 argv。不要把 8765 端口直接暴露到公网。

运行数据

.msaw/
  credentials.json
  hosts.json
  settings.json
  *.lock
  known_hosts
  keystore/
  logs/
  runtime/
  shared/

不要提交 .msaw/、真实主机清单、凭据、日志或共享文件。RSA keystore 只在系统凭据服务不可用时作为兼容 fallback。

开发

python scripts/codegraph.py
python -m unittest discover -s tests -p "test_*.py" -v

核心模块:

src/multi_ssh_workspace/
  config.py
  credentials.py
  execution.py
  isolation.py
  mcp_stdio.py
  settings.py
  ssh_client.py
  web.py
  websocket.py
  workspace.py

License

MIT

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选