Skip to content

feat: agentic billing MCP tools — billing_status + billing_purchase_credits (MPP) #16

@stackbilt-admin

Description

@stackbilt-admin

Vision

When an agent hits a quota wall during an MCP session, it handles the credit purchase autonomously — no human interruption for routine top-ups. The human gate is exactly one thing: authorizing a payment method on file (one-time). After that, the agent executes within the policy ceiling.

Agent hits quota_exhausted
  → billing_status: quota gone, balance 0, has_saved_card: true, policy: autoSpendLimit=$10
  → purchase is $0.99 (100-credit pack), under limit
  → billing_purchase_credits: charges card via Stripe RAK, balance +100
  → retries image_generate: succeeds
  → human sees: image + email receipt, never interrupted

Architecture

Gateway owns: MCP protocol surface, per-session spend accumulator (KV), escalation logic, RAK-based charge flow.

Edge-auth owns: tenant identity, policy, Stripe customer relationship, balance ledger. NOT charge execution.

Stripe owns: charge execution, card vault, 3DS bypass (Data Only Auth), MPP rails.

The gateway calls Stripe directly (using a tenant-scoped RAK from edge-auth) — it does not proxy the charge through edge-auth RPC. Settlement flows back via Stripe webhook → edge-auth Transactional Outbox → balance credit.

Target wire format: MPP (Machine Payments Protocol)

Charges should target Stripe's Machine Payments Protocol rails for high-velocity M2M support, streaming payment options, and compatibility with the UCP discovery layer. Build billing_purchase_credits against MPP from day one, not a custom internal format.

MCP tools

billing_status

Calls edge-auth.getBillingStatus(tenantId). Returns tier, quota remaining, credit balance, has_saved_card, can_purchase_credits. Free tool (no quota consumed).

// Response
{
  tier: 'pro',
  quotaRemaining: 0,
  quotaResetsAt: '2026-07-01T00:00:00Z',
  creditBalance: 0,
  hasSavedCard: true,
  canPurchaseCredits: true,
  autoSpendLimitUsd: 10.00,
}

billing_purchase_credits

Requires billing:write scope on the bearer token (not granted by default — opt-in per tenant).

Flow:

  1. Check per-session spend accumulator (KV) — reject if adding this purchase would exceed autoSpendLimitUsd
  2. Call edge-auth.getStripeChargeContext(tenantId) — get customer ID + scoped RAK + saved PaymentMethod ID
  3. If no saved card → surface createSetupIntent URL to human, return early
  4. If purchase > requiresConfirmationAboveUsd → escalate to human, return early
  5. Call Stripe API with RAK: POST /v1/payment_intents with off_session: true + MIT exemption
  6. Add purchase amount to session spend accumulator
  7. Return receipt (charge ID, credits purchased, new balance from webhook — or poll)

Session spend accumulator

KV key: billing_session_spend:{sessionId} — tracks USD spent this session. TTL = session TTL (30 min). Checked before every billing_purchase_credits call, incremented after success.

Escalation paths (human gating)

  • No saved card → return { action: 'setup_required', url: setupIntentUrl } — agent surfaces to human once
  • Above requiresConfirmationAboveUsd → return { action: 'confirmation_required', amount, description } — agent asks human
  • Policy disabled → return structured error, direct to account settings

Scope: what is NOT in this issue

  • Charge logic (Stripe API calls) — gateway-level, not edge-auth
  • Credit balance updates — edge-auth Transactional Outbox (edge-auth#156)
  • RAK minting — edge-auth#155
  • 3DS bypass — edge-auth#157
  • Agent Guardrails sync with Stripe Dashboard — future iteration

Dependencies (all edge-auth)

  • edge-auth#154 — getBillingStatus, getStripeChargeContext, getAgentSpendPolicy RPCs
  • edge-auth#155 — agent_spend_policy table + RAK minting
  • edge-auth#156 — Transactional Outbox + v2 thin event webhook handler
  • edge-auth#157 — Data Only Authentication (3DS bypass for off-session charges)
  • edge-auth#134 — tenant routing fix (admin token must resolve to correct tenant first)

Related

  • mcp-gateway#64 — tenant routing bug; must be fixed before billing tools are testable end-to-end
  • Stripe 2026 strategy: MPP wire format, RAKs for agent spending authority, Data Only Auth for frictionless M2M

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions