Hetzner Cloud (unofficial) について
Hetzner Cloud (unofficial) は、MCP クライアントから Hetzner Cloud を操作するための stdio 対応ローカル MCP サーバーです。API 操作ごとの型付きツールに加え、一般的なサーバー操作のラッパーと書き込み制御を備えています。
主な機能
- 01Hetzner Cloud API 操作を網羅
- 02一般的なサーバー操作のラッパー
- 03汎用 raw request ツール
- 04自動ページネーションとレート制限リトライ
- 05書き込み確認と読み取り専用制御
活用シーン
- 01Hetzner Cloud リソースの確認や管理
- 02ページネーションによる大規模リストの取得
- 03MCP 呼び出しの書き込み操作を制限
MCP 対応
stdio 経由で MCP クライアントに Hetzner Cloud API の読み取り・書き込みツールを提供します。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
npx -y @mguttmann/hetzner-cloud-mcpHETZNER_API_TOKENシークレットHetzner Cloud API token from the Cloud Console (project > Security > API tokens). The server can do exactly what this token allows; use a Read token if the client only needs to read.HETZNER_READ_ONLYtrue: every tool that is not read-only, and hcloud_raw_request with a method other than GET, returns an error without sending a request. Any value other than true, 1, yes, false, 0, no or empty stops the server at startup.HETZNER_CONFIRM_WRITEStrue: every tool that is not read-only returns a preview unless the call carries confirm "YES". Friction against mistakes, not a security boundary.HETZNER_DENY_TOOLSComma-separated tool name globs (for example hcloud_delete_*,hcloud_raw_request) that always return an error. Deny hcloud_raw_request as well, otherwise denied endpoints stay reachable through it. A pattern that matches no tool stops the server at startup.LOG_LEVELLog level of the JSON logs on stderr.ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。
ツール
202掲載時のツール一覧 · 2 日前に更新
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
| server_id | integer | はい | |
| firewall_id | integer | いいえ | |
| firewall_name | string | いいえ |
詳細
the-real-hetzner-mcp
Hetzner Cloud API 向けの非公式ローカル Model Context Protocol (MCP) サーバー
(stdio)です。ベンダー提供の Hetzner Cloud API 仕様にあるすべての操作を、読み取り・書き込み可能な型付きツールとして提供し、一般的なサーバー操作向けに手作業で調整したラッパーも備えています。npm パッケージ:@mguttmann/hetzner-cloud-mcp。
非公式プロジェクトです。 このサーバーは Hetzner Online GmbH とは提携、承認、出資、支援を受けていません。「Hetzner」は Hetzner Online GmbH の商標です。ベンダー提供の API 仕様(specs/cloud.spec.json)は Hetzner のものであり、このプロジェクトの MIT License の対象ではありません。NOTICE を参照してください。
メンテナンス状況
- 1 人のメンテナー(@mguttmann)が空き時間に、可能な範囲でメンテナンスしています。サポート契約はなく、応答時間も保証されません。
- セキュリティ修正は機能追加より優先されます。脆弱性は GitHub の非公開脆弱性報告機能から非公開で報告してください。公開 Issue には投稿しないでください。SECURITY.md を参照してください。
- 修正の対象となるのは最新のマイナーリリースのみです(サポート対象バージョンは SECURITY.md に記載されています)。
- 依存関係の更新は Dependabot が行います。実行時依存関係に既知の高または重大なアドバイザリがある場合、CI は失敗します。
- リリースは
mainのタグから GitHub Actions によってビルド、公開され、CycloneDX SBOM、SHA256SUMS、ビルドの来歴情報が付属します(変更点は CHANGELOG.md に記載されています)。 - Issue とプルリクエストを歓迎します。ツール名、パラメーター、環境変数はリリース間で安定して維持されます。契約上のルールについては AGENTS.md を参照してください。
機能
specs/cloud.spec.jsonからのコード生成により、Hetzner Cloud API を全面的にカバーします(操作ごとに生成ツールを 1 つ提供)。一般的なサーバー操作向けに手作業で調整したラッパーも備えています。正確なツール一覧と数は、tests/tools-contract.test.tsでtests/snapshots/tools-contract.jsonに照らして固定されています。- あらゆるエンドポイントに対応する汎用の回避手段として
hcloud_raw_requestを提供します。 - 上限付きの 429 バックオフ、上限値を設けた自動ページネーション、実時間予算を設けたアクションのポーリング(タイムアウトと再試行を参照)。
- オプションの書き込みガード
HETZNER_CONFIRM_WRITES=true:読み取り専用ではないすべてのツールは、呼び出しにconfirm: "YES"が含まれない限り、プレビュー(ツール名と入力)を返します。 - オプションのオペレータースイッチ
HETZNER_READ_ONLY=true(読み取り専用ツールとhcloud_raw_request経由のGETのみ実行)およびHETZNER_DENY_TOOLS(常にエラーを返すツール名の glob パターン)。どちらを使用しても、ツール一覧とスキーマは変更されません。
対象外
対象外: Hetzner Robot(専用サーバー API)、Hetzner DNS(Cloud DNS とは別の API を使用する独立した DNS 製品)、Hetzner Storage Boxes。これらは Cloud API の一部ではなく、コード生成用の仕様もありません。
対象: Cloud DNS ゾーンおよび RRSet(/v1/zones)は Cloud API 仕様の一部であるため、生成ツールを通じて対象になります。
インストール
Node.js 22.12 以降が必要です(package.json の engines を参照。.github/workflows/ci.yml の CI マトリックスでは、最低バージョンと現行の Node.js 系列をテストしています)。
0.1.x はインストールしないでください。 npm の 0.2.0 より前のバージョン(0.1.0 および 0.1.1)には、0.2.0 で修正されたパスインジェクション脆弱性があります。SECURITY.md を参照してください。
npm から(0.2.0 以降)
パッケージ名は @mguttmann/hetzner-cloud-mcp です。同じような名前のパッケージは、このプロジェクトのものではありません。
npm install -g "@mguttmann/hetzner-cloud-mcp@>=0.2.0"
バージョン範囲を指定すると、npm は脆弱性のある 0.1.x バージョンを拒否します。一致するバージョンがないと npm が報告する場合、0.2.0 はまだ公開されていません。その場合は、固定した git commit からインストールしてください。MCP クライアントの設定では、command は hetzner-cloud-mcp のみになります(パスは不要です)。
npx を使用(グローバルインストール不要)
npx -y "@mguttmann/hetzner-cloud-mcp@>=0.2.0"
MCP クライアントも同じ方法で起動します。バリアント C を参照してください。バージョン範囲はそのままにしてください。指定しない場合、npx は npm が latest として提供するバージョンを取得します。
MCP Registry から
登録されると、サーバーは公式 MCP Registry に io.github.mguttmann/the-real-hetzner-mcp として掲載され、パッケージには上記の npm パッケージが使用されます。Registry からインストールするクライアントも、同じ npm パッケージを使用します。
固定した git コミットから
git clone https://github.com/mguttmann/the-real-hetzner-mcp.git
cd the-real-hetzner-mcp
git checkout <full commit sha>
npm ci
npm run build
ブランチ名ではなく、完全なコミット SHA を固定してください。v0.2.0 タグのコミット(git rev-list -n 1 v0.2.0)、または main 上のそれ以降のコミットを指定します。npm ci はコミットされたロックファイルどおりにインストールします。
セットアップ
npm パッケージを使用する場合は、MCP クライアント設定の env ブロックで変数を設定してください(MCP Connector Setup を参照)。パッケージには .env ファイルは含まれていません。git チェックアウトの場合:
cp .env.example .env
# Add HETZNER_API_TOKEN to .env (Read & Write token from the Hetzner Cloud Console)
npm run refresh-spec と npm run generate はセットアップには含まれません。これらはツールの構成を変更します(Spec Updates を参照)。
サーバーは環境変数から設定を読み込みます。起動時には、パッケージディレクトリ内(package.json の隣)の .env ファイルも読み込みます(dotenv)。現在の作業ディレクトリにあるファイルは読み込みません。すでに設定されている変数が優先されます。デプロイ時には、代わりに任意の作業ディレクトリからファイルを明示的に指定できます:node --env-file=/path/to/.env dist/index.js。
実際の API に対する任意のスモークテスト(読み取り専用の呼び出しを 4 回):
npm run test:live
設定
必須なのは HETZNER_API_TOKEN のみです。以下のデフォルト値は tests/config.test.ts で固定されています。正の数ではない数値、認識できないブール値、またはログレベルを指定した場合は、デフォルト値にフォールバックします。ただし、HETZNER_API_BASE が無効な場合と、HETZNER_READ_ONLY の値が認識できない場合は例外となり、サーバーの起動が停止します。
| 変数 | デフォルト値 | 意味 |
|---|---|---|
HETZNER_API_TOKEN | (必須) | Hetzner Cloud API トークンです。すべてのリクエストでベアラートークンとして送信されます。サーバーが実行できる操作は、このトークンで許可されているものに限られます。 |
HETZNER_API_BASE | https://api.hetzner.cloud/v1 | API ベース URL です。https が必須です。平文の http を使用できるのは、localhost、127.0.0.1、または ::1 の場合のみです。それ以外の値を指定すると、サーバーの起動が停止します。テストまたはローカルの偽アップストリームを使用する場合にのみ上書きしてください。 |
HETZNER_CONFIRM_WRITES | false | true、1、または yes の場合、読み取り専用ではないすべてのツールは、呼び出しに confirm: "YES" が含まれていない限り、プレビューを返します。 |
HETZNER_READ_ONLY | false | true、1、または yes の場合、読み取り専用の注釈がないすべてのツールと、メソッドが GET 以外の hcloud_raw_request は、リクエストを送信せずに isError を返します。確認ガードより前にチェックされます。ツール一覧とスキーマは変更されません。true、1、yes、false、0、no、または空文字列以外の値を指定すると、サーバーの起動が停止します。 |
HETZNER_DENY_TOOLS | (空) | カンマ区切りのツール名グロブです(* は任意の文字列、? は任意の1文字に一致し、ツール名全体を大文字・小文字を区別して照合します)。例:hcloud_delete_*,hcloud_raw_request。一致したツールは、読み取り専用ツールも含め、リクエストを送信せずに isError を返します。ツール一覧とスキーマは変更されません。パターンでは、ゲートウェイのプレフィックスが付いた名前ではなく、サーバー独自の hcloud_* 名を使用します。どのツールにも一致しないパターンを指定すると、サーバーの起動が停止します。ツールを拒否しても、hcloud_raw_request 経由でそのエンドポイントをブロックすることはできません。そのため、拒否したエンドポイントがすべてそこから引き続き利用可能にならないよう、hcloud_raw_request も拒否してください。 |
LOG_LEVEL | warn | debug、info、warn、または error。ログは stderr に JSON 形式で出力され、stdout には MCP プロトコルが出力されます。 |
HTTP_TIMEOUT_MS | 30000 | 1回の API リクエストに対する実時間の上限です。すべての試行と再試行の待機時間が含まれます。 |
HTTP_MAX_RETRY_DELAY_MS | 10000 | 1回の再試行待機時間の上限です。429 エラーの Retry-After がこれを超える待機時間を要求する場合は、ただちにエラーとして返されます。 |
ACTION_POLL_TIMEOUT_MS | 45000 | wait: true を指定した呼び出しの実時間の上限です。呼び出しの開始時点から計測され、書き込みリクエスト、ポーリングリクエスト、およびそれらの再試行が含まれます。また、hcloud_wait_action の timeout_ms 引数の上限でもあります。 |
ACTION_POLL_INTERVAL_MS | 2000 | 2回のポーリング間の待機時間です。hcloud_wait_action の interval_ms 引数は、1000 またはこの値のいずれか低い方を下回ることはできません。 |
PAGINATION_MAX_ITEMS | 500 | 自動ページネーションを行うリストが収集する項目数のソフト上限です。上限に達したリストでは truncated: true が返されます。 |
PAGINATION_MAX_PAGES | 10 | 自動ページネーションを行うリストがリクエストするページ数のソフト上限です。 |
MAX_OUTPUT_BYTES | 8388608 | ツール結果のテキストの最大バイト数です。送信時のサイズ(JSON エスケープ後)で計算します。上限を超える結果は切り詰められ、末尾に [output truncated by MAX_OUTPUT_BYTES=...] が付きます。デフォルトを超える値はデフォルト値まで引き下げられ、1行の結果が stdio の上限である 10 MiB を下回るようにします。 |
PAGINATION_TIMEOUT_MS | 45000 | 1回の自動ページネーションを行うリストの実時間の上限です。上限に達すると、それまでに読み込まれたページが truncated: true と note とともに返されます。 |
MCP_SERVE_MODERN_PROTOCOL | false | true、1、または yes の場合、stdio 経由で MCP 2026-07-28 リビジョンも提供します(MCP プロトコルを参照)。initialize で接続を開始するクライアントには、false の場合と同じ 2025 年代のセッションが提供されます。 |
開発専用:RUN_LIVE_TESTS=1 を設定すると tests/live-smoke.test.ts が有効になります(npm run test:live により設定されます)。また、HETZNER_LIVE_SMOKE_ANCHORS では、このテストが存在を確認するサーバーを任意で指定できます。
タイムアウトと再試行
再試行:429 は Retry-After の後に再試行します。ヘッダーがない場合は、短いバックオフの後に再試行します(Hetzner は 1 秒あたり 1 件のリクエストを補充します。RateLimit-Reset はバケットが再び満杯になる時刻であり、遅延時間としては使用しません)。5xx はバックオフを伴って再試行します。ただし、すでに処理されている可能性がある POST は除きます。デフォルト設定では、1 回のツール呼び出しは約 max(HTTP_TIMEOUT_MS, ACTION_POLL_TIMEOUT_MS) 以内に応答するため(tests/call-budget.test.ts で測定)、MCP クライアントやゲートウェイで一般的な 60 秒のクライアント呼び出しタイムアウトを下回ります。値を大きくする場合は、この関係を維持してください。自動ページネーションされるリストでは、PAGINATION_TIMEOUT_MS の間、ページごとに 1 件のリクエストを実行します。この予算に達すると、読み取り済みのページが truncated: true と note を付けて返され、完全なリストに見える形で返されることはありません。
ポーリングに失敗した場合、または書き込みの成功後に予算を使い切った場合、ツールは書き込み応答(新しいリソース ID や一度だけ表示される root_password など)を polling_timed_out: true とともに返します。ポーリングに失敗した場合は、さらに polling_error も返します。
MCP プロトコル
サーバーは stdio 経由でのみ MCP を提供し、ネットワークポートは開きません。
- プロトコルのリビジョン:
2024-11-05、2025-03-26、2025-06-18、または2025-11-25を要求するクライアントには、そのリビジョンを返します。initializeでより新しいリビジョン(例:2026-07-28)を要求するクライアントには、2025-11-25を返します(tests/server.test.ts)。 - 2026-07-28 はオプトインです:
MCP_SERVE_MODERN_PROTOCOL=trueにすると、server/discoverで接続するクライアントにも応答し、同じツールを提供したうえで、2026-07-28 のリビジョンを使用します。initializeで接続するクライアントには、引き続き上記の 2025 年代のセッションが提供されます(tests/serve-protocol.test.ts)。デフォルトはfalseです。自動モードのクライアント(pythonmcpクライアントなど)は、新しいリビジョンが提示されるとすぐに切り替わるため、クライアントを確認してから有効にしてください。docs/adr/0001-mcp-sdk-v2.mdを参照してください。 - メッセージサイズの上限: 受信する JSON-RPC メッセージ 1 件(stdin の 1 行)は、MCP SDK の stdio 上限である 10 MiB 以下でなければなりません(
tests/transport-lifecycle.test.ts)。これを超える行があると、トランスポートが閉じます。サーバーは stderr にmcp transport errorを記録し、コード 1 で終了します。大きな引数(例:user_data)は、このサイズを大幅に下回るようにしてください。送信時は、ツールの結果がMAX_OUTPUT_BYTES(最大 8 MiB、tests/output-cap.test.ts)で切り詰められ、末尾に[output truncated by MAX_OUTPUT_BYTES=...]マーカーが付加されます。
MCP Connector のセットアップ(Claude Desktop / Claude Code)
クライアントの MCP 設定(Claude Desktop の場合は ~/Library/Application Support/Claude/claude_desktop_config.json、Claude Code の場合は同等の設定ファイル)に追記してください。
バリアント A:npm 経由でインストールした場合
{
"mcpServers": {
"hetzner-cloud": {
"command": "hetzner-cloud-mcp",
"env": {
"HETZNER_API_TOKEN": "...",
"HETZNER_CONFIRM_WRITES": "false",
"LOG_LEVEL": "warn"
}
}
}
}
バリアント B:git checkout からの場合
{
"mcpServers": {
"hetzner-cloud": {
"command": "node",
"args": ["/absolute/path/to/the-real-hetzner-mcp/dist/index.js"],
"env": {
"HETZNER_API_TOKEN": "...",
"HETZNER_CONFIRM_WRITES": "false",
"LOG_LEVEL": "warn"
}
}
}
}
バリアント C:npx を使う場合
{
"mcpServers": {
"hetzner-cloud": {
"command": "npx",
"args": ["-y", "@mguttmann/hetzner-cloud-mcp@>=0.2.0"],
"env": {
"HETZNER_API_TOKEN": "...",
"HETZNER_CONFIRM_WRITES": "false",
"LOG_LEVEL": "warn"
}
}
}
}
クライアントを再起動して変更を反映してください。tools/list には、tests/snapshots/tools-contract.json に固定されたツールがすべて表示され、名前はすべて hcloud_* です。
ツール:概要
手動調整済みラッパー
| ツール | 機能 |
|---|---|
hcloud_list_servers | name_contains フィルターを指定でき、デフォルトで name 順に並べ替えたサーバー一覧を取得します。 |
hcloud_get_server | id または name でサーバーを取得します。 |
hcloud_server_power | poweron/poweroff/reboot/shutdown/reset を1つのツールで実行します。 |
hcloud_server_rebuild | image_id または image_name を指定してサーバーを再構築します。 |
hcloud_server_snapshot | デフォルトで type=snapshot を指定して create_image を実行します。 |
hcloud_server_backup | 自動バックアップを切り替えます。 |
hcloud_server_rescue | デフォルトで type=linux64 を指定してレスキューモードを切り替えます。 |
hcloud_server_change_type | デフォルトで upgrade_disk=false を指定してサーバーのタイプを変更します。 |
hcloud_get_server_metrics | id または name でサーバーのメトリクスを取得します。デフォルトの時間範囲は「過去1時間」です。 |
hcloud_apply_firewall_to_server | ID または名前を指定して、ファイアウォールをサーバーに適用します。 |
hcloud_raw_request | API に対する任意のリクエストを実行します。クエリパラメーターは query に指定します。URL の正規化で変更される path、または %2F、%5C、%2E を含む path は拒否されます。 |
hcloud_wait_action | アクションが成功またはエラーになるか、タイムアウトするまでポーリングします。 |
生成されたツール
OpenAPI の操作ごとに1つのツールがあり、命名規則は hcloud_<verb>_<resource> または hcloud_<resource>_<action>_action です。ラッパーと名前が重複する場合、生成されたツールには接尾辞 _raw が付きます(hcloud_list_servers_raw、hcloud_get_server_raw、hcloud_get_server_metrics_raw)。
Inspector で tools/list を実行すると、全一覧を確認できます。
入力の検証
ハンドラーの実行前に、引数がツールで宣言された inputSchema に照らして検証されます。低レベルの MCP SDK サーバーが検証するのは tools/call リクエストの形式だけなので、このチェックによって宣言されたスキーマとのバインディングが確実になります。違反があると、問題のプロパティ名を示す isError 結果が返されます。ハンドラーは呼び出されず、Hetzner API にリクエストも送信されません。
検証される内容:
- リソース ID は 1 以上の JSON 整数でなければなりません。
"42"のような文字列でエンコードされた数値は、型変換されずに拒否されます。API が文字列として宣言しているパスパラメーター(id_or_name、rr_name、rr_type)は文字列のままですが、パスで使用する文字列は下記のとおり、単一のセグメントを指定する必要があります。 - トップレベルの型、
enum、minimum/maximum、minLength/maxLength、フラット配列の要素(要素の型、items.enum、items.minimum/maximum)、およびrequired。スカラー値の配列として宣言されたパラメーターには、スカラー値を直接指定することもでき、要素のスキーマに照らして検証されます。sortやstatusのような繰り返し可能な クエリ パラメーターの場合、シリアライズ後はパラメーターが 1 つだけの場合とまったく同じになるため、これを拒否すると、これまで常に機能していた呼び出しが壊れてしまいます。リクエスト ボディ に渡される配列型パラメーターはhcloud_server_rescue.ssh_keysの 1 つだけで、スカラー値を 1 要素の配列に正規化します。そのため、呼び出し元が送信した値は必ず使用されるか拒否され、黙って破棄されることはありません。不正な配列の要素ごとのメッセージは、先頭 10 件と件数に制限されます(tests/validate-input.test.ts)。これにより、大きな入力が結果やログに大量に展開されるのを防ぎます。 - トップレベルの未知のプロパティ。これは、スキーマで
additionalProperties: falseが宣言されているツール(すべてのラッパーと生成されたツール)に適用されます。範囲外のキーであるconfirm、wait、auto_paginateは常に許容されます。そのため、HETZNER_CONFIRM_WRITESが無効のときにconfirmを送信したり、これらを宣言していないツールにwait/auto_paginateを送信したりしても、エラーにはなりません。これらのキーはリクエストの構築前に破棄されます。 - パスパラメーターは、パスセグメントを厳密に 1 つ指定する必要があります。 API が文字列として宣言しているパラメーター(
id_or_name、rr_name)では、値が空、.または..、/または\を含む、あるいはパーセントエンコードされた区切り文字やドット(大文字・小文字を問わず%2f、%5c、%2e)を含む場合に拒否されます。理由:パーセントエンコードによって値が 1 つのセグメント内にとどまるのは、ローカルの URL パーサー上だけです。パスを解決するのは オリジン であり、オリジンはエンコードされた区切り文字をデコードし、ルーティングの前にドットセグメントを解決します。そのため、このチェックがなければ、細工された値によってツールが意図したものとは別のリソースを指定できてしまいます。正当な値は変更されません。IDN ゾーン名(生の値でも Punycode でも)、末尾のドット、@、*、*.sub、_dmarcなどはすべて許可され、従来どおりパーセントエンコードされます。 - すべての挿入箇所でパスセグメントがパーセントエンコードされ、HTTP クライアントは URL の正規化によって変更されるパスを拒否します。拒否されるもの:
?と#(パスがクエリ/フラグメントで切り詰められるため)、\(URL パーサーがパス区切り文字として扱うため)、RFC 3986 のpchar以外の文字(パーサーによって除去され、ドットセグメントを形成する可能性のある制御文字など)、空のセグメント、およびパーセントエンコードされたものを含むあらゆる表記の./..セグメント。組み立てられた URL は、その後、意図された宛先と照合されます。オリジンは設定されたものと一致し、パスはベースパスに要求されたパスを加えたものと完全に一致していなければなりません。これにより、残った正規化があれば、リダイレクトするのではなくリクエストを中止します。このクライアント側のチェックで検出できるのは、ローカルの URL パーサーが書き換える内容だけです。そのため、これは最後の防御線であって、保証のすべてではありません。オリジン による書き換えをカバーするのは、上記のパラメーターごとのルールです。 - 入力が拒否された場合、HTTP リクエストはまったく送信されません。 無害化されたリクエストが送信されることもありません。
意図的に 検証しない もの:リクエスト body の内容です。これらの構造は Hetzner Cloud API 自身の契約に従います。API が検証を行い、その 400 レスポンスは変更されずに呼び出し元へ返されます。format、pattern、nullable も評価されません。
検証エラーをログに記録する際は、問題のプロパティ名と問題の値の 型 が記録されます。値そのものは呼び出し元への返答にのみ含まれるため、秘密鍵やパスワードを含む不正な body がログに残ることはありません。
hcloud_raw_request に関する注意:このツールは、設計上、任意のパスを受け付ける意図的なエスケープハッチであり、リソースの許可リストによる制約はありません。設定された API ベース URL(オリジンとパスプレフィックス)に固定されますが、このツールを許可された呼び出し元は Hetzner Cloud API のあらゆるエンドポイントにアクセスできます。他のすべてのツールと同様に、path にパーセントエンコードされた区切り文字またはドット(大文字・小文字を問わず %2F、%5C、%2E)が含まれている場合は拒否します。エンコードされた区切り文字の意味を決めるのは、ローカルの URL パーサーではなくオリジンだからです。hcloud_raw_request はそれに応じて許可してください。
仕様の更新
Hetzner が OpenAPI を更新した場合:
npm run refresh-spec # re-downloads specs/cloud.spec.json
# update the fetch date and the SHA-256 in specs/SOURCE.md
npm run generate # rebuilds src/tools/generated/operations.ts
npm test # codegen and contract snapshots show the diff
npm run refresh-snapshot # rewrite the snapshots deliberately (after review)
git add specs/cloud.spec.json specs/SOURCE.md src/tools/generated/operations.ts tests/snapshots/tool-registry.json tests/snapshots/tools-contract.json
git commit -m "chore(spec): refresh from Hetzner"
更新するとツールの入力スキーマが変わり、ツールが追加されることもあります。これは MCP クライアントとゲートウェイにとって契約の変更となります。CHANGELOG.md の「Behaviour changes」に記載してください。新しい仕様によって既存ツールの body フィールドが必須になる場合は、ツールの契約を厳格化しないよう、scripts/generate.ts の PINNED_BODY_REQUIRED に以前のリストを残してください。そのフィールドがない呼び出しは、引き続き API によって拒否されます。新しいツールが追加されると、ゲートウェイベースラインのツール数と名前のハッシュが変わります。これらは tests/gateway-baseline.json にまとめられており、tests/tools-contract.test.ts と CI、リリース時のスモークテストで読み込まれます。
開発
ツール契約のスナップショット
tests/tools-contract.test.ts は、stdio サーバーとまったく同じ方法でレジストリ(src/build-registry.ts)を構築し、すべてのツールについて tests/snapshots/tools-contract.json と比較します。比較対象は、名前、inputSchema.required、inputSchema の正規化済み(キー順にソートされた)JSON の sha256(HETZNER_CONFIRM_WRITES=true の場合とそうでない場合)、説明の sha256、アノテーションです。また、ツール数とソート済みツール名の sha256 をゲートウェイベースラインに固定します。この 2 つの値は tests/gateway-baseline.json にあり、スクリプトによって書き換えられることはありません。
npm run refresh-snapshot を実行すると、tests/snapshots/tool-registry.json と tests/snapshots/tools-contract.json の両方が再生成されます。契約を意図的に変更する場合にのみ実行し、差分を確認してください。required、スキーマ、説明のハッシュが変わると、MCP クライアントに表示される内容も変わります。
Stdio スモークテスト
npm run smoke は dist/index.js を起動し(先に npm run build を実行してください)、stdio 経由で initialize、notifications/initialized、tools/list を送信します。その後、合意されたプロトコルバージョン、serverInfo、ツール数、ソート済みツール名の sha256 を JSON として出力します。ネットワーク接続は不要です:
HETZNER_API_TOKEN=dummy HETZNER_API_BASE=http://127.0.0.1:1 npm run smoke -- \
--min-tools <n> --expect-names-sha256 <sha256>
# or with an env file, passed to node as --env-file:
npm run smoke -- --env-file ./smoke.env
オプション:--protocol-version <v>、--min-tools <n>、--expect-names-sha256 <hex>、--baseline <file>(toolCount と namesSha256 を含む JSON ファイルから両方を設定)、--server <path>(既定値は dist/index.js)、--timeout-ms <ms>。既定値は scripts/smoke-stdio.mjs の先頭にあります。終了コード 0 はすべてのチェックに合格したことを示し、1 はチェック失敗、2 はサーバーの起動または応答に失敗したことを示します。CI は --baseline tests/gateway-baseline.json を指定して実行します。このファイルは tests/tools-contract.test.ts でも読み込まれます。
手動検証手順
リリースの準備完了を宣言する前に実行してください:
npm run inspectorを実行して、このサーバーで MCP Inspector を開きます。tools/list:ツール数がtests/snapshots/tools-contract.jsonのtoolCountと一致すること、および上記の表にあるすべてのラッパーが表示されることを確認します。hcloud_list_servers(引数なし):アカウント内の既知のサーバーを少なくとも 1 台使って確認します。hcloud_get_serverにname: "<one of your server names>"を指定します。id、type、ip が返されるはずです。{ name: "mcp-smoke", public_key: "<your test key>" }を指定してhcloud_create_ssh_keyを実行し、返された id を控えます。- その id を指定して
hcloud_delete_ssh_keyを実行し、正常に削除されたことを確認します。
スモークテストの一環として、本番サーバーに対する電源操作、再構築、スナップショット操作は実行しないでください。
セキュリティ
サポート対象バージョン、脆弱性を非公開で報告する方法、脅威モデル(トークンの権限、確認ガード、ツール名による許可)については、SECURITY.md を参照してください。
ライセンス
MIT ライセンスです。LICENSEをご覧ください。ただし、ベンダー提供の Hetzner Cloud API 仕様(specs/cloud.spec.json)は Hetzner に帰属します。NOTICEおよびspecs/SOURCE.mdをご覧ください。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。