qaqnuz MCP public API reference

Authentication#

Every MCP request authenticates with a scoped api key. The key is presented as an HTTP-style Authorization: Bearer <key> value, or as a bare key string on the stdio transport. The server resolves the key to a single brand and role, then governs every call against that context.

The api key#

  • Keys are minted show-once by a brand owner or manager. The raw value is

shown exactly once at creation; only an HMAC-SHA-256 hash is stored server-side. qaqnuz cannot recover a lost key — rotate instead.

  • A key carries a role (default viewer, i.e. read-only) and resolves to

exactly one brand. The brand is taken from the key record alone; it can never be overridden by a request header or parameter.

  • A key carries a set of scopes<resource>.<action> strings. A key with

no scopes can call nothing (default-deny).

  • Keys support expires_at and revoked_at. A revoked or expired key fails auth

before any tool is resolved.

Entitlement gate. The MCP surface is available on the Growth and Enterprise plans only. On a non-entitled brand, list_tools returns an empty list and call_tool returns a permission error — regardless of the key's scopes. This check runs first, before scopes are considered.

Presenting the key#

The auth layer accepts either form:

text
Authorization: Bearer qx_live_8s9d...        # standard Bearer scheme
qx_live_8s9d...                              # bare key (stdio transport)

The Bearer prefix is case-insensitive. An empty or missing value is rejected as Unauthorized — the server never reveals why a key failed (unknown vs. revoked vs. expired all look identical), which is deliberate enumeration-resistance.

Connecting over MCP (stdio)#

The v1 GA transport is stdio: the qaqnuz MCP server runs as a local or sidecar process that your MCP client launches and speaks JSON-RPC to over stdin/stdout. Your api key is supplied to that process (typically via an environment variable it reads on startup).

A typical MCP client configuration entry:

json
{
  "mcpServers": {
    "qaqnuz": {
      "command": "qaqnuz-mcp",
      "args": [],
      "env": {
        "QAQNUZ_API_KEY": "qx_live_8s9d..."
      }
    }
  }
}
No public HTTPS base URL yet. A hosted mcp.qaqnuz.uz/v1 HTTP/SSE endpoint is designed but not yet deployed (it depends on platform GATE-5 infrastructure). Until it is announced, integrate over stdio. The authentication model is identical on both transports, so code written against stdio carries over unchanged when the gateway ships.

Scopes#

Scopes use the same grammar the in-product policy engine uses:

text
<resource>.<action>

Examples: sheets.read, orders.write, contacts.read.

Rules:

  • No wildcards. Any scope containing * (*, *.*, admin.*, *.read) is

rejected — at key creation and again at resolution time. Wildcards are never expanded to a set of tools.

  • Subtract-only. Your effective authorization is the intersection of the

key's scopes and your brand's existing tool-permission policy. A key can narrow what the brand allows; it can never grant something the brand denies.

  • Exact match. A tool is callable only if the key's scope set contains that

tool's exact scope. There is no prefix or hierarchical matching.

Verifying a key works#

Once connected, call list_tools. A working, entitled key with at least one in-scope tool returns a non-empty tool list. An empty list means one of: the brand is not entitled, no tool is flagged MCP-exposable, or the key's scopes do not intersect any exposable tool — all of which are indistinguishable by design.

Security notes for integrators#

  • Never embed a key in client-side or public code. Treat it like a password.
  • Scope minimally. Request only the scopes your integration needs; prefer a

read-only (viewer) key unless you specifically need write/external tools.

  • Rotate on suspicion. Mint a new key, cut over, then revoke the old one.
  • Expect generic auth errors. Do not build logic that depends on

distinguishing failure reasons — the server intentionally returns the same Unauthorized for every auth failure.