Skip to main content
Glama

MSAW 是一个运行在本地的多 SSH 工作区。它给 Agent 一组边界清楚的 MCP 工具,用来管理多台 VPS、执行命令和流转文件;私钥与密码留在本机,不进入 Agent 上下文。

项目仍在早期阶段。先用非生产机器验证,再把它接进真正的运维流程。

为什么做

一个 Agent 同时照看几台 VPS 时,麻烦通常不在 ssh 命令本身,而在三件事:

  • 凭据不能跟着对话四处流动。

  • 每台机器都应该有明确的操作边界。

  • 跨机器文件需要一个看得见、可检查的中转层。

MSAW 把这三件事放进同一个本地工作区。默认模式只允许 Agent 在远端工作目录内活动;需要管理整台机器时,再为单台主机显式打开全局模式。

Related MCP server: ssh-mcp-server

工作方式

flowchart LR
    Agent["Agent / Codex"] -->|MCP stdio| MCP["MSAW MCP"]
    UI["Web UI"] <-->|WebSocket + API| Core["Local Core"]
    MCP --> Core
    Core -->|OpenSSH| A["VPS A"]
    Core -->|OpenSSH| B["VPS B"]
    A -->|pull| Shared[".msaw/shared"]
    Shared -->|push| B
    Vault["Encrypted credentials"] --> Core

关注点

MSAW 的处理方式

SSH 认证

系统 OpenSSH、保存的私钥或保存的密码

凭据

本地加密保存,不通过 MCP 返回

远端权限

默认工作区模式,按主机显式开启全局模式

跨机文件

统一经过 .msaw/shared

页面状态

WebSocket 实时同步

长输出

首尾压缩、无重复增量读取、按需全量返回

快速开始

需要 Python 3.10+ 和本机 OpenSSH 客户端。

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

打开 http://127.0.0.1:8765。如果端口被占用,daemon 会选择可用端口并在状态结果中返回实际地址。

Linux 和 macOS 激活虚拟环境时使用:

source .venv/bin/activate
python -m pip install -e .

添加主机

系统 OpenSSH 配置:

msaw host add demo --host example.com --user root --auth-method system

保存私钥:

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

保存密码:

msaw host add demo-password --host example.com --user root `
  --auth-method password --password "replace-with-password"

命令行密码可能进入 Shell 历史。保存密码和粘贴私钥时,更建议使用 Web UI。

连接测试:

msaw test demo

两种远端模式

工作区模式

这是默认模式。命令会先进入主机配置的 workspace_path,pull/push 只接受相对路径,文件操作不会越出远端工作区。

全局模式

为单台主机显式开启后,命令不再自动进入工作区,pull/push 可以使用绝对路径和 ~。此时 Agent 拥有该 SSH 账号在整台远端机器上的权限,误操作影响也会明显放大。

msaw host add demo-global --host example.com --user root --global-mode

接入 Codex

在 Codex config.toml 中加入:

[mcp_servers.msaw]
command = "python"
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"

修改配置后重启 Codex,并在新任务中使用。推荐顺序:

daemon_ensure -> hosts_list -> host_test -> exec / transfer

MCP 工具

MSAW 暴露 13 个工具:

分组

工具

生命周期

daemon_status, daemon_ensure

主机

hosts_list, host_upsert, host_remove, host_test

执行

host_exec

共享区

shared_list, shared_read, shared_write

文件流转

host_pull_to_shared, host_push_from_shared

结果读取

result_read

长结果不会反复烧上下文

超过 8,000 字符或 120 行时,MSAW 默认只返回结果开头、结尾和一个 output_ref

继续读取时:

{
  "output_ref": "<output-ref>",
  "mode": "incremental",
  "max_chars": 8000
}

每次增量只返回尚未交付的字符区间。需要完整原文时,将 mode 改为 full;也可以在第一次调用常规工具时传入 full_output: true

结果缓存只存在于当前 MCP 进程,最多保留最近 32 条长结果。

安全边界

运行态数据全部放在 .msaw/,并被 Git 忽略:

.msaw/
  credentials.json
  hosts.json
  known_hosts
  keystore/
  logs/
  runtime/
  shared/
  • MCP 只返回认证类型和保存状态,不返回凭据内容。

  • 保存的凭据使用本地 RSA-2048 密钥对加密。

  • 临时私钥文件会限制权限,并在 SSH 调用结束后删除。

  • 主机指纹单独保存在 .msaw/known_hosts,首次连接采用 TOFU。

  • 命令回显会隐藏私钥文件路径和口令参数。

本地加密解决的是明文落盘和 MCP 暴露问题。它不能抵御已经能同时读取凭据文件与本地私钥的系统账号。操作系统账号和项目目录仍然需要正常的访问控制。

不要提交 .msaw/、真实主机清单、私钥、密码、日志或共享区文件。

开发

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

项目结构:

src/multi_ssh_workspace/
  cli.py
  credentials.py
  daemon.py
  mcp_stdio.py
  ssh_client.py
  web.py
  websocket.py
  workspace.py
  ui/
tests/
scripts/
docs/

License

MIT

A
license - permissive license
-
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/LusiyAvA/msaw'

If you have feedback or need assistance with the MCP directory API, please join our Discord server