FinOps as MCPs in a Trench Coat — a demo app showing how to use PostHog MCP, vendor MCPs, and Grafana MCP to understand product growth vs vendor bills.
This app ships with demo data (real concepts, fake numbers) so you can explore the UI and Claude skills without any API keys. When you're ready to investigate your own vendors, swap the mock JSON files for real data from your MCPs.
pnpm install
pnpm run dev # http://localhost:3000| Route | Vendor | MCP data sources |
|---|---|---|
/ |
Overview | All vendors — combined run-rate |
/warpstream/ |
WarpStream (Kafka) | WarpStream Chargeback MCP, PostHog MCP, Grafana MCP |
/temporal/ |
Temporal Cloud | Temporal Billing API, Grafana MCP, PostHog MCP |
Each vendor investigation has sections for: cost overview, per-resource breakdown, product-area attribution, usage correlation, and infrastructure metrics.
Two Claude Code skills are included in .claude/commands/:
Walks through the foundational Next.js setup: dark theme, Detective Hog branding, sidebar shell, cost-area registry. Useful for seeing the workflow of how this app was built from scratch.
The main skill. Orchestrates a full FinOps investigation:
- Search your codebase for how the vendor is used (which products, which resources)
- Query PostHog MCP for product usage trends (events, recordings, logs, etc.)
- Query vendor MCP for billing and cost attribution (invoices, chargebacks)
- Query Grafana MCP for infrastructure metrics (throughput, action rates)
- Build the analysis page with charts and tables correlating usage to cost
This is designed as a starting point. Here's how to adapt it for your products.
The /investigate-vendor Claude skill searches your codebase to understand how a vendor maps to your products. In this demo we pointed it at the PostHog repo — you'll want to point it at yours instead.
In .claude/commands/investigate-vendor.md, the skill tells Claude to search the codebase for vendor references. It works with any repo — Claude will look for imports, config, topic names, queue names, etc. to build the product → vendor mapping for your architecture.
The app is built around three types of MCP data sources. Configure them in your .mcp.json or Claude Code settings:
PostHog MCP — The product usage side. PostHog captures all the product usage context an agent needs to understand what's actually driving your costs — events ingested, recordings, log volumes, feature flag evaluations, etc. The MCP exposes this via HogQL so Claude can query usage trends directly and correlate them against vendor bills. This is the demand side of the equation: "how much are our products being used, and by whom?"
Vendor MCPs — The billing side. This depends entirely on what vendors you use:
- Check if your vendor has an MCP (more are shipping them every month)
- If they don't have an MCP but expose metrics to Grafana/Datadog/etc., use that MCP instead
- If they have a billing API but no MCP, you can write a simple data-fetch script and drop the JSON into
public/data/ - Even a CSV export from your vendor dashboard works — just reshape it into the JSON format the app expects
Grafana MCP (or your observability platform's MCP) — The infrastructure side. Queries dashboards for real-time throughput, action rates, latency, etc. Works with any vendor that exposes metrics to your observability stack. If you use Datadog, there's a Datadog MCP. Etc.
The demo ships with WarpStream and Temporal because that's what PostHog uses. You should delete these and add your own vendors. The vendors you investigate are whatever your product depends on — your database, your queue, your CDN, your auth provider, your AI model API, whatever.
All data lives in public/data/. The app fetches these JSON files client-side at runtime — no rebuild needed when you swap files.
To add a vendor, create four things + a registry entry:
1. public/data/<vendor>/*.json — your data files (billing, usage, metrics)
2. lib/<vendor>/model.js — parse your JSON into cost objects
3. components/<vendor>/*.jsx — React components for each section
4. app/<vendor>/page.jsx — page route with section navigation
5. lib/finops.js — add entry to COST_AREAS array
Each vendor is fully namespaced — they don't share math or data models. This is intentional: vendors bill on completely different things (GiB written vs actions vs seats vs API calls), so there's no useful abstraction across them.
Use the /investigate-vendor Claude skill to automate this. Tell it your vendor name and point it at your repo — it'll search your code, query your MCPs, and build the analysis page.
Once your MCPs are connected, you have two options:
Option A: Manual refresh. Run your MCP queries, save the results as JSON in public/data/<vendor>/. The app will pick them up on next page load.
Option B: Scripted refresh. Write a small script (Python, Node, whatever) that calls your vendor's API or MCP and writes the JSON files. Add it as a refresh-data:<vendor> script in package.json so you can run pnpm run refresh-data:<vendor> to pull fresh numbers.
The mock data files follow the shapes that real MCPs return. Here's what each expects:
invoices.json (WarpStream-style — monthly cost per resource):
[
{
"date_from": "2026-01-01",
"date_to": "2026-02-01",
"total": 14280.40,
"clusters": [
{
"cluster_name": "vcn_events_us",
"region": "us-east-1",
"total": 5180.20,
"gib_written": 482000,
"products": {
"Uncompressed GiB written": 4340.60,
"Cluster minutes": 839.60
}
}
]
}
]billing.json (Temporal-style — namespace costs + queue attribution):
{
"months": ["2026-01", ...],
"namespaces": [
{
"namespace": "acme-prod-us.abc1",
"region": "us-east-1",
"monthly_actions_millions": [620, 660, ...],
"monthly_cost": [18200, 19400, ...]
}
],
"task_queues": [
{
"name": "workflow-orchestrator",
"namespace": "acme-prod-us.abc1",
"product_area": "core_pipeline",
"monthly_actions_millions": [185, 197, ...]
}
]
}usage.json (PostHog MCP — product metrics mapped to vendor resources):
{
"months": ["2026-01", ...],
"metrics": {
"event_count_in_period": {
"label": "Events Ingested",
"unit": "events",
"maps_to_clusters": ["events"],
"data": [84200000000, 89500000000, ...]
}
},
"cluster_mapping": {
"events": {
"warpstream_clusters": ["vcn_events_us", "vcn_events_eu"],
"topics": "events_json, person, groups"
}
}
}app/
page.jsx # Home — Detective Hog hero, vendor cards
warpstream/page.jsx # WarpStream investigation (5 sections)
temporal/page.jsx # Temporal investigation (5 sections)
components/
AppShell.jsx # Sidebar shell with branding + nav
warpstream/ # WarpStream-specific components
temporal/ # Temporal-specific components
lib/
finops.js # COST_AREAS registry (drives sidebar + home)
format.js # fmtUSD, fmtBigNum, fmtMonthLabel, fmtPct
scenario.js # URL scenario sync + hash section nav
warpstream/model.js # WarpStream data parsing
temporal/model.js # Temporal data parsing
public/data/
posthog/usage.json # PostHog product usage (shared)
warpstream/ # WarpStream invoices, chargebacks, throughput
temporal/ # Temporal billing, action metrics
Key design decisions:
- Static export (
next build→./out) — no server runtime, deploy anywhere - Runtime data loading — pages fetch JSON on mount, swap files without rebuilding
- Namespaced vendors — each vendor has its own lib/components/data, no shared math
- Chart.js for visualizations — lightweight, works with static export
This app accompanies the demo "FinOps as MCPs in a Trench Coat" about using Model Context Protocol servers to build a FinOps practice. The core idea: instead of building custom integrations for every vendor billing API, use MCPs as a composable layer that Claude can orchestrate to investigate costs across your stack.
The three MCP types form a complete picture for any vendor:
- PostHog MCP → "how much are our products being used?" (the demand side)
- Vendor MCP → "how much is that usage costing us?" (the supply side)
- Observability MCP → "what's happening at the infrastructure level?" (the reality check)
When cost growth outpaces usage growth, something changed — maybe a compression regression, an architectural change, a new feature pushing more data through a pipeline. That's where the investigation begins.
This pattern works regardless of your stack. The investigation workflow is the same: understand the product → vendor mapping, measure both sides, and look for divergence.
