Mentioned as a sponsorship option for the project, allowing users to support the development through donations
Supports querying Kubernetes resources through Azure Resource Graph using custom KQL templates for inventory management
Azure-Assistant-MCP
Minimal, fast MCP server for exploring Azure using Azure Resource Graph (ARG). It generates and runs KQL to answer questions about your Azure environment(s), with clear, explicit scoping and optional management group coverage.
Disclaimer
Use this project at your own risk. It is provided "as is" without warranties or guarantees of any kind. You are solely responsible for how you use it, including configuration, access control, and compliance with your organization’s policies. The author and contributors are not liable for any damages, data loss, security incidents, costs, or policy violations that result from using this software. No employer or organization is implied to endorse or support this project.
Why this exists
Make it trivial to inspect and run ARG KQL directly.
Avoid heavyweight dependencies; ship a small, stdio-based MCP server.
Highlights
Natural‑language → KQL for common tasks; always shows the query.
Direct KQL execution against ARG with paging caps (
top).Explicit scope in responses: tenant + subscriptions or management group.
Auto‑discover subscriptions or query at management group scope.
Optional diagnostics mode for quick scope debugging.
Requirements
Python 3.10+
Azure SPN(s) with Reader at the scope you intend to query:
Subscriptions: Reader on each target subscription
Management group: Reader on the MG (and underlying resources)
Install
From the repo root:
pip install -e .Or use the wrapper:
./azure-assistant-mcp.sh(prefers.venvif present)
Add as an MCP stdio server in your client using the wrapper command.
Ensure the wrapper is executable:
chmod +x ./azure-assistant-mcp.shExample (Claude Desktop CLI):
claude mcp add azure-assistant-mcp \ /your/path/Azure-Assistant-MCP/azure-assistant-mcp.sh \ --env AZURE_ASSISTANT_CONFIG=/your/path/Azure-Assistant-MCP/azure-config.json \ --scope user \ --transport stdio
Configuration
Place your secrets in
azure-config.json(ignored by git). Seeazure-config-example.jsonfor structure.The launch script exports
AZURE_ASSISTANT_CONFIGto the repo’sazure-config.jsonto avoid accidental cross‑repo configs.You can also point to a custom location via
AZURE_ASSISTANT_CONFIG.
Schema
Top level
debug(optional): enables diagnostics tooltenants: list of configured tenants
Per tenant
id: tenant guidname: friendly nameservice_principal.client_id/service_principal.client_secretdefault_subscription_id(optional fallback)management_group_id(optional; short name likecontoso-rootor full resource id). The server normalizes to the short name.
Scoping Rules
If
subscription_idsare provided: use those subscriptions.Else if
use_all_subscriptionsis true andmanagement_group_idis configured: run at MG scope in ARG.Else attempt to enumerate subscriptions via ARM and use that list.
Else fall back to
default_subscription_id.Responses always print
Tenantand eitherScope: managementGroup=...orSubscriptions used: N.
Tools
ask-azure:Input:
{ "question": string, "tenant_name?": string, "subscription_ids?": string[], "use_all_subscriptions?": boolean, "auto_execute?": boolean }Generates KQL for your question. If
auto_executeis true (default), executes it using Scoping Rules. Iftenant_nameis omitted, the server heuristically infers it from text (matches names and initialisms).
list-tenants:Input:
{}Lists configured tenants from
azure-config.jsonwith their IDs, optionalmanagement_group_id, anddefault_subscription_idto help you pick scope and SPN.
run-arg-kql:Input:
{ "kql_query": string, "tenant_name?": string, "subscription_ids?": string[], "use_all_subscriptions?": boolean, "top?": integer }Executes provided KQL using Scoping Rules. Adds
Rows,Tenant, and the scope line to the header.
run-kql-template:Input:
{ "template_name": string, "params?": object, "tenant_name?": string, "subscription_ids?": string[], "use_all_subscriptions?": boolean, "top?": integer }Loads
src/azure_assistant_mcp/kql/<template_name>.md(fenced kql) or.kql, applies simple{{key}}replacements fromparams, and executes with Scoping Rules.
list-subscriptions:Input:
{ "tenant_name?": string }Lists subscriptions. Uses ARM enumeration when possible, enriches with ARG; prefers MG scope if configured to return a complete list.
vm-count-by-tenant:Input:
{ "tenant_names?": string[], "use_all_subscriptions?": boolean }Runs a simple VM count per tenant using the Scoping Rules.
diagnostics(shown only whendebugis true):Input:
{ "tenant_name?": string }Prints config path, resolved tenant, normalized MG id, ARM enumeration sample and count, ARG MG coverage sample and count, and the default scoping decision.
arg-tables:Input:
{}Prints an overview of common Azure Resource Graph tables (resourcecontainers, resources, resourcechanges, advisorresources, healthresources, policyresources) with purposes and typical use cases.
arg-examples:Input:
{ "topic?": string }where topic can besubscriptions,resourcegroups,changes,containerchanges,advisor,health, orpolicy.Returns sample KQL snippets for common scenarios across the ARG tables.
KQL Templates (customize queries)
You can edit the KQL used by built-in tools and examples without touching Python code.
Templates live in
src/azure_assistant_mcp/kql/as.mdfiles with a fenced ```kql block (or plain.kqlfiles).At runtime, the server loads these templates. There is no fallback: if a required template is missing, the server raises an error so you can fix it.
Override the template directory by setting
AZURE_ASSISTANT_KQL_PATHto another folder.Examples:
list_subscriptions.mdlist_resource_groups.mduntagged_resource_groups.mdmanual_changes.mdresource_changes_recent.mdstopped_vms.mdgeneric_list_resources.mdCreate your own, e.g.
kubernetes_inventory.md, then run with:run-kql-template { "template_name": "kubernetes_inventory", "params": { ... } }.
Usage Examples
List subscriptions in a tenant by MG:
Tool:
list-subscriptionsInput:
{ "tenant_name": "Contoso" }
Count VMs across all subs in a tenant:
Tool:
ask-azureInput:
{ "tenant_name": "Contoso", "question": "How many virtual machines exist?" }
Run KQL directly across all subs at MG scope:
Tool:
run-arg-kqlInput:
{ "tenant_name": "Contoso", "kql_query": "resourcecontainers | where type =~ 'microsoft.resources/subscriptions' | project name, subscriptionId | order by name asc" }
Security
Do not commit real credentials.
azure-config.jsonis git‑ignored; use the example file as a template.Consider storing secrets in a secure store and templating your config.
Ensure service principals have least privilege for the scopes you query.
Troubleshooting
Seeing only one subscription:
Add a
management_group_idthat contains all target subscriptions, or passsubscription_idsexplicitly.
BadRequestfrom ARG:Check KQL syntax and selected scope. Start with
run-arg-kqlusing a small query andtop.
Validate scope quickly:
Enable
debug: trueand run thediagnosticstool for the tenant.
Development
Code lives in
src/azure_assistant_mcp/. Entry point isazure_assistant_mcp:main.Wrapper script:
azure-assistant-mcp.sh(setsPYTHONPATHand pinsAZURE_ASSISTANT_CONFIG).Backwards-compatibility alias:
azure-assistant.sh(deprecated).Dependencies:
mcp,python-dotenv,azure-identity,azure-mgmt-resourcegraph,azure-mgmt-subscription.
Claude Code
Suggested sub-agent:
Claude_Agents/azure-cloud-architect.md— an Azure cloud architecture helper you can load in Claude Code alongside this MCP server.Getting started:
Copy
Claude_Agents/azure-cloud-architect.mdinto your.claude/agentsfolder
Contributing
Issues and PRs welcome. Please omit real tenant IDs, secrets, or organization names from examples and logs.
License
Licensed under Apache-2.0. See
LICENSEfor full terms.Attribution: This project includes a
NOTICEfile. Per Apache-2.0 §4(d), redistributors must retain the attribution notices inNOTICEin any source distributions and in documentation or about dialogs where such notices normally appear.
Commercial use & sponsorship
Enterprise users are encouraged to attribute the project in documentation or about pages.
If your organization benefits from this project, please consider sponsorship or a commercial support agreement.
Options:
Commercial support/license inquiries: open an issue or contact the maintainer.

remote-capable server
The server can be hosted and run remotely because it primarily relies on remote services or has no dependency on the local environment.
Tools
Enables natural language exploration of Azure environments by generating and executing KQL queries against Azure Resource Graph. Supports multi-tenant configurations, subscription scoping, and provides direct access to Azure resource information through conversational interactions.