Skip to content

Repository files navigation

FinOps Detective

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.

Quick start

pnpm install
pnpm run dev    # http://localhost:3000

What's in the box

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.

Claude skills

Two Claude Code skills are included in .claude/commands/:

/setup-app — Scaffold the app

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.

/investigate-vendor <name> — Run a vendor investigation

The main skill. Orchestrates a full FinOps investigation:

  1. Search your codebase for how the vendor is used (which products, which resources)
  2. Query PostHog MCP for product usage trends (events, recordings, logs, etc.)
  3. Query vendor MCP for billing and cost attribution (invoices, chargebacks)
  4. Query Grafana MCP for infrastructure metrics (throughput, action rates)
  5. Build the analysis page with charts and tables correlating usage to cost

Using this for your own FinOps

This is designed as a starting point. Here's how to adapt it for your products.

Step 1: Point it at your codebase

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.

Step 2: Connect your MCPs

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.

Step 3: Replace the demo vendors with yours

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.

Step 4: Make the data real

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.

Data model reference

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"
    }
  }
}

Architecture

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

The idea

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.

About

demo of how you can use posthog mcp for finops

Resources

Code of conduct

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages