Aspire was previously an infrastructure tool: start services, wire up connections, deploy. In Aspire 13 a new dimension is added – AI integration as a concept embedded in the AppHost, the CLI, and the dashboard.
MCP: Aspire as a Tool for AI Agents
The Model Context Protocol (MCP) defines how AI agents access external tools and data sources. Aspire 13.1 integrates MCP on two levels.
First, as a development tool: aspire agent init sets up an MCP server through which AI assistants can interact directly with the running Aspire environment – starting services, reading logs, querying configurations, without the developer as an intermediary. An AI agent can thereby autonomously understand the state of the running application and react to it.
aspire agent init # set up MCP server for the current project
Second, as a hosting concept: services that themselves provide MCP servers can be registered in the AppHost and referenced like any other resource. Aspire handles service discovery and ensures that MCP clients automatically receive the server endpoints.
Caution: MCP authentication is not documented. The MCP server uses an x-mcp-api-key header for security, but neither the generation nor the value of the key is described in the official documentation. The launchSettings.json contains an MCP endpoint URL that does not work directly in practice (microsoft/aspire#16396). Anyone wanting to integrate the MCP server into their own AI client must extract the key from the dashboard or from the Aspire logs.
Further limitation: MCP integration is local. The MCP tools and agent registrations configured via aspire agent init exist only in local development mode. aspire deploy does not transfer this configuration to the target environment. For a production agent architecture, the MCP server endpoints must be manually integrated into the production infrastructure (microsoft/aspire#16063).
Azure AI Foundry and Microsoft Foundry
Azure AI Foundry integration enables local model development without an active Azure subscription. Aspire starts the model locally and exposes it through the same endpoint abstraction as a remotely hosted service:
var model = builder.AddAzureAIFoundry("foundry")
.AddDeployment("gpt4o", "gpt-4o", "2024-11-20");
builder.AddProject<Projects.ChatApi>("chat")
.WithReference(model);
The chat service receives the endpoint as an environment variable and doesn't need to distinguish whether it's talking to a local or Azure-hosted instance. For deployment to Azure Container Apps or AKS, Aspire automatically switches to the Azure endpoint.
From 13.2, Microsoft Foundry replaced the Azure AI Foundry branding; the API surface remained compatible.
Aspire as an Orchestrator for Agent Workflows
AI agent architectures typically consist of multiple components: an orchestrator, specialist agents, a vector store, an embedding service, and a database. That's precisely the domain where Aspire shows its value.
A typical agent stack in the AppHost:
var vectorDb = builder.AddQdrant("vectordb");
var embeddings = builder.AddAzureAIFoundry("embeddings")
.AddDeployment("embed", "text-embedding-3-small", "1");
var orchestrator = builder.AddProject<Projects.Orchestrator>("orchestrator")
.WithReference(vectorDb)
.WithReference(embeddings);
var specialist = builder.AddPythonApp("specialist", "../SpecialistAgent")
.WithReference(orchestrator);
Aspire handles all local wiring: service discovery, connection strings, certificates. All components of the agent stack are visible in the Aspire Dashboard – logs, traces, and the connections between them – just like any other distributed application.
AI Agents in the Dashboard
From 13.4, the Aspire Dashboard has a dedicated AI Agents dialog in the header. This shows all registered AI agents in the running environment, their status, and – for MCP-capable agents – the available tools.
The combination of the Aspire Dashboard and MCP integration allows AI agent workflows to be observed in the same way as classic service interactions: as traces showing which agent called which tools with which parameters.
Local Development Without Cloud Costs
A practical aspect that is often underestimated: Aspire enables the complete local execution of AI workflows before a single Azure resource is provisioned. Models run locally via the Foundry integration, vector stores like Qdrant start as containers, and the entire agent stack is observable through the dashboard.
Example: Orchestrating Ollama and Open WebUI
An impressive example of the local setup is the integration of open-source models with Ollama, coupled with an interface like Open WebUI. Aspire orchestrates the downloading of the containers, mounts the necessary drives for models and startup scripts, and automatically injects the URLs for API communication.
Here is what the setup in the AppHost looks like, using the qwen3:1.7b model as an example:
// Add Ollama resource as container and expose port
var ollamaResource = builder.AddContainer("ollama", "ollama/ollama:latest")
.WithEnvironment("OLLAMA_MODELS", "/root/.ollama/models")
.WithEnvironment("OLLAMA_NOPRUNE", "true")
.WithBindMount("ollama", "/root/.ollama")
.WithBindMount("./ollamaconfig", "/usr/config")
.WithBindMount("./ollama-startup.sh", "/usr/local/bin/startup.sh")
.WithHttpEndpoint(11434, 11434, "ollama")
.WithEntrypoint("/bin/bash")
.WithArgs("-c", "chmod +x /usr/local/bin/startup.sh && /usr/local/bin/startup.sh") // Automatically load models on startup
.WithLifetime(ContainerLifetime.Persistent);
var ollamaEndpoint = ollamaResource.GetEndpoint("ollama");
// Open WebUI as frontend, communicates directly with Ollama
var openWebUiResource = builder.AddContainer("openwebui", "ghcr.io/open-webui/open-webui:main")
.WithEnvironment("OLLAMA_BASE_URL", ollamaEndpoint)
.WithVolume("open-webui", "/app/backend/data")
.WithHttpEndpoint(8080, 8080)
.WaitFor(ollamaResource);
The corresponding ollama-startup.sh script ensures that when the container starts, the models are not only downloaded but also started, and the container remains active:
#!/bin/bash
set -e
echo "=== Ollama Container Startup ==="
export OLLAMA_HOST=0.0.0.0:11434
# Check if ollama binary is available and working
echo "Checking ollama binary..."
which ollama || { echo "ERROR: ollama binary not found"; exit 1; }
# Ensure the data directory exists and has proper permissions
echo "Setting up ollama data directory..."
mkdir -p /root/.ollama
chmod 755 /root/.ollama
echo "Starting Ollama server..."
# Start ollama serve in the background
ollama serve &
OLLAMA_PID=$!
# Wait for ollama to be ready
echo "Waiting for Ollama server to be ready..."
sleep 10
# Check if model already exists
if ! ollama list | grep -q "qwen3:1.7b"; then
echo "Pulling qwen3:1.7b model..."
ollama pull qwen3:1.7b
echo "Model pull completed successfully!"
else
echo "Model qwen3:1.7b already exists, skipping pull"
fi
echo "=== Ollama setup completed successfully! ==="
# Keep the container running by waiting for the ollama process
wait $OLLAMA_PID
With just a few lines of code, we start the AI model and a chat frontend. The startup script for Ollama is injected directly into the container via mount and loads the models automatically upon startup. The dependencies (WaitFor) ensure that Open WebUI only boots when the model is ready. The environment variable OLLAMA_BASE_URL is parsed asynchronously at startup directly via ollamaEndpoint, without developers having to worry about port collisions or IP addresses.
Only on aspire deploy do the local resources switch to their cloud equivalents – using the same connection abstractions that were used locally.
