# AI assistants (MCP)

> Sell from Claude Code, Cursor or Codex in one prompt: products, prices, payment links and test payments, through a local MCP server with your key.

`perly-pay-mcp` lets your coding assistant set up Perly Pay for you: make a product and its price, share a payment link, pay it in [test mode](https://pay.perly.io/docs/test-mode.md), and read what came in. It runs on your machine and talks only to Perly Pay's API, with your key. Nothing of ours sits in between.

> **Note:** `perly-pay-mcp` goes up on npm shortly; the lines below work from the day it does. Until then, call the [API](https://pay.perly.io/docs/api.md) or use the [SDKs](https://pay.perly.io/docs/sdks.md).

## Set up

1. **Get a test key** — Dashboard → Developers → API keys: `sk_test_…`. Build with it; nothing real moves.
2. **Add the server** — One line in Claude Code, or a few in Cursor's or Codex's config. Node 20 or newer.
3. **Ask** — "Sell a one-hour consultation for $49 with a payment link, then pay it in test mode and show me the payment."

**Claude Code**

```bash
claude mcp add perly-pay --env PERLY_PAY_SECRET_KEY=sk_test_… -- npx -y perly-pay-mcp
```

**Cursor**

```json
// ~/.cursor/mcp.json, or .cursor/mcp.json in a project
{
  "mcpServers": {
    "perly-pay": {
      "command": "npx",
      "args": ["-y", "perly-pay-mcp"],
      "env": { "PERLY_PAY_SECRET_KEY": "sk_test_…" }
    }
  }
}
```

**Codex**

```toml
# ~/.codex/config.toml
[mcp_servers.perly-pay]
command = "npx"
args = ["-y", "perly-pay-mcp"]
env = { PERLY_PAY_SECRET_KEY = "sk_test_…" }
```

> **Warning:** Keep the key out of git: a config file inside a project is often committed.

| Variable | What |
| --- | --- |
| `PERLY_PAY_SECRET_KEY` | `sk_test_…` while you build. `sk_live_…` works too, with the limits below. |
| `PERLY_PAY_API` | Default `https://pay.perly.io`. |
| `PERLY_PAY_WEBHOOK_SECRET` | Optional `whsec_…`, the default for `verify_webhook_signature`. |

## Tools

Generated from the [API](https://pay.perly.io/docs/api.md)'s own description, so every argument is the API's. Amounts are integers in cents: `4900` is $49.00.

| Tools | For |
| --- | --- |
| `create_product`, `list_products`, `update_product`, `create_price`, `list_prices`, `update_price` | products and prices |
| `create_payment_link`, `list_payment_links`, `update_payment_link` | payment links |
| `create_invoice`, `list_invoices`, `retrieve_invoice`, `cancel_invoice`, `create_checkout_session`, `retrieve_checkout_session` | invoices and checkout |
| `create_customer`, `list_customers`, `retrieve_customer` | customers |
| `create_subscription`, `list_subscriptions`, `retrieve_subscription` | subscriptions |
| `check_entitlement`, `list_entitlements`, `consume_entitlement_credits`, `list_credit_usage` | access and credits |
| `list_payments`, `retrieve_payment`, `list_receipts`, `retrieve_receipt`, `list_events` | payments, receipts, events |
| `create_refund`, `list_refunds` | refunds |
| `create_webhook_endpoint`, `list_webhook_endpoints`, `delete_webhook_endpoint` | webhooks |
| `simulate_payment` | test mode |
| `verify_webhook_signature`, `pay_links` | on your machine |

`simulate_payment` pays an invoice, or buys from a payment link and pays that, so fulfilment, receipts and [webhooks](https://pay.perly.io/docs/webhooks.md) fire as for a real buyer. `pay_links` gives the dashboard pages for what only you can do.

## What it will not do

- **With a live key**, nothing that moves or redirects money, spends a buyer's credits or deletes: no simulated payments, refunds, credit spending, or new or deleted webhook endpoints. The tool says why and where you do it. Reading, and making products, prices, links and invoices, work as in test.
- **Wallets, API keys, your plan, going live and two-factor sign-in** have no tool. You do them in the dashboard; `pay_links` gives the pages.
- **What cannot be undone** — cancelling an invoice, opening a refund, deleting a webhook endpoint — waits for `confirm: true`, which the assistant sends only after asking you.
- **Your secret key is never repeated** in an answer or a log.

## Go live

1. **Connect a wallet** — Its public key or address, in the dashboard. We never ask for a seed or a private key. See [Wallets](https://pay.perly.io/docs/wallets.md).
2. **Turn on live mode** — In the dashboard, once the wallet is connected.
3. **Swap the key** — Put `sk_live_…` where `sk_test_…` was, in your app's server. Your assistant can keep the test key.
