mcpField
K
Kubernetes Troubleshoot

Kubernetes Troubleshoot

ローカル
github.comクラウド・インフラ09 週間前に更新

Kubernetes Troubleshoot について

Kubernetes Troubleshoot は、クラスターの問題を調べる Kubernetes 運用担当者や開発者向けの読み取り専用 MCP サーバーです。RBAC とネームスペース制限で読み取り範囲を絞り、書き込みツールは提供しません。

主な機能

  1. 01Pod の状態、ログ、イベントの照会
  2. 02ノードの状態とリソース情報の確認
  3. 03Deployment、StatefulSet、DaemonSet の確認
  4. 04サービス、エンドポイント、PVC、HPA の参照
  5. 05ネームスペース単位の読み取り制限

活用シーン

  1. 01未準備または再起動を繰り返す Pod の調査
  2. 02ノードが Ready でない理由と taint の確認
  3. 03HPA のメトリクスとスケーリング状態の確認

MCP 対応

stdio 経由で 16 個の Kubernetes 診断ツールを MCP クライアントに公開します。範囲を限定した ServiceAccount の認証情報でクラスターを読み取り、構造化データを返します。

設定

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

mcp.json · 共通設定
{
"mcpServers": {
"nanagyamfiprempeh30-k8s-troubleshoot": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"-e",
"KUBECONFIG",
"-e",
"ALLOWED_NAMESPACES",
"-e",
"LOG_LEVEL",
"-e",
"API_TIMEOUT_SECONDS",
"-e",
"MAX_LOG_LINES",
"docker.io/yawgyamfiprem32/k8s-troubleshoot-mcp:1.0.0"
],
"env": {
"KUBECONFIG": "<KUBECONFIG>",
"ALLOWED_NAMESPACES": "<ALLOWED_NAMESPACES>",
"LOG_LEVEL": "<LOG_LEVEL>",
"API_TIMEOUT_SECONDS": "<API_TIMEOUT_SECONDS>",
"MAX_LOG_LINES": "<MAX_LOG_LINES>"
}
}
}
}
起動コマンドdocker run -i --rm -e KUBECONFIG -e ALLOWED_NAMESPACES -e LOG_LEVEL -e API_TIMEOUT_SECONDS -e MAX_LOG_LINES docker.io/yawgyamfiprem32/k8s-troubleshoot-mcp:1.0.0
設定が必要な環境変数
KUBECONFIGPath to the kubeconfig inside the container. Must match the mount destination. There is no fallback to ~/.kube/config and no in-cluster config: a missing, unreadable or malformed file is a startup failure rather than a silent downgrade to an ambient credential.
ALLOWED_NAMESPACESComma-separated namespaces the server may read, e.g. staging,production. Wildcards (* and all) are rejected at startup, and kube-system and kube-public are stripped even if listed. This is defense-in-depth, not the security boundary — the boundary is the ServiceAccount's RBAC bindings.
LOG_LEVELDEBUG, INFO, WARNING or ERROR. All logging goes to stderr; stdout carries the JSON-RPC stream exclusively.
API_TIMEOUT_SECONDSKubernetes API request timeout. Must be a positive integer.
MAX_LOG_LINESMaximum log lines any single get_pod_logs call may return. Must be a positive integer; clamped to a hard ceiling of 1000 with a warning.

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

パッケージ
ocidocker.io/yawgyamfiprem32/k8s-troubleshoot-mcp:1.0.0

ツール

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

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

詳細

k8s-troubleshoot-mcp

AI アシスタントが Kubernetes クラスターを診断できる、読み取り専用の MCP(Model Context Protocol) サーバーです。kubectl コマンドを 6 回実行して出力を手作業で照合する代わりに、Pod がクラッシュループしている理由を尋ねられます。

読み取り専用であることは構造上の特性であり、単なる約束ではありません。 書き込みツールはなく、RBAC マニフェストには書き込み動詞が許可されていません。セキュリティモデルをご覧ください。

機能

このサーバーは、stdio 経由で 16 個の診断ツールを公開します。Claude Desktop、VS Code、Kiro に接続すると、次のような質問ができます。

  • 「staging の checkout Pod が Ready でないのはなぜですか?」
  • 「api コンテナのログの直近 50 行を表示してください」
  • 「Ready でないノードと、それぞれの taint を教えてください」
  • 「web HPA はスケーリングしていますか? 現在のメトリクスは何を示していますか?」
  • 「直近数分間に production で発生したイベントは何ですか?」

アシスタントがツールを呼び出し、サーバーはスコープを限定した ServiceAccount トークンを使って Kubernetes API に問い合わせます。エラーも含め、すべての応答は構造化された dict として返され、MCP レイヤーに例外として送出されることはありません。

アーキテクチャ

┌──────────────────┐    stdio (JSON-RPC)   ┌──────────────────────────┐
│   MCP Client     │◄─────────────────────►│   MCP Server             │
│  Claude Desktop  │                       │   (this project)         │
│  VS Code / Kiro  │                       │                          │
└──────────────────┘                       │  config.py   ─ validate  │
                                           │  server.py   ─ 16 tools  │
                                           │  tools/*.py  ─ read+shape│
                                           │  response.py ─ escape +  │
                                           │                structure │
                                           └───────────┬──────────────┘
                                                       │ HTTPS, explicit
                                                       │ KUBECONFIG only
                                           ┌───────────▼──────────────┐
                                           │  Kubernetes API server   │
                                           │  ── RBAC boundary ──     │
                                           │  ServiceAccount:         │
                                           │  get/list/watch only     │
                                           └──────────────────────────┘

設定は起動時に一度だけ検証されます。KUBECONFIG が未設定、ファイルが読み取れない、形式が不正、ALLOWED_NAMESPACES が未設定、またはワイルドカードを含むなど、問題があれば、プロセスは stderr に 1 行を書き込んで終了コード 1 で終了します。一部のみ有効な状態で起動することはありません。

利用可能なツール

? が付いた引数は省略可能です。

ツール説明パラメーター
get_pod_statusPod のフェーズ、条件、コンテナのステータス、QoS クラス、ノードpod_name、namespace
get_pod_logsPod コンテナの直近のログ行。内容は信頼できないものとして扱ってください。get_pod_logs の出力を読むをご覧くださいpod_name、namespace、container?、previous?、tail_lines?
get_pod_eventsPod の直近のイベント。新しい順で、total_available を含みますpod_name、namespace
list_pods名前空間内の Pod と、フェーズ、再起動回数、Ready 状態namespace、label_selector?
get_node_statusノードの条件、容量、割り当て可能量、taint、ロールnode_name
list_nodesクラスターのノードと、Ready 状態、ロール、経過時間、kubelet のバージョンなし
get_deployment_statusレプリカ数、条件、ロールアウト戦略deployment_name、namespace
list_deployments名前空間内の Deployment と、レプリカ数、利用可能数namespace
get_statefulset_statusレプリカ数、リビジョン、更新戦略statefulset_name、namespace
get_daemonset_statusスケジューリング数、更新戦略daemonset_name、namespace
get_serviceサービスのタイプ、ClusterIP、ポート、セレクター、Ready なエンドポイント数service_name、namespace
get_endpointsサービスに対応する Ready および NotReady のエンドポイントアドレスservice_name、namespace
get_pvc_statusPVC のフェーズ、容量、バインド状態、サイズ変更状態pvc_name、namespace
get_hpa_statusHPA のレプリカ数の範囲、現在のメトリクス、条件hpa_name、namespace
get_namespace_events名前空間内の直近のイベント。新しい順で、total_available を含みますnamespace、limit?
list_namespacesこのサーバーに読み取りが許可されている名前空間なし

名前空間を指定するすべてのツールは、API を呼び出す前に namespace 引数を検証します。そのため、許可されていない名前空間が指定された場合は、構造化されたエラーが返され、ネットワークリクエストは発生しません。

意図的に含めていない機能

get_secrets、get_configmap、exec_into_pod、port_forward、およびあらゆる create/update/patch/delete ツールはありません。新たな脅威モデルレビューを実施し、文書化しない限り、これらはすべてのバージョンから除外されます。バックログ項目ではありません。それぞれの理由はSECURITY.mdに記載されています。

セキュリティモデル

詳細はSECURITY.mdをご覧ください。概要は次のとおりです。

境界となるのは Kubernetes RBAC です

このサーバーがアプリケーションコード内で行うすべての処理は、多層防御の一部です。強制適用の境界となるのは、ServiceAccount の RBAC バインディングです。 バインディングで意図した範囲を超える権限を付与している場合、アプリケーション層の許可リストだけが最後の防壁となります。これを頼りにするべきではありません。

プロビジョニングはスコープごとに分け、クラスター全体に付与する権限を最小限にしています。

マニフェストスコープ付与する権限
clusterrole.yaml + clusterrolebinding.yamlクラスターnodes と namespaces に対する get/list/watch のみ
role.yaml名前空間診断用リソースに対する get/list/watch
rolebinding.yaml.template名前空間Role を一度に 1 つの名前空間にバインド

クラスター全体を対象とするペアを適用しても、読み取り可能になる名前空間はありません。名前空間が読み取り可能になるのは、その中に Role と RoleBinding の両方が存在する場合だけです。ALLOWED_NAMESPACES に記載されていても、バインドされていない名前空間は読み取りできません。RBAC が優先されます。

pods/log は独立したルールブロックで許可しており、pods のルールに含めていません。Kubernetes のサブリソースは親から権限を継承しないためです。

多層防御の層
層役割対象外となるもの
RBACバインドされた名前空間内の診断用リソースに対する読み取り権限のみを付与します— これが境界です
明示的な kubeconfig正確なパスから KUBECONFIG を読み取ります。~/.kube/config、クラスター内設定、フォールバックチェーンは使用しません権限チェックではありません。環境内の認証情報を暗黙的に取得することを防ぎます
名前空間の許可リストワイルドカードを拒否し、kube-system/kube-public を除外して、呼び出しのたびに検証しますあくまで参考情報です。ここにバグがあっても RBAC によって影響が抑えられます
出力のエスケープクラスター内で生成されたすべての自由形式テキストを serialize_log_content に通しますJSON 文字列から抜け出すことを防ぎます。モデルが読み取れる指示に従うことは防げません
構造化エラーすべての失敗で dict を返します。例外が MCP 層に到達することはありません—
プロンプトインジェクションは軽減できますが、排除はできません

Pod のログとイベントメッセージは、クラスター内のワークロードによって書き込まれます。コンテナは、読み取るモデルへの指示のように見えるテキストを含め、あらゆる内容を出力できます。エスケープによって、挿入されたテキストを JSON 文字列の中にとどめることはできますが、データとして読み取った指示にモデルが従うことは防げません。ツールの出力は、それを利用するあらゆるものにとって信頼できない入力として扱ってください。 この残存リスクは許容され、文書化されています。

前提条件

  1. Kubernetes クラスターと、ServiceAccount、Role、RoleBinding、ClusterRole、ClusterRoleBinding を作成できる十分な権限を持つ kubectl コンテキスト。これはプロビジョニング時に一度だけ必要です。サーバー自体が管理者の認証情報を使用することはありません。
  2. Kubernetes 1.24 以降 — scripts/generate-kubeconfig.sh は、従来の自動マウントされる Secret ではなく、TokenRequest API を使ってトークンを発行します。
  3. Python 3.11 以降
  4. uv — curl -LsSf https://astral.sh/uv/install.sh | sh(または、ホストに Python も uv も必要としない Docker を使用します)

セットアップ

git clone https://github.com/NanaGyamfiPrempeh30/k8s-troubleshoot-mcp.git
cd k8s-troubleshoot-mcp

# Install dependencies (uv creates .venv automatically)
uv sync

# Run the test suite
uv run pytest tests/ -q
RBAC をプロビジョニングして kubeconfig を生成する
scripts/generate-kubeconfig.sh /secure/path/k8s-mcp-kubeconfig.yaml staging production

最初の引数は kubeconfig の書き込み先です。残りの引数は、サーバーが読み取り可能な名前空間です。ALLOWED_NAMESPACES に設定する予定の名前空間と同じものを渡してください。RBAC が強制境界となるため、ここでバインドした名前空間が許可リストにない場合(またはその逆の場合)、実際の権限と設定された機能が一致しません。

このスクリプトは、クラスター全体に適用するマニフェストをまとめて適用した後、明示的な -n <namespace> を指定して role.yaml を適用し、名前空間ごとに RoleBinding を生成します。成功すると、kubeconfig のパスだけを標準出力に出力し、ほかには何も出力しません。診断メッセージはすべて標準エラーに出力されます。また、プロビジョニング後に kubectl auth can-i get secrets の結果が no であることを確認し、そうでない場合は中断します。

kubectl apply -f kubernetes/ は実行しないでください。 失敗にはならず、成功したように見えますが、現在の名前空間に role.yaml を作成し、rolebinding.yaml.template は完全にスキップします。これは、kubectl apply -f <dir> が .yaml/.yml/.json のみを読み込むためです。その結果、プロビジョニング済みに見えるものの、何も読み取れないサーバーが作られます。--dry-run=server を指定した v1.35 API サーバーで検証済みです。適用されたリソースは 6 つではなく 5 つでした。

生成された kubeconfig は umask 077 と chmod 600 を使って書き込まれます。リポジトリには含めないでください。出力先がリポジトリ内にあり、.gitignore の対象になっていない場合、スクリプトが警告します。

実行する
KUBECONFIG=/secure/path/k8s-mcp-kubeconfig.yaml \
ALLOWED_NAMESPACES=staging,production \
uv run k8s-troubleshoot-mcp

サーバーは標準入力/標準出力で JSON-RPC をやり取りするため、応答がないように見えますが、これは正常です。クライアントからの接続を待っています。

Claude Desktop に接続する

claude_desktop_config.json に追加します(Windows の場合は %APPDATA%\Claude\claude_desktop_config.json、macOS の場合は ~/Library/Application Support/Claude/claude_desktop_config.json)。

{
  "mcpServers": {
    "k8s-troubleshoot": {
      "command": "uv",
      "args": ["run", "k8s-troubleshoot-mcp"],
      "cwd": "/path/to/k8s-troubleshoot-mcp",
      "env": {
        "KUBECONFIG": "/secure/path/k8s-mcp-kubeconfig.yaml",
        "ALLOWED_NAMESPACES": "staging,production"
      }
    }
  }
}

Claude Desktop を完全に再起動し(システムトレイから終了して、再度開き)、Settings → Developer で k8s-troubleshoot が running と表示されることを確認してください。

Windows でサーバーが切断状態と表示される場合は、バッチファイルのラッパーを使用してください。Claude Desktop では、インタープリターを直接呼び出すと作業ディレクトリの問題が発生します。

@echo off
cd /d C:\Users\YourUsername\k8s-troubleshoot-mcp
uv run k8s-troubleshoot-mcp
{
  "mcpServers": {
    "k8s-troubleshoot": {
      "command": "cmd.exe",
      "args": ["/c", "C:\\Users\\YourUsername\\k8s-troubleshoot-mcp\\run_mcp.bat"],
      "env": {
        "KUBECONFIG": "C:\\secure\\path\\k8s-mcp-kubeconfig.yaml",
        "ALLOWED_NAMESPACES": "staging,production"
      }
    }
  }
}

Docker で実行する

docker build -t k8s-troubleshoot-mcp .

docker run -i --rm \
  -v /secure/path/k8s-mcp-kubeconfig.yaml:/kubeconfig:ro \
  -e KUBECONFIG=/kubeconfig \
  -e ALLOWED_NAMESPACES=staging,production \
  k8s-troubleshoot-mcp

-i は必須です。JSON-RPC は標準入力/標準出力でやり取りされるためです。:ro は単なる飾りではありません。このサーバーは一切書き込みを行わないため、書き込み可能なマウントを指定すると、サーバーが必要としない権限を与えることになります。

イメージは 非 root、UID 10001 で実行され、認証情報は含まれません。

注意すべき点は 2 つあります。

  • kubeconfig は UID 10001 が読み取り可能である必要があります。 モード 600 で作成され、ホストユーザーが所有するファイルは読み取れません。また、バインドマウントではホスト側の所有者情報が保持されます。グループまたはその他のユーザーに読み取り権限を付与するか、--user "$(id -u)" を指定して実行してください。
  • ホストのループバック上にあるクラスター(minikube、kind)を利用する場合、Linux では --network host が必要です。Docker Desktop ではそれだけでは不十分です。minikube を使用したローカルテストを参照してください。

Claude Desktop からコンテナーを使用するには、"command": "docker" を設定し、run -i --rm … の呼び出し全体を "args" に指定してください。

環境変数

変数必須デフォルト説明
KUBECONFIGはい—kubeconfig の正確なパスです。~/.kube/config へのフォールバックや、クラスター内設定はありません。ファイルが存在しない、読み取り不可、または形式が不正な場合、起動に失敗します
ALLOWED_NAMESPACESはい—サーバーが読み取り可能な名前空間をカンマ区切りで指定します。ワイルドカード(*、all)は拒否されます。kube-system と kube-public は、指定されていても警告を出して除外されます
LOG_LEVELいいえINFODEBUG、INFO、WARNING、ERROR を指定します。認識できない値の場合は INFO にフォールバックします
API_TIMEOUT_SECONDSいいえ30正の整数を指定する必要があります
MAX_LOG_LINESいいえ200正の整数を指定する必要があります。警告を出して上限の 1000 に切り詰められます

すべてのログは標準エラーに出力されます。標準出力は JSON-RPC ストリーム専用です。print() が 1 つでも余計にあるとプロトコルが壊れるため、src/ にはそのようなコードはありません。

get_pod_logs の出力を読む

content フィールドはログテキストではなく、エスケープされたログテキストです。MCP レスポンスに対して json.loads を 1 回実行するだけでは、表示可能な出力を取得できません。

serialize_log_content はレスポンスエンベロープを JSON エンコードする前にログをエスケープするため、そのエスケープは転送後も維持されます。レスポンスをデコードしても、転送レイヤーだけが元に戻ります。

resp = json.loads(raw_mcp_response)
content = resp["data"]["content"]

print(content)
# line one\nline two\tsaid \"hi\" \u003cb\u003e\n   <- one physical line

content.count("\n")   # 0  -- there are no real newlines in it

元のテキストを復元するには、フィールドをもう一度デコードします。

text = json.loads('"' + content + '"')

print(text)
# line one
# line two    said "hi" <b>

これは意図的な動作であり、バグではありません。エスケープは、構造的なプロンプトインジェクション対策(REQ-020、REQ-027)です。1 回のデコードで実際の制御文字と生の < が復元されると、コンテンツがモデルに届く前に対策が失われてしまいます。2 回目のデコードは、ターミナルやログファイルなど、出力が解釈されない場所に送る場合に限って行ってください。

MCP Inspector の生データ表示では、\\n(バックスラッシュが 2 つ)と表示されます。これは正しい表示です。転送レイヤーが、すでにエスケープされた \n のバックスラッシュをエスケープしているためです。

content から行数を算出しないでください。 改行で分割すると、ログの長さにかかわらず結果は 1 になります。行数を確認するには、行数を返すために存在する lines_returned を使用してください。

minikube を使ったローカルテスト

minikube の再起動後に kubeconfig が古くなっている

minikube は、セッションごとにポートが割り当てられるプロキシアドレスを介して API サーバーを公開します。そのアドレスは kubectl cluster-info で確認でき、minikube stop/minikube start の実行サイクル間や、WSL2 の再起動後に変わることがあります。

以前のセッション中に scripts/generate-kubeconfig.sh で生成された kubeconfig には、古い host:port が固定されています。サーバーは正常に起動しますが、その後、どこもリッスンしていないエンドポイントを示す connection_error が発生し、すべてのツール呼び出しが失敗します。

Kubernetes control plane is running at https://127.0.0.1:54489
                                                        ^^^^^ per-session

復旧するには:

  1. 現在のエンドポイントを確認します。

    kubectl cluster-info
    
  2. そのエンドポイントを使って新しい kubeconfig を生成します。

    scripts/generate-kubeconfig.sh /path/to/kubeconfig.yaml <namespace> [namespace...]
    
  3. MCP サーバーのプロセスを完全に再起動します。 サーバーは起動時に KUBECONFIG を 1 回だけ読み込み(REQ-002)、その後は再読み込みしません。そのため、実行中のサーバーが参照するファイルを上書きしても何も変わりません。また、~/.kube/config へのフォールバックもありません(REQ-003)。同じマシンで kubectl が正常に動作していても、古い kubeconfig による問題は解決しません。

同じエラーは、古いポート、失効したトークン、または実際に到達不能なクラスターのいずれが原因でも発生します。kubectl cluster-info で原因を見分けられます。サーバーが connection_error を報告している間に kubectl cluster-info が成功する場合は、kubeconfig が古くなっています。

Docker Desktop のコンテナーから minikube に接続する

--network host が参加するのは、WSL ディストリビューションではなくDocker VM のネットワーク名前空間です。そのため、公開された minikube のポートはそのループバック上になく、コンテナーは ConnectionRefused になります。host.docker.internal には接続できますが、kubeconfig の server をこのアドレスに書き換えると TLS 検証に失敗します。host.docker.internal は minikube API サーバーの証明書の SAN に含まれていないためです。

URL を host.docker.internal に設定し、さらにクラスターエントリーに tls-server-name を追加してください。これは、まさにこの用途のためにある kubeconfig のフィールドです。

clusters:
- name: minikube
  cluster:
    server: https://host.docker.internal:54489
    tls-server-name: localhost
    certificate-authority-data: ...

プロジェクト構成

k8s-troubleshoot-mcp/
├── .github/workflows/
│   ├── build-and-push.yml       # Docker build + push to Docker Hub
│   └── secret-scan.yml          # TruffleHog secret scanning
├── kubernetes/
│   ├── namespace.yaml
│   ├── serviceaccount.yaml      # automountServiceAccountToken: false
│   ├── clusterrole.yaml         # nodes + namespaces, read verbs only
│   ├── clusterrolebinding.yaml
│   ├── role.yaml                # pods/log in its own rule block
│   └── rolebinding.yaml.template
├── scripts/
│   ├── generate-kubeconfig.sh   # provisions RBAC, mints a scoped token
│   └── check-namespaces.py      # CI guard: GitHub vs Docker Hub handles
├── docs/
│   ├── PUBLISHING.md            # Docker Hub + MCP Registry release runbook
│   └── dockerhub-overview.md    # Docker Hub repository description
├── server.json                  # MCP Registry listing metadata
├── src/k8s_troubleshoot_mcp/
│   ├── __main__.py              # startup sequence, fail-closed
│   ├── config.py                # env validation (REQ-001..010, 069..071)
│   ├── k8s_client.py            # explicit-path client factory
│   ├── server.py                # FastMCP instance + 16 tool registrations
│   ├── response.py              # serialize_log_content + structured errors
│   ├── pagination.py            # total_available / continue-token detection
│   └── tools/                   # pods, nodes, workloads, services,
│                                #   storage, autoscaling, events, namespaces
├── tests/
│   ├── unit/
│   └── property/                # P1-P18, Hypothesis-driven
├── requirements.md              # EARS-format requirements
├── design.md                    # architecture + 18 correctness properties
├── SECURITY.md                  # threat model, RBAC boundary, exclusions
├── DEBUG_LOG.md                 # every error found, root cause, resolution
├── Dockerfile                   # multi-stage, non-root UID 10001
├── uv.lock                      # 67 pinned dependencies
└── README.md                    # this file

トラブルシューティング

KUBECONFIG environment variable is not set — 明示的なパスが指定されていない場合、サーバーは起動を拒否し、~/.kube/config にフォールバックしません。これは意図的な動作です(REQ-003)。まだ実行していない場合は、scripts/generate-kubeconfig.sh を実行してください。

is not a valid kubeconfig — ファイルは存在し、読み取り可能ですが、形式が正しくありません。メッセージにはパス、行、列が示されますが、ファイルの内容は表示されません。kubeconfig にはベアラートークンが含まれるためです。

kubectl は動作するのに、すべてのツールで connection_error が発生する — kubeconfig が古くなっています。minikube でのローカルテストを参照してください。

namespace_not_allowed — 名前空間が ALLOWED_NAMESPACES に含まれていないか、起動時に一覧から除外される kube-system/kube-public です。これらの名前空間は一覧に記載されていても除外されます。

名前空間が許可されているのに、http_status: 403 を伴う kubernetes_api_error が発生する — 許可リストと RBAC バインディングに不整合があります。ALLOWED_NAMESPACES を設定しても、何も許可されません。名前空間は、その中に Role と RoleBinding が作成されて初めて読み取り可能になります。名前空間の全一覧を指定して、generate-kubeconfig.sh を再実行してください。

エラーは次の 3 種類のコードのいずれかで返されます。namespace_not_allowed(API 呼び出しの前に拒否)、kubernetes_api_error(API サーバーからの http_status と reason を含む)、および connection_error です。

Docker で kubeconfig の読み取りが拒否される — コンテナは UID 10001 で実行され、バインドマウントではホストの所有権が保持されます。Docker での実行を参照してください。

ログの内容が \n を含む長い 1 行に見える — エスケープが機能している状態です。get_pod_logs の出力を読むを参照してください。

MCP Inspector に Logging ✗ と表示される — 想定どおりであり、不具合ではありません。FastMCP は set_logging_level ハンドラーを登録しないため、get_capabilities() からこの機能が省略されます。この MCP 機能はログレコードをクライアントに送信するものですが、このサーバーは stderr にログを出力しており、これは無関係です。Inspector では Resources と Prompts がサポート対象と表示されますが、これはその逆の理由によるものです。FastMCP は、どちらも定義されていないにもかかわらず、それらのハンドラーを無条件に登録します。

これがどのように構築されたか

DEBUG_LOG.md には、開発中に遭遇したすべてのエラーについて、それぞれの根本原因と解決方法が記録されています。テストスイート全体が成功した後、実際のクラスターに対して実行して初めて見つかったものもいくつか含まれています。

このサーバーにクラスターの認証情報を預けられるか評価する際は、ぜひお読みください。記録を通じて繰り返し現れるテーマがあります。テスト用モックはクラスターではなく、互いに同じ動作をしていました。 その結果、互いに異なる 5 件の不具合が見つかり、いずれも実際とは逆の動作を確認するテストが成功していました。これを受けて実施した検証手順の概要は、SECURITY.mdに記載されています。

開発

uv sync --extra dev
uv run pytest tests/ -q

プロパティテスト(tests/property/)は、共有レジストリである tests/property/strategies.py の NAMESPACED_TOOLS からツールを列挙します。新しいツールを追加する場合は、同じ変更で必ずレジストリにも追加してください。レジストリにないツールは、P4/P6/P7 の対象からひそかに外れても、テストは成功したままになります。

初回コミットの前に TruffleHog の pre-commit フックをインストールしてください(pre-commit はプロジェクトの依存関係ではなく、開発ツールとして別途インストールします)。

pip install pre-commit
pre-commit install

ロードマップ

  • 読み取り専用の診断ツール 16 個
  • 18 件の正当性プロパティ(P1~P18)、Hypothesis によるテスト
  • RBAC マニフェストとスコープを限定した kubeconfig の生成
  • 稼働中のクラスターでの検証
  • Docker パッケージ化(マルチステージ、非 root、認証情報をイメージに含めない)
  • TruffleHog によるシークレットスキャン(pre-commit と GitHub Actions)
  • Docker Hub と MCP Registry への掲載準備(docs/PUBLISHING.md)
  • get_endpoints を discovery.k8s.io/v1 EndpointSlice に移行
  • Smithery に公開
  • get_ingress_status および get_networkpolicy ツール
  • ネットワーク経由のデプロイに対応する HTTP トランスポート

クレジット

ライセンス

MIT

コメント

MCP は初めてですか?

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

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