Corridor

architecture

A metering engine built like a ledger

Corridor's engine is deliberately boring where it counts: double-entry accounting, serializable isolation, idempotency everywhere — and deliberately fast where it counts: policy and pricing decisions inside a hard authorize budget.

your product

API · MCP server · data feed — instrumented with the SDK or called directly

corridor engine

meter → price → policy → ledger · Go, Postgres, hot-path latency budget

rail adapters

one canonical event model; rail-specific data stays in adapter metadata

stripe connect · stripe mpp

full-stack money path · metering on the Stripe account you keep

A ledger you can audit, not a counter

Money state lives in a double-entry ledger written under serializable isolation, with an append-only, hash-chained audit log and idempotent writes. Every ledger invariant ships as both a runtime assertion and a property test.

Authorize before the work happens

Usage follows an authorize-then-capture lifecycle: policy and pricing run before your tool executes, at a hard latency budget (under 10ms added at authorize, p99) — guardrails at machine speed, not on the invoice.

Per-agent identity, first-class

Every metered event attributes to an agent identity — not an account, not an API key. Attribution, spend, and limits are per-agent from the schema up.

Rails are backends, not the product

The event model is rail-agnostic; adapters for Stripe Connect (full-stack) and Stripe's Machine Payments Protocol (metering-only) plug in behind the same interface. Rail-specific data never leaks into canonical types.

One wrap() away for MCP servers

The TypeScript SDK, @corridor/mcp, follows the official MCP SDK's conventions: a low-level client (authorize / capture / void) plus a one-line server wrapper.

import { CorridorClient, wrap } from "@corridor/mcp";

const corridor = new CorridorClient({ apiKey: process.env.CORRIDOR_API_KEY });

// One call instruments an MCP server: every tool invocation is
// authorized, metered, and priced per-agent before it runs.
wrap(server, corridor, {
  currency: "USD",
  pricing: {
    tools: { search_corpus: { type: "flat", amount_cents: 100 } },
    default: "deny",
  },
  agentIdentityResolver: resolveAgent,
});

Stack, plainly: a Go engine on Postgres; a typed TypeScript SDK; a Next.js provider dashboard; structured logs, metrics, and traces on every engine decision. Specs first — every subsystem is written down before it is built, and the invariants in those specs run as tests.