estimate_cost
Estimate the monthly cloud bill for an architecture specification. Returns per-component cost breakdown, total monthly cost, data-transfer costs, and currency. Deterministic and works offline with no network calls.
Instructions
Estimate the monthly cloud bill for an architecture spec.
Returns a structured estimate with per-component breakdown, total monthly cost, data-transfer costs, and currency. Deterministic: same spec + tier yields same result.
When to use: You need the numeric bill for one architecture on one
provider+tier combination. For multi-provider comparison of just the
costs, use compare_provider_costs. For side-by-side architecture +
cost comparison across providers, use compare_providers + this tool.
Behavior: Pure computation — no LLM, no network, no API costs. Works offline. Does not deploy or touch cloud resources.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| spec_json | Yes | ArchSpec to price. Pricing is resolved per-component against a bundled SQLite catalog (no network calls), with formula dispatch for serverless/managed services and a static fallback for rare ones. | |
| pricing_tier | No | Pricing tier multiplier applied to compute and data-store components. Values: 'on_demand' (1.0x), 'reserved_1yr' (0.6x), 'reserved_3yr' (0.4x), 'spot' (0.3x). | on_demand |
Implementation Reference
- The MCP tool handler for 'estimate_cost'. Takes an ArchSpec dict and pricing_tier, validates with ArchSpec.model_validate, then calls CostEngine().estimate() to compute monthly cost breakdown. Returns CostEstimate dict.
def estimate_cost( spec_json: Annotated[ dict, Field( description=( "ArchSpec to price. Pricing is resolved per-component against a " "bundled SQLite catalog (no network calls), with formula dispatch " "for serverless/managed services and a static fallback for rare ones." ), ), ], pricing_tier: Annotated[ str, Field( description=( "Pricing tier multiplier applied to compute and data-store components. " "Values: 'on_demand' (1.0x), 'reserved_1yr' (0.6x), " "'reserved_3yr' (0.4x), 'spot' (0.3x)." ), examples=["on_demand", "reserved_1yr", "reserved_3yr", "spot"], ), ] = "on_demand", ) -> dict: """Estimate the monthly cloud bill for an architecture spec. Returns a structured estimate with per-component breakdown, total monthly cost, data-transfer costs, and currency. Deterministic: same spec + tier yields same result. When to use: You need the numeric bill for one architecture on one provider+tier combination. For multi-provider comparison of just the costs, use `compare_provider_costs`. For side-by-side architecture + cost comparison across providers, use `compare_providers` + this tool. Behavior: Pure computation — no LLM, no network, no API costs. Works offline. Does not deploy or touch cloud resources. """ from cloudwright.cost import CostEngine from cloudwright.spec import ArchSpec spec = ArchSpec.model_validate(spec_json) estimate = CostEngine().estimate(spec, pricing_tier=pricing_tier) return estimate.model_dump(exclude_none=True) - packages/mcp/cloudwright_mcp/tools/cost.py:9-10 (registration)Tool registration via @mcp.tool() decorator on the estimate_cost function inside the register() function.
def register(mcp: FastMCP) -> None: @mcp.tool() - Input schema: spec_json (dict, ArchSpec) and pricing_tier (str, default 'on_demand', choices: on_demand/reserved_1yr/reserved_3yr/spot).
def estimate_cost( spec_json: Annotated[ dict, Field( description=( "ArchSpec to price. Pricing is resolved per-component against a " "bundled SQLite catalog (no network calls), with formula dispatch " "for serverless/managed services and a static fallback for rare ones." ), ), ], pricing_tier: Annotated[ str, Field( description=( "Pricing tier multiplier applied to compute and data-store components. " "Values: 'on_demand' (1.0x), 'reserved_1yr' (0.6x), " "'reserved_3yr' (0.4x), 'spot' (0.3x)." ), examples=["on_demand", "reserved_1yr", "reserved_3yr", "spot"], ), ] = "on_demand", ) -> dict: - CostEstimate return type schema: monthly_total, breakdown (list of ComponentCost), data_transfer_monthly, currency, as_of.
class CostEstimate(BaseModel): monthly_total: float breakdown: list[ComponentCost] = Field(default_factory=list) data_transfer_monthly: float = 0.0 currency: str = "USD" as_of: str = Field(default_factory=lambda: date.today().isoformat()) - CostEngine.estimate() method — the core logic that prices each component via _price_component (3-tier resolution: catalog DB, registry formulas, static fallback), sums data transfer costs, and returns a CostEstimate.
class CostEngine: def __init__(self, catalog: Catalog | None = None, registry: ServiceRegistry | None = None): self.catalog = catalog or Catalog() self.registry = registry or get_registry() def estimate( self, spec: ArchSpec, pricing_tier: str = "on_demand", workload_profile: str | None = None, ) -> CostEstimate: """Price every component in an ArchSpec and return a full breakdown. Args: spec: The architecture specification to price. pricing_tier: Pricing model — on_demand, reserved_1yr, reserved_3yr, spot. workload_profile: Optional sizing profile — small, medium, large, enterprise. When set, applies realistic defaults for request volumes, storage sizes, node counts, and data transfer that match production workloads. """ breakdown: list[ComponentCost] = [] for comp in spec.components: effective = _apply_profile(comp, workload_profile) if workload_profile else comp monthly = self._price_component(effective, spec.provider, spec.region, pricing_tier) hourly = round(monthly / 730, 4) if monthly > 0 else None notes = self._cost_notes(effective) breakdown.append( ComponentCost( component_id=comp.id, service=comp.service, monthly=monthly, hourly=hourly, notes=notes, ) ) component_total = round(sum(c.monthly for c in breakdown), 2) data_transfer = self._estimate_data_transfer(spec, workload_profile=workload_profile) total = round(component_total + data_transfer, 2) return CostEstimate( monthly_total=total, breakdown=breakdown, data_transfer_monthly=data_transfer, currency="USD", as_of=date.today().isoformat(), )