Page 1 of 7 · Intro & Getting Started
Two MCP servers for FinOps
This repository ships an independent, unofficial agentic interface to the FinOps Foundation's published guidance: one MCP server for the FinOps Framework, one for the FOCUS™ specification. Both are read-only, offline, version-pinned, and label every derived answer as unofficial. This page gets them running in your client and shows the first call against each.
What this repo is
An LLM asked “how mature is our Allocation practice?” or “which FOCUS columns do I need for effective savings rate?” will happily improvise. These two servers exist so it doesn't have to: they serve the Foundation's own text, structured, with the source URL and licence attached to every response.
Each server is the same three decoupled parts — and the last two run with no network access at all:
- Official by default. Out of the box the framework server serves only content published on finops.org/framework, restructured — no invented relationships between capabilities, no maturity levels beyond the Foundation's Crawl / Walk / Run.
- Unofficial work is labelled, not hidden. The FOCUS server's KPI mapping, KPI calculation and 1.0→1.2 diff ship in the default surface but carry UNOFFICIAL in-text and official: false in structured output.
- Reproducible. The data artifacts are committed; cli.js derive regenerates every JSON file from the canonical markdown offline, and the servers validate the artifact at startup and refuse to run on a bad one.
- Version-pinned. FOCUS answers are always scoped to a spec version rather than blended across releases.
framework · get_framework_info {} · focus · list_versions {} · both list-tools
The two servers, side by side counts from live probes
Every number in these two cards was read out of a live server response, not a hand-maintained list.
finops-framework-mcp
The FinOps Framework · finops.org/framework · data v2.1.1, crawled 2026-07-23
The operating model: what a capability is, its official Crawl/Walk/Run assessment prose, who does what in it, and which KPIs it publishes.
- 6
- Principles
- 3
- Phases (Inform / Optimize / Operate)
- 4
- Domains
- 22
- Capabilities
- 11
- Personas (6 core + 5 allied)
- 5
- Technology Categories
- 3
- Maturity levels
- 88
- KPI library entries
- 11
- tools
- 4
- prompts
- 44
- resources listed + 4 URI templates (finops://)
finops-focus-mcp
The FOCUS™ specification · versions 1.0 and 1.2 · latest 1.2
The data contract: what each billing column means in a given spec version, its normative MUST/SHOULD requirements, and what changed between releases.
- 1.0
- 43 columns, 9 attributes (source tag v1.0)
- 1.2
- 57 columns, 9 attributes (source tag v1.2) — the default
- 9
- tools
- 3
- prompts
- 125
- resources listed + 4 URI templates (focus://)
FOCUS columns by feature level
| Spec version | Mandatory | Conditional | Recommended | Total |
|---|---|---|---|---|
| 1.0 | 21 | 20 | 2 | 43 |
| 1.2 | 21 | 32 | 4 | 57 |
The mandatory count is identical in both versions — all 14 columns 1.2 adds land in the Conditional and Recommended tiers. The FOCUS server page walks the full 1.0→1.2 diff.
framework · get_framework_info {} · list-prompts · list-resources · list-resource-templates
focus · list_versions {} · list_columns {version, feature_level} × 6 · list-prompts · list-resources
Getting started — install
Both servers are published on npm — finops-framework-mcp and finops-focus-mcp, each a stdio binary — so an MCP client only ever needs a command and its arguments, and there is nothing to clone or build. Each package carries its own data artifact, so both run offline after install. Node >=22 is required by both.
# run either server directly — stdio, nothing to configure npx -y finops-framework-mcp npx -y finops-focus-mcp # or from a clone of this repo npm install && npm run build && npm run server
The framework server loads the data artifact packaged with its release (data/framework); point it at a locally-refreshed artifact with FINOPS_MCP_DATA or the first CLI argument.
Claude Code — one command per server
claude mcp add finops-framework -- npx -y finops-framework-mcp claude mcp add focus-spec -- npx -y finops-focus-mcp
Claude Code — project-scoped .mcp.json
Commit this at the repo root to give everyone on the project both servers:
{
"mcpServers": {
"finops-framework": {
"command": "npx",
"args": ["-y", "finops-framework-mcp"]
},
"focus-spec": {
"command": "npx",
"args": ["-y", "finops-focus-mcp"]
}
}
}
Claude Desktop — claude_desktop_config.json
{
"mcpServers": {
"finops-framework": {
"command": "npx",
"args": ["-y", "finops-framework-mcp"]
},
"focus-spec": {
"command": "npx",
"args": ["-y", "finops-focus-mcp"]
}
}
}
Same shape either way — any generic stdio MCP client takes the identical {"command": "npx", "args": ["-y", "finops-focus-mcp"]} pair. (-y skips npx's first-run install prompt, which can hang non-interactive MCP clients.)
Or run them remotely — the Cloudflare Worker
Both servers are also deployable over Streamable HTTP from a single bundled Cloudflare Worker (src/workers/), which serves them at two paths:
The Worker builds a fresh MCP server and transport per request — stateless by design: no session state persists across requests or isolates, and there is no user-supplied data path (calculate_kpi computes only over the bundled samples, exactly as the stdio servers do). Both data artifacts are compiled into the bundle at build time; nothing reachable from the Worker entry point touches node:fs at runtime, and a test statically walks the import graph to keep it that way.
Two operational notes before you point a browser at it. Requests with no Origin header — stdio-bridged and server-to-server MCP clients — are always allowed; browser requests need their origin on the Worker's ALLOWED_ORIGINS allowlist, which is also what drives CORS. And there is deliberately no authentication and no rate limiting: the Worker serves only public, read-only content with no per-user state behind it.
There is no public hosted endpoint to point you at here — deploying is a human approval point in this repo, so the URL is whatever the operator's own wrangler deploy produces. A deployment smoke test looks like this:
curl -s "$WORKER_URL/mcp/focus" \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
source: docs/deploy-worker.md (owner deployment checklist)
Your first call against each server official
Both servers publish a “start here” tool. Below is real, unedited output from each — captured through the repo's own MCP client bridge, which is the same stdio protocol your client will speak.
finops-focus-mcp · list_versions
Call this first: it tells you which version values every other FOCUS tool will accept.
$ node evals/framework/mcp-call.mjs --server=focus call list_versions '{}'
{
"content": [
{
"type": "text",
"text": "- 1.0: 43 columns, 9 attributes (source v1.0)\n- 1.2 (latest): 57 columns, 9 attributes (source v1.2)"
}
],
"structuredContent": {
"latest": "1.2",
"versions": [
{
"spec_version": "1.0",
"source_tag": "v1.0",
"data_version": "1.0.1",
"is_latest": false,
"counts": {
"attributes": 9,
"columns": 43
}
},
{
"spec_version": "1.2",
"source_tag": "v1.2",
"data_version": "1.0.1",
"is_latest": true,
"counts": {
"attributes": 9,
"columns": 57
}
}
]
}
}
focus · list_versions {}
finops-framework-mcp · get_capability
Capability documents are large, so get_capability is section-selectable via include — here, the summary alone. Note the two things that come back on every official response: a source_url pointing at the page the text came from, and the CC BY 4.0 attribution footer.
$ node evals/framework/mcp-call.mjs call get_capability \
'{"capability":"anomaly-management","include":["summary"]}'
{
"content": [
{
"type": "text",
"text": "{\n \"slug\": \"anomaly-management\",\n \"title\": \"Anomaly Management\",\n \"domain\": \"understand-usage-and-cost\",\n \"sections\": {\n \"summary\": \"Detect, identify, alert and manage unexpected or unforecasted technology cost and usage irregularities in a timely manner to lower risk and ensure cost-effective operations.\"\n },\n \"uri\": \"finops://framework/capabilities/anomaly-management\",\n \"source_url\": \"https://www.finops.org/framework/capabilities/anomaly-management/\",\n \"license\": \"CC-BY-4.0\"\n}\n\n---\nSource: https://www.finops.org/framework/capabilities/anomaly-management/ — © FinOps Foundation, licensed CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/). Content restructured and adapted by finops-framework-mcp (data v2.1.1, crawled 2026-07-23); unofficial extensions are always marked."
},
{
"name": "anomaly-management",
"uri": "finops://framework/capabilities/anomaly-management",
"description": "Full anomaly-management capability document",
"mimeType": "text/markdown",
"type": "resource_link"
}
],
"structuredContent": {
"slug": "anomaly-management",
"title": "Anomaly Management",
"domain": "understand-usage-and-cost",
"sections": {
"summary": "Detect, identify, alert and manage unexpected or unforecasted technology cost and usage irregularities in a timely manner to lower risk and ensure cost-effective operations."
},
"uri": "finops://framework/capabilities/anomaly-management",
"source_url": "https://www.finops.org/framework/capabilities/anomaly-management/",
"license": "CC-BY-4.0"
}
}
framework · get_capability {capability: "anomaly-management", include: ["summary"]}
Don't know a slug? Don't guess
Both servers ship a ranked keyword search whose whole job is turning words into slugs you can feed to the other tools — search_framework {query} on one side, search_focus {query, version} on the other. Each hit returns a slug and a resource URI. And if you'd rather orient than search, get_framework_info {} returns the framework's structure and a short navigation guide in one call:
framework · get_framework_info {} → content[0].text, “How to navigate”
Where to go next
Two reference pages, then four worked examples that use both servers together — three planned walkthroughs and one live, unscripted Q&A session. Every number and quote on all six is produced the same way as the transcripts above.
The one-minute version
Install both bins (npx -y finops-framework-mcp, npx -y finops-focus-mcp), register them in your client with the same command/args pair, then start every session with get_framework_info {} and list_versions {}. Ask the framework server what good looks like; ask the FOCUS server which columns prove it. Anything the servers derived rather than quoted arrives already labelled unofficial — believe the label.