Claude Media
OpenAPI仕様からMCPサーバーを自動生成する3つの方法

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. 1

    確認用の仕様を用意する

    3操作だけのpetstore.jsonです。GET /pets(listPets)とPOST /pets(createPet)、それに/admin/purge(purgeAll)を書きました。/admin/purgeのパスにはx-mcp: falseを書きました。

  2. 2

    CLIで生成する

    openapi-mcp-generator -i petstore.json -o outを実行すると、out/にプロジェクト一式が作られました。

  3. 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ツールは絞り込みの手段が異なります。

くらべる

絞り込みの置き場所

Pythonのコード

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と、絞り込みの置き場所で選ぶと後の運用が楽になります。

この記事を共有:XはてブLinkedIn
MCP をもっと見る →