OpenAPI仕様からMCPサーバーを自動生成する3つの方法
OpenAPI仕様をFastMCP・AWS製openapi-mcp-server・openapi-mcp-generatorで自動的にMCPサーバー化する手順と、3ツールの使い分けを扱います。
既存のREST APIをMCPサーバー化するとき、エンドポイントを1つずつ手作業でツール定義に書き起こす必要はありません。OpenAPI仕様さえあれば、FastMCP・AWS製のopenapi-mcp-server・openapi-mcp-generatorのいずれかが、エンドポイントをMCPツールへ自動変換します。3つは言語・配布形態・絞り込みの手段が違い、選び方で運用の手間が変わります。
MCPツールを手作業で1つずつ定義する自作の基本はMCPサーバー自作ガイド、生成したサーバーの動作確認はMCP Inspectorの使い方が扱っています。
どのツールから試すか
OpenAPI仕様からのMCPサーバー自動生成とは、既存のOpenAPI 3.x定義(JSON/YAML)を読み込み、各エンドポイントをMCPのツールやリソースへ機械的に変換する手法です。3ツールとも既存APIをすぐAIエージェントから叩ける状態にする点は同じで、迷ったときは今の手元の状況から選べます。
状況で選ぶ3ツール
Pythonに組み込んで細かく制御したい
FastMCPが向きます。ライブラリなので、ルーティング・名前・生成後の部品を、Pythonのコードで書き換えられます。
複数のAPIを1つのサーバーにまとめたい
AWS製の
openapi-mcp-serverが向きます。仕様を複数合成でき、仕様ごとに別の認証を持たせられます。トランスポートはstdioです。生成物のコードを手元で直して配布したい
openapi-mcp-generatorが向きます。TypeScriptのプロジェクト一式が出力され、Web・StreamableHTTP・Cloudflare Workersの形でも動かせます。
FastMCPでPythonのMCPサーバーを生成する
FastMCPはFastMCP.from_openapi()にOpenAPI仕様とHTTPクライアントを渡すだけでMCPサーバーを構築するPythonライブラリです。
import httpx2
from fastmcp import FastMCP
# APIへのHTTPクライアントを作成
client = httpx2.AsyncClient(base_url="https://api.example.com")
# OpenAPI仕様を取得
openapi_spec = httpx2.get("https://api.example.com/openapi.json").json()
# MCPサーバーを作成
mcp = FastMCP.from_openapi(
openapi_spec=openapi_spec,
client=client,
name="My API Server",
)
if __name__ == "__main__":
mcp.run()既定では、OpenAPI仕様に含まれるすべてのエンドポイントがMCPのツールに変換されます。ほとんどのMCPクライアントがツールにしか対応していないため、互換性を優先した既定値です。認証が必要なAPIでは、httpx2.AsyncClientにheaders={"Authorization": "Bearer ..."}を渡します。
FastMCP 4ではHTTPクライアントがhttpxからhttpx2に替わりました。httpx.AsyncClientも当面は受け付けられますが、非推奨の警告が出ます。
変換の振る舞いはRouteMapという順序付きのルールリストで決まります。OpenAPIのルートをTOOL・RESOURCE・RESOURCE_TEMPLATE・EXCLUDEのどれにするかを、メソッド・パス・タグの組み合わせで指定します。ルールの使い方は、公開範囲を絞る節で扱います。
AWS製のopenapi-mcp-serverを使う
AWS Labsが公開するopenapi-mcp-serverは、OpenAPI仕様からMCPのツールとリソースを動的に生成するPython製サーバーです。pipで直接インストールして使います。
pip install "awslabs.openapi-mcp-server"API名・ベースURL・仕様のURLは、環境変数かコマンドライン引数で渡して起動します。README掲載の起動例は次のとおりです。
awslabs.openapi-mcp-server --api-name petstore \
--api-url https://petstore3.swagger.io/api/v3 \
--spec-url https://petstore3.swagger.io/api/v3/openapi.json特徴は次のとおりです。
- GETもツールにする — クエリパラメータ付きのGETはリソースでなくツールに割り当てられ、検索・絞り込み系のエンドポイントをLLMが扱いやすくなる
- タグで公開範囲を絞る —
--include-tags pet,storeや--exclude-tags admin,internal、環境変数のINCLUDE_TAGS/EXCLUDE_TAGSで指定する - 複数仕様の合成 —
--additional-specsに仕様ごとのJSONを渡すと、1つのサーバーにまとまる - 認証方式 — Basic・Bearer Token・APIキー・Cognitoに対応する
- 出力検証の切り替え — レスポンスがスキーマと食い違うAPIでは
--no-validate-output(VALIDATE_OUTPUT=false)で検証を止められる
YAML形式の仕様を読み込むときや、Prometheusでメトリクスを集めるときは、拡張パッケージを追加でインストールします。
pip install "awslabs.openapi-mcp-server[yaml]"
pip install "awslabs.openapi-mcp-server[prometheus]"openapi-mcp-generatorでNode.jsプロジェクトを生成する
openapi-mcp-generatorは、OpenAPI仕様から独立したNode.jsプロジェクト一式を出力するCLIツールです。生成後のサーバーは既存APIへのプロキシとして動き、リクエストの構造をZodスキーマで実行時に検証します。動作にはNode.js 20以上が必要です。
npm install -g openapi-mcp-generator
openapi-mcp-generator --input path/to/openapi.json --output path/to/output/dir主なCLIオプションは次のとおりです。
| オプション | 説明 | 既定値 |
|---|---|---|
--transport / -t | 説明stdio / web / streamable-http / cloudflare-worker | 既定値stdio |
--base-url / -b | 説明APIのベースURL(OpenAPIのserversが無い・曖昧な場合は必須) | 既定値自動検出 |
--max-tool-name-length | 説明ツール名の最大文字数(Claude Desktopの上限は64) | 既定値64 |
--default-include | 説明x-mcpによる絞り込みで、指定の無い操作を含めるか | 既定値true |
--custom-auth | 説明組み込み認証の前に呼ばれるsrc/auth.tsを編集可能な形で生成 | 既定値false |
--allow-external-refs | 説明$refでの外部URL参照解決を許可(解析時のSSRF対策で既定は無効) | 既定値false |
--insecure / -k | 説明TLS証明書の検証を省略(自己署名証明書の開発環境向け) | 既定値false |
トランスポートごとの違いは次のとおりです。stdioはローカルのMCPクライアント向けで、webはServer-Sent Events(SSE)のWebサーバー、streamable-httpはStreamableHTTPです。webとstreamable-httpにはブラウザで動くテストクライアントが付き、生成直後に動作確認できます。cloudflare-workerはCloudflare Workersにデプロイできるプロジェクトを出力し、MCPエンドポイントは/mcpになります。こちらのテストクライアントは付かないので、READMEはMCP Inspectorでの接続を案内しています。
実際に生成してみる
READMEの説明だけでなく、手元で最小のOpenAPI仕様を生成して挙動を確かめました。確認した環境はopenapi-mcp-generator 4.1.0とNode.js v20.18.0で、一時ディレクトリの中だけで実行しています。
生成から出力までの流れ
- 1
確認用の仕様を用意する
3操作だけの
petstore.jsonです。GET /pets(listPets)とPOST /pets(createPet)、それに/admin/purge(purgeAll)を書きました。/admin/purgeのパスにはx-mcp: falseを書きました。 - 2
CLIで生成する
openapi-mcp-generator -i petstore.json -o outを実行すると、out/にプロジェクト一式が作られました。 - 3
出力を確かめる
src/index.tsのツール一覧に入っていたのはlistPetsとcreatePetの2つで、purgeAllはありませんでした。
生成されたファイルは8つで、package.json・tsconfig.json・.env.exampleのほか、ESLint・Prettier・Jestの設定が含まれます。サーバーの本体はsrc/index.tsの1ファイル(632行)にまとまっていました。生成された.env.exampleには、API_BASE_URLでOpenAPIのserversの値を実行時に上書きできると書かれています。ステージングと本番を切り替えるときに、再生成が要りません。
同じ仕様に--default-include falseを付けて生成すると、3操作のどれもsrc/index.tsに入りませんでした。x-mcpは「既定で含めて、外したい操作にfalseを書く」使い方と、「既定で外して、公開したい操作にtrueを書く」使い方の両方ができます。優先順位は操作、パス、ルートの順で、タグではなくOpenAPIの拡張フィールドで絞る点が、他の2ツールと違います。
公開範囲を絞る3つの流儀
自動生成の最大の落とし穴は、全エンドポイントがそのままAIエージェントに見えることです。3ツールは絞り込みの手段が異なります。
絞り込みの置き場所
FastMCP
route_mapsにパターンやタグを書きます。ルールは上から順に評価され、最初に全条件が合ったものが採用されます。
AWS製 / generator
AWS製は--include-tags / --exclude-tagsで、openapi-mcp-generatorは仕様に書いたx-mcpで絞ります。コードを書かずに済みます。
FastMCPでは、管理用のパスとinternalタグ付きのルートを除外する書き方になります。
from fastmcp import FastMCP
from fastmcp.server.providers.openapi import RouteMap, MCPType
mcp = FastMCP.from_openapi(
openapi_spec=spec,
client=client,
route_maps=[
# /admin/ 配下は除外
RouteMap(pattern=r"^/admin/.*", mcp_type=MCPType.EXCLUDE),
# internal タグが付いたルートも除外
RouteMap(tags={"internal"}, mcp_type=MCPType.EXCLUDE),
],
)カスタムルールは既定ルールより先に評価されるため、除外したいルートだけを列挙すれば残りは既定どおりツールになります。逆に、リストの末尾にRouteMap(mcp_type=MCPType.EXCLUDE)を置くと、既定のルールまで届かず、書いたルートだけが残る許可リスト方式になります。公開したい操作が少ないAPIでは、こちらのほうが事故が起きにくい構成です。
FastMCP 2.8.0より前は、GETがリソースかリソーステンプレートに割り当てられていました。互換性のためツールに変更された経緯があり、旧来の挙動に戻したいときはmethods=["GET"]のルールをRESOURCE / RESOURCE_TEMPLATEで書きます。さらに細かい判断が要るときは、各ルートと割り当て結果を受け取るroute_map_fnを使えます。この関数はEXCLUDEにしたルートにも呼ばれるので、除外を上書きできてしまう点に注意が要ります。
ツール名を制御する
自動生成したツール名がAPIのoperationIdをそのまま反映するだけだと、AIエージェントにとって選びにくい名前になることがあります。FastMCPはoperationIdを最初の二重アンダースコア(__)までで自動的に名付け、さらにスラッグ化(記号除去)・56文字までの切り詰め・重複時の連番付与を行います。個別に名前を決めたい場合は、mcp_names辞書でoperationIdごとの名前を指定します。
mcp = FastMCP.from_openapi(
openapi_spec=spec,
client=client,
mcp_names={
"list_users__with_pagination": "user_list",
"create_user__admin_required": "create_user",
},
)AWS製のopenapi-mcp-serverは、ツールの説明文を充実させる方向を取っています。OpenAPI仕様のレスポンスコードやパラメータの例を、ツールの説明に自動で追記します。READMEは別機能として、API操作ごとのプロンプトを動的に生成する仕組みも挙げ、プロンプトのトークンを70〜75%減らしていると説明しています。
openapi-mcp-generatorにはCLIとは別に、ツール定義だけを取り出すプログラムのAPIもあります。既存のNode.jsサーバーにツール定義だけを組み込みたいときは、こちらを使います。
import { getToolsFromOpenApi } from 'openapi-mcp-generator';
const tools = await getToolsFromOpenApi('./petstore.json', {
baseUrl: 'https://api.example.com',
excludeOperationIds: ['deletePet'],
filterFn: (tool) => tool.method.toLowerCase() === 'get',
});よくあるつまずき
自動変換したツールの質がそのまま使えるとは限らない
FastMCPのドキュメントは、自動変換したMCPサーバーより、設計して選別したMCPサーバーのほうがLLMの性能は大きく上がると書いています。特にエンドポイントやパラメータが多い複雑なAPIで差が出るそうです。同じ注記は、自動変換をプロトタイピングの起点にとどめ、実際のAPIの鏡写しにしないよう勧めています。本番では前節の絞り込みを前提にします。
Claude Desktopでツール名が長すぎて弾かれる
openapi-mcp-generatorは、Claude Desktopのツール名の上限が64文字であることを理由に、既定で64文字を超える名前をハッシュ付きで切り詰めます。他のツールで生成したサーバーをClaude Desktopに接続するときも、operationIdが長いAPIでは同じ問題が起きえます。
外部$refを含む仕様が読み込めない
外部URLへの$refは、2ツールとも既定で解決しません。openapi-mcp-generatorは--allow-external-refsでhttp(s)の参照を許可でき、これは解析時のSSRF対策を外す操作です。AWS製のREADMEは、ドキュメント内の参照(#/components/...)だけを解決し、schemas.yaml#/Petのような複数ファイルの参照は解析前に拒否すると書いています。許可の引数は挙げられていないため、複数ファイルの仕様は1つに束ねてから読み込ませます。
ローカルのAPIにつないだら仕様の取得が拒否される
AWS製は、additional_specsに書いたURLを取得する前に検証します。READMEによると、http://のURLとプライベートネットワーク・ループバックのIPは既定で拒否されます。社内や開発中のAPIでは、--allow-insecure-httpと--allow-private-networksで許可します。環境変数ならALLOW_INSECURE_HTTPとALLOW_PRIVATE_NETWORKSです。追加した仕様は主APIの認証情報を引き継がないため、仕様ごとにauth_typeなどを書かないと認証なしになります。
認証をどこで設定するか迷う
FastMCPはhttpx2クライアントにヘッダーとして設定します。AWS製は--auth-typeと--auth-tokenなどの引数かAUTH_TYPEなどの環境変数です。openapi-mcp-generatorはAPI_KEY_<スキーム名>やBEARER_TOKEN_<スキーム名>の環境変数を使います。独自の処理が要るときは、--custom-authでsrc/auth.tsを生成します。いずれのツールも、認証情報はコードに直書きせず環境変数側に置きます。
まとめ
自動生成は、全エンドポイントを一気にツール化する近道です。どれを選ぶにしても、AIエージェントに見せる範囲は自分で決め直す必要があります。Pythonのコードで制御するならFastMCP、起動引数で絞るならAWS製、仕様のx-mcpで絞るならopenapi-mcp-generatorと、絞り込みの置き場所で選ぶと後の運用が楽になります。