Skip to main content
Glama
bigonil

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 issues