MCP(Model Context Protocol)が登場し、MCPサーバをまとめて配布できる MCP Bundle(MCPB)/ Desctop Extention(DXT) という仕組みがAnthropicから提唱されました。これを使うと、
- Node.js で MCP サーバを書いて DXT にパック
- ZIP で配れば、クライアントがそのまま実行
という軽快さを実現でき、かなり魅力的です。
しかし Python で MCPB/DXT を利用しようとすると、途端に「扱いづらさ」が出てきます。
- ランタイムと ABI の整合性問題
- wheel(ネイティブ拡張)の ABI タグ
-
server/lib/server/venvの前提と限界 - ホスト側(MCPクライアント)が何を保証すべきか不明瞭
など、Python 特有の難しさを DXT が十分吸収できていないためです。
本記事では、「なぜ Python サーバだけがこんなに扱いづらいのか?」を技術的に整理します。
1. MCPB/DXT が Python に提供している仕組み(現状)
MCPB/DXT では Python で実装されたMCPサーバ向けに以下のようなガイダンスを出しています:
- 依存は以下のどちらかでバンドル
-
server/lib/(依存モジュールをまとめて置く) -
server/venv/(仮想環境そのものを入れる)
-
また、manifest.jsonの内容として以下を表現できます:
-
compatibility.runtimes.pythonで対応する Python のバージョン範囲を指定できる(例:">=3.10,<3.13")
一見すると十分そうですが、 重要な抜け落ち があります。
2. Python製 MCPサーバの配布の難しさ:ABI タグ問題
たとえば、今配りたいMCPサーバが、Python のネイティブ拡張に依存するライブラリ(numpy、pillow、lxml など)を使っているとします。これらの実体は、wheel ファイルとして配布されていますが、wheel には次のようなタグが付きます。
cp310-win_amd64
cp312-manylinux_x86_64
cp311-macosx_11_0_arm64
つまり、
- Python バージョン(例: cp312)
- OS(win / manylinux / macosx)
- CPU(x86_64 / arm64)
- Python ABI の互換性(ABI breakpoints)
が組み合わさった環境 “だけ” で実行できる、ということです。
ネイティブ依存を含むパッケージはこの ABI に強く縛られるため、
Python LC の実行環境が少しでもズレれば wheel は読み込めない
という性質があります。
3. spec で「できていること」と「できていないこと」
✔ できていること
→ Python バージョン互換性の表明
compatibility.runtimes.python: ">=3.10,<3.13"
これは MCPB からホストへ:
「この Python サーバは Python 3.10〜3.12 で動いて欲しい」
と伝えるための仕組みとして機能しています。
✘ できていないこと
→ ABI タグ(実行可能 wheel のプロファイル)を表現できない
compatibility.runtimes.python はあくまで「バージョン範囲」です。
しかし、本当に必要なのは:
- wheel の ABI タグ(例:
cp312-win_amd64) - ホストランタイムの ABI タグ
- それらが一致しているかどうか
というレベルの整合性です。
現状はここが “推測” に委ねられています。
- MCPB作者
→server/libにどの ABI の wheel を入れるべきか曖昧 - ホスト側
→ 自分の Python ランタイムが 本当にその wheel と一致するのか判断できない
という構造的なギャップが残っています。
4. server/lib と server/venv の限界
■ server/lib の前提は「ABI の一致が当然」
server/lib に依存を詰め込む方式は一見シンプルで「できそう」ですが、
「同梱した wheel の ABI は、ホスト側のランタイムと一致しているはず」
という暗黙の前提があるだけで、specとして保証されているわけではありません。
■ server/venv はもっと危険
仮想環境丸ごと同梱する案もありますが、実際には:
- venv 内にはベース Python のパスが埋め込まれることがある
- OS や Python バージョンと密結合
- 再配置すると壊れるケースも多い
つまり、「動くこともあるけど本質的には壊れやすい」 のが現実です。
5. Binaryタイプは Python よりはマシ、だが万能ではない
Pythonタイプは、Binary タイプと比較すると、
- OS差分は
platform_overridesで宣言できる - ホストは「バイナリをそのまま実行するだけ」
という意味で、Pythonより扱いやすいのは確かです。
しかし:
- OS × CPU ごとにビルドが必要
- GPU/ネイティブ依存を含めばさらにマトリクスが増える
- macOS コード署名・Windows SmartScreen など別の難しさもある
つまり、Binary は Python より“マシ”なだけで、本質的な問題は別レイヤーに残る のが重要な点です。結局のところ、一応使えそうなのはNode.js上で動くMCPサーバだけになります。
6. どこに設計上のギャップがあるのか?
まとめると、以下の3点です。
ギャップ1:
Python の「実行環境プロファイル」が粒度不足
現在は「バージョン範囲」しか表現できない。
本当に必要なのは ABI タグレベルのプロファイル。
ギャップ2:
ホストと MCPB 作者の責務の境界が曖昧
- Binary → 責務を作者側に閉じ込められる
- Python → ランタイム整合性が両者に中途半端に分散する
ギャップ3:
「薄い Python DXT」 と 「太い Python DXT」 が同じ枠に押し込まれている
- 純 Python の軽量スクリプト(依存少なめ)
- ネイティブ依存が多い重厚な Python サーバ
この両者に必要な仕組みは本来違うのに、spec 上は分けられていません。
7. 結論:現状の Python DXT/MCPB は「構造的に扱いづらい」
以上から、現時点の結論は次の通りです。
- MCPB/DXT の Python サポートは
ランタイム・ABI 整合性まで考えると“最低限”の仕様に留まっている -
server/lib/server/venvは
軽量なケースでは動くが、ネイティブ依存が増えるほど脆い - Binary タイプは Python より扱いやすいが、
OS・CPU差分という本質的なネイティブ問題は依然残る
そのため現在の実務的な落としどころは、
- 本格的な Python MCP サーバは Binary 形式で配布する
- 純 Python スクリプトに限定するなら type: "python" を使う
という方針が無難です。
おわりに
MCPB/DXT 自体は面白いと思いますが、Python の扱いに関しては、現状 spec と実用性の間にまだギャップがあります。
- ABI タグを含む「実行環境プロファイル」の導入
- ランタイム責務の明確化
- 軽量/重量 Python DXT の区別
などが今後検討されると、Python でも少しはマシに DXT/MCPB を扱えるようになるはずです。
少なくとも、現時点でPython を本番環境向けに DXT/MCPB 化したい方は、Binary ベース(PyInstaller など)への移行を検討する価値があります。Node.jsベースで作り変えるほうが、さらにマシです。