Skip to main content
Glama
JadenRazo

CloudCost MCP Server

by JadenRazo
README.md
<h1 align="center">CloudCost MCP Server</h1>

<p align="center">
  Multi-cloud cost analysis for Terraform, CloudFormation, Pulumi, and Bicep/ARM. Live AWS/Azure pricing with bundled GCP pricing snapshots.
  <br />
  Built on the <a href="https://modelcontextprotocol.io">Model Context Protocol</a> for seamless AI agent integration.
</p>

<p align="center">
  <a href="https://github.com/jadenrazo/CloudCostMCP/actions/workflows/ci.yml"><img src="https://github.com/jadenrazo/CloudCostMCP/actions/workflows/ci.yml/badge.svg" alt="CI" /></a>
  <a href="https://www.npmjs.com/package/@jadenrazo/cloudcost-mcp"><img src="https://img.shields.io/npm/v/@jadenrazo/cloudcost-mcp.svg" alt="npm version" /></a>
  <a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License: MIT" /></a>
  <img src="https://img.shields.io/badge/node-%3E%3D20-brightgreen" alt="Node.js" />
</p>

<p align="right">
  <img src="https://github.com/user-attachments/assets/7d5f613a-851e-4480-900f-438d13f9a56e" alt="CloudCost MCP demo" width="700" />
</p>

<p align="center">
  <a href="#installation">Installation</a> &nbsp;&bull;&nbsp;
  <a href="#tools">Tools</a> &nbsp;&bull;&nbsp;
  <a href="#how-pricing-works">Pricing</a> &nbsp;&bull;&nbsp;
  <a href="#configuration">Config</a> &nbsp;&bull;&nbsp;
  <a href="#architecture">Architecture</a> &nbsp;&bull;&nbsp;
  <a href="#limitations">Limitations</a>
</p>

---

CloudCost MCP is a [Model Context Protocol](https://modelcontextprotocol.io) server that lets AI agents parse infrastructure-as-code across multiple formats (Terraform, CloudFormation, Pulumi, Bicep/ARM), query pricing data, and generate multi-cloud cost comparison reports. AWS and Azure pricing are queried from public pricing endpoints; GCP pricing is served from bundled snapshots because Google does not provide CloudCost a credential-free live pricing path. No cloud credentials are required.

### What it does

- Parses Terraform HCL files, CloudFormation templates, Pulumi stack exports, and Bicep/ARM templates with automatic format detection
- Extracts resource inventories with variable resolution, including referenced modules and OpenTofu `.tofu` files
- Queries live on-demand pricing from AWS Bulk Pricing CSV and Azure Retail Prices REST API; GCP from a weekly-refreshed bundled snapshot
- Maps equivalent resources across AWS, Azure, and GCP (compute, database, storage, networking, Kubernetes, container registries, secrets management, DNS)
- Generates cost estimates with per-resource breakdowns (monthly and yearly) across multiple currencies
- Compares costs across all three providers side-by-side in markdown, JSON, CSV, or FOCUS format
- Provides optimization recommendations: right-sizing, reserved pricing, provider switching, spot/preemptible instances
- Models hypothetical scenarios (instance type changes, region moves, commitment levels) without modifying Terraform files
- Projects costs over 3, 6, 12, and 36-month horizons with reserved instance comparisons
- Tags resources for cost attribution and groups report output by team, environment, or any custom label
- Posts cost estimate comments to pull requests via a reusable GitHub Actions composite action

### Provider pricing support

| Provider | Pricing source | Support level |
|---|---|---|
| AWS | Live public pricing APIs + bundled fallback tables | Live |
| Azure | Live Retail Prices API + bundled fallback tables | Live |
| GCP | Bundled pricing snapshots + fixed public rates | Supported, but **not live** |

GCP cost estimation still works, but its figures are snapshot-based and should not be described as real-time Google Cloud pricing. See [How Pricing Works](#how-pricing-works) and [Limitations](#limitations) for the freshness model.

### Supported IaC Formats

| Format | Extensions | Auto-detected |
|---|---|---|
| Terraform/OpenTofu | `.tf`, `.tofu` | Yes |
| CloudFormation | `.yaml`, `.yml`, `.json`, `.template` | Yes |
| Pulumi | `.json` (stack export) | Yes |
| Bicep/ARM | `.json` (ARM template) | Yes |

### How this compares to Infracost

Infracost is the mature choice for **Terraform-on-AWS cost estimation in CI** — PR-comment cost deltas, threshold gating, deep Terragrunt support. If that's your workflow, use it.

CloudCostMCP targets a different surface:

- **Agent-native via MCP.** Models call it as a tool *during* generation. `check_cost_budget` returns `allow` / `warn` / `block` with the specific blocking resources named, fast enough on a warm pricing cache for an agent to veto an expensive config before writing it to disk.
- **Multi-IaC in one server.** Terraform, CloudFormation, Pulumi, Bicep/ARM — one tool, not four.
- **Zero cloud credentials.** AWS and Azure pricing use public endpoints; GCP pricing uses bundled snapshots. No account, cloud IAM, or cloud API keys are required.
- **Optimization + what-if scenarios built in.** Right-sizing, reserved-pricing, cross-provider switching, and spot modeling are first-class tools.

The two are complementary. Use Infracost in CI; use CloudCostMCP inside your agent or editor.

---

## Installation

Requires **Node.js 20** or later.

### 60-second quick start (Claude Code)

```bash
npm install -g @jadenrazo/cloudcost-mcp
claude mcp add cloudcost -- cloudcost-mcp
```

Then, inside a project directory with Terraform files, ask Claude:

> *"Use cloudcost to estimate the monthly AWS cost of this Terraform config, then check it against a $2000/month budget with check_cost_budget."*

No API keys, no cloud credentials, no separate account. For other MCP clients (Claude Desktop, Cursor, any MCP-compatible agent), see the detailed setup below.

### All install options

```bash
# From source
git clone https://github.com/jadenrazo/CloudCostMCP.git
cd CloudCostMCP
npm install
npm run build
```

```bash
# Global npm install
npm install -g @jadenrazo/cloudcost-mcp
```

```bash
# One-shot, no install
npx -y @jadenrazo/cloudcost-mcp
```

### Claude Desktop

Add to your Claude Desktop MCP configuration (`claude_desktop_config.json`):

```json
{
  "mcpServers": {
    "cloudcost": {
      "command": "node",
      "args": ["/path/to/CloudCostMCP/dist/index.js"]
    }
  }
}
```

If installed globally via npm:

```json
{
  "mcpServers": {
    "cloudcost": {
      "command": "cloudcost-mcp"
    }
  }
}
```

### Claude Code

```bash
claude mcp add cloudcost -- node /path/to/CloudCostMCP/dist/index.js
```

Or if installed globally via npm:

```bash
claude mcp add cloudcost -- cloudcost-mcp
```

### As a standalone MCP server (stdio)

```bash
node dist/index.js
```

---

## Tools

The server exposes twelve MCP tools. Each accepts JSON input and returns structured JSON output. For agent-centric workflows, `check_cost_budget` is the headline tool: it returns an `allow` / `warn` / `block` verdict fast enough to be called between IaC generation and disk write — see [docs/guardrails.md](./docs/guardrails.md).

Cost-reporting tools (`estimate_cost`, `compare_providers`, `check_cost_budget`, `analyze_plan`, `compare_actual`) also include a `pricing_metadata` block — `{ source, as_of, age_days, staleness }` — describing the vintage of the bundled pricing data behind the numbers (`fresh` < 14 days, `aging` < 45 days, `stale` ≥ 45 days; `compare_providers` reports one block per compared provider). When a non-USD `currency` is requested, responses additionally carry `exchange_rate: { rate, rate_as_of }` — conversions use a static rate snapshot (currently `2026-03`), not a live FX feed.

### `analyze_terraform`

Parse Terraform files and return a resource inventory. Detects the cloud provider, resolves variables (including `tfvars`), and extracts cost-relevant attributes like instance types, storage sizes, and database engines.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `files` | `{path, content}[]` | Yes | Terraform `.tf` files to analyze |
| `tfvars` | `string` | No | Contents of a `terraform.tfvars` file |

### `estimate_cost`

Calculate costs for parsed resources on a specific provider. Returns monthly and yearly breakdowns per resource with confidence scores.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `files` | `{path, content}[]` | Yes | Terraform files |
| `tfvars` | `string` | No | Variable overrides |
| `provider` | `aws \| azure \| gcp` | Yes | Target provider for pricing |
| `region` | `string` | No | Target region (auto-mapped if omitted) |
| `currency` | `string` | No | Output currency (default: `USD`). Supports: USD, EUR, GBP, JPY, CAD, AUD, INR, BRL |

### `compare_providers`

Full pipeline: parse Terraform, map resources across providers, fetch pricing, and produce a comparison report. This is the main entry point for cost analysis.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `files` | `{path, content}[]` | Yes | Terraform files |
| `tfvars` | `string` | No | Variable overrides |
| `format` | `markdown \| json \| csv \| focus` | No | Report format (default: `markdown`) |
| `providers` | `string[]` | No | Providers to compare (default: all three) |
| `currency` | `string` | No | Output currency (default: `USD`). Supports: USD, EUR, GBP, JPY, CAD, AUD, INR, BRL |

### `get_equivalents`

Look up the equivalent Terraform resource type and instance size across providers. Useful for migration planning.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `resource_type` | `string` | Yes | Terraform resource type (e.g., `aws_instance`) |
| `source_provider` | `aws \| azure \| gcp` | Yes | Provider the resource belongs to |
| `target_provider` | `aws \| azure \| gcp` | No | Specific target (omit for all) |
| `instance_type` | `string` | No | Instance type to also map (e.g., `t3.large`) |

### `get_pricing`

Direct pricing lookup. Returns the normalized unit price with metadata for a specific resource on a specific provider.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `provider` | `aws \| azure \| gcp` | Yes | Cloud provider |
| `service` | `compute \| database \| storage \| network \| kubernetes` | Yes | Service category |
| `resource_type` | `string` | Yes | Instance type, storage type, etc. |
| `region` | `string` | Yes | Cloud region |

### `optimize_cost`

Analyze Terraform resources and return optimization recommendations. Includes right-sizing suggestions, reserved instance comparisons, and cross-provider savings opportunities.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `files` | `{path, content}[]` | Yes | Terraform files |
| `tfvars` | `string` | No | Variable overrides |
| `providers` | `string[]` | No | Providers to evaluate (default: all three) |

### `what_if`

Run hypothetical pricing scenarios against existing Terraform resources. Change instance types, regions, providers, or commitment levels and see the cost delta without modifying your actual configuration.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `files` | `{path, content}[]` | Yes | Terraform files |
| `tfvars` | `string` | No | Variable overrides |
| `scenarios` | `object[]` | Yes | Changes to model. Each specifies a resource name and the attributes to override |
| `providers` | `string[]` | No | Providers to evaluate (default: all three) |
| `currency` | `string` | No | Output currency (default: `USD`) |

**Example**: model the cost impact of switching compute from on-demand to spot across providers:

```json
{
  "files": [{ "path": "main.tf", "content": "..." }],
  "scenarios": [
    { "resource": "aws_instance.web", "pricing_model": "spot" },
    { "resource": "aws_instance.app", "instance_type": "m6i.2xlarge" }
  ]
}
```

### `analyze_plan`

Parse terraform plan JSON output for before/after cost-of-change analysis. Shows what resources are being added, changed, or destroyed and the cost impact of each change.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `plan_json` | `string` | Yes | JSON output from `terraform show -json planfile` |
| `provider` | `aws \| azure \| gcp` | No | Target provider for pricing (auto-detected if omitted) |
| `currency` | `string` | No | Output currency (default: `USD`) |

### `compare_actual`

Parse `.tfstate` files to compare actual infrastructure costs vs estimates. Identifies drift between planned and deployed resources.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `state_json` | `string` | Yes | Contents of a `terraform.tfstate` file |
| `provider` | `aws \| azure \| gcp` | No | Target provider for pricing (auto-detected if omitted) |
| `currency` | `string` | No | Output currency (default: `USD`) |

### `price_trends`

Query historical pricing trends and price change tracking. Shows how pricing has changed over time for specific resource types.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `provider` | `aws \| azure \| gcp` | Yes | Cloud provider |
| `service` | `string` | Yes | Service category |
| `resource_type` | `string` | Yes | Instance type, storage type, etc. |
| `region` | `string` | Yes | Cloud region |
| `period_days` | `number` | No | Lookback period in days (default: `90`) |

### `detect_anomalies`

Cost anomaly detection with budget checks, price changes, concentration risk, and right-sizing hints. Analyzes parsed resources and flags potential cost issues.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `files` | `{path, content}[]` | Yes | IaC files to analyze |
| `tfvars` | `string` | No | Variable overrides |
| `provider` | `aws \| azure \| gcp` | No | Target provider (auto-detected if omitted) |
| `budget_monthly` | `number` | No | Monthly budget cap in USD |
| `currency` | `string` | No | Output currency (default: `USD`) |

### `check_cost_budget`

Fast cost-safety guardrail designed for AI agents. Returns `allow` / `warn` / `block` with the specific blocking resources named, so an agent can veto an expensive IaC generation before writing it to disk. Thresholds cascade: per-call params → `CLOUDCOST_GUARDRAIL_*` env → `CLOUDCOST_BUDGET_*` env. See [docs/guardrails.md](./docs/guardrails.md) for integration patterns.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `files` | `{path, content}[]` | Yes | IaC files to evaluate |
| `tfvars` | `string` | No | Variable overrides |
| `provider` | `aws \| azure \| gcp` | No | Target provider (auto-detected if omitted) |
| `region` | `string` | No | Target region (auto-detected if omitted) |
| `currency` | `string` | No | Output currency (default: `USD`) |
| `max_monthly` | `number` | No | Aggregate monthly threshold. Over = `block`. |
| `max_per_resource` | `number` | No | Per-resource threshold. One over = `block`. |
| `warn_ratio` | `number` (0–1) | No | Fraction of limit that triggers `warn` (default `0.8`) |

---

## How Pricing Works

CloudCost uses a tiered approach to get the most accurate pricing available without requiring any API keys or credentials. That constraint is real and it has a cost: where a provider has closed off anonymous access, CloudCost ships a snapshot instead of pretending to query live. See the GCP section below.

### AWS

1. **Live CSV streaming** (primary). For EC2 compute pricing, the server streams the AWS Bulk Pricing CSV for the target region line-by-line. This avoids loading the full ~267 MB file into memory. All on-demand compute prices for the region are extracted in a single pass and cached in SQLite for 24 hours. Concurrent requests for the same region share a single download.

2. **Live JSON API** (secondary). For RDS (~24 MB), S3, ELB, and VPC, the server fetches regional JSON from the [AWS Price List Bulk API](https://pricing.us-east-1.amazonaws.com/offers/v1.0/aws/index.json). These files are small enough to parse directly.

3. **Fallback tables + interpolation**. If live fetching fails (network issues, timeouts), the server falls back to built-in pricing tables covering 85+ EC2 and 29 RDS instance types. A size-interpolation algorithm estimates prices for unlisted sizes within known families by following AWS's predictable doubling pattern (e.g., `large` to `xlarge` doubles the price).

### Azure

1. **Live REST API** (primary). Queries the [Azure Retail Prices API](https://prices.azure.com/api/retail/prices) with OData filters for exact SKU matching (`armSkuName`). Fast, free, unauthenticated. Returns precise per-SKU pricing. Results are paginated and fully consumed.

2. **Fallback tables + interpolation**. If the API is unreachable, falls back to built-in tables covering 40+ VM sizes and 14 database tiers. A vCPU-proportional interpolation algorithm estimates prices for unlisted sizes.

### GCP

**GCP has no live path, and this is a limitation rather than a design choice.** Google has retired every key-free bulk pricing source it used to publish, and `cloudbilling.googleapis.com` answers unregistered callers with `403 PERMISSION_DENIED`. Since CloudCost ships no credentials, GCP prices come from bundled data.

1. **Bundled pricing data** (only path). Served from `data/gcp-pricing/`, which ships with the package. Covers Compute Engine machine types, Cloud SQL tiers, Cloud Storage classes and Persistent Disk types across 37 regions. Every GCP price is tagged `pricing_source: "bundled"` and carries its vintage in `pricing_metadata`.

2. **How it stays current.** `.github/workflows/refresh-pricing.yml` rebuilds the Compute Engine, Persistent Disk and Cloud Storage tables weekly from [gcosts](https://github.com/Cyclenerd/google-cloud-pricing-cost-calculator) (Apache-2.0), a weekly regeneration of the Cloud Billing Catalog. The recorded `last_updated` is that snapshot's own generation date, not the date our job ran. Cloud SQL is not covered by that source and remains hand-curated; `check-freshness.ts` reports it separately.

3. **Infrastructure services**. Load balancer, Cloud NAT, and GKE pricing use fixed public rates. GKE Autopilot is an approximation: it is billed per-pod across vCPU, memory and ephemeral storage, and the bundled figure is a per-vCPU/hour estimate.

### Pricing Source Transparency

Every price returned includes a `pricing_source` attribute indicating its origin:
- `"live"`: fetched from a public API in real time
- `"fallback"`: from built-in tables (approximate, but reasonable for estimates)
- `"bundled"`: from bundled data files shipped with the package

All pricing data is cached in a local SQLite database (`~/.cloudcost/cache.db`) with a 24-hour TTL to minimize redundant API calls.

---

## Example

Given this Terraform config:

```hcl
# infrastructure.tf
resource "aws_instance" "web" {
  count         = 3
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t3.xlarge"
}

resource "aws_instance" "app" {
  count         = 2
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "m5.2xlarge"
}

resource "aws_db_instance" "primary" {
  instance_class    = "db.r6g.xlarge"
  engine            = "postgres"
  allocated_storage = 200
}

resource "aws_ebs_volume" "data" {
  count = 5
  size  = 500
  type  = "gp3"
}

resource "aws_s3_bucket" "assets" {}

resource "aws_lb" "main" {
  load_balancer_type = "application"
}

resource "aws_nat_gateway" "main" {}

resource "aws_eks_cluster" "main" {
  name = "prod"
}
```

Running `compare_providers` against that config produces:

```
| Category        | AWS (USD/mo) | Azure (USD/mo) | GCP (USD/mo) |
|-----------------|-------------|----------------|--------------|
| Compute         |   $1,176.48 |      $1,209.60 |    $1,142.88 |
| Database        |     $314.64 |        $297.12 |      $285.48 |
| Storage         |      $48.00 |         $52.80 |       $44.00 |
| Load Balancer   |      $16.20 |         $18.00 |       $18.26 |
| NAT Gateway     |      $32.40 |         $32.40 |       $31.68 |
| Kubernetes      |      $72.00 |         $72.00 |       $72.00 |
| **Total**       | **$1,659.72** | **$1,681.92** | **$1,594.30** |
```

*Prices are on-demand estimates. Actual costs vary by usage, region, and commitment level.*

---

## Configuration

All configuration is optional. The server works out of the box with sensible defaults.

### Environment Variables

| Variable | Default | Description |
|----------|---------|-------------|
| `CLOUDCOST_CACHE_TTL` | `86400` | Cache TTL in seconds (24 hours) |
| `CLOUDCOST_CACHE_PATH` | `~/.cloudcost/cache.db` | SQLite cache file location |
| `CLOUDCOST_LOG_LEVEL` | `info` | Log level: `debug`, `info`, `warn`, `error` |
| `CLOUDCOST_MONTHLY_HOURS` | `730` | Hours per month for cost calculations |
| `CLOUDCOST_INCLUDE_DATA_TRANSFER` | `true` | Include a synthetic default estimate of 100 GB/month internet egress per provider+region. Its share of the total is surfaced separately as `estimated_egress_monthly` (still included in `total_monthly`) |
| `CLOUDCOST_PRICING_MODEL` | `on_demand` | Default pricing model: `on_demand`, `spot`, or `reserved` |
| `CLOUDCOST_RESOLVE_MODULES` | `true` | Expand referenced Terraform modules during parsing |
| `CLOUDCOST_BUDGET_MONTHLY` | | Monthly budget cap in USD. Triggers a warning when exceeded |
| `CLOUDCOST_BUDGET_PER_RESOURCE` | | Per-resource monthly budget cap in USD |
| `CLOUDCOST_BUDGET_WARN_PCT` | `80` | Percentage of budget at which a warning is surfaced (default: 80%) |
| `CLOUDCOST_GUARDRAIL_MAX_MONTHLY` | | Aggregate monthly ceiling for `check_cost_budget`. Over = `block` verdict |
| `CLOUDCOST_GUARDRAIL_MAX_PER_RESOURCE` | | Per-resource ceiling for `check_cost_budget`. One over = `block` verdict |
| `CLOUDCOST_GUARDRAIL_WARN_RATIO` | `0.8` | Fraction of guardrail threshold that triggers `warn` instead of `allow` |

### Config File

You can also create `~/.cloudcost/config.json`:

```json
{
  "cache": {
    "ttl_seconds": 43200,
    "db_path": "/tmp/cloudcost-cache.db"
  },
  "pricing": {
    "monthly_hours": 730,
    "default_currency": "USD"
  },
  "logging": {
    "level": "debug"
  }
}
```

Configuration priority: environment variables > config file > built-in defaults.

---

## Architecture

```
                        ┌───────────────────────────────┐
                        │          MCP Client           │
                        │   (Claude Desktop / Agent)    │
                        └──────────────┬────────────────┘
                                       │ stdio
                        ┌──────────────▼────────────────┐
                        │     CloudCost MCP Server      │
                        │        (src/server.ts)        │
                        └──────────────┬────────────────┘
                                       │
              ┌────────────────────────┼───────────────────────┐
              │                        │                       │
    ┌─────────▼─────────┐    ┌─────────▼─────────┐   ┌─────────▼─────────┐
    │   Tool Handlers   │    │   HCL Parsers     │   │   Cost Engine     │
    │ (src/tools/*.ts)  │    │  (src/parsers/)   │   │ (src/calculator/) │
    └─────────┬─────────┘    └───────────────────┘   └─────────┬─────────┘
              │                                                │
    ┌─────────▼────────────────────────────────────────────────▼─────────┐
    │                       PricingEngine (router)                       │
    │                  (src/pricing/pricing-engine.ts)                   │
    └──────┬───────────────────┬─────────────────────┬───────────────────┘
           │                   │                     │
  ┌────────▼───────┐  ┌────────▼───────┐    ┌────────▼───────┐
  │  AWS Bulk      │  │  Azure Retail  │    │  GCP Bundled   │
  │  Loader        │  │  Client        │    │  Loader        │
  │  (CSV + JSON)  │  │  (REST API)    │    │  (static JSON) │
  └────────┬───────┘  └────────┬───────┘    └────────┬───────┘
           │                   │                     │
           ▼                   ▼                     ▼
  AWS Bulk Pricing   Azure Retail API       data/gcp-pricing/
  CSV (public)       (public, no auth)      (bundled files)
```

Highlights: no cloud credentials required; AWS and Azure use public pricing endpoints, while GCP uses bundled pricing snapshots and fixed public rates. SQLite-backed caching is used by live/fallback pricing paths, AWS bulk CSV ingest is streamed, and every response carries `pricing_source` and `confidence` so callers can distinguish live quotes from bundled or fallback estimates. Full layer-by-layer walkthrough and extension guides in [docs/architecture.md](./docs/architecture.md).

---

## Supported Resources

| Category | AWS | Azure | GCP |
|----------|-----|-------|-----|
| **Compute** | `aws_instance` | `azurerm_virtual_machine`, `azurerm_linux_virtual_machine` | `google_compute_instance` |
| **Database** | `aws_db_instance`, `aws_rds_cluster` | `azurerm_postgresql_flexible_server`, `azurerm_mysql_flexible_server` | `google_sql_database_instance` |
| **Storage** | `aws_ebs_volume`, `aws_s3_bucket` | `azurerm_managed_disk`, `azurerm_storage_account` | `google_compute_disk`, `google_storage_bucket` |
| **Network** | `aws_lb`, `aws_nat_gateway` | `azurerm_lb`, `azurerm_nat_gateway` | `google_compute_forwarding_rule` |
| **Kubernetes** | `aws_eks_cluster` | `azurerm_kubernetes_cluster` | `google_container_cluster` |
| **Container Registries** | `aws_ecr_repository` | `azurerm_container_registry` | `google_artifact_registry_repository` |
| **Secrets Management** | `aws_secretsmanager_secret` | `azurerm_key_vault` | `google_secret_manager_secret` |
| **DNS** | `aws_route53_zone` | `azurerm_dns_zone` | `google_dns_managed_zone` |
| **API Gateway** | `aws_api_gateway_rest_api`, `aws_apigatewayv2_api` | `azurerm_api_management` | `google_api_gateway_api` |
| **WAF** | `aws_wafv2_web_acl` | `azurerm_web_application_firewall_policy` | |
| **OpenSearch** | `aws_opensearch_domain` | | |
| **Messaging** | `aws_sns_topic`, `aws_mq_broker` | `azurerm_servicebus_namespace`, `azurerm_eventhub_namespace` | `google_pubsub_topic` |
| **ML/AI** | `aws_sagemaker_endpoint`, `aws_sagemaker_notebook_instance` | | `google_vertex_ai_endpoint` |

Instance type mapping covers 70+ AWS instance types (including Graviton/ARM families: m6g, m7g, c6g, c7g, r6g, r7g, t4g), 40+ Azure VM sizes, and 20+ GCP machine types with full bidirectional cross-provider mapping.

---

## Limitations

- **On-demand pricing only** by default. Prices reflect pay-as-you-go rates. The `optimize_cost` tool recommends reserved instances; AWS Savings Plans are not yet supported (tracked in [docs/roadmap.md](./docs/roadmap.md)). Pass `pricing_model: "spot"` in `what_if` scenarios to model spot/preemptible pricing.
- **GCP pricing is always bundled.** There is no live GCP path: `cloudbilling.googleapis.com` rejects unauthenticated callers and CloudCost ships no credentials. The bundled tables are rebuilt weekly (see *How Pricing Works > GCP*), and every GCP figure reports its own vintage, but they are a snapshot rather than a live quote.
- **Fallback-data signaling.** When a live pricing API is unreachable and `estimate_cost` / `compare_providers` / `get_pricing` serve data from bundled or fallback tables, the response includes a `warnings` entry ("using fallback/bundled pricing data for …") so callers can flag stale estimates. AWS and Azure bundled tables are re-verified weekly via CI; the GCP tables are rebuilt weekly from an upstream snapshot. Datasets no automation covers (GCP Cloud SQL, AWS EBS, Azure disk and database tables) are listed under `curated_datasets` in each `data/*-pricing/metadata.json` and reported by `scripts/check-freshness.ts`.
- **Synthetic egress line item.** Unless `CLOUDCOST_INCLUDE_DATA_TRANSFER=false`, every breakdown includes an assumed 100 GB/month of internet egress per provider+region. `total_monthly` includes it (unchanged behavior); its share is reported separately as `estimated_egress_monthly` with an explanatory warning so the composition is visible.
- **Static FX rates.** Non-USD output is converted with a bundled rate table, not a live feed. Every converted response carries `exchange_rate: { rate, rate_as_of }` so consumers know which snapshot produced the figures.
- **First request latency**. The initial EC2 pricing lookup for a new AWS region may take 30-120 seconds as the CSV file is streamed. Subsequent lookups for the same region are instant (cached for 24 hours).
- **Specialty instance types**. GPU instances (p4d, g5, etc.), high-memory (x2idn), and bare-metal types may fall back to interpolated pricing if not in the built-in tables and live fetch fails.

---

## More docs

- **[docs/guardrails.md](./docs/guardrails.md)** — `check_cost_budget` integration patterns for Claude Code, Cursor, and other agents.
- **[docs/architecture.md](./docs/architecture.md)** — internal layers, design decisions, extension guides.
- **[docs/ci-integration.md](./docs/ci-integration.md)** — GitHub Actions cost-estimate composite action for PR comments.
- **[docs/development.md](./docs/development.md)** — local setup, npm scripts, source layout.
- **[docs/troubleshooting.md](./docs/troubleshooting.md)** — `$0` estimates, slow first request, cache issues, fallback warnings.
- **[docs/roadmap.md](./docs/roadmap.md)** — what's shipped, in flight, backlog, and explicitly not planned.
- **[VERSIONING.md](./VERSIONING.md)** — SemVer-locked public surface and support policy.
- **[CONTRIBUTING.md](./CONTRIBUTING.md)** — PR guidelines and code style.
- **[SECURITY.md](./SECURITY.md)** — vulnerability reporting.

---

## License

MIT. See [LICENSE](LICENSE) for details.