Azure Cost Management MCP
# Azure Cost Management MCP Server
MCP (Model Context Protocol) server per l'integrazione con le API di **Azure Cost Management**, allineato alle linee guida **WAF Cost Optimization** e **CAF (Cloud Adoption Framework)** di Microsoft.
Compatibile con **GitHub Copilot Chat**, **Claude Desktop**, e qualsiasi client MCP.
---
## Indice
- [Prerequisiti](#prerequisiti)
- [Installazione](#installazione)
- [Autenticazione Azure](#autenticazione-azure)
- [Configurazione IDE](#configurazione-ide)
- [VS Code + GitHub Copilot Chat](#vs-code--github-copilot-chat)
- [Claude Desktop](#claude-desktop)
- [Cursor](#cursor)
- [Windsurf](#windsurf)
- [Riferimento Scope](#riferimento-scope)
- [Tool disponibili](#tool-disponibili)
- [azure\_cost\_query](#azure_cost_query)
- [azure\_cost\_forecast](#azure_cost_forecast)
- [azure\_cost\_dimensions](#azure_cost_dimensions)
- [azure\_cost\_alerts](#azure_cost_alerts)
- [azure\_budget\_list](#azure_budget_list)
- [azure\_budget\_get](#azure_budget_get)
- [azure\_budget\_create](#azure_budget_create)
- [azure\_budget\_delete](#azure_budget_delete)
- [azure\_advisor\_recommendations](#azure_advisor_recommendations)
- [Esempi d'uso in chat](#esempi-duso-in-chat)
- [RBAC — Ruoli richiesti](#rbac--ruoli-richiesti)
- [Architettura del codice](#architettura-del-codice)
- [Sviluppo](#sviluppo)
---
## Prerequisiti
| Requisito | Versione minima |
|-----------|----------------|
| Node.js | 18.0.0 |
| npm | 9.x |
| Azure CLI (`az`) | qualsiasi — solo per autenticazione locale |
---
## Installazione
```bash
cd azure-cost-management-mcp
npm install
npm run build
```
Il server compilato sarà disponibile in `dist/index.js`.
---
## Autenticazione Azure
Il server usa [`DefaultAzureCredential`](https://learn.microsoft.com/azure/developer/javascript/sdk/credential-chains#use-defaultazurecredential-for-flexibility) dall'SDK `@azure/identity`, che tenta automaticamente le seguenti modalità in ordine:
### Opzione A — Azure CLI (sviluppo locale, consigliata)
```bash
az login
# oppure, per un tenant specifico:
az login --tenant <TENANT_ID>
```
Nessuna variabile d'ambiente necessaria. Il server rileva il token CLI in modo automatico.
### Opzione B — Service Principal (CI/CD, automazione)
Imposta le seguenti variabili d'ambiente (vedi `.env.example`):
```bash
AZURE_TENANT_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
AZURE_CLIENT_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
AZURE_CLIENT_SECRET=your-client-secret
AZURE_SUBSCRIPTION_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx # default subscription
```
### Opzione C — Managed Identity (workload ospitati su Azure)
Nessuna configurazione. `DefaultAzureCredential` rileva l'identità gestita tramite IMDS in modo automatico.
---
## Configurazione IDE
### VS Code + GitHub Copilot Chat
**Metodo 1 — File `.vscode/mcp.json` nel workspace (consigliato)**
Crea o modifica il file `<cartella-workspace>/.vscode/mcp.json`:
```json
{
"servers": {
"azure-cost-management": {
"type": "stdio",
"command": "node",
"args": ["${userHome}/azure-cost-management-mcp/dist/index.js"],
"env": {
"AZURE_SUBSCRIPTION_ID": "${env:AZURE_SUBSCRIPTION_ID}"
}
}
}
}
```
> Se usi `az login`, la sezione `env` può rimanere vuota — `DefaultAzureCredential` usa il token CLI.
> Per Service Principal aggiungi `AZURE_TENANT_ID`, `AZURE_CLIENT_ID`, `AZURE_CLIENT_SECRET`.
**Metodo 2 — Settings utente VS Code (globale)**
Apri `Ctrl+Shift+P` → **Preferences: Open User Settings (JSON)** e aggiungi:
```json
{
"mcp.servers": {
"azure-cost-management": {
"type": "stdio",
"command": "node",
"args": ["C:/Users/<TUO_UTENTE>/azure-cost-management-mcp/dist/index.js"]
}
}
}
```
**Verifica connessione in VS Code:**
1. Apri il pannello **GitHub Copilot Chat** (`Ctrl+Alt+I`)
2. Seleziona modalità **Agent** (`@`)
3. Scrivi: `@azure-cost-management qual è la spesa del mese corrente per la subscription xxx?`
---
### Claude Desktop
Modifica il file di configurazione di Claude Desktop:
- **Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
- **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
```json
{
"mcpServers": {
"azure-cost-management": {
"command": "node",
"args": ["C:/Users/<TUO_UTENTE>/azure-cost-management-mcp/dist/index.js"],
"env": {
"AZURE_SUBSCRIPTION_ID": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
}
}
}
```
Riavvia Claude Desktop dopo la modifica.
---
### Cursor
Crea o modifica `.cursor/mcp.json` nella home utente oppure nella cartella del progetto:
```json
{
"mcpServers": {
"azure-cost-management": {
"command": "node",
"args": ["C:/Users/<TUO_UTENTE>/azure-cost-management-mcp/dist/index.js"],
"env": {
"AZURE_SUBSCRIPTION_ID": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
}
}
}
```
---
### Windsurf
Modifica `~/.codeium/windsurf/mcp_config.json`:
```json
{
"mcpServers": {
"azure-cost-management": {
"command": "node",
"args": ["C:/Users/<TUO_UTENTE>/azure-cost-management-mcp/dist/index.js"],
"env": {
"AZURE_SUBSCRIPTION_ID": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
}
}
}
```
---
## Riferimento Scope
Tutti i tool accettano un parametro `scope` che identifica il livello Azure su cui operare.
| Formato | Esempio | Scope risultante |
|---------|---------|-----------------|
| Path completo | `/subscriptions/aaaa-bbbb` | Subscription |
| Path completo | `/subscriptions/aaaa/resourceGroups/my-rg` | Resource Group |
| UUID nudo | `aaaa-bbbb-cccc-dddd-eeee` | Subscription |
| `sub:{id}` | `sub:aaaa-bbbb` | Subscription |
| `sub:{id}/rg:{name}` | `sub:aaaa/rg:my-rg` | Resource Group |
| `rg:{name}` | `rg:my-rg` | RG nella subscription default (`AZURE_SUBSCRIPTION_ID`) |
| `mg:{id}` | `mg:my-management-group` | Management Group (CAF enterprise) |
| `ba:{id}` | `ba:12345678` | Billing Account (EA/MCA) |
| `ba:{id}/bp:{id}` | `ba:12345/bp:ABCD` | Billing Profile (MCA) |
> **CAF tip:** usa `mg:` per analisi cross-subscription su tutti i landing zone senza dover iterare su ogni subscription singolarmente.
---
## Tool disponibili
### `azure_cost_query`
Interroga i costi effettivi o ammortizzati per uno scope Azure con raggruppamento e filtri temporali.
**Parametri:**
| Parametro | Tipo | Default | Descrizione |
|-----------|------|---------|-------------|
| `scope` | string | — | Scope Azure (vedi [Riferimento Scope](#riferimento-scope)) |
| `type` | `ActualCost` \| `AmortizedCost` | `ActualCost` | `ActualCost`: addebiti pay-as-you-go. `AmortizedCost`: include l'ammortamento di Reserved Instances e Savings Plans |
| `timeframe` | enum | `MonthToDate` | Finestra temporale: `BillingMonth`, `MonthToDate`, `TheLastMonth`, `TheLastBillingMonth`, `WeekToDate`, `Custom` |
| `from` | string (ISO 8601) | — | Data inizio (solo con `timeframe=Custom`) |
| `to` | string (ISO 8601) | — | Data fine (solo con `timeframe=Custom`) |
| `granularity` | `None` \| `Daily` \| `Monthly` | `None` | `None`=totale unico, `Daily`=trend giornaliero, `Monthly`=riepilogo mensile |
| `groupBy` | string[] | `[]` | Dimensioni per il raggruppamento (vedi esempi sotto) |
| `top` | integer (1-1000) | `100` | Numero massimo di righe restituite |
**Valori comuni per `groupBy`:**
```
ResourceGroup ServiceName ResourceType
Location SubscriptionName MeterCategory
MeterSubCategory ChargeType
tag:CostCenter tag:Environment tag:Application
```
---
### `azure_cost_forecast`
Restituisce le previsioni di spesa basate sui trend di utilizzo correnti.
**Parametri:**
| Parametro | Tipo | Default | Descrizione |
|-----------|------|---------|-------------|
| `scope` | string | — | Scope Azure |
| `from` | string (ISO 8601) | — | Data inizio previsione |
| `to` | string (ISO 8601) | — | Data fine previsione |
| `granularity` | `Daily` \| `Monthly` | `Monthly` | Granularità della previsione |
| `includeActualCost` | boolean | `true` | Includi i costi reali per confronto con la previsione |
---
### `azure_cost_dimensions`
Elenca le dimensioni disponibili per raggruppamento e filtro allo scope indicato. Da usare prima di `azure_cost_query` per scoprire i valori validi di `groupBy`.
**Parametri:**
| Parametro | Tipo | Descrizione |
|-----------|------|-------------|
| `scope` | string | Scope Azure |
---
### `azure_cost_alerts`
Elenca gli alert di costo attivi per uno scope: sforamenti budget, avvisi credito, violazioni quota, anomalie.
**Parametri:**
| Parametro | Tipo | Descrizione |
|-----------|------|-------------|
| `scope` | string | Scope Azure |
**Risposta — campi principali:**
```json
{
"total": 2,
"active": 1,
"alerts": [
{
"name": "alert-xxx",
"definitionType": "Budget",
"definitionCategory": "Cost",
"status": "Active",
"creationTime": "2024-01-15T10:30:00Z"
}
]
}
```
---
### `azure_budget_list`
Elenca tutti i budget di costo allo scope con la spesa corrente, le soglie e lo stato.
**Parametri:**
| Parametro | Tipo | Descrizione |
|-----------|------|-------------|
| `scope` | string | Scope Azure (richiede subscription) |
**Stati possibili nel campo `status`:**
| Status | Significato |
|--------|-------------|
| `OK` | Spesa < 80% del budget |
| `WARNING` | Spesa tra 80% e 90% |
| `CRITICAL` | Spesa tra 90% e 100% |
| `EXCEEDED` | Spesa > 100% del budget |
---
### `azure_budget_get`
Recupera i dettagli completi di un budget specifico: spesa corrente, spesa prevista, soglie di notifica e filtri.
**Parametri:**
| Parametro | Tipo | Descrizione |
|-----------|------|-------------|
| `scope` | string | Scope Azure |
| `budgetName` | string | Nome del budget |
---
### `azure_budget_create`
Crea o aggiorna un budget di costo con le soglie di alert raccomandate da WAF. Se esiste già un budget con lo stesso nome nello stesso scope, verrà aggiornato.
**Parametri:**
| Parametro | Tipo | Default | Descrizione |
|-----------|------|---------|-------------|
| `scope` | string | — | Scope Azure (richiede subscription) |
| `name` | string | — | Nome univoco del budget nello scope |
| `amount` | number | — | Importo del budget nella valuta della subscription |
| `timeGrain` | enum | `Monthly` | Periodo di reset: `Monthly`, `Quarterly`, `Annually`, `BillingMonth`, `BillingQuarter`, `BillingAnnually` |
| `startDate` | string (YYYY-MM-DD) | — | Data inizio. Per grain `Monthly` deve essere il primo del mese |
| `endDate` | string (YYYY-MM-DD) | +10 anni | Data fine (opzionale) |
| `contactEmails` | string[] | `[]` | Email da notificare al raggiungimento delle soglie |
| `contactRoles` | string[] | `["Owner","Contributor"]` | Ruoli RBAC da notificare |
| `notifyAt80Percent` | boolean | `true` | Alert WAF: avviso anticipato all'80% della spesa effettiva |
| `notifyAt100Percent` | boolean | `true` | Alert WAF: budget raggiunto al 100% della spesa effettiva |
| `notifyForecastAt100Percent` | boolean | `true` | Alert WAF: previsione che raggiungerà il 100% prima della fine del periodo |
---
### `azure_budget_delete`
Elimina permanentemente un budget. **L'operazione non è reversibile.**
**Parametri:**
| Parametro | Tipo | Descrizione |
|-----------|------|-------------|
| `scope` | string | Scope Azure |
| `budgetName` | string | Nome del budget da eliminare |
---
### `azure_advisor_recommendations`
Recupera le raccomandazioni di Azure Advisor per la categoria Cost Optimization.
Copre: ridimensionamento VM sottoutilizzate, eliminazione risorse idle (dischi non collegati, IP pubblici inutilizzati), acquisto Reserved Instances o Savings Plans per workload prevedibili.
**Parametri:**
| Parametro | Tipo | Default | Descrizione |
|-----------|------|---------|-------------|
| `scope` | string | — | Scope a livello subscription (UUID, `sub:{id}`, o path completo) |
| `impact` | `High` \| `Medium` \| `Low` \| `All` | `All` | Filtra per impatto. `High` = maggior risparmio potenziale |
| `top` | integer (1-500) | `50` | Numero massimo di raccomandazioni |
> **Nota:** Azure Advisor opera solo a livello di subscription. Lo scope `mg:` non è supportato per questo tool.
---
## Esempi d'uso in chat
Questi esempi funzionano sia con GitHub Copilot Chat che con Claude Desktop, Cursor, e Windsurf.
### Analisi spesa corrente
```
Mostrami la spesa del mese corrente per la subscription aaaa-bbbb-cccc,
raggruppata per ServiceName e ordinata per costo decrescente.
```
```
Qual è la spesa degli ultimi 3 mesi raggruppata per ResourceGroup?
Usa il periodo Custom da 2024-01-01 a 2024-03-31 con granularità Monthly.
```
```
Mostrami la ripartizione dei costi per tag:CostCenter e tag:Environment
nella subscription aaaa — voglio fare il chargeback ai team.
```
### Previsioni e anomalie
```
Prevedi la spesa di marzo per la subscription aaaa.
Poi confronta con il budget esistente per capire se siamo a rischio sforamento.
```
```
Ci sono alert di costo attivi nella subscription aaaa?
```
### Gestione budget
```
Elenca tutti i budget nella subscription aaaa con il loro stato attuale.
```
```
Crea un budget mensile da 5000 EUR per il resource group "prod-rg"
nella subscription aaaa, con notifiche a mario@example.com.
```
```
Il budget "monthly-prod" nella subscription aaaa è stato superato?
Mostrami i dettagli e la spesa prevista per fine mese.
```
### Ottimizzazione costi (WAF/CAF)
```
Quali sono le raccomandazioni di Azure Advisor ad alto impatto
per la subscription aaaa? Voglio massimizzare i risparmi.
```
```
Fai un'analisi completa dei costi per il management group "my-mg":
spesa corrente per subscription, alert attivi, e raccomandazioni Advisor.
```
```
Quali dimensioni sono disponibili per il raggruppamento dei costi
nella subscription aaaa? Voglio capire su quali tag posso fare showback.
```
---
## RBAC — Ruoli richiesti
Assegna i ruoli allo scope appropriato (subscription, resource group o management group):
| Operazione | Ruolo minimo richiesto |
|------------|----------------------|
| Leggere costi, forecast, dimensioni, alert | **Cost Management Reader** |
| Leggere budget | **Cost Management Reader** |
| Creare/aggiornare/eliminare budget | **Cost Management Contributor** |
| Raccomandazioni Advisor | **Reader** (a livello subscription) |
**CAF enterprise:** assegna i ruoli a livello di **Management Group** per coprire tutte le subscription dei landing zone con un'unica assegnazione.
```bash
# Esempio: assegnare Cost Management Reader al management group
az role assignment create \
--role "Cost Management Reader" \
--assignee <CLIENT_ID_O_UPN> \
--scope /providers/Microsoft.Management/managementGroups/<MG_ID>
```
---
## Architettura del codice
```
azure-cost-management-mcp/
├── src/
│ ├── index.ts # Entry point MCP server, registrazione tool
│ ├── client.ts # Client Azure singleton + helper scope/risposta
│ ├── tools/
│ │ ├── cost.ts # azure_cost_query, forecast, dimensions, alerts
│ │ ├── budgets.ts # azure_budget_list/get/create/delete
│ │ └── advisor.ts # azure_advisor_recommendations
│ └── __tests__/
│ ├── client.test.ts # Unit test: normalizeScope, transformRows, ecc.
│ └── server.integration.test.ts # Integration test: protocollo MCP
├── dist/ # Output compilato TypeScript (generato da npm run build)
├── package.json
├── tsconfig.json
└── .env.example
```
**Dipendenze principali:**
| Pacchetto | Versione | Uso |
|-----------|---------|-----|
| `@modelcontextprotocol/sdk` | ^1.27.1 | Protocollo MCP, transport stdio |
| `@azure/arm-costmanagement` | 1.0.0-beta.1 | Query costi, forecast, dimensioni, alert |
| `@azure/arm-consumption` | ^9.2.0 | Gestione budget |
| `@azure/arm-advisor` | ^3.2.0 | Raccomandazioni Cost Optimization |
| `@azure/identity` | ^4.13.1 | DefaultAzureCredential (auth unificata) |
| `zod` | ^3.23.0 | Validazione input schema tool |
**Flusso architetturale:**
```
GitHub Copilot / Claude / Cursor
│ MCP (stdio)
▼
src/index.ts (McpServer + StdioServerTransport)
│
src/client.ts (DefaultAzureCredential, singleton client, normalizeScope)
│
┌────┼────────────────────┐
▼ ▼ ▼
Azure Cost Azure Azure
Management Consumption Advisor
API API (Budgets) API
```
---
## Sviluppo
```bash
# Avvia in watch mode (rebuild automatico al salvataggio)
npm run dev
# Verifica tipi senza compilare
npm run typecheck
# Build di produzione
npm run build
# Avvia il server compilato
npm start
# Esegui tutti i test (unit + integration)
npm test
# Solo unit test (client utilities)
npm run test:unit
# Solo integration test (protocollo MCP)
npm run test:integration
```
**Test rapido del server:**
```bash
# Verifica che il server si avvii e risponda al protocollo MCP
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}' \
| node dist/index.js
```
**Lista tool registrati:**
```bash
(
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}'
echo '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}'
) | node dist/index.js
```
TDQS
Scored across 9 tools
Each tool targets a distinct aspect of cost management: querying, forecasting, dimensions, alerts, budget CRUD, and Advisor recommendations. The descriptions clarify boundaries between similar tools like alerts vs. budget list, preventing confusion.
Names follow a consistent prefix pattern (azure_cost_, azure_budget_, azure_advisor_) with mostly verb-based actions (query, forecast, list, get, create, delete). However, 'azure_cost_dimensions' and 'azure_cost_alerts' use noun forms, which is a minor deviation from the verb_noun convention.
Nine tools is well-scoped for an Azure cost management server. Each tool serves a clear purpose without redundancy, covering the essential operations for cost analysis and budget management.
The tool surface covers the core cost management lifecycle: querying, forecasting, alerts, budget CRUD, and recommendations. Minor gaps exist, such as lacking cost export functionality or direct alert configuration, but these are not critical for most workflows.