🌊 HTTP + SSE MCP サーバー(OAuth 対応)
導入
このリポジトリは、MCP 仕様に基づいて OAuth で承認された、ストリーミング可能な HTTP および SSE トランスポートをサポートするリモート MCP サーバーを作成するためのリファレンス実装を提供します。
このリポジトリの MCP サーバーは、レポート SSE + HTTP トランスポートを処理するアプリケーションおよび OAuth とは論理的に分離されていることに注意してください。
その結果、このリポジトリを簡単にフォークし、独自の MCP サーバーと OAuth 資格情報をプラグインして、独自の機能を備えた動作する SSE/HTTP + OAuth MCP サーバーを構築できます。
しかし、なぜ?
素晴らしい質問ですね!MCP仕様では、2025年3月25日にOAuthに基づく認可仕様が追加されました。現在、2025年5月1日時点では以下のとおりです。
Typescript SDKには、ストリーミング可能なHTTPを備えたOAuth認証MCPサーバーを実現するための多くの構成要素が含まれていますが、そのようなサーバーの構築方法に関するドキュメントやチュートリアルはありません。
Python SDKには、ストリーミング可能なHTTPトランスポートの実装も、Typescript SDKにあるOAuthビルディングブロックの実装も含まれていません。
Streamable HTTPトランスポートは、CursorやClaudeデスクトップなどのMCPホストアプリケーションでは広くサポートされていませんが、JS/TS SDKの
StreamableHttpClientTransportクラスを使用してJavaScriptで記述されたエージェントに直接統合できます。
Naptha AIでは、ストリーミング可能な HTTP トランスポート上に OAuth 承認の MCP サーバーを構築したいと考えていましたが、リファレンス実装が見つからなかったため、自分たちで構築することにしました。
Related MCP server: MCP Dockerized Server
依存関係
このリポジトリでは、高速なオールインワンJavaScriptランタイムnpmあるBunが推奨ランタイムおよびパッケージマネージャーです。npm + tscとの互換性テストは限定的に実施済みです。
概要
このリポジトリは以下を提供します:
MCPサーバーは簡単に独自のサーバーに置き換えることができます
SSE とストリーミング可能な HTTP トランスポートおよびOAuth 認証の両方を管理する express.js アプリケーション。
この Express アプリケーションに資格情報と MCP サーバーを接続します。
この Express アプリは/authorizeや Authorization Server Metadata エンドポイント ( RFC8414 ) などの必要な OAuth エンドポイントを実装していますが、 OAuth 承認サーバーは実装していないことに注意してください。
この例では、動的クライアント登録( RFC7591 )をサポートする上流のOAuthサーバーにOAuthをプロキシします。この例を使用するには、独自の認可サーバーを用意する必要があります。Auth0の使用を推奨します。詳細は、以下の「OAuthの設定」セクションをご覧ください。
サーバーの設定
OAuthと動的クライアント登録に関する注意事項
この例を使用するには、OAuth 認可サーバーが必要です。*ご自身で実装しないでください。*デモを作成するために、 Auth0 を使用しました。Auth0 は優れた選択肢ですが、他にも多くの選択肢があります。
MCP 仕様では、珍しい OAuth 機能、具体的にはRFC7591 の動的クライアント登録のサポートが求められています。MCP仕様では、MCP クライアントとサーバーが動的クライアント登録プロトコルをサポートすることが規定されており、これにより MCP クライアント (クライアントトランスポートがどこであっても) はユーザー登録なしでクライアント ID を取得できます。これにより、新しいクライアント (エージェント、アプリなど) は新しいサーバーに自動的に登録できます。詳細については、 MCP 仕様の承認セクションを参照してください。ただし、これは残念ながら、動的クライアント登録をサポートしていない Google や GitHub などのプロバイダーに直接プロキシすることはできないことを意味します (これらのプロバイダーの UI でクライアントを登録する必要があります)。
この場合、2 つの選択肢があります。
GoogleやGitHubなどのOIDC IDPを認証に使用でき、動的なクライアント登録をサポートするAuth0などのアップストリームOAuthプロバイダーを選択するか、
アプリケーションに動的なクライアント登録を実装します(つまり、Expressアプリケーションは単なるOAuthプロキシではなく、完全または部分的に完全なOAuthサーバーになります)。CloudflareはWorkers OAuth MCPサーバーに同様の機能を実装しており、このプロジェクトでは後々これを拡張する予定です。詳細はこちらをご覧ください。
簡潔にするために、Auth0 を使用する前者のオプションを選択しました。
[!注記]
この実装は上流のOAuthサーバーをプロキシするため、OAuthサーバーからクライアントにアクセストークンを転送するというデフォルトのアプローチでは、ユーザーの上流アクセストークンが下流のクライアントとMCPホストに公開されてしまいます。これは多くのユースケースには適さないため、このアプローチではいくつかの@modelcontextprotocol/typescript-sdkクラスを再実装することでこの問題を解決しています。
上流の認可サーバーをプロキシしている間、エンドユーザーの認証トークンをMCPクライアント/ホストに返すのではなく、独自のトークンを発行し、クライアント/ホストがそのトークンを使用してサーバーに認可できるようにします。これにより、悪意のあるクライアントやホストによるトークンの悪用、あるいはトークンが漏洩した場合に悪用されることを防ぎます。
Auth0でOAuthを設定する
Auth0 を使い始めるには:
Auth0.comで Auth0 アカウントを作成します。
GoogleやGitHubなどのIDPへの接続を少なくとも1つ作成してください。手順については、こちらをご覧ください。
接続をドメインレベルの接続に昇格します。新しいOAuthクライアントは各MCPクライアントによって登録されるため、アプリケーション/クライアントごとにIDP接続を設定することはできません。つまり、接続はドメイン内のすべてのアプリで利用可能である必要があります。 その方法については、こちらをご覧ください。
動的クライアント登録(auth0では「動的アプリケーション登録」とも呼ばれます)を有効にします。設定方法については、こちらをご覧ください。
これらすべてを設定したら、次の情報が必要になります。
Auth0クライアントID
Auth0クライアントシークレット
Auth0テナントドメイン
これらの情報を.envに必ず入力してください.env.templateをコピーし、設定とシークレットの値を更新してください。
サーバーの実行
このリポジトリには、2 つの独立したスタンドアロン サーバーが含まれています。
src/app.stateless.tsにあるストリーミング可能なHTTPサーバーのステートレス実装。これはストリーミング可能なHTTPトランスポートのみをサポートし、(理論的には)サーバーレスデプロイメントに適しています。src/app.stateful.tsにあるSSEとストリーミング可能なHTTPの両方のステートフル実装。このアプリは両方のトランスポートを提供しますが、redisストレージ戦略を使用している場合でもメモリ内の状態を維持するため(接続はメモリ内に保持される必要がある)、サーバーレスデプロイメントや単純な水平スケーリングには適していません。
どちらもbunで実行できます。
すべてをまとめる
ストリーミング可能な HTTP および OAuth サポートを備えた MCP サーバーをテストするには、いくつかのオプションがあります。
前述のとおり、Python MCP SDK はこれらの機能をサポートしていないため、現時点ではリモート サーバーを Cursor や Claude Desktop などの MCP ホストに接続するか、TypeScript/JavaScript アプリケーションに直接接続することができますが、Python アプリケーションに接続することはできません。
サーバーを MCP ホストに接続する (Cursor / Claude)
ほとんどの MCP ホストはストリーミング可能な HTTP (多くの点で SSE より優れています) も OAuthもサポートしていないため、OAuth 認証を処理するmcp-remote npm パッケージを使用し、リモート トランスポートをホストの STDIO トランスポートにブリッジすることをお勧めします。
コマンドは次のようになります。
--transportオプションにはいくつかのオプションがあります。
http-first(デフォルト): 最初に HTTP トランスポートを試行し、HTTP が 404 エラーで失敗した場合は SSE にフォールバックします。sse-first: 最初に SSE トランスポートを試行し、SSE が 405 エラーで失敗した場合は HTTP にフォールバックします。http-only: HTTPトランスポートのみを使用します。サーバーがサポートしていない場合は失敗します。sse-only: SSEトランスポートのみを使用します。サーバーがサポートしていない場合は失敗します。
src/app.stateless.tsを使用してステートレスバージョンのサーバーを起動する場合、SSEトランスポートは利用できないため、 --transport http-onlyを使用する必要があります。このエントリポイントを使用する場合、SSEトランスポートは動作しないと考えられます。
サーバーをエージェントに接続する
StreamableHTTPClientTransportを使用することで、Streamable HTTP サーバーを JS/TS のエージェントに接続できます。ただし、これは OAuth で保護されたサーバーでは機能しません。代わりに、クライアント側でAuthorizationヘッダーを使用し、サーバー側で有効なアクセストークンを使用する必要があります。
クライアント認証情報、APIキー、またはその他の方法で実装できます。このパターンはこのリポジトリではサポートされていませんが、 Vercel AI SDKを使用すると次のようになります。