{
  "markdown": "<!-- mcp-name: io.github.artgas1/robokassa-mcp -->\n\n<p align=\"center\">\n  <img src=\"https://raw.githubusercontent.com/artgas1/robokassa-mcp/main/.github/hero.svg\" alt=\"robokassa-mcp — Robokassa payment gateway exposed to AI agents through MCP\" width=\"820\"/>\n</p>\n\n<h1 align=\"center\">robokassa-mcp</h1>\n\n<p align=\"center\">\n  <a href=\"https://github.com/artgas1/robokassa-mcp/actions/workflows/ci.yml\"><img src=\"https://github.com/artgas1/robokassa-mcp/actions/workflows/ci.yml/badge.svg\" alt=\"CI\"/></a>\n  <a href=\"https://pypi.org/project/robokassa-mcp/\"><img src=\"https://img.shields.io/pypi/v/robokassa-mcp.svg\" alt=\"PyPI\"/></a>\n  <a href=\"https://pypi.org/project/robokassa-mcp/\"><img src=\"https://img.shields.io/pypi/pyversions/robokassa-mcp.svg\" alt=\"Python\"/></a>\n  <a href=\"./LICENSE\"><img src=\"https://img.shields.io/pypi/l/robokassa-mcp.svg\" alt=\"License\"/></a>\n  <a href=\"https://ag-ae4b3bf7.mintlify.app\"><img src=\"https://img.shields.io/badge/docs-mintlify-0068FF.svg\" alt=\"Docs\"/></a>\n</p>\n\n<p align=\"center\">\n  <b>📚 <a href=\"https://ag-ae4b3bf7.mintlify.app\">Documentation</a></b> &nbsp;·&nbsp;\n  <a href=\"https://pypi.org/project/robokassa-mcp/\">PyPI</a> &nbsp;·&nbsp;\n  <a href=\"https://github.com/artgas1/robokassa-mcp/pkgs/container/robokassa-mcp\">Docker</a> &nbsp;·&nbsp;\n  <a href=\"https://registry.modelcontextprotocol.io/v0/servers?search=robokassa\">MCP Registry</a>\n</p>\n\n---\n\nComprehensive Python client and [Model Context Protocol](https://modelcontextprotocol.io) server for [Robokassa](https://robokassa.com) — the Russian payment gateway.\n\nCovers the full API surface: checkout, XML status interfaces, refunds, holding (pre-auth), recurring subscriptions, 54-ФЗ fiscal receipts, Partner API, and auxiliary endpoints.\n\n## Install (once published)\n\n```bash\n# As an MCP server for Claude Desktop / Claude Code / Cursor / Windsurf\nuvx robokassa-mcp\n\n# As a Python library\npip install robokassa-mcp\n```\n\n## Use as a Python library\n\n```python\nimport asyncio\nfrom decimal import Decimal\nfrom robokassa import create_invoice, RobokassaClient\n\n# Build a signed checkout URL (no HTTP — just URL construction).\ninvoice = create_invoice(\n    merchant_login=\"my-shop\",\n    out_sum=Decimal(\"599.00\"),\n    inv_id=12345,\n    password1=\"...\",\n    description=\"Premium subscription\",\n    email=\"user@example.com\",\n)\nprint(invoice.url)  # https://auth.robokassa.ru/Merchant/Index.aspx?...\n\n# Check the state of a payment (hits the OpStateExt XML endpoint).\nasync def check() -> None:\n    async with RobokassaClient(\"my-shop\", password2=\"...\") as client:\n        state = await client.check_payment(inv_id=12345)\n        print(state.is_paid, state.info.op_key)\n\nasyncio.run(check())\n```\n\n### Full refund flow\n\n```python\nfrom robokassa import RobokassaClient\n\nasync def refund_flow(inv_id: int) -> None:\n    async with RobokassaClient(\"my-shop\", password2=\"p2\", password3=\"p3\") as client:\n        # 1. Fetch the payment state to get its OpKey.\n        state = await client.check_payment(inv_id)\n        assert state.info.op_key, \"payment not complete yet\"\n\n        # 2. Initiate a refund.\n        created = await client.refund_create(state.info.op_key)\n        print(\"refund requestId:\", created.request_id)\n\n        # 3. Poll status until finished / canceled.\n        while True:\n            status = await client.refund_status(created.request_id)\n            if status.is_terminal:\n                print(\"final:\", status.state)\n                break\n```\n\n### Webhook signature verification (FastAPI example)\n\n```python\nfrom fastapi import FastAPI, Request, HTTPException, PlainTextResponse\nfrom robokassa import verify_result_signature, build_ok_response\n\napp = FastAPI()\n\n@app.post(\"/robokassa/result\")\nasync def result_url(req: Request) -> PlainTextResponse:\n    form = dict(await req.form())\n    if not verify_result_signature(form, password2=\"...\"):\n        raise HTTPException(status_code=403, detail=\"Bad signature\")\n    # ... persist the notification, mark invoice paid ...\n    return PlainTextResponse(build_ok_response(form[\"InvId\"]))\n```\n\n## Use as an MCP server\n\n### Claude Desktop\n\nEdit `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\\Claude\\claude_desktop_config.json` (Windows):\n\n```json\n{\n  \"mcpServers\": {\n    \"robokassa\": {\n      \"command\": \"uvx\",\n      \"args\": [\"robokassa-mcp\"],\n      \"env\": {\n        \"ROBOKASSA_LOGIN\": \"your-shop-login\",\n        \"ROBOKASSA_PASSWORD1\": \"password1\",\n        \"ROBOKASSA_PASSWORD2\": \"password2\",\n        \"ROBOKASSA_PASSWORD3\": \"password3\"\n      }\n    }\n  }\n}\n```\n\n### Claude Code\n\n```bash\nclaude mcp add robokassa \\\n  -e ROBOKASSA_LOGIN=my-shop \\\n  -e ROBOKASSA_PASSWORD1=... \\\n  -e ROBOKASSA_PASSWORD2=... \\\n  -e ROBOKASSA_PASSWORD3=... \\\n  -- uvx robokassa-mcp\n```\n\n### Cursor\n\nEdit `~/.cursor/mcp.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"robokassa\": {\n      \"command\": \"uvx\",\n      \"args\": [\"robokassa-mcp\"],\n      \"env\": {\n        \"ROBOKASSA_LOGIN\": \"your-shop-login\",\n        \"ROBOKASSA_PASSWORD1\": \"password1\",\n        \"ROBOKASSA_PASSWORD2\": \"password2\",\n        \"ROBOKASSA_PASSWORD3\": \"password3\"\n      }\n    }\n  }\n}\n```\n\n### VS Code (GitHub Copilot)\n\nIn user or workspace `settings.json`:\n\n```json\n{\n  \"github.copilot.chat.mcp.servers\": {\n    \"robokassa\": {\n      \"command\": \"uvx\",\n      \"args\": [\"robokassa-mcp\"],\n      \"env\": {\n        \"ROBOKASSA_LOGIN\": \"your-shop-login\",\n        \"ROBOKASSA_PASSWORD1\": \"password1\",\n        \"ROBOKASSA_PASSWORD2\": \"password2\",\n        \"ROBOKASSA_PASSWORD3\": \"password3\"\n      }\n    }\n  }\n}\n```\n\n### Windsurf\n\nEdit `~/.codeium/windsurf/mcp_config.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"robokassa\": {\n      \"command\": \"uvx\",\n      \"args\": [\"robokassa-mcp\"],\n      \"env\": {\n        \"ROBOKASSA_LOGIN\": \"your-shop-login\",\n        \"ROBOKASSA_PASSWORD1\": \"password1\",\n        \"ROBOKASSA_PASSWORD2\": \"password2\",\n        \"ROBOKASSA_PASSWORD3\": \"password3\"\n      }\n    }\n  }\n}\n```\n\n### HTTP transport (MCP Inspector, remote clients)\n\n```bash\nuvx robokassa-mcp --transport http --port 8000\n```\n\nFlags: `--transport {stdio,http,streamable-http,sse}`, `--host`, `--port`.\n\n## MCP tools exposed to agents\n\nAll 18 tools are wrapped as `@mcp.tool()` and available to any MCP-capable agent (Claude Desktop, Claude Code, Cursor, Windsurf, etc.).\n\n| Tool | Purpose | Auth |\n|---|---|---|\n| `create_invoice` | Build a signed checkout URL (optional 54-ФЗ receipt). | Password#1 |\n| `check_payment` | Get current state of a payment by InvId (via OpStateExt). | Password#2 |\n| `list_currencies` | List payment methods available to the shop. | — |\n| `calc_out_sum` | Compute amount credited to shop for a given payment. | Password#1 |\n| `refund_create` | Initiate a refund (requires Refund API access). | Password#3 JWT |\n| `refund_status` | Poll refund progress by requestId. | — |\n| `verify_result_signature` | Validate a ResultURL webhook. | Password#2 |\n| `verify_success_signature` | Validate a SuccessURL redirect. | Password#1 |\n| `hold_init` / `hold_confirm` / `hold_cancel` | Two-step card pre-authorization. | Password#1 |\n| `init_recurring_parent` / `recurring_charge` | Subscription auto-charges. | Password#1 |\n| `build_split_invoice` | Marketplace multi-recipient checkout. | — |\n| `send_sms` | Paid SMS service. | Password#1 |\n| `second_receipt_create` / `second_receipt_status` | 54-ФЗ final receipt after advance. | Password#1 |\n| `partner_refund` | Alternative refund path for partner integrators. | Partner JWT |\n\nLow-level signature helpers are available from Python only: `compute_signature`, `op_state_signature`, `build_checkout_signature`, `build_refund_jwt`, `build_sms_signature`, `compute_result_signature`, `compute_success_signature`, `encode_fiscal_body`.\n\n## API coverage\n\nMapped against the 8 public Robokassa API groups:\n\n| Group | Coverage | Module |\n|---|---|---|\n| Merchant Checkout | ✅ `create_invoice` (+ 54-ФЗ) | `robokassa.checkout` |\n| XML Interfaces | ✅ `check_payment`, `list_currencies`, `calc_out_sum` | `robokassa.xml_interface` |\n| Refund API | ✅ `refund_create`, `refund_status` | `robokassa.refund` |\n| Holding / Pre-auth | ✅ init / confirm / cancel | `robokassa.holding` |\n| Recurring | ✅ parent + child | `robokassa.recurring` |\n| Fiscal 54-ФЗ | ✅ second receipt create / status | `robokassa.fiscal` |\n| Partner API | 🟡 `partner_refund` only — [see coverage notes](./docs/partner-api.md) | `robokassa.partner` |\n| Auxiliary | ✅ `send_sms`, webhook signatures, split payments | `robokassa.sms`, `robokassa.webhooks`, `robokassa.split` |\n\n## Environment variables\n\nMost high-level entry points fall back to these env vars when credentials aren't passed explicitly:\n\n| Variable | Required for |\n|---|---|\n| `ROBOKASSA_LOGIN` | All operations |\n| `ROBOKASSA_PASSWORD1` | Checkout, webhook SuccessURL verification, CalcOutSumm, fiscal, SMS |\n| `ROBOKASSA_PASSWORD2` | `check_payment` (OpStateExt), webhook ResultURL verification |\n| `ROBOKASSA_PASSWORD3` | `refund_create` |\n\n## Signature algorithms\n\nAll signature-producing helpers accept `algorithm=` with `\"md5\" / \"sha256\" / \"sha384\" / \"sha512\"` — match whatever is configured in your Robokassa cabinet.\n\n## Development\n\n```bash\ngit clone https://github.com/artgas1/robokassa-mcp.git\ncd robokassa-mcp\nuv sync --all-extras --dev\nuv run pytest            # 107+ unit tests\nuv run ruff check .\nuv run pyright\n```\n\n## License\n\nMIT — see [LICENSE](./LICENSE). Drop-and-forget maintenance; PRs welcome but not guaranteed to be reviewed promptly.\n",
  "bytes": 9462,
  "sha": "99df33840f21030c7ceec1cd06e3d8ca615732c13aa4f7b5727b714336f1a6ac",
  "repo_slug": "artgas1/robokassa-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_artgas1_robokassa_mcp_3575c320/readme"
}