Developers

Let an agent spend inside a limit you set. Keep the treasury out of reach.

The PQTABS SDK and MCP server connect your agent to a post-quantum root's capability on Arc mainnet. Read a capability, price a question, and pay for research only inside the cap, expiry, and payee the root approved. The MCP server runs locally over stdio. It cannot create a root, raise a limit, or add a payee.

Arc mainnet 5042pqtabs-barkeepRead-only firstLocal stdio MCPMIT
01Onboarding

Connect an agent, step by step

Each step is a check you can run yourself. The root authorizes the agent, the local signer holds the agent key, and the MCP server asks the signer for one signature per approved payment. Nothing on this page signs or spends.

1Circle Agent Wallet

Optional. Not connected here

Circle's agent wallet from the CLI is a smart contract account. Barkeep's capability accepts only an ECDSA signature from an externally owned account, so the CLI wallet cannot be the agent. The tab requires the recovered ECDSA signer to equal its agent address, and an on-chain check confirmed that rule for EOA agents. The contract-wallet case follows from that rule. It was not tested live. A Circle developer-controlled EOA on ARC is a separate option. It needs your Circle API key and entity secret on your own server. This page never asks for them, and the primary path below does not need them.

2Create a local signer

Create, then paste the public address

Run this once on the machine that will run your agent. It creates a new key, protects it with your operating system account, and prints only the public address.

Create a signer (prints only the public address)
node "<path to packages/pqtabs-signer/dist/src/cli.js>" create

Check it any time with pqtabs-signer status --agent 0x…. The key never reaches this page, the backend, or the MCP process.

Paste the address that pqtabs-signer create printed. Nothing is sent anywhere.

Recovery: move an existing key from a dashboard backup

Only if you already exported an encrypted backup from the PQTABS dashboard and need it on this machine. The passphrase is typed into the terminal, hidden, and never into this page.

Import a backup
node "<path to packages/pqtabs-signer/dist/src/cli.js>" import-backup <backup file> --agent 0x…

3Pair the signer

Needs the address

Pairing proves that the signer on your machine holds the address above. The page issues a one-time request, you sign it locally, and the page checks the signature. It does not authorize any payment.

Enter the public address in step 2. Pairing starts from that address.

4Authorize the agent

Root action. Not done here

Only the root can open a capability. Open the PQTABS app and create a capability for the paired address. Review the cap, the per-call limit, the approved payees, and the expiry. Then sign with the root security key. Nothing on this page creates, signs, or changes a capability.

Open the PQTABS app

5Connect the MCP server

Needs the address

pqtabs-mcp 0.1.2 is on npm and reads both variables below. It holds no key: it asks the local signer for one signature per payment. The signer itself is not on npm, so point PQTABS_SIGNER_CLI at the built file from this repository. On Windows, Cursor may need cmd /c npx.

MCP configuration (no key)
{
  "mcpServers": {
    "pqtabs": {
      "command": "npx",
      "args": [
        "-y",
        "pqtabs-mcp@0.1.2"
      ],
      "env": {
        "PQTABS_SIGNER_CLI": "<path to packages/pqtabs-signer/dist/src/cli.js>",
        "PQTABS_SIGNER_AGENT": "0x<agent address from pqtabs-signer status>"
      }
    }
  }
}

6Test safely

Read-only first
  1. Call pqtabs_status. It reads the backend and Arc, and spends nothing.
  2. Call pqtabs_check_spend_policy for the capability and a task. It checks the quote against the capability and signs nothing.
  3. Only after you approve one specific payment, call pqtabs_run_paid_researchwith confirmSpend true and a maxPriceRaw. It is never run automatically.

7Manage access

In the PQTABS app

Each capability carries these limits. Change or close it in the app. Closing returns unspent USDC to the root.

  • Scope

    What the agent may buy. Today: pqtabs-barkeep research only.

  • Expiry

    After this time the capability refuses every payment.

  • Cap

    The most the capability may spend in total.

  • Per-call limit

    The most it may pay in one payment.

  • Payee

    Only the approved recipients. Others are refused.

  • Balance

    The USDC left in the capability right now.

  • Revoke

    Close the capability. The agent can no longer spend.

8Read-only API session

Optional. Reads only

A session reads portfolio data for your roots through the API. It cannot sign a payment, open or close a capability, or change a limit or payee. Your wallet signs one sign-in message, and nothing else.

When a call is refused

Each message says whether anything was signed or broadcast. A refusal before signing never moves money.

CodeWhat it meansWhat to do
signer_unavailableThe local signer did not return a signature. The signer may be locked, missing, or refused the request.Run pqtabs-signer status --agent <address>. Fix what it reports. Nothing was broadcast.
signer_mismatchThe signature does not recover to this capability's agent.Check PQTABS_SIGNER_AGENT. It must be the agent the root opened. Nothing was broadcast.
policy_refusedThe capability refused the payment: cap, per-call limit, expiry, or payee.Read the reason in the PQTABS app. Nothing was signed.
exceeds_max_priceThe quote costs more than maxPriceRaw.Raise maxPriceRaw only if you accept the quoted price. Nothing was signed.
quote_expiredThe quote expired before it was paid.Ask for a new quote. Nothing was signed.
rate_limitedThe backend is limiting requests.Wait for retry-after, then try again. The same authorization is resent, never re-signed.
rpc_rate_limitedArc is limiting reads. The read proves nothing about the payment.Retry shortly. Nothing was decided from this read.
rpc_unavailableArc's RPC node is catching up to the head.Retry in a few seconds.
settlement_unknownA payment may have settled, but the receipt is not confirmed yet.Open the transaction in the explorer before you retry. Do not pay again.
chain_mismatchThe backend and the RPC do not both report Arc mainnet (5042).Fix PQTABS_BACKEND_URL or PQTABS_RPC_URL. Nothing was started.

A developer session is read-only. It never authorizes a signature, a capability, or a payment. Pairing proves that a signer holds an address. It does not authorize a capability, and only the root can do that.

02Packages

TypeScript SDK

pqtabs-sdk 0.1.1

Typed reads, quote and policy checks, receipt verification, and paid research. Read, research, and spend are separate namespaces, so a read never moves money.

MCP server

pqtabs-mcp 0.1.2

A local stdio server for MCP hosts. Seven read and quote tools are always available. A paid tool is offered only when a signer is configured for an already-authorized capability.

03SDK

Install and read in one minute

Node.js 20.19 or later, ESM. The read example needs no keys and talks to the public backend and the Arc RPC.

Install
npm install pqtabs-sdk
TypeScript, read-only
import { PqtabsClient } from "pqtabs-sdk";

// Read-only: no keys, no money. Uses the public backend and Arc mainnet (chain 5042).
const pqtabs = new PqtabsClient();

const config = await pqtabs.read.config();     // refuses unless the backend is Arc mainnet
const chainId = await pqtabs.read.rpcChainId(); // read from the Arc RPC, never assumed
const portfolio = await pqtabs.read.portfolio("<your root address>");

console.log(config.chainId, chainId, portfolio.tabs.filter((tab) => tab.open).length);

Paying for research

Paid calls need a local signer and a capability your root already opened. The SDK checks the quote against the cap, per-payment limit, expiry, payee, balance, and chain before it signs. If a check fails, nothing is signed.

  • The agent key stays inside the signer. It is never sent to the backend.
  • A quote is signed at most once. Retries send the same authorization.
  • Use an external signer (hardware wallet, KMS, or enclave) when you can.
TypeScript, paid (spends USDC)
import { PqtabsClient, externalSigner } from "pqtabs-sdk";

// Spends USDC. Only for a capability your root has already opened.
// signTypedData calls YOUR signer (hardware wallet, KMS, enclave, or local signer) and returns the 65-byte signature.
// The agent key never enters this process.
const signer = externalSigner({
  address: "<agent address the root opened>",
  signTypedData: (typedData) => mySigner.signTypedData(typedData),
});

const outcome = await new PqtabsClient().spend.research({
  tab: "<open capability address>",
  signer,
  maxPriceRaw: "1000",               // the most this run may pay: 0.001 USDC
  task: "What is the Arc USDC gas token?",
});

// outcome.status: "complete" | "result_pending" | "settlement_pending"
04MCP hosts

Connect an MCP host

Three hosts are documented here, using their own configuration formats. Each one starts the server with the same command. Setup is not zero-click: you must add the entry, restart or approve the server in the host, and then confirm that tools appear. A host that is not listed uses the same stdio command.

Optional: install globally
npm install -g pqtabs-mcp

The configs below use npx, so a global install is optional. Use it if your host cannot run npx.

Claude Desktop

claude_desktop_config.json
{
  "mcpServers": {
    "pqtabs": {
      "command": "npx",
      "args": ["-y", "pqtabs-mcp"]
    }
  }
}

On Windows the file is %APPDATA%\Claude\claude_desktop_config.json. Quit and restart Claude Desktop after saving.

Cursor

.cursor/mcp.json
{
  "mcpServers": {
    "pqtabs": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "pqtabs-mcp"]
    }
  }
}

Put it in .cursor/mcp.json for one project, or ~/.cursor/mcp.json for every project. Enable the server in Cursor's MCP settings, then check the MCP logs if it stays off.

Claude Code

terminal
claude mcp add --transport stdio pqtabs -- npx -y pqtabs-mcp

The command adds the server to local scope. Add --scope user to use it in every project.

Before you configure paid research

The entries above are read-only. Paid research needs a signer for an agent your root has already authorized. The repository build uses PQTABS_SIGNER_CLI and PQTABS_SIGNER_AGENT, so the MCP process never holds the key. The published 0.1.2 package also reads PQTABS_AGENT_PRIVATE_KEY for older setups. That is a legacy path, because the key sits in the server process. Do not paste a root backup phrase or a root private key into any configuration.

05Tools

Read-only tools and paid tools

Only one tool can move USDC, and it is listed only when a signer is configured. Every tool reads the live backend or Arc. None returns a mock balance or a success the chain did not confirm.

ToolEffect classWhat it does
pqtabs_statusread-onlyChecks the backend and Arc RPC chain. Moves nothing.
pqtabs_get_portfolioread-onlyReads one root and its capabilities from Arc.
pqtabs_list_capabilitiesread-onlyCaps, per-payment limits, live balances, expiry, and payees.
pqtabs_get_receiptread-onlyChecks one Arc transaction against one expected payment.
pqtabs_create_research_quotequote onlyPrices a question and creates a quote record. Signs nothing.
pqtabs_check_spend_policyquote onlyReturns ALLOW or REFUSE with reasons. Creates a quote record. Signs nothing.
pqtabs_recover_resultno paymentFetches the answer for a quote that already settled. Never relays, signs, or charges.
pqtabs_run_paid_researchspends USDCPays one capability inside its limits. Listed only when a signer is configured. Requires confirmSpend true and maxPriceRaw.

Refusals and their reasons

A refusal means nothing was signed or broadcast. The reasons come from the backend's policy check.

  • capability_inactive: The capability is closed or not yet open.
  • expired: The capability has passed its expiry.
  • wrong_payee: The quote pays an address the capability does not approve.
  • balance: The capability does not hold enough USDC for this payment.
  • exposure: The root's open exposure ceiling would be exceeded.
  • max_per_call: The payment is above the capability's per-payment limit.
  • wrong_agent: The signer is not the capability's agent.

Results and receipts

A result is returned only after an Arc receipt succeeds and contains exactly one USDC transfer from the capability to the payee for the stated amount. A reverted receipt never produces a result.

  • complete: The receipt matched exactly one USDC transfer from the capability to the payee, and the answer is ready.
  • result_pending: The receipt matched, but the answer is not ready. Call pqtabs_recover_result later. It never charges again.
  • settlement_pending: Submitted to Arc, but the receipt is not confirmed yet. Retry with the same quote id. It never signs or relays again.
06Boundary and configuration

The signing boundary

  • The root is the only authority. Creating a root, opening or closing a capability, changing a cap, a limit, or a payee, and rotating root authority happen in the PQTABS app, never through MCP or the SDK.
  • The agent key authorizes one payment at a time, inside an already open capability. The SDK and MCP server never send that key anywhere except the signer.
  • Backend and RPC must both report Arc mainnet (5042). The USDC is the 6-decimal ERC-20 at 0x3600000000000000000000000000000000000000.
  • The protocol is named pqtabs-barkeep. It is not standard x402 exact, and it has no ArcRouter PAYMENT-RESPONSE.

Environment variables

NameDefault
PQTABS_BACKEND_URL

Backend. Plain http is allowed only for localhost.

https://pqtabs.onrender.com
PQTABS_RPC_URL

Arc RPC for chain checks and receipts.

https://rpc.mainnet.arc.io
PQTABS_STATE_DIR

Stores spend attempts so a retry never signs twice.

~/.pqtabs
PQTABS_SIGNER_CLI

Repository build. Path to the pqtabs-signer CLI. The MCP asks it for one signature per approved payment and never holds the key.

unset
PQTABS_SIGNER_AGENT

Repository build. The public agent address. It must match the address the signer stores.

unset
PQTABS_AGENT_PRIVATE_KEY

Legacy, pqtabs-mcp 0.1.1 and earlier. The raw key sits in the server process. Prefer a local signer. Unset it to run read-only.

unset

Chain 5042 · RPC https://rpc.mainnet.arc.io · Explorer https://explorer.arc.io

07Setup prompt for an agent

Ask your agent to set it up

Give this prompt to a capable AI agent that can edit its own MCP configuration. It installs the published package, adds a read-only entry, restarts or asks you to approve, and runs read-only checks. It never asks for a backup phrase or a private key, and it never spends.

Setup stops at read-only. Paid research is a separate step you take on purpose, with your own key in your secret store.

Copy and give to your agent
You are configuring the PQTABS MCP server on this machine. PQTABS is a post-quantum spending boundary on Arc mainnet (chain 5042). Work through these steps in order and report each result.

1. Detect which MCP host you run in (Claude Desktop, Cursor, Claude Code, or another). If you cannot tell, ask me which host to configure.
2. Check that Node.js 20.19 or later is installed: run "node --version".
3. Add one MCP server entry named "pqtabs" to the host's own configuration file, using the host's documented format. Use command "npx" and args ["-y", "pqtabs-mcp"]. Do not add any environment variables.
4. If the host needs a restart or an approval for a new server, tell me exactly what to do, then wait for me to confirm.
5. Call pqtabs_status. It must report backendOk true, sdkRpcChainId 5042, and onArc true.
6. List the advertised tools. Expect seven read tools and no pqtabs_run_paid_research.
7. Run read-only smoke tests: call pqtabs_get_portfolio, then pqtabs_list_capabilities, for a root address I give you.

Rules you must follow:
- Never ask me for a root backup phrase, a post-quantum private key, or any private key in this chat.
- Do not create or open a capability, close one, change a cap, limit, or payee, rotate a root, fund a wallet, or broadcast a transaction.
- Do not set PQTABS_AGENT_PRIVATE_KEY, PQTABS_SIGNER_CLI, or PQTABS_SIGNER_AGENT unless I explicitly ask you to enable paid research and point you to my secret store or signer. Never print a key or a signer secret.
- Do not call a paid tool or spend USDC during setup.
- If a check fails, report the error code and stop. Do not work around it by changing limits, keys, or the payee.
08Troubleshooting

When something does not connect

Start with pqtabs_status. It shows whether the backend and the Arc RPC answer and which chain each reports. Most problems below show up there first.

The host does not list any PQTABS tools

Restart the host completely. Check that the JSON is valid. If the host asks you to approve a new server, approve it. Then open the host's MCP log for the pqtabs entry.

npx cannot be found on Windows

Install Node.js 20.19 or later from nodejs.org, then run npm install -g pqtabs-mcp and set command to pqtabs-mcp. A host started from a different PATH may need the full path to npx.cmd.

onArc is false, or chain_mismatch

The backend or the RPC is not reporting Arc mainnet (5042). Unset PQTABS_BACKEND_URL and PQTABS_RPC_URL, or set PQTABS_RPC_URL to https://rpc.mainnet.arc.io. Do not point at testnet.

backend_unavailable, timeout, or HTTP 5xx

The public backend is not answering. Wait a short while and retry. Reads move no money. If this happens during a paid run, the outcome may be unknown, so use the same quote id with pqtabs_recover_result or the SDK resume call. That call never charges twice.

rate_limited (HTTP 429)

The public backend allows 240 reads and 8 relays per minute per client. Wait for the retryAfterSeconds value, then retry. The SDK retries relays with the same authorization, so it never charges twice.

policy_refused, with reasons

Nothing was signed or broadcast. Read the reasons in the table above. Fix the capability through the PQTABS app under your root, not through the MCP server.

receipt_mismatch

The Arc transaction is not the exact payment for this quote, so no result is produced. Do not pay again. Inspect the transaction with pqtabs_get_receipt and the explorer.

settlement_pending or result_pending

The payment is either not yet confirmed or confirmed without an answer yet. Retry pqtabs_recover_result (or the SDK resume call) later with the same quote id. Retrying never charges again.

The server exits: PQTABS_AGENT_PRIVATE_KEY is not a 32-byte hex key

The value is malformed. The server prints no key. Fix the value in your secret store, or unset the variable to run read-only.

signer_unavailable or signer_mismatch

The local signer did not sign for this agent. Run pqtabs-signer status --agent with the address, and check that PQTABS_SIGNER_AGENT is the address the root opened. Nothing was broadcast.

plain http is refused for a remote backend

Use an https backend URL. Plain http is allowed only for localhost during development.

09Verify without spending

Check the connection first

  1. Install the SDK in a scratch project and run the read example above. It must print chain 5042.
  2. Configure the MCP server without a key, restart the host, and call pqtabs_status. Expect onArc: true.
  3. Call pqtabs_get_receipt with the settled example receipt to confirm receipt checks work end to end.

None of these steps sends a transaction. Paid research is a separate step, and it needs an open capability and a key you control.

Example receipt (settled, read-only)
tx        0x74ce7b557f8e5156af8fca701b40d833651ff1d206442f0a3ef4c801698f1b15
tab       0x7D627201477f192DBB3dC5E7e993aeF6701F302d
payee     0xf76e6B0920e9332fF4410f6dD53F01722AbC71a3
amountRaw 360