ほぼ初めてMCPサーバなるものにチャレンジ。
Function Callingはすっ飛ばしてMCP。
何やらMCP界隈では、Server Sent Eventというのがレガシー扱いになりStreamable HTTPというのが主流になったとか(よくわかっていない)。
そのStreamable HTTPにAzure Functionsも対応したらしいので(どう変わったのかわからんけど)、とりあえず久々にAzure Functionsを触ってみる。
言語はいつものNode.jsで。
C#とPythonはこちらのブログが詳しい。
実装する
まずはVS CodeからAzure Functions用のプロジェクトを作る。
適当なディレクトリを開いて、以下のメニューから作成。

言語はTypeScriptを選択。

一緒に関数も作るか聞かれるけど、MCPトリガーの関数はここから選べないので、今回はスキップ。

プロジェクトが出来上がるので、まず最初にやらないといけないのは、ExtentionBundleのバージョン指定。
プロジェクトのルートにある host.json を開いて、extensionBundleのidに.Experimentalを追記。

versionの変更はなし。
なんでこんな変更が必要なのかというと、MCPトリガーに必要な拡張機能 Microsoft.Azure.Functions.Extensions.Mcp がまだ正式にExtensionBundleに含まれていないから。
Experimentalだと入っているので変更している。
github.com
サンプルコード
今回のお題は、Copilotに現在時刻を返させる。
通常は、日時までは返せても、時刻は返してくれない。

この現在時刻をAzure Functions上のMCPサーバで取れるようにしてみる。
以下は、MCPサーバ、というか、MCPToolトリガーの関数のソース。
import { z } from "zod"; import { app, InvocationContext } from "@azure/functions"; // mcpToolWhatTimeIsIt function - responds with current time export async function mcpToolWhatTimeIsIt(_toolArguments: unknown, context: InvocationContext): Promise<string> { const mcptoolargs = context.triggerMetadata.mcptoolargs as { timezone?: string } const timeZone = mcptoolargs.timezone || 'UTC'; const formatter = new Intl.DateTimeFormat('ja-JP', { timeZone, dateStyle: 'full', timeStyle: 'long', }); return `It's ${formatter.format(new Date())} in ${timeZone}`; } // Register the what time is it tool app.mcpTool('what-time-is-it', { toolName: 'what-time-is-it', description: 'MCP Tool that responds with the current time.', toolProperties: { timezone: z.string().describe('The timezone to get the current time for (default is UTC)') }, handler: mcpToolWhatTimeIsIt });
ついでに、引数でタイムゾーンを指定すると、指定のゾーンでの時刻を返すようにした。
これを src/functions/whatTimeIsItMcpTool.ts として保存してデバッグ実行、、、とはうまくいかない。
パラメータの型を宣言するために使っているzodというライブラリが入っていないので、ソースコードの最初の行でエラーが出ている。

なので zod を入れる。
$ npm install zod@3
気を付けないといけないところは @3を付けてメジャーバージョンを指定すること。
これがないと最新のv4が入ってしまい、どうもうまくJavaScriptへのトランスパイルができない。
このzodを入れればソースのエラーは消えるので、今度こそデバッグ実行、、、またうまくいかない。
Azure上のストレージアカウントか、ローカルのエミュレータを指定しろ、と言ってくる。

幸い、VS Codeに Azurite拡張を入れていたので、今回はローカルエミュレータを使うことにする。
local.settings.jsonを開いて、AzureWebJobsStorageにUseDevelopmentStorage=trueという値を指定する。

昔はこの値が思い出せなくて、毎回Web検索してたけど、今はCopilotが入れてくれるので楽になった。
最後に、AzuriteのBlobサービスを起動して、やっとデバッグ実行開始!
無事起動したら、起動したローカルサーバをMCPサーバとして登録しないといけないので、ターミナルに MCP server endpointというURLが表示されるのでこれをコピーする。

再度VS Codeのコマンドパレットを開き、MCP: Add Server...を実行。

MCPサーバのタイプを聞かれるので、「HTTP」を選択。

さっきコピーしたURLを貼り付ける。

MCPサーバIDを指定できるけど、とりあえずこのままEnter。

MCPサーバのスコープは、今回はWorkspaceで。

すると、VS CodeのMCP SERVERSに追加される。

これでさっきと同じように時刻を聞いてみると、

と、現在時刻が取れた。
ついでに都市を指定してみると、

何やらそれっぽい時差がついて時刻が取れた。
やったぜ。
👆で書いた通り、まだExperimentalなExtensionBundleなのでProductionには使うのはお勧めしないけど、早くGAしたらいいですな。