Vantage MCP for AI Agents
What Is Vantage MCP
Vantage is the cloud cost-management tool HungryHub uses for rightsizing recommendations and savings analysis (see EKS Cost Optimization 2026 and Kubernetes CPU Request Rightsizing).
Vantage ships two official MCP (Model Context Protocol)
servers, both remote HTTP — no local install, no npx:
| Server | URL | Auth | Purpose |
|---|---|---|---|
| Vantage (data) | https://mcp.vantage.sh/mcp | OAuth (or API token) | Query your real cost data, reports, recommendations |
| Vantage Docs | https://docs.vantage.sh/mcp | None (public) | Search Vantage product docs, setup guides |
Source docs:
- Data MCP — https://docs.vantage.sh/vantage_mcp
- Docs MCP — https://docs.vantage.sh/docs_mcp
MCP is an open protocol, so both servers work with any compatible client (Claude Code, Copilot, Cursor, OpenCode, custom agents).
What the Agent Can Do
Vantage (data) MCP — the agent queries your live Vantage account: cost reports, provider resource reports, rightsizing recommendations, and savings opportunities. This replaces the manual “download the Provider Resource Report CSV from Vantage → Cost Reports” step described in Kubernetes CPU Request Rightsizing — the agent pulls the same data directly during a conversation.
Vantage Docs MCP — single search tool that finds relevant Vantage guides, setup steps,
and implementation details with links back to the docs.
HungryHub Account State (verified via MCP, June 2026)
Single workspace: Default (workspace token redacted — get it from
https://console.vantage.sh/settings/tokens or GET /v2/me with your API token),
currency USD, no currency conversion. Web UI: https://console.vantage.sh/settings/integrations.
Integrations (cost providers connected)
Vantage exposes 6 provider types; HungryHub uses all of them. Five are native
integrations, one (custom_provider) is the CSV/API bucket holding vendors Vantage has no
native connector for:
| Provider key | Type | What it tracks |
|---|---|---|
aws | Native | AWS org o-e33ctelaj8 — all 9 accounts via management acct 891572013503 (see StackSet below) |
kubernetes (kubernetes_agent) | Native | EKS workload costs — feeds rightsizing |
github | Native | GitHub Actions / org spend (account 53513081) |
mongo | Native | MongoDB Atlas |
databricks | Native | Databricks |
custom_provider | CSV/API | DigitalOcean, Aiven, Netlify, Redpanda, Hetzner, Cloudflare, OpenRouter, Fal.ai |
So 13 distinct vendors are monitored: AWS, Kubernetes, GitHub, MongoDB, Databricks, DigitalOcean, Aiven, Netlify, Redpanda, Hetzner, Cloudflare, OpenRouter, Fal.ai.
The custom_provider vendors are fed by the vantage-cost-sync
app (see AGENTS.md repo #24). It fetches each vendor’s billing, normalizes to the FinOps
FOCUS CSV format, and uploads to Vantage as a Custom Provider. ensure_provider() is
idempotent (looks up the existing integration by account_identifier before creating), so
each vendor stays a single stable integration — see the note below.
Cloudflare — invoice PDF, not API. Cloudflare has no usable cost API (its billable-usage API returns usage quantities but not dollar amounts yet), so cost comes from the monthly invoice PDF emailed to the billing address (
payment@hungryhub.com). Thecloudflare_invoiceprovider parses every PDF in a committedcloudflare-invoices/folder; a new invoice PDF is dropped there each month. Usage charges land in the previous month and plan/subscription fees in the upcoming month, matching how the invoice itemises them. Likewise, Hetzner Cloud has no billing API — that provider computes cost from live resources × the/pricingendpoint, emitting one per-day record (one day =hourly_rate × 24ormonthly_rate / 30) per project; the daily cron sums them into the correct monthly total (see the daily-MTD inflation note below).
History — custom_provider duplicate sprawl (fixed,
hungryhub-terraform#415). Until June 2026 the sync recreated a newaccss_crdntl_*integration on every CI run (the state file was ephemeral in CI), leaving ~95 orphaned entries. Fixed by makingensure_provideridempotent and pruning the orphans down to one per vendor. If you ever see custom_provider entries multiplying again, check that fix first. To query a custom provider in VQL, scope to its token:(costs.provider = 'custom_provider:accss_crdntl_...')— a bare(costs.provider = 'custom_provider')returns0.
History — daily-MTD inflation bug (fixed,
vantage-cost-sync#11). From the start of the daily cron (0 7 * * *) through mid-2026, the DigitalOcean and Hetzner providers uploaded the full month-to-date cumulative cost on every run. Vantage’s custom-provider CSV appends every row, so N daily uploads of MTD produced roughly N(N+1)/2 inflation. Live evidence (queried 2026-06-18):
Provider Vantage Apr Vantage May Vantage Jun 1-18 Actual DigitalOcean $0 $2,223 $8,912.90 $1,300 MTD Hetzner $0 $0 $2,779.46 ~$400 MTD Fixed by emitting one record per day in the requested range, with
billed_cost = monthly_amount / days_in_month(DigitalOcean) orbilled_cost = hourly_rate × 24/monthly_rate / 30(Hetzner) andcharge_period_start == charge_period_endset to that single day. The daily cron now syncs a single day (--start-date today --end-date today); 30 daily uploads sum to the correct monthly total.Aiven / Netlify / Redpanda were unaffected because they use the vendors’ own billing APIs and return finalized per-period totals. Native providers (AWS, K8s, GitHub, Mongo, Databricks) were also unaffected.
Backfill (done 2026-06-19). Deleted the stale DO and Hetzner integrations (the two original
accss_crdntl_*tokens for DigitalOcean and Hetzner; lookup viaGET /v2/integrations?provider=custom_providerto confirm) and re-synced with per-day records. Post-backfill Vantage shows:
Provider April May Jun 1-17 DigitalOcean $2,416 $2,223 $1,291 Hetzner (combined Apr 1 – Jun 17 = $897)
OpenRouter + Fal.ai (added,
vantage-cost-sync#12). Vantage has no native support for OpenRouter or Fal.ai (verified viadocs.vantage.sh/mcp— theconnecting_*.mdxlist includes Anthropic, OpenAI, Anyscale but neither OpenRouter nor Fal.ai). Both go through thecustom_providerCSV path viavantage-cost-sync. Daily cron (07:00 UTC) syncs today’s activity for both; 30 daily uploads sum to the correct monthly total (same per-day pattern as DO / Hetzner). The OpenRouter activity API only retains 30 days, so missed daily runs lose history; the monthly cron on the 3rd is the safety net.
Workspace-assign quirk (fixed,
vantage-cost-sync#12). Vantage’sPOST /integrations/custom_providersilently dropsworkspace_tokensfrom the request body (the create endpoint only acceptsname+description— verified via/api/integrations/create-custom-provider-integration.mdx). Without a follow-upPUT, the new integration hasworkspace_tokens=[]and uploaded cost data never appears in cost reports.ensure_providernow calls_assign_workspaceafter a successful POST. Best-effort: a 5xx on the PUT is logged but does not abort the sync. If you ever see a freshcustom_provider:accss_crdntl_*withworkspace_tokens=[], PUT it manually:curl -X PUT -H "Authorization: Bearer $VANTAGE_TOKEN" \ -H "Content-Type: application/json" \ -d '{"workspace_tokens":["<workspace_token>"]}' \ "https://api.vantage.sh/v2/integrations/accss_crdntl_XXX"
AWS — org-wide connection (CloudFormation StackSet)
The AWS integration spans the entire AWS Organization (o-e33ctelaj8), not just one
account. Two layers, intentionally separate — not duplicates:
- Cost / CUR data — the management account
891572013503connection. Because Vantage is connected to the root/management account, it profiles every member account and reports org-wide accrued costs through the single consolidated CUR. This is the cost source. - Active Resources (per-account IAM role) — a service-managed CloudFormation StackSet
(
ConnectToVantage17573-...) deploys a read-onlyvantage-integrationIAM role into each member account, unlocking resource-level inventory (EC2/RDS/etc.) per account. This does not re-import costs, so there is no double-counting.
All 9 accounts now appear once each under the aws provider, sharing the org provider_uuid
(arn:aws:organizations::891572013503:account/o-e33ctelaj8/<id>):
| Account ID | Name |
|---|---|
| 891572013503 | HungryHub-Root (management) |
| 202255947274 | production |
| 079994049689 | sandbox |
| 965444437277 | HungryHub GenAI Sandbox |
| 512438352490 | Hungry Hub-AI |
| 380983552701 | Hungry Hub-Security |
| 454538763126 | Hungry Hub-Audit Log |
| 993490993790 | Hungry Hub-Log Archive |
| 858647427345 | Surasit Sachdev |
How it was set up (run from the management account, profile root = 891572013503):
# Step 1 — create the StackSet (SERVICE_MANAGED, auto-deploy on for new accounts)
aws cloudformation create-stack-set \
--profile root --region us-east-1 \
--auto-deployment Enabled=true,RetainStacksOnAccountRemoval=true \
--permission-mode SERVICE_MANAGED \
--stack-set-name ConnectToVantage17573-<id> \
--template-url https://vantage-public.s3.amazonaws.com/vantage-integration-nocur-latest.json \
--parameters ParameterKey=VantageID,ParameterValue='<vantage-id>' \
ParameterKey=VantageDomain,ParameterValue='https://console.vantage.sh' \
ParameterKey=VantageHandshakeID,ParameterValue='<handshake-id>' \
ParameterKey=VantagePingbackArn,ParameterValue='arn:aws:sns:us-east-1:630399649041:cross-account-cloudformation-connector' \
ParameterKey=VantageIamRole,ParameterValue='<vantage-iam-role>' \
--capabilities CAPABILITY_IAM
# Step 2 — fan out to every member account (Root OU = r-onzh)
aws cloudformation create-stack-instances \
--profile root --region us-east-1 \
--stack-set-name ConnectToVantage17573-<id> \
--regions us-east-1 \
--deployment-targets OrganizationalUnitIds=r-onzh
Get the exact VantageID/VantageHandshakeID/VantageIamRole parameters from the Vantage
console (Integrations → AWS → Connect via CloudFormation StackSet) — they are
connection-specific. The Vantage SNS pingback ARN (630399649041) and template URL are
constant.
Notes:
- The management account
891572013503is excluded by SERVICE_MANAGED (it’s already connected via the CUR integration) — expected, not an error. --auto-deployment Enabled=true→ any new org account is connected automatically.- Roles are read-only; the only outward grant is cross-account trust to Vantage’s account
630399649041. - Active Resources data backfills over a few hours after the StackSet completes.
- Vantage docs reference: search the docs MCP for “Connecting Multiple AWS Accounts” / “Connecting via Stackset”, or https://docs.vantage.sh → Provider Integrations → AWS.
(The custom_provider duplicate-import issue that this section used to warn about was fixed in June 2026 — see the custom_provider note under Integrations above.)
Kubernetes — a new cluster only appears after its AWS account’s CUR is ingested
The Vantage Kubernetes Agent (one per cluster, installed via Helm — managed in
hungryhub-terraform/helm-releases/vantage-agent.tf) reports pod/node metrics, but a new
cluster does not show up as a kubernetes integration until the underlying cloud account’s
cost data is ingested. Per the Vantage K8s agent docs:
the agent needs a connected primary provider (AWS here) so Vantage can join its metrics to
the EC2 node costs and compute pod costs.
Concretely, when we added the sandbox cluster eks-dev-262 (account 079994049689):
- The agent installed fine and uploaded reports immediately (verified in its logs).
- But the cluster did not appear in
list-cost-integrationsfor ~a day, because the sandbox AWS account had only just been connected via the StackSet — its first CUR can take up to 24h to arrive (status=connected, last_updated=nulluntil then). - Prod
eks-prod-21shows immediately only because its AWS CUR was ingested long ago.
So if a freshly-installed agent’s cluster is missing from the integrations list: it’s almost
certainly not an agent problem — check whether the cluster’s AWS account has ingested a
CUR yet (GET /integrations?provider=aws → last_updated non-null). Wait out the ≤24h CUR
window before debugging the agent.
Spend snapshot (native providers, May 2026)
| Provider | Monthly cost (USD) |
|---|---|
| AWS | $13,316.58 |
| Kubernetes | $1,787.24 |
| GitHub | $796.91 |
| MongoDB | $136.77 |
| Databricks | $27.85 |
| Total (native) | $16,065.34 |
(Custom-provider spend — DigitalOcean/Aiven/Netlify/Redpanda — is tracked separately and not included above.)
Open recommendations
| Type | Potential savings/mo | Scope |
|---|---|---|
kubernetes:workload:rightsizing | $615.75 | 34 workloads, 80 resources — feeds Kubernetes CPU Request Rightsizing |
aws:elasticache:reserved-instances | $0 (0 resources) | RI buy suggestion, prod 202255947274 |
aws:rds:reserved-instances | $0 (0 resources) | RI buy suggestion, prod 202255947274 |
The Kubernetes rightsizing recommendation is the live source behind the manual CSV workflow — the agent can now pull it directly (see examples below).
Setup
HungryHub config (this workspace)
Both servers are configured in the workspace-root .mcp.json (which is gitignored). Vantage
uses OAuth, so no token is stored in the file:
{
"mcpServers": {
"vantage": {
"type": "http",
"url": "https://mcp.vantage.sh/mcp"
},
"vantage-docs": {
"type": "http",
"url": "https://docs.vantage.sh/mcp"
}
}
}
On first connect, Claude Code opens a browser to complete the Vantage OAuth flow. Manage /
re-trigger auth from inside a session with the /mcp command. vantage-docs needs no auth.
Alternative: API token instead of OAuth
For headless/CI contexts where the interactive OAuth browser flow won’t work, pass a Vantage
API token (vntg_tkn_..., generated in Vantage → Settings → API Tokens) as a bearer header.
Never commit the raw token — reference it via env var:
{
"mcpServers": {
"vantage": {
"type": "http",
"url": "https://mcp.vantage.sh/mcp",
"headers": {
"Authorization": "Bearer ${VANTAGE}"
}
}
}
}
# In ~/.zshrc / ~/.bashrc, or a gitignored .env loaded into the shell
export VANTAGE="vntg_tkn_..."
OAuth is preferred for interactive local use (no long-lived secret on disk). Use the API token only where OAuth is not possible.
Other AI clients
Both are plain remote HTTP MCP servers; point any MCP-capable client at the same URLs.
Cursor / Windsurf — mcp.json:
{
"mcpServers": {
"vantage": { "url": "https://mcp.vantage.sh/mcp" },
"vantage-docs": { "url": "https://docs.vantage.sh/mcp" }
}
}
Codex CLI:
codex mcp add Vantage -- npx -y mcp-remote https://mcp.vantage.sh/mcp
codex mcp add VantageDocs -- npx -y mcp-remote https://docs.vantage.sh/mcp
After saving, restart the client. Vantage tools appear in the tool list.
Practical Examples
These prompts work in any MCP-compatible client once the data server is authenticated.
Pull current rightsizing recommendations
List Vantage's current rightsizing recommendations for our Kubernetes workloads,
with estimated monthly savings per namespace.
Replaces the manual CSV download for Kubernetes CPU Request Rightsizing.
Check savings opportunities
What cost savings has Vantage identified this month? Sort by estimated savings.
Mirrors the “Vantage Savings Identified” report referenced in EKS Cost Optimization 2026.
Search the docs
How do I set up a Vantage cost report filtered to a single EKS cluster?
Routes to the vantage-docs search tool and returns guide links.
Key Tools & VQL Notes
The data server exposes ~80 tools (cost reports, budgets, recommendations, anomalies, virtual tags, dashboards, billing rules). The ones you reach for most:
| Tool | Use |
|---|---|
get-myself | Returns workspace token(s) — needed for almost every other call |
list-cost-integrations | All connected providers + accounts (the integration inventory above) |
list-cost-providers | Provider keys valid in VQL (per workspace) |
list-recommendations | Open savings recommendations (filter open/resolved/dismissed, min_savings, provider) |
query-costs | Ad-hoc cost query via VQL (no saved report needed) |
list-recommendation-resources / get-recommendation-details | Drill into a specific recommendation |
list-anomalies | Cost spikes against a cost report token |
VQL gotchas (learned the hard way):
- Every query needs a provider:
(costs.provider = '<key>'). Keys come fromlist-cost-providers— note Kubernetes iskubernetesin VQL butkubernetes_agentin the provider list;custom_providerfor the CSV vendors. - Multiple providers →
OR:((costs.provider = 'aws') OR (costs.provider = 'mongo')). - AWS services use short names:
AmazonEC2,AmazonRDS(not the long display names). Uselist-cost-servicesto get exact names. - Custom providers must be scoped by token:
(costs.provider = 'custom_provider:accss_crdntl_...')— a barecustom_providerreturns 0. - Default date range is 30 days; pass
start_date/end_date(YYYY-MM-DD) for anything else.
Example — native-provider spend for May 2026 (the snapshot above):
query-costs(
workspace_token = "<workspace_token>", # from `GET /v2/me`
filter = "((costs.provider='aws') OR (costs.provider='kubernetes') OR
(costs.provider='mongo') OR (costs.provider='databricks') OR
(costs.provider='github'))",
groupings = ["provider"], date_bin = "month",
start_date = "2026-05-01", end_date = "2026-05-31"
)
Limitations
- Data server requires auth — OAuth (browser) or API token; without it, only
vantage-docsworks. - Docs server is read-only search — no access to your cost data, just product docs.
- OAuth needs an interactive browser — for CI/headless, use the API-token variant.
.mcp.jsonis gitignored — config is local per machine; the token/OAuth session does not sync.
Related
- Grafana MCP for AI Agents — same remote-MCP pattern for metrics/logs
- EKS Cost Optimization 2026 — real use of Vantage savings reports
- Kubernetes CPU Request Rightsizing — workflow the data MCP automates