关于 VPS Ops
VPS Ops 是通过 SSH 检查和操作单台 VPS 的 stdio MCP 服务。它提供主机与 Docker 的只读诊断工具,以及必须明确确认后才能执行的变更工具。
主要功能
- 01检查主机状态与系统日志
- 02查看 Docker 和 Compose 状态
- 03检查防火墙与 SSH 加固情况
- 04重启、停止或启动容器
- 05变更操作要求明确确认
适用场景
- 01诊断 VPS 上的资源或服务问题
- 02检查容器日志与 Compose 部署
- 03审查防火墙和 SSH 配置
- 04执行经确认的容器或 Compose 操作
MCP 相关
该服务通过 stdio 向 MCP 客户端提供 VPS 检查与管理工具,由 Cursor 或 Codex 启动;变更操作必须明确确认。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
npx -y @koller-nexus/vps-ops-mcpVPS_SSH_KEY_PATH密钥Absolute path to a readable SSH private keyVPS_HOSTSSH hostname of the single target VPSVPS_USERSSH usernameVPS_PORTSSH portVPS_COMPOSE_DIRAbsolute Compose directory on the remote hostVPS_COMMAND_TIMEOUT_MSRemote command timeout in millisecondsVPS_LOG_MAX_BYTESStdout/stderr byte cap for remote commandsVPS_ALLOW_MUTATIONSSet false to reject every mutation toolVPS_SSH_KEY_PASSPHRASE密钥Optional key passphrase; prefer ssh-agent instead本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
vps-ops-mcp
一个通过 SSH 操作单台 VPS 的 stdio MCP 服务。Cursor 和 Codex 使用 bun 启动进程,并调用只读工具(主机健康状况、Unix 调试、Docker、Compose、Swarm、防火墙)和变更工具(重启、停止、启动、清理)。变更操作需要明确确认。
传输方式为 stdio。请勿手动将服务作为长期运行的进程启动:客户端(Cursor 或 Codex)会启动它。
贡献
请参阅 CONTRIBUTING.md(分支、拉取请求、验证)和 ISSUE.md(如何提交问题)。
要求
- Bun
- Python 3(注册脚本会用到)
- OpenSSH 客户端(
PATH中的ssh) - 可读取且有权访问远程用户的 SSH 私钥
- 远程主机上:Docker(如果使用
ufw、fail2ban、sshd -T、ss和dmesg工具,还需要免密码的sudo -n)
配置
cp .env.example .env
编辑 .env。该文件已加入 gitignore。
| 变量 | 必需 | 默认值 | 用途 |
|---|---|---|---|
VPS_SSH_KEY_PATH | 是 | — | 私钥的绝对路径。若文件不存在或不可读,进程将拒绝启动。 |
VPS_HOST | 否 | vps.example.invalid | SSH 主机(占位值;请设置自己的主机)。 |
VPS_USER | 否 | ubuntu | SSH 用户。 |
VPS_PORT | 否 | 22 | SSH 端口。 |
VPS_COMPOSE_DIR | 否 | — | VPS 上 Compose 目录的绝对路径。未设置时,Compose 工具需要 dir 参数。 |
VPS_COMMAND_TIMEOUT_MS | 否 | 30000 | 远程命令超时时间。超时会返回 exit_code 124。 |
VPS_LOG_MAX_BYTES | 否 | 200000 | stdout/stderr 上限。超出部分将被截断,且 truncated 为 true。 |
VPS_ALLOW_MUTATIONS | 否 | true | 设置为 false、0、no 或 off 时,禁用所有变更操作。 |
VPS_SSH_KEY_PASSPHRASE | 否 | — | 请避免使用。建议使用 ssh-agent。注册脚本不会将此变量复制到客户端。 |
VPS_COMPOSE_DIR 必须是绝对路径,并匹配 /^[a-zA-Z0-9/_.-]+$/(必须以 / 开头)。
安装
bun install
npm 软件包(需要 Bun;MCP Registry 指向此构件):
bunx @koller-nexus/vps-ops-mcp
MCP Registry 名称:io.github.koller-nexus/vps-ops-mcp。只有在软件包发布到公开 npm 后,Registry 才会发布元数据。
注册客户端
脚本会使用已在 Shell 中导出的变量写入 MCP 配置。它们不会自行加载 .env。如果跳过导出,脚本将使用默认值(主机、用户、端口和本地密钥路径)。
在仓库根目录下,先执行一次以下操作,然后再运行每个脚本:
set -a
source .env
set +a
每次运行都会备份目标文件(*.bak.YYYYMMDDHHMMSS),并且只替换 vps-ops 服务。其他 MCP 服务会保留不变。
可选脚本变量:
| 变量 | 默认值 | 用途 |
|---|---|---|
MCP_PROJECT_DIR | 当前仓库根目录 | src/index.ts 路径的来源。 |
CURSOR_MCP_JSON | ~/.cursor/mcp.json | 要更新的 Cursor 文件。 |
CODEX_CONFIG | ~/.codex/config.toml | 要更新的 Codex 文件。 |
仅当设置了 VPS_COMPOSE_DIR 且其值非空时,才会将其写入客户端配置。
Cursor
全局注册(适用于每个工作区):
./scripts/register-cursor-mcp.sh
脚本会按以下格式写入 ~/.cursor/mcp.json:
{
"mcpServers": {
"vps-ops": {
"command": "bun",
"args": ["/absolute/path/vps-ops-mcp/src/index.ts"],
"env": {
"VPS_HOST": "your.host",
"VPS_USER": "ubuntu",
"VPS_PORT": "22",
"VPS_SSH_KEY_PATH": "/absolute/path/to/key",
"VPS_COMMAND_TIMEOUT_MS": "30000",
"VPS_LOG_MAX_BYTES": "200000",
"VPS_ALLOW_MUTATIONS": "true"
}
}
}
}
若要将其限定在单个项目中,请将脚本指向该项目的 mcp.json:
CURSOR_MCP_JSON="/absolute/path/to/project/.cursor/mcp.json" ./scripts/register-cursor-mcp.sh
然后重新加载 Cursor 窗口(命令面板 → Developer: Reload Window),或在 Settings → MCP 下重启服务。该服务会显示为 vps-ops。
Codex
./scripts/register-codex-mcp.sh
脚本会写入 ~/.codex/config.toml:
[mcp_servers.vps-ops]
command = "bun"
args = ["/absolute/path/vps-ops-mcp/src/index.ts"]
[mcp_servers.vps-ops.env]
VPS_HOST = "your.host"
VPS_USER = "ubuntu"
VPS_PORT = "22"
VPS_SSH_KEY_PATH = "/absolute/path/to/key"
VPS_COMMAND_TIMEOUT_MS = "30000"
VPS_LOG_MAX_BYTES = "200000"
VPS_ALLOW_MUTATIONS = "true"
关闭并重新打开 Codex 会话,使其重新读取 config.toml。如果 CLI 位于 PATH 中,运行 codex mcp list 应能看到 vps-ops。
验证
在 MCP 外部使用与服务相同的标志测试 SSH:
ssh -i "$VPS_SSH_KEY_PATH" \
-o BatchMode=yes \
-o IdentitiesOnly=yes \
-o StrictHostKeyChecking=accept-new \
-p "${VPS_PORT:-22}" \
"${VPS_USER}@${VPS_HOST}" \
'uname -a'
在 Cursor 或 Codex 中,请求客户端调用 vps_ping。响应为 JSON:
{
"exit_code": 0,
"stdout": "...",
"stderr": "",
"duration_ms": 0,
"truncated": false
}
exit_code 非零表示 MCP 错误。如果进程立即退出,并提示 VPS_SSH_KEY_PATH is required 或 missing or unreadable,说明该变量未传递到客户端的 env 中——导出 .env 后重新运行注册脚本。
工具
每次调用都会返回 exit_code、stdout、stderr、duration_ms 和 truncated。
只读
| 工具 | 参数 | 功能 |
|---|---|---|
vps_ping | — | uname -a、uptime、hostname。 |
vps_resources | — | df -h、free -h、负载平均值。 |
vps_journal | unit、n?(1–500,默认值 100) | journalctl -u。Unit 来自允许列表(docker、sshd、fail2ban、ufw、cron,可带或不带 .service),或是以 .service 结尾的安全名称。 |
docker_ps | — | 将 docker ps -a 作为 JSON 行返回。 |
docker_inspect | name | docker inspect。 |
docker_logs | name、n?(1–1000,默认值 200)、since? | docker logs --tail --timestamps。 |
docker_stats | — | docker stats --no-stream。 |
docker_service_ls | — | 将 docker service ls 作为 JSON 行返回(Swarm)。 |
docker_node_ls | — | 将 docker node ls 作为 JSON 行返回(Swarm)。 |
compose_ps | dir?、file? | 在 dir 或 VPS_COMPOSE_DIR 中运行 docker compose ps(file,例如 stack.yml,会转换为 -f)。 |
compose_config_vars | dir?、file? | 渲染 stack(docker compose config),并仅返回各服务的环境变量名称,不返回变量值。 |
host_deps | — | docker、docker compose(v2)和 jq 的版本。 |
host_listen | — | ss -lntup(使用 sudo -n,否则不使用 sudo)。 |
host_failed_units | — | systemctl --failed --no-pager --full。 |
host_top | — | 按内存占用列出前 30 个进程(ps aux --sort=-%mem)。 |
host_dmesg | n?(1–200,默认值 100) | dmesg -T + tail(使用 sudo -n,否则不使用 sudo)。 |
host_firewall | — | ufw status verbose(使用 sudo -n,否则不使用 sudo)。 |
host_fail2ban | jail? | fail2ban-client status(使用 sudo -n)。 |
ssh_hardening_check | — | 过滤后的 sshd -T:端口、密码、root 登录、公钥。 |
容器、服务、镜像和 jail 名称必须匹配 ^[a-zA-Z0-9][a-zA-Z0-9_.-]*$。
修改
这些操作都需要 confirm: true。设置 VPS_ALLOW_MUTATIONS=false 时,所有这些操作都会被拒绝。
| 工具 | 额外参数 | 远程命令 |
|---|---|---|
docker_restart | name | docker restart |
docker_stop | name | docker stop |
docker_start | name | docker start |
compose_up | dir?、services? | docker compose up -d |
compose_restart | dir?、services? | docker compose restart |
compose_pull_up | dir?、services? | 先运行 docker compose pull,再运行 up -d |
docker_rm | name、force_name | docker rm -f。force_name 必须与 name 相同。 |
disk_cleanup_docker | confirm_volumes? | docker system prune -f。只有设置 confirm_volumes: true 时才会清理卷。 |
安全
- 远程命令是固定的,不提供自由格式的 shell 工具。
- 名称和路径参数会通过允许列表校验,并在 shell 中加引号。
- SSH 使用
BatchMode=yes、IdentitiesOnly=yes和StrictHostKeyChecking=accept-new。 - 未设置
confirm: true的修改操作会被拒绝。docker_rm会要求输入两次名称。清理卷需要设置confirm_volumes: true。 - 对于只读客户端,请使用
VPS_ALLOW_MUTATIONS=false进行注册。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。