HTTP TriggerのAzure FunctionsにMCPサーバーをデプロイしようとしたらできなかった話
TL;DR
- HTTP Trigger の function に MCP 公式 SDK を使って実装したサーバーのデプロイができなかった
- Azure Functions にデプロイするならプレビュー版の MCP Trigger を使おう
モチベーション
Azure Functions にはプレビュー版ですが MCP サーバーをデプロイすることができる MCP Trigger が提供されています。
一方でプレビュー版のため安定性に欠けている点や、1 つの Functions リソースに複数の MCP サーバーをデプロイできない点が課題として存在します。
そこで今回は HTTP Trigger の functions の各エンドポイントに対して MCP 公式 SDK を使って実装したサーバーをバインドすることで対応することができないかを試してみました
発生した問題
HTTP Trigger の function では、handler の引数としてHttpRequest
とInvocationContext
が渡されます。どちらも Azure Functions の SDK 内で定義されているオブジェクトですが、HttpRequest
は Web 標準のRequest
の拡張です。
一方で公式 SDK のhandleRequest
で求められるのはIncomingMessage
オブジェクトです。これは HTTP リクエストの Stream であり、Request
に比べて低レイヤーのオブジェクトになっています。
つまり Azure Functions の SDK によって落とされてしまっている情報まで MCP 公式 SDK では求められてしまっているという問題が発生しています。
HTTP Trigger で MCP を実装しようとしてみた例
app.http("mcpA", {
route: "/mcp/A",
methods: ["GET", "POST", "DELETE", "PUT"],
authLevel: "anonymous",
handler: async (req: HttpRequest, context: InvocationContext) => {
const transport = new StreamableHTTPServerTransport({
sessionIdGenerator: undefined,
});
await mcpServer.connect(transport);
const resp = new HttpResponse();
await transport.handleRequest(req, resp, req.body); // ここでエラー、第一引数にはIncomingMessageが求められる
return resp;
},
});
解決するには
案 1. リクエストが抽象化されないサービスにデプロイする
まず一つ目の解決案としてリクエストをIncomingMessage
として取得できるサービスにデプロイするということが考えられます。特に Azure Functions のようなサーバーレス環境では今回のような問題が発生しまいがちなため、Azure であれば App Service や Container Apps のようなサービスにデプロイすることで問題を回避できるかと思います。
案 2. MCP Trigger を使用する
前述の通り、複数の MCP サーバーをデプロイしたい場合、MCP Trigger を使用すると一つの Functions リソースで複数の MCP サーバーをデプロイするということができません。そのため、Functions リソースを複数作成する必要がある点があります。
しかし、一方で今回のようにリクエストの形式を気にすることなく、簡単にデプロイすることができるので Azure Functions で MCP を扱うにはこれが一番かと思います。
まとめ
今回は Azure Functions にデプロイできるというお手軽さを取って MCP Trigger を使うことを選択しました。
ただ、この情報は 2025 年 6 月現在のプレビュー版の状況のため今後安定版になることによって複数 MCP サーバーに対応する可能性もあります。
今後のアップデートに期待したいと思います。
Discussion