mcpField
M
Modal MCP

Modal MCP

ローカル
github.com/george-bobbyクラウド・インフラ47 週間前に更新

Modal MCP について

Modal MCPは、ローカルのModal CLIを通じてアプリ、コンテナ、ボリューム、シークレットを管理するMCPサーバーです。Claude CodeなどのMCPクライアントからModalアプリをデプロイ、実行、調査したい開発者向けです。

主な機能

  1. 01リソースとアプリ履歴の確認
  2. 02アプリログの取得と検索
  3. 03アプリのデプロイとタスク実行
  4. 04アプリ状態の管理とロールバック
  5. 05コストとシークレットの確認

活用シーン

  1. 01アプリログのエラー調査
  2. 02共有可能なアプリエンドポイントのデプロイ
  3. 03単発またはデタッチ実行のジョブ

MCP 対応

MCPクライアントにModal管理用の12個のツールを提供します。各ツールはローカルの`modal` CLIを呼び出し、マシンに設定されたModalプロファイルと認証情報を使用します。

設定

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

mcp.json · 共通設定
{
"mcpServers": {
"modal": {
"command": "uvx",
"args": [
"mcp-modal"
]
}
}
}
起動コマンドuvx mcp-modal

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

パッケージ
pypimcp-modal0.5.0

ツール

12

掲載時のツール一覧 · 2 週間前に更新

パラメーター型必須説明
envanyいいえ
actionstringはい
versionanyいいえ
app_identifierstringはい

詳細

MCP Modal サーバー

mcp-modal MCP server

PyPI

Modal(アプリ、コンテナ、ボリューム、シークレット)を管理し、Claude Code やその他の MCP クライアントから Modal アプリを直接デプロイして実行するための MCP サーバーです。

すべてのツールはローカルの modal CLI を呼び出すため、お使いのマシンで設定されている Modal プロファイルと認証情報を使用して動作します。管理が必要な追加のトークンはありません。

インストール

このサーバーは PyPI に mcp-modal として公開されています。手動でインストールする必要はありません。推奨される実行方法は、必要に応じて取得して起動する uvx を使うことです。MCP クライアントで、以下のコマンドを指定してください(設定を参照)。

すべてのバージョンはタグ付けされ、リリースページにも公開されています。リリースノートと、PyPI で配布されているものと同じ .whl/.tar.gz が添付されています。バージョンを固定する場合、ネットワークに接続できない環境にインストールする場合、またはバージョン間の変更点を確認する場合に便利です。

Modal へのログイン

このサーバーはローカルの Modal 認証情報を使用します。まだ認証していない場合は、次を実行してください。

modal setup

ブラウザーが開いてログインし、トークンが ~/.modal.toml に保存されます。すでに別の場所でログインしている場合は、modal profile current で確認してください。

設定

claude mcp CLI を使って、Claude Code にサーバーを追加します。

claude mcp add mcp-modal -- uvx mcp-modal@latest

または、プロジェクトのルートにある .mcp.json ファイルに追加することもできます。チームで使う場合はこちらが適しています。リポジトリを開く全員に、同じ設定が適用されます。

{
  "mcpServers": {
    "mcp-modal": {
      "command": "uvx",
      "args": ["mcp-modal@latest"]
    }
  }
}
@latest を使う理由と、バージョンを固定する場合

uvx は初回実行時に構築した環境をキャッシュし、その後は PyPI を再確認しません。

「uvx は、初回の呼び出し時に、要求されたツールの利用可能な最新バージョンを使用します。 その後は、別のバージョンが要求された場合、キャッシュが削除された場合、またはキャッシュが更新された場合を除き、uvx はツールのキャッシュ済みバージョンを使用します。」 — uv のドキュメント

つまり、単に uvx mcp-modal と指定すると、インストール時点では最新ですが、その後は永久に固定されます。キャッシュはディスク上に保存されるため、クライアントを再起動したり、マシンを再起動したりしても変わりません。初回実行の時期によって利用者ごとに異なるバージョンになり、警告も表示されません。

  • mcp-modal@latest は起動のたびにバージョンを再解決するため、再起動すると新しいリリースが反映されます。起動時にネットワークへのラウンドトリップが1回発生します。ツールの仕様がまだ変化している間に使ってください。
  • [email protected](明示的なバージョン指定)は再現性があり、アップグレードも1行を意図的に変更して行えます。安定性を重視する場合や、より多くの利用者に展開する場合に使ってください。

すでに古いビルドがキャッシュされているマシンを移行する場合は、上記のどちらかに切り替えるだけで十分です。バージョンを指定するとキャッシュが無効になります。それ以外の場合は、uv cache clean mcp-modal を実行すると強制的に更新できます。

要件

  • Python 3.11 以降
  • uv(uvx を提供)
  • 有効な認証情報で設定された Modal CLI 1.5 以降(modal setup)。1.5 では modal billing summary/rates が追加され、請求レポートの列が snake_case に変更されました。コストツールはどちらの表記にも対応していますが、これら2つのビューには1.5が必要です。
  • Modal の デプロイおよび実行をサポートする場合:
    • デプロイ/実行するプロジェクトでは、依存関係管理に uv を使用する必要があります。
    • modal がそのプロジェクトの仮想環境にインストールされている必要があります。

セキュリティ

このサーバーは、~/.modal.toml にある認証情報を使って、ローカルの modal CLI をシェルから実行します。一部のツールは設計上、強力な権限を持ちます。サーバーを操作する MCP クライアントがプロンプトインジェクションを受けた場合(たとえば、取得したログに含まれる悪意のあるテキストによって)、以下の手段で権限が昇格される可能性があります。これらは自動承認せず、クライアントのツール承認プロンプトを必ず介すようにしてください。

  • deploy_modal_app / run_modal_app — ホスト上で任意のローカル Python を実行します(modal deploy はアプリファイルをインポートし、uv run は対象プロジェクトの依存関係を解決してインストールします)。
  • modal_volume_files(action="put") — 任意のローカルファイル(例:~/.ssh/id_rsa、~/.modal.toml)を読み取り、クラウドボリュームにアップロードできます(データを外部に持ち出すための手段になります)。
  • modal_volume_files(action="get" と force=True) — 任意のローカルパスを上書きできます(例:~/.zshrc やシェルプロファイル。永続化の手段になります)。
  • manage_modal_container(action="exec") — 設計上、コンテナ内で任意のコマンドを実行します。

すべてのツールは MCP ツールアノテーションを宣言しているため、クライアントは、読み取り専用の4つのツール(list_modal_resources、get_modal_logs、search_modal_logs、analyze_modal_costs。いずれも readOnlyHint: true)と、リモートの状態を変更するかコンピューティングを開始する8つのツールを区別できます。この8つのうち6つは destructiveHint: true です。例外は、何かを削除したり上書きしたりせずにコンピューティングを開始する run_modal_app と inspect_modal_secret です。読み取り操作は自動承認し、それ以外は承認プロンプトを介すようにしてください。

ローカルパスの許可リスト(任意)

ファイルシステムにアクセスする2つのボリュームツールの動作を制限するには、MCP_MODAL_ALLOWED_LOCAL_PATHS 環境変数に、ディレクトリを os.pathsep で区切ったリスト(macOS/Linux では :)を設定します。この変数が設定されている場合、解決後のパス(~ を展開し、.. やシンボリックリンクを正規化した後)がいずれかのルートディレクトリ内にないローカルパスに対する modal_volume_files の操作は拒否されます。対象となるのは、action="put" の local_path と、action="get" の保存先です。ダウンロード先が "-"(ファイルに書き込まず内容を返す)の場合は、ディスクに何も書き込まないため対象外です。

環境変数が未設定(デフォルト)の場合、制限はありません。そのため、既存の設定には影響しません。たとえば、MCP クライアントで次のように設定します。

{
  "mcpServers": {
    "mcp-modal": {
      "command": "uvx",
      "args": ["mcp-modal"],
      "env": { "MCP_MODAL_ALLOWED_LOCAL_PATHS": "/Users/me/modal-workspace:/tmp/modal" }
    }
  }
}

すべてのツールは、ユーザー指定の名前やパスを -- で示すオプション終端セパレーターの後に渡すため、- で始まる値も常にデータとして扱われ、modal CLI のフラグになることはありません。manage_modal_secret に渡されたシークレット値は、エコーされるコマンド、ログ、エラー出力からマスキングされます。

サポート対象のツール

ツールは12個です。関連する操作は、CLI のサブコマンドごとに分けるのではなく、action/resource 引数の背後にまとめられています。各ツールのスキーマはセッション全体を通じてモデルのコンテキストに読み込まれるため、ツールの数を抑えることで、実際の作業に使える余地が増え、モデルが選択する類似ツールも少なくなります。

環境ごとにスコープされたリソースを扱うツールでは、特定の Modal 環境を指定するための env 引数を任意で指定できます。省略した場合は、プロファイルのデフォルト(または MODAL_ENVIRONMENT)が使われます。例外は manage_modal_container とコンテナログです。コンテナ ID はグローバルに一意であり、CLI では環境を指定できません。

読み取り専用
  1. Modal リソースの一覧表示(list_modal_resources)— アカウント全体を一度に検索します。

    • パラメーター:resource(必須)、name、path(デフォルトは /)、env
    • resource の値:
      値返される内容name の意味
      appsデプロイ済み/実行中/最近停止したアプリ—
      app_history1 つのアプリのデプロイバージョン(ロールバック用)アプリ名/ID
      containers実行中のコンテナ(ta-...)絞り込みに使うアプリ ID
      volumes名前付きボリューム—
      volume_filesボリューム内のファイル(path を使用)ボリューム名
      secretsシークレット名(値は公開されません)—
      environmentsこのワークスペースで有効な env の値—
      profileアクティブなプロファイルとすべてのプロファイル—
    • volume_files の一覧取得で実際に何も見つからない場合は、メッセージとともに empty: true が設定されるため、空のディレクトリと誤ったパスを区別できます。
    • 200 件を超える一覧は上限が適用され、除外された件数は omitted_items に示されます。
  2. Modal ログの取得(get_modal_logs)— アプリ または コンテナのログを取得またはストリーミングします。

    • パラメーター:identifier(必須)、target(auto/app/container、デフォルトは auto — ta- で始まるものはコンテナです)、timeout_seconds(デフォルトは 30)、env、since、until、tail、source(stdout/stderr/system)、timestamps、follow
    • tail を指定せずに since を指定すると、範囲内のすべてのログが取得されます。負荷の高いアプリの出力を制限するには、until も指定してください(最大範囲は 35 日、tail の上限は 20,000 件です)。
    • follow=True の場合、アプリ/コンテナが停止するか timeout_seconds に達するまでログがストリーミングされ、truncated: true を含むスナップショットが返されます。
    • 対象は stdout/stderr/system ストリームのみです。一部の障害(例:「... exited with ...」として報告されるクラッシュ)はログ行ではなく Modal ダッシュボードのイベントであるため、ここには表示されません。
  3. Modal ログの検索(search_modal_logs)— ログを grep し、「どこで問題が起きたのか?」をデバッグできるよう、各ヒットと前後の行を取得します。ログは一度取得してローカルで検索するため、前後のコンテキスト、正規表現、大文字と小文字の区別、正確な一致件数を利用できます。

    • パラメーター:identifier(必須)、pattern(必須)、target(デフォルトは auto)、regex、case_sensitive、context_lines(デフォルトは 3)、max_matches(デフォルトは 50)、since、until、tail(デフォルトでは直近の 1000 件)、source、exclude(検索前にノイズ行を除外します。例:"queue put failed")、prefilter、timestamps(デフォルトは true)、timeout_seconds、env
    • 負荷の高いアプリでは検索範囲を絞ってください。 since のみを指定すると、その時点から現在までのすべてが取得されます。ログの多いアプリでは 1 時間あたり数百 KB に達するため、30 秒の取得制限で中断され(logs_truncated: true)、さらに出力予算によって切り詰められます。調べたい時間帯の前後に since と until を指定すれば解決でき、通常は数 KB で済みます。
    • prefilter=True を指定すると、pattern がサーバー側の部分文字列フィルター(modal app logs --search)として Modal に渡され、一致しない行は取得されません。取得しきれないほど大きなログに有効です。regex=False が必要で、前後の行には他の一致行のみが表示されます。そのため、時間帯を特定する用途に使い、その後 prefilter=False で再検索してください。
    • match_count と matches が返されます。matches はタイムスタンプと行番号を含むコンテキストブロックで、一致した行には > が付加されます。例:> 8: 2026-06-04T... ValueError: bad input。取得したログ全体が必ず検索されるため、返されるブロックが少なくても match_count は正確です。returned は返された一致件数です(隣接する一致は 1 つのブロックにまとめられ、returned_blocks で数えられます)。exclude を使用した場合は excluded_lines が報告されます。
    • CLI が拒否する検索範囲(逆転した期間、35 日超、tail が 20,000 件超)を指定した場合は、終了コードだけではなく、Modal 独自のメッセージとともに success: false が返されます。
    • get_modal_logs と同様、対象は stdout/stderr/system のみです。
デプロイと実行
  1. Modal アプリのデプロイ(deploy_modal_app)

    • Modal アプリをデプロイします(modal deploy)。デプロイされた Web エンドポイントは有効なまま維持されるため、出力に含まれるリンクは有効で共有できます(urls で返されます)。
    • パラメーター:absolute_path_to_app(必須)、env、name、tag、 strategy(rolling/recreate)、stream_logs
    • アプリのディレクトリでは、仮想環境に modal をインストールした状態で uv を使用する必要があります。
  2. Modal アプリの実行(run_modal_app)

    • 関数またはローカルのエントリーポイントを一度実行し、出力を収集します(modal run)。
    • パラメーター:absolute_path_to_app(必須)、function_name、env、detach、 timeout_seconds(デフォルトは 120)
    • タイムアウト時に実行が続いている場合は、truncated: true を含むスナップショットを返します。 タイムアウト後も Modal 上で長時間実行されるジョブを継続するには、detach=True を指定します。

modal serve ツールがないのはなぜですか? modal serve は、ブロッキングプロセスの実行中に限りエンドポイントを維持します。応答を返す MCP ツールで実行すると、エンドポイントが直ちに破棄され、無効な URL が返されます。永続的に利用でき、共有可能なエンドポイントには deploy_modal_app を使用してください。

状態の変更
  1. Modal アプリの管理(manage_modal_app)— action は stop(アプリを停止してコンテナを終了)または rollback(以前のバージョンを再デプロイ)です。

    • パラメーター:action(必須)、app_identifier(必須)、version(rollback の場合のみ。直前のバージョンがデフォルトです)、env
  2. Modal コンテナの管理(manage_modal_container)— action は exec(実行中のコンテナ内でコマンドを実行。modal container exec --no-pty)または stop(コンテナを終了)です。

    • パラメーター:action(必須)、container_id(必須)、command(exec の場合のみ。引数のリスト。例:["python", "-c", "print('hi')"])、timeout_seconds(デフォルトは 60)
  3. Modal ボリュームの管理(manage_modal_volume)— action は create、delete(ボリュームとその全データを削除します。取り消せません)、または rename です。

    • パラメーター:action(必須)、volume_name(必須)、new_name(rename の場合のみ)、env
  4. Modal ボリュームのファイル(modal_volume_files)— ボリューム内のファイルに対する書き込み操作です。 action は put(アップロード)、get(ダウンロード)、cp(ボリューム内でコピー)、または rm です。

    • パラメーター:action(必須)、volume_name(必須)、local_path、remote_path、 paths(cp の場合:コピー元の後にコピー先)、recursive、force、env
    • local_path="-" を指定して action="get" を実行すると、ファイルを書き込む代わりにファイルの内容を返します。
    • ボリュームの内容を一覧表示するには、list_modal_resources(resource="volume_files") を使用します。
  5. Modal シークレットの管理(manage_modal_secret)— action は create または delete です。

    • パラメーター:action(必須)、secret_name(必須)、key_values(辞書)、 from_dotenv(パス)、from_json(パス)、force、env。作成時は、 key_values、from_dotenv、from_json のいずれかが少なくとも 1 つ必要です。
    • 返されるすべてのフィールドで、エラー出力も含め、シークレットの値はマスキングされます。
    • シークレット名を一覧表示するには、list_modal_resources(resource="secrets") を使用します。
コスト
  1. Modal のコストを分析(analyze_modal_costs)— 読み取り専用です。modal billing を一度取得してローカルで集計するため、何百もの生データ行ではなく、順位付けされた合計と期間ごとの変化を確認できます。
    • パラメーター:view(デフォルトは by_app)、period、start、end、resolution(d/h)、timezone、app、environment、top_n(デフォルトは 10)、tag_names
    • view の値:
      値回答する質問
      by_app「最もコストがかかっているアプリは?」— 支出額順のアプリと、全体に占める割合
      timeline「月曜日のコストが高かったのはなぜ?」— 区間ごとのコストに加え、ピーク区間をその直前の区間と比較し、増加したアプリを順位付けする explanation
      by_environmentどの環境に費用がかかっているか
      by_resourceCPU、GPU クラス、メモリ、ストレージの内訳
      summary月次サイクルの請求コストと計測コスト、およびクレジットやプランの調整
      rates現在の単価
    • groups が top_n 件に制限されても、total_cost は常に期間内のすべての行を対象とします。表示された行を合計せず、total_cost をそのまま引用してください。
    • 請求情報はワークスペース全体が対象です(CLI では -e を指定しません)。そのため、このツールはすべての環境を対象にレポートします。environment を指定すると、その後で行が絞り込まれます。
    • Modal が報告するのは完了した区間のみのため、途中まで経過した日のコストは低く表示されます。
シークレット — 内容の確認
  1. Modal シークレットを確認(inspect_modal_secret)— シークレット内のキー名を一覧表示します。値は決して表示しません。
    • パラメーター:secret_name(必須)、env、image、timeout_seconds(デフォルトは 300)
    • Modal は設計上、CLI、SDK、gRPC レイヤーのいずれにも API を提供していません。シークレットに定義されているキーを確認する唯一の方法は、コンテナにマウントして環境変数を一覧表示することです。そのため、このツールは compgen -e(エクスポートされた変数の名前のみを出力する bash 組み込みコマンド)を使って modal shell --secret <name> を実行します。コンテナ内でも、値が出力されることはありません。その後、イメージと Modal ランタイムが設定する変数を除外します。既知の 23 個の名前に加え、6 つのプレフィックス(MODAL_、PYTHON、PIP_、NVIDIA_、CUDA_、LD_LIBRARY_PATH)に一致するものも除外します。これにより、すべてのコンテナにある MODAL_TOKEN_* 認証情報も対象になります。
    • この呼び出しではリモートコンピューティングが起動するため、数十秒かかり、数セントの費用が発生します(イメージのビルドが必要な場合はさらに時間がかかります)。このサーバーのそれ以外の読み取り処理はすべて無料です。存在するシークレットの確認には list_modal_resources(resource="secrets") を使い、シークレットの中身を知る必要がある場合にのみ、このツールを使用してください。
    • keys に加えて、フィルター適用前の all_env_names も返します。これにより、ランタイム変数のように見えるキーも、黙って除外されずに確認できます。
    • image を省略すると、Modal のデフォルトが使用されます(サーバーの Python に合わせてビルドされており、最も確実な選択肢です)。ワークスペースのイメージビルダーがその Python バージョンを拒否する場合は、python:3.12-slim などを指定してください。

プロンプト

このサーバーには、クライアントから直接呼び出せる 4 つの MCP プロンプト(複数ステップのワークフロー)も付属しています(Claude Code では /mcp__mcp-modal__<name> として表示されます)。プロンプトは必要に応じて取得されるため、ツールとは異なり、セッションごとのコンテキストを消費しません。

  • debug_modal_app(app_name、symptom は省略可能)— アプリが起動していることを確認し、コンテキストを含めてログ内のトレースバックを検索します。ログ取得結果が途中で切り詰められていた場合は、範囲を広げるのではなく狭め、ログ末尾の取得に切り替えます。続いて、同じ時間帯に関連アプリにも影響があったかを確認し、コンテナを調査した後、デプロイ履歴と比較してロールバックを検討する、順序立てたトリアージ手順です。
  • deploy_and_verify(absolute_path_to_app、env は省略可能)— 対象のワークスペースを確認してデプロイし、公開 URL を報告した後、アプリが正常だと思い込まずに実際に検証します。
  • review_modal_account(env は省略可能)— 読み取り専用のインベントリです。アイドル状態のアプリ、説明のつかない実行中コンテナ、孤立したボリュームやシークレットを特定し、それぞれをクリーンアップするための具体的な呼び出しを示しますが、実行はしません。
  • investigate_modal_costs(period、app は省略可能)— 支出の増加を日ごとの推移からピーク時間、リソースクラス、そして原因となったデプロイまたは実行中のコンテナまでたどります。

出力の上限

ログ、実行、exec の出力は返される前に上限が適用されるため、出力の多いアプリによってコンテキストウィンドウが埋め尽くされることはありません。デフォルトの上限はテキストフィールドあたり 40,000 文字(約 10k トークン)です。フィールドが切り詰められた場合、結果の output_capped: true が設定され、テキストには削除された量を示すマーカーが含まれます。上限に達したフィールドには先頭と末尾の両方が残るため、起動時のバナーと末尾のトレースバックをどちらも確認できます。

検索結果は、検索前に切り詰められることはありません。search_modal_logs は取得したログ全体を grep し、返されるコンテキストブロック数だけを制限するため、match_count は常に正確です。

ログ検索の結果が途中で切れている場合、timeout_seconds や出力上限を引き上げるのは通常適切な対処ではありません。取得量を減らすのが有効です。since と until で期間を絞り、source/exclude でフィルタリングするか、prefilter=True を設定して Modal 内で一致しない行を除外してください。

MCP_MODAL_MAX_OUTPUT_CHARS を設定すると、上限を引き上げたり引き下げたりできます。0 を設定すると、上限が無効になります。

{
  "mcpServers": {
    "mcp-modal": {
      "command": "uvx",
      "args": ["mcp-modal"],
      "env": { "MCP_MODAL_MAX_OUTPUT_CHARS": "80000" }
    }
  }
}

レスポンス形式

すべてのツールは標準化された形式でレスポンスを返します。操作の種類によって、多少の違いがあります。

# Lookups (list_modal_resources):
{
    "success": True,
    "apps": [...],          # or "containers", "volumes", "contents", "secrets", ...
    "omitted_items": 0      # present when the listing was capped at 200 entries
}

# Action operations (deploy, stop, rollback, create, delete, rename, cp, put, get, rm):
{
    "success": True,
    "message": "Operation successful message",
    "command": "executed command string",
    "stdout": "command output",  # if any
    "stderr": "error output"     # if any
}

# Log / run / exec operations (snapshot-based):
{
    "success": True,
    "logs": "...",          # or "output" for run/exec
    "truncated": False,     # True when cut off at timeout_seconds
    "output_capped": False, # True when text was trimmed to fit MCP_MODAL_MAX_OUTPUT_CHARS
    "command": "executed command string"
}

# Log search (search_modal_logs):
{
    "success": True,
    "match_count": 12,      # exact: the whole fetched log is searched
    "returned": 5,          # matches actually shown
    "returned_blocks": 2,   # adjacent matches merge into one context block
    "matches": ["> 8: ...", ...],
    "logs_truncated": False,  # True when the log fetch hit timeout_seconds
    "output_capped": False,
    "command": "executed command string"
}

# Error case (all operations):
{
    "success": False,
    "error": "Error message describing what went wrong",
    "command": "executed command string",
    "stdout": "command output",  # if available
    "stderr": "error output"     # if available
}

ライセンス

このプロジェクトは MIT ライセンスの下でライセンスされています。詳細については LICENSE ファイルを参照してください。

コメント

MCP は初めてですか?

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

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