DePix App Gateway

Non-custodial Pix payment gateway on the Liquid Network. An AI agent creates checkouts/products, reads transaction status, and manages support tickets — 22 tools. Non-custodial: no funds, no keys held.

Documentation

depix-mcp

smithery badge

MCP (Model Context Protocol) server for DePix App — the agent-facing interface of the non-custodial Pix↔DePix payment gateway.

Connect an AI agent (Claude Code, Claude Desktop, Cursor, or any MCP client) and it can receive Pix payments (checkouts and products) and read transaction status — end to end, in sandbox (sk_test_) and production (sk_live_).

  • Remote (Streamable HTTP): https://mcp.depixapp.com/mcp
  • Local (stdio): npx -y @depixapp/mcp with DEPIX_API_KEY in the environment

What it is (and isn't)

  • A pure client of the public DePix API (https://api.depixapp.com/api/*). It holds zero critical credentials — no Eulen token, no database, no webhook HMAC, no Liquid key.
  • Never custodial. It never signs a transaction, never holds funds, never stores your key. Your sk_ key is passed verbatim to the API on each call and lives only in memory for that request.
  • Same door as everyone. The MCP goes through the same auth, scopes and rate limits as any external agent — no privileged path.

It does not create deposits or withdrawals (that moves funds and belongs to the Wallet SDK — see Related). The pay-side tools here are read-only status reads.

Related — moving funds: the Wallet SDK

This gateway receives payments and reads status. To hold, sign, and move funds — an agent running its own non-custodial Liquid wallet that pays and receives over Pix/DePix, converts DePix/L-BTC/USDt, buys gift cards, and self-onboards — use the companion @depixapp/sdk (source). The seed never leaves the agent and the backend never signs.

Quickstart 1 — Connect Claude Code (remote, HTTP)

Pass your DePix API key as a Bearer header. Always start with a sandbox key.

claude mcp add --transport http depix https://mcp.depixapp.com/mcp \
  --header "Authorization: Bearer sk_test_YOUR_KEY"

Then test the connection by asking Claude to run get_account. It should return your merchant with is_live: false (sandbox).

Cursor — add to ~/.cursor/mcp.json (or a project .cursor/mcp.json):

{
  "mcpServers": {
    "depix": {
      "url": "https://mcp.depixapp.com/mcp",
      "headers": { "Authorization": "Bearer sk_test_YOUR_KEY" }
    }
  }
}

Or use the one-click deeplink. The key placeholder lives INSIDE the base64 config= value, so re-encode it with your real key first:

node -e 'const cfg={url:"https://mcp.depixapp.com/mcp",headers:{Authorization:"Bearer sk_test_YOUR_KEY"}};console.log(Buffer.from(JSON.stringify(cfg)).toString("base64"))'
cursor://anysphere.cursor-deeplink/mcp/install?name=depix&config=<base64 from the command above>

The claude.ai web UI custom-connector only supports OAuth (no custom header). This server is an OAuth 2.1 Resource Server (WorkOS AuthKit): the web connector signs you in, and the session forwards your verified login to the API as the bearer. To operate you must first link that login to your DePix account (dashboard → connector settings); until then the tools return a typed "not linked yet" message. OAuth sessions are read + merchant only and can never move money (wallet_write) — use an sk_ key for withdrawals. The whole OAuth surface is feature-flagged (AUTHKIT_DOMAIN): with it unset, only the sk_ header/stdio paths above are active. Terminal clients keep using sk_ keys.

Quickstart 2 — Local stdio (Claude Desktop)

The same server runs as a local process over stdio. The key comes from DEPIX_API_KEY (env), never a flag. The only official npm package is @depixapp/mcp — the @depixapp scope is organization-owned; do not install any similarly-named unscoped package. Add to your Claude Desktop config (claude_desktop_config.json):

{
  "mcpServers": {
    "depix": {
      "command": "npx",
      "args": ["-y", "@depixapp/mcp"],
      "env": { "DEPIX_API_KEY": "sk_test_YOUR_KEY" }
    }
  }
}

Run it directly to sanity-check:

DEPIX_API_KEY=sk_test_YOUR_KEY npx -y @depixapp/mcp

Quickstart 3 — Sandbox testing (the full loop)

Always test with an sk_test_ key before sk_live_. Sandbox QRs are non-payable placeholders (SANDBOX-…-DO-NOT-PAY).

  1. create_checkoutamount and payer_tax_number are both required (the CPF/CNPJ is required even in sandbox). Use a test CPF like 52998224725:

    { "amount": 1500, "payer_tax_number": "52998224725" }
    

    Returns a chk_… id, a payment_url, a sandbox pix.qr_code, and is_live: false.

  2. simulate_checkout_payment{ "checkout_id": "chk_…" } marks the sandbox checkout paid (sandbox-only; live checkouts return sandbox_only).

  3. wait_for_checkout{ "checkout_id": "chk_…" }. The server polls internally and streams progress; you make one call and it returns { "status": "completed", "terminal": true } — no client-side polling loop.

You can also read a synthetic deposit: get_deposit_status with a sandbox_… id returns depix_sent.

Tools (22)

ToolAPIScope
create_checkoutPOST /api/checkoutsmerchant_write
get_checkoutGET /api/checkouts/:idmerchant_read
list_checkoutsGET /api/checkoutsmerchant_read
simulate_checkout_paymentPOST /api/checkouts/:id/simulate-paymentmerchant_write (sandbox-only)
wait_for_checkoutGET /api/checkouts/:id (server-side loop)merchant_read
create_productPOST /api/productsmerchant_write
list_productsGET /api/productsmerchant_read
get_productGET /api/products/:idmerchant_read
update_productPATCH /api/products/:idmerchant_write
activate_productPOST /api/products/:id/activatemerchant_write
deactivate_productPOST /api/products/:id/deactivatemerchant_write
set_featured_productsPOST /api/products/featuredmerchant_write
list_product_checkoutsGET /api/products/:id/checkoutsmerchant_read
get_accountGET /api/memerchant_read
get_deposit_statusGET /api/deposits/:idwallet_read (read-only)
get_withdrawal_statusGET /api/withdrawals/:idwallet_read (read-only)
open_support_ticketPOST /api/ticketsany key (scope-less)
get_support_ticketGET /api/tickets/:idany key (scope-less)
list_support_ticketsGET /api/ticketsany key (scope-less)
reply_support_ticketPOST /api/tickets/:id/messagesany key (scope-less)
attach_support_ticket_filePOST /api/tickets/:id/attachmentsany key (scope-less)
close_support_ticketPOST /api/tickets/:id/closeany key (scope-less)

The last six are the support channel: open a ticket, poll for the human reply, reply back, attach a screenshot or diagnostic/log file (base64, ~3 MB), or close it (up to 5 open per account). Replies are not pushed — poll get_support_ticket. Amounts are BRL cents. A tool call whose key lacks the required scope returns an insufficient_scope tool error naming the missing scope — that is the only way to discover a missing scope (the API never lists a key's scopes).

Configuration (public, no secrets)

EnvMeaningDefault
DEPIX_API_BASEAPI base URL (allowlisted origins only)https://api.depixapp.com
MCP_MAX_WAIT_SECONDSMax wait_for_checkout budget; prod sets ~780 (Vercel Pro)290 (Hobby-safe)
MCP_SERVER_VERSIONVersion reported in the handshake1.1.0
MCP_ALLOWED_HOSTSComma-separated Host allowlist (DNS-rebinding protection); set on previews to add the *.vercel.app hostmcp.depixapp.com
DEPIX_API_KEYstdio mode only — your sk_ key

There is deliberately no env for an API key, Eulen token, HMAC or DB credential in the remote server. In HTTP mode the key arrives per-request in the Authorization header.

Endpoints

  • POST /mcp — the MCP Streamable HTTP endpoint (DELETE ends a session; GET returns 405 — this stateless server offers no standalone SSE stream).
  • GET /.well-known/mcp.json — minimal discovery document.
  • GET /api/health (also /) — service status.

Development

npm install
npm test          # vitest
npm run typecheck # tsc --noEmit
npm run lint      # eslint
npm run build     # compile src → dist (the stdio bin)

Set DEPIX_TEST_KEY=sk_test_… to run the real-sandbox e2e test (test/e2e/sandbox.test.ts), otherwise it is skipped.

CI (.github/workflows/ci.yml) runs typecheck + lint + test + build on every push to main and every PR — that is the correctness gate.

Releasing

Publishing is automated via GitHub Actions using npm Trusted Publishing (OIDC) — no npm token, no 2FA prompt, and every release carries build provenance. .github/workflows/publish-mcp.yml (on a v* tag) publishes the npm package and then the MCP Registry entry (registry/server.json).

To cut a release:

  1. Bump the version in package.json AND registry/server.json (both the top-level version and packages[].version) — they must match, and the CI guard fails the release if the tag, package.json, and the registry npm entry disagree.
  2. Commit to main.
  3. Tag and push:
    git tag v1.2.0 && git push origin v1.2.0
    

The workflow verifies the versions, publishes to npm with provenance, then publishes the registry entry (idempotent — re-running a tag is a safe no-op). Re-tagging an already-published version skips both publishes.

One-time setup (already done): the package is registered as an npm Trusted Publisher for this repo with workflow filename publish-mcp.yml (npmjs.com → package → Settings → Trusted Publisher). No secrets are stored in the repo.

Release smoke test

After a preview/production deploy:

  1. claude mcp add --transport http depix <url>/mcp --header "Authorization: Bearer sk_test_…"
  2. Ask Claude to run get_account → returns the merchant, is_live: false.
  3. create_checkout (sandbox) → simulate_checkout_paymentwait_for_checkoutcompleted.

Pushing to main deploys to production (mcp.depixapp.com). Validate on a Vercel preview deploy before merging. Preview hosts are not on the default DNS-rebinding allowlist — set MCP_ALLOWED_HOSTS in the preview environment (e.g. mcp.depixapp.com,depix-mcp-<hash>.vercel.app) to smoke-test there.