Skip to main content
Glama

TokenControlPlane

Stop runaway agents. One gateway in front of all your agent traffic — MCP tools and LLM models — one budget, one kill switch. Sits between AI clients (Cursor, Claude Desktop, Windsurf) and remote MCP servers / OpenAI-compatible model APIs; hard token budgets; a single static Go binary.

What problem does this solve?

AI agents can make many tool and model calls without a single place to control the total amount of traffic they generate.

With MCP, an agent may call multiple tools repeatedly, and with LLM APIs those calls can also consume significant token budgets. Controls implemented independently inside each client or MCP server make it difficult to enforce a shared budget, revoke access immediately, or see usage across tools and models.

TokenControlPlane puts a gateway between AI clients and their MCP servers / OpenAI-compatible LLM APIs.

It provides:

  • Per-key token budgets

  • Per-server token caps

  • A kill switch for individual gateway keys

  • Rate limiting and runaway-loop detection

  • Tool allow/deny policies

  • Usage and activity visibility

  • One gateway key across MCP and LLM traffic

  • Support for both remote HTTP MCP servers and local stdio MCP servers

  • OpenAI-compatible LLM routing through the same gateway

The goal is not to replace MCP authorization or provider-side limits. It provides a centralized control point for agent traffic.

Related MCP server: mcp-guardian

Why does MCP need this?

MCP defines how an AI application communicates with tools and resources, but it does not by itself provide a centralized budget or operational control plane for all of the traffic generated by an agent.

For example, an agent may have access to several MCP servers:

Agent
  ├── MCP server A
  ├── MCP server B
  ├── MCP server C
  └── LLM provider

Without a shared gateway, each component can have its own credentials, limits, and monitoring.

TokenControlPlane changes the topology to:

                 ┌── MCP server A
                 ├── MCP server B
Agent ── TCP ────┼── MCP server C
                 └── LLM provider(s)
                    │
              TokenControlPlane

The gateway key becomes the control boundary.

This makes it possible to suspend one agent/key without changing the upstream MCP server, apply budgets across multiple services, and inspect MCP and LLM activity from one place.

TokenControlPlane also supports local stdio MCP servers by spawning the configured process and exposing it through the same gateway interface used for remote MCP servers.

Source: github.com/devthinker-ai/TokenControlPlane

Overview — MCP and LLM usage under one budget

Dashboard overview: servers, active keys, requests today, budget used, daily tokens, and top tools — MCP and LLM traffic in one place.

5-minute quickstart

docker run -p 8080:8080 -v mcp-data:/data ghcr.io/devthinker-ai/tokencontrolplane:latest
  1. Open http://localhost:8080 → register

  2. Add a remote MCP server (streamable-HTTP URL + API key, or OAuth sign-in for servers like Higgsfield — see docs/UPSTREAM_AUTH.md), or a local (stdio) server (npx / uvx / binary — see docs/STDIO.md). Browse tools and (Pro) control access — see docs/TOOL_POLICY.md.

  3. Generate a gateway key (tcp_*)

  4. Paste the Claude Desktop / Cursor snippet into your client config

  5. Call a tool — usage shows up on the dashboard; kill the key anytime → clients get 402

Total: about five minutes, zero other tooling.

Servers — upstream MCP list

Add remote HTTP or local stdio MCP servers; health, tool counts, and protocol in one list.

API keys — per-server monthly caps and kill

Issue tcp_* keys, set per-server token caps, kill a runaway key → clients get 402 on the next request.

Or build from source:

make build
./bin/tokencontrolplane -addr :8080

make build-go builds without npm if pkg/web/dist already exists.

Updating

Migrations are forward-only (no down-migrations in v1). Before each unapplied migration the gateway writes *.db.backup via VACUUM INTO (one generation).

Docker

docker compose pull && docker compose up -d

Migrations run on container start. Tag images as ghcr.io/devthinker-ai/tokencontrolplane:<TAG> and :latest on release (matches github.com/devthinker-ai/TokenControlPlane). Pinning :latest is fine because migrations are forward-only and tested; pin a TAG when you need to stay put.

Self-hosted binary

tokencontrolplane update --check          # exit 1 if newer
tokencontrolplane update                  # download, verify SHA256SUMS, replace binary
tokencontrolplane rollback                # restore tokencontrolplane.prev (one generation only)

Air-gapped:

tokencontrolplane update --file ./tokencontrolplane_linux_amd64_v1.0.0 --sha256 <hex>
# or place SHA256SUMS in the cwd and omit --sha256

Set NO_UPDATE_CHECK=1 or UPDATE_URL for mirrors. Rollback refuses if the DB schema is newer than the binary’s embedded migrations — restore a DB backup in that case.

Dashboard

GET /api/v1/version joins build metadata with the license update window. When a newer release exists and the window is active, the dashboard banner offers Update now (admin can run a verified server-side update). If the window expired, the banner points at renew — the version you own keeps working. Set NO_UPDATE_CHECK=1 to disable outbound checks (air-gap). See docs/RELEASING.md.

Stop runaway agents

Code

Meaning

401

Bad gateway key

403

Disabled key or server

402

Budget exhausted or kill switch (distinct JSON bodies)

429

Rate limit (Retry-After)

503

Upstream circuit open

  • Kill switch: kill a key from the dashboard or /admin → immediate 402 on the next request.

  • Local (stdio) MCP servers: spawn npx / uvx / binaries; same client URL as remote — see docs/STDIO.md.

  • One-time license, no subscription — pay once, self-host, keep the version you own.

  • Team seats — invite colleagues (no SMTP); named-team flat key (docs/TEAM.md).

  • LLM providers — OpenAI-compatible chat completions through the same keys/budgets (docs/LLM_ROUTING.md).

  • Auto-kill: >120 requests / 60s per key (configurable via LOOP_THRESHOLD) → key auto-killed.

  • Budgets: estimated tokens = bytes/4; enforced pre-flight (the oversized call completes; the next dies).

Server detail — per-tool toggles

Tool policy: enable or disable what agents may call without changing the upstream.

Providers — model routes and fallbacks

LLM providers and model routes — same keys and budgets as MCP traffic.

Add provider — one-click presets

Quick-add presets (Anthropic, Groq, Mistral, Gemini, Ollama, …) or a custom OpenAI-compatible base URL.

Activity feed — kills, budgets, circuit, policy

Activity: kills, budget hits, circuit open/closed, tool denied by policy, OAuth, plan changes.

Members — seats and roles

Team seats and roles — humans in the dashboard, not API consumers.

Settings — 2FA and SMTP

Settings: authenticator 2FA for dashboard users; optional SMTP for invites and password reset.

Self-hosted licensing

Offline RS256 license JWTs (TOKENCONTROLPLANE_LICENSE_KEY). Unlicensed installs get the free tier (3 servers, 3 seats, 5M monthly tokens). Invalid/expired keys fail open to free — a bad key never takes down an air-gapped gateway.

Self-hosted licensing is offline and honor-based; keys are bound to plan caps, not machines, in v1. No phone-home.

Buy & install

No subscription. Pay once via Lemon Squeezy (merchant of record — they handle VAT/sales tax/refunds). You keep the version you bought; renew only for the next version. After checkout the license key appears in your dashboard License page and in the LS order email.

TOKENCONTROLPLANE_LICENSE_KEY=*** tokencontrolplane
# or in docker-compose:
# environment:
#   TOKENCONTROLPLANE_LICENSE_KEY: "***"

Sign keys manually with tokencontrolplane-license (private key never in the repo):

tokencontrolplane-license --private-key ~/.secrets/license.pem --in claims.json

Configuration

Everything is env vars (see tokencontrolplane -h):

Variable

Purpose

JWT_SECRET

Dashboard session secret

ADMIN_TOKEN

/admin/* bearer token

GATEWAY_URL

Public URL for client snippets

DISABLE_REGISTER

1 blocks new account signup (invite join still works)

TOKENCONTROLPLANE_LICENSE_KEY

Self-hosted license JWT

TOKENCONTROLPLANE_LICENSE_PRIVATE

RSA private key path (dashboard mint / reissue)

TOKENCONTROLPLANE_FOUNDERS_LIMIT

Founders offer cap (default 100; 0=unlimited, -1=off)

LQ_SECRET_KEY

Lemon Squeezy API key

LQ_WEBHOOK_SECRET

Webhook HMAC secret

LQ_STORE_ID / LQ_VARIANT_ID_PRO / LQ_VARIANT_ID_TEAM

LS catalog IDs

DB_PATH

SQLite file (default ~/.tokencontrolplane/gateway.db)

UPDATE_URL

Override GitHub releases API (mirrors / air-gap)

NO_UPDATE_CHECK

1 disables outbound update checks

GITHUB_REPO

owner/name for releases (default devthinker-ai/TokenControlPlane)

Docker Compose

cp .env.example .env   # optional
docker compose up --build

SQLite persists under ./data.

Development

go test ./...
cd frontend && npm test && npm run build

CGO is off (CGO_ENABLED=0); SQLite is pure Go (modernc.org/sqlite).

Licensing

Two different things are licensed here:

  1. The code — Apache-2.0 (LICENSE). Free to use, modify, and redistribute, including commercially. You must keep the license and copyright notices. There is no requirement to share changes back, no copyleft, and no fee.

  2. The license key — commercial license. A one-time purchase (see Buy & install) that unlocks Pro/Team plan caps. The key is an offline RS256 JWT signed with the vendor's private key; it grants plan capabilities, not a copy of the code.

This is the standard open-core model: the source is fully open and auditable (self-hosters can verify exactly what runs), while revenue comes from plan-gated capabilities delivered via a signed key.

What this means in practice:

You can…

Under Apache-2.0

Run the gateway free (free tier, fail-open)

Yes

Buy a key for Pro/Team caps

Yes

Fork, modify, or redistribute the source, even commercially

Yes

Forge a license key

No — only the vendor's private key can sign one

Honor-based gating. The license check is plain source code, so a determined fork can change which caps it enforces. That is permitted by Apache-2.0. Enforcement is honor-based, not cryptographic — like other open-core products (GitLab, Keycloak). No phone-home: an unlicensed or expired key fails open to the free tier and never takes a gateway down.

Private key hygiene. Only the public key is committed (pkg/license/license_pub.pem). The signing private key is kept out of the repo and injected at build/sign time via TOKENCONTROLPLANE_LICENSE_PRIVATE or --private-key.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    A
    maintenance
    Guardrail sidecar proxy between AI agents and their MCP/REST/CLI tools. Policy engine, human approval gates, time-limited grants, rate limiting, and OTEL tracing. One Go binary, one YAML config, fail-closed by default.
    1
    Apache 2.0
  • A
    license
    A
    quality
    B
    maintenance
    Security, cost, and health governance proxy for MCP infrastructure. Enforces YAML-configurable security policies (blocklists, rate limits, token budgets), tracks real token costs via tiktoken, monitors server health with live JSON-RPC probes. Features OAuth 2.1/OIDC with RBAC, web dashboard, payload normalization, semantic shell AST analysis, mTLS, and a formal STRIDE threat model.
    4
    173 npm
    3
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Budget & cost control for AI agents: hard per-agent spend caps, rate limits, idempotency, and human-in-the-loop approval — enforced before each LLM call, not after the invoice. One hosted MCP endpoint (no proxy or self-hosting), settled via x402 (USDC on Base).
    MIT