Qut Pay (Kaspi QR payments)

Kaspi QR payments (Kazakhstan) via Qut Pay: create invoices, check status, refund, sandbox tests.

Should I use this

Quality & Safety

A
Description quality
98%
Schema completeness
77%
Naming quality
80%
Poisoning risk
100%
Permission match
100%
Protocol compliance
100%

Based on automated analysis of tool definitions and protocol compliance.

Context Cost

~1,447Tokens (tool definitions)
~1.0 KBTypical response size
Moderate attention impact (1.13% of 128k context)

This is the approximate number of tokens consumed each time the server's tools are loaded into a model's context. Higher counts reduce the attention available for other tasks.

Install

One-Click Install

Add this to your `claude_desktop_config.json` file:

{
  "mcpServers": {
    "mcp": {
      "command": "npx",
      "args": [
        "@qutpay/mcp"
      ]
    }
  }
}

Runnable packages

npm@qutpay/mcp0.1.2stdio

Remote endpoints

https://api.qut.kz/mcpstreamable-http

What it can do

Tool inventory

Tools (9)

🟢 Read-only🟡 Write🔴 Delete⚪ Unknown
🟢qutpay_account

Returns the organization behind the API key: mode (sandbox or live), tariff and limits, connected Kaspi cashiers, provider status. Call this first.

Input Schema

{
  "type": "object",
  "properties": {},
  "$schema": "http://json-schema.org/draft-07/schema#"
}
🟡qutpay_create_invoice(amount, description, externalOrderId, idempotencyKey, kind, ...)

Creates an invoice (QR by default, or pushed to the customer's Kaspi.kz app with kind="phone"). Returns payUrl (hosted pay page), qrImageUrl, deepLink, expiresAt (~3 min). Always pass idempotencyKey (e.g. "order-1001") so a retry never creates a second invoice. Amount in KZT, ≤ 2 decimals; whole tenge for kind="phone".

Input Schema

{
  "type": "object",
  "properties": {
    "amount": {
      "type": "number",
      "exclusiveMinimum": 0,
      "description": "Amount in KZT, e.g. 2500 or 1500.5"
    },
    "description": {
      "type": "string",
      "maxLength": 255,
      "description": "Shown to the customer, e.g. \"Order #1001\""
    },
    "externalOrderId": {
      "type": "string",
      "maxLength": 120,
      "description": "Your order id; later GET /invoices?externalOrderId finds it"
    },
    "idempotencyKey": {
      "type": "string",
      "minLength": 1,
      "maxLength": 120,
      "description": "Unique per order; same key → same invoice"
    },
    "kind": {
      "type": "string",
      "enum": [
        "qr",
        "phone"
      ],
      "description": "\"qr\" (default) or \"phone\" (invoice pushed into the customer's Kaspi.kz app; needs customer.phone)"
    },
    "customer": {
      "type": "object",
      "properties": {
        "name": {
          "type": "string"
        },
        "phone": {
          "type": "string",
          "pattern": "^7\\d{10}$",
          "description": "7XXXXXXXXXX"
        },
        "email": {
          "type": "string",
          "format": "email"
        }
      },
      "additionalProperties": false
    },
    "successUrl": {
      "type": "string",
      "format": "uri"
    },
    "failUrl": {
      "type": "string",
      "format": "uri"
    },
    "metadata": {
      "type": "object",
      "additionalProperties": {},
      "description": "Returned unchanged in webhooks"
    }
  },
  "required": [
    "amount"
  ],
  "additionalProperties": false,
  "$schema": "http://json-schema.org/draft-07/schema#"
}
🟢qutpay_get_invoice(id, live)

Reads one invoice by id (inv_…). live=true asks Kaspi right now instead of the cached status. Status flow: new → pending → paid | failed | expired | cancelled; paid → partially_refunded → refunded.

Input Schema

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "minLength": 1
    },
    "live": {
      "type": "boolean"
    }
  },
  "required": [
    "id"
  ],
  "additionalProperties": false,
  "$schema": "http://json-schema.org/draft-07/schema#"
}
🟢qutpay_list_invoices(status, externalOrderId, from, to, limit, ...)

Lists invoices of the organization, newest first. Filter by status, externalOrderId, date range (ISO), limit ≤ 50, offset for paging.

Input Schema

{
  "type": "object",
  "properties": {
    "status": {
      "type": "string",
      "enum": [
        "new",
        "pending",
        "paid",
        "failed",
        "expired",
        "cancelled",
        "partially_refunded",
        "refunded"
      ]
    },
    "externalOrderId": {
      "type": "string"
    },
    "from": {
      "type": "string",
      "description": "ISO date/time, inclusive"
    },
    "to": {
      "type": "string",
      "description": "ISO date/time, exclusive"
    },
    "limit": {
      "type": "integer",
      "minimum": 1,
      "maximum": 50
    },
    "offset": {
      "type": "integer",
      "minimum": 0
    }
  },
  "additionalProperties": false,
  "$schema": "http://json-schema.org/draft-07/schema#"
}
🔴qutpay_cancel_invoice(id)

Closes a pending invoice. A QR may still be paid until expiresAt — then invoice.paid arrives anyway; handle it.

Input Schema

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "minLength": 1
    }
  },
  "required": [
    "id"
  ],
  "additionalProperties": false,
  "$schema": "http://json-schema.org/draft-07/schema#"
}
🔴qutpay_refund_invoice(id, amount, reason, confirm)

Full refund (omit amount) or partial refund of a paid invoice. Needs the refunds:write scope. With a LIVE key real money is returned to the customer, so confirm=true is required and the merchant must have asked for this refund explicitly.

Input Schema

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "minLength": 1
    },
    "amount": {
      "type": "number",
      "exclusiveMinimum": 0,
      "description": "Omit for a full refund"
    },
    "reason": {
      "type": "string",
      "maxLength": 255
    },
    "confirm": {
      "type": "boolean",
      "description": "Required (true) with a live key"
    }
  },
  "required": [
    "id"
  ],
  "additionalProperties": false,
  "$schema": "http://json-schema.org/draft-07/schema#"
}
⚪qutpay_simulate_payment(id, status)

Completes a sandbox invoice as paid / failed / expired without Kaspi, so the whole flow including the merchant's webhook can be tested. Refuses to run with a live key.

Input Schema

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "minLength": 1
    },
    "status": {
      "type": "string",
      "enum": [
        "paid",
        "failed",
        "expired"
      ],
      "description": "Default \"paid\""
    }
  },
  "required": [
    "id"
  ],
  "additionalProperties": false,
  "$schema": "http://json-schema.org/draft-07/schema#"
}
🟢qutpay_list_subscriptions(status, limit)

Read-only list of recurring invoice schedules. Needs the subscriptions:manage scope on the key.

Input Schema

{
  "type": "object",
  "properties": {
    "status": {
      "type": "string",
      "enum": [
        "active",
        "paused",
        "cancelled"
      ]
    },
    "limit": {
      "type": "integer",
      "minimum": 1,
      "maximum": 50
    }
  },
  "additionalProperties": false,
  "$schema": "http://json-schema.org/draft-07/schema#"
}
🟢qutpay_get_subscription(id)

Reads a recurring invoice schedule by id (sub_…). Needs the subscriptions:manage scope.

Input Schema

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "minLength": 1
    }
  },
  "required": [
    "id"
  ],
  "additionalProperties": false,
  "$schema": "http://json-schema.org/draft-07/schema#"
}

Community

Rate this Server

Evidence

Recent observations

verifiedversion not recorded9 tools