ROMANCE DAWN for the new world

Microsoft Azure を中心とした技術情報を書いています。

Microsoft Ignite 2025 に現地参加してきました【サンフランシスコ観光編】

Microsoft Ignite 2025 にサンフランシスコで現地参加してきました。ダウンタウン周辺を観光したので、その様子をまとめておきます。
Ignite のカンファレンスについては、こちらを参照してください。
gooner.hateblo.jp

San Francisco International Airport

日本からサンフランシスコ国際空港までは8時間(帰りは10時間)のフライトです。
入国審査で優先レーンを使える MPC(Mobile Passport Control)を事前に登録していたので、スムーズに入国できました。

到着ターミナルから BART の電車に乗ってダウンタウンまで移動します。交通系 IC の Clipper Card を iPhone のウォレットに追加しておいたので、改札口にタッチするだけで乗ることができました。市内の電車やバスやケーブルカーでも使うことができます。

宿泊するホテルの最寄り駅である Powell Street Station までは 30 分くらいでした。Red Line と Yellow Line のどちらでもダウンタウンまで行けます。

San Francisco Marriott Marquis

Ignite の参加申込の際に Advantage Pass($525)を追加したので、会場のすぐ近くにある Marriott Marquis Hotel に宿泊できました。


治安の懸念があったのと、カンファレンス期間中は朝早い時間の移動ですし、セッション中に少し仕事で部屋に戻ることもできるので、会場からの近さは重要です。Advantage Pass にはランチの優先レーンも含まれていましたが、普通に並んで食べることができたので意味がありませんでした。

Union Square

ホテルから歩いて Union Square を散策しました。クリスマスツリーやアイススケートリンクがありました。


Union Square の隣には、Nintendo SAN FRANCISCO があります。限定ロゴが入った T シャツなどがありましたが、品揃えは日本と変わらない感じでした。


Cable Car

Powell Street Station の近くにケーブルカーの Turnaround があるので、Fisherman's wharf まで乗りました。2人がかりで手動(背中)でケーブルカーを180°回転させているのは驚きました。


急勾配な坂道を進みながら眺める街並みは、なかなか良かったです。片道$9で少し高めなので、移動手段というよりはアトラクション的な要素が大きいですが、サンフランシスコに来たら一度は乗ることをお勧めします。




Cruise

ゴールデンゲートブリッジとアルカトラズ島を巡る遊覧クルーズに乗りました。

天気はあまり良くありませんでしたが、60分で約6000円の丁度いいクルーズでした。





Waymo

サンフランシスコには無人運転の電気自動車配車サービス Waymo があるので、乗ってみました。スマホのアプリで行き先を指定して迎えに来てもらい、アプリでドアをアンロックして乗り込み、車内のタッチパネルでスタートボタンを押すだけ。


360°のセンサー(カメラ)で周囲の人や車の動きを感知して、上手に自動運転していました。死角がない分、人間よりも安全運転かもしれません。Uber との違いは、乗り降りしやすい場所を Waymo が決めるので、現在地や目的地までは少しズレることがあるくらいです。無人の運転席でハンドルがクルクル回っているのは驚きで、今回の旅で一番の衝撃でした。

youtu.be

Golden Gate Bridge

最終日にやっと晴れたので、Golden Gate Bridge まで行きました。




Golden Gate Bridge を少しだけ歩いてみました。片道4キロあるので、渡るとしたら自転車が良さそうです。




Fisherman's wharf

Fisherman's wharf には、シーフードのレストランやお土産物屋がたくさんあります。サンフランシスコに観光で来るとしたら、このあたりのホテルに泊まると便利なのかもしれません。


Pier39 はちょっとしたショッピングモールのようなエリアです。想像よりも数は少なかったですが、野生のアシカも見ることができました。



Palace of Fine Arts

Palace of Fine Arts は円形ドームのある庭園で、万国博覧会のためのイベント会場の跡地です。




Alamo Square

Alamo Square は、アメリカのホームドラマ「フルハウス」にも登場するビクトリア建築の家が並ぶ公園です。パステルカラーの街並みが奇麗でした。




Lombard Street

Lombard Street は、「世界で最も曲がりくねった通り」として知られる有名な坂道です。かなりの急勾配ですが観光客の車がたくさん通っていました。




Grace Cathedral

Grace Cathedral は、Union Square の近くにある教会でステンドグラスが奇麗でした。




Ferry Building Marketplace

Ferry Building Marketplace は、フェリーターミナル兼マーケットになっています。ベイブリッジもよく見えました。


いい感じのワインバーで飲んだカリフォルニアワインが美味しかったです。



San Francisco Downtown

サンフランシスコの街並み。








San Francisco Foods

シーフードがたっぷりの魚介トマトスープのチョッピーノが一番のお気に入りです。写真を撮り忘れたのですが、どのお店もクラフトビールが美味しかったです。

Boudin Bakery Cafe の Clam Chowder
Pier Market Seafood Restaurant の Cioppino
Tad's Steakhouse の Famous Steak
In-N-Out Burger の Cheese Burger Animal Style
IPPUDO の Shiromaru Classic

Microsoft Ignite 2025 に現地参加してきました

昨年11月の Ignite 2024 に続き、今年も Ignite 2025 に現地参加してきました。昨年の開催地はシカゴでしたが、今年はサンフランシスコで開催されました。
ignite.microsoft.com
Ignite 2025 でアナウンスされた内容は、このあたりの記事で説明されています。
キーノートやブレイクアウトのセッション動画も公開されているので、気になるトピックは視聴してみてください。

この記事では、現地参加の雰囲気や個人的に感じたことをお伝えしていきます。

Registration

会場は、サンフランシスコにある Moscone Center です。

参加者数は昨年よりも多い2万人となり、Registration に行列ができていました。


Keynote

今年のキーノートは、Moscone Center とは別の場所となる Chase Center で行われました。NBA のゴールデンステイト・ウォリアーズのホームアリーナです。
当日は朝6時から1時間半くらい外で並ぶことになり、とにかく寒かったので来年参加する方はしっかりと防寒対策しておくことをお勧めします。

今回も MVP 向けの Priority Seat が用意されており、広いアリーナの中でもステージに近い席でテンションが上がりました。キーノートのスピーカーは Satya Nadella ではなく、Judson Althoff でした。Zava という架空の企業を想定したシナリオに沿って、キーノートが進められました。


今回の Ignite の重要なキーワードのひとつ「Work IQ」は、RAG を拡張させたインテリジェンスレイヤーです。Copilot やエージェントにデータ、メモリ、推論を与えることで、より有用でパーソナライズされた情報を生成できるようにします。

Azure AI Foundry 改め Microsoft Foundry が発表されました。App Builder、Copilot Studio、GitHub Copilot を動かすプラットフォームとして、Model router、Foundry IQ、Agent Service、Control Plane などの機能が統合されています。

キーノートでオーディエンスの反応が最も大きかったのは、Anthropic とのパートナーシップの発表でした。Microsoft Foundry で Claude の Sonnet や Opus など最新のモデルをデプロイできるようになります。

Microsoft Agent 365 は、企業内でどのようなエージェントが動いているのか、エージェント毎のアクセス制御、利用状況などを一元管理できます。従業員の ID 管理の延長でエージェントも管理するというコンセプトが面白いと感じました。

最後に、Scott Guthrie から AI データセンターや Azure アップデートの話があり、AKS Automatic の GA や Azure Horizon DB の発表がありました。Azure Copilot も リソースを選択して質問できるようになり、Migration Agent の発表もありました。

今回の Ignite は「Agent」という言葉が頻繁に登場し、エージェントを活用したビジネスのビジョンを強く打ち出していました。これまでの Copilot のような“副操縦士”にとどまらず、タスクを任せられる“人”に近い存在としての将来像でした。

Microsoft Agent 365 には、エージェントがきちんと仕事をしているかを確認するための“可観測性”を提供する役割があります。エラーで止まっていれば解決し、結果が物足りなければプロンプトを改善する。まるで、プロジェクトの朝会でメンバーの進捗を確認し、フォローするのと同じ感覚です。AI がチームの一員になる未来が、少しずつ現実味を帯びてきました。

歴史は繰り返すと言いますが、エージェントも本質的にはマイクロサービス(API)に近い存在だと思います。ただ、決定的に違うのはインターフェースが自然言語であること。この違いが、エンジニアだけでなくビジネスユーザーにも広く普及する鍵になると感じました。

とはいえ、今回のキーノートは概念的な話が中心で、「業務で使えるエージェントを本当に作れるのか?」というモヤっと感は残りました。結局のところ、データをいかに LLM が理解しやすい形式に変換できるか、ナレッジをどう言語化するか。この整備ができれば、汎用的な回答ではなく、より有用でパーソナライズされた回答が得られるはずです。この部分こそがインテリジェンスレイヤー(IQ)だと思いました。

Microsoft 365 で ID 管理を担う Entra ID と SharePoint Online に置かれた企業データを握っている Microsoft は強いと改めて感じました。

Breakout

ブレイクアウトセッションの様子。



個人的に熱いと感じた Azure 関連のアップデート。

アーセナルファンとして、今回の Ignite で一番ワクワクしたのは、Microsoft と Premier League の協業による事例セッションでした。今シーズンから試合中継の左上に表示される Stats に「Copilot」の文字があります。さらに、公式モバイルアプリも AI を活用したコンパニオンアプリに刷新されています。
セッションでは、その裏側で Azure 上にどのような仕組みが構築されているのかを知ることができました。スケーラブルなエージェント型アーキテクチャを採用し、数十年分の統計データ、動画、ニュースを活用して、ファンごとにパーソナライズされた体験を提供しているとのことでした。

そして、会場で本物のトロフィーを見られたのは感激でした。スピーカーをサポートしていた女性が Bukayo Saka のユニフォームを着ていたのも、ファンとしてはポイントが高かったです。今シーズンこそ、アーセナルが優勝してそのトロフィーを掲げる瞬間を見たいです。



会場の様子

Moscone Center には West、North、South の3つの建物があり、自由に聞きたいセッションを選べます。隣の Marriott Marquis Hotel も会場になっており、昨年のシカゴの会場と比較しても、かなり広い会場でセッション間の移動が大変でした。



HUB はパートナーのブースやシアターセッションがある広い会場でした。エキスパートのブースもあったので、開発チームにいくつかフィードバックしておきました。

  • Azure Functions Flex Consumption で Dutable Task Scheduler を使いたい(Consumption は発表あり)
  • Azure Functions Flex Consumption で Deployment Slot を使いたい(Rolling updates はあるけど、Swap したい)
  • GitHub Actions の Azure private networking を東日本でも使いたい(西日本はある)



恒例の MVP と RD の名前が書かれた Wall もあって、自分の名前を発見しました。


今年5月の Build ランチが美味しかったので期待していましたが、Ignite ランチは全体的に例年並みでした。

今回の戦利品。Backpack と Water Bottle が貰えました。


まとめ

Microsoft Ignite 2025 にサンフランシスコで現地参加してきました。
日本からのオンライン視聴では感じ取れない熱量があってモチベーションも高まるので、やはり現地参加は楽しいです。一緒に行った会社の同僚も楽しかったようなので、多くの若手エンジニアに経験してほしいです。
サンフランシスコを観光した話は、こちらの記事を参照してください。
gooner.hateblo.jp

Azure Functions MCP extension を使用して Agentic Web アプリケーションを構築する【Streamable HTTP 版】

7月の AOAI Dev Day 2025 は仕事の都合で参加できなかったのですが、しばやんさんのセッションをスライドを読んで Agentic Web アプリケーションを MCP に寄せて作るアーキテクチャが面白そうだったので試してみました。

speakerdeck.com

なぜ Agentic Web アプリケーションを MCP で構築するのか?

今回は、以前に Azure Durable Functions + Durable Task Scheduler を使って構築した旅行コンシェルジュの Agentic Web アプリケーションを題材にします。
gooner.hateblo.jp

Durable Functions の Activity を Agent に見立て、Orchestration の中で「実行すべき Activity を Function calling で決定→ Activity を呼び出し→ Activity の実行結果を合成」というロジックを実装しています。Activity の決定や実行結果の合成の処理も LLM を利用した Activity として実装しています。

このアーキテクチャを MCP に寄せることで、次のようなシーケンスで先程と同様の Agentic Web アプリケーションを構築できます。

MCP Server が提供する Tools を Agent に見立て、OrchestratorWorker が MCP Client となり、LLM が登録された Tools を必要に応じて実行し、最終的にユーザー向けのメッセージを合成するところまで処理してくれます。

  • Azure Functions MCP extension や MCP Client SDK を使ってすぐにアーキテクチャを組めるので、Tools(Agent)の内部実装に注力できる
  • LLM に任せる部分が増えることで OrchestratorWorker がシンプルになり、プロンプトを調整しやすいし、LLM の性能向上の恩恵を受やすくなる
  • MCP Server が提供する Tools を拡張するだけで、すぐに MCP Client に反映される
  • MCP Server を外部公開する想定はないが、外部提供されているリモート MCP Server を組み込みやすい

などが、Agentic Web アプリケーションを MCP で構築するモチベーションです。

MCP Server を実装する

Azure Functions MCP extension を使って、MCP Server を実装します。
.NET9 の Azure Functions を作って、Microsoft.Azure.Functions.Worker.Extensions.Mcp の NuGet Package をインストールします。

PM> NuGet\Install-Package Microsoft.Azure.Functions.Worker.Extensions.Mcp -Version 1.0.0

McpToolTriggerAttribute を使用して、Function を実装します。旅行コンシェルジュ向けの Tools をいくつか実装しますが、今回の本題とは逸れるのでロジックは決め打ちの文字列としています。

public class DestinationSuggestAgent(ILogger<DestinationSuggestAgent> logger)
{
    private readonly ILogger<DestinationSuggestAgent> _logger = logger;

    [Function(nameof(GetDestinationSuggest))]
    public string GetDestinationSuggest(
        [McpToolTrigger(nameof(GetDestinationSuggest), "希望の行き先に求める条件を自然言語で与えると、おすすめの旅行先を提案します。")] ToolInvocationContext context,
        [McpToolProperty(nameof(searchTerm), "行き先に求める希望の条件", true)] string searchTerm)
    {
        // This is sample code. Replace this with your own logic.
    }
}

MCP Client を実装する

MCP C# SDK を使って、MCP Client を実装します。
まずは、ModelContextProtocol 関連の NuGet Package をインストールします。

PM> NuGet\Install-Package Azure.AI.OpenAI -Version 2.5.0-beta.1
PM> NuGet\Install-Package Azure.Identity -Version 1.17.0
PM> NuGet\Install-Package Microsoft.Extensions.AI -Version 9.10.1
PM> NuGet\Install-Package Microsoft.Extensions.AI.OpenAI-Version 9.10.1-preview.1.25521.4
PM> NuGet\Install-Package ModelContextProtocol -Version 0.4.0-preview.3

Program.cs で、ChatClient のインスタンスを DI に登録しておきます。

builder.Services
    .AddApplicationInsightsTelemetryWorkerService()
    .ConfigureFunctionsApplicationInsights()
    .AddTransient<IOrchestratorWorker, OrchestratorWorker>()
    .Configure<TravelConciergeSettings>(builder.Configuration.GetSection("Function"))
    .AddChatClient(_ => BuildChatClient(builder.Configuration));

builder.Build().Run();

static IChatClient BuildChatClient(IConfiguration configuration)
{
    string GetRequired(string key) =>
        configuration[key] ?? throw new InvalidOperationException($"{key} is required.");

    var endpoint = GetRequired("Function:AzureOpenAIEndpoint");
    var apiKey = GetRequired("Function:AzureOpenAIApiKey");
    var modelDeploymentName = GetRequired("Function:ModelDeploymentName");

    return new ChatClientBuilder(
            new AzureOpenAIClient(new Uri(endpoint), new AzureKeyCredential(apiKey))
                .GetChatClient(modelDeploymentName).AsIChatClient())
        .UseFunctionInvocation()
        .Build();
}

AOAI のエンドポイントやキーは、secrets.json に定義しておきます。MCP 関連の項目は後ほど解説します。

{
  "Function": {
    "AzureOpenAIEndpoint": "https://xxx-xxx-eastus2.cognitiveservices.azure.com/",
    "AzureOpenAIApiKey": "xxx",
    "ModelDeploymentName": "gpt-4o",
    "MCPServerEndpoint": "http://localhost:xxxx/runtime/webhooks/mcp",
    "MCPExtensionSystemKey": "xxx"
  }
}

OrchestratorWorker クラスに、MCP Client を実装します。

public async Task<OrchestratorWorkerResult> RunOrchestrator(Prompt prompt)
{
    var messages = prompt.Messages.ConvertToChatMessageArray();
    ChatMessage[] allMessages = [
        new ChatMessage(ChatRole.System, OrchestratorWorkerPrompt.SystemPrompt),
        .. messages,
    ];

    // Create the MCP client
    // Configure it to start and connect to MCP server.
    var mcpClient = await CreateMcpClientAsync();

    // List all available tools from the MCP server.
    _logger.LogInformation("Available tools:");
    var tools = await mcpClient.ListToolsAsync();
    foreach (var tool in tools)
    {
        _logger.LogInformation("Tool: {ToolName} - {ToolDescription}", tool.Name, tool.Description);
    }

    // Conversation that can utilize the tools via prompts.
    var response = await _chatClient.GetResponseAsync(allMessages, new() { Tools = [.. tools] });
    return new OrchestratorWorkerResult
    {
        Content = response.Text,
        CalledAgentNames = ExtractFunctionCallNames(response.Messages)
    };
}

上記の通り、シンプルな実装です。secrets.json に定義した MCP Server の Endpoint と MCP Extension の System Key を使った McpClient の生成が肝となります。localhost で実行する場合、MCPExtensionSystemKey はどんな値でも構いません。

private async Task<McpClient> CreateMcpClientAsync()
{
    IClientTransport clientTransport = new HttpClientTransport(new()
    {
        Endpoint = new Uri(_settings.MCPServerEndpoint),
        TransportMode = HttpTransportMode.StreamableHttp,
        Name = "Travel Concierge MCP Server",
        AdditionalHeaders = new Dictionary<string, string>
        {
            {"x-functions-key", _settings.MCPExtensionSystemKey}
        }
    });
    return await McpClient.CreateAsync(clientTransport!);
}

実行された Tools の名前は、返却されたアシスタントのプロンプトから取得できます。

private List<string> ExtractFunctionCallNames(IList<ChatMessage> messages)
{
    return messages
        .Where(m => m.Role == ChatRole.Assistant && m.Contents != null && m.Contents.All(c => c is FunctionCallContent))
        .SelectMany(m => m.Contents.OfType<FunctionCallContent>().Select(c => c.Name))
        .ToList();
}

以上の手順で、MCP を使用した Agentic Web アプリケーションを構築できました。

ローカルのエミュレーターで動かす

Azurite が Docker Image で公開されていますので、ローカルの Docker Desktop で実行します。

$ docker run --rm -it -p 10000:10000 -p 10001:10001 -p 10002:10002 -v c:/azurite:/data mcr.microsoft.com/azure-storage/azurite:3.33.0

フロントエンドの Streamlit とバックエンドの Functions をローカルで実行し、チャットを入力してみます。

Tools の get_destination_suggest を利用して、おすすめの旅行先が提案されています。

Azure にデプロイする

構築したアプリケーションを Azure Functions Flex Consumption にデプロイします。ポイントは、MCP Extension の System Key を確認する部分です。

MCP Extension の System Key を含め、ローカルの secrets.json に定義していた値を App Settings に追加します。

以上の手順で、MCP を使用した Agentic Web アプリケーションを Azure 上でも動かすことができます。

まとめ

Azure Functions MCP Extension を使って、Agentic Web アプリケーションを構築してみました。

これまで Function Calling を駆使して実装していた Orchestration ロジックを、LLM と MCP に委ねることで、Tools(Agent)の内部実装に集中できるメリットは大きいと感じました。MCP extension が Ver.1.0.0 となって Streamable HTTP にも対応しました。
一方で、Durable Task Scheduler のダッシュボードで可視化できていた可観測性が失われるため、別の手段で組み込む必要があります。

また、MCP Client に登録する Tools の情報をリクエストごとに取得するのはオーバーヘッドが大きいため、MCP Server と Client を Function App として分離し、Tools の情報を永続化する仕組みも検討したいです。

逆に、長時間の処理や複雑なオーケストレーションが求められる Agent に関しては、Durable Functions を活用する方が適していると感じました。

今回のソースコードは、こちらのリポジトリで公開しています。
github.com