sample-aws-pricing-calculator-mcp 1.2.1 → 1.2.4
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/README.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
- **Build estimates from natural language** - agent constructs the estimate via MCP tools; the server saves it to AWS Pricing Calculator and returns a shareable URL.
|
|
10
10
|
- **No AWS credentials required** - uses public, unauthenticated calculator.aws CDN endpoints.
|
|
11
11
|
- **Live service definitions** - fetches the AWS Pricing Calculator manifest at runtime (~436 services).
|
|
12
|
-
- **Verified Configs Catalog** -
|
|
12
|
+
- **Verified Configs Catalog** - 18 per-service entries declaring the smallest config that produces a priced estimate, with documented gotchas.
|
|
13
13
|
- **Lint refusal before save** - refuses estimates the calculator would render read-only or required-input, with actionable recovery hints.
|
|
14
14
|
- **Import existing estimates** - download by URL or ID as JSON (for region swaps, modifications) or Markdown (for LLM analysis).
|
|
15
15
|
- **Two transport modes** - stdio (default, for local clients like Claude Desktop, Kiro, Cursor) and optional HTTP (`MCP_TRANSPORT=http`) for hosted deployments.
|
|
@@ -182,10 +182,11 @@ EC2 uses a custom config transform (`lib/ec2.js`) that converts agent-friendly f
|
|
|
182
182
|
|
|
183
183
|
### Partition support
|
|
184
184
|
|
|
185
|
-
The server supports
|
|
185
|
+
The server supports the following AWS partitions:
|
|
186
186
|
- `aws` — standard commercial regions
|
|
187
187
|
- `aws-iso` — US ISO East/West
|
|
188
188
|
- `aws-iso-b` — US ISOB East
|
|
189
|
+
- `aws-eusc` (Experimental) AWS European Sovereign Cloud
|
|
189
190
|
|
|
190
191
|
### Export to calculator.aws
|
|
191
192
|
|
|
@@ -274,7 +275,7 @@ The catalog (`catalog/services/*.json`) is a set of curated per-service entries.
|
|
|
274
275
|
|
|
275
276
|
| Status | Count | Meaning |
|
|
276
277
|
|---|---|---|
|
|
277
|
-
| `verified` |
|
|
278
|
+
| `verified` | 18 | Reverified end-to-end: a fresh save from `minimalConfig` renders non-zero cost in calculator.aws |
|
|
278
279
|
| `partial` | 1 | Authored but not fully verified |
|
|
279
280
|
| **Total entries** | **17** | Out of ~436 services in the manifest |
|
|
280
281
|
|
|
@@ -299,7 +300,7 @@ The cost-oracle sweep saves a fresh estimate from each verified entry's `minimal
|
|
|
299
300
|
|
|
300
301
|
The 1.2.0 catalog content was audited along three independent axes before release.
|
|
301
302
|
|
|
302
|
-
**Cost-rendering correctness (deterministic).** The `validate-catalog:cost` sweep saves each of the
|
|
303
|
+
**Cost-rendering correctness (deterministic).** The `validate-catalog:cost` sweep saves each of the verified entries' `minimalConfig` and confirms a non-zero rendered cost via the DOM oracle. Result: **entries render priced cost** (e.g. Lambda $699.80/mo, RDS PostgreSQL $175.75/mo, EC2 $70.08/mo).
|
|
303
304
|
|
|
304
305
|
**Trap content audit (manifest cross-check + LLM cold-eye).** Each `traps[]` claim was checked against the live manifest data and, where applicable, the saved blob of the corresponding `verifiedEstimateId`. Result across the 60 shipped traps: **0 hallucinated claims**. Every trap was then classified by the type of utility it provides to a runtime agent — falling roughly into:
|
|
305
306
|
|
|
@@ -321,7 +322,7 @@ The trap audit and earns-place data are summarized here for transparency; the de
|
|
|
321
322
|
- With the default `memory` store, in-flight estimates don't persist across restarts. Use `ESTIMATES_STORE=dynamodb` for stateless or multi-replica deployments.
|
|
322
323
|
- No local cost calculation — pricing is computed by AWS when viewing the shareable link. Press **Update estimate** in the calculator UI to reflect the latest pricing.
|
|
323
324
|
- Only `https://calculator.aws/` is supported.
|
|
324
|
-
- Catalog coverage is partial (
|
|
325
|
+
- Catalog coverage is partial (verified entries against ~436 manifest services). Uncatalogued services still benefit from the lint and trace events; they just don't get the magnitude-calibration role the catalog plays.
|
|
325
326
|
|
|
326
327
|
## Security
|
|
327
328
|
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "../schema.json",
|
|
3
|
+
"serviceCode": "aWSDataTransfer",
|
|
4
|
+
"displayName": "AWS Data Transfer",
|
|
5
|
+
"templateId": "awsDatatransfer",
|
|
6
|
+
"status": "verified",
|
|
7
|
+
"lastVerifiedAt": "2026-06-17",
|
|
8
|
+
"verifiedEstimateId": "0000000000000000000000000000000000000000",
|
|
9
|
+
"traps": [
|
|
10
|
+
"The dataTransfer field is a composite dataTransferV2 widget. Its value must be an array of transfer entries, each with entryType, value, unit, and a region field. Valid entryTypes: INBOUND, OUTBOUND, INTRA_REGION.",
|
|
11
|
+
"Unit must be \"tb_month\" or \"gb_month\".",
|
|
12
|
+
"OUTBOUND entries require a \"toRegion\" field — use \"External\" for internet or \"other\" for other AWS regions. INBOUND entries require a \"fromRegion\" field with the same options. INTRA_REGION requires neither.",
|
|
13
|
+
"All three entryTypes (INBOUND, OUTBOUND, INTRA_REGION) must be present in the array even if their value is \"0\"."
|
|
14
|
+
],
|
|
15
|
+
"minimalConfig": {
|
|
16
|
+
"region": "us-east-1",
|
|
17
|
+
"description": "Data Transfer",
|
|
18
|
+
"dataTransfer": {
|
|
19
|
+
"value": [
|
|
20
|
+
{ "entryType": "INBOUND", "value": "0", "unit": "tb_month", "fromRegion": "External" },
|
|
21
|
+
{ "entryType": "OUTBOUND", "value": "1", "unit": "tb_month", "toRegion": "External" },
|
|
22
|
+
{ "entryType": "INTRA_REGION", "value": "1", "unit": "tb_month" }
|
|
23
|
+
]
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "../schema.json",
|
|
3
|
+
"serviceCode": "amazonElasticBlockStore",
|
|
4
|
+
"displayName": "Amazon Elastic Block Store (EBS)",
|
|
5
|
+
"templateId": "elasticBlockStore",
|
|
6
|
+
"status": "partial",
|
|
7
|
+
"lastVerifiedAt": "2026-06-17",
|
|
8
|
+
"verifiedEstimateId": "23290262d80f4d88c38df1ce90524f8d129db99f",
|
|
9
|
+
"traps": [
|
|
10
|
+
"gp3Throughput is a throughput-type field. The correct format is {\"value\": \"<number>\", \"unit\": \"mbps\"}. Do NOT use the options id from get_service_fields — the unit is always \"mbps\".",
|
|
11
|
+
"gp3Throughput minimum is 125 MBps (included in baseline), maximum is 2000 MBps. Only throughput above 125 MBps incurs additional cost.",
|
|
12
|
+
"gp3Iops minimum is 3000 (included in baseline), maximum is 80000. Only IOPS above 3000 incur additional cost.",
|
|
13
|
+
"storageType must be one of the full option IDs from the dropdown (e.g. \"Storage General Purpose gp3 GB Mo\"), not shorthand like \"gp3\".",
|
|
14
|
+
"snapshotFrequency uses numeric string IDs (e.g. \"0\" for no snapshots, \"30\" for daily, \"729\" for hourly) — not human-readable labels."
|
|
15
|
+
],
|
|
16
|
+
"minimalConfig": {
|
|
17
|
+
"region": "us-east-1",
|
|
18
|
+
"description": "EBS gp3 Volume",
|
|
19
|
+
"numberOfInstances": "1",
|
|
20
|
+
"durationOfInstanceRuns": {"value": "730", "unit": "hours"},
|
|
21
|
+
"storageType": "Storage General Purpose gp3 GB Mo",
|
|
22
|
+
"storageAmount": {"value": "30", "unit": "gb|NA"},
|
|
23
|
+
"gp3Iops": "3000",
|
|
24
|
+
"gp3Throughput": {"value": "125", "unit": "mbps"},
|
|
25
|
+
"snapshotFrequency": "0"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
},
|
|
15
15
|
{
|
|
16
16
|
"field": "pricingStrategy",
|
|
17
|
-
"hint": "Pricing model. Accepts shorthand strings (ondemand,
|
|
17
|
+
"hint": "Pricing model. Accepts shorthand strings for simple cases OR a full object for committed pricing.\n\nShorthand (On-Demand/Spot only): \"ondemand\", \"spot\"\n\nFull object (required for any committed/discounted pricing):\n- EC2 Instance Savings Plans: {\"model\":\"instanceSavings\",\"term\":\"1 Year\",\"upfrontPayment\":\"None\"}\n- Compute Savings Plans: {\"model\":\"computeSavings\",\"term\":\"1 Year\",\"upfrontPayment\":\"None\"}\n- Standard Reserved Instances (dedicated tenancy only): {\"model\":\"standard\",\"term\":\"1 Year\",\"upfrontPayment\":\"None\"}\n- Convertible Reserved Instances (dedicated tenancy only): {\"model\":\"convertible\",\"term\":\"1 Year\",\"upfrontPayment\":\"None\"}\n\nValid term values: \"1 Year\", \"3 Year\" (exact case, full words)\nValid upfrontPayment values: \"None\", \"Partial\", \"All\" (exact case)\n\nCRITICAL: Do NOT use shorthand \"reserved\" or \"instanceSavings\" for committed pricing — these may silently fall back to On-Demand or produce $0 costs. Always use the full object format for any non-OnDemand, non-Spot pricing. EstimateBuilder normalizes via lib/ec2.js.",
|
|
18
18
|
"enum": [
|
|
19
19
|
"ondemand",
|
|
20
20
|
"reserved",
|
|
@@ -28,12 +28,17 @@
|
|
|
28
28
|
],
|
|
29
29
|
"traps": [
|
|
30
30
|
"Use serviceCode 'ec2Enhancement' with templateId 'template'. The legacy (eC2Next, quickEstimate) format saves cleanly but renders Read-only — the calculator cannot rehydrate it. EstimateBuilder forces this transformation automatically; do not bypass it.",
|
|
31
|
-
"Reserved Instances (standard, convertible) are HIDDEN under shared tenancy. For shared,
|
|
31
|
+
"Reserved Instances (standard, convertible) are HIDDEN under shared tenancy. For shared tenancy with committed pricing, ALWAYS use the full object format: {\"model\":\"instanceSavings\",\"term\":\"1 Year\",\"upfrontPayment\":\"None\"} or {\"model\":\"computeSavings\",\"term\":\"1 Year\",\"upfrontPayment\":\"None\"}. The shorthand \"reserved\" and \"instanceSavings\" strings are unreliable and may produce On-Demand pricing or $0 costs. Real Standard/Convertible RIs require tenancy:\"dedicated\" or \"host\".",
|
|
32
32
|
"pricingStrategy term values are exact-case strings: '1 Year', '3 Year' — full words, capitalized. Lowercase variants silently produce wrong pricing.",
|
|
33
33
|
"pricingStrategy upfrontPayment values: 'None', 'Partial', 'All'. EstimateBuilder accepts shorthand 'No' and converts to 'None'.",
|
|
34
34
|
"The calculator silently demands tenancy, workload, workloadSelection, dataTransferForEC2, detailedMonitoringCheckbox, and ec2AdvancedPricingMetrics — even though the PCT does not mark them validations.required. EstimateBuilder injects all of these via lib/ec2.js#transformConfig.",
|
|
35
|
-
"utilization is HIDDEN inside the pricingStrategy component and does NOT appear in get_service_fields' field list.
|
|
36
|
-
"workload is the INSTANCE COUNT — use it for the user's quantity. For 'two instances' set workload: 2 (one entry) or save two entries with workload: 1 each. Either is fine. Do NOT save workload: 1 for 'two instances' and stash the '2' only in description (the saved estimate prices for one instance and the user reads two). Do NOT compensate for utilization with workload (e.g. workload: 0.8 to fake 80% utilization) — the total cost may match but the saved estimate structurally lies about how many instances are running. Use the explicit utilization field instead."
|
|
35
|
+
"utilization is HIDDEN inside the pricingStrategy component and does NOT appear in get_service_fields' field list. To set utilization, pass top-level utilization: 'N' (string, 1–100); EstimateBuilder routes it into pricingStrategy.value.utilizationValue.",
|
|
36
|
+
"workload is the INSTANCE COUNT — use it for the user's quantity. For 'two instances' set workload: 2 (one entry) or save two entries with workload: 1 each. Either is fine. Do NOT save workload: 1 for 'two instances' and stash the '2' only in description (the saved estimate prices for one instance and the user reads two). Do NOT compensate for utilization with workload (e.g. workload: 0.8 to fake 80% utilization) — the total cost may match but the saved estimate structurally lies about how many instances are running. Use the explicit utilization field instead.",
|
|
37
|
+
"The dataTransferForEC2 field is a composite widget. Its value must be an array of transfer entries, each with entryType, value, unit, and a region field. Valid entryTypes: INBOUND, OUTBOUND, INTRA_REGION.",
|
|
38
|
+
"Unit must be \"tb_month\" or \"gb_month\".",
|
|
39
|
+
"OUTBOUND entries require a \"toRegion\" field — use \"External\" for internet or \"other\" for other AWS regions. INBOUND entries require a \"fromRegion\" field with the same options. INTRA_REGION requires neither.",
|
|
40
|
+
"All three entryTypes (INBOUND, OUTBOUND, INTRA_REGION) must be present in the array even if their value is \"0\"."
|
|
41
|
+
|
|
37
42
|
],
|
|
38
43
|
"minimalConfig": {
|
|
39
44
|
"region": "us-east-1",
|
|
@@ -46,8 +51,8 @@
|
|
|
46
51
|
"defaultFields": {
|
|
47
52
|
"dataTransferForEC2": {
|
|
48
53
|
"value": [
|
|
49
|
-
{ "entryType": "INBOUND", "value": "", "unit": "tb_month", "fromRegion": "" },
|
|
50
|
-
{ "entryType": "OUTBOUND", "value": "", "unit": "tb_month", "toRegion": "" },
|
|
54
|
+
{ "entryType": "INBOUND", "value": "", "unit": "tb_month", "fromRegion": "External" },
|
|
55
|
+
{ "entryType": "OUTBOUND", "value": "", "unit": "tb_month", "toRegion": "External" },
|
|
51
56
|
{ "entryType": "INTRA_REGION", "value": "", "unit": "tb_month" }
|
|
52
57
|
]
|
|
53
58
|
}
|