VPS Ops について
VPS Opsは、SSH経由で1台のVPSを調査・操作するstdio MCPサーバーです。ホストやDockerの読み取り専用診断に加え、明示的な確認を必要とする変更ツールを備えています。
主な機能
- 01ホスト状態とシステムログの確認
- 02DockerとComposeの状態確認
- 03ファイアウォールとSSH設定の確認
- 04コンテナの再起動、停止、起動
- 05変更操作に明示的な確認を要求
活用シーン
- 01VPSのリソースやサービスの問題を診断
- 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 経由で 1 台の 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 を編集します。このファイルは Git の追跡対象外です。
| 変数 | 必須 | デフォルト | 用途 |
|---|---|---|---|
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。Registry は、パッケージが公開 npm に存在するようになってからメタデータを公開します。
クライアントへの登録
スクリプトは、すでにシェルでエクスポートされている変数から 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"
}
}
}
}
1 つのプロジェクトに適用するには、そのプロジェクトの 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"
config.toml を再読み込みさせるため、Codex セッションを閉じてから再度開きます。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。ユニットは許可リスト(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? | スタックをレンダリングし(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 の場合のみです。 |
セキュリティ
- リモートコマンドは固定されています。自由形式のシェルツールはありません。
- 名前とパスの引数は許可リストを通し、シェル内で引用符で囲まれます。
- SSH では
BatchMode=yes、IdentitiesOnly=yes、StrictHostKeyChecking=accept-newを使用します。 confirm: trueがない変更操作は拒否されます。docker_rmでは名前を 2 回指定します。ボリュームの削除にはconfirm_volumes: trueが必要です。- 読み取り専用のクライアントでは、
VPS_ALLOW_MUTATIONS=falseを指定して登録してください。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。