A production-ready Model Context Protocol (MCP) server for Azure Cloud and Azure DevOps, built with Python for DevOps teams.
This server CANNOT delete, modify, or create anything in Azure. All operations are read-only.
- ✅ List resource groups
- ✅ List and manage subscriptions across multiple Azure accounts
- ✅ Manage AKS clusters (list, get details, autoscaler info)
- ✅ Storage account operations (list, details, containers)
- ✅ Key Vault management (list vaults, get details)
- ✅ Database services (Azure SQL, Cosmos DB, MySQL, PostgreSQL)
- ✅ List namespaces in AKS clusters
- ✅ Query pods with label filtering (e.g., find Airflow pods)
- ✅ Retrieve pod logs for debugging
- ✅ List deployments and services
- ✅ Monitor pod health and status
- ✅ List and search Azure AD groups
- ✅ Get detailed group information
- ✅ List users with OData filtering
- ✅ List service principals
- ✅ Project and team management
- ✅ Pipeline monitoring and execution history
- ✅ Repository operations
- ✅ Pull request tracking with reviewers
- ✅ Team listing and details
- ✅ Branch policies (required reviewers, build validation, etc.)
- ✅ Branch permissions and ACLs
- ✅ Comprehensive error handling with retries
- ✅ Structured logging with
structlog - ✅ Type hints throughout
- ✅ 70%+ test coverage
- ✅ Docker support
- ✅ Multiple authentication methods
- ✅ Input validation with Pydantic
- Python 3.11 or higher
- Poetry (recommended) or pip
- Azure subscription
- Azure CLI (for local development)
- (Optional) Azure DevOps organization and PAT
- (Optional) Node.js/npx (for official Azure MCP)
# 1. Clone and navigate
git clone https://github.com/nomadicmehul/azure-mcp-server.git
cd azure-mcp-server
# 2. Run automated setup (installs everything + Azure login)
./scripts/setup.sh
# 3. Verify installation
make test
# 4. Start the server
poetry run azure-mcp-serverThat's it! The setup script handles:
- Poetry installation and dependencies
- Azure login and subscription selection
- Optional: Service Principal creation
- Optional: Azure DevOps configuration with PAT token
# Clone the repository
git clone https://github.com/nomadicmehul/azure-mcp-server.git
cd azure-mcp-server
# Install dependencies
poetry install
# Set up environment
cp .env.example .env
# Edit .env with your Azure credentials# Install from source
pip install -e .
# Or install from PyPI (when published)
pip install azure-mcp-server# Install all dependencies
make install
# Set up environment file
make setup-env
# Validate configuration
make validateCreate a .env file in the project root:
# Required
AZURE_SUBSCRIPTION_ID=your-subscription-id
# Optional: Service Principal (for production)
AZURE_TENANT_ID=your-tenant-id
AZURE_CLIENT_ID=your-client-id
AZURE_CLIENT_SECRET=your-client-secret
# Optional: Azure DevOps
AZURE_DEVOPS_ORG=your-org-name
AZURE_DEVOPS_PAT=your-personal-access-token
# Server settings
LOG_LEVEL=INFO
ENABLE_CACHE=true
CACHE_TTL=300If you want to use Azure DevOps features, you'll need a Personal Access Token:
- Go to:
https://dev.azure.com/{your-org}/_usersSettings/tokens - Click "New Token"
- Select the following scopes:
- Code: Read
- Build: Read
- Project and Team: Read
- Graph: Read
- Identity: Read
- Copy the token and add it to your
.envfile
Note: Azure DevOps is optional. If not configured, only Azure resource tools will be available.
The server supports multiple authentication methods (in priority order):
-
Service Principal (Production)
export AZURE_TENANT_ID="..." export AZURE_CLIENT_ID="..." export AZURE_CLIENT_SECRET="..."
-
Azure CLI (Development)
az login az account set --subscription "your-subscription-id"
-
Managed Identity (Azure resources)
- Works automatically on Azure VMs, AKS, App Service, Container Instances
# Using Poetry
poetry run azure-mcp-server
# Using Make
make run
# Direct Python
python -m azure_mcp_server.mainAdd to your Claude Desktop config (~/Library/Application Support/Claude/claude_desktop_config.json on macOS):
Option 1: Use Both Official + Custom Servers (Recommended)
{
"mcpServers": {
"azure-official": {
"command": "npx",
"args": [
"-y",
"@azure/mcp@latest",
"server",
"start",
"--read-only"
]
},
"azure-devops": {
"command": "/Users/yourusername/.local/bin/poetry",
"args": [
"-C",
"/path/to/azure-mcp-server",
"run",
"azure-mcp-server"
]
}
}
}Option 2: Custom Server Only (For Kubernetes/DevOps)
{
"mcpServers": {
"azure": {
"command": "/Users/yourusername/.local/bin/poetry",
"args": [
"-C",
"/path/to/azure-mcp-server",
"run",
"azure-mcp-server"
]
}
}
}Why use both?
azure-official: General Azure resources (officially supported)azure-devops: Kubernetes, Azure DevOps, Entra ID (custom features)
Note: The server automatically reads configuration from:
.envfile in the project directory (Azure subscription ID, DevOps PAT, etc.)- Azure CLI session (
az login) - System environment variables
No need to specify credentials in Claude's config file.
Restart Claude Desktop after updating the config.
Once integrated with Claude Desktop, you can ask questions like:
Kubernetes Operations:
- "List all pods in the airflow namespace in my prod-cluster"
- "Show me the logs for the scheduler pod"
- "What Airflow-related pods are running? (using label: app=airflow)"
- "List all deployments in the default namespace"
Azure Resources:
- "List all AKS clusters in my subscription"
- "Show me storage accounts in the prod resource group"
- "What are the details of my production AKS cluster?"
- "List all my Azure subscriptions"
- "Show me all Key Vaults in the security resource group"
- "List secrets in vault https://myvault.vault.azure.net/"
- "Search for secret 'database-password' across all Key Vaults"
- "Find secrets containing 'api-key' in the prod resource group"
- "List all SQL servers in my subscription"
- "What Cosmos DB accounts do we have?"
- "List MySQL servers in the database resource group"
Azure AD:
- "List all Azure AD groups"
- "Show me users in the Engineering department"
- "What service principals do we have?"
# Build image
make docker-build
# Run container
make docker-run
# View logs
make docker-logs
# Stop container
make docker-stop# Run all tests
make test
# Run with coverage
make test-cov
# Run specific test file
poetry run pytest tests/test_auth.py -v# Format code
make format
# Run linters
make lint
# Type checking
poetry run mypy src/azure-mcp-server/
├── src/azure_mcp_server/ # Main source code
│ ├── main.py # MCP server entry point
│ ├── config.py # Configuration management
│ ├── logging.py # Structured logging
│ ├── azure/
│ │ └── auth.py # Azure authentication
│ └── tools/
│ ├── aks.py # AKS operations
│ ├── storage.py # Storage operations
│ ├── devops.py # DevOps operations
│ ├── entra.py # Azure AD/Entra ID operations
│ └── kubernetes.py # Kubernetes operations
├── tests/ # Test suite
│ ├── conftest.py
│ ├── test_aks.py
│ ├── test_auth.py
│ └── test_config.py
├── scripts/ # Setup and utility scripts
│ ├── setup.sh # Full project setup
│ ├── azure-setup.sh # Azure configuration
│ ├── quick-login.sh # Quick Azure login
│ └── validate-azure.sh # Validate configuration
├── .github/workflows/ # CI/CD pipeline
├── .env.example # Environment template
├── .gitignore # Git ignore rules
├── pyproject.toml # Poetry dependencies
├── Dockerfile # Container image
├── docker-compose.yml # Docker orchestration
├── Makefile # Development shortcuts
├── LICENSE # MIT License
└── README.md # Documentation
list_subscriptions- List all Azure subscriptions accessible to your accountget_subscription_details- Get detailed information about a specific subscription
Multi-Subscription Support: You can now view and work with resources across all your Azure subscriptions!
Resource Groups
list_resource_groups- List all resource groups in subscription
AKS Clusters
list_aks_clusters- List AKS clusters in a resource groupget_aks_cluster_details- Get detailed cluster information
Storage
list_storage_accounts- List storage accountsget_storage_account_details- Get account detailslist_blob_containers- List blob containers
Key Vaults
list_key_vaults- List Key Vaults in a resource group or subscriptionget_key_vault_details- Get detailed Key Vault information including policies and network ACLslist_vault_secrets- List secret names and metadata in a Key Vault (does NOT return secret values)search_secret_across_vaults- Search for secrets by name across all Key Vaults (metadata only)
Databases
list_sql_servers- List Azure SQL servers in a resource group or subscriptionlist_sql_databases- List databases in an Azure SQL serverlist_cosmos_accounts- List Cosmos DB accountslist_mysql_servers- List MySQL flexible serverslist_postgresql_servers- List PostgreSQL flexible servers
list_k8s_namespaces- List all namespaces in an AKS clusterlist_k8s_pods- List pods in a namespace (supports label filtering for apps like Airflow)get_k8s_pod_logs- Get logs from a specific podlist_k8s_deployments- List deployments in a namespacelist_k8s_services- List services in a namespace
Example: Query Airflow pods with label_selector: "app=airflow"
list_entra_groups- List Azure AD groups with optional OData filteringget_entra_group_details- Get detailed information about a specific grouplist_entra_users- List Azure AD users with optional filteringlist_service_principals- List service principals
Example: Filter users by department: filter: "department eq 'Engineering'"
list_devops_projects- List all DevOps projectslist_pipelines- List pipelines in a projectget_pipeline_runs- Get recent pipeline runslist_repositories- List Git repositoriesget_pull_requests- Get pull requests with reviewerslist_teams- List teams in a project or organizationget_branch_policies- Get branch policies (required reviewers, build validation, etc.)get_branch_permissions- Get branch permissions and ACLs for repositories
Note: Requires AZURE_DEVOPS_ORG and AZURE_DEVOPS_PAT in .env
🛡️ This MCP server is 100% READ-ONLY by design:
- ❌ Cannot create Azure resources
- ❌ Cannot delete anything (pods, clusters, storage, etc.)
- ❌ Cannot modify configurations
- ❌ Cannot restart or stop services
- ❌ Cannot scale deployments
- ✅ Only reads information from Azure
All tools are read-only:
list_*- Only lists resourcesget_*- Only retrieves information- No write, update, delete, or modify operations exist
- ✅ No hardcoded credentials
- ✅ Multiple authentication methods
- ✅ Read-only operations by default (and enforced)
- ✅ Input validation on all parameters
- ✅ Structured error handling
- ✅ Secure secret management
- ✅ No destructive operations possible
- ✅ Key Vault secrets: Only lists secret NAMES, never returns actual secret values
Azure Resources:
- ❌ Create/delete resource groups
- ❌ Create/delete AKS clusters
- ❌ Modify storage accounts
- ❌ Delete blob containers
Key Vault Security:
- ✅ Can list secret names and metadata
- ❌ CANNOT retrieve actual secret values
- ❌ Cannot create or delete secrets
- ❌ Cannot modify secret values or permissions
- ✅ Only provides visibility into what secrets exist
- ❌ Change permissions
Kubernetes:
- ❌ Delete pods or deployments
- ❌ Scale deployments
- ❌ Restart pods
- ❌ Modify configurations
- ❌ Apply YAML manifests
- ✅ Only view logs (read-only)
Azure AD:
- ❌ Create/delete users or groups
- ❌ Modify permissions
- ❌ Change group memberships
Azure DevOps:
- ❌ Trigger pipeline runs
- ❌ Approve/reject PRs
- ❌ Modify repository settings
✅ Read and observe only:
- List and view Azure resources
- Query Kubernetes pods and logs
- Check Azure AD users and groups
- Monitor Azure DevOps pipelines
- Get detailed information about resources
Perfect for: Monitoring, troubleshooting, inventory, documentation, and observation without risk of accidental changes.
1. Poetry not found
# Install Poetry
curl -sSL https://install.python-poetry.org | python3 -
export PATH="$HOME/.local/bin:$PATH"2. Authentication Issues
# Verify Azure CLI login
az account show
# Re-login
az login
az account set --subscription "your-subscription-id"
# Test authentication
poetry run python -c "from azure_mcp_server.azure.auth import AzureAuth; from azure_mcp_server.config import get_config; import asyncio; auth = AzureAuth(get_config()); asyncio.run(auth.validate())"3. Kubernetes Tools Failing
# Verify AKS access
az aks get-credentials --resource-group your-rg --name your-cluster
# Test kubectl access
kubectl get namespaces4. Configuration Issues
# Validate entire setup
make validate
# Or use the validation script
./scripts/validate-azure.sh5. Claude Desktop Not Connecting
- Verify Poetry path:
which poetry(use full path in config) - Check logs:
tail -f ~/Library/Logs/Claude/mcp*.log - Restart Claude Desktop completely (Cmd+Q, then reopen)
- Verify
.envfile exists in project root with AZURE_SUBSCRIPTION_ID - Ensure project path in Claude config matches actual location
# One-command setup
git clone <repo> && cd azure-mcp-server && ./scripts/setup.shThis runs the complete setup: Poetry install, dependencies, Azure login, configuration, and validation.
# Quick setup
./scripts/setup.sh
# Daily use
poetry run azure-mcp-server# Use Service Principal
export AZURE_TENANT_ID="..."
export AZURE_CLIENT_ID="..."
export AZURE_CLIENT_SECRET="..."
export AZURE_SUBSCRIPTION_ID="..."
# Install and run
poetry install
poetry run pytest# Build and run
docker-compose up -d
# Or use Make
make docker-build
make docker-run# Use environment variables (no .env file)
export AZURE_SUBSCRIPTION_ID="..."
export AZURE_TENANT_ID="..."
export AZURE_CLIENT_ID="..."
export AZURE_CLIENT_SECRET="..."
# Run as systemd service
sudo systemctl start azure-mcp-serverContributions welcome! Please:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes
- Add tests
- Run linters and tests (
make lint test) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
- Built with MCP SDK
- Uses Azure SDK for Python
- Inspired by DevOps best practices
- � Issues: GitHub Issues
- 💬 Discussions: GitHub Discussions
Made with ❤️ for DevOps enthusiast