@jadenrazo/cloudcost-mcp 0.1.0
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/LICENSE +21 -0
- package/README.md +384 -0
- package/data/gcp-pricing/cloud-sql.json +72 -0
- package/data/gcp-pricing/cloud-storage.json +13 -0
- package/data/gcp-pricing/compute-engine.json +343 -0
- package/data/gcp-pricing/metadata.json +6 -0
- package/data/gcp-pricing/persistent-disk.json +13 -0
- package/data/instance-map.json +230 -0
- package/data/instance-types/aws-instances.json +77 -0
- package/data/instance-types/azure-vm-sizes.json +36 -0
- package/data/instance-types/gcp-machine-types.json +34 -0
- package/data/region-mappings.json +21 -0
- package/data/resource-equivalents.json +16 -0
- package/data/storage-map.json +16 -0
- package/dist/chunk-KZJSZMWM.js +153 -0
- package/dist/chunk-KZJSZMWM.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +4488 -0
- package/dist/index.js.map +1 -0
- package/dist/loader-WIX54B7L.js +30 -0
- package/dist/loader-WIX54B7L.js.map +1 -0
- package/package.json +64 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024-2026 Jaden Razo
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<h1 align="center">CloudCost MCP Server</h1>
|
|
3
|
+
<p align="center">
|
|
4
|
+
Multi-cloud cost analysis for Terraform — powered by live pricing data from AWS, Azure, and GCP.
|
|
5
|
+
<br />
|
|
6
|
+
Built on the <a href="https://modelcontextprotocol.io">Model Context Protocol</a> for seamless AI agent integration.
|
|
7
|
+
</p>
|
|
8
|
+
</p>
|
|
9
|
+
|
|
10
|
+
<p align="center">
|
|
11
|
+
|
|
12
|
+
 [](https://www.npmjs.com/package/@jadenrazo/cloudcost-mcp) [](https://opensource.org/licenses/MIT) 
|
|
13
|
+
|
|
14
|
+
</p>
|
|
15
|
+
|
|
16
|
+
<p align="center">
|
|
17
|
+
<a href="#installation">Installation</a> •
|
|
18
|
+
<a href="#tools">Tools</a> •
|
|
19
|
+
<a href="#how-pricing-works">Pricing</a> •
|
|
20
|
+
<a href="#configuration">Config</a> •
|
|
21
|
+
<a href="#architecture">Architecture</a> •
|
|
22
|
+
<a href="#limitations">Limitations</a>
|
|
23
|
+
</p>
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
CloudCost MCP is an MCP server that lets AI agents parse Terraform codebases, query real-time pricing data, and generate multi-cloud cost comparison reports. It connects directly to public pricing APIs from AWS and Azure — no API keys or cloud credentials required. GCP pricing is bundled from public catalog data.
|
|
28
|
+
|
|
29
|
+
### What it does
|
|
30
|
+
|
|
31
|
+
- Parses Terraform HCL files and extracts resource inventories with variable resolution
|
|
32
|
+
- Queries live on-demand pricing from AWS Bulk Pricing CSV and Azure Retail Prices REST API
|
|
33
|
+
- Maps equivalent resources across AWS, Azure, and GCP (compute, database, storage, networking, Kubernetes)
|
|
34
|
+
- Generates cost estimates with per-resource breakdowns (monthly and yearly)
|
|
35
|
+
- Compares costs across all three providers side-by-side in markdown, JSON, or CSV
|
|
36
|
+
- Provides optimization recommendations: right-sizing, reserved pricing, provider switching
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Installation
|
|
41
|
+
|
|
42
|
+
Requires **Node.js 20** or later.
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
git clone https://github.com/jadenrazo/CloudCostMCP.git
|
|
46
|
+
cd CloudCostMCP
|
|
47
|
+
npm install
|
|
48
|
+
npm run build
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Or install from npm:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
npm install -g @jadenrazo/cloudcost-mcp
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Claude Desktop
|
|
58
|
+
|
|
59
|
+
Add to your Claude Desktop MCP configuration (`claude_desktop_config.json`):
|
|
60
|
+
|
|
61
|
+
```json
|
|
62
|
+
{
|
|
63
|
+
"mcpServers": {
|
|
64
|
+
"cloudcost": {
|
|
65
|
+
"command": "node",
|
|
66
|
+
"args": ["/path/to/cloudcost-mcp/dist/index.js"]
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
If installed globally via npm:
|
|
73
|
+
|
|
74
|
+
```json
|
|
75
|
+
{
|
|
76
|
+
"mcpServers": {
|
|
77
|
+
"cloudcost": {
|
|
78
|
+
"command": "cloudcost-mcp"
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Claude Code
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
claude mcp add cloudcost -- node /path/to/cloudcost-mcp/dist/index.js
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### As a standalone MCP server (stdio)
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
node dist/index.js
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## Tools
|
|
99
|
+
|
|
100
|
+
The server exposes six MCP tools. Each accepts JSON input and returns structured JSON output.
|
|
101
|
+
|
|
102
|
+
### `analyze_terraform`
|
|
103
|
+
|
|
104
|
+
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.
|
|
105
|
+
|
|
106
|
+
| Parameter | Type | Required | Description |
|
|
107
|
+
|-----------|------|----------|-------------|
|
|
108
|
+
| `files` | `{path, content}[]` | Yes | Terraform `.tf` files to analyze |
|
|
109
|
+
| `tfvars` | `string` | No | Contents of a `terraform.tfvars` file |
|
|
110
|
+
|
|
111
|
+
### `estimate_cost`
|
|
112
|
+
|
|
113
|
+
Calculate costs for parsed resources on a specific provider. Returns monthly and yearly breakdowns per resource with confidence scores.
|
|
114
|
+
|
|
115
|
+
| Parameter | Type | Required | Description |
|
|
116
|
+
|-----------|------|----------|-------------|
|
|
117
|
+
| `files` | `{path, content}[]` | Yes | Terraform files |
|
|
118
|
+
| `tfvars` | `string` | No | Variable overrides |
|
|
119
|
+
| `provider` | `aws \| azure \| gcp` | Yes | Target provider for pricing |
|
|
120
|
+
| `region` | `string` | No | Target region (auto-mapped if omitted) |
|
|
121
|
+
|
|
122
|
+
### `compare_providers`
|
|
123
|
+
|
|
124
|
+
Full pipeline: parse Terraform, map resources across providers, fetch pricing, and produce a comparison report. This is the main entry point for cost analysis.
|
|
125
|
+
|
|
126
|
+
| Parameter | Type | Required | Description |
|
|
127
|
+
|-----------|------|----------|-------------|
|
|
128
|
+
| `files` | `{path, content}[]` | Yes | Terraform files |
|
|
129
|
+
| `tfvars` | `string` | No | Variable overrides |
|
|
130
|
+
| `format` | `markdown \| json \| csv` | No | Report format (default: `markdown`) |
|
|
131
|
+
| `providers` | `string[]` | No | Providers to compare (default: all three) |
|
|
132
|
+
|
|
133
|
+
### `get_equivalents`
|
|
134
|
+
|
|
135
|
+
Look up the equivalent Terraform resource type and instance size across providers. Useful for migration planning.
|
|
136
|
+
|
|
137
|
+
| Parameter | Type | Required | Description |
|
|
138
|
+
|-----------|------|----------|-------------|
|
|
139
|
+
| `resource_type` | `string` | Yes | Terraform resource type (e.g., `aws_instance`) |
|
|
140
|
+
| `source_provider` | `aws \| azure \| gcp` | Yes | Provider the resource belongs to |
|
|
141
|
+
| `target_provider` | `aws \| azure \| gcp` | No | Specific target (omit for all) |
|
|
142
|
+
| `instance_type` | `string` | No | Instance type to also map (e.g., `t3.large`) |
|
|
143
|
+
|
|
144
|
+
### `get_pricing`
|
|
145
|
+
|
|
146
|
+
Direct pricing lookup. Returns the normalized unit price with metadata for a specific resource on a specific provider.
|
|
147
|
+
|
|
148
|
+
| Parameter | Type | Required | Description |
|
|
149
|
+
|-----------|------|----------|-------------|
|
|
150
|
+
| `provider` | `aws \| azure \| gcp` | Yes | Cloud provider |
|
|
151
|
+
| `service` | `compute \| database \| storage \| network \| kubernetes` | Yes | Service category |
|
|
152
|
+
| `resource_type` | `string` | Yes | Instance type, storage type, etc. |
|
|
153
|
+
| `region` | `string` | Yes | Cloud region |
|
|
154
|
+
|
|
155
|
+
### `optimize_cost`
|
|
156
|
+
|
|
157
|
+
Analyze Terraform resources and return optimization recommendations. Includes right-sizing suggestions, reserved instance comparisons, and cross-provider savings opportunities.
|
|
158
|
+
|
|
159
|
+
| Parameter | Type | Required | Description |
|
|
160
|
+
|-----------|------|----------|-------------|
|
|
161
|
+
| `files` | `{path, content}[]` | Yes | Terraform files |
|
|
162
|
+
| `tfvars` | `string` | No | Variable overrides |
|
|
163
|
+
| `providers` | `string[]` | No | Providers to evaluate (default: all three) |
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## How Pricing Works
|
|
168
|
+
|
|
169
|
+
CloudCost uses a tiered approach to get the most accurate pricing available without requiring any API keys or credentials.
|
|
170
|
+
|
|
171
|
+
### AWS
|
|
172
|
+
|
|
173
|
+
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.
|
|
174
|
+
|
|
175
|
+
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.
|
|
176
|
+
|
|
177
|
+
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` → `xlarge` doubles the price).
|
|
178
|
+
|
|
179
|
+
### Azure
|
|
180
|
+
|
|
181
|
+
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`). This is a fast, free, unauthenticated API that returns precise per-SKU pricing. Results are paginated and fully consumed.
|
|
182
|
+
|
|
183
|
+
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.
|
|
184
|
+
|
|
185
|
+
### GCP
|
|
186
|
+
|
|
187
|
+
1. **Bundled pricing data** — GCP's Cloud Billing Catalog API requires an API key, so the server ships with curated pricing data in `data/gcp-pricing/`. This covers Compute Engine machine types, Cloud SQL tiers, Cloud Storage classes, and Persistent Disk types across all major regions.
|
|
188
|
+
|
|
189
|
+
2. **Infrastructure services** — Load balancer, Cloud NAT, and GKE pricing use fixed public rates.
|
|
190
|
+
|
|
191
|
+
### Pricing Source Transparency
|
|
192
|
+
|
|
193
|
+
Every price returned includes a `pricing_source` attribute indicating its origin:
|
|
194
|
+
- `"live"` — fetched from a public API in real time
|
|
195
|
+
- `"fallback"` — from built-in tables (approximate, but reasonable for estimates)
|
|
196
|
+
- `"bundled"` — from bundled data files shipped with the package
|
|
197
|
+
|
|
198
|
+
All pricing data is cached in a local SQLite database (`~/.cloudcost/cache.db`) with a 24-hour TTL to minimize redundant API calls.
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## Example
|
|
203
|
+
|
|
204
|
+
Running `compare_providers` against a typical AWS Terraform config with 3 web servers (t3.xlarge), 2 app servers (m5.2xlarge), an RDS instance (db.r6g.xlarge), EBS volumes, S3, ALB, NAT Gateway, and an EKS cluster:
|
|
205
|
+
|
|
206
|
+
```
|
|
207
|
+
| Category | AWS (USD/mo) | Azure (USD/mo) | GCP (USD/mo) |
|
|
208
|
+
|-----------------|-------------|----------------|--------------|
|
|
209
|
+
| Compute | $1,176.48 | $1,209.60 | $1,142.88 |
|
|
210
|
+
| Database | $314.64 | $297.12 | $285.48 |
|
|
211
|
+
| Storage | $48.00 | $52.80 | $44.00 |
|
|
212
|
+
| Load Balancer | $16.20 | $18.00 | $18.26 |
|
|
213
|
+
| NAT Gateway | $32.40 | $32.40 | $31.68 |
|
|
214
|
+
| Kubernetes | $72.00 | $72.00 | $72.00 |
|
|
215
|
+
| **Total** | **$1,659.72** | **$1,681.92** | **$1,594.30** |
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
*Prices are on-demand estimates. Actual costs vary by usage, region, and commitment level.*
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## Configuration
|
|
223
|
+
|
|
224
|
+
All configuration is optional. The server works out of the box with sensible defaults.
|
|
225
|
+
|
|
226
|
+
### Environment Variables
|
|
227
|
+
|
|
228
|
+
| Variable | Default | Description |
|
|
229
|
+
|----------|---------|-------------|
|
|
230
|
+
| `CLOUDCOST_CACHE_TTL` | `86400` | Cache TTL in seconds (24 hours) |
|
|
231
|
+
| `CLOUDCOST_CACHE_PATH` | `~/.cloudcost/cache.db` | SQLite cache file location |
|
|
232
|
+
| `CLOUDCOST_LOG_LEVEL` | `info` | Log level: `debug`, `info`, `warn`, `error` |
|
|
233
|
+
| `CLOUDCOST_MONTHLY_HOURS` | `730` | Hours per month for cost calculations |
|
|
234
|
+
|
|
235
|
+
### Config File
|
|
236
|
+
|
|
237
|
+
You can also create `~/.cloudcost/config.json`:
|
|
238
|
+
|
|
239
|
+
```json
|
|
240
|
+
{
|
|
241
|
+
"cache": {
|
|
242
|
+
"ttl_seconds": 43200,
|
|
243
|
+
"db_path": "/tmp/cloudcost-cache.db"
|
|
244
|
+
},
|
|
245
|
+
"pricing": {
|
|
246
|
+
"monthly_hours": 730,
|
|
247
|
+
"default_currency": "USD"
|
|
248
|
+
},
|
|
249
|
+
"logging": {
|
|
250
|
+
"level": "debug"
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
Configuration priority: environment variables > config file > built-in defaults.
|
|
256
|
+
|
|
257
|
+
---
|
|
258
|
+
|
|
259
|
+
## Architecture
|
|
260
|
+
|
|
261
|
+
```
|
|
262
|
+
┌───────────────────────────────┐
|
|
263
|
+
│ MCP Client │
|
|
264
|
+
│ (Claude Desktop / Agent) │
|
|
265
|
+
└──────────────┬────────────────┘
|
|
266
|
+
│ stdio
|
|
267
|
+
┌──────────────▼────────────────┐
|
|
268
|
+
│ CloudCost MCP Server │
|
|
269
|
+
│ (src/server.ts) │
|
|
270
|
+
└──────────────┬────────────────┘
|
|
271
|
+
│
|
|
272
|
+
┌────────────────────────┼─────────────────────────┐
|
|
273
|
+
│ │ │
|
|
274
|
+
┌─────────▼─────────┐ ┌─────────▼─────────┐ ┌─────────▼─────────┐
|
|
275
|
+
│ Tool Handlers │ │ HCL Parsers │ │ Cost Engine │
|
|
276
|
+
│ (src/tools/*.ts) │ │ (src/parsers/) │ │ (src/calculator/) │
|
|
277
|
+
└─────────┬─────────┘ └───────────────────┘ └─────────┬─────────┘
|
|
278
|
+
│ │
|
|
279
|
+
┌─────────▼──────────────────────────────────────────────────▼─────────┐
|
|
280
|
+
│ PricingEngine (router) │
|
|
281
|
+
│ (src/pricing/pricing-engine.ts) │
|
|
282
|
+
└───────┬────────────────────┬──────────────────────┬─────────────────┘
|
|
283
|
+
│ │ │
|
|
284
|
+
┌─────────▼──────┐ ┌─────────▼──────┐ ┌──────────▼──────┐
|
|
285
|
+
│ AWS Bulk │ │ Azure Retail │ │ GCP Bundled │
|
|
286
|
+
│ Loader │ │ Client │ │ Loader │
|
|
287
|
+
│ (CSV + JSON) │ │ (REST API) │ │ (static JSON) │
|
|
288
|
+
└───────┬────────┘ └───────┬────────┘ └────────┬────────┘
|
|
289
|
+
│ │ │
|
|
290
|
+
▼ ▼ ▼
|
|
291
|
+
AWS Bulk Pricing Azure Retail API data/gcp-pricing/
|
|
292
|
+
CSV (public) (public, no auth) (bundled files)
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
### Key Design Decisions
|
|
296
|
+
|
|
297
|
+
- **Zero API keys** — All pricing comes from public endpoints. AWS uses the unauthenticated Bulk Pricing files. Azure uses the free Retail Prices REST API. GCP uses bundled data from public catalog information.
|
|
298
|
+
- **SQLite cache** — A single `better-sqlite3` database caches all pricing lookups with configurable TTL. Shared across all tools per server lifetime.
|
|
299
|
+
- **Streaming for large files** — AWS EC2 pricing data (~267 MB CSV) is streamed line-by-line rather than loaded into memory. All prices for a region are extracted in one pass and cached.
|
|
300
|
+
- **Graceful degradation** — If any live pricing source is unavailable, the server falls back to built-in tables with size-interpolation. Every response includes the pricing source so the consumer knows the confidence level.
|
|
301
|
+
- **ESM-only** — Requires Node 20+. All internal imports use `.js` extensions.
|
|
302
|
+
|
|
303
|
+
---
|
|
304
|
+
|
|
305
|
+
## Supported Resources
|
|
306
|
+
|
|
307
|
+
| Category | AWS | Azure | GCP |
|
|
308
|
+
|----------|-----|-------|-----|
|
|
309
|
+
| **Compute** | `aws_instance`, `aws_launch_template` | `azurerm_virtual_machine`, `azurerm_linux_virtual_machine` | `google_compute_instance` |
|
|
310
|
+
| **Database** | `aws_db_instance`, `aws_rds_cluster` | `azurerm_postgresql_flexible_server`, `azurerm_mysql_flexible_server` | `google_sql_database_instance` |
|
|
311
|
+
| **Storage** | `aws_ebs_volume`, `aws_s3_bucket` | `azurerm_managed_disk`, `azurerm_storage_account` | `google_compute_disk`, `google_storage_bucket` |
|
|
312
|
+
| **Network** | `aws_lb`, `aws_nat_gateway` | `azurerm_lb`, `azurerm_nat_gateway` | `google_compute_forwarding_rule` |
|
|
313
|
+
| **Kubernetes** | `aws_eks_cluster` | `azurerm_kubernetes_cluster` | `google_container_cluster` |
|
|
314
|
+
|
|
315
|
+
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.
|
|
316
|
+
|
|
317
|
+
---
|
|
318
|
+
|
|
319
|
+
## Limitations
|
|
320
|
+
|
|
321
|
+
- **Data transfer costs** are not included. Inter-region, inter-AZ, and internet egress charges are excluded from estimates.
|
|
322
|
+
- **On-demand pricing only** by default. Prices reflect pay-as-you-go rates. The `optimize_cost` tool will recommend reserved instances and savings plans, but base estimates use on-demand.
|
|
323
|
+
- **No Terraform module expansion**. Only direct resource blocks in the provided files are parsed. Resources defined inside referenced modules (`source = "..."`) are not resolved.
|
|
324
|
+
- **GCP pricing is bundled**, not live. Prices may lag behind actual rates. AWS and Azure pricing is fetched in real time.
|
|
325
|
+
- **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).
|
|
326
|
+
- **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.
|
|
327
|
+
|
|
328
|
+
---
|
|
329
|
+
|
|
330
|
+
## Troubleshooting
|
|
331
|
+
|
|
332
|
+
**$0 cost estimates** — This usually means the instance type string in your Terraform code doesn't match any known pricing data. Check that you're using a real instance type (e.g., `t3.xlarge`) rather than a variable reference that wasn't resolved. Pass your `terraform.tfvars` content via the `tfvars` parameter to resolve variables.
|
|
333
|
+
|
|
334
|
+
**Slow first request** — The first EC2 pricing lookup for a new region streams the full AWS pricing CSV (~267 MB). This is a one-time cost per region; all subsequent lookups hit the local SQLite cache. Set `CLOUDCOST_LOG_LEVEL=debug` to see progress.
|
|
335
|
+
|
|
336
|
+
**Cache issues** — Delete `~/.cloudcost/cache.db` to clear all cached pricing data. The cache rebuilds automatically on the next request.
|
|
337
|
+
|
|
338
|
+
**Node version** — The server requires Node.js 20+. It uses ESM modules, Web Streams API (`TextDecoderStream`), and `AbortSignal.timeout()`.
|
|
339
|
+
|
|
340
|
+
---
|
|
341
|
+
|
|
342
|
+
## Development
|
|
343
|
+
|
|
344
|
+
```bash
|
|
345
|
+
npm run dev # Run with tsx (hot reload, no build needed)
|
|
346
|
+
npm test # Run all tests (vitest)
|
|
347
|
+
npm run test:watch # Watch mode
|
|
348
|
+
npm run build # Production build (tsup → dist/)
|
|
349
|
+
npm run lint # Type check (tsc --noEmit)
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
### Project Structure
|
|
353
|
+
|
|
354
|
+
```
|
|
355
|
+
src/
|
|
356
|
+
├── index.ts # Entry point (process error handlers + start)
|
|
357
|
+
├── server.ts # MCP server setup, tool registration
|
|
358
|
+
├── config.ts # Config loader (defaults → file → env vars)
|
|
359
|
+
├── logger.ts # Structured logger
|
|
360
|
+
├── tools/ # MCP tool handlers + Zod schemas
|
|
361
|
+
├── parsers/ # HCL parsing, variable resolution
|
|
362
|
+
├── pricing/
|
|
363
|
+
│ ├── pricing-engine.ts # Router: dispatches to provider adapters
|
|
364
|
+
│ ├── cache.ts # SQLite-backed pricing cache
|
|
365
|
+
│ ├── aws/ # Bulk CSV streaming + JSON + fallback
|
|
366
|
+
│ ├── azure/ # Retail Prices REST API + fallback
|
|
367
|
+
│ └── gcp/ # Bundled pricing data loader
|
|
368
|
+
├── calculator/ # Cost calculations per resource type
|
|
369
|
+
├── mapping/ # Cross-provider resource/instance mapping
|
|
370
|
+
├── reporting/ # Output formatters (markdown, JSON, CSV)
|
|
371
|
+
└── types/ # Shared TypeScript interfaces
|
|
372
|
+
|
|
373
|
+
data/
|
|
374
|
+
├── instance-map.json # Bidirectional instance type mappings
|
|
375
|
+
├── storage-map.json # Cross-provider storage type mappings
|
|
376
|
+
├── gcp-pricing/ # Bundled GCP pricing data
|
|
377
|
+
└── instance-types/ # Instance type metadata
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
---
|
|
381
|
+
|
|
382
|
+
## License
|
|
383
|
+
|
|
384
|
+
MIT — see [LICENSE](LICENSE) for details.
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
{
|
|
2
|
+
"us-central1": {
|
|
3
|
+
"db-custom-1-3840": 0.0500,
|
|
4
|
+
"db-custom-2-7680": 0.1000,
|
|
5
|
+
"db-custom-4-15360": 0.2000,
|
|
6
|
+
"storage_per_gb": 0.170,
|
|
7
|
+
"ha_multiplier": 2.0
|
|
8
|
+
},
|
|
9
|
+
"us-east1": {
|
|
10
|
+
"db-custom-1-3840": 0.0500,
|
|
11
|
+
"db-custom-2-7680": 0.1000,
|
|
12
|
+
"db-custom-4-15360": 0.2000,
|
|
13
|
+
"storage_per_gb": 0.170,
|
|
14
|
+
"ha_multiplier": 2.0
|
|
15
|
+
},
|
|
16
|
+
"europe-west1": {
|
|
17
|
+
"db-custom-1-3840": 0.0550,
|
|
18
|
+
"db-custom-2-7680": 0.1100,
|
|
19
|
+
"db-custom-4-15360": 0.2200,
|
|
20
|
+
"storage_per_gb": 0.187,
|
|
21
|
+
"ha_multiplier": 2.0
|
|
22
|
+
},
|
|
23
|
+
"us-west1": {
|
|
24
|
+
"db-custom-1-3840": 0.0500,
|
|
25
|
+
"db-custom-2-7680": 0.1000,
|
|
26
|
+
"db-custom-4-15360": 0.2000,
|
|
27
|
+
"storage_per_gb": 0.170,
|
|
28
|
+
"ha_multiplier": 2.0
|
|
29
|
+
},
|
|
30
|
+
"asia-northeast1": {
|
|
31
|
+
"db-custom-1-3840": 0.0575,
|
|
32
|
+
"db-custom-2-7680": 0.1150,
|
|
33
|
+
"db-custom-4-15360": 0.2300,
|
|
34
|
+
"storage_per_gb": 0.196,
|
|
35
|
+
"ha_multiplier": 2.0
|
|
36
|
+
},
|
|
37
|
+
"asia-south1": {
|
|
38
|
+
"db-custom-1-3840": 0.0525,
|
|
39
|
+
"db-custom-2-7680": 0.1050,
|
|
40
|
+
"db-custom-4-15360": 0.2100,
|
|
41
|
+
"storage_per_gb": 0.179,
|
|
42
|
+
"ha_multiplier": 2.0
|
|
43
|
+
},
|
|
44
|
+
"australia-southeast1": {
|
|
45
|
+
"db-custom-1-3840": 0.0590,
|
|
46
|
+
"db-custom-2-7680": 0.1180,
|
|
47
|
+
"db-custom-4-15360": 0.2360,
|
|
48
|
+
"storage_per_gb": 0.201,
|
|
49
|
+
"ha_multiplier": 2.0
|
|
50
|
+
},
|
|
51
|
+
"europe-west2": {
|
|
52
|
+
"db-custom-1-3840": 0.0550,
|
|
53
|
+
"db-custom-2-7680": 0.1100,
|
|
54
|
+
"db-custom-4-15360": 0.2200,
|
|
55
|
+
"storage_per_gb": 0.187,
|
|
56
|
+
"ha_multiplier": 2.0
|
|
57
|
+
},
|
|
58
|
+
"europe-west4": {
|
|
59
|
+
"db-custom-1-3840": 0.0550,
|
|
60
|
+
"db-custom-2-7680": 0.1100,
|
|
61
|
+
"db-custom-4-15360": 0.2200,
|
|
62
|
+
"storage_per_gb": 0.187,
|
|
63
|
+
"ha_multiplier": 2.0
|
|
64
|
+
},
|
|
65
|
+
"northamerica-northeast1": {
|
|
66
|
+
"db-custom-1-3840": 0.0525,
|
|
67
|
+
"db-custom-2-7680": 0.1050,
|
|
68
|
+
"db-custom-4-15360": 0.2100,
|
|
69
|
+
"storage_per_gb": 0.179,
|
|
70
|
+
"ha_multiplier": 2.0
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"us-central1": { "STANDARD": 0.020, "NEARLINE": 0.010, "COLDLINE": 0.004, "ARCHIVE": 0.0012 },
|
|
3
|
+
"us-east1": { "STANDARD": 0.020, "NEARLINE": 0.010, "COLDLINE": 0.004, "ARCHIVE": 0.0012 },
|
|
4
|
+
"europe-west1": { "STANDARD": 0.020, "NEARLINE": 0.010, "COLDLINE": 0.004, "ARCHIVE": 0.0012 },
|
|
5
|
+
"asia-southeast1": { "STANDARD": 0.023, "NEARLINE": 0.013, "COLDLINE": 0.006, "ARCHIVE": 0.0015 },
|
|
6
|
+
"us-west1": { "STANDARD": 0.020, "NEARLINE": 0.010, "COLDLINE": 0.004, "ARCHIVE": 0.0012 },
|
|
7
|
+
"asia-northeast1": { "STANDARD": 0.023, "NEARLINE": 0.013, "COLDLINE": 0.006, "ARCHIVE": 0.0015 },
|
|
8
|
+
"asia-south1": { "STANDARD": 0.021, "NEARLINE": 0.011, "COLDLINE": 0.005, "ARCHIVE": 0.0013 },
|
|
9
|
+
"australia-southeast1": { "STANDARD": 0.024, "NEARLINE": 0.013, "COLDLINE": 0.006, "ARCHIVE": 0.0015 },
|
|
10
|
+
"europe-west2": { "STANDARD": 0.022, "NEARLINE": 0.011, "COLDLINE": 0.005, "ARCHIVE": 0.0013 },
|
|
11
|
+
"europe-west4": { "STANDARD": 0.022, "NEARLINE": 0.011, "COLDLINE": 0.005, "ARCHIVE": 0.0013 },
|
|
12
|
+
"northamerica-northeast1": { "STANDARD": 0.021, "NEARLINE": 0.011, "COLDLINE": 0.005, "ARCHIVE": 0.0013 }
|
|
13
|
+
}
|