Sezzlee OpenAPI について
Sezzlee OpenAPI は、OpenAPI ドキュメントをリモート API 向けの検索可能な MCP ツールカタログに変換します。独立したサービスとしてネットワーク経由でバックエンドを呼び出し、stdio または streamable HTTP に対応します。
主な機能
- 01SwaggerとOpenAPIドキュメントの取り込み
- 02APIツールの検索と読み込み
- 03リモートAPI操作の呼び出し
- 04保存された大容量結果の読み取り
- 05操作の選択とツール名の設定
- 06ドキュメントからのカタログ再読み込み
活用シーン
- 01選択したAPIエンドポイントをMCPツールとして公開する
- 02エージェントが関連するAPI操作を見つける
- 03MCPクライアントからリモートバックエンドを呼び出す
- 04ドキュメント変更後にツールカタログを更新する
MCP 対応
OpenAPIで記述されたバックエンド操作を、検索・読み込み・呼び出し・結果読み取り用のMCPメタツールとして公開します。stdio または streamable HTTP で動作し、fetch でリモートバックエンドを呼び出します。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
ツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
@sezzlee/openapi-mcp
OpenAPI(Swagger 2.0 / OpenAPI 3.0–3.2)ドキュメントを、リモートバックエンド上で fetch を使って呼び出す、sezzlee の検索優先型ツールカタログ(search_tools、load_tool、invoke_tool、read_result)として公開する MCP サーバーです。
ステータス:
1.0.0、安定版です。npm install -g @sezzlee/openapi-mcpでインストールするか、npx -y @sezzlee/openapi-mcpで実行してください。バイナリ名はsezzlee-openapiです。
組み込み SDK との違い
NestJS SDK はバックエンドプロセスの内部で動作します。独自のコントローラーやルートからエンドポイントを検出し、各 MCP 呼び出しを既存のパイプライン経由で再生するため、認証と認可は現在とまったく同じように実行されます。
openapi-mcp は独立したサービスです。バックエンドのプロセスやパイプラインにはアクセスできません。バックエンドのOpenAPI ドキュメントを読み取って、利用可能な操作を把握し(取り込みルール)、呼び出しのたびにネットワーク経由でバックエンドを呼び出します。その際、独自に解決した認証情報を付与します(認証情報の選択と書き込み方法)。これは、組み込み SDK が統合されていないバックエンドで利用できる唯一の方法です。
組み込み SDK がコードで宣言するすべての内容は、ドキュメントでは操作ごとの x-sezzlee 拡張で宣言します。ドキュメントを編集できないホストでは、この設定の operations の下で宣言します。対象の選択、ツール名、プレフィックス、動作のヒント、引数の調整、バリアント、ファミリー、検索語、リビジョンが含まれます(x-sezzlee 拡張)。多くの機能を単一のエンドポイント(POST /Rest/InvokeDynamicMethod/{methodId})経由でルーティングするバックエンドでは、その操作の x-sezzlee.family に機能を列挙します。各メンバーは、それぞれ独自の名前、説明、ボディを持つ独立したツールとなり、ディスパッチキーは非表示のままです。
クイックスタート
サーバーは、SEZZLEE_OPENAPI_CONFIG で指定したファイルから設定を読み込みます。まずパッケージをビルドしてください(このリポジトリでは、@sezzlee/core のコンシューマーを古い dist に対して実行することはありません)。
pnpm turbo run build --filter=@sezzlee/openapi-mcp
最小限の設定例です。ローカルのドキュメントを使い、少なくとも1つの操作を公開するためにオプトイン方式で選択し、デフォルトの stdio トランスポートを使用します。
{
"source": "./openapi.json",
"selection": { "default": "include" }
}
SEZZLEE_OPENAPI_CONFIG=/absolute/path/to/config.json node packages/servers/openapi-mcp/dist/cli.js
source にはパス(設定ファイルのあるディレクトリを基準に解決されます)または http(s):// URL を指定します。起動時にサーバーはドキュメントを取り込み、カタログを構築して、診断コードごとに1行の要約を標準エラー出力に表示します。その後、transport.kind に応じて stdio でサービスを提供するか、streamable HTTP をリッスンします。
設定の検証に失敗した場合、または設定で指定された環境変数が設定されていない場合、標準エラー出力にメッセージを表示してプロセスを終了コード 2 で終了します。致命的な診断を伴うドキュメントの取り込み、または致命的な診断(name_collision、invalid_name、ambiguous_selection、…)を伴うカタログの場合は、終了コード 1 で終了します。
設定
以下のすべてのキーは SEZZLEE_OPENAPI_CONFIG JSON ファイルから読み込まれ、未知のキーを拒否する zod スキーマ(src/platform/config.ts)で検証されます。
| キー | 型 | デフォルト値 | 備考 |
|---|---|---|---|
transport.kind | "stdio" | "http" | "stdio" | — |
transport.host | string (http only) | "127.0.0.1" | tokenExchange が設定されていない限り、ループバック(127.0.0.1、::1、localhost)に維持する必要があります。以下を参照してください |
transport.port | int, 0–65535 (http only) | 8787 | — |
transport.path | string starting with / (http only) | "/mcp" | — |
transport.resource | url (http only) | required | /.well-known/oauth-protected-resource で公開される OAuth 保護リソース識別子 |
transport.authorizationServers | array of url, min 1 (http only) | required | — |
transport.allowedHostnames | array of string (http only) | [] | localhost のデフォルトに加えて受け入れる、追加の Host ヘッダー値 |
tokenExchange | object | not configured | RFC 8693 トークン交換。呼び出し元を認証するために http トランスポートで必要です(ルールを参照) |
tokenExchange.tokenEndpoint | url | required | — |
tokenExchange.clientId | string | required | — |
tokenExchange.clientSecret | { fromEnv: string } | required | — |
tokenExchange.clientAuth | "basic" | "post" | "basic" | client_secret_basic または client_secret_post |
tokenExchange.audience | string | not sent | — |
tokenExchange.resource | url | not sent | — |
tokenExchange.scope | string | not sent | — |
tokenExchange.schemes | array of string, min 1 | required | 交換後のトークンが満たすセキュリティスキーム名 |
source | string, non-empty | required | ローカルファイルパス(設定ファイルからの相対パス)、または OpenAPI ドキュメントを指す http(s):// URL |
reload.intervalSeconds | integer ≥ 10 | not set | この間隔に最大 10%のジッターを加えて source を再読み込みします。http(s) ソースでは前回の ETag/Last-Modified に基づいて条件付きで再読み込みし、提供されたものと同一の本文は無視されます |
reload.onSignal | boolean | true | SIGHUP により source を再読み込みします。reload ブロックがない場合、起動時にドキュメントを一度読み込み、SIGHUP はデフォルトの動作を維持します |
baseUrl | url | not set | ドキュメントのルート servers を置き換えます |
serverVariables | record<string, string> | not set | ドキュメントのサーバー変数のデフォルト値を上書きします |
hoistPathPrefix | string starting with / | not set | すべてのルートからベース URL に移動する先頭のパスセグメント |
outputSchema | "document" | "omit" | "document" | 応答がドキュメントと一致しないバックエンドでは omit を指定します |
requestBodyRequired | "document" | "always" | "document" | always は、宣言されていない requestBody.required を true として扱います |
strict | boolean | false | openapi_document_invalid を警告ではなく致命的な診断として発生させます |
selection.default | "include" | "exclude" | "exclude" | どのルールにも一致しない場合に操作を公開するかどうか(デフォルトでは明示的な許可が必要) |
selection.rules | array of { route?, method?, decision } | [] | route/method は、組み込み SDK がコントローラールートを照合するのと同じ方法で照合されます |
operations | record<operation key, x-sezzlee object> | {} | 各操作の x-sezzlee フィールドにフィールドごとに重ねて適用します。存在しない操作を指定するキーは致命的エラーです。ここで設定したフィールドは names、searchTerms、revision.operations からも設定できません |
names | record<operation key, string> | {} | ツール名を上書きします。値は ^[a-z][a-z0-9_]{0,255}$ に一致する必要があります |
revision.catalog | integer ≥ 1 | not configured | すべてのツールの動作リビジョンです。ドキュメントのルートにある x-sezzlee のリビジョンより前に適用されます |
revision.paths | record<document path, integer ≥ 1> | {} | そのパス項目配下のすべての操作の動作リビジョンです。パス項目の x-sezzlee のリビジョンより前に適用されます |
revision.operations | record<operation key, integer ≥ 1> | {} | 1つの操作の動作リビジョンです。その x-sezzlee のリビジョンより前に適用されます。各レベルは置き換えずに加算されます |
credentials | record<security scheme name, credential> | {} | { "value": { "fromEnv": "..." } } または { "username": { "fromEnv": "..." }, "password": { "fromEnv": "..." } } のいずれかです。credentials.mdを参照してください |
allowHosts | array of string | [] | ドキュメント自身のルートサーバーに加えて、バックエンド操作の提供元として許可するホスト |
refHosts | array of string | [] | ドキュメント自身のホストに加えて、外部 $ref の取得元として許可するホスト。allowHosts とは分けて管理されるため、スキーマのホストを許可しても、そこへの呼び出しや認証情報の送信は許可されません |
identityCookies | array of string | [] | デフォルトの拒否リストに加えて、IDを伝達するものとして扱う Cookie 名(大文字と小文字を区別せずに比較)。デフォルトの拒否リストを拡張するもので、置き換えることはありません |
limits.timeoutMs | positive int | 30000 | 呼び出しごとの期限 |
limits.maxResponseBytes | positive int | 262144 | エージェントに渡される最大応答サイズ。これを超える成功応答は、results.enabled が有効な間は read_result 用に保存され、それ以外の場合は拒否されます |
limits.maxBufferedBytes | positive int | 16777216 | 読み取るバックエンド本文の最大サイズ。本文のストリーミング中に適用され、これを超える本文は読み取らずに拒否されます |
results.enabled | boolean | true | 上限を超えた成功応答をメモリに保持し、read_result を公開します。result-reading.mdを参照してください |
results.lifetimeMs | int ≥ 1000 | 600000 | 保存した結果を保持する期間 |
results.maxCallerBytes | positive int | 16777216 | 1人の呼び出し元の保存結果に許可される容量。古い結果から削除されます。呼び出し元とは、認証に使用したベアラートークン、またはトークン交換がない場合はすべてのループバック呼び出し元です |
results.maxBytes | positive int | 67108864 | すべての保存結果に許可される容量。results.maxCallerBytes 以上である必要があります |
limits.maxInlineFileBytes | positive int | 1048576 | — |
credentials エントリーは、それが満たすセキュリティスキーム名をキーとします。tokenExchange.schemes | |||
エントリーは、交換後のトークンが同じスキームを満たすものとしてマークします。credentials の値が直接埋め込まれることはなく、環境変数への参照のみを指定するため、設定ファイルをコミットして共有できます。 |
ルール
- ネットワークにアクセスするのは
src/net/fetch.tsだけです。 ホスト許可リスト、リダイレクトの手動処理、バイト数の上限を適用する場所はここだけです。src/transport/http.tsでnode:httpを使えるのは リッスン する場合のみで、外部へのリクエストには使えません。リダイレクトは決して追跡しません。追跡すると、リクエストとその認証情報が、許可リストで承認されていないホストに送信される可能性があるためです。 - ファイルシステムにアクセスするのは
src/platform/files.tsだけです。 ドキュメントが外部$refを通じて参照するファイル、またはsourceで指定されたファイルは、ドキュメントを読み込んだディレクトリの範囲内にあるか、realpath で確認されます。そのため、../セグメントやシンボリックリンクを使って範囲外に出ることはできません。 - 呼び出し元の MCP トークンがバックエンドに転送されることはありません。 トークンの対象者はこのサーバーであり、バックエンドではありません。転送すると、バックエンド独自の対象者チェックを迂回することになります。
tokenExchangeが設定されたhttpトランスポートでは、トランスポートのベアラーゲートで呼び出し元のトークンが交換され(RFC 8693)、交換後のトークンのみがinvoke_toolに渡されます。 tokenExchangeのないhttpトランスポートは呼び出し元を認証しないため、ループバックホスト(127.0.0.1、::1、localhost)にのみバインドできます。そうしなければ、オペレーターの静的認証情報がネットワークからアクセス可能になります。同様に、stdioトランスポートでtokenExchangeを設定すると拒否されます(token_exchange_requires_http)。stdioには交換対象の呼び出し元トークンがないためです。- 再読み込みによって送信先の範囲が広がることはありません。
reloadが再読み込みするのはドキュメントのみで、設定は再読み込みしません。最初のカタログが呼び出せるホストが、それ以降のすべてのカタログの上限になります。ドキュメント内のサーバーが範囲外のホストに移動する場合、https から通常の http に変わる場合、または以前は認証情報を送信していなかった通常の http オリジンに認証情報を送信する場合、そのドキュメントは拒否されます(widens_egress)。拒否されたドキュメント、致命的な診断を含むドキュメント、または読み込めないドキュメントの場合、実行中のカタログが維持されます。再読み込みが確定すると、すべてのメタツールに付与されるカタログの世代番号が更新され、tools/list_changedが送信されます。再読み込み前に読み込まれたツールは、削除されていればunknown_toolを返し、古いバージョンに固定された呼び出しにはtool_changedを返します。 - 可視性は強制ではありません。操作の
securityが示すのは呼び出しに必要な認証情報であり、呼び出し可能な呼び出し元ではありません。そのため、ドキュメントにsecurity: []と記載されていない限り、カタログはすべての操作の ID をunknownとして報告します。
開発
pnpm turbo run build --filter=@sezzlee/openapi-mcp
pnpm turbo run lint --filter=@sezzlee/openapi-mcp
pnpm turbo run check-types --filter=@sezzlee/openapi-mcp
pnpm turbo run test --filter=@sezzlee/openapi-mcp
pnpm --filter @sezzlee/openapi-mcp <task> ではなく、これらは Turbo 経由で実行してください。フィルターを直接指定すると dependsOn: ["build"] がスキップされ、テストタスクが古い dist に対して実行されます。
test/ には、環境変数を必要としないユニットテストスイートと、条件付きで実行されるスイートが 1 つあります。
acceptance.spec.ts—SEZZLEE_OPENAPI_ACCEPTANCE_DOCに実際のバックエンドの OpenAPI ドキュメントへのパスが指定されていない場合はスキップされます。ドキュメント自体がリポジトリに含まれることはありません。このスイートはドキュメントを取り込み、カタログを構築し、致命的な診断がないことを検証して、バックエンドのインターフェースをツリーにコピーするスナップショットを固定する代わりに、診断の概要を出力します。SEZZLEE_OPENAPI_ACCEPTANCE_DOCは、このパッケージのturbo.jsonのtestタスクで宣言されているため、Turbo を通じて渡されます。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。