<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Azure Functions | The .NET Blog</title><link>https://thedotnetblog.com/tags/azure-functions/</link><description>Articles, tutorials and insights from the .NET community.</description><generator>Hugo</generator><language>en</language><managingEditor>@thedotnetblog (The .NET Blog)</managingEditor><webMaster>@thedotnetblog</webMaster><lastBuildDate>Sun, 31 May 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://thedotnetblog.com/tags/azure-functions/index.xml" rel="self" type="application/rss+xml"/><item><title>Durable Workflows in Microsoft Agent Framework: From In-Memory to Azure Functions</title><link>https://thedotnetblog.com/news/emiliano-montesdeoca/maf-durable-workflows-azure-functions-durable-task/</link><pubDate>Sun, 31 May 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/news/emiliano-montesdeoca/maf-durable-workflows-azure-functions-durable-task/</guid><description>MAF's workflow programming model now supports durable execution backed by Durable Task — here's how to build composable agent workflows that survive process restarts and scale across Azure Functions.</description><content:encoded>&lt;p&gt;One of the pain points with early AI agent workflows: they&amp;rsquo;re fragile. A long-running multi-step workflow tied to a single process means process restart = lost state. For simple demos this is fine. For production workloads it isn&amp;rsquo;t.&lt;/p&gt;
&lt;p&gt;Microsoft Agent Framework&amp;rsquo;s workflow programming model now supports &lt;strong&gt;durable execution&lt;/strong&gt;, backed by the Durable Task framework, with Azure Functions hosting. Here&amp;rsquo;s how the programming model works and why the durability story matters.&lt;/p&gt;
&lt;h2 id="the-core-building-blocks"&gt;The Core Building Blocks&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Executors&lt;/strong&gt; are the fundamental unit of work. Each one is typed — it takes a specific input and produces a specific output:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Microsoft.Agents.AI.Workflows&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;internal&lt;/span&gt; &lt;span class="kd"&gt;sealed&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderLookup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Executor&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;OrderCancelRequest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;OrderLookup&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;override&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="n"&gt;ValueTask&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;HandleAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;OrderCancelRequest&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;IWorkflowContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;CancellationToken&lt;/span&gt; &lt;span class="n"&gt;cancellationToken&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// look up the order, return it&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OrderId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Workflows&lt;/strong&gt; wire executors into directed graphs using a fluent builder. The framework handles execution, data flow between steps, and error propagation.&lt;/p&gt;
&lt;p&gt;You can model:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Sequential chains (step A → step B → step C)&lt;/li&gt;
&lt;li&gt;Parallel fan-out/fan-in (run agents A, B, C in parallel, aggregate results)&lt;/li&gt;
&lt;li&gt;Conditional branching&lt;/li&gt;
&lt;li&gt;Human-in-the-loop approvals (pause workflow, wait for external signal)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="the-in-memory-runner-for-local-dev"&gt;The In-Memory Runner for Local Dev&lt;/h2&gt;
&lt;p&gt;Getting started is fast:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;dotnet&lt;/span&gt; &lt;span class="k"&gt;add&lt;/span&gt; &lt;span class="n"&gt;package&lt;/span&gt; &lt;span class="n"&gt;Microsoft&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Agents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AI&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;dotnet&lt;/span&gt; &lt;span class="k"&gt;add&lt;/span&gt; &lt;span class="n"&gt;package&lt;/span&gt; &lt;span class="n"&gt;Microsoft&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Agents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Workflows&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The core package includes a lightweight in-process runner. No external dependencies, no database, no Azure resources. Works great for local development and unit testing.&lt;/p&gt;
&lt;h2 id="adding-durability-with-durable-task"&gt;Adding Durability with Durable Task&lt;/h2&gt;
&lt;p&gt;When a workflow needs to survive process restarts — because it&amp;rsquo;s long-running, because it has human-in-the-loop steps, because it fans out across many parallel agent calls — the in-memory runner isn&amp;rsquo;t enough.&lt;/p&gt;
&lt;p&gt;MAF&amp;rsquo;s Durable Task integration stores workflow state in Azure Storage. If the process restarts, the workflow resumes from where it left off. The programming model stays the same; you just swap the runner.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;dotnet&lt;/span&gt; &lt;span class="k"&gt;add&lt;/span&gt; &lt;span class="n"&gt;package&lt;/span&gt; &lt;span class="n"&gt;Microsoft&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Agents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Workflows&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DurableTask&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The same executors, the same workflow graph — backed by durable state.&lt;/p&gt;
&lt;h2 id="azure-functions-hosting"&gt;Azure Functions Hosting&lt;/h2&gt;
&lt;p&gt;The third layer is Azure Functions hosting. Your workflow becomes a Function app: trigger the workflow via an HTTP endpoint, and the durable runtime handles scaling, state, and reliability.&lt;/p&gt;
&lt;p&gt;This means a multi-agent workflow with parallel calls, conditional branches, and human approvals can scale across a serverless Functions environment without custom state management.&lt;/p&gt;
&lt;h2 id="why-this-matters"&gt;Why This Matters&lt;/h2&gt;
&lt;p&gt;The combination is significant for real AI systems:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Parallel agent calls&lt;/strong&gt; — fan out to multiple specialized agents simultaneously without blocking, aggregate results when all complete&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Long-running processes&lt;/strong&gt; — workflows that involve human approval or external events can pause and resume across hours or days&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Scale&lt;/strong&gt; — Azure Functions scales the execution horizontally; the Durable Task framework handles coordinating the parallel state&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you&amp;rsquo;re building MAF workflows beyond simple local demos, this is the path to production-grade execution.&lt;/p&gt;
&lt;p&gt;Original post: &lt;a href="https://devblogs.microsoft.com/dotnet/durable-workflows-in-microsoft-agent-framework/"&gt;Durable Workflows in the Microsoft Agent Framework&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title>Stop Hammering a Struggling Dependency: Retry Patterns for Azure Functions + Service Bus</title><link>https://thedotnetblog.com/news/emiliano-montesdeoca/azure-functions-service-bus-exponential-backoff-circuit-breaker/</link><pubDate>Thu, 21 May 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/news/emiliano-montesdeoca/azure-functions-service-bus-exponential-backoff-circuit-breaker/</guid><description>Exponential backoff and circuit breaker patterns are now natively supported for Service Bus-triggered Azure Functions — here's how they work and why you want both.</description><content:encoded>&lt;p&gt;Here&amp;rsquo;s how a recoverable fault becomes an outage in a Functions app: a dependency starts timing out, every Function instance retries immediately and indefinitely, the dependency gets hammered with hundreds of concurrent failed requests, and what started as a transient hiccup turns into a system-wide backpressure event.&lt;/p&gt;
&lt;p&gt;You probably know this story. Azure Functions scale out fast — that&amp;rsquo;s the whole point. But &amp;ldquo;scale out fast&amp;rdquo; and &amp;ldquo;retry immediately&amp;rdquo; together can make failures dramatically worse.&lt;/p&gt;
&lt;p&gt;Two patterns help. Exponential backoff and circuit breaker. Both are now natively supported for Service Bus-triggered Azure Functions.&lt;/p&gt;
&lt;h2 id="two-patterns-different-roles"&gt;Two Patterns, Different Roles&lt;/h2&gt;
&lt;p&gt;These patterns are complementary, not alternatives:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Exponential backoff&lt;/strong&gt; answers: &lt;em&gt;when should I try again?&lt;/em&gt;
It increases the delay between retries so a dependency has time to recover. Message-level, pacing the retry timing.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Circuit breaker&lt;/strong&gt; answers: &lt;em&gt;should I call this dependency at all right now?&lt;/em&gt;
It stops repeated calls to an unhealthy dependency after a failure threshold is hit, then probes carefully after a cooldown period. System-level, preventing retry storms.&lt;/p&gt;
&lt;p&gt;You want both. Backoff handles per-message retry pacing. Circuit breaker handles aggregate health decisions.&lt;/p&gt;
&lt;h2 id="why-this-matters-especially-for-service-bus"&gt;Why This Matters Especially for Service Bus&lt;/h2&gt;
&lt;p&gt;The queue absorbs burst traffic, which is good. But without controls, the queue can grow while workers keep wasting compute on calls that will fail. Poison messages stay active longer than they should. Hot partitions or limited downstream capacity create cascading problems.&lt;/p&gt;
&lt;p&gt;The safer design:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Detect transient failure&lt;/li&gt;
&lt;li&gt;Delay the next attempt with exponential backoff&lt;/li&gt;
&lt;li&gt;Stop calling the dependency when a failure threshold is reached (circuit open)&lt;/li&gt;
&lt;li&gt;Resume carefully after a cooldown period (circuit probe)&lt;/li&gt;
&lt;li&gt;Move irrecoverable work to dead-letter or a quarantine path&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="what-the-native-support-looks-like"&gt;What the Native Support Looks Like&lt;/h2&gt;
&lt;p&gt;The new support integrates with the existing Azure Functions host model — no extra libraries, no custom implementations. Configuration goes in your &lt;code&gt;host.json&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;extensions&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;serviceBus&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;messageHandlerOptions&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;maxRetryCount&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;retryPolicy&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;mode&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;exponentialBackoff&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;minBackoff&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;00:00:02&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;maxBackoff&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;00:05:00&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;maxRetryCount&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Circuit breaker configuration sets the failure threshold and reset interval so unhealthy dependencies don&amp;rsquo;t get pummeled during recovery.&lt;/p&gt;
&lt;h2 id="languages-covered"&gt;Languages Covered&lt;/h2&gt;
&lt;p&gt;This isn&amp;rsquo;t .NET only. The feature covers dotnet, JavaScript, TypeScript, and Python — the full set of Service Bus trigger supported languages in Azure Functions.&lt;/p&gt;
&lt;h2 id="wrapping-up"&gt;Wrapping Up&lt;/h2&gt;
&lt;p&gt;Retry patterns aren&amp;rsquo;t exciting to configure until the first time a downstream outage causes your Functions to compound the problem instead of gracefully degrading. Setting these up proactively is cheap. Retrofitting them during an incident is not.&lt;/p&gt;
&lt;p&gt;Original post: &lt;a href="https://devblogs.microsoft.com/azure-sdk/exponential-backoff-circuit-breaker-azure-functions/"&gt;Exponential backoff and circuit breaker for Service Bus-triggered Azure Functions&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title>Connect Your MCP Servers on Azure Functions to Foundry Agents — Here's How</title><link>https://thedotnetblog.com/news/emiliano-montesdeoca/foundry-agents-mcp-servers-azure-functions/</link><pubDate>Fri, 10 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/news/emiliano-montesdeoca/foundry-agents-mcp-servers-azure-functions/</guid><description>Build your MCP server once, deploy it to Azure Functions, and connect it to Microsoft Foundry agents with proper auth. Your tools work everywhere — VS Code, Cursor, and now enterprise AI agents.</description><content:encoded>&lt;p&gt;Here&amp;rsquo;s something I love about the MCP ecosystem: you build your server once, and it works everywhere. VS Code, Visual Studio, Cursor, ChatGPT — every MCP client can discover and use your tools. Now, Microsoft is adding another consumer to that list: Foundry agents.&lt;/p&gt;
&lt;p&gt;Lily Ma from the Azure SDK team &lt;a href="https://devblogs.microsoft.com/azure-sdk/give-your-foundry-agent-custom-tools-with-mcp-servers-on-azure-functions/"&gt;published a practical guide&lt;/a&gt; on connecting MCP servers deployed to Azure Functions with Microsoft Foundry agents. If you already have an MCP server, this is pure value-add — no rebuilding required.&lt;/p&gt;
&lt;h2 id="why-this-combination-makes-sense"&gt;Why this combination makes sense&lt;/h2&gt;
&lt;p&gt;Azure Functions gives you scalable infrastructure, built-in auth, and serverless billing for hosting MCP servers. Microsoft Foundry gives you AI agents that can reason, plan, and take actions. Connecting the two means your custom tools — querying a database, calling a business API, running validation logic — become capabilities that enterprise AI agents can discover and use autonomously.&lt;/p&gt;
&lt;p&gt;The key point: your MCP server stays the same. You&amp;rsquo;re just adding Foundry as another consumer. The same tools that work in your VS Code setup now power an AI agent your team or customers interact with.&lt;/p&gt;
&lt;h2 id="authentication-options"&gt;Authentication options&lt;/h2&gt;
&lt;p&gt;This is where the post really adds value. Four auth methods depending on your scenario:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Use Case&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Key-based&lt;/strong&gt; (default)&lt;/td&gt;
&lt;td&gt;Development or servers without Entra auth&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Microsoft Entra&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Production with managed identities&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;OAuth identity passthrough&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Production where each user authenticates individually&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Unauthenticated&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Dev/testing or public data only&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;For production, Microsoft Entra with agent identity is the recommended path. OAuth identity passthrough is for when user context matters — the agent prompts users to sign in, and each request carries the user&amp;rsquo;s own token.&lt;/p&gt;
&lt;h2 id="setting-it-up"&gt;Setting it up&lt;/h2&gt;
&lt;p&gt;The high-level flow:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Deploy your MCP server to Azure Functions&lt;/strong&gt; — samples available for &lt;a href="https://github.com/Azure-Samples/remote-mcp-functions-dotnet"&gt;.NET&lt;/a&gt;, Python, TypeScript, and Java&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Enable built-in MCP authentication&lt;/strong&gt; on your function app&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Get your endpoint URL&lt;/strong&gt; — &lt;code&gt;https://&amp;lt;FUNCTION_APP_NAME&amp;gt;.azurewebsites.net/runtime/webhooks/mcp&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Add the MCP server as a tool in Foundry&lt;/strong&gt; — navigate to your agent in the portal, add a new MCP tool, provide endpoint and credentials&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Then test it in the Agent Builder playground by sending a prompt that would trigger one of your tools.&lt;/p&gt;
&lt;h2 id="my-take"&gt;My take&lt;/h2&gt;
&lt;p&gt;The composability story here is getting really strong. Build your MCP server once in .NET (or Python, TypeScript, Java), deploy to Azure Functions, and every MCP-compatible client can use it — coding tools, chat apps, and now enterprise AI agents. That&amp;rsquo;s a &amp;ldquo;write once, use everywhere&amp;rdquo; pattern that actually works.&lt;/p&gt;
&lt;p&gt;For .NET developers specifically, the &lt;a href="https://github.com/Azure-Samples/remote-mcp-functions-dotnet"&gt;Azure Functions MCP extension&lt;/a&gt; makes this straightforward. You define your tools as Azure Functions, deploy, and you&amp;rsquo;ve got a production-grade MCP server with all the security and scaling Azure Functions provides.&lt;/p&gt;
&lt;h2 id="wrapping-up"&gt;Wrapping up&lt;/h2&gt;
&lt;p&gt;If you have MCP tools running on Azure Functions, connecting them to Foundry agents is a quick win — your custom tools become enterprise AI capabilities with proper auth and no code changes to the server itself.&lt;/p&gt;
&lt;p&gt;Read the &lt;a href="https://devblogs.microsoft.com/azure-sdk/give-your-foundry-agent-custom-tools-with-mcp-servers-on-azure-functions/"&gt;full guide&lt;/a&gt; for step-by-step instructions on each authentication method, and check the &lt;a href="https://learn.microsoft.com/azure/azure-functions/functions-mcp-foundry-tools?tabs=entra%2Cmcp-extension%2Cfoundry"&gt;detailed docs&lt;/a&gt; for production setups.&lt;/p&gt;</content:encoded></item><item><title>MCP Apps Get a Fluent API — Build Rich AI Tool UIs in .NET with Three Steps</title><link>https://thedotnetblog.com/news/emiliano-montesdeoca/mcp-fluent-api-azure-functions-dotnet/</link><pubDate>Fri, 10 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/news/emiliano-montesdeoca/mcp-fluent-api-azure-functions-dotnet/</guid><description>The new fluent configuration API for MCP Apps on Azure Functions lets you turn any .NET MCP tool into a full app with views, permissions, and CSP policies in just a few lines of code.</description><content:encoded>&lt;p&gt;MCP tools are great for giving AI agents capabilities. But what if your tool needs to show something to the user — a dashboard, a form, an interactive visualization? That&amp;rsquo;s where MCP Apps come in, and they just got a lot easier to build.&lt;/p&gt;
&lt;p&gt;Lilian Kasem from the Azure SDK team &lt;a href="https://devblogs.microsoft.com/azure-sdk/mcp-as-easy-as-1-2-3-introducing-the-fluent-api-for-mcp-apps/"&gt;introduced the new fluent configuration API&lt;/a&gt; for MCP Apps on .NET Azure Functions, and it&amp;rsquo;s the kind of developer experience improvement that makes you wonder why it wasn&amp;rsquo;t always this simple.&lt;/p&gt;
&lt;h2 id="what-are-mcp-apps"&gt;What are MCP Apps?&lt;/h2&gt;
&lt;p&gt;MCP Apps extend the Model Context Protocol by letting tools carry their own UI views, static assets, and security controls. Instead of just returning text, your MCP tool can render full HTML experiences — interactive dashboards, data visualizations, configuration forms — all invocable by AI agents and presented to users by MCP clients.&lt;/p&gt;
&lt;p&gt;The catch was that wiring all this up manually required knowing the MCP spec intimately: &lt;code&gt;ui://&lt;/code&gt; URIs, special mime types, metadata coordination between tools and resources. Not hard, but fiddly.&lt;/p&gt;
&lt;h2 id="the-fluent-api-in-three-steps"&gt;The fluent API in three steps&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Step 1: Define your function.&lt;/strong&gt; Just a standard Azure Functions MCP tool:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;[Function(nameof(HelloApp))]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;HelloApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt; [McpToolTrigger(&amp;#34;HelloApp&amp;#34;, &amp;#34;A simple MCP App that says hello.&amp;#34;)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ToolInvocationContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;Hello from app&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Step 2: Promote it to an MCP App.&lt;/strong&gt; In your program startup:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ConfigureMcpTool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;HelloApp&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AsMcpApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;assets/hello-app.html&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithTitle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Hello App&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithPermissions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;McpAppPermissions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ClipboardWrite&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;McpAppPermissions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ClipboardRead&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithCsp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;csp&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;csp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AllowBaseUri&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;https://www.microsoft.com&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ConnectTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;https://www.microsoft.com&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Step 3: Add your HTML view.&lt;/strong&gt; Create &lt;code&gt;assets/hello-app.html&lt;/code&gt; with whatever UI you need.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s it. The fluent API handles all the MCP spec plumbing — generating the synthetic resource function, setting the correct mime type, injecting the metadata that connects your tool to its view.&lt;/p&gt;
&lt;h2 id="the-api-surface-is-well-designed"&gt;The API surface is well-designed&lt;/h2&gt;
&lt;p&gt;A few things I really like:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;View sources are flexible.&lt;/strong&gt; You can serve HTML from files on disk, or embed resources directly in your assembly for self-contained deployments:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;McpViewSource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FromFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;assets/my-view.html&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;McpViewSource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FromEmbeddedResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;MyApp.Resources.view.html&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;CSP is composable.&lt;/strong&gt; You explicitly allowlist origins your app needs, following least-privilege principles. Call &lt;code&gt;WithCsp&lt;/code&gt; multiple times and origins accumulate:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithCsp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;csp&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;csp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ConnectTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;https://api.example.com&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LoadResourcesFrom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;https://cdn.example.com&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AllowFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;https://youtube.com&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Visibility control.&lt;/strong&gt; You can make a tool visible to the LLM only, the host UI only, or both. Want a tool that only renders UI and shouldn&amp;rsquo;t be called by the model? Easy:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithVisibility&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;McpVisibility&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;App&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// UI-only, hidden from the model&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="getting-started"&gt;Getting started&lt;/h2&gt;
&lt;p&gt;Add the preview package:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dotnet add package Microsoft.Azure.Functions.Worker.Extensions.Mcp --version 1.5.0-preview.1
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you&amp;rsquo;re already building MCP tools with Azure Functions, this is just a package update. The &lt;a href="https://learn.microsoft.com/azure/azure-functions/scenario-mcp-apps?tabs=bash%2Clinux&amp;amp;pivots=programming-language-csharp"&gt;MCP Apps quickstart&lt;/a&gt; is the best place to start if you&amp;rsquo;re new to the concept.&lt;/p&gt;
&lt;h2 id="wrapping-up"&gt;Wrapping up&lt;/h2&gt;
&lt;p&gt;MCP Apps are one of the more exciting developments in the AI tooling space — tools that don&amp;rsquo;t just &lt;em&gt;do things&lt;/em&gt; but can &lt;em&gt;show things&lt;/em&gt; to users. The fluent API removes the protocol complexity and lets you focus on what matters: your tool&amp;rsquo;s logic and its UI.&lt;/p&gt;
&lt;p&gt;Read the &lt;a href="https://devblogs.microsoft.com/azure-sdk/mcp-as-easy-as-1-2-3-introducing-the-fluent-api-for-mcp-apps/"&gt;full post&lt;/a&gt; for the complete API reference and examples.&lt;/p&gt;</content:encoded></item></channel></rss>