ai-usage-mcp

MCP serverAI & models

Reports real token usage and cost from Claude Code and OpenCode data. Nothing leaves your machine.

Unavailable. This server has no hosted endpoint yet, so ahel can't serve it.

Connect ahel once, and every AI you use reads what you have installed.

From the project's README

As published by mohitbansal321/ai-usage-mcp in README.md.

Whatever is telling you what your coding agent costs is probably inflating it. Claude Code writes one JSONL line per content block, and every line repeats the same usage object with a cumulative output_tokens. Summing those lines — the obvious thing to do, and what naive tools do — inflated every figure by 2.15× to 3.05× on the development machine: 1.79B cache-read tokens claimed where the truth was 800M.

Cache tokens are also where the money actually is. Cache-read outweighed input by roughly 33,000× (800,839,432 vs 24,381), so any tool that blends token classes into a single "total" has told you nothing you can act on.

This one reads the same files, deduplicates on requestId + message.id, and then proves it: ai-usage verify re-reads both sources with a second, independent implementation that shares no reduction code with the collectors, and diffs the result against its own database.

$ ai-usage verify

== claude-code ==
  MATCH    claude JSONL, deduped by stop_reason line (independent rule)
  INFO     claude JSONL, naive sum of every usage line (NOT used -- shows the double count)
           delta:  cache-read 990,824,820 ...

RESULT: every client reconciles exactly against at least one independent read of its source.

So the question it answers, from real data on your machine:

How many tokens have I used, from which client, model and session — and what did it cost?

Phase 1 supports two coding agents: Claude Code and OpenCode. It reads the data those clients already wrote to disk, normalises it into one schema, stores it in a local SQLite database, and exposes seven MCP tools -- plus resources, prompts and a debug CLI.

It never fabricates a number. If a source does not record something, it is reported as unavailable — not as zero.

$ ai-usage stats --today
Usage summary -- today (local time)
Subagent/sidechain turns: INCLUDED (3 main + 1 subagent turns).

Records: 4   Sessions: 2

Tokens (all clients):
  Input:        1,871
  Output:       16,909 (16.9K)
  Cache read:   2,452,000 (2.45M)
  Cache write:  37,300 (37.3K)
  Reasoning:    2,600
  Total:        2,508,080 (2.51M)

  Cost (reported by client, exact): $0.41  [1 records]
  Cost (estimated, API-equivalent):  $1.50  [3 records]

By client:
  claude-code  --  3 records, 1 sessions
    Cache read:   2,238,000 (2.24M)
    Total:        2,280,001 (2.28M)
    Cost (estimated, API-equivalent):  $1.50  [3 records]

  opencode  --  1 records, 1 sessions
    Cache read:   214,000 (214.0K)
    Total:        228,079 (228.1K)
    Cost (reported by client, exact): $0.41  [1 records]

The two cost lines are never added together, and never will be — see How cost is reported.


Install

Requires Node.js 22.13+. No compiler, build tools or particular npm version needed: storage uses Node's built-in node:sqlite, which is unflagged from 22.13.0 onward. There is no mandatory native dependency.

better-sqlite3 remains an optional fallback for hosts whose Node predates that. It is never required — if it cannot be built, npm skips it and the server still runs.

Claude Code

As a plugin — recommended. Run these two inside Claude Code:

/plugin marketplace add MohitBansal321/ai-usage-mcp
/plugin install ai-usage@ai-usage-mcp

That wires up the MCP server and installs the three prompts as real slash commands — /ai-usage:daily-review, /ai-usage:why-was-today-expensive, /ai-usage:project-cost — which most clients never surface from MCP prompts alone. If the install summary says Run /reload-plugins to activate., run that. The equivalent from your shell is claude plugin marketplace add MohitBansal321/ai-usage-mcp.

The plugin declares npx -y ai-usage-mcp as its server, so the server itself still comes from npm and re-resolves on each cold start. Updating the plugin and updating the server are therefore independent — see Updating.

Or as a plain MCP server, if you would rather not add a marketplace. Nothing to install first — npx fetches it on demand:

claude mcp add ai-usage -s user -- npx -y ai-usage-mcp

On native Windows (not WSL), wrap it in cmd /c instead:

claude mcp add ai-usage -s user -- cmd /c npx -y ai-usage-mcp

Why: on Windows npx is npx.cmd, and the MCP TypeScript SDK spawns servers with shell: false. Node cannot execute a .cmd file that way — its docs say such files "can be invoked using child_process.spawn() with the shell option set … or by spawning cmd.exe and passing the .bat or .cmd file as an argument". cmd /c is that second form. This applies to every SDK-based client below, not just Claude Code.

-s user makes it available in every project. Drop it to add the server to the current project only. Then run /mcp inside Claude Code to confirm it connected.

The extension reads the same configuration as the CLI, so you can add the server by editing a file — no CLI needed. Pick whichever scope you want:

For one project — create .mcp.json in the project root:

{
  "mcpServers": {
    "ai-usage": {
      "command": "npx",
      "args": ["-y", "ai-usage-mcp"]
    }
  }
}

Claude Code asks you to approve a project-scoped server the first time it loads it. This file is safe to commit if you want your team to get it too.

For all your projects — add the same mcpServers block at the top level of ~/.claude.json (%USERPROFILE%\.claude.json on Windows):

{
  "mcpServers": {
    "ai-usage": {
      "command": "npx",
      "args": ["-y", "ai-usage-mcp"]
    }
  }
}

That file already exists and holds other settings — add the mcpServers key alongside them rather than replacing the file.

Then reload the window (Developer: Reload Window in VS Code) and run /mcp. Configuration is read when a session starts, so an already-open session will not pick it up.

OpenCode

opencode mcp add ai-usage       # choose a local server, command: ai-usage-mcp

Or add it to ~/.config/opencode/opencode.jsonc:

{
  "mcp": {
    "ai-usage": {
      "type": "local",
      "command": ["npx", "-y", "ai-usage-mcp"],
    },
  },
}

Confirm with opencode mcp list.

Other MCP clients

The client you ask from does not have to be a client you measure. This server reports on the Claude Code and OpenCode data already on your disk no matter who asks for it — so if you spend your day in Cursor but your tokens go through Claude Code, ask Cursor and you still get the real numbers.

Cursor, Google Antigravity, Windsurf and Claude Desktop all take the same block. Only the file path changes:

{
  "mcpServers": {
    "ai-usage": {
      "command": "npx",
      "args": ["-y", "ai-usage-mcp"]
    }
  }
}
ClientFile to put it in
Cursor~/.cursor/mcp.json (all projects), or .cursor/mcp.json in one repo
Google Antigravity~/.gemini/antigravity/mcp_config.json
Windsurf~/.codeium/windsurf/mcp_config.json
Claude DesktopSettings → Developer → Edit Config — see the paths below

For Claude Desktop, that button creates the file if it does not exist and opens it either way, which is more reliable than editing by hand:

PlatformPath
macOS~/Library/Application Support/Claude/claude_desktop_config.json
Windows%APPDATA%\Claude\claude_desktop_config.json

Claude Desktop on Linux is in beta and Anthropic publishes no config path for it, so use the Edit Config button rather than guessing one. Fully quit and relaunch afterwards — the file is read at startup.

Two clients need a different shape:

Codex uses TOML, not JSON. Easiest is the CLI:

codex mcp add ai-usage -- npx -y ai-usage-mcp

Or add the table by hand to ~/.codex/config.toml (or a project-scoped .codex/config.toml):

[mcp_servers.ai-usage]
command = "npx"
args = ["-y", "ai-usage-mcp"]

Confirm with codex mcp list.

GitHub Copilot CLI uses ~/.copilot/mcp-config.json, where the top-level key is servers, not mcpServers:

{
  "servers": {
    "ai-usage": {
      "command": "npx",
      "args": ["-y", "ai-usage-mcp"]
    }
  }
}

On native Windows, use the cmd /c form in any of these — "command": "cmd" with "args": ["/c", "npx", "-y", "ai-usage-mcp"], or command = "cmd" with args = ["/c", "npx", "-y", "ai-usage-mcp"] for Codex. See the note under Claude Code for why.

Provenance, 2026-09-08: Cursor, Windsurf, Codex and Claude Desktop paths are from each vendor's own documentation. The Antigravity and Copilot CLI paths and key names were read off installed copies of those apps on Linux, since neither publishes the path — including Copilot CLI's servers key, which differs from every other client here.

The debug CLI

The MCP server needs no install. To also get the ai-usage CLI on your PATH:

npm install -g ai-usage-mcp
ai-usage status

Or run it without installing:

npx -y -p ai-usage-mcp ai-usage stats --today

Windows: no longer needs a particular npm. The node-gyp failure that used to break this install came from the native better-sqlite3 dependency, which is now optional and unused on Node 22.13+. If npm still reports a build failure for it, that message is a skipped optional dependency, not a failed install — ai-usage status will show SQLite driver: node:sqlite and everything works.

Verified against Claude Code 2.1.251 and OpenCode 1.18.25.

Updating

npx -y ai-usage-mcp — the form the instructions above use — re-resolves the version every time your client cold-starts the server, so it keeps itself current. Restart the client to pick up a new release.

A global install is pinned until you update it by hand:

npm install -g ai-usage-mcp@latest
ai-usage --version

ai-usage status tells you when you are behind:

Update available: 0.1.0 installed, 0.2.0 latest -- npm i -g ai-usage-mcp@latest

The MCP server says so too, because most people never run the CLI. When the server finds a newer release it says it once per process, through whichever channel comes first: a line added to the instructions it returns at handshake time, or a one-off note attached to the next tool result. It is a separate content block, so the numbers a tool returns stay exactly what the CLI prints for the same query, and it never repeats itself on later calls. The same line goes to the server's stderr log, and @usage://status shows the state on demand.

The advice differs by how you installed it, and the notice says the right one:

Installed asWhat actually fixes it
npm i -g ai-usage-mcpnpm i -g ai-usage-mcp@latest
npx -y ai-usage-mcpRestart the server -- npx re-resolves on a cold start
A version pinned in your MCP configChange it there; no command will do it for you
A project dependencynpm i ai-usage-mcp@latest
A source checkoutgit pull && npm run build

That check is the only network call in the package: a version lookup against the npm registry, at most once a day, cached in <config dir>/update-check.json, skipped when CI is set, and silently abandoned after 1.5s if you are offline. It sends no usage data and no identifier -- just a GET for a version string. Set AI_USAGE_NO_UPDATE_CHECK=1 to turn it off everywhere, CLI and server alike. In the server it runs after the handshake, never during it, so it cannot slow down a client starting up.


Ask it things

Once connected, ask in plain language:

How many tokens have I used today?
Show my usage for this session.
Which model consumed the most tokens?
How much did Claude Code cost me today?
Show all usage from the last 7 days.
Which repository is my spend going to?
Break my last 7 days down day by day.

MCP tools

ToolReturns
usage_summaryTotals for a period, split by client, tokens + cost
session_usageOne session: client, model, duration, token breakdown, cost
model_usagePer-model tokens and cost
client_usagePer-client (Claude Code vs OpenCode) tokens and cost
recent_sessionsRecent sessions with project, client, tokens, cost
project_usagePer-project tokens and cost, by the directory a turn ran in
daily_usagePer-day tokens and cost, newest day first
counterfactual_costThese tokens at another model's list rates, beside what they actually cost

Every period-based tool takes projectPath to narrow the report to one project.

counterfactual_cost answers "would a cheaper model have cost less for this?" — it re-prices the exact token counts that were recorded, grouped by client, model and speed so the fast-mode premium and the two clients' different reasoning-token conventions are both handled. It is a counterfactual, not a saving: the same task on a different model generally takes a different number of turns carrying a different context on each, and nothing on disk can say what that would have been. The caveat ships with the numbers.

Resources and prompts

Three resources can be pulled into a conversation with an @ mention, instead of asking for a tool call:

ResourceContents
usage://todayToday's totals, split by client
usage://session/latestThe most recent session in detail
usage://statusWhich build is answering, its sources, and whether it is stale

Three prompts appear as slash commands in a client that surfaces them:

PromptAsks
daily-reviewWhat did I spend today, and on what
why-was-today-expensiveWhich model, session and project drove today's cost
project-costWhat one project has cost over a period

Each prompt names the tools to call and carries the reported-vs-estimated cost rule with it, so a paraphrased summary cannot quietly merge the two cost bases.

Most clients do not surface MCP prompts, which is why the Claude Code plugin ships the same three as real slash commands (/ai-usage:daily-review and friends). They are the same feature through two surfaces, and a test asserts the two lists cannot drift apart.

Debug CLI

Same service layer, different frontend — so the two can never disagree.

ai-usage status      # collectors, data stores, db path, record counts, last sync
ai-usage sync        # run the collectors
ai-usage stats       # totals   (--today, --days N, --since/--until)
ai-usage models      # per-model
ai-usage clients     # per-client
ai-usage projects    # per-project  (--limit N)
ai-usage sessions    # recent sessions
ai-usage session ID  # one session in detail
ai-usage daily       # per-day breakdown
ai-usage counterfactual  # these tokens on another model (--models a,b)
ai-usage verify      # re-read the sources and diff them against the local database

Add --json to any command for machine-readable output, and --project <path> to any period-based command to restrict it to one project.

ai-usage stats --today returns exactly what the usage_summary tool returns; a test in tests/mcp/parity.test.ts asserts they are byte-identical.


How cost is reported

Cost is never a single blended number. Every figure carries a basis:

BasisMeaning
reportedThe client told us the cost. OpenCode does this. Exact.
estimatedComputed from a versioned pricing table. Claude Code records no cost.
unavailableWe could not produce an honest number (e.g. no price for that model).

The Claude Code figure is an "API-equivalent estimated cost" — what those tokens would cost at Anthropic API list prices. If you are on a Claude Pro or Max subscription, your marginal cost per request is $0, and this number is not what you paid. It is useful for comparing workloads, not for reconciling a bill.

Reported and estimated costs are shown on separate lines and must not be added together.

Cache tokens are priced properly rather than lumped in with input:

  • cache read bills at 0.1× the input rate
  • cache write bills at 1.25× (5-minute TTL) or (1-hour TTL)

The two cache-write TTLs are tracked separately because both occur heavily in practice — on the machine this was developed against, 18.0M of 27.2M cache-write tokens used the 1-hour TTL, so averaging the rates would have understated cost substantially.

Correcting prices yourself

The pricing table is versioned data (src/pricing/tables/), not constants buried in a service. Prices change; to override without waiting for a release, drop a JSON file at:

~/.config/ai-usage-mcp/pricing.json      # or $AI_USAGE_PRICING_FILE

It must contain version, models, and cacheMultipliers.{read,write5m,write1h}. A malformed override raises an error rather than silently falling back — quietly using different prices than you think are in effect would be worse than failing.

ai-usage status always shows which table is in force.


Why token counts here are trustworthy

Both source formats are internal and undocumented, and both contain traps that produce badly wrong numbers if taken at face value. What this tool does about them:

  • Claude Code writes one line per content block, repeating the same usage object with a cumulative output_tokens. Summing those lines inflates every figure by 2.15×-3.05× depending on the token class (measured). Records are deduplicated on requestId + message.id, taking the maximum of each field.
  • usage.iterations[] is already included in the top-level totals and is never summed.
  • Subagent turns live in separate files (<session>/subagents/…), not behind the isSidechain flag — which is never set in practice. They are classified by path.
  • <synthetic> is not a model and is excluded.
  • OpenCode's session rollup columns can be stale. They are a cached aggregate; on the development machine they had lost 545,977 input tokens across 4 sessions. This tool reads the message grain instead, which is corroborated byte-for-byte by the independent part table.
  • Reasoning tokens mean different things per client. In Claude Code, thinking tokens are inside output_tokens; in OpenCode, reasoning is a sibling of output. Totals are computed per client accordingly, so reasoning is never double-counted.
  • Cache tokens dwarf everything else (800M cache-read vs 24K input is a real ratio), so token classes are always broken out and never presented as one blended total.

Run ai-usage verify to check this yourself. It re-reads both sources with a second, independent implementation that shares no reduction code with the collectors, and diffs the result against the database:

== opencode ==
  MATCH    opencode.db message grain (what we collect)
  MATCH    opencode.db part/step-finish grain (independent corroboration)
  INFO     opencode.db session rollup grain (what `opencode stats` headline shows)
           delta:  input -545,977 ...

== claude-code ==
  MATCH    claude JSONL, deduped by stop_reason line (independent rule)
  INFO     claude JSONL, naive sum of every usage line (NOT used — shows the double count)
           delta:  cache-read 990,824,820 ...

RESULT: every client reconciles exactly against at least one independent read of its source.

verify syncs first and compares only activity before a shared cutoff — both clients append to their stores while we read them, so without a cutoff the source always looks a few requests ahead.

Subagent turns

Included by default, because they are real spend. Every report says which way it went, and --no-subagents / includeSubagents: false excludes them. session_usage always shows the main/subagent split separately.


What stays on your machine

Everything. Your usage data never leaves the machine.

  • No telemetry, no analytics, no crash reporting, no phone-home.
  • No cloud sync, no accounts, no API keys — the tool never calls an LLM API.
  • One outbound request exists, and only in the CLI: ai-usage status asks the npm registry for the latest published version number. It sends nothing but that GET — no usage data, no identifiers — caches the answer for a day, and is disabled by AI_USAGE_NO_UPDATE_CHECK=1. The MCP server makes no network calls at all.
  • No conversation content is read into the database. The collectors extract token counts, model ids, timestamps, session ids and project paths. Prompts, completions, tool inputs and file contents are skipped.
  • Source data is opened read-only. A running OpenCode is never disturbed: the collector opens its database with a read-only connection, and falls back to a temporary snapshot copy (.db + -wal + -shm) only if that fails.
  • Everything is stored in one local SQLite file:
~/.local/share/ai-usage-mcp/usage.db          # override with AI_USAGE_DB

Delete that file to erase everything the tool knows.

Shortened here. Read the whole README on GitHub.

Signals

GitHub stars
1
Last commit
Sep 2026
Weekly downloads
302
Advanced
Delivery
ai-usage-mcp MCP server → your ahel gateway (mcp.ahel.ai) → every connected AI client.
Catalog kind
mcp-server
Gateway key
io-github-mohitbansal321-ai-usage-mcp
Source
github.com/mohitbansal321/ai-usage-mcp