PayPal

PayPal's own MCP server gives an agent refunds, invoices, orders and disputes, with no limit or approval of its own. Shotoku sits in front of it.

agent → paypal__create_refund $89 ✓ APPROVED refunded by PayPal agent → paypal__create_refund $480 ◷ PENDING over the $100 limit, sent to your phone you → tap Approve or Deny agent → retries the exact same call ✓ refunded, or ✗ blocked

Shotoku never moves the money. It decides whether each call may run, and records the answer in the local ledger.


Setup

Wrap @paypal/mcpas an upstream of the Shotoku MCP server and name the PayPal pricer. Use your PayPal app's client ID and secret: Shotoku mints an access token each time it starts and gives the PayPal server only the token.

json
{
  "mcpServers": {
    "paypal": {
      "command": "npx",
      "args": ["-y", "@paypal/mcp", "--tools=all"],
      "env": {
        "PAYPAL_CLIENT_ID": "...",
        "PAYPAL_CLIENT_SECRET": "...",
        "PAYPAL_ENVIRONMENT": "SANDBOX"
      },
      "pricing": "paypal"
    }
  }
}

Point SHOTOKU_MCP_UPSTREAMS at that file. Each PayPal tool then appears to the agent as paypal__<tool>. See MCP: putting a price on wrapped tools.


A policy for a support agent

yaml
rules:
  - resource: paypal__list_*
    verdict: approved
  - resource: paypal__get_*
    verdict: approved
  - resource: paypal__create_refund
    verdict: approved
    maxAmount: 100
    maxDailyAmount: 1000
    overLimit: pending_approval

budgets:
  - actor: support-agent
    maxDailyAmount: 1000

defaultVerdict: pending_approval

Reads are free. Refunds up to $100 go through; a bigger one waits for a human. Anything else PayPal offers is held for review.


How calls are priced

ToolPriced at
create_refund with amountThat amount.
create_refund without amountThe full capture, looked up from PayPal: that is what PayPal refunds.
accept_dispute_claimThe disputed amount, looked up from PayPal.
Every other tool$0. None of them sends money out.

A call that cannot be priced gets no amount, never zero, so a limited rule holds it for a human.


Run the demo

The repository ships a demo that runs against the PayPal sandbox in a few minutes: two orders paid with PayPal's test card, a customer email, and either a scripted agent or a real one.

bash
node examples/paypal/setup.mjs
node examples/paypal/agent.mjs

See examples/paypal for the full walkthrough.