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.
- opencloudcosts-0.7.0/.env.example +24 -0
- opencloudcosts-0.7.0/.github/workflows/workflow.yml +40 -0
- opencloudcosts-0.7.0/.gitignore +49 -0
- opencloudcosts-0.7.0/Dockerfile +16 -0
- opencloudcosts-0.7.0/LICENSE +21 -0
- opencloudcosts-0.7.0/PKG-INFO +298 -0
- opencloudcosts-0.7.0/README.md +261 -0
- opencloudcosts-0.7.0/docs/finops-guide.md +456 -0
- opencloudcosts-0.7.0/docs/future-tasks.md +31 -0
- opencloudcosts-0.7.0/docs/plans/T18-aws-spot-pricing.md +127 -0
- opencloudcosts-0.7.0/docs/plans/T19-ri-upfront-options.md +120 -0
- opencloudcosts-0.7.0/docs/plans/T20-os-field-bom.md +56 -0
- opencloudcosts-0.7.0/docs/plans/T21-refresh-cache-metadata.md +56 -0
- opencloudcosts-0.7.0/docs/plans/T22-gcp-major-regions.md +81 -0
- opencloudcosts-0.7.0/docs/plans/T23-phase4-error-messages.md +63 -0
- opencloudcosts-0.7.0/docs/plans/T24-test-coverage.md +180 -0
- opencloudcosts-0.7.0/docs/plans/T25-no-results-hints.md +95 -0
- opencloudcosts-0.7.0/docs/plans/T26-gcp-effective-pricing.md +129 -0
- opencloudcosts-0.7.0/docs/plans/T27-get-database-price-tool.md +128 -0
- opencloudcosts-0.7.0/docs/plans/T28-azure-provider.md +192 -0
- opencloudcosts-0.7.0/docs/plans/T29-http-transport.md +146 -0
- opencloudcosts-0.7.0/docs/plans/T30-spot-price-history.md +201 -0
- opencloudcosts-0.7.0/docs/plans/T31-gcp-windows-pricing.md +99 -0
- opencloudcosts-0.7.0/docs/roadmap.md +349 -0
- opencloudcosts-0.7.0/docs/tools.md +422 -0
- opencloudcosts-0.7.0/pyproject.toml +76 -0
- opencloudcosts-0.7.0/src/opencloudcosts/__init__.py +0 -0
- opencloudcosts-0.7.0/src/opencloudcosts/cache.py +202 -0
- opencloudcosts-0.7.0/src/opencloudcosts/config.py +46 -0
- opencloudcosts-0.7.0/src/opencloudcosts/models.py +214 -0
- opencloudcosts-0.7.0/src/opencloudcosts/providers/__init__.py +0 -0
- opencloudcosts-0.7.0/src/opencloudcosts/providers/aws.py +1166 -0
- opencloudcosts-0.7.0/src/opencloudcosts/providers/azure.py +385 -0
- opencloudcosts-0.7.0/src/opencloudcosts/providers/base.py +87 -0
- opencloudcosts-0.7.0/src/opencloudcosts/providers/gcp.py +765 -0
- opencloudcosts-0.7.0/src/opencloudcosts/server.py +139 -0
- opencloudcosts-0.7.0/src/opencloudcosts/tools/__init__.py +0 -0
- opencloudcosts-0.7.0/src/opencloudcosts/tools/availability.py +689 -0
- opencloudcosts-0.7.0/src/opencloudcosts/tools/bom.py +322 -0
- opencloudcosts-0.7.0/src/opencloudcosts/tools/lookup.py +1335 -0
- opencloudcosts-0.7.0/src/opencloudcosts/utils/__init__.py +0 -0
- opencloudcosts-0.7.0/src/opencloudcosts/utils/baseline.py +53 -0
- opencloudcosts-0.7.0/src/opencloudcosts/utils/gcp_specs.py +437 -0
- opencloudcosts-0.7.0/src/opencloudcosts/utils/regions.py +215 -0
- opencloudcosts-0.7.0/src/opencloudcosts/utils/units.py +68 -0
- opencloudcosts-0.7.0/tests/__init__.py +0 -0
- opencloudcosts-0.7.0/tests/conftest.py +29 -0
- opencloudcosts-0.7.0/tests/test_cache.py +87 -0
- opencloudcosts-0.7.0/tests/test_models.py +80 -0
- opencloudcosts-0.7.0/tests/test_providers/__init__.py +0 -0
- opencloudcosts-0.7.0/tests/test_providers/test_aws.py +654 -0
- opencloudcosts-0.7.0/tests/test_providers/test_azure.py +399 -0
- opencloudcosts-0.7.0/tests/test_providers/test_gcp.py +439 -0
- opencloudcosts-0.7.0/tests/test_providers/test_gcp_cloud_storage_sql.py +272 -0
- opencloudcosts-0.7.0/tests/test_tools/__init__.py +0 -0
- opencloudcosts-0.7.0/tests/test_tools/test_azure_list_instance_types.py +147 -0
- opencloudcosts-0.7.0/tests/test_tools/test_bom.py +184 -0
- opencloudcosts-0.7.0/tests/test_tools/test_bom_extended.py +237 -0
- opencloudcosts-0.7.0/tests/test_tools/test_cache_tools.py +130 -0
- opencloudcosts-0.7.0/tests/test_tools/test_fargate_bedrock.py +353 -0
- opencloudcosts-0.7.0/tests/test_tools/test_gcp_major_regions.py +252 -0
- opencloudcosts-0.7.0/tests/test_tools/test_list_instance_types_effective_max.py +202 -0
- opencloudcosts-0.7.0/tests/test_tools/test_lookup_db.py +242 -0
- opencloudcosts-0.7.0/tests/test_tools/test_lookup_extended.py +229 -0
- opencloudcosts-0.7.0/tests/test_tools/test_lookup_no_results.py +251 -0
- opencloudcosts-0.7.0/tests/test_tools/test_phase2.py +203 -0
- opencloudcosts-0.7.0/tests/test_tools/test_storage_monthly_estimate.py +309 -0
- opencloudcosts-0.7.0/tests/test_tools/test_t23_gcp_errors.py +149 -0
- 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)
|
|
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)
|