qrblox-mcp · v0.1

Qrblox MCP

qrblox-mcp is the JSON-RPC MCP server that gives AI agents safe, merchant-scoped tools. Sign in to Qrblox Create, mint a sk-qrblox- key, paste it into Claude Desktop or Cursor, and the agent can draft QR codes, audio codes, menus, and scan challenges — and read scan analytics — for one merchant workspace, nothing more.

What it is

The Qrblox MCP server (qrblox-mcp) connects AI agents to merchant-owned Qrblox data over the Model Context Protocol. A merchant mints an API key in Qrblox Create, pastes it into Claude Desktop, Cursor, or a custom agent, and the assistant can draft QR codes, audio codes, menus, and loyalty challenges — and summarize scan activity — all scoped to that one merchant workspace.

Draft-first by design. Creation tools produce drafts. High-risk publishing, billing, and destructive changes stay in the merchant's hands inside Qrblox Create — the agent proposes, the merchant approves.

Quick start (no signup)

The fastest path: agents can generate a real, scannable QR code with no key and no OAuth. Sandbox codes work immediately, are IP rate-limited, and expire in 7 days unless claimed into a real account.

POST a URL, get a QR backbash
curl -X POST https://app.qrblox.com/api/generate-qr-code \
  -H "content-type: application/json" \
  -d '{"url":"https://example.com"}'
responsejson
{
  "ok": true,
  "code": {
    "id":             "…",
    "destinationUrl": "https://example.com",
    "qrImage":        "data:image/png;base64,…",
    "claimToken":     "…",
    "expiresAt":      "2026-06-02T…Z"
  },
  "upgrade": { "signup": "https://app.qrblox.com", /* … */ }
}

Agents can discover the endpoint without writing code first — GET https://app.qrblox.com/api/generate-qr-code returns a JSON manifest describing every field, the bulk endpoint, the limits, and the path to a real key. The MCP itself is reachable at the same host: GET https://app.qrblox.com/api/mcp returns the full tool list, and the JSON-RPC tools/list method works with no auth.

Sandbox limits
3 codes per IP per day on POST /api/generate-qr-code. Above that — or for bulk and any production use — mint a free API key.
Sandbox storage
Codes live in a separate sandboxCodes collection and auto-expire after 7 days.
Upgrade path
Every response carries a claimToken and links to app.qrblox.com to claim and keep them.

Get an API key

MCP keys are merchant-scoped and created in Qrblox Create:

1. Sign in
Go to create.qrblox.com and sign in with Google.
2. Open API keys
Navigate to Settings → API keys.
3. Create a key
Click New API key. Qrblox mints a key shaped like sk-qrblox-<64 hex chars> for your merchant workspace.
4. Copy it once
The plaintext key is shown a single time. Copy it into your agent now — Firestore stores only a SHA-256 hash and a short prefix, and can never show it again.
5. Revoke anytime
Revoking a key rejects it on the very next request.

Keys carry merchant-scoped permissions:

merchant:read
Read the merchant workspace and its QR codes, menus, and scan summaries.
qr:write
Create draft QR codes.
menu:write
Create menus and add menu items.
audio:write
Create draft audio codes.
challenge:write
Create draft scan challenges and loyalty campaigns.

Authentication

Send the key as a Bearer token. Keys begin with sk-qrblox- and are validated against Firestore on every request; the matching record carries the merchant id and scopes that the tool layer enforces.

authorization headerhttp
Authorization: Bearer sk-qrblox-4c2fa8e1b7d9…

The server also accepts a Firebase ID token or a session cookie for in-app callers on Qrblox Create. External agents use the sk-qrblox- API key — that is what this page covers.

Endpoint and transport

One endpoint: POST https://app.qrblox.com/api/mcp. Standard MCP JSON-RPC 2.0 envelopes in the body, a single JSON-RPC response in the reply. A GET on the same URL returns server metadata (name, endpoint, docs link). Each POST is stateless — no session handshake between requests.

calling a toolhttp
POST /api/mcp HTTP/1.1
Host: app.qrblox.com
Authorization: Bearer sk-qrblox-…
Content-Type: application/json

{"jsonrpc":"2.0","id":1,"method":"tools/call",
 "params":{"name":"qrblox.qr.list",
  "arguments":{"limit":10}}}

Supported JSON-RPC methods:

  • initialize — handshake. Returns protocolVersion 2025-03-26 and server info (qrblox-mcp). No auth required.
  • notifications/initialized — accepted as a notification; replies 204 No Content.
  • ping — protocol-level liveness probe; returns an empty result. No auth (distinct from the qrblox.ping tool).
  • tools/list — discover the tool registry. Requires auth.
  • tools/call — invoke a tool by name with { name, arguments }. Requires auth.

Tools

qrblox.ping
Confirm the server is reachable for the authenticated merchant. No arguments. Returns ok, merchantId, and authMethod.
qrblox.merchant.get_profile
Get the merchant workspace attached to this user or API key. No arguments.
qrblox.qr.list
List recent QR codes for the merchant. Optional limit (1–100).
qrblox.qr.create
Create a draft QR code for a URL, menu, offer, or campaign landing page. Required: title, destinationUrl. Optional: campaign, tags (string array).
qrblox.audio.create
Create a draft audio code payload that can later be published as a near-ultrasonic sharing experience. Required: title, payloadText. Optional: campaign.
qrblox.menu.create
Create a merchant menu that can be connected to QR codes, audio codes, and scan experiences. Required: name. Optional: description, locationId.
qrblox.menu.list
List recent menus for the merchant. Optional limit (1–100).
qrblox.menu.add_item
Add an item to a section in an existing menu. Required: menuId, sectionName, name. Optional: description, price (number).
qrblox.challenge.create
Create a draft scan challenge, streak, game, or loyalty campaign. Required: name, challengeType (streak, scan_count, visit_window, or game). Optional: description, rewardText, startsAt, endsAt (ISO dates).
qrblox.analytics.scan_summary
Summarize recent scan activity for the merchant workspace. Optional days (1–365).

Every tool re-derives the merchant from the verified caller, so an agent can only ever read and write within its own merchant workspace.

Example call

tools/call → qrblox.qr.createjson
{
  "jsonrpc": "2.0",
  "id": "create-menu-qr",
  "method": "tools/call",
  "params": {
    "name": "qrblox.qr.create",
    "arguments": {
      "title": "Table 12 lunch menu",
      "destinationUrl": "https://qrblox.com/m/table-12",
      "campaign": "Lunch menu rollout",
      "tags": ["menu", "table-12"]
    }
  }
}

Bulk generation (requires an API key)

Bulk generation is for real marketing — it writes permanent codes into your merchant workspace with evergreen Firebase Storage PNG URLs, no sandbox, no expiry. So it requires a sk-qrblox- key. Mint one for free at create.qrblox.com/settings/api-keys.

Why the gate? Keyless sandbox makes it trivial to try the flow, but bulk is the one path that an abuser would target. Requiring a key here keeps the public sandbox cheap to run and makes the lead-gen funnel work — agents prove the flow on the free single endpoint, then mint a key to scale.

One bulk call

POST https://app.qrblox.com/api/bulk-qr-codesbash
curl -X POST https://app.qrblox.com/api/bulk-qr-codes \
  -H "authorization: Bearer sk-qrblox-…" \
  -H "content-type: application/json" \
  -d '{"urls":[
       "https://qrblox.com/menu/spring",
       "https://qrblox.com/menu/summer",
       "https://qrblox.com/menu/fall"
     ]}'

Up to 50 URLs per call. Response shape: { ok, count, codes: [{ codeId, title, destinationUrl, qrImageUrl }] }. Each qrImageUrl is a Firebase Storage download URL — stable, sharable, no expiry.

Or one tool call per row, through the MCP

Same shape as bulk, item by item — useful when you want per-row error handling, per-row delay, or richer per-row arguments (campaign labels, tags).

node — generate one code per campaign rowjs
const rows = [
  { "title": "Email — June", "destinationUrl": "https://qrblox.com/june", "campaign": "june" },
  { "title": "Print — June", "destinationUrl": "https://qrblox.com/june", "campaign": "june" },
];

for (const args of rows) {
  await fetch("https://app.qrblox.com/api/mcp", {
    method: "POST",
    headers: { "authorization": "Bearer sk-qrblox-…", "content-type": "application/json" },
    body: JSON.stringify({
      jsonrpc: "2.0", id: args.title, method: "tools/call",
      params: { name: "qrblox.qr.create", arguments: args },
    }),
  });
}

Want all codes labelled by campaign for reporting? Pass a consistent campaign argument — the scan summary rolls up by campaign.

Tracking & analytics

Qrblox supports two flavors of code, and your tracking story depends on which one you create:

Static (default)
The QR encodes the destination URL directly. Works with any scanner forever, no redirect. Scans from inside the Qrblox apps are still counted to your account and show up in your daily reports — scans from other apps are not.
Dynamic / tracked
The QR encodes link.qrblox.com/qr/<uniqueQRCodeID>. Every scanner sends users through Qrblox before forwarding to your URL, so every scan is counted and the destination is re-pointable without reprinting.

For account-owned codes, agents can read scan counts via:

tools/call → qrblox.analytics.scan_summaryjson
{ "jsonrpc":"2.0", "id":1, "method":"tools/call",
  "params":{ "name":"qrblox.analytics.scan_summary",
              "arguments":{ "days": 30 } } }

Returns totalScans and a byDay series. The deeper raw export is the daily DataPro report (see Reports on the docs home) — per-code, with city, lat/lng, and day-of-week.

Marketing playbook

Concrete patterns agents can run on a merchant's behalf, end-to-end through the MCP:

Per-channel codes
Generate one code per channel (email, print, social, billboard) all pointing at the same landing page. Label each with a different campaign so you can compare which channels actually drive scans.
Re-target without reprinting
A printed code lives for years. Use a dynamic code and re-point the destination as your offer changes — same print run, new landing page, no waste.
A/B testing
Generate two codes for two destination variants, distribute them evenly, then call qrblox.analytics.scan_summary on each to see which converts.
Bulk store rollouts
One bulk-qr-codes (or scripted qrblox.qr.create) call gives you N store-specific codes in seconds — each labelled by location and rolling up in the daily city-rank report.
Geographic insight
The daily city-rank report tells you where your audience is scanning, by city, every day. Re-point or re-spend from there.
From sandbox to production. Start an agent on the keyless sandbox to prove the flow works, then upgrade to a Qrblox account, mint a key, and rerun the same script against tools/call with qrblox.qr.create — the calls and the code shape are the same. Sandbox codes can be claimed into the account using the claimToken.

Errors

Tool results come back as JSON-RPC result objects; failures come back as JSON-RPC error objects. Auth failures carry a data.code of NO_AUTH, INVALID_API_KEY, INVALID_TOKEN, or REVOKED.

400 · -32600
Body is not a valid JSON-RPC 2.0 request (bad JSON or missing method).
401 · -32001
Missing or invalid key / token.
403 · -32001
Key was revoked. Mint a new one.
200 · -32601
Unsupported JSON-RPC method.
200 · -32602
Missing or unknown tool name.
200 · -32000
Tool handler threw — read error.message.

Security model

Merchant-scoped
Every API key is tied to one merchant workspace and one owner or member uid. Tools cannot reach another merchant's data.
Hashed keys
Plaintext keys are shown once. Firestore stores only a SHA-256 hash and a short prefix.
Audited tools
Each tool call writes an audit event with the caller, tool name, and status — without storing full arguments or result payloads.
Draft-first
Creation tools produce drafts; publishing, billing, and destructive changes stay with the merchant in Qrblox Create.

Connect snippets

Claude Desktop

~/Library/Application Support/Claude/claude_desktop_config.jsonjson
{
  "mcpServers": {
    "qrblox": {
      "url": "https://app.qrblox.com/api/mcp",
      "headers": { "Authorization": "Bearer sk-qrblox-…" }
    }
  }
}

Cursor

In Cursor settings, add a new MCP server with the same URL and Authorization header.

curl (smoke test)

tools/call → qrblox.pingbash
# Expect: { ok: true, merchantId: "…", authMethod: "api-key" }
curl -s https://app.qrblox.com/api/mcp \
  -H "Authorization: Bearer sk-qrblox-…" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"qrblox.ping","arguments":{}}}'

Looking for the rest of the stack? Web Portal · Canva app · All docs