ROMANCE DAWN for the new world

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

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

Japan Azure User Group 15周年イベント&第7回 Azure Travelers 勉強会 東京の旅に参加してきました

先月、Japan Azure User Group 15周年と第7回 Azure Travelers 勉強会 東京の旅のコラボレーションイベントに参加してきました。
jazug.connpass.com

前夜祭

いつもは地方へ旅に行く Azure Travelers ですが、今回は東京開催ということで前夜祭として屋形船の LT 大会を企画しました。

jat.connpass.com

北品川の船宿平井の屋形船を貸切予約しました。料理は天ぷらとお刺身のプランで、周遊コースはお台場・隅田川コースを選びました。


北品川を出港して、お台場沖で停泊しました。停泊中は屋形船の屋根の上のデッキに上がることができて、夜景が奇麗でした。



その後、隅田川を北上して勝鬨橋あたりまで行きました。150分の飲み放題付で料理もボリュームがありましたし、とくに揚げたての天ぷらが美味しかったです。



船内では LT 大会やカラオケをして盛り上がりましたし、船外に出た時の気候もちょうど良く快適でした。何よりも参加した方たちが皆楽しそうにしていたので、企画して良かったなと思いました。

イベント当日

JAZUG × JAT で15周年を記念したパネルディスカッションを行いました。このセッションのみ配信のアーカイブがあります。

www.youtube.com

会場の様子。

パネルディスカッションの後のタイムテーブルは、こちら。

運営のお手伝いをしていたこともあり、じっくり聴くことはできませんでしたが、どのセッションも面白そうな内容でした。セッション資料は、Connpass にアップロードされているので、そちらをご覧いただければと。

今回、Azure Travelers で有志の協賛を募ってステッカーを作りました。Tech Tiles 規格に準拠したコレクションしたくなるステッカーです。

懇親会では、開催地をサイコロで決める Azure Travelers 恒例の催しがあり、次々回は石川県に決定しました。

まとめ

前夜祭の屋形船に始まり、イベント本編と懇親会にも多くの方に参加していただき、3次会まで楽しく過ごすことができました。お仕事でも趣味でも Azure が好きな人たちが集まって楽しめるコミュニティになるように、今後も盛り上げていきたいです。

JAZUG は Tokyo Jazug Night を今後も緩く開催していきますし、次回の Azure Travelers は来年1月の仙台の旅となります。
jazug.connpass.com
jat.connpass.com