MCP Security
The MCP server sits in front of the same REST API a merchant integration would use, and every request runs under the merchant’s own API key. It doesn’t hold or generate any credentials of its own.Authentication
Every request to the MCP endpoint must include the merchant’s API key:401 before any tool logic runs:
/v1 for direct REST callers. There is no separate account or session for MCP.
Rotate a key with POST /auth/rotate-api-key. Rotation invalidates the old key immediately for both REST and MCP callers.
Rate limiting
Each API key gets a token bucket sized to 120 requests / minute by default (configurable server-side viaMCP_RATE_LIMIT_PER_MINUTE). Exceeding the budget returns 429:
dry_run for destructive tools
retry_payment and cancel_subscription accept dry_run: true. When set:
- The tool does not mutate anything.
- Instead it fetches the target invoice or subscription and returns its current state, wrapped in an envelope that makes the intent explicit:
Structured error envelope
Tool errors come back as JSON with three fields so clients can decide how to react:invalid_input— the tool arguments were rejected before hitting the engine (bad date format, empty ID, unknown metric name, unknown enum value). Never retry without changing the input.engine_error— the engine returned an error at HTTP time.retryable: trueon transient failures. Clients can retry with a backoff.
What the server does not do
- No caching of merchant data. Every tool call is a live REST call.
- No cross-tenant fan-out. One MCP session is scoped to exactly one API key.
- No stored PII. The MCP server keeps only the session id needed for the JSON-RPC protocol.
Operational safeguards
- Health endpoint at
GET /healthbypasses auth so load balancers can probe without carrying secrets. - Structured logging on every failure path — Nomba error bodies, business-level failures (
status: falseon HTTP 200), and rate-limit hits. - Read-only tools all declare
readOnlyHint: truein their MCP annotations, so clients that gate confirmation UX on destructive vs. read-only can respect that.
