Skip to main content
Glama
Azure Cost Management MCP

Azure Cost Management MCP

by bigonil
README.md
# 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

A4.1/5.0

Scored across 9 tools

Disambiguation5/5

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.

Naming Consistency4/5

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.

Tool Count5/5

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.

Completeness4/5

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.

Maintenance

ActivityInactive
ResponsivenessNo recent community issues