Azure (MCP)¶
The Azure MCP server gives Holmes read-only access to any Azure API you permit via RBAC. This means Holmes can query VMs, AKS, SQL databases, Activity Log, Azure Monitor, networking, storage, and hundreds of other Azure services - limited only by the roles you assign.
Overview¶
The Azure MCP server runs as a pod in your Kubernetes cluster.
- Helm users: The pod is deployed automatically when you enable the addon
- CLI users: You deploy the pod manually to your cluster, then point Holmes at it
Note
Even when using Holmes CLI locally, the Azure MCP server must run in a Kubernetes cluster. Local-only deployment is not currently supported.
Configuration¶
For CLI usage, you need to deploy the Azure MCP server first, then configure Holmes to connect to it.
Step 1: Deploy the Azure MCP Server
Create a file named azure-mcp-deployment.yaml:
apiVersion: v1
kind: Namespace
metadata:
name: holmes-mcp
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: azure-mcp-sa
namespace: holmes-mcp
labels:
azure.workload.identity/use: "true"
# For Workload Identity, add annotations:
# annotations:
# azure.workload.identity/client-id: "YOUR_CLIENT_ID"
# azure.workload.identity/tenant-id: "YOUR_TENANT_ID"
---
apiVersion: v1
kind: ConfigMap
metadata:
name: azure-mcp-config
namespace: holmes-mcp
data:
AZURE_TENANT_ID: "YOUR_TENANT_ID"
AZURE_SUBSCRIPTION_ID: "YOUR_SUBSCRIPTION_ID"
AZ_AUTH_METHOD: "workload-identity" # Options: workload-identity, managed-identity, service-principal
READ_ONLY_MODE: "true"
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: azure-mcp-server
namespace: holmes-mcp
spec:
replicas: 1
selector:
matchLabels:
app: azure-mcp-server
template:
metadata:
labels:
app: azure-mcp-server
azure.workload.identity/use: "true"
spec:
serviceAccountName: azure-mcp-sa
containers:
- name: azure-mcp
image: me-west1-docker.pkg.dev/robusta-development/development/azure-cli-mcp:1.0.1
imagePullPolicy: IfNotPresent
args:
- "--transport"
- "streamable-http"
- "--host"
- "0.0.0.0"
- "--port"
- "8000"
- "--readonly"
ports:
- containerPort: 8000
name: http
env:
- name: AZURE_TENANT_ID
valueFrom:
configMapKeyRef:
name: azure-mcp-config
key: AZURE_TENANT_ID
- name: AZURE_SUBSCRIPTION_ID
valueFrom:
configMapKeyRef:
name: azure-mcp-config
key: AZURE_SUBSCRIPTION_ID
- name: AZ_AUTH_METHOD
valueFrom:
configMapKeyRef:
name: azure-mcp-config
key: AZ_AUTH_METHOD
- name: AZURE_CLIENT_ID
value: "YOUR_CLIENT_ID" # For workload identity or managed identity
# For service principal authentication, add:
# - name: AZURE_CLIENT_SECRET
# valueFrom:
# secretKeyRef:
# name: azure-mcp-creds
# key: AZURE_CLIENT_SECRET
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
livenessProbe:
httpGet:
path: /health
port: http
initialDelaySeconds: 30
periodSeconds: 30
readinessProbe:
httpGet:
path: /health
port: http
initialDelaySeconds: 10
periodSeconds: 10
---
apiVersion: v1
kind: Service
metadata:
name: azure-mcp-server
namespace: holmes-mcp
spec:
selector:
app: azure-mcp-server
ports:
- port: 8000
targetPort: 8000
protocol: TCP
name: http
Deploy it to your cluster:
Step 2: Configure Azure Authentication
Choose one of these authentication methods:
Option A: Workload Identity (Recommended for AKS)
Follow the Workload Identity setup guide to: 1. Enable Workload Identity on your AKS cluster 2. Create a managed identity with appropriate permissions 3. Establish federated identity credentials 4. Configure the ServiceAccount annotations
Option B: Managed Identity
For clusters with node-level managed identity:
1. Ensure your AKS nodes have a managed identity assigned
2. Update the deployment to use authMethod: managed-identity
3. Set the AZURE_CLIENT_ID to your managed identity's client ID
Option C: Service Principal
For service principal authentication: 1. Create a service principal and assign appropriate roles 2. Create a Kubernetes secret with the credentials:
kubectl create secret generic azure-mcp-creds \
--from-literal=AZURE_CLIENT_ID=YOUR_CLIENT_ID \
--from-literal=AZURE_CLIENT_SECRET=YOUR_CLIENT_SECRET \
-n holmes-mcp
- Update the deployment to reference the secret (uncomment the secret reference in the YAML above)
- Set
AZ_AUTH_METHOD: "service-principal"in the ConfigMap
Step 3: Configure Holmes CLI
Add the MCP server configuration to ~/.holmes/config.yaml:
mcp_servers:
azure_api:
description: "Azure API MCP Server - comprehensive Azure service access via Azure CLI"
url: "http://azure-mcp-server.holmes-mcp.svc.cluster.local:8000"
llm_instructions: |
IMPORTANT: When investigating issues related to Azure resources or Kubernetes workloads running on Azure,
you MUST actively use this MCP server to gather data rather than providing manual instructions to the user.
## Investigation Principles
**ALWAYS follow this investigation flow:**
1. First, gather current state and configuration using Azure CLI commands
2. Check Activity Log for recent changes that might have caused the issue
3. Collect metrics and logs from Azure Monitor if available
4. Analyze all gathered data before providing conclusions
**Never say "check in Azure portal" or "verify in Azure" - instead, use the MCP server to check it yourself.**
See the Azure MCP documentation for comprehensive investigation patterns and common commands.
Step 4: Port Forwarding (Optional for Local Testing)
If running Holmes CLI locally and need to access the MCP server:
Then update the URL in config.yaml to:
Workload Identity Authentication (Recommended for AKS)
The recommended approach for AKS clusters is to use Workload Identity. This provides secure, passwordless authentication.
mcpAddons:
azure:
enabled: true
# Service account configuration
serviceAccount:
create: true
name: "azure-api-mcp-sa"
annotations:
azure.workload.identity/client-id: "YOUR_CLIENT_ID"
azure.workload.identity/tenant-id: "YOUR_TENANT_ID"
# Azure configuration
config:
tenantId: "YOUR_TENANT_ID"
subscriptionId: "YOUR_SUBSCRIPTION_ID"
authMethod: "workload-identity"
clientId: "YOUR_CLIENT_ID"
readOnlyMode: true # Recommended for safety
Setup Steps:
- Follow the Workload Identity setup guide
- Create a managed identity and assign Azure RBAC roles
- Configure federated identity credentials
- Deploy with the configuration above
Service Principal Authentication
For non-AKS clusters or if Workload Identity is not available:
mcpAddons:
azure:
enabled: true
serviceAccount:
create: true
name: "azure-api-mcp-sa"
config:
tenantId: "YOUR_TENANT_ID"
subscriptionId: "YOUR_SUBSCRIPTION_ID"
authMethod: "service-principal"
readOnlyMode: true
# Reference to existing secret with credentials
secretName: "azure-mcp-creds"
Create the secret before deploying:
kubectl create secret generic azure-mcp-creds \
--from-literal=AZURE_CLIENT_ID=YOUR_CLIENT_ID \
--from-literal=AZURE_CLIENT_SECRET=YOUR_CLIENT_SECRET \
-n YOUR_NAMESPACE
Managed Identity Authentication
For AKS clusters with node-level managed identity:
mcpAddons:
azure:
enabled: true
config:
tenantId: "YOUR_TENANT_ID"
subscriptionId: "YOUR_SUBSCRIPTION_ID"
authMethod: "managed-identity"
clientId: "YOUR_MANAGED_IDENTITY_CLIENT_ID"
readOnlyMode: true
For additional configuration options (resources, network policy, node selectors, etc.), see the full chart values.
Then deploy or upgrade your Holmes installation:
Workload Identity Authentication (Recommended for AKS)
globalConfig:
# Your existing Robusta configuration
# Add the Holmes MCP addon configuration
holmes:
mcpAddons:
azure:
enabled: true
# Service account configuration
serviceAccount:
create: true
name: "azure-api-mcp-sa"
annotations:
azure.workload.identity/client-id: "YOUR_CLIENT_ID"
azure.workload.identity/tenant-id: "YOUR_TENANT_ID"
# Azure configuration
config:
tenantId: "YOUR_TENANT_ID"
subscriptionId: "YOUR_SUBSCRIPTION_ID"
authMethod: "workload-identity"
clientId: "YOUR_CLIENT_ID"
readOnlyMode: true
Service Principal Authentication
globalConfig:
# Your existing Robusta configuration
holmes:
mcpAddons:
azure:
enabled: true
serviceAccount:
create: true
name: "azure-api-mcp-sa"
config:
tenantId: "YOUR_TENANT_ID"
subscriptionId: "YOUR_SUBSCRIPTION_ID"
authMethod: "service-principal"
readOnlyMode: true
secretName: "azure-mcp-creds"
Create the secret before deploying:
kubectl create secret generic azure-mcp-creds \
--from-literal=AZURE_CLIENT_ID=YOUR_CLIENT_ID \
--from-literal=AZURE_CLIENT_SECRET=YOUR_CLIENT_SECRET \
-n YOUR_NAMESPACE
Managed Identity Authentication
globalConfig:
# Your existing Robusta configuration
holmes:
mcpAddons:
azure:
enabled: true
config:
tenantId: "YOUR_TENANT_ID"
subscriptionId: "YOUR_SUBSCRIPTION_ID"
authMethod: "managed-identity"
clientId: "YOUR_MANAGED_IDENTITY_CLIENT_ID"
readOnlyMode: true
For additional configuration options (resources, network policy, node selectors, etc.), see the full chart values.
Then deploy or upgrade your Robusta installation:
IAM Configuration¶
Azure RBAC Roles¶
Assign roles based on what you want Holmes to investigate. At minimum, assign Reader on the subscription. For broader investigations, add more roles:
| Role | Purpose |
|---|---|
| Reader | Read-only access to all resources (minimum) |
| Azure Kubernetes Service Cluster User Role | kubectl access via az aks get-credentials |
| Log Analytics Reader | Container Insights and Azure Monitor logs |
| Monitoring Reader | Azure Monitor metrics |
| Cost Management Reader | Cost analysis |
Setup Script:
curl -O https://raw.githubusercontent.com/robusta-dev/holmes-mcp-integrations/master/servers/azure/setup-workload-identity.sh
bash setup-workload-identity.sh
This script will:
- Create a managed identity
- Assign appropriate RBAC roles
- Configure federated identity credentials
- Output the configuration values for your Helm chart
Manual Role Assignment:
# Assign Reader role to managed identity
az role assignment create \
--assignee YOUR_CLIENT_ID \
--role Reader \
--scope /subscriptions/YOUR_SUBSCRIPTION_ID
# Assign Log Analytics Reader for monitoring
az role assignment create \
--assignee YOUR_CLIENT_ID \
--role "Log Analytics Reader" \
--scope /subscriptions/YOUR_SUBSCRIPTION_ID
# Assign Cost Management Reader for cost analysis
az role assignment create \
--assignee YOUR_CLIENT_ID \
--role "Cost Management Reader" \
--scope /subscriptions/YOUR_SUBSCRIPTION_ID
Multi-Subscription Access¶
Holmes can automatically discover and switch between subscriptions within the same tenant. Just ensure your identity has the appropriate roles in each subscription.
Example Usage¶
Testing the Connection¶
After deploying the Azure MCP server, verify it's working:
# Check pod status
kubectl get pods -n YOUR_NAMESPACE -l app.kubernetes.io/name=azure-mcp-server
# Check logs
kubectl logs -n YOUR_NAMESPACE -l app.kubernetes.io/name=azure-mcp-server
# Health check
kubectl port-forward -n YOUR_NAMESPACE svc/RELEASE_NAME-azure-mcp-server 8000:8000
curl http://localhost:8000/health
# Ask Holmes
holmes ask "Can you list all resource groups in my Azure subscription?"
Troubleshooting¶
Authentication Issues¶
Problem: Pod logs show authentication errors
Solutions:
-
For Workload Identity: Verify federated identity credentials are configured correctly
-
For Service Principal: Verify secret exists and contains correct credentials
-
Check service account annotations
Permission Errors¶
Problem: Holmes reports "AuthorizationFailed" or "Forbidden" errors
Solution: Verify RBAC role assignments
# Check role assignments for your managed identity or service principal
az role assignment list --assignee YOUR_CLIENT_ID --output table
Connection Timeouts¶
Problem: Holmes can't connect to the MCP server
Solutions:
-
Verify the service is running
-
Check network policy isn't blocking traffic
-
Test connectivity from Holmes pod
Subscription Access Issues¶
Problem: Can't query certain subscriptions
Solution: Verify your identity has access to all required subscriptions
# List accessible subscriptions
az account list --output table
# Check role assignments in specific subscription
az role assignment list \
--assignee YOUR_CLIENT_ID \
--subscription SUBSCRIPTION_ID