mcpField
P
Python SSH MCP

Python SSH MCP

ローカル
github.com/Nightreaver開発ツール821 週間前に更新

Python SSH MCP について

Python SSH MCPは、設定したホストへのSSHアクセスを制御してLLMに提供するFastMCPサーバーです。アクセス階層、パス制限、監査ログにより、公開する操作を絞れます。

主な機能

  1. 01設定可能な4段階のアクセス権
  2. 02SSHツールの10グループ
  3. 03パス許可リストと厳格なknown_hosts
  4. 04秘密情報を伏せたファイル読み取り
  5. 05Docker、systemctl、パッケージ操作
  6. 06ハッシュ化監査ログと運用者フック

活用シーン

  1. 01ホストへの読み取り専用SSH確認
  2. 02許可したパスにファイル操作を制限
  3. 03指定したDockerやsystemctl操作の実行
  4. 04秘密情報を見せずに設定を確認

MCP 対応

stdioまたはHTTP経由で、SSHやホスト管理用ツールをMCPクライアントに提供します。公開するアクセス階層とツールグループを設定できます。

設定

ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。

mcp.json · 共通設定
{
"mcpServers": {
"python-ssh": {
"command": "uvx",
"args": [
"git+https://github.com/Nightreaver/python-ssh-mcp"
],
"env": {
"LOG_LEVEL": "<LOG_LEVEL>",
"ALLOW_LOW_ACCESS_TOOLS": "<ALLOW_LOW_ACCESS_TOOLS>",
"ALLOW_DANGEROUS_TOOLS": "<ALLOW_DANGEROUS_TOOLS>",
"ALLOW_SUDO": "<ALLOW_SUDO>"
}
}
}
}
起動コマンドuvx 'git+https://github.com/Nightreaver/python-ssh-mcp'
設定が必要な環境変数
LOG_LEVEL
ALLOW_LOW_ACCESS_TOOLS
ALLOW_DANGEROUS_TOOLS
ALLOW_SUDO

ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。

パッケージ
pypigit+https://github.com/Nightreaver/python-ssh-mcp

ツール

ツール一覧はまだ取得されていません

ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。

詳細

Python SSH MCP

Python FastMCP License Tests

FastMCP 上に Python で構築された SSH MCP サーバーです。目的は、細かな制御を維持しながら、LLM に多数のホストへの実際の SSH アクセスを提供することです。何ができて何ができないかを細かく制御できます。設定項目は意図的に幅広くしています。単一の ssh_exec ツールだけが必要な場合は過剰かもしれませんが、複数のホストへの接続や、特定のパス、コマンド、可視性レベルへのエージェントの制限を始めると、その価値を発揮します。必要なツールが見当たらない場合は、issue を作成してください。

現在実装済み: 10 グループにわたる 100 個のツール、成功したユニットテスト 1649 件に加え、Docker 化された sshd の統合テスト 6 件、さらにオペレーターの実際の hosts.toml を使ってすべてのツールを実行するオプトイン方式の tests/e2e/ テストスイートがあります。デフォルトでは厳格な known_hosts を使用し、パスを扱うすべてのツールでパスの許可リストによる制限を適用します。監査ログは SHA-256 でハッシュ化され、フックはオペレーターがプラグイン可能です。LLM が秘密情報を見ずに設定ファイルを読めるようにする、秘密情報のマスキングポリシーも備えています(HMAC-SHA256 ハッシュマーカー、redact_paths_globs の block/warn/audit_only バイパスモード)。パスを扱う 5 つの sudo ティアツールは、sudo の下でもパスのポリシーを順守します(read/read_redacted/write/edit/sftp_list)。upload/deploy/download/sudo_write ではローカルディスクのストリーミングモードを利用できるため、大容量ファイルは LLM の base64 チャネルを通りません。ほとんどのツールは型付きの Pydantic 結果を返すため、MCP クライアントは tools/list で汎用の object ではなく実際のスキーマを確認できます。正当な理由でペイロードのマージや二峰性が発生する一部のツールは、dict[str, Any] のままとし、その理由を関数に記載しています。POSIX の SSH ターゲットをエンドツーエンドでサポートしています。Windows の SSH ターゲットも、PowerShell の -EncodedCommand を介した SFTP、ファイル操作、ssh_file_hash をサポートします(ADR-0023 を参照)。Docker CLI は SSH_DOCKER_CMD またはホストごとの docker_cmd で Podman に切り替えられます。

Contents

このファイルの内容:

Quick Start

  • python-ssh-mcp をインストールします
  • 最初の hosts.toml エントリーを記述します(ウォークスルー §3)
  • MCP クライアント(Claude Desktop、Claude Code、Cursor など)をセットアップします
  • LLM にターゲットに対して ssh_host_ping を実行するよう依頼します。エージェント、known_hosts、プールがエンドツーエンドで検証されます
  • 必要なティアフラグ(ALLOW_LOW_ACCESS_TOOLS、ALLOW_DANGEROUS_TOOLS、ALLOW_SUDO)を有効にすると、LLM がファイル操作、実行、sudo を利用できるようになります。詳しくはCONFIGURATION.md → アクセスティアを参照してください

CONFIGURATION.md — ホストの追加、アクセスティア、許可リスト/ブロックリスト、ツールグループ、Docker/Podman、ホストごとの SSH ID、known_hosts の管理、sudo の設定について説明します。
ADVANCED.md — ランブック(FastMCP Skills)、フック、可観測性、テスト、キーのローテーション、アーキテクチャ、コントリビューションについて説明します。

Features

  • MCP 準拠のサーバー。stdio 経由で SSH を公開します(必要に応じて HTTP も選択できます)。トランスポートは MCP と直接通信し、シムは不要です。
  • 4 段階のアクセスモデル — read / low-access / dangerous / sudo。各段階はそれぞれ専用の環境変数フラグで切り替え、FastMCP の Visibility トランスフォームで適用します。デフォルトは読み取り専用です。
  • 10 個のツールグループ。アクセス段階とは独立したグループ(host、session、sftp-read、file-ops、exec、sudo、shell、docker、systemctl、pkg)です。SSH_ENABLED_GROUPS を使うと、各アシスタントが実際に必要とするツールだけにカタログを絞り込めます。
  • 100 個のツール:ツールごとの完全なリファレンスは TOOLS.md を参照してください。主な機能:
    • 読み取り専用のプローブ(ping、ホスト情報、ディスク使用量、プロセス、アラート、known-hosts の検証、ユーザー情報、ホストメモ、server-info)
    • mcp://ssh-mcp/server-info リソースと ssh_server_info フォールバックツール -- サーバーの ID と機能一覧を提供するため、LLM(またはオペレーター)はカタログを grep せずに「このサーバーのバージョンは何か/どのアクセス段階が有効か/表示されるツールはいくつか」を自己確認できます(v1.5.0)
    • SFTP による読み取り(一覧表示、stat、ダウンロード、検索、file_hash)。リモートの realpath による制限付きです。
    • ssh_read_redacted — 設定ファイル(.env、.yml など)を読み取り、シークレットを HMAC-SHA256 ハッシュマーカーにインラインで置き換えます。LLM は構造情報を取得できますが、平文を見ることはありません(v1.4.0)
    • 低アクセスのファイル操作(cp、mv、mkdir、delete、delete_folder、edit、patch、upload、deploy、link、transfer)— SFTP 優先で、書き込みはアトミックです。upload/deploy/sftp_download は local_path= に対応し、base64 の往復処理なしで大きなファイルをストリーミングできます(v1.3.0)
    • 呼び出しごとのタイムアウト、ストリーミング版、ホスト間の一括実行に対応した Exec 段階。また、デフォルトで有効なチートシートが cat/tee/sudo cat/... を検出し、適切なネイティブツールに振り分けます。
    • Sudo 段階 — ssh_sudo_exec に加え、sudo 段階のパスを受け取る 5 つのツール(ssh_sudo_read、_read_redacted、_write、_edit、_sftp_list)を用意しています。これにより、root 所有のファイルも、sudo cat を直接実行して迂回するのではなく、パスのポリシー内に保たれます(v1.4.0)。パスワードは stdin 経由で渡し、argv には含めません。環境変数によるパスワードは起動時に必ず拒否されます。
    • Docker ツール 27 個(ps、logs、inspect、stats、events、system_df、images、volumes、compose up/down/logs/...、コンテナのライフサイクル管理、exec、run、prune)
    • systemctl ツール 17 個(読み取りおよびライフサイクルの変更)と journalctl/一覧表示用ヘルパー 8 個
    • APT/パッケージ用ツール 9 個 — 読み取り(apt_list、apt_search、apt_show、apt_show_holds)と変更(apt_install、apt_upgrade、apt_remove、apt_autoremove、apt_mark)。Debian 以外のホストでは、明確な PlatformNotSupported が返されます。
    • cwd を追跡する永続的なシェルセッション(リモート PTY は使わず、センチネルベースで状態を管理)
  • 厳格な known_hosts — 自動承認は行いません。不明なキーや一致しないキーは安全側に倒して拒否します。
  • すべてのパスを制限 — パスを受け取る各ツールは、リモートの realpath(Windows では SFTP の realpath)を通じてパスを正規化し、許可リストと照合します。機密領域には restricted_paths の例外を設定できます。
  • hosts.toml によるホストごとのポリシー — ユーザー、キー、許可リスト、sudo モード、プラットフォーム、プロキシチェーン、アラートしきい値、永続セッションの無効化を設定できます。
  • Windows SSH ターゲットへの対応(SFTP とファイル操作。詳しくは ADR-0023 を参照)。POSIX 専用ツールは Windows ターゲットでの実行を拒否し、不足している機能を明示した PlatformNotSupported を返します。
  • 監査ログ — ツール呼び出しごとに JSON を 1 行記録します(全アクセス段階対象)。パス/コマンドは SHA-256 でハッシュ化され、error フィールドには例外クラスのみが記録されます(全文はローカルの DEBUG にのみ記録)。
  • オペレーター向けフック:SSH_HOOKS_MODULE から任意のモジュールをインポートして、STARTUP/SHUTDOWN/PRE_TOOL_CALL/POST_TOOL_CALL イベントを処理できます。フックごとのタイムアウトには上限があり、例外は分離されます。保留タスクが滞留した場合は警告が出ます。
  • FastMCP Skills によるランブック — ツールごとの SKILL.md ファイルにより、LLM は必要に応じて対象を絞った使い方のドキュメントを取得できます。
  • BM25 ツール検索(任意)— 50 個以上のスキーマがコンテキストを圧迫し始めた場合、tools/list を search_tools と call_tool に置き換えます。
  • 起動時にツールカタログの概要をログに記録(アクセス段階別およびグループ別の件数)。これにより、オペレーターは LLM に提示される内容を正確に確認できます。

インストール

Python SSH MCP は、標準的な PEP 621 Python パッケージです(ビルドバックエンドは hatchling)。お好みのインストーラーを使用できます。uv の使用をおすすめします。

uv sync                      # create .venv + install runtime deps + dev extras
uv run ssh-mcp               # start the server on stdio

# Or without syncing a venv first — build + run in an ephemeral environment:
uvx --from . ssh-mcp

# Plain pip also works (PEP 517):
pip install -e ".[dev]"
ssh-mcp

# FastMCP shortcuts (once the package is installed):
fastmcp dev inspector        # dev UI: MCP Inspector + hot reload; auto-finds fastmcp.json
fastmcp run                  # run the server; auto-finds fastmcp.json
fastmcp run -t http -p 8000  # HTTP transport instead of stdio

オプションの依存関係グループ:

  • .[tasks] — 本番環境のタスクバックエンド用に Redis クライアント(redis>=5.0.0)を追加します。FastMCP のタスクランタイム自体(デフォルトではメモリ内で動作する docket)は、fastmcp[tasks] を通じた必須依存関係であり、常に含まれます。この追加依存関係をインストールするのは、FASTMCP_DOCKET_URL を実際の Redis に設定する場合に限ります(ALLOW_DANGEROUS_TOOLS=true の本番環境では、再起動時のタスク消失が問題になる場合があります。詳細は _warn_task_backend を参照してください)。
  • .[telemetry] — OpenTelemetry ディストリビューションと OTLP エクスポーター。
  • .[dev] — pytest、ruff、mypy。

MCP クライアント(Claude Desktop、Claude Code、Cursor)は、fastmcp.json を通じてサーバーを検出します。

クライアントのセットアップ

主要な MCP クライアントはどれも、サーバーの起動方法を指定する JSON スニペットに対応しています。形式は mcpServers オブジェクトを基本とし、クライアントごとに異なるのはファイルパスだけです。クライアントを選び、該当するファイルにスニペットを貼り付け、クライアントを再起動してサブプロセスを再生成してください。

注意: プロジェクト内に fastmcp.json の deployment.env ブロックを残している場合、クライアントの環境変数より常に優先されます。このブロックにティアフラグを含めず、クライアント設定または .env から指定してください。コードを変更した後もクライアントが古いサブプロセスを保持しているように見える場合は、トラブルシューティングを参照してください。ほとんどのクライアントはサーバーのサブプロセスを起動して管理するため、ターミナル側で再起動するだけでは不十分です。

基本のスニペット(Claude Desktop、Cursor、Windsurf、Kilocode など、ほとんどのクライアントが使用する形式):

{
  "mcpServers": {
    "ssh-mcp": {
      "command": "uvx",
      "args": ["--from", "git+https://github.com/Nightreaver/python-ssh-mcp", "ssh-mcp"],
      "env": {
        "LOG_LEVEL": "INFO",
        "ALLOW_LOW_ACCESS_TOOLS": "false",
        "ALLOW_DANGEROUS_TOOLS": "false",
        "ALLOW_SUDO": "false"
      }
    }
  }
}

uvx --from <path> ssh-mcp は、uv が管理する一時的な環境でサーバーをビルドして実行します。クライアント側に永続的な venv は必要ありません。代替方法として、すでに PATH 上に fastmcp がある venv をお持ちの場合は、"command": "fastmcp"、"args": ["run", "<path-to-clone>/fastmcp.json"] に置き換えてください。

アシスタントに機能を許可する際は、ALLOW_* フラグを切り替えてください。デフォルトは読み取り専用に保ち、必要な場合に限って exec/sudo ティアを有効にしてください。

Claude Desktop

設定ファイル:

  • macOS:~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows:%APPDATA%\Claude\claude_desktop_config.json
  • Linux:~/.config/Claude/claude_desktop_config.json

基本のスニペットを貼り付けます。Claude Desktop を完全に終了し(システムトレイのアイコン → Quit)、再起動してください。再読み込みでは MCP サブプロセスは再生成されません。

Claude Code

JSON の編集は不要です。CLI コマンドを使用します。

claude mcp add --transport stdio ssh-mcp -- uvx --from git+https://github.com/Nightreaver/python-ssh-mcp ssh-mcp

スコープを指定するには、--scope user(グローバル)、--scope project(現在のリポジトリに .mcp.json をコミット)、--scope local(デフォルト。このプロジェクトのみ)を使用します。環境変数は --env KEY=VALUE フラグを繰り返し指定するか、後から ~/.claude/mcp.json を編集して設定できます。

Cursor

設定ファイル:

  • グローバル:~/.cursor/mcp.json
  • ワークスペースごと:<workspace>/.cursor/mcp.json

基本のスニペットと同じ mcpServers 形式です。Cursor は次のチャットセッションで設定変更を反映するため、完全な再起動は不要です。

VS Code(GitHub Copilot Chat/Agent Mode)

VS Code の MCP サポート(1.102 以降)では、少し異なるキーを使用します。設定ファイル:

  • ワークスペースごと:<workspace>/.vscode/mcp.json
  • グローバルユーザー設定:settings.json → "mcp.servers"

ワークスペースの .vscode/mcp.json:

{
  "servers": {
    "ssh-mcp": {
      "type": "stdio",
      "command": "uvx",
      "args": ["--from", "git+https://github.com/Nightreaver/python-ssh-mcp", "ssh-mcp"],
      "env": {
        "LOG_LEVEL": "INFO",
        "ALLOW_LOW_ACCESS_TOOLS": "false",
        "ALLOW_DANGEROUS_TOOLS": "false",
        "ALLOW_SUDO": "false"
      }
    }
  }
}

トップレベルのキーは mcpServers ではなく servers で、各エントリーには "type": "stdio" という識別子が含まれる点に注意してください。VS Code ウィンドウを再読み込み(Developer: Reload Window)して再生成します。

Windsurf(Codeium)

設定ファイル:~/.codeium/windsurf/mcp_config.json。基本のスニペットと同じ mcpServers 形式です。編集後に Windsurf を再起動してください。

Kilocode

設定ファイル:~/.kilocode/mcp.json(または Kilocode のインストール先にある同等のファイル。正確なパスは拡張機能のドキュメントに記載されています)。基本のスニペットと同じ mcpServers 形式です。編集後に VS Code ウィンドウを再読み込みしてください。

Continue.dev

設定ファイル:~/.continue/config.json。Continue では入れ子になったキーを使用します。

{
  "experimental": {
    "modelContextProtocolServers": [
      {
        "transport": {
          "type": "stdio",
          "command": "uvx",
          "args": ["--from", "git+https://github.com/Nightreaver/python-ssh-mcp", "ssh-mcp"]
        }
      }
    ]
  }
}

注:名前付きマップではなく、オブジェクトのリストです。環境変数は transport ブロック内に記述します。

Zed

コマンドパレットから設定します:assistant: configure context servers、 または ~/.config/zed/settings.json を編集します。

{
  "context_servers": {
    "ssh-mcp": {
      "source": "custom",
      "command": {
        "path": "uvx",
        "args": ["--from", "git+https://github.com/Nightreaver/python-ssh-mcp", "ssh-mcp"],
        "env": {}
      }
    }
  }
}
MCP Inspector(開発用 UI)

実際のクライアントに接続する前にサーバーをデバッグする場合:

fastmcp dev inspector

fastmcp.json を自動検出し、MCP Inspector を接続した状態で Web UI を起動します。ソースの変更時にホットリロードします。


ウォークスルー — 5 分で最初のホストを設定する

最短の手順は、エージェント認証+ホスト 1 台+読み取り専用の階層です。手順は 5 つです。

1. エージェントにキーを読み込む
  • Linux/macOS: ssh-add ~/.ssh/id_ed25519
  • Windows: Pageant を起動して .ppk を読み込む(または ssh-agent + ssh-add を実行する)

エージェントにアクセスできることを確認します。

uv run python -c "import asyncio; from ssh_mcp.ssh.agent import list_agent_fingerprints; print(asyncio.run(list_agent_fingerprints()))"

SHA256:... の行が 1 行以上表示されます。使用するキーの行をコピーしてください。後ほど参照します。

2. 対象ホストのホストキーをピン留めする(信頼する前に検証)

厳格な known_hosts 検証はデフォルトで有効です(自動承認は行いません)。ピン留めは 3 ステップで行います。ssh-keyscan の出力を直接 known_hosts に追加してはいけません。

# 2a. Scan to a scratch file. This does NOT trust anything yet.
ssh-keyscan -t ed25519,ecdsa,rsa web01.example.com > /tmp/web01.hostkey

# 2b. Print the fingerprint and compare OUT-OF-BAND.
ssh-keygen -lf /tmp/web01.hostkey
# → 256 SHA256:abc123... web01.example.com (ED25519)

SHA256:... を、スキャンに使用したネットワーク以外の信頼できる情報源と照合します。たとえば、ホストのプロビジョナーの出力、コンソールセッション、terraform の出力、システム管理者からの Signal メッセージなどです。一致しない場合は中止してください。 入力ミスや MITM によって、悪意のあるキーを信頼済みとしてピン留めしてしまう可能性があります。

# 2c. Only after the out-of-band fingerprint matches, append and clean up.
cat /tmp/web01.hostkey >> ~/.ssh/known_hosts
rm /tmp/web01.hostkey

known_hosts が存在しない、空である、または一致しない場合、MCP サーバーは接続を拒否します。

3. hosts.toml を作成する

注釈付きのスターターテンプレートをコピーして編集します。

cp hosts.toml.example hosts.toml
# Replace the SHA256:REPLACE-WITH-... fingerprints with yours from step 1.

または、一から作成する場合は、最小限の実用的なブロックを使用します。

[defaults]
user = "deploy"

[defaults.auth]
method = "agent"
identity_fingerprint = "SHA256:<paste-your-fingerprint-here>"
identities_only = true

[hosts.web01]
hostname = "web01.example.com"
path_allowlist = ["/opt/app", "/var/log"]

踏み台/プロキシジャンプ、ホストごとのキーの上書き、ディスク上のキーとキーチェーンのパスフレーズを組み合わせるパターンについては、hosts.toml.example を参照してください。複数ホスト向けの設定例(踏み台、ロールごとのキー、レガシーホスト)については、CONFIGURATION.md → さらに多くのホストを設定する を参照してください。

~/.ssh/config から継承する

~/.ssh/config(ホストエイリアス、ProxyJump、IdentityFile、レガシー機器向けの Ciphers/MACs の上書きなど)をすでに管理している場合は、SSH_CONFIG_FILE をそのファイルに設定すれば、これらの項目を hosts.toml に重複して記述する必要はありません。

SSH_CONFIG_FILE=~/.ssh/config

優先順位:常に hosts.toml が優先されます。~/.ssh/config は、ホストごとに設定していない項目のみを補います。OpenSSH の設定で、path_allowlist、command_allowlist、またはホストのブロックリストで許可されている範囲を広げることはできません。起動ログには ssh_config: honoring <abs-path>(ファイルが見つからない場合は WARNING)が記録されるため、設定ミスはすぐに判明します。

4. .env を作成する
# Start locked down — only read-only tools are active.
ALLOW_LOW_ACCESS_TOOLS=false
ALLOW_DANGEROUS_TOOLS=false
ALLOW_SUDO=false

# Optional safety rail
SSH_HOSTS_BLOCKLIST=
5. 最初から最後まで動作を確認する
uv run ssh-mcp

MCP クライアント(または簡単な Python シェル)から、次を呼び出します。

from ssh_mcp.server import mcp_server
# tools: ssh_host_ping, ssh_host_info, ssh_sftp_list, ssh_find, ...

ssh_host_ping(host="web01") は {reachable: true, auth_ok: true, latency_ms: N, ...} を返します。

失敗した場合は、トラブルシューティングを参照してください。


トラブルシューティング

no SSH agent reachable

エージェントの解決順序は、hosts.toml の identity_agent の明示的な指定 → SSH_AUTH_SOCK 環境変数 → Windows の自動検出(Pageant/OpenSSH パイプ)です。次を確認してください。

# Unix / macOS
echo $SSH_AUTH_SOCK
ssh-add -l

# Windows (PowerShell)
Get-Process Pageant -ErrorAction SilentlyContinue
uv run python -c "import asyncio; from ssh_mcp.ssh.agent import list_agent_fingerprints; print(asyncio.run(list_agent_fingerprints()))"
identity 'SHA256:...' not found in agent

hosts.toml のフィンガープリントが、エージェントから公開されているどのキーとも一致しません。実際に読み込まれているキーを確認します。

uv run python -c "import asyncio; from ssh_mcp.ssh.agent import list_agent_fingerprints; [print(fp) for fp in asyncio.run(list_agent_fingerprints())]"

表示されたフィンガープリントのいずれかを identity_fingerprint にコピーします。

HostKeyMismatch / UnknownHost

ホストキーが変更された(ローテーションまたは MITM)か、known_hosts にエントリがありません。LLM からこの検証を回避してはいけません。また、検証せずにスキャン結果を >> で直接 known_hosts に追加してはいけません。ウォークスルー §2 の 3 ステップの手順に従ってください。

ssh-keyscan -t ed25519,ecdsa <host> > /tmp/h.hostkey
ssh-keygen -lf /tmp/h.hostkey                     # compare fingerprint out-of-band
cat /tmp/h.hostkey >> ~/.ssh/known_hosts && rm /tmp/h.hostkey
HostNotAllowed

ホストが hosts.toml にも SSH_HOSTS_ALLOWLIST にも登録されていません。解決時には、まず入力を hosts.<alias> キーとして検索し、次に hosts.*.hostname と照合し、その後 env の許可リストを確認します。hosts.toml にエントリーを追加するか、ホスト名をそのまま SSH_HOSTS_ALLOWLIST に追加してください。

HostBlocked

拒否設定が優先されます。SSH_HOSTS_BLOCKLIST を確認してください。これは意図された動作です。ブロックが誤りであればエントリーを削除できますが、まず追加したオペレーターに確認してください。

PathNotAllowed

解決後(正規化後)のパスが path_allowlist 内のどのルートにも含まれていません。以下を確認してください。

  • パスは正しいですか?アクセス制限の低いツールは確認前にシンボリックリンクを解決するため、シンボリックリンク自体が /opt/app 内にあっても、/opt/app の外を指していれば拒否されます。
  • hosts.<name>.path_allowlist で対象パスが許可されていますか?
command_allowlist is empty but ALLOW_DANGEROUS_TOOLS=true

実行を有効にしているのに、許可するコマンドの範囲が指定されていない場合、ローダーは警告を表示します。SSH_COMMAND_ALLOWLIST を設定するか、ホストごとに空の command_allowlist を設定してください(明示的に指定すると制限なしになります)。

MCP クライアントにツールが表示されない場合
  • ティアを確認してください。ALLOW_LOW_ACCESS_TOOLS/ALLOW_DANGEROUS_TOOLS/ALLOW_SUDO は、デフォルトで拒否されます。
  • グループを確認してください。SSH_ENABLED_GROUPS は、空の場合はすべてのグループが対象となり、明示的に指定すると絞り込みます。
  • MCP クライアントを再起動してください。ツール一覧は MCP サーバーのバージョンごとにキャッシュされます。

監査ログのクエリ

すべてのツール呼び出しは、読み取りティアのツールも含め(v1.4.0 以降、すべてのティアが監査対象です)、ssh_mcp.audit Python ロガーに JSON を 1 行ずつ書き込みます。**監査ログをクエリするためのプロセス内ツールはありません。**これは意図的な仕様です(INC-052)。LLM が自身の監査証跡を読み取れると、侵害されたエージェントやジェイルブレイクされたエージェントが、自分の行動のうち何が検知されたかを監視し、検知を回避するように調整できてしまいます。監査ログはオペレーターに一方向で送られます。

ご自身のロギング設定で、ssh_mcp.audit を任意の送信先(ファイル、Loki、Splunk、Datadog、journald など)に接続してください。ローカルでのデバッグやインシデントの迅速な初期調査では、ログ行をファイルに書き込み、jq でクエリできます。

# In your own bootstrap (or a custom run_server wrapper)
import logging
h = logging.FileHandler("/var/log/ssh-mcp/audit.jsonl")
h.setFormatter(logging.Formatter("%(message)s"))
logging.getLogger("ssh_mcp.audit").addHandler(h)

各行は、単一のコンパクトな JSON オブジェクトです。スキーマは以下のとおりです。

fieldtypenotes
tsfloatUnix エポック秒
correlation_idstr16 桁の 16 進数文字列。ssh_mcp.audit の DEBUG レベルの詳細なエラー行と対応します
toolstrMCP ツール名(例:ssh_exec_run、ssh_broadcast)
tierstrread/low-access/dangerous/sudo
hoststr解決されたホスト名(または、ssh_broadcast のような複数ホスト対象ツールの場合は ?)
resultstrok/error
duration_msintツール呼び出しの実時間
path_hashstr正規化されたパスの sha256:<16hex>(ツールがパスにアクセスした場合)
command_hashstrマスキングされたコマンドの sha256:<16hex>(ツールがコマンドを実行した場合)
exit_codeint該当する場合
errorstr例外クラス名のみ。詳細なテキストは DEBUG レベルに記録されます(INC-008)

便利な jq の使用例:

# All errors in the last hour, sorted by tool
jq -r 'select(.result == "error") | "\(.ts) \(.tool) \(.host) \(.error)"' \
  /var/log/ssh-mcp/audit.jsonl | sort -k2

# Slowest dangerous-tier calls (top 20 by duration_ms)
jq 'select(.tier == "dangerous")' /var/log/ssh-mcp/audit.jsonl \
  | jq -s 'sort_by(-.duration_ms) | .[:20] | .[] | {tool, host, duration_ms}'

# Count by tool to see what the LLM is actually using
jq -r '.tool' /var/log/ssh-mcp/audit.jsonl | sort | uniq -c | sort -rn

# Trace one specific call end-to-end via correlation_id
jq 'select(.correlation_id == "a1b2c3d4e5f6abcd")' /var/log/ssh-mcp/audit.jsonl

command_hash と path_hash のフィールドは重複排除の補助であり、プライバシー保護のための制御ではありません。短い SHA-256 のプレフィックスは、よく使われるコマンドや正規化されたパスであれば、レインボーテーブルで簡単に特定できます。監査ログの機密性が重要な場合は、転送の暗号化(ログバックエンドへの TLS)と、送信先自体へのアクセス制御で保護してください。

免責事項

Python SSH MCP は、LLM(または任意の MCP クライアント)に、SSH 経由でリモートシステム上のコマンドを実行する権限を付与するローカルインフラストラクチャです。**ご自身の責任でご利用ください。**デフォルトで拒否されるティアフラグと厳格な known_hosts の適用により、明らかな落とし穴からは保護されますが、影響範囲を理解せずにすべてのフラグを true にするオペレーターから保護できるソフトウェアはありません。

本番環境で危険なティアまたは sudo ティアを有効にする前に、DECISIONS.md をお読みください。ssh_mcp.audit の JSON 行を定期的に監査してください。判断に迷う場合は、ティアを無効のままにしてください。

このプロジェクトは、いかなる SSH、FastMCP、または MCP のプロバイダーとも提携しておらず、推奨も受けていません。


サポート

AI の支援があっても、この MCP サーバーの構築と保守には多くの時間と労力がかかります。この SSH MCP によってワークフローや生活が楽になったと感じたら、ぜひご支援ください。

問題、質問、フィードバックがある場合は、GitHub issue を開いてください。Python SSH MCP が役立つと感じたら、リポジトリにスターを付けていただけると幸いです。本当に助けになります。

コメント

MCP は初めてですか?

プロトコルの概要から最初のサーバーの導入まで、よくある疑問にまとめて答えます。

AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。