@jadenrazo/cloudcost-mcp 1.2.1 → 1.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +143 -0
- package/README.md +24 -12
- package/data/aws-pricing/metadata.json +22 -2
- package/data/azure-pricing/metadata.json +297 -2
- package/data/gcp-pricing/cloud-storage.json +222 -16
- package/data/gcp-pricing/compute-engine.json +2051 -253
- package/data/gcp-pricing/metadata.json +19 -5
- package/data/gcp-pricing/persistent-disk.json +222 -16
- package/dist/{chunk-CGMU4ETN.js → chunk-4P3I7BSL.js} +73 -664
- package/dist/{chunk-LWTVE7UY.js → chunk-R2BI5AVN.js} +13 -7
- package/dist/cli.js +2 -2
- package/dist/index.js +2 -2
- package/dist/{loader-CMBV7346.js → loader-G7WW74B6.js} +2 -2
- package/package.json +12 -10
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,142 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/), and this
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [1.2.2] - 2026-10-07
|
|
10
|
+
|
|
11
|
+
### Security
|
|
12
|
+
|
|
13
|
+
- Patch the MCP SDK OAuth issuer advisory and transitive proxy-addr,
|
|
14
|
+
fast-uri and ip-address advisories using compatible dependency updates.
|
|
15
|
+
Also patch development-only brace-expansion and source-map-js advisories.
|
|
16
|
+
Both production and full dependency audits pass at release verification.
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
|
|
20
|
+
- Select refresh liveness from the current workflow's paginated REST history
|
|
21
|
+
by branch and creation time, with diagnostics. A hosted health query had
|
|
22
|
+
selected an 85-day-old failure despite newer successful refreshes.
|
|
23
|
+
- Restore completed provider verification through the established refresh
|
|
24
|
+
pipeline while preserving the 21-day freshness gate. Record source vintage,
|
|
25
|
+
response SHA-256, retrieval time and completed verification separately.
|
|
26
|
+
- Refuse to certify interrupted AWS streams, invalid or expired GCP snapshots,
|
|
27
|
+
insufficient source coverage and failed generated fallback validation.
|
|
28
|
+
- Recover a scheduled refresh that never acquired a hosted runner with at most
|
|
29
|
+
one narrowly scoped retry. Retain acquisition diagnostics, preserve branch
|
|
30
|
+
protections, and keep Actions write isolated from provider retrieval.
|
|
31
|
+
- Scope refresh liveness to the branch being checked so another branch's preview
|
|
32
|
+
cannot certify main. Add preview and recovery probes that do not update pricing PRs
|
|
33
|
+
or issues. The GitHub cost-estimate Action now installs this release.
|
|
34
|
+
|
|
35
|
+
- **Live AWS EC2 pricing selected order-dependent duplicate rows.** The bulk
|
|
36
|
+
catalog contains several Shared/Used/Linux rows for some instance types,
|
|
37
|
+
including licensed variants. The loader overwrote one cache key for every
|
|
38
|
+
match, so the last row won: `t3.micro`, `m6i.large`, and `t3.medium` were
|
|
39
|
+
overstated by 2.6x to 7.5x. It now keeps the lowest qualifying on-demand row,
|
|
40
|
+
applies identical filters to the final unterminated CSV line, and has a
|
|
41
|
+
duplicate-row regression test. See [the incident review](./docs/incidents/2026-08-pricing-drift.md).
|
|
42
|
+
|
|
43
|
+
- **Azure Linux VM selection could fall through to a Windows price.** Azure's
|
|
44
|
+
current `skuName` uses `Standard_D2s_v5`, while the selector expected a
|
|
45
|
+
space-separated shape. When exact matching failed, sorted fallback order
|
|
46
|
+
selected the $0.188/hr Windows row instead of the $0.096/hr Linux row. SKU
|
|
47
|
+
comparison is now punctuation-insensitive, prefers canonical `armSkuName`,
|
|
48
|
+
and preserves the requested OS.
|
|
49
|
+
|
|
50
|
+
- **Pricing drift coverage existed but never ran in Health.** The daily workflow
|
|
51
|
+
now runs the full golden-range suite, catalog misses fail instead of reporting
|
|
52
|
+
a green skip, and the reviewed `p4d.24xlarge` range reflects the live
|
|
53
|
+
$21.9576/hr rate observed on 2026-08-30.
|
|
54
|
+
|
|
55
|
+
- **GCP pricing had not refreshed since 2026-04-15.** `scripts/refresh-pricing.ts`
|
|
56
|
+
read `gstatic.com/cloud-site-ux/pricing/data/gcp-compute.json`, an undocumented
|
|
57
|
+
Google asset that has returned 404 since before the first scheduled run on
|
|
58
|
+
2026-04-20. All 16 scheduled refreshes failed; the GCP fetcher never once
|
|
59
|
+
succeeded. Bundled GCP data is now rebuilt weekly from the
|
|
60
|
+
[gcosts](https://github.com/Cyclenerd/google-cloud-pricing-cost-calculator)
|
|
61
|
+
snapshot of the Cloud Billing Catalog (Apache-2.0), which also extends
|
|
62
|
+
coverage from 17 regions to 37.
|
|
63
|
+
|
|
64
|
+
- **GCP compute prices were reconstructed, and the reconstruction was wrong for
|
|
65
|
+
newer families.** The old refresh derived every instance price as
|
|
66
|
+
`vcpus * coreRate + memGb * memRate`. That collapsed c3 and c4 to identical
|
|
67
|
+
prices in all 102 region/shape pairs, which they are not. The new source ships
|
|
68
|
+
assembled per-instance rates, so the derivation is gone. 944 of 1,197 existing
|
|
69
|
+
values are unchanged; the 253 that moved are corrections in the c2d, c3, c4 and
|
|
70
|
+
n4 families. `c2d-standard-4` and `c2d-standard-8` shipped in the data file but
|
|
71
|
+
were absent from the refresh allow-list, so nothing had ever refreshed them.
|
|
72
|
+
|
|
73
|
+
- **Cloud Storage regional prices were multiplier-derived, not real.**
|
|
74
|
+
`asia-southeast1` was recorded as pricier than `us-central1`; both are in the
|
|
75
|
+
same $0.020 Standard tier. Two tests asserted the incorrect ordering and now
|
|
76
|
+
assert against a region that genuinely differs.
|
|
77
|
+
|
|
78
|
+
- **The live GCP path could not work, and would have been harmful if it had.**
|
|
79
|
+
`CloudBillingClient` queried `cloudbilling.googleapis.com`, which answers
|
|
80
|
+
unregistered callers with `403 PERMISSION_DENIED`, so every uncached GCP lookup
|
|
81
|
+
paid a guaranteed-failing round trip before serving bundled data. Worse, its
|
|
82
|
+
compute path returned the per-vCPU "Instance Core" SKU as the whole-instance
|
|
83
|
+
price: an `e2-standard-2` would have priced at roughly $0.021/hr against a true
|
|
84
|
+
$0.067/hr, and live was preferred over bundled. The 403 was the only thing
|
|
85
|
+
preventing a silent ~3x under-estimate on every machine type. The client is
|
|
86
|
+
removed and `GcpProvider` is bundled-only.
|
|
87
|
+
|
|
88
|
+
- **The GCP smoke test was built to skip on the only failure it could see.**
|
|
89
|
+
`fetchComputeSkus` returns `null` on any error, and the test read `null` as an
|
|
90
|
+
"upstream catalog miss" and called `ctx.skip()`. A hard 403 was reported as a
|
|
91
|
+
green skip, which is why the daily health check scored "live provider APIs: ok"
|
|
92
|
+
throughout the outage. It now probes the source the refresh actually depends
|
|
93
|
+
on, imported rather than retyped, and a non-2xx fails.
|
|
94
|
+
|
|
95
|
+
- **The health check asked whether the refresh ran, not whether it worked.**
|
|
96
|
+
`health.yml` requested the last run's `conclusion` and used only `createdAt`,
|
|
97
|
+
so sixteen consecutive failures scored a healthy `LOOP=0`. It now evaluates the
|
|
98
|
+
conclusion, and an unparseable timestamp reports as unknown instead of being
|
|
99
|
+
mislabelled as "has not run recently".
|
|
100
|
+
|
|
101
|
+
- **AWS and Azure could have rotted the same way, silently.** Their fetch helpers
|
|
102
|
+
return empty maps on failure, every SKU falls through to "no live data", and
|
|
103
|
+
the metadata was stamped with today's date regardless - no failed run, no issue.
|
|
104
|
+
Both now refuse to stamp when live coverage falls below 80% of known SKUs. GCP
|
|
105
|
+
was only ever loud because its fetcher happened to return before the stamp.
|
|
106
|
+
|
|
107
|
+
- **The weekly refresh PR deadlocked every Monday.** `create-pull-request` was
|
|
108
|
+
passed no `token:`, so it force-pushed as `github-actions[bot]`; under this
|
|
109
|
+
repo's `first_time_contributors` approval policy those runs park at
|
|
110
|
+
`action_required` with zero jobs allocated. PR #38 sat that way for six days.
|
|
111
|
+
The workflow now mints a scoped GitHub App token when one is configured, and
|
|
112
|
+
falls back to the previous behaviour when it is not.
|
|
113
|
+
|
|
114
|
+
### Changed
|
|
115
|
+
|
|
116
|
+
- **`metadata.json` carries two dates and a policy.** `last_updated` is the
|
|
117
|
+
vintage of the numbers, `last_verified` is when the refresh loop last completed,
|
|
118
|
+
and `refresh_policy` is `automated` or `curated`. One date was doing the work of
|
|
119
|
+
two: for GCP it was real vintage, for AWS/Azure an unconditional heartbeat, and
|
|
120
|
+
one 21-day threshold was applied to both. `curated_datasets` now names the
|
|
121
|
+
tables no automation refreshes (GCP Cloud SQL, AWS EBS, Azure disk/database),
|
|
122
|
+
which the automated stamp used to silently re-certify as fresh.
|
|
123
|
+
`pricing_metadata` reports the older of the two dates, never the flattering one.
|
|
124
|
+
|
|
125
|
+
- **`refresh_policy` is finally written.** `check-freshness.ts` has read the field
|
|
126
|
+
since it was created but nothing set it, so every row printed
|
|
127
|
+
`refresh=unspecified` and the gate could not tell a dead loop from overdue
|
|
128
|
+
curation.
|
|
129
|
+
|
|
130
|
+
- **CI.** `fail-fast: false` on the test matrix (a formatting nit in one file
|
|
131
|
+
cancelled the Node 20 leg and destroyed its signal); Node 24.15.0 added to the
|
|
132
|
+
matrix, since that is the version that actually ships; `npm run format:check`
|
|
133
|
+
instead of a direct prettier call, so CI and the documented local gate cannot
|
|
134
|
+
drift; `build-artifact` restricted to `main`, where it is not duplicating a
|
|
135
|
+
build the matrix already ran three times.
|
|
136
|
+
|
|
137
|
+
- **`cost-estimate-example.yml` moved to `examples/`.** Its first line said it was
|
|
138
|
+
a file to copy; GitHub registered and ran it on every pull request anyway. The
|
|
139
|
+
composite action's self-install pin moved from 1.0.1 to 1.2.1.
|
|
140
|
+
|
|
141
|
+
- **README.** Corrected the claims that GCP pricing is fetched live from the Cloud
|
|
142
|
+
Billing Catalog API using "unauthenticated public endpoints", and that bundled
|
|
143
|
+
data is refreshed weekly - true for AWS and Azure, false for GCP for 128 days.
|
|
144
|
+
|
|
9
145
|
## [1.2.1] - 2026-08-07
|
|
10
146
|
|
|
11
147
|
### Fixed
|
|
@@ -83,11 +219,13 @@ Hardened the MCP tool surface against the attack classes catalogued in the OWASP
|
|
|
83
219
|
First stable release. No breaking API changes from 0.5 — this version ratifies the existing surface as SemVer-locked. See [`VERSIONING.md`](./VERSIONING.md#migration-notes) for details.
|
|
84
220
|
|
|
85
221
|
### Added
|
|
222
|
+
|
|
86
223
|
- **`VERSIONING.md`**: Formal stability contract defining the SemVer-locked public surface (12 MCP tools, CLI binaries, package entry points), the change-classification policy, and the 0.x → 1.0 migration notes. (At release this lived in two files, `STABILITY.md` and `MIGRATION.md`; they were later consolidated.)
|
|
87
224
|
- **Smoke integration tests**: Live-API smoke coverage for AWS Bulk Pricing, Azure Retail Prices, and GCP Cloud Billing Catalog, gated behind `RUN_INTEGRATION=1`. New `integration-smoke` CI job runs on manual dispatch and weekly schedule (Mondays 12:00 UTC).
|
|
88
225
|
- **Publish workflow gates**: `npm audit --audit-level=high` and `npm test` now run before `npm publish`, preventing broken or vulnerable releases.
|
|
89
226
|
|
|
90
227
|
### Security
|
|
228
|
+
|
|
91
229
|
- Resolved transitive advisories via npm `overrides`:
|
|
92
230
|
- `hono` → `^4.12.12` (GHSA-26pp-8wgv-hjvm, GHSA-r5rp-j6wh-rvv4, GHSA-xf4j-xp2r-rqqx, GHSA-wmmm-f939-6g9c, GHSA-xpcf-pg52-r92g)
|
|
93
231
|
- `@hono/node-server` → `^1.19.13` (GHSA-92pp-h63x-v22m)
|
|
@@ -96,11 +234,13 @@ First stable release. No breaking API changes from 0.5 — this version ratifies
|
|
|
96
234
|
- `npm audit --audit-level=high` now reports zero vulnerabilities.
|
|
97
235
|
|
|
98
236
|
### Packaging
|
|
237
|
+
|
|
99
238
|
- `VERSIONING.md` and `CHANGELOG.md` are now included in the published npm tarball. (Originally shipped as `STABILITY.md` + `MIGRATION.md`, now merged.)
|
|
100
239
|
|
|
101
240
|
## [0.4.0] - 2026-03-28
|
|
102
241
|
|
|
103
242
|
### Added
|
|
243
|
+
|
|
104
244
|
- **Multi-IaC support**: CloudFormation (JSON/YAML), Pulumi (stack export), and Bicep/ARM template parsing via unified `IaCParser` interface with auto-format detection
|
|
105
245
|
- **`analyze_plan` tool**: Parse `terraform plan -json` output for precise before/after cost-of-change analysis
|
|
106
246
|
- **`compare_actual` tool**: Parse `.tfstate` files to compare actual infrastructure costs against estimates
|
|
@@ -120,6 +260,7 @@ First stable release. No breaking API changes from 0.5 — this version ratifies
|
|
|
120
260
|
- **`docs/architecture.md`**: Layered architecture documentation with extension guides (originally at repo root, moved to `docs/` in a later cleanup).
|
|
121
261
|
|
|
122
262
|
### Changed
|
|
263
|
+
|
|
123
264
|
- Refactored `bulk-loader.ts` (929 -> 708 lines) into focused modules: csv-parser, fallback-data
|
|
124
265
|
- Refactored `resource-extractor.ts` (778 -> 299 lines) into per-provider extractors
|
|
125
266
|
- Refactored `retail-client.ts` (614 -> 499 lines) with extracted fallback-data
|
|
@@ -127,10 +268,12 @@ First stable release. No breaking API changes from 0.5 — this version ratifies
|
|
|
127
268
|
- Updated CI pipeline with security audit job and format checking
|
|
128
269
|
|
|
129
270
|
### Fixed
|
|
271
|
+
|
|
130
272
|
- picomatch HIGH severity vulnerability (ReDoS + method injection)
|
|
131
273
|
- Unused imports and variables across codebase (ESLint cleanup)
|
|
132
274
|
|
|
133
275
|
### Security
|
|
276
|
+
|
|
134
277
|
- Resolved picomatch 4.0.0-4.0.3 vulnerability via npm audit fix
|
|
135
278
|
- Added `npm audit --audit-level=high` to CI pipeline
|
|
136
279
|
|
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<h1 align="center">CloudCost MCP Server</h1>
|
|
2
2
|
|
|
3
3
|
<p align="center">
|
|
4
|
-
Multi-cloud cost analysis for Terraform, CloudFormation, Pulumi, and Bicep/ARM. Live pricing
|
|
4
|
+
Multi-cloud cost analysis for Terraform, CloudFormation, Pulumi, and Bicep/ARM. Live AWS/Azure pricing with bundled GCP pricing snapshots.
|
|
5
5
|
<br />
|
|
6
6
|
Built on the <a href="https://modelcontextprotocol.io">Model Context Protocol</a> for seamless AI agent integration.
|
|
7
7
|
</p>
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
<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>
|
|
11
11
|
<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>
|
|
12
12
|
<a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License: MIT" /></a>
|
|
13
|
-
<img src="https://img.shields.io/badge/node-%3E%
|
|
13
|
+
<img src="https://img.shields.io/badge/node-%3E%3D20-brightgreen" alt="Node.js" />
|
|
14
14
|
</p>
|
|
15
15
|
|
|
16
16
|
<p align="right">
|
|
@@ -28,13 +28,13 @@
|
|
|
28
28
|
|
|
29
29
|
---
|
|
30
30
|
|
|
31
|
-
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
|
|
31
|
+
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.
|
|
32
32
|
|
|
33
33
|
### What it does
|
|
34
34
|
|
|
35
35
|
- Parses Terraform HCL files, CloudFormation templates, Pulumi stack exports, and Bicep/ARM templates with automatic format detection
|
|
36
36
|
- Extracts resource inventories with variable resolution, including referenced modules and OpenTofu `.tofu` files
|
|
37
|
-
- Queries live on-demand pricing from AWS Bulk Pricing CSV and Azure Retail Prices REST API; GCP
|
|
37
|
+
- Queries live on-demand pricing from AWS Bulk Pricing CSV and Azure Retail Prices REST API; GCP from a weekly-refreshed bundled snapshot
|
|
38
38
|
- Maps equivalent resources across AWS, Azure, and GCP (compute, database, storage, networking, Kubernetes, container registries, secrets management, DNS)
|
|
39
39
|
- Generates cost estimates with per-resource breakdowns (monthly and yearly) across multiple currencies
|
|
40
40
|
- Compares costs across all three providers side-by-side in markdown, JSON, CSV, or FOCUS format
|
|
@@ -44,6 +44,16 @@ CloudCost MCP is a [Model Context Protocol](https://modelcontextprotocol.io) ser
|
|
|
44
44
|
- Tags resources for cost attribution and groups report output by team, environment, or any custom label
|
|
45
45
|
- Posts cost estimate comments to pull requests via a reusable GitHub Actions composite action
|
|
46
46
|
|
|
47
|
+
### Provider pricing support
|
|
48
|
+
|
|
49
|
+
| Provider | Pricing source | Support level |
|
|
50
|
+
|---|---|---|
|
|
51
|
+
| AWS | Live public pricing APIs + bundled fallback tables | Live |
|
|
52
|
+
| Azure | Live Retail Prices API + bundled fallback tables | Live |
|
|
53
|
+
| GCP | Bundled pricing snapshots + fixed public rates | Supported, but **not live** |
|
|
54
|
+
|
|
55
|
+
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.
|
|
56
|
+
|
|
47
57
|
### Supported IaC Formats
|
|
48
58
|
|
|
49
59
|
| Format | Extensions | Auto-detected |
|
|
@@ -61,7 +71,7 @@ CloudCostMCP targets a different surface:
|
|
|
61
71
|
|
|
62
72
|
- **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.
|
|
63
73
|
- **Multi-IaC in one server.** Terraform, CloudFormation, Pulumi, Bicep/ARM — one tool, not four.
|
|
64
|
-
- **Zero credentials.**
|
|
74
|
+
- **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.
|
|
65
75
|
- **Optimization + what-if scenarios built in.** Right-sizing, reserved-pricing, cross-provider switching, and spot modeling are first-class tools.
|
|
66
76
|
|
|
67
77
|
The two are complementary. Use Infracost in CI; use CloudCostMCP inside your agent or editor.
|
|
@@ -310,7 +320,7 @@ Fast cost-safety guardrail designed for AI agents. Returns `allow` / `warn` / `b
|
|
|
310
320
|
|
|
311
321
|
## How Pricing Works
|
|
312
322
|
|
|
313
|
-
CloudCost uses a tiered approach to get the most accurate pricing available without requiring any API keys or credentials.
|
|
323
|
+
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.
|
|
314
324
|
|
|
315
325
|
### AWS
|
|
316
326
|
|
|
@@ -328,11 +338,13 @@ CloudCost uses a tiered approach to get the most accurate pricing available with
|
|
|
328
338
|
|
|
329
339
|
### GCP
|
|
330
340
|
|
|
331
|
-
|
|
341
|
+
**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.
|
|
342
|
+
|
|
343
|
+
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`.
|
|
332
344
|
|
|
333
|
-
2. **
|
|
345
|
+
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.
|
|
334
346
|
|
|
335
|
-
3. **Infrastructure services**. Load balancer, Cloud NAT, and GKE pricing use fixed public rates.
|
|
347
|
+
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.
|
|
336
348
|
|
|
337
349
|
### Pricing Source Transparency
|
|
338
350
|
|
|
@@ -488,7 +500,7 @@ Configuration priority: environment variables > config file > built-in defaults.
|
|
|
488
500
|
CSV (public) (public, no auth) (bundled files)
|
|
489
501
|
```
|
|
490
502
|
|
|
491
|
-
Highlights:
|
|
503
|
+
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).
|
|
492
504
|
|
|
493
505
|
---
|
|
494
506
|
|
|
@@ -517,8 +529,8 @@ Instance type mapping covers 70+ AWS instance types (including Graviton/ARM fami
|
|
|
517
529
|
## Limitations
|
|
518
530
|
|
|
519
531
|
- **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.
|
|
520
|
-
- **GCP
|
|
521
|
-
- **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.
|
|
532
|
+
- **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.
|
|
533
|
+
- **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`.
|
|
522
534
|
- **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.
|
|
523
535
|
- **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.
|
|
524
536
|
- **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).
|
|
@@ -1,8 +1,28 @@
|
|
|
1
1
|
{
|
|
2
|
-
"last_updated": "2026-
|
|
2
|
+
"last_updated": "2026-10-07",
|
|
3
|
+
"last_verified": "2026-10-07",
|
|
4
|
+
"verified_at": "2026-10-07T06:00:57.034Z",
|
|
5
|
+
"sources": [
|
|
6
|
+
{
|
|
7
|
+
"url": "https://pricing.us-east-1.amazonaws.com/offers/v1.0/aws/AmazonEC2/current/us-east-1/index.csv",
|
|
8
|
+
"retrieved_at": "2026-10-07T06:00:56.209Z",
|
|
9
|
+
"sha256": "3b72dd89fc32fa9c9f148373663221c28124abab29d366fe4577fcbee655e736",
|
|
10
|
+
"source_vintage": "2026-10-06T17:24:54Z"
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"url": "https://pricing.us-east-1.amazonaws.com/offers/v1.0/aws/AmazonRDS/current/us-east-1/index.csv",
|
|
14
|
+
"retrieved_at": "2026-10-07T06:00:56.679Z",
|
|
15
|
+
"sha256": "6c216380d45af7df6376624ac5f63e321168c29717efe938ccb26737be4fea60",
|
|
16
|
+
"source_vintage": "2026-10-06T22:40:50Z"
|
|
17
|
+
}
|
|
18
|
+
],
|
|
19
|
+
"refresh_policy": "automated",
|
|
3
20
|
"source": "https://pricing.us-east-1.amazonaws.com/offers/v1.0/aws",
|
|
4
21
|
"sku_count": 142,
|
|
5
|
-
"refresh_script_version": "
|
|
22
|
+
"refresh_script_version": "3.1.0",
|
|
6
23
|
"currency": "USD",
|
|
24
|
+
"curated_datasets": [
|
|
25
|
+
"EBS_BASE_PRICES (src/pricing/aws/fallback-data.ts)"
|
|
26
|
+
],
|
|
7
27
|
"notes": "Written by scripts/refresh-pricing.ts --write"
|
|
8
28
|
}
|