opencloudcosts 0.7.0__tar.gz

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.
Files changed (69) hide show
  1. opencloudcosts-0.7.0/.env.example +24 -0
  2. opencloudcosts-0.7.0/.github/workflows/workflow.yml +40 -0
  3. opencloudcosts-0.7.0/.gitignore +49 -0
  4. opencloudcosts-0.7.0/Dockerfile +16 -0
  5. opencloudcosts-0.7.0/LICENSE +21 -0
  6. opencloudcosts-0.7.0/PKG-INFO +298 -0
  7. opencloudcosts-0.7.0/README.md +261 -0
  8. opencloudcosts-0.7.0/docs/finops-guide.md +456 -0
  9. opencloudcosts-0.7.0/docs/future-tasks.md +31 -0
  10. opencloudcosts-0.7.0/docs/plans/T18-aws-spot-pricing.md +127 -0
  11. opencloudcosts-0.7.0/docs/plans/T19-ri-upfront-options.md +120 -0
  12. opencloudcosts-0.7.0/docs/plans/T20-os-field-bom.md +56 -0
  13. opencloudcosts-0.7.0/docs/plans/T21-refresh-cache-metadata.md +56 -0
  14. opencloudcosts-0.7.0/docs/plans/T22-gcp-major-regions.md +81 -0
  15. opencloudcosts-0.7.0/docs/plans/T23-phase4-error-messages.md +63 -0
  16. opencloudcosts-0.7.0/docs/plans/T24-test-coverage.md +180 -0
  17. opencloudcosts-0.7.0/docs/plans/T25-no-results-hints.md +95 -0
  18. opencloudcosts-0.7.0/docs/plans/T26-gcp-effective-pricing.md +129 -0
  19. opencloudcosts-0.7.0/docs/plans/T27-get-database-price-tool.md +128 -0
  20. opencloudcosts-0.7.0/docs/plans/T28-azure-provider.md +192 -0
  21. opencloudcosts-0.7.0/docs/plans/T29-http-transport.md +146 -0
  22. opencloudcosts-0.7.0/docs/plans/T30-spot-price-history.md +201 -0
  23. opencloudcosts-0.7.0/docs/plans/T31-gcp-windows-pricing.md +99 -0
  24. opencloudcosts-0.7.0/docs/roadmap.md +349 -0
  25. opencloudcosts-0.7.0/docs/tools.md +422 -0
  26. opencloudcosts-0.7.0/pyproject.toml +76 -0
  27. opencloudcosts-0.7.0/src/opencloudcosts/__init__.py +0 -0
  28. opencloudcosts-0.7.0/src/opencloudcosts/cache.py +202 -0
  29. opencloudcosts-0.7.0/src/opencloudcosts/config.py +46 -0
  30. opencloudcosts-0.7.0/src/opencloudcosts/models.py +214 -0
  31. opencloudcosts-0.7.0/src/opencloudcosts/providers/__init__.py +0 -0
  32. opencloudcosts-0.7.0/src/opencloudcosts/providers/aws.py +1166 -0
  33. opencloudcosts-0.7.0/src/opencloudcosts/providers/azure.py +385 -0
  34. opencloudcosts-0.7.0/src/opencloudcosts/providers/base.py +87 -0
  35. opencloudcosts-0.7.0/src/opencloudcosts/providers/gcp.py +765 -0
  36. opencloudcosts-0.7.0/src/opencloudcosts/server.py +139 -0
  37. opencloudcosts-0.7.0/src/opencloudcosts/tools/__init__.py +0 -0
  38. opencloudcosts-0.7.0/src/opencloudcosts/tools/availability.py +689 -0
  39. opencloudcosts-0.7.0/src/opencloudcosts/tools/bom.py +322 -0
  40. opencloudcosts-0.7.0/src/opencloudcosts/tools/lookup.py +1335 -0
  41. opencloudcosts-0.7.0/src/opencloudcosts/utils/__init__.py +0 -0
  42. opencloudcosts-0.7.0/src/opencloudcosts/utils/baseline.py +53 -0
  43. opencloudcosts-0.7.0/src/opencloudcosts/utils/gcp_specs.py +437 -0
  44. opencloudcosts-0.7.0/src/opencloudcosts/utils/regions.py +215 -0
  45. opencloudcosts-0.7.0/src/opencloudcosts/utils/units.py +68 -0
  46. opencloudcosts-0.7.0/tests/__init__.py +0 -0
  47. opencloudcosts-0.7.0/tests/conftest.py +29 -0
  48. opencloudcosts-0.7.0/tests/test_cache.py +87 -0
  49. opencloudcosts-0.7.0/tests/test_models.py +80 -0
  50. opencloudcosts-0.7.0/tests/test_providers/__init__.py +0 -0
  51. opencloudcosts-0.7.0/tests/test_providers/test_aws.py +654 -0
  52. opencloudcosts-0.7.0/tests/test_providers/test_azure.py +399 -0
  53. opencloudcosts-0.7.0/tests/test_providers/test_gcp.py +439 -0
  54. opencloudcosts-0.7.0/tests/test_providers/test_gcp_cloud_storage_sql.py +272 -0
  55. opencloudcosts-0.7.0/tests/test_tools/__init__.py +0 -0
  56. opencloudcosts-0.7.0/tests/test_tools/test_azure_list_instance_types.py +147 -0
  57. opencloudcosts-0.7.0/tests/test_tools/test_bom.py +184 -0
  58. opencloudcosts-0.7.0/tests/test_tools/test_bom_extended.py +237 -0
  59. opencloudcosts-0.7.0/tests/test_tools/test_cache_tools.py +130 -0
  60. opencloudcosts-0.7.0/tests/test_tools/test_fargate_bedrock.py +353 -0
  61. opencloudcosts-0.7.0/tests/test_tools/test_gcp_major_regions.py +252 -0
  62. opencloudcosts-0.7.0/tests/test_tools/test_list_instance_types_effective_max.py +202 -0
  63. opencloudcosts-0.7.0/tests/test_tools/test_lookup_db.py +242 -0
  64. opencloudcosts-0.7.0/tests/test_tools/test_lookup_extended.py +229 -0
  65. opencloudcosts-0.7.0/tests/test_tools/test_lookup_no_results.py +251 -0
  66. opencloudcosts-0.7.0/tests/test_tools/test_phase2.py +203 -0
  67. opencloudcosts-0.7.0/tests/test_tools/test_storage_monthly_estimate.py +309 -0
  68. opencloudcosts-0.7.0/tests/test_tools/test_t23_gcp_errors.py +149 -0
  69. opencloudcosts-0.7.0/uv.lock +1510 -0
@@ -0,0 +1,24 @@
1
+ # CloudCost MCP Server Configuration
2
+ # Copy this file to .env and fill in the values you need.
3
+ # Public AWS pricing works without any credentials.
4
+
5
+ # --- General ---
6
+ # OCC_CACHE_DIR=~/.cache/cloudcostmcp
7
+ # OCC_CACHE_TTL_HOURS=24
8
+ # OCC_DEFAULT_CURRENCY=USD
9
+ # OCC_DEFAULT_REGIONS=us-east-1,us-west-2
10
+
11
+ # --- AWS (optional — public pricing works without auth) ---
12
+ # AWS_PROFILE=default
13
+ # AWS_ACCESS_KEY_ID=...
14
+ # AWS_SECRET_ACCESS_KEY=...
15
+ # AWS_DEFAULT_REGION=us-east-1
16
+ #
17
+ # Enable Cost Explorer for effective/bespoke pricing (note: costs $0.01/API call)
18
+ # OCC_AWS_ENABLE_COST_EXPLORER=false
19
+
20
+ # --- GCP (Phase 3) ---
21
+ # GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json
22
+ # OCC_GCP_PROJECT_ID=my-project
23
+ # OCC_GCP_BILLING_DATASET=my-project.billing_export
24
+ # OCC_GCP_API_KEY=... # alternative to service account for catalog-only access
@@ -0,0 +1,40 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ jobs:
9
+ build:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+
14
+ - name: Install uv
15
+ uses: astral-sh/setup-uv@v5
16
+
17
+ - name: Build package
18
+ run: uv build
19
+
20
+ - name: Upload dist
21
+ uses: actions/upload-artifact@v4
22
+ with:
23
+ name: dist
24
+ path: dist/
25
+
26
+ publish:
27
+ needs: build
28
+ runs-on: ubuntu-latest
29
+ environment: pypi
30
+ permissions:
31
+ id-token: write
32
+ steps:
33
+ - name: Download dist
34
+ uses: actions/download-artifact@v4
35
+ with:
36
+ name: dist
37
+ path: dist/
38
+
39
+ - name: Publish to PyPI
40
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,49 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.pyo
5
+ *.pyd
6
+ *.so
7
+ *.egg
8
+ *.egg-info/
9
+ dist/
10
+ build/
11
+ wheels/
12
+
13
+ # Virtual environments
14
+ .venv/
15
+ venv/
16
+ env/
17
+
18
+ # uv
19
+ .python-version
20
+
21
+ # Secrets / local config — .env.example is tracked, .env is not
22
+ .env
23
+
24
+ # SQLite cache databases
25
+ *.db
26
+ *.db-shm
27
+ *.db-wal
28
+
29
+ # Test & lint caches
30
+ .pytest_cache/
31
+ .mypy_cache/
32
+ .ruff_cache/
33
+ .coverage
34
+ htmlcov/
35
+
36
+ # IDE
37
+ .idea/
38
+ .vscode/
39
+ *.swp
40
+ *.swo
41
+
42
+ # Claude Code local state
43
+ .claude/
44
+
45
+ # Local LLM test harness — results, traces, scratch work
46
+ local-test-harness/
47
+
48
+ # macOS
49
+ .DS_Store
@@ -0,0 +1,16 @@
1
+ FROM python:3.12-slim
2
+
3
+ RUN pip install uv
4
+
5
+ WORKDIR /app
6
+ COPY pyproject.toml uv.lock* ./
7
+ RUN uv sync --frozen --no-dev 2>/dev/null || uv sync --no-dev
8
+
9
+ COPY src/ src/
10
+
11
+ ENV OCC_HTTP_HOST=0.0.0.0
12
+ ENV OCC_HTTP_PORT=8080
13
+
14
+ EXPOSE 8080
15
+
16
+ CMD ["uv", "run", "opencloudcosts", "--transport", "http", "--host", "0.0.0.0"]
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 x7even
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.
@@ -0,0 +1,298 @@
1
+ Metadata-Version: 2.4
2
+ Name: opencloudcosts
3
+ Version: 0.7.0
4
+ Summary: Open source MCP server for accurate public and effective cloud pricing (AWS, GCP, Azure)
5
+ Project-URL: Homepage, https://github.com/x7even/cloudcostmcp
6
+ Project-URL: Repository, https://github.com/x7even/cloudcostmcp
7
+ Project-URL: Issues, https://github.com/x7even/cloudcostmcp/issues
8
+ Author-email: x7even <x7sima@gmail.com>
9
+ License: MIT
10
+ License-File: LICENSE
11
+ Keywords: aws,azure,cloud,cost,finops,gcp,mcp,pricing
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Topic :: Internet
20
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
21
+ Requires-Python: >=3.11
22
+ Requires-Dist: aiosqlite>=0.20
23
+ Requires-Dist: boto3>=1.34
24
+ Requires-Dist: httpx>=0.27
25
+ Requires-Dist: mcp[cli]>=1.0
26
+ Requires-Dist: pydantic-settings>=2.0
27
+ Requires-Dist: pydantic>=2.0
28
+ Provides-Extra: dev
29
+ Requires-Dist: boto3-stubs[ce,pricing,savingsplans]>=1.34; extra == 'dev'
30
+ Requires-Dist: mypy>=1.10; extra == 'dev'
31
+ Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
32
+ Requires-Dist: pytest>=8.0; extra == 'dev'
33
+ Requires-Dist: ruff>=0.4; extra == 'dev'
34
+ Provides-Extra: gcp
35
+ Requires-Dist: google-cloud-billing>=1.13; extra == 'gcp'
36
+ Description-Content-Type: text/markdown
37
+
38
+ # OpenCloudCosts MCP
39
+
40
+ An open source MCP server that gives AI assistants accurate cloud pricing data for AWS, GCP, and Azure.
41
+
42
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
43
+
44
+ Supports both **public list pricing** (no credentials needed for AWS and Azure; GCP requires a free API key) and **effective/bespoke pricing** (post-discount: Reserved Instances, Savings Plans, CUDs, EDPs).
45
+
46
+ ## Key Use Cases
47
+
48
+ - "What is the on-demand price of an m5.xlarge in us-east-1 vs ap-southeast-2, and what's the % delta?"
49
+ - "Give me a TCO estimate for this architecture: 3x m5.xlarge + 1x 500GB gp3 EBS in us-east-1"
50
+ - "What's the cost per user if I run this stack for 50,000 MAUs?"
51
+ - "List all c6g instances in eu-west-1 with >= 8 vCPUs"
52
+ - "What's my effective hourly rate on m5.xlarge after Savings Plans?"
53
+
54
+ ## Tools
55
+
56
+ | Tool | Description |
57
+ |------|-------------|
58
+ **Pricing Lookup**
59
+
60
+ | Tool | Description |
61
+ |------|-------------|
62
+ | `get_compute_price` | Price for a specific instance type in a region |
63
+ | `get_storage_price` | EBS/S3/GCS storage pricing |
64
+ | `get_service_price` | **Generic pricing for any AWS service** — CloudWatch, data transfer, RDS, Lambda, ELB, Route53, DynamoDB, EFS, and 250+ others |
65
+ | `get_prices_batch` | Prices for multiple instance types in one call (concurrent) |
66
+ | `compare_compute_prices` | Compare same instance across multiple regions with optional baseline deltas |
67
+ | `search_pricing` | Search pricing catalog by keyword — any service, not just EC2 |
68
+
69
+ **Effective & Discount Pricing**
70
+
71
+ | Tool | Description |
72
+ |------|-------------|
73
+ | `get_effective_price` | Effective rate after account discounts (requires credentials) |
74
+ | `get_discount_summary` | All active RIs and Savings Plans with utilization % |
75
+
76
+ **Discovery**
77
+
78
+ | Tool | Description |
79
+ |------|-------------|
80
+ | `list_services` | All 260+ AWS services with pricing data |
81
+ | `list_regions` | All regions with friendly names |
82
+ | `list_instance_types` | Available instance types with vCPU/memory filters |
83
+ | `check_availability` | Is a SKU available in a region? |
84
+
85
+ **Region Analysis**
86
+
87
+ | Tool | Description |
88
+ |------|-------------|
89
+ | `find_cheapest_region` | Cheapest region for an instance type with optional baseline deltas |
90
+ | `find_available_regions` | Every region where an instance exists — prices, region names, deltas |
91
+
92
+ **Cost Estimation**
93
+
94
+ | Tool | Description |
95
+ |------|-------------|
96
+ | `estimate_bom` | TCO for a Bill of Materials |
97
+ | `estimate_unit_economics` | Cost per user/request/transaction |
98
+
99
+ **Cache**
100
+
101
+ | Tool | Description |
102
+ |------|-------------|
103
+ | `refresh_cache` | Invalidate pricing cache |
104
+ | `cache_stats` | Cache entry counts and DB size |
105
+
106
+ See [docs/tools.md](docs/tools.md) for full parameter reference and [docs/finops-guide.md](docs/finops-guide.md) for usage examples.
107
+
108
+ ## Setup
109
+
110
+ ### Prerequisites
111
+ - [uv](https://docs.astral.sh/uv/) installed (`curl -LsSf https://astral.sh/uv/install.sh | sh`)
112
+ - AWS credentials (optional — public pricing works without them)
113
+
114
+ ### Clone & configure
115
+
116
+ ```bash
117
+ git clone https://github.com/x7even/cloudcostsmcp opencloudcosts
118
+ cd opencloudcosts
119
+ cp .env.example .env
120
+ # Edit .env if you want effective pricing / Cost Explorer
121
+ ```
122
+
123
+ ### Test it works
124
+
125
+ ```bash
126
+ uv run pytest
127
+ ```
128
+
129
+ ### Run the server
130
+
131
+ ```bash
132
+ uv run opencloudcosts
133
+ ```
134
+
135
+ ### Run as HTTP server
136
+
137
+ HTTP transport enables shared/remote deployments — one server, many clients.
138
+
139
+ ```bash
140
+ # Localhost only (default)
141
+ uv run opencloudcosts --transport http --port 8080
142
+
143
+ # Bind to all interfaces (e.g. for Docker or remote access)
144
+ uv run opencloudcosts --transport http --host 0.0.0.0 --port 8080
145
+ ```
146
+
147
+ Environment variable equivalents: `OCC_HTTP_HOST` and `OCC_HTTP_PORT`.
148
+
149
+ Connect to Claude Code via `.mcp.json`:
150
+
151
+ ```json
152
+ {
153
+ "mcpServers": {
154
+ "cloudcost": {
155
+ "transport": "http",
156
+ "url": "http://localhost:8080/mcp/v1"
157
+ }
158
+ }
159
+ }
160
+ ```
161
+
162
+ ### Docker
163
+
164
+ ```bash
165
+ docker build -t opencloudcosts .
166
+ docker run -p 8080:8080 \
167
+ -e OCC_GCP_API_KEY=AIza... \
168
+ -v ~/.aws:/root/.aws:ro \
169
+ opencloudcosts
170
+ ```
171
+
172
+ The container starts in HTTP transport mode by default (bound to `0.0.0.0:8080`).
173
+ Pass cloud credentials via `-e` flags or mount your AWS credentials directory.
174
+
175
+ ### Connect to Claude Code
176
+
177
+ Add to your project's `.mcp.json`:
178
+
179
+ ```json
180
+ {
181
+ "mcpServers": {
182
+ "cloudcost": {
183
+ "command": "uv",
184
+ "args": ["run", "--directory", "/path/to/opencloudcosts", "opencloudcosts"],
185
+ "env": {
186
+ "AWS_PROFILE": "default",
187
+ "OCC_GCP_API_KEY": "AIza..."
188
+ }
189
+ }
190
+ }
191
+ }
192
+ ```
193
+
194
+ Or to `~/.claude/settings.json` for global access:
195
+
196
+ ```json
197
+ {
198
+ "mcpServers": {
199
+ "cloudcost": {
200
+ "command": "uv",
201
+ "args": ["run", "--directory", "/path/to/opencloudcosts", "opencloudcosts"]
202
+ }
203
+ }
204
+ }
205
+ ```
206
+
207
+ ### Test with MCP Inspector
208
+
209
+ ```bash
210
+ npx @modelcontextprotocol/inspector uv run --directory /path/to/opencloudcosts opencloudcosts
211
+ ```
212
+
213
+ ## AWS Credentials
214
+
215
+ | Feature | Credentials needed |
216
+ |---------|--------------------|
217
+ | Public pricing (EC2, EBS, RDS list prices) | None |
218
+ | Effective pricing (RI / SP discounts) | AWS credentials + `OCC_AWS_ENABLE_COST_EXPLORER=true` |
219
+
220
+ Minimal IAM policy for public pricing:
221
+ ```json
222
+ {
223
+ "Effect": "Allow",
224
+ "Action": ["pricing:GetProducts", "pricing:DescribeServices", "pricing:GetAttributeValues"],
225
+ "Resource": "*"
226
+ }
227
+ ```
228
+
229
+ Add these for effective pricing:
230
+ ```json
231
+ "ce:GetCostAndUsage", "savingsplans:DescribeSavingsPlans", "savingsplans:DescribeSavingsPlanRates"
232
+ ```
233
+
234
+ ## Configuration
235
+
236
+ All settings via environment variables (prefix `OCC_`) or `.env` file:
237
+
238
+ | Variable | Default | Description |
239
+ |----------|---------|-------------|
240
+ | `OCC_CACHE_TTL_HOURS` | 24 | Public price cache TTL |
241
+ | `OCC_AWS_ENABLE_COST_EXPLORER` | false | Enable effective pricing (costs $0.01/call) |
242
+ | `OCC_DEFAULT_REGIONS` | us-east-1,us-west-2 | Default regions |
243
+ | `AWS_PROFILE` | (default chain) | AWS credentials profile |
244
+
245
+ ## Caching
246
+
247
+ Prices are cached in SQLite at `~/.cache/opencloudcosts/pricing.db`. Public list prices are cached for 24 hours — AWS pricing changes infrequently. Use the `refresh_cache` tool to force a refresh.
248
+
249
+ ## GCP Setup
250
+
251
+ Unlike AWS (which has public bulk pricing endpoints), GCP's pricing API always requires at least a free API key. No credit card or billing account is needed.
252
+
253
+ **Option A — Free API key (recommended, 2 min setup):**
254
+ 1. Go to [console.cloud.google.com/apis/credentials](https://console.cloud.google.com/apis/credentials)
255
+ 2. Create a Project if you don't have one (free)
256
+ 3. Click **Create Credentials → API key**
257
+ 4. Set the key:
258
+
259
+ ```bash
260
+ export OCC_GCP_API_KEY=AIza...
261
+ ```
262
+
263
+ Or add `OCC_GCP_API_KEY=AIza...` to your `.env` file.
264
+
265
+ **Option B — Application Default Credentials** (if you already use `gcloud`):
266
+ ```bash
267
+ gcloud auth application-default login
268
+ # or set GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json
269
+ ```
270
+
271
+ **GCP instance type format:** `{family}-{series}-{vcpus}` e.g. `n2-standard-4`, `e2-highmem-8`, `c2-standard-16`
272
+
273
+ ## Azure Setup
274
+
275
+ Azure pricing is fully public — no credentials, API key, or subscription needed.
276
+
277
+ ```bash
278
+ # No configuration needed — works out of the box
279
+ uv run opencloudcosts
280
+ ```
281
+
282
+ **Azure instance type format:** ARM SKU names e.g. `Standard_D4s_v3`, `Standard_E8s_v3`, `Standard_B2ms`
283
+
284
+ **Azure pricing terms:** `on_demand` (default), `reserved_1yr`, `reserved_3yr`, `spot`
285
+
286
+ **Azure regions:** ARM region names e.g. `eastus`, `westeurope`, `southeastasia` (use `list_regions` for full list)
287
+
288
+ **GCP pricing terms:** `on_demand` (default), `spot` (preemptible), `cud_1yr`, `cud_3yr`
289
+
290
+ ## Phases
291
+
292
+ - **Phase 1** ✅ AWS public pricing (EC2, EBS, list instances)
293
+ - **Phase 2** ✅ AWS effective pricing (Cost Explorer, Savings Plans, Reserved Instances)
294
+ - **Phase 3** ✅ GCP public pricing (Compute Engine families, Persistent Disk, CUDs)
295
+ - **Phase 4** ✅ Azure public pricing (Retail Prices API, no credentials)
296
+ - **Phase 4** ✅ Streamable-HTTP transport (`--transport http`), Dockerfile
297
+ - **Phase 4** ✅ Spot price history tool (`get_spot_history`), GCP Windows pricing
298
+ - **Phase 5**: GCP effective pricing (BigQuery billing export)