🏗️ ARCHITECTURE
全体アーキテクチャ
Claude.ai → Cloudflare Tunnel → LXC上のMCPサーバー → 任意のSSHホスト。
Claude.ai (ブラウザ / モバイル)
│
│ POST /mcp?key=ak_xxx&key=uk_aaa
│ HTTPS (Anthropic Cloud → Cloudflare Tunnel)
▼
┌──────────────────────────────────────┐
│ LXC: ssh-mcp-server (port 3000) │
│ │
│ Express + Streamable HTTP MCP │
│ ?key= → KeyStore → CallerContext │
│ (複数キー → 1つのコンテキスト) │
│ │
│ SSH Session Manager (in-memory) │
│ session_token = SHA-256 capability │
└──────────────────┬───────────────────┘
│ SSH (port 22)
▼
Proxmox / LXC / VM / NAS
🔑 AUTHENTICATION
3層認証モデル
門番(Admin Key) → 接続権(User Key) → 操作権(Session Token)
LAYER 1
Admin Key
環境変数で設定。User Key CRUD、全セッション閲覧。SSH新規接続は不可(権限分離)。
?key=ak_a8f3b2c1...
LAYER 2
User Key
MCP経由で発行。SSH接続の作成権。自分のセッションのみ一覧可能。
?key=uk_84e17ac6...
LAYER 3
Session Token
ssh_connectの戻り値。SHA-256ハッシュ。持っていれば誰でも操作可能。
sess_e7b2a4f1c3d8...
🔗 MULTI-KEY
マルチキー対応
?key= を複数指定すると、それぞれの権限が合成されます。
?key=ak_xxx&key=uk_hori
?key=uk_hori&key=uk_tanaka
?key=ak_xxx&key=uk_hori&key=uk_tanaka
💡 Primary User Key = ?key= パラメータで最初に指定したUser Key。ssh_connectで新しいセッションの所有者になります。
⏱️ SESSION LIFECYCLE
セッションのライフサイクル
$ ssh_connect(host, user, pass)
→ session_token: sess_a3f8b2c1e7d4...
→ state: CREATED (TTL: 1日)
$ ssh_execute(sess_..., "uptime")
→ state: USED (TTL: 最終使用から3ヶ月)
→ state: EXPIRED (auto-disconnected)
$ ssh_disconnect(sess_...)
→ state: DISCONNECTED
🆕 未使用 (TTL: 1日)
ssh_connect後、execute/upload/downloadを一度も実行していない。放置防止のため短め。
✅ 使用済 (TTL: 3ヶ月)
execute/upload/downloadを1回以上実行。最終使用時刻から3ヶ月。長期利用を想定。
🔒 SECURITY
セキュリティ設計
🔐 全経路HTTPS
Cloudflare Tunnel経由。Claude.ai → Anthropic → Cloudflare → LXC 全てTLS暗号化。直接ポート公開なし。
🛡️ セルフSSH防御
サーバー自身へのSSH接続をブロック。ADMIN_KEYやWEBHOOK_SECRETの漏洩を防止。BLOCKED_HOSTS環境変数 + localhost系は常時ブロック。
🗑️ 認証情報の非保存
SSHパスワード/秘密鍵はリクエスト処理中のみ使用。保存もログ出力もしない。再起動で全セッション消去。
🔗 SHA-256トークン
session_tokenは256bitハッシュ。SSH接続情報を逆算不可能。ブルートフォース不可能。
⚡ ASYNC COMMANDS
非同期コマンド実行
apt install や npm run build など、数分〜数十分かかるコマンドに対応。MCPタイムアウトを超える長時間コマンドも安全に実行。
$ ssh_execute(command="apt install -y nodejs", wait_ms=5000)
→ command_id: cmd_0001, running: true
→ stdout: "Reading package lists..."
$ ssh_command_status(command_id="cmd_0001", tail_lines=10)
→ running: false, exit_code: 0, elapsed_ms: 34521
$ ssh_execute(command="nohup ./deploy.sh &", wait_ms=0)
→ command_id: cmd_0002, running: true(バックグラウンド実行)
wait_ms
コマンドの出力を何ms待つか。0で即座に返す。デフォルト30秒。最大120秒。
tail_lines
大量出力の末尾N行のみ返す。apt installの進捗確認等に有効。
command_id
各コマンドにcmd_0001形式のIDが付与。ssh_command_statusで後からポーリング可能。結果は1時間保持。
🔄 CI/CD
GitHub Webhook自動デプロイ
GitHubにPushするだけで本番サーバーが自動更新。約5秒で新コードが稼働。
git push → GitHub Webhook
→ POST /webhook/github
→ HMAC-SHA256署名検証
→ git pull → npm install → tsc
→ process.exit(0) → systemd再起動
→ 約5秒で本番更新完了
💡 デプロイ失敗時は旧コードのまま稼働継続します(process.exitしない)。
セットアップは4ステップ
LXCデプロイ → Admin Key生成 → Cloudflare Tunnel → コネクター登録
🚀 始め方へ