Skip to main content
Glama
README.md
# tbcontracts-mcp

An MCP (Model Context Protocol) server that exposes
[`token-budget-contracts`](https://pypi.org/project/token-budget-contracts/)
as tools, so any MCP-aware client (Claude Code, Claude Desktop, Cursor,
etc.) can manage token budgets across a multi-agent LLM system.

## What this actually does

Multi-agent orchestrators (a planner spawning a researcher, a writer, a
critic, ...) burn tokens unevenly. A high-priority agent can starve
mid-task while a low-priority agent sits on unused budget. This server's
one job is answering, in real time: **given these agents' priorities and
current spend, how should the remaining budget move right now?**

It does this by wrapping `token-budget-contracts`'
priority-weighted `Reallocator`: spare budget flows from idle or
lower-priority agents to whichever agent is actually starved, never
below a donor's protected minimum reserve, and never "uphill" from a
more important agent to a less important one.

This is **not** a cost-tracking dashboard or a network gateway. See
[Honest scope](#honest-scope) below.

## Install

```bash
pip install tbcontracts-mcp
```

This pulls in `token-budget-contracts>=0.3.0` and `opentelemetry-api` as
dependencies. Requires Python 3.10+ (see [Why not Python 3.9](#why-not-python-39)).

## Tools

| Tool | What it does |
|---|---|
| `register_agent` | Register an agent with a priority weight and initial token budget. |
| `record_spend` | Record raw input/output tokens an agent consumed for a task. Automatically triggers priority-weighted reallocation if the agent goes over budget. |
| `get_remaining_budget` | Look up one agent's current remaining budget, priority, and reserve. |
| `request_reallocation` | **The core tool.** Given an agent that needs more tokens right now, runs the real priority-weighted borrowing logic and returns a concrete plan: which agents gave up how much, which agent received it, and why each donor was eligible. |
| `get_budget_snapshot` | Full current state of every registered agent, as structured JSON. |

Every tool takes a strict, typed JSON input schema and returns structured
JSON (`{"success": true/false, ...}`) - never free text - so a calling
agent or orchestrator can parse the result programmatically.

### Error handling

Unknown agent IDs, invalid input, and budget-exceeded conditions all come
back as a structured error, never a stack trace:

```json
{
  "success": false,
  "error": {
    "type": "unknown_agent",
    "message": "Agent 'ghost' was never registered. Call register_agent first.",
    "agent_id": "ghost",
    "known_agents": ["critic", "researcher"]
  }
}
```

Error `type` is one of `unknown_agent`, `invalid_input`, `budget_exceeded`,
`tbcontracts_error`, or `internal_error`. A bad tool call never crashes
the server process - the MCP client keeps working.

## Quick start (as a library, for testing)

```python
from tbcontracts_mcp import server

server.register_agent(agent_id="researcher", priority=3, max_tokens=4000)
server.register_agent(agent_id="critic", priority=1, max_tokens=2000)

server.record_spend(agent_id="researcher", input_tokens=3800, output_tokens=100)
# -> over budget by 400 tokens; automatically borrows from critic

plan = server.request_reallocation(agent_id="researcher", tokens_needed=1000)
print(plan)
```

Normally you won't call these functions directly - an MCP client calls
them as tools over stdio. See the client configs below.

## Using it from an MCP client

The server runs over stdio and needs no network setup - just point your
client at the `tbcontracts-mcp` command.

### Claude Code

```bash
claude mcp add tbcontracts -- tbcontracts-mcp
```

Or add it directly to `.mcp.json`:

```json
{
  "mcpServers": {
    "tbcontracts": {
      "command": "tbcontracts-mcp"
    }
  }
}
```

### Claude Desktop

Add to `claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "tbcontracts": {
      "command": "tbcontracts-mcp"
    }
  }
}
```

### Cursor

Add to `.cursor/mcp.json`:

```json
{
  "mcpServers": {
    "tbcontracts": {
      "command": "tbcontracts-mcp"
    }
  }
}
```

Any of these can equally run it via `python -m tbcontracts_mcp` instead of
the console script, e.g. if you've installed it into a specific venv:

```json
{
  "mcpServers": {
    "tbcontracts": {
      "command": "/path/to/venv/bin/python",
      "args": ["-m", "tbcontracts_mcp"]
    }
  }
}
```

## Observability

Spend recorded through `record_spend` is emitted two ways, both additive
to your existing observability stack rather than replacing it:

1. **The underlying library's own OTel spans.** `token-budget-contracts`
   already instruments every governance decision (registration, spend,
   reallocation) as an OpenTelemetry span when telemetry is enabled. This
   server wires `record_spend` straight through that existing hook rather
   than building a parallel tracer - set `TBCONTRACTS_MCP_OTEL=1` in the
   server's environment to turn it on (uses the global OTel tracer
   provider; configure your exporter the usual OTel way).
2. **A `gen_ai.client.token.usage` counter**, following the emerging
   OpenTelemetry `gen_ai.*` semantic conventions, emitted via
   `opentelemetry-api` for every `record_spend` call. This tracks **raw
   input/output token counts per agent**, not pre-computed dollar cost -
   pricing tables change constantly and a token counter shouldn't be
   coupled to one. Attach whatever OTel `MeterProvider`/exporter you like
   in the process that launches this server; if none is configured, this
   is a no-op.

## Honest scope

`tbcontracts-mcp` is the allocation-decision layer for one thing:
priority-weighted budget reallocation between agents you've already told
it about. It is meant to be composed with other tools, not to replace
them. Specifically, it does **not**:

- **do cross-provider cost tracking.** It emits raw token counters, not
  dollar costs, and has no notion of a pricing table for OpenAI,
  Anthropic, or anyone else.
- **do network-level rate limiting or gateway routing.** It doesn't sit
  in the request path between your app and an LLM provider, and it can't
  throttle or route calls. Tools like Bifrost, MuleSoft, or Solo.io's
  gateways already do that well - use one of those alongside this.
- **replace an observability platform.** It emits spans/counters you can
  send to Grafana, Datadog, Honeycomb, etc., but it isn't a dashboard,
  storage backend, or alerting system itself.

What it does do: given the agents you've registered and their current
spend, decide - and actually execute - how unused budget should move
between them right now, based on priority.

## Why not Python 3.9?

`token-budget-contracts` itself supports Python 3.9+, but the official
`mcp` Python SDK this server depends on has never supported Python 3.9
(it requires 3.10+ on every released version). This package therefore
requires Python 3.10+, even though the library it wraps does not.

## Development

```bash
git clone https://github.com/swaranshu-borgaonkar/tbcontracts-mcp
cd tbcontracts-mcp
pip install -e ".[dev]"
pytest -v
```

## License

MIT for the code in this package. `token-budget-contracts`, which this
server wraps, implements the governance model described in a pending
U.S. provisional patent application (see its own README for details). If
you plan to use this commercially at scale, consult your own counsel.

TDQS

A4.4/5.0

Scored across 5 tools

Disambiguation5/5

Each tool maps to a distinct action: registration, spend recording, single-agent read, system-wide read, and reallocation. Although record_spend can trigger reallocation as a side effect, the descriptions clearly separate that automatic behavior from the explicit request_reallocation decision tool.

Naming Consistency5/5

All tool names follow a consistent snake_case verb_noun pattern: register_agent, record_spend, get_remaining_budget, get_budget_snapshot, request_reallocation. The verb and noun choices are predictable and match each tool's purpose.

Tool Count5/5

Five tools is well-scoped for a narrow budget-management domain. Each tool earns its place, covering registration, spending, inspection, and reallocation without redundancy or bloat.

Completeness4/5

The core lifecycle is covered: register agents, record spend, inspect individual and global state, and manually reallocate budget. Minor gaps include no explicit unregister/agent removal or direct priority adjustment without re-registering/resetting, but these are workable limitations rather than blocking dead ends.

Maintenance

ActivitySlowing
ResponsivenessNo issues