Skip to main content

Don't Pester Your Customer — Bitcoin Lightning micropayments for MCP servers

Project description

Tollbooth DPYC

License PyPI version Python 3.10+

Milo drives the Lightning Turnpike — Don't Pester Your Customer

Don't Pester Your Customer — Bitcoin Lightning micropayments for MCP servers.

The metaphors in this project are drawn with admiration from The Phantom Tollbooth by Norton Juster, illustrated by Jules Feiffer (1961). Milo, Tock, the Tollbooth, Dictionopolis, and Digitopolis are creations of Mr. Juster's extraordinary imagination. We just built the payment infrastructure.


The Problem

Thousands of developers are building MCP servers — services that let AI agents like Claude interact with the world. Knowledge graphs, financial data, code repositories, medical records. Each one is a city on the map. But the turnpike between them? Wide open. No toll collectors. No sustainable economics. Just a growing network of roads that nobody's figured out how to fund.

Every MCP operator faces the same question: how do I keep the lights on?

Traditional API keys with monthly billing? You're running a SaaS company now. The L402 protocol — Lightning-native pay-per-request? Every single API call requires a payment negotiation. Milo's toy car stops at every intersection to fumble for exact change.

The Solution

Tollbooth DPYC takes a different approach — one that respects everyone's time:

Milo drives up to the tollbooth once, buys a roll of tokens with a single Lightning invoice, and drives. No stops. No negotiations. No per-request friction. The tokens quietly decrement in the background. When the roll runs low, he buys another. The turnpike stays fast.

Prepaid credits over Bitcoin's Lightning Network, gated at the tool level, settled instantly, with no subscription management and no third-party payment processor taking a cut.

Install

pip install tollbooth-dpyc

What's in the Box

Module Purpose
TollboothConfig Plain frozen dataclass — no pydantic, no env-var reading. Your host constructs it.
UserLedger Per-user credit balance with debit/credit/rollback, daily usage logs, JSON serialization.
BTCPayClient Async HTTP client for BTCPay Server's Greenfield API — invoices, payouts, health checks.
VaultBackend Protocol for pluggable persistence — implement store_ledger, fetch_ledger, snapshot_ledger.
LedgerCache In-memory LRU cache with write-behind flush. The hot path for all credit operations.
ToolTier Cost tiers for tool-call metering (FREE=0, READ=1, WRITE=5, HEAVY=10 sats per call).
tools.credits Ready-made tool implementations: purchase_credits, check_payment, check_balance, and more.

Quick Start

from tollbooth import TollboothConfig, UserLedger, BTCPayClient, LedgerCache

# Configure — your host reads env vars, Tollbooth gets a plain dataclass
config = TollboothConfig(
    btcpay_host="https://your-btcpay.example.com",
    btcpay_store_id="your-store-id",
    btcpay_api_key="your-api-key",
    tollbooth_royalty_address="tollbooth@btcpay.digitalthread.link",
)

# Create a BTCPay client
async with BTCPayClient(config.btcpay_host, config.btcpay_api_key, config.btcpay_store_id) as client:
    # Create an invoice for 1000 sats
    invoice = await client.create_invoice(1000, metadata={"user": "milo"})
    print(f"Pay here: {invoice['checkoutLink']}")

Configuration

TollboothConfig is a plain frozen dataclass. Your host application constructs it from its own settings (env vars, pydantic-settings, YAML — whatever you prefer). Tollbooth never reads environment variables directly.

Field Type Default Purpose
btcpay_host str | None None BTCPay Server URL for creating invoices and checking payments
btcpay_store_id str | None None BTCPay store ID — each operator runs their own store
btcpay_api_key str | None None BTCPay API key — must have invoice + payout permissions
btcpay_tier_config str | None None JSON string mapping tier names to credit multipliers
btcpay_user_tiers str | None None JSON string mapping user IDs to tier names
seed_balance_sats int 0 Free starter balance granted to new users (0 to disable)
tollbooth_royalty_address str | None None Lightning Address for the 2% royalty payout to the Tollbooth originator
tollbooth_royalty_percent float 0.02 Royalty percentage (0.02 = 2%)
tollbooth_royalty_min_sats int 10 Minimum royalty payout in sats (below this, no payout fires)
authority_public_key str | None None Authority's Ed25519 PEM public key for certificate verification. When set, purchase_credits requires a valid Authority JWT.
authority_url str | None None Authority MCP endpoint URL (scaffolding for future use)

Tool Functions

The tollbooth.tools.credits module provides ready-made implementations that your MCP server wraps as tools. Each function takes infrastructure objects (BTCPayClient, LedgerCache) as parameters — you wire them up, Tollbooth handles the logic.

Function Purpose
purchase_credits_tool Creates a BTCPay invoice, records it as pending, returns a checkout link. Validates Authority certificate when authority_public_key is configured.
verify_certificate Verifies an Authority-signed Ed25519 JWT. Checks signature, expiry, and anti-replay (JTI).
check_payment_tool Polls an invoice, credits the balance on settlement, fires the royalty payout. Idempotent.
check_balance_tool Returns current balance, usage summary, tier info, and invoice history. Read-only.
restore_credits_tool Recovers credits from a paid invoice lost to cache/vault issues. Checks vault first, falls back to BTCPay.
btcpay_status_tool Diagnostics: BTCPay connectivity, store name, API key permissions, royalty config.
compute_low_balance_warning Pure function — returns a warning dict if balance is below threshold, None if healthy.

The Three-Party Settlement

Here's where the story takes a turn that even Milo wouldn't expect.

We didn't build Tollbooth to sell. We built it to give away — like the Massachusetts Turnpike Authority. The Authority doesn't operate every toll plaza. Independent operators run the booths. What the Authority does is simpler: it collects a small percentage of every fare that flows through infrastructure it designed.

When a user purchases credits, the settlement is three-party:

  1. Milo pays the operator's Lightning invoice
  2. The operator's BTCPay Server credits Milo's balance
  3. Automatically, in the background — BTCPay creates a small payout to the Tollbooth originator's Lightning Address

A royalty. Two percent of the fare. The operator sees it transparently in their BTCPay dashboard. Milo never knows it happened.

The enforcement is both technical and social. At startup, Tollbooth inspects the operator's BTCPay API key permissions. If the key lacks payout capability, Tollbooth refuses to start. Not a warning. A hard stop. The social contract, made executable.

The Economics

For Milo (the user): Nothing changes. Buy credits, use tools, drive the turnpike.

For the operator: A free, production-tested monetization framework. No license fee. The 2% royalty is a rounding error compared to the revenue you couldn't collect before. The tollbooth pays for itself on the first transaction.

For the ecosystem: Revenue scales with adoption, not effort. Every new MCP server that installs Tollbooth becomes a node in the Lightning economy. The infrastructure hums along — collecting its modest fare, maintaining the roads, and making sure the turnpike stays open for everyone.

It's the transition from mining fees to transaction fees. You stop competing on compute and start collecting on flow.

Reference Integration

thebrain-mcp — the first MCP server powered by Tollbooth. A FastMCP service that gives AI agents access to TheBrain knowledge graphs, with all 40+ tools metered via Tollbooth credits.

Architecture

Tollbooth is a three-party ecosystem:

Repo Role
tollbooth-authority The institution — tax collection, EdDSA signing, purchase order certification
tollbooth-dpyc (this package) The booth — operator-side credit ledger, BTCPay client, tool gating
thebrain-mcp The first city — reference MCP server powered by Tollbooth

See the Three-Party Protocol diagram for the full architecture.

tollbooth-authority               tollbooth-dpyc (this package)     your-mcp-server (consumer)
================================  ================================  ================================
EdDSA signing + tax ledger        TollboothConfig                   Settings ──constructs──> TollboothConfig
certify_purchase → JWT            UserLedger                        implements VaultBackend
Authority BTCPay                  BTCPayClient                      TOOL_COSTS maps tools to ToolTier
                                  VaultBackend (Protocol)
                                  LedgerCache + credit tools

Dependency flows one way: your-mcp-server --> tollbooth-dpyc. Authority is a network peer, not a code dependency. Only runtime dependency: httpx.

Development

git clone https://github.com/lonniev/tollbooth-dpyc.git
cd tollbooth-dpyc
python -m venv venv
source venv/bin/activate
pip install -e ".[dev]"
pytest tests/ -q

Further Reading

The Phantom Tollbooth on the Lightning Turnpike — the full story of how we're monetizing the monetization of AI APIs, and then fading to the background.

License

Apache 2.0 — see LICENSE.


Because in the end, the tollbooth was never the destination. It was always just the beginning of the journey.

Project details


Release history Release notifications | RSS feed

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tollbooth_dpyc-0.1.2.tar.gz (1.9 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

tollbooth_dpyc-0.1.2-py3-none-any.whl (29.0 kB view details)

Uploaded Python 3

File details

Details for the file tollbooth_dpyc-0.1.2.tar.gz.

File metadata

  • Download URL: tollbooth_dpyc-0.1.2.tar.gz
  • Upload date:
  • Size: 1.9 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for tollbooth_dpyc-0.1.2.tar.gz
Algorithm Hash digest
SHA256 07bc263ff754bc9da9c9a7f14b5a34e2ee8dec4ee963cefc404b6e1171cd984f
MD5 5cf89a53c1a735be4d6bb7ec308fbf1d
BLAKE2b-256 e10d330c5ec539d69f38bf7f7c805463d5a181bbd28c08608e5db79e94b12f9b

See more details on using hashes here.

File details

Details for the file tollbooth_dpyc-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: tollbooth_dpyc-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 29.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for tollbooth_dpyc-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 3094c12eb587d70bdc6105a341003712c69dbc9a8eb11653a81aa30fcb9aa0e0
MD5 36e12e065ef5e02e18e8104ff9e4f58d
BLAKE2b-256 9c4794f5e037696add6fd789288f812dbd71cf68ef059d8e42f68c425696c404

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page