Why Expose Workflows as MCP Tools
When you start building with agents, the first question is usually straightforward: one agent, one task. But production systems rarely stay that simple. You end up with multiple agents, each handling different responsibilities. One might handle customer queries, another manages orders, a third handles billing logic. They need to coordinate.
The conventional approach is direct API integration: agents call each other’s endpoints, manage authentication between themselves, and maintain knowledge of each other’s interfaces. This approach works well for tightly integrated teams and stable architectures.
Exposing your Durable Workflows as MCP (Model Context Protocol) tools offers a different path. Instead of agents knowing about each other’s internals, they discover available tools through a standardized protocol. Your workflow becomes a composable capability that any agent can use, regardless of where it runs. The infrastructure becomes language-agnostic: a Python agent can invoke your .NET workflow just as easily as another .NET agent.
This pattern is particularly valuable in enterprise environments where teams are distributed, workflows need independent scaling, and you want to build a reusable tool ecosystem across your organization.
The Architecture: Workflows as Discoverable Tools
Here’s how it works at a high level: Your Azure Function exposes an MCP server endpoint at /runtime/webhooks/mcp. When an agent connects to that endpoint, it receives a list of available tools. Each tool corresponds to a workflow registered in your Microsoft Agent Framework setup. The agent can then call any of those tools, which triggers the corresponding workflow instance in Durable Task. The workflow executes, returns results, and the agent receives the response.
According to the devblogs.microsoft.com documentation, the Functions host automatically registers an MCP tool trigger for each workflow, generating function metadata using AOT-safe JSON serialization. This means zero boilerplate: the framework handles metadata generation, routing, and state management automatically.
Setting Up Your Azure Function
Start with a new Azure Functions project targeting .NET 8 or later. Install the required packages:
dotnet new azurefunctions -n AgentWorkflowServer
cd AgentWorkflowServer
dotnet add package Microsoft.Agents.AI.Hosting.AzureFunctions
dotnet add package Microsoft.Agents.AI.DurableTask
dotnet add package Azure.Functions.Worker
The Microsoft Agent Framework handles the MCP endpoint automatically. You don’t need to write a custom HTTP function. Instead, you configure your workflows in the host builder.
Defining Your Workflows
Define your workflows using the Durable Task programming model. Each workflow becomes a tool that agents can discover and invoke. Here’s an example workflow for processing an order:
using Microsoft.Agents.AI.DurableTask;
using Durable.Functions.Orchestration;
public class OrderProcessingWorkflow
{
[Workflow]
public static async Task<OrderResult> ProcessOrder(
[OrchestrationTrigger] TaskOrchestrationContext context,
OrderRequest request)
{
var validationResult = await context.CallActivityAsync(
"ValidateOrder",
request);
if (!validationResult.IsValid)
{
return new OrderResult
{
Success = false,
Message = "Order validation failed"
};
}
var paymentResult = await context.CallActivityAsync(
"ProcessPayment",
request);
if (!paymentResult.Success)
{
return new OrderResult
{
Success = false,
Message = "Payment processing failed"
};
}
var fulfillmentResult = await context.CallActivityAsync(
"InitiateFulfillment",
request);
return new OrderResult
{
Success = true,
OrderId = request.OrderId,
Message = "Order processed successfully"
};
}
}
Registering Workflows with MCP Tool Trigger
Register your workflows in the host builder with the exposeMcpToolTrigger flag set to true. This tells the Azure Functions host to expose the workflow as an MCP tool:
using Microsoft.Agents.AI.Hosting.AzureFunctions;
using Microsoft.Agents.AI.DurableTask;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.Hosting;
var host = new HostBuilder()
.ConfigureFunctionsWorkerDefaults()
.ConfigureDurableWorkflows(workflows =>
{
workflows.AddWorkflow(
new OrderProcessingWorkflow(),
exposeStatusEndpoint: false,
exposeMcpToolTrigger: true);
})
.Build();
await host.RunAsync();
The workflow’s name and description are automatically used as the MCP tool name and description. Set these using the workflow builder or attributes:
workflows.AddWorkflow(workflow)
.WithName("ProcessOrder")
.WithDescription("Process a customer order through validation, payment, and fulfillment");
How MCP Tool Discovery Works
When an MCP client connects to your Azure Function, it queries the /runtime/webhooks/mcp endpoint. The framework responds with a list of available tools. Each tool includes the workflow name, description, and expected input properties.
According to learn.microsoft.com, MCP clients can then invoke tools with arguments. The framework validates inputs, schedules the workflow orchestration, waits for completion, and returns the result to the client.
This is particularly powerful in enterprise scenarios. A Python-based agent can discover your .NET workflows and invoke them as standard tools. A JavaScript agent can do the same. The protocol is language-agnostic, and the framework handles all the serialization and orchestration details.
Connecting Remote Agents
On the client side, configure your agent to connect to your Azure Function’s MCP server. The agent automatically discovers workflows exposed by your function and can invoke them as standard tools:
var mcpClient = new HttpClientTransport(
new Uri("https://your-function-app.azurewebsites.net/runtime/webhooks/mcp"),
apiKey: "your-function-key");
var agent = new Agent(mcpClient);
var tools = await agent.DiscoverTools();
foreach (var tool in tools)
{
Console.WriteLine($"Tool: {tool.Name} - {tool.Description}");
}
var result = await agent.InvokeTool("ProcessOrder", new { orderId = "12345", amount = 99.99m });
The agent receives the workflow result just as it would from any other tool. The orchestration, durability, and state management happen transparently in the background.
Key Benefits
Exposing workflows as MCP tools decouples agent logic from infrastructure. Teams can own their workflows independently and scale them separately. You build a composable tool ecosystem where agents discover capabilities dynamically rather than relying on hardcoded integrations.
The pattern also enables better observability. Each workflow execution is tracked by Durable Task, providing visibility into long-running operations, retries, and state transitions. This is invaluable in production systems where you need to understand what agents are doing and why.
What is MCP and why use it for workflows?
MCP (Model Context Protocol) is a standardized protocol for agents to discover and invoke tools. By exposing workflows as MCP tools, you enable any agent to use your workflows without tight coupling or knowledge of internal implementation details. This is especially valuable in distributed teams and multi-language environments.
Can agents in different languages invoke my workflows?
Yes. MCP is language-agnostic. A Python agent can invoke your .NET workflows through the MCP protocol just as easily as another .NET agent. The protocol handles serialization and communication transparently.
How does authentication work with MCP tools?
Use Azure Function authorization levels and API keys. Set your MCP endpoint to require a function key, and provide that key when connecting as an MCP client. For more details, see the learn.microsoft.com documentation on MCP bindings.
What happens if a workflow takes a long time?
Durable Workflows are designed for long-running operations. The MCP call will await the workflow completion. For very long operations, consider implementing async patterns with status polling or webhooks to notify clients when results are ready.
Can multiple agents call the same workflow simultaneously?
Yes. Each call creates a new workflow instance. Durable Task handles orchestration and state management automatically, allowing concurrent executions without conflicts.
Do I need to write custom MCP server code?
No. The Microsoft Agent Framework handles MCP server setup automatically when you set exposeMcpToolTrigger: true. The framework generates function metadata, manages the endpoint, and routes requests to your workflows.