npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@hassanalitamam/mcp-budget

v0.1.0

Published

Transparent MCP proxy: budget-aware result shaping with zero info loss. Ships Claude Code / Cursor / Gemini plugins and an agent-guidance skills pack.

Readme

mcp-budget

A transparent MCP proxy that shrinks oversized tool results — without losing access to the full content.

npm version CI License: Apache-2.0 MCP Registry

Quickstart · How it works · Skills & integrations · Savings report · Host configs · FAQ


📦 What is this?

mcp-budget is a local proxy that wraps any MCP (Model Context Protocol) server and reshapes oversized tool results to fit a per-call token budget — so your AI agent (Claude Code, Cursor, VS Code, Cline, Gemini CLI) doesn't burn its context window on a single tool call.

Without losing data. Every full upstream result is stored locally (content-addressed by BLAKE3) before any shaping runs. The agent retrieves anything missed via a new fetch_result(result_id, query?) tool — no upstream re-run, safe for mutating tools (send email, create issue, browser actions).

With agent guidance built in. The proxy ships a Claude Code / Cursor / Gemini plugin and a skills pack that teaches the agent how to read the _meta.mcp.budget envelope, call fetch_result with the cheapest slice that answers the question, and recover from the documented error modes.

"MCP Discussion #315 was the right idea, rejected for the wrong reason — here it is as a proxy."

mcp-budget is complementary to mcp-compressor: compressor shrinks tool schemas (tools/list bloat), budget shrinks tool results (tools/call bloat). Run both for max savings.

🎯 The problem

graph LR
    subgraph Without["WITHOUT mcp-budget"]
        A1[Agent calls read_file] --> B1["MCP server returns<br/>14,604 tokens"]
        B1 --> C1["Agent context:<br/>14,604 tokens burned"]
        style C1 fill:#fee
    end

    subgraph With["WITH mcp-budget"]
        A2[Agent calls read_file] --> P[mcp-budget proxy]
        P --> B2["MCP server returns<br/>14,604 tokens"]
        B2 --> P
        P --> S[("Local store<br/>BLAKE3-addressed")]
        P --> C2["Agent context:<br/>499 tokens (-96.6%)"]
        style C2 fill:#efe
    end

⚡ 60-second install

# Wrap any MCP server with mcp-budget
npx @hassanalitamam/mcp-budget --default-budget 8000 -- npx -y @modelcontextprotocol/server-fetch

Everything before -- is mcp-budget config; everything after is the upstream server command.

📊 Benchmark results

Verified against the real @modelcontextprotocol/server-filesystem, judged by OpenAI gpt-5.4-mini, tiktoken cl100k_base, budget = 500 tokens. Full analysis: docs/BENCH_RESULTS.md.

| Server | Tasks | Shaped | Median reduction | p90 | Max | Success delta | Errors | |----------------|------:|-------:|-----------------:|----:|----:|--------------:|-------:| | Filesystem MCP | 20 | 9 | 58.4% | 83.8% | 96.6% | +0.0 pp | 0 / 40 |

  • 🏆 Largest single win: fs-008 — 14,604 → 499 tokens (96.6% saved)
  • Zero errors on 20/20 tasks across both direct + proxied paths
  • +0.0 pp success delta — external LLM judge scored every shaped result identically to its direct counterpart
  • Zero info loss — roundtrip tests prove byte-for-byte recoverability via fetch_result

🛡️ How it works

sequenceDiagram
    participant Agent
    participant Proxy as mcp-budget
    participant Upstream
    participant Store as Local store

    Agent->>Proxy: tools/call read_text_file
    Proxy->>Upstream: forward
    Upstream-->>Proxy: full result (14,604 tokens)
    Proxy->>Store: put(full, result_id)
    Note over Proxy: shape to fit budget
    Proxy-->>Agent: shaped (499 tokens) + result_id

    Note over Agent: needs more?
    Agent->>Proxy: fetch_result(result_id)
    Proxy->>Store: get(result_id)
    Store-->>Proxy: original (14,604 tokens)
    Proxy-->>Agent: full payload — no upstream re-run

Four shaping strategies tried in order (per-tool configurable):

| Strategy | When | What it does | |---|---|---| | structured | Tool has an outputSchema + structuredContent | Project highest-priority fields that fit the budget. Schema-validated. | | verbatim-trim | Text content | Keep head (60%) + tail (30%) of text, mark the elided middle. | | head-preview | Text content over budget | Keep a coherent head + attach a mcp-budget:// ResourceLink to the rest. | | resource-link | Guaranteed fallback | Replace content with a ResourceLink to the full payload. Agent calls fetch_result to retrieve. |

🧠 Skills & integrations

mcp-budget ships a plugin and skills pack so AI agents automatically learn to use the proxy efficiently — read _meta.mcp.budget, call fetch_result(id, query) with the cheapest slice that answers the question, and handle the documented error reasons (store_entry_missing, no_store_mode, race_eviction, invalid_query, arguments_unavailable).

Hosts without a skills mechanism still benefit because the fetch_result tool description itself has been enriched with when-to-use guidance (visible in any MCP client's tool list).

Claude Code

/plugin marketplace add hassanalitamam/mcp-budget
/plugin install mcp-budget@mcp-budget-plugins

After install, five skills appear under /skills:

  • mcp-budget — top-level overview; loads on any _meta.mcp.budget mention.
  • fetch-result-recovery — when and how to call fetch_result with the right SliceQuery variant.
  • budget-hints — per-call _meta.mcp.budget/maxResultTokens operator hints.
  • troubleshooting — the documented error reasons + remediation.
  • savings-report — driving the savings subcommand and reading the net-vs-gross output.

Cursor

Add the workspace plugin manifest at .cursor-plugin/plugin.json to your .cursor/plugins/ directory. Cursor surfaces the same skill catalog as Claude Code under its plugin context UI.

Gemini CLI

gemini extensions install --auto-update https://github.com/hassanalitamam/mcp-budget

AGENT_GUIDE.md (mirrors the skills-pack guidance in a single file) is auto-loaded via .gemini/settings.json so the Gemini model gains the same when-to-call-fetch_result instincts as the Claude / Cursor flows.

MCP Registry

server.json lists the proxy at io.github.hassanalitamam/mcp-budget so MCP-Registry-aware hosts (LangGraph, Continue's MCP catalogue, …) can discover and install the proxy without any host-specific manifest.

📈 Measuring your savings

Want to see how much the proxy is saving you? Enable opt-in local telemetry and run the savings report.

# 1. Start the proxy with telemetry on (or set MCP_BUDGET_TELEMETRY=events)
npx @hassanalitamam/mcp-budget --telemetry events --default-budget 5000 -- <upstream-server>

# 2. Use the proxy normally for a while (drive your agent / MCP client).

# 3. Show the report
npx -p @hassanalitamam/mcp-budget mcp-budget-cli savings

Example output:

Savings — last 7 days (net)
─────────────────────────────────────────────────────────────────
                            calls    gross     redeemed    net
By tool
  read_text_file              127    453,120     12,400   440,720
  fetch                        43    121,800      5,200   116,600
  search_files                 18     28,400          0    28,400
─────────────────────────────────────────────────────────────────
Totals                        188    603,320     17,600   585,720

Net savings ratio: 97.1% of gross retained after fetch_result redemptions.
Tokenizer: tiktoken-cl100k_base. Window: 2026-05-14 → 2026-05-21 (UTC).

Net vs gross — why the honest number subtracts

gross_saved is the sum of original_tokens − shaped_tokens over every shape event. But when the agent calls fetch_result(id, {type: "full"}) to pull back the content that was shaped away, those tokens are re-spent. The report subtracts them as redeemed, leaving net_saved = gross − redeemed — the only number that reflects what the proxy actually saved your context window. The --gross flag falls back to the marketing number that ignores fetch-redeems if you need it.

savings subcommand flags

| Flag | Values | Default | Meaning | |---|---|---|---| | --by | tool | server | strategy | day | tool | Grouping key for the breakdown rows. | | --since | duration (e.g. 24h, 7d, 30d) | 7d | Lookback window. | | --top | integer | 20 | Maximum rows per group. | | --gross | flag | off | Show gross savings only (ignore fetch_redeem). | | --json | flag | off | Emit machine-readable JSON instead of the text table. |

Privacy

All telemetry is local. Nothing leaves your machine. Honors DO_NOT_TRACK=1 (W3C universal opt-out, takes precedence over every other setting). Opt out anytime by removing the --telemetry events flag and wiping the call_events rows (or mcp-budget-cli store clear --yes for a full reset).

🔌 Host configs

{
  "mcpServers": {
    "fetch": {
      "command": "npx",
      "args": ["@hassanalitamam/mcp-budget", "--default-budget", "8000", "--", "npx", "-y", "@modelcontextprotocol/server-fetch"]
    }
  }
}
{
  "mcpServers": {
    "fetch": {
      "command": "npx",
      "args": ["@hassanalitamam/mcp-budget", "--default-budget", "8000", "--", "npx", "-y", "@modelcontextprotocol/server-fetch"]
    }
  }
}
{
  "servers": {
    "fetch": {
      "type": "stdio",
      "command": "npx",
      "args": ["@hassanalitamam/mcp-budget", "--default-budget", "8000", "--", "npx", "-y", "@modelcontextprotocol/server-fetch"]
    }
  }
}
{
  "mcpServers": {
    "fetch": {
      "command": "npx",
      "args": ["@hassanalitamam/mcp-budget", "--default-budget", "8000", "--", "npx", "-y", "@modelcontextprotocol/server-fetch"]
    }
  }
}
{
  "mcpServers": {
    "fetch": {
      "command": "npx",
      "args": ["@hassanalitamam/mcp-budget", "--default-budget", "8000", "--", "npx", "-y", "@modelcontextprotocol/server-fetch"]
    }
  }
}

Canonical copy-paste files live in examples/.

⚙️ Configuration

CLI flags also accept env vars (MCP_BUDGET_DEFAULT_BUDGET=…, etc.) or a policies.toml file at the platform config directory.

| Flag | Default | Notes | |---------------------|--------------------------------------------------------------------|----------------------------------------------------| | --default-budget | 8000 | Tokens per response. | | --prefer-shape | structured,verbatim-trim,head-preview,resource-link | Strategy order — first that fits the budget wins. | | --policy-file | platform config dir | Per-tool overrides (TOML). | | --store-path | platform data dir | SQLite + content-addressed blobs. | | --store-ttl-days | 7 | How long to keep stored results. | | --store-cap-mb | 1024 | LRU cap (1 GiB default). | | --no-store | off | Privacy / dry-run; disables fetch_result. | | --log-file | unset | Required to enable logging in stdio mode. | | --log-level | warn | error \| warn \| info \| debug. | | --tokenizer | auto | auto \| tiktoken \| anthropic \| approx. | | --model-hint | unset | Drives tokenizer resolver (e.g. claude-sonnet-4).| | --transport | stdio | stdio \| sse \| http. | | --telemetry | off | off \| events — opt-in local savings tracking. |

Example policies.toml (per-tool overrides):

[defaults]
budget = 8000
prefer_shape = ["structured", "verbatim-trim", "head-preview", "resource-link"]

[servers."github-mcp"]
budget = 4000

[tools."playwright::browser_snapshot"]
budget = 6000
prefer_shape = ["head-preview", "resource-link"]

[tools."github-mcp::list_*"]
budget = 3000

Precedence: per-request _meta.mcp.budget/* > per-tool exact > per-tool glob (longest pattern) > per-server > [defaults] > built-in.

🛠️ Subcommands

mcp-budget-cli store stats              # store size, entry count, oldest entry
mcp-budget-cli store gc                 # force TTL+LRU eviction now
mcp-budget-cli store clear --yes        # wipe all entries
mcp-budget-cli store get <result_id>    # pretty-print a stored result
mcp-budget-cli doctor                   # check tokenizer + store + runtime
mcp-budget-cli savings                  # token savings report (see above)
mcp-budget --print-config -- <cmd>      # dump effective config as JSON

🌍 Positioning vs alternatives

| Project | Layer | Scope | Complement? | When to use | |---|---|---|---|---| | mcp-budget (this) | proxy | tool result shaping + retrieval | — | huge tool outputs | | mcp-compressor | proxy | tool schema compression | yes ✅ | huge tool lists | | mcp-cache | proxy | response caching | yes ✅ | repeated identical calls | | Morph Flash Compact | host plugin | per-turn context compaction | yes ✅ | long conversations | | Better Stack Context Mode | host feature | session-level context budgeting | yes ✅ | long conversations | | Cloudflare Code Mode | runtime | code-execution-driven tool wrapping | yes ✅ | client supports code execution | | Discussion #315 | protocol spec | per-call size negotiation (rejected) | — | will not ship at protocol layer |

❓ FAQ

Will this break my agent? No. The benchmark shows +0.0 pp success delta when judged by an external LLM across all 20 tasks. The shaped result keeps enough information for the agent to act, and fetch_result is always one call away. The skills pack teaches agents the recovery pattern explicitly.

Does it cost anything to run? No. Pure local-first: no cloud, no telemetry by default. The opt-in --telemetry events mode also stays 100% local — nothing leaves your machine. An OpenAI key is only needed if you run the bench harness yourself.

What if the local store fills up? 1 GiB LRU cap by default + 7-day TTL. Both configurable. The store is content-addressed by BLAKE3 — identical calls deduplicate to a single blob. A 5-minute sticky window protects in-flight fetch_result calls from eviction.

What about mutating tools (send email, create issue, browser actions)? Safe. fetch_result reads from the local store and never re-runs the upstream tool. Retries don't double-send. On a miss, the proxy returns isError=true with the original arguments embedded so the agent can decide whether re-running is safe.

What's in _meta.mcp.budget on every response? original_tokens, shaped_tokens, strategy, result_id, tokenizer_used, model_hint, reason, persistent_storage. Use it to debug and to call fetch_result(result_id) when you need the full payload. The skills pack walks through every field with examples.

Can I use a different tokenizer? Yes. tiktoken cl100k_base for OpenAI families (default), Anthropic SDK count_tokens for Claude (requires ANTHROPIC_API_KEY), or approx (chars/4) as a fallback.

What does the --telemetry events flag store? One row per shape event and one per fetch_result redemption: tool name, server name, strategy, original / shaped token counts, tokenizer, model hint, timestamp. No tool arguments, no result content, no user data. Stored in a local SQLite table you can wipe at any time. DO_NOT_TRACK=1 forces it off regardless.

📚 Documentation

🗂️ Repository layout

mcp-budget/
├── src/                   # proxy implementation
├── tests/                 # unit + integration tests
├── skills/                # Claude Code skills pack (5 skills + references)
├── docs/                  # user / architecture / design docs
├── examples/              # copy-paste host configs
├── bench/                 # benchmark harness + fixtures
├── .claude-plugin/        # Claude Code plugin manifest
├── .cursor-plugin/        # Cursor plugin manifest
├── .gemini/               # Gemini context auto-injection
├── server.json            # MCP Registry listing
├── AGENT_GUIDE.md         # agent runtime guide
└── legacy/                # historical Python implementation + planning docs

The legacy/python/ directory preserves the original reference implementation (Python + FastMCP 3.x) that defined the algorithm, plus the audit and planning documents from the project's design phase. It is kept for historical reference; active development happens at the root.

🤝 Contributing

See CONTRIBUTING.md. Issues and PRs welcome — please run the test suite before submitting.

📜 License

Apache-2.0.

📋 Changelog

CHANGELOG.md follows Keep a Changelog 1.1.