Skip to content

Agent-driven cloud cost management connects Claude Code, Codex or Cursor to a read-only billing MCP server (AWS Billing and Cost Management, or Vantage for multi-cloud). The agent explains what moved the bill, ranks right-sizing candidates by risk and drafts the infrastructure-as-code change. Cost Explorer totals and terraform plan verify it; a human approves each change.

This page is for the developer or tech lead who owns a service’s cloud bill. Finance asks why spend jumped this month, nobody remembers launching anything, and the growth sits in an untagged EC2-Other line. The console answers one question per twenty clicks. You want a ranked story with evidence, and a change you can merge safely.

This page covers cloud infrastructure spend. For what the coding agents themselves cost, see AI usage cost governance.

What you get from an agent-driven FinOps loop

Section titled “What you get from an agent-driven FinOps loop”
  • A read-only billing MCP setup for Claude Code, Codex and Cursor, with an IAM role that cannot change a resource.
  • Six copy-paste prompts: cost drivers, untagged spend, anomaly triage, right-sizing to Terraform, a quarterly forecast, and over-requested Kubernetes deployments.
  • A verification routine that checks the agent’s numbers against Cost Explorer without re-reading its analysis line by line.
  • A failure-modes list for the ways this goes wrong: wrong account, quiet lookback windows, missing tags, and an agent with write access.

Which billing MCP server should you connect?

Section titled “Which billing MCP server should you connect?”

Pick the narrowest server that answers your cost questions. A general cloud server with write tools is the wrong default for FinOps work.

Your spendServerTransport and authWhy this one
AWS onlyawslabs.billing-cost-management-mcp-server (PyPI 0.0.39, checked 2026-09-26)stdio via uvx, your AWS_PROFILECost Explorer, forecasts, Cost Anomaly Detection, Budgets, Compute Optimizer, Cost Optimization Hub, Savings Plans and cost allocation tags in one server
AWS, Azure, GCP, Kubernetes and SaaSVantage MCPHosted https://mcp.vantage.sh/mcp with OAuth, or npx -y vantage-mcp-server with a VANTAGE_TOKENOne normalised view across providers, if your organisation already uses Vantage
Broader AWS work (Lambda runtimes, drift)AWS MCP Server through the Agent Toolkit for AWSSigV4 proxy via uvxAWS’s recommended general server. Setup is on cloud and platform MCP servers

If you would rather not keep a server connected, the Agent Toolkit for AWS aws-core plugin also ships an aws-billing-and-cost-management skill. It covers cost analysis, Savings Plans and Reserved Instances, Compute Optimizer right-sizing, anomalies and CUR queries with Athena, and suits a guided cost review; install steps are on cloud and platform MCP servers. Either way, the read-only IAM role below is the control.

As of 0.0.39 (checked 2026-09-26), the AWS billing server’s tools read and analyse; none of them resize or delete resources (Storage Lens queries do write Athena results to S3). Enforce that with IAM rather than trusting the tool list. The Vantage server can also create Vantage objects such as reports, so scope its token accordingly.

New to MCP? Start with essential MCP servers.

  1. Create a read-only billing role. Attach a policy with read actions only: ce:Get*, ce:Describe*, ce:List*, compute-optimizer:Get*, cost-optimization-hub:Get*, cost-optimization-hub:List*, savingsplans:Describe*, pricing:Get*, pricing:Describe*, budgets:ViewBudget and budgets:DescribeBudgetActionsFor*. The Savings Plans and commitment-analysis generation tools also need ce:StartSavingsPlansPurchaseRecommendationGeneration and ce:StartCommitmentPurchaseAnalysis. Those start a recommendation job and change no resource, but they are not Get actions, so leave them out if you do not use those tools. The server’s README lists the exact actions per tool. Give it a profile name such as finops-readonly in ~/.aws/config.

  2. Confirm the identity before the agent sees it. In a terminal, run:

    Terminal window
    aws sts get-caller-identity --profile finops-readonly

    The account ID must be the payer (management) account if you want organisation-wide spend. A member account sees only its own costs.

  3. Install uv from Astral’s installation guide. The server runs through uvx.

  4. Register the server. The definition is the same for every tool; only the file or command differs.

    Terminal window
    claude mcp add aws-billing \
    -e AWS_PROFILE=finops-readonly -e AWS_REGION=us-east-1 -e FASTMCP_LOG_LEVEL=ERROR \
    -- uvx awslabs.billing-cost-management-mcp-server@latest

    The default scope is local, which keeps the profile name out of the repository. Check the connection with claude mcp list, or /mcp inside a session.

  5. Add Vantage if you run more than one cloud. The hosted server signs you in through the browser, so no token sits in a config file:

    Terminal window
    # Claude Code: then run /mcp in a session to finish OAuth
    claude mcp add --transport http vantage https://mcp.vantage.sh/mcp
    # Codex: run `codex mcp login vantage` if it asks you to authenticate
    codex mcp add vantage --url https://mcp.vantage.sh/mcp

    In Cursor, add "vantage": { "url": "https://mcp.vantage.sh/mcp" } under mcpServers.

Explain the bill: which services moved, and why?

Section titled “Explain the bill: which services moved, and why?”

Run analysis sessions in a mode that cannot edit files, so the agent reads and reports only.

Start with claude --permission-mode plan, or press Shift+Tab until the mode reads plan. Claude can call the billing tools and write its findings, but it proposes rather than edits. Claude may ask before each MCP tool call; approve the read-only billing tools or add them to permissions.allow.

Then ask a question with a named metric, window, grouping and output shape:

The last numbered line is the one that makes the output checkable. You compare one total, not ten rows (see how to prove the numbers are right).

The usual next question is the untagged spend, because a large untagged bucket is the most common reason nobody can explain a bill:

Tag activation applies from the moment you switch it on, not to past bills, unless you request a backfill. Expect this month’s report to stay partly untagged even after you fix the tags.

Triage an anomaly without paging the whole team

Section titled “Triage an anomaly without paging the whole team”

If AWS Cost Anomaly Detection is enabled, the server can read its findings. Let the detector decide what is anomalous and let the agent explain it; an agent inventing its own thresholds produces a different answer every run. For versioned, replay-tested alert rules, use deterministic anomaly detection.

Turn a right-sizing recommendation into a reviewed change

Section titled “Turn a right-sizing recommendation into a reviewed change”

Compute Optimizer and Cost Optimization Hub produce the candidates; the agent’s job is to rank them, attach the risk, and edit your infrastructure-as-code rather than the live resource. For the IaC review workflow itself, see infrastructure as code with AI.

How you drive the edit differs by tool:

Leave plan mode (Shift+Tab to acceptEdits) for this prompt only. Claude asks before it runs terraform plan unless you have allowed that command in .claude/settings.json. Keep terraform apply out of the allow list.

The change then goes through your normal pipeline: pull request, terraform plan in CI, and approval by the service owner. Savings Plans and Reserved Instance purchases never go through the agent. Those are one- or three-year financial commitments, so the agent drafts the recommendation and finance signs it off.

For approval modes and sandboxes side by side, see permissions, sandboxes and approval modes.

Forecast next quarter’s spend and check it against budgets

Section titled “Forecast next quarter’s spend and check it against budgets”

A flat “same as last month” projection fails for any service with seasonality. Use Cost Explorer’s own forecast, which includes a prediction interval, and have the agent join it to your budgets:

Forecasts inherit the quality of your tags. If a quarter of the bill is untagged, every per-team number is an estimate; fix tag coverage first.

For a scheduled report, compute the numbers in code and let the model only explain them. The deltas are then deterministic and testable, and the model cannot miscount.

// weekly-cost-report.mts: run with `npx tsx weekly-cost-report.mts`
// (.mts makes tsx emit ESM, which the top-level await below needs)
import { CostExplorer } from '@aws-sdk/client-cost-explorer';
import Anthropic from '@anthropic-ai/sdk';
const ce = new CostExplorer({ region: 'us-east-1' }); // uses AWS_PROFILE
const anthropic = new Anthropic(); // reads ANTHROPIC_API_KEY from the environment
const day = (offset: number) => new Date(Date.now() - offset * 864e5).toISOString().slice(0, 10);
async function byService(start: string, end: string): Promise<Map<string, number>> {
const { ResultsByTime = [] } = await ce.getCostAndUsage({
TimePeriod: { Start: start, End: end },
Granularity: 'MONTHLY',
Metrics: ['UnblendedCost'],
GroupBy: [{ Type: 'DIMENSION', Key: 'SERVICE' }],
});
const totals = new Map<string, number>();
for (const period of ResultsByTime) {
for (const g of period.Groups ?? []) {
const name = g.Keys?.[0] ?? 'unknown';
totals.set(name, (totals.get(name) ?? 0) + Number(g.Metrics?.UnblendedCost?.Amount ?? 0));
}
}
return totals;
}
// Skip the last two days: Cost Explorer data for today and yesterday is still incomplete.
const [current, previous] = await Promise.all([byService(day(9), day(2)), byService(day(16), day(9))]);
const movers = [...current]
.map(([service, cost]) => ({ service, cost, delta: cost - (previous.get(service) ?? 0) }))
.sort((a, b) => b.delta - a.delta)
.slice(0, 5);
const msg = await anthropic.messages.create({
model: 'claude-opus-5-5',
max_tokens: 4000, // Opus 5.5 always thinks, and thinking tokens count against this limit
messages: [{
role: 'user',
content: `These are the five AWS services whose cost grew most this week versus last week, as JSON.
Write a five-line summary for the engineering channel. Use the numbers exactly as given; do not compute new ones.
${JSON.stringify(movers)}`,
}],
});
for (const block of msg.content) if (block.type === 'text') console.log(block.text);

claude-opus-5-5 is Anthropic’s recommended starting model (and Claude Code’s default from v2.1.280, on both release channels); a cheaper model works for a summary this short, and the models hub lists prices. Store ANTHROPIC_API_KEY in your scheduler’s secret store, never in the script. The Budgets API lives in a separate package, @aws-sdk/client-budgets.

When the spend sits in a cluster, the waste usually hides in container requests far above real usage. Connect a Kubernetes MCP server in read-only mode; setup and the read_only = true TOML setting are on infrastructure MCP servers. The server sees current usage from the metrics API, not history, so a request cut based on one afternoon is a guess. Pair it with your Prometheus data for the p95 over at least a week.

How do you prove the agent’s cost numbers are right?

Section titled “How do you prove the agent’s cost numbers are right?”

You do not re-read the analysis. You check a few numbers that the rest depends on, and you let existing gates check the change.

What to verifyHowWho signs off
The bill totalsRun the same query yourself and compare the one grand total the prompt asked for: aws ce get-cost-and-usage --time-period Start=2026-08-01,End=2026-09-01 --granularity MONTHLY --metrics UnblendedCost --group-by Type=DIMENSION,Key=SERVICE --profile finops-readonly (replace the dates with the period the agent stated). A mismatch means the agent queried a different period, account or metric.You
Each recommendation is realEvery row must name a resource ARN or ID and a Compute Optimizer or Cost Optimization Hub finding. Spot-check one with aws compute-optimizer get-ec2-instance-recommendations --instance-arns INSTANCE_ARN. INSTANCE_ARN is the ARN from the agent’s row. Drop any row without a source.You
The change does only what it saysterraform plan in CI shows one attribute change per resource and no replacements you did not expect. A forces replacement line on a database is a stop.Service owner, in the pull request
Production survives itWatch latency, error rate and throttling for seven days after the change, against the service’s SLO, with the previous instance type recorded for rollback. See monitoring and observability.On-call
The saving happenedNext month, rerun the cost-driver prompt and compare the service’s cost with the estimate you merged.Tech lead

What breaks when an agent analyses cloud costs?

Section titled “What breaks when an agent analyses cloud costs?”
  1. Every query comes back empty or with an access error. The profile resolves to the wrong account, the role lacks ce:Get*, or Cost Explorer was never enabled in the billing console. Run aws sts get-caller-identity --profile finops-readonly, fix the policy, enable Cost Explorer, and restart the agent so it relaunches the server.

  2. The server never starts. uvx is not on the PATH the agent process sees, which is common when the agent is launched from a desktop app. Run uvx awslabs.billing-cost-management-mcp-server@latest in a terminal: it should start and wait on stdin. Then restart the tool, or set the absolute path to uvx as the command.

  3. The numbers disagree with the console. Cost Explorer data is not real time, so today’s and yesterday’s spend may still be incomplete. The agent may also have used BlendedCost or AmortizedCost, or a member account instead of the payer. Ask it to restate the metric, period and account, then rerun.

  4. The bill for the analysis grows. Cost Explorer API requests are billed per request, and an agent that loops over daily granularity per service can issue hundreds. Ask for monthly granularity first, narrow to daily only on the services that moved, and do not attach the billing server to an unattended loop.

  5. A right-size causes throttling. The recommendation came from a quiet lookback window, or from average rather than peak utilisation. Revert to the recorded instance type through the same pipeline, then rerun the right-sizing prompt with a lookback that includes your monthly peak.

  6. Allocation numbers are wrong by team. Tags are missing or were activated mid-month. Treat per-team figures as estimates until tag coverage is high, and rerun the untagged-spend prompt after each tagging change.

  7. The agent reports a server or tool that does not exist. A prompt that names a server you never configured does nothing, and the agent may fill the gap with plausible figures. Use the exact server name from claude mcp list or codex mcp list, and reject any figure that the verification table cannot reproduce.