Developer Docs · v1

One install.
Seven tools.

Paystack ships as a Model Context Protocol server plus a REST API. Everything is typed. Every call carries a ReasoningLog. Every state change is signed.

§ Install

Point your agent at it.

install
# Claude Desktop · Cursor · any MCP client
mcp install codelucent/paystack

# or: self-hosted
docker run -p 7022:7022 \
  -e PAYSTACK_API_KEY=psk_live_... \
  ghcr.io/codelucent/paystack-mcp:latest
§ Tool surface

Seven verbs. That’s it.

The API is small on purpose. Each verb has a clear posture, clear scope, and a documented risk level. Most agents only need two: initiate_escrow_payout and reverse_escrow.

ToolPurposeRisk
initiate_escrow_payoutHold funds against a counter-party. Emits VFP, state=held.medium
release_escrowRelease held funds before the buffer elapses. Rarely used.high · requiresApproval
reverse_escrowPull back a held escrow. Safe, reversible, operator-approved.low
refund_releasedVendor-initiated return after release. Creates a linked entry.low
list_pendingEnumerate held escrows in operator scope. Read-only.read
set_limitAdjust per-agent autonomy ceiling. Operator scope only.high · requiresApproval
verify_vfpPublic endpoint. Returns state, amount, buffer progress for any VFP.public
§ initiate_escrow_payout

The MCP schema.

paystack.mcp.json
{
  "name": "initiate_escrow_payout",
  "description": "Hold funds in the custodial buffer against a counter-party. Returns a VFP.",
  "requiresApproval": false,
  "input": {
    "amount_cents":   "integer",
    "counter_party":  "string",
    "priority":       "'instant' | 'disputable' | 'scheduled'",
    "audit_window":   "duration?",
    "reasoning":      "ReasoningEnvelope"
  },
  "output": {
    "vfp":          "string",
    "state":        "'held'",
    "releases_at":  "iso8601"
  }
}
§ ReasoningLog

The envelope every call carries.

Every agent-triggered payment includes a ReasoningEnvelope. It travels with the ledger entry and through webhooks. Finance, compliance, and engineering all read the same field — no after-the-fact reconstruction.

reasoning.ts
type ReasoningEnvelope = {
  // Why the agent chose to act
  policy:      string           // dotted policy path (e.g. 'maintenance.repair')
  confidence:  number           // [0, 1]
  agent_id:    string           // stable id for the acting agent
  model:       string           // model version that authorized

  // Evidence
  inputs_hash: sha256           // hash of the prompt/context that produced this
  citations:   string[]?        // source ids the agent grounded on
  tool_trace:  string[]?        // upstream tool calls that led here

  // Operator overrides
  approved_by: string?          // operator id if human-in-the-loop fired
  override:    boolean?         // true if policy would have blocked
}
§ Webhooks

Signed events on every state change.

webhook.json
// Webhook payload — POST to your endpoint
{
  "type":        "escrow.released",
  "vfp":         "VFP-7D4C-11A2",
  "amount_cents": 120000,
  "counter_party": "acme-roofing-llc",
  "reasoning": { ... },        // the original envelope
  "ledger_entry": "0192f3a7-...",
  "signature":   "ed25519:..."  // verify against pubkey from trust center
}

Event types

  • escrow.heldFunds successfully captured.
  • escrow.releasedBuffer elapsed · funds cleared.
  • escrow.reversedPulled back inside the window.
  • escrow.refundedVendor returned released funds.
  • safety.pauseSafetySwitch triggered on a tenant.
  • verifier.alertIntegrity check raised an incident.