Docs Back to site Menu

Manual setup

Install the MCP by hand, or connect your own x402 client to the HTTP API, then verify what you installed.

Option 1: Install the MCP

Use SECONDED in Claude Code, Codex, Gemini CLI, Claude Desktop, Cursor or another MCP client, with one tool for each of the thirteen checks. Install with Node.js 20 or newer, including npm and npx, available to your host. Choose your host below and preserve any existing server entries; if SECONDED is already configured, update its entry instead of adding a duplicate.

Claude Desktop

Merge this into claude_desktop_config.json in Claude Desktop’s user application-support directory. Fully quit Claude Desktop, including its tray or menu-bar process, then reopen it.

{ "mcpServers": { "seconded": { "command": "npx", "args": [ "--yes", "@seconded/mcp@0.4.4", "serve", "--host", "claude-desktop" ] } } }

Claude Code

Run this in your terminal. Exit the current session and start a new claude session.

claude mcp add --scope user seconded -- npx --yes @seconded/mcp@0.4.4 serve --host claude-code

Cursor

Merge this into ~/.cursor/mcp.json. Fully quit and reopen Cursor.

{ "mcpServers": { "seconded": { "command": "npx", "args": [ "--yes", "@seconded/mcp@0.4.4", "serve", "--host", "cursor" ] } } }

Codex

Add this table to ~/.codex/config.toml. Exit and restart the Codex session.

[mcp_servers.seconded] command = "npx" args = ["--yes", "@seconded/mcp@0.4.4", "serve", "--host", "codex"]

Gemini CLI

Merge this into your user ~/.gemini/settings.json. Exit and restart Gemini CLI.

{ "mcpServers": { "seconded": { "command": "npx", "args": [ "--yes", "@seconded/mcp@0.4.4", "serve", "--host", "gemini" ] } } }

Another MCP client

Most MCP apps take this mcpServers entry. Add it to your app’s user-level MCP settings, then fully quit and reopen the app.

{ "mcpServers": { "seconded": { "command": "npx", "args": [ "--yes", "@seconded/mcp@0.4.4", "serve", "--host", "generic" ] } } }

Your local check wallet

After restarting, ask your agent to call seconded_wallet. On a fresh installation, the first tool call creates a dedicated check wallet on this computer and shows its public funding address; it does not run or queue a check. An existing installation keeps its wallet and stored limits. The private key stays on your machine; MCP tools see the public address and funding guidance, never the key.

Storage prefers the OS credential store. If it is unavailable, SECONDED uses an unencrypted wallet.key file private to your user account and shows its location. Keep the profile and backups private. If the tool warns that it could not check for an earlier wallet, resolve that warning before funding the new address.

Fund the network you will use

Call seconded_wallet again to see the wallet address, balances, token contracts and storage guidance. Verify the address and selected network, then send only a few dollars of the matching stablecoin to that address on that network:

Base mainnet — USDC.
Use network: "base". This is the default when a paid check omits the network.
Arc mainnet — USDC.
Pass network: "arc" on every paid check.
Robinhood Chain mainnet — USDG (Global Dollar).
Pass network: "robinhood" on every paid check. Robinhood Chain does not take USDC for checks.

Fund checks with the listed stablecoin only, on the matching network. These are real mainnet payments; testnet balances are separate. Installation does not fund the wallet or pay for a check. Keep only what checks need in this dedicated wallet.

New wallets default to $2.50 per check and $25 per day across networks. Ask your agent to show seconded_get_limits or lower limits with seconded_set_limits. Chat can tighten limits or freeze payments; raising limits, unfreezing or switching wallets requires you to confirm in your own terminal.

Run your first check

Ask for seconded_products to see the checks and their inputs. Listing products is free. Preview this short Scam Check for free with seconded_quote:

{ "product": "scam_check", "input": { "message": "Urgent: send funds to unlock your account.", "source": "email" } }

Quote previews use Base mainnet only; they do not choose the network for a paid check. This Small Scam Check costs $0.10, or $0.15 paid on Robinhood Chain; max_price_usd below is the most you allow.

Once you have funded the wallet and want to pay for the check, ask your agent to call seconded_scam_check with these arguments. For Arc or Robinhood Chain, change network to arc or robinhood to match the wallet you funded:

{ "input": { "message": "Urgent: send funds to unlock your account.", "source": "email" }, "network": "base", "max_price_usd": "0.25" }

Read the answer and receipt

The check’s tool result includes the answer and signed receipt in your MCP host. Ask the agent to show them, including what was checked and any coverage gaps. Call seconded_receipt with no arguments for recent checks, including after an error or timeout, before asking for another check. Pending, failed or NOT VERIFIED results mean pause; act only on an agreed signed receipt for the exact input supplied.

Receipts and payment history also stay in private local files in the selected profile (by default ~/.seconded, or %USERPROFILE%\.seconded on Windows). Keep that profile and its backups private.

Option 2: Connect directly over x402

It needs an x402 client, or any code that can make HTTP requests and sign with a wallet, and a wallet just for checks. Fund it with a few dollars of USDC on Base or Arc, or USDG on Robinhood Chain. Checks pay on Base unless the request names Arc or Robinhood Chain.

These are mainnet funds: every paid check is a real payment from this wallet. Only ordinary wallet (EOA) signatures are accepted; smart-contract wallets are refused before anything is charged. Two doors take payment, and the choice is simple: an agent using a stock x402 SDK pays through the standard x402 door at POST /v1/x402/checks; a custom client that can sign the nonce the 402 supplies may use either door — the original door binds the payment to that nonce. The worked example below uses the standard door. Read the standard door’s contract before paying there: raise the SDK’s $1 default per-payment cap to the quoted price, and write a private recovery record before the first paid send.

A wallet only for checks is safer: if anything goes wrong, only those few dollars are at risk. Why a separate wallet

1Send the check

For stock x402 SDKs, use the standard door. Here is a Scam Check on one short email. Send the check and its input to /v1/x402/checks, with no payment yet:

curl -i https://api.secondedoracle.xyz/v1/x402/checks \ -H 'Content-Type: application/json' \ -H 'SECONDED-CLIENT-VERSION: 0.4.4' \ -d '{"product":"scam_check","input":{"message":"Urgent: send funds to unlock your account.","source":"email"},"options":{"network":"eip155:8453","max_price":"0.25"}}'

The reply is 402 Payment Required. The payment terms are in the JSON body and, identical, in the base64 PAYMENT-REQUIRED header: accepts[0] names the price, network, asset and payee. This message is Small, so the check costs $0.10, or $0.15 paid on Robinhood Chain. The SECONDED-CLIENT-VERSION: 0.4.4 header selects these current prices and the newer checks; without it, the API keeps the older prices. The standard door’s public 402 contains pricing, domain and validity terms plus an opaque nonexclusive ticket, without check/quote/offer IDs, salt, request commitment or exact billable byte count. Each verified payer selects a separate private purchase.

options.network picks where you pay: eip155:8453 for Base, eip155:5042 for Arc, eip155:4663 for Robinhood Chain. options.max_price is the most this check may cost, in US dollars; if the price is higher, the reply is 409 and no payment is asked for. The payee is the same on every network: accepts[0].payTo in the 402 must be 0x010ab46D566cDe25Cca0ee55eb105e781C7Bcf3a; stop if it differs.

2Pay with your x402 client

Your x402 client signs a payment for exactly those terms and sends the same request again, with the payment in the PAYMENT-SIGNATURE header:

curl -i https://api.secondedoracle.xyz/v1/x402/checks \ -H 'Content-Type: application/json' \ -H 'SECONDED-CLIENT-VERSION: 0.4.4' \ -H "PAYMENT-SIGNATURE: $PAYMENT" \ -d '<the same body as step 1, byte for byte>'

$PAYMENT is the base64 x402 v2 payment created by your SDK. Echo the selected accepts entry unchanged, including accepted.extra. Before the first paid send, save a private recovery record using the recovery hooks. The complete buy.py example handles this and defaults to a $0.25 cap; a larger cap requires an explicit --max-price. It sends SECONDED-CLIENT-VERSION: 0.4.4, so it pays the current prices; see the note. A receipt-free 202 is unverified pending information; it proves neither payment nor an answer.

If a request times out, send the same signed payment again. Never sign a new one for the same check: sending the same payment again never charges twice, but a new payment is a new purchase. More in Waiting, timeouts and retries.

3Fetch the answer

On the standard door, repeat the exact same paid POST with a plain HTTP client, the saved body and the same PAYMENT-SIGNATURE. Never use an automatic payment wrapper for recovery. With recover.py, your private record and trusted public /v1/keys data are all you need:

python recover.py private/purchase-001.json public-keys.json

The helper verifies the receipt’s signed purchase_association against your full original authorization, accepted terms and canonical request, plus billing, before accepting the answer. New records use seconded-door-recovery/v2 and require this association. It classifies status and response shape before reading the receipt, accepts an answer only on HTTP 200, and verifies signed 202 replies as pending with no answer or PAYMENT-RESPONSE. It never signs another payment. Keep the record if it stops while pending; run recovery again later with the same record.

A 202 means the check is still running; wait as Retry-After says. Then your agent gets the signed receipt and, when both models agreed, the answer, and knows what to do with it:

benign
Proceed.
suspicious
Pause and verify through an independent channel.
malicious
Stop and show you.
NOT VERIFIED
No agreed answer. Pause or ask a human. Free: up to 5 free NOT VERIFIED results per wallet in any rolling 24 hours; at the cap, new checks from that wallet wait until one leaves the window. How free results work

Do not read agreement from the HTTP status alone: act only on an agreed answer in a signed receipt, for the exact input you sent — and read the receipt’s coverage list. It names each part of the check as checked, partial, not checked or unavailable for your input; a part marked not checked was not verified, even next to an agreed answer. The fields of the ownership proof and how to verify a receipt are in the docs.

Alternative: original door for custom clients

A custom client that can sign the server-supplied nonce may instead start with POST /v1/checks. For the same Small Scam Check, the unpaid request is:

curl -i https://api.secondedoracle.xyz/v1/checks \ -H 'Content-Type: application/json' \ -H 'SECONDED-CLIENT-VERSION: 0.4.4' \ -d '{"product":"scam_check","input":{"message":"Urgent: send funds to unlock your account.","source":"email"},"options":{"network":"eip155:8453","max_price":"0.25"}}'

On this original door, the EIP-3009 authorization must use accepts[0].extra.authNonce from the 402 as its nonce. A client-chosen nonce is refused with 400 quote_nonce_required and nothing is charged. Send the same body and signed payment back to /v1/checks.

Fetch GET /v1/checks/$CHECK_ID, taking the ID from seconded.check_id in the 402. Sign the 401 ownership challenge with the paying wallet (it moves no funds), then repeat the GET with the proof in SECONDED-OWNERSHIP. See the original-door steps and proof fields. Stock SDKs should use the standard-door example above.

Waiting, timeouts and retries

The answer is released once your payment lands on-chain: typically tens of seconds on Arc, usually under 2 minutes on Base, and one to two minutes on Robinhood Chain. A check itself never works longer than about three minutes — a slow answer is fetched, never bought again. Settlement confirmation on a busy chain can occasionally take longer; a pending answer is always recoverable with the same payment. Keep the payment record and resume recovery later. Do not pay again. Quote expiry does not end recovery of an admitted check. Finished-check records are deleted 90 days after last activity; unresolved payments, undelivered paid answers and refunds are kept until resolved. Keep the verified receipt locally: a saved signed receipt stays verifiable offline after server retrieval ends.

202: still running.
Wait as Retry-After says, usually 2–5 seconds, then repeat the same paid POST with a plain HTTP client (or the ownership GET on the original door). To hold the request open instead of polling, send Prefer: wait=25; the API waits up to 25 seconds before replying.
Timeout, or a lost reply after paying.
Send the same signed payment again — it never charges twice and returns the same check — or recover with GET /v1/checks/$CHECK_ID and the ownership proof. Never sign a new payment for a check that may still be running: a new payment is a new purchase. Application replies may carry hints — do_not_resign, poll_after_s, new_quote_allowed — follow them. A plain-text ingress 503 is retryable. Structured 503 errors store_unavailable, internal_error and verification_unavailable are retryable only with do_not_resign: true and new_quote_allowed: false. A retry proves neither payment nor answer entitlement. Other refusals stop recovery and preserve the private record. Honour numeric or HTTP-date Retry-After and poll_after_s, waiting at least one second within the recovery budget. The Python helper allows up to 30 minutes; if it stops pending, resume with the saved record. A verified terminal receipt is different — see the next entry.
A signed receipt saying service_failed: terminal, nothing charged.
The live service returns this as a 503; the helpers recognise it on HTTP 200 or 503. In either case, a reply whose signed receipt says state: service_failed with billing.charged: "no" is final: the check failed on our side, you were not charged, and retrying the same request cannot change it. Verify the receipt, stop polling, and archive your recovery record; when hints.new_quote_allowed is true you may deliberately start a new purchase later, from a fresh 402 and, on the standard door, a new record file. The receipt’s reason names the cause: prefetch_unavailable — a data source the check needed (a chain reader, an official token list, public records) could not be read in time; provider_unavailable — a model provider could not be reached; engine_error — an internal failure on our side. The published recover.py and recover.mjs recognise this receipt, print a clear no-charge result and archive the record.
429: a rate or fair-use limit.
Wait as Retry-After says, then repeat the same request. A 429 never cancels a running check, and its hints say do_not_resign: it is never a reason to sign anything new. The free NOT VERIFIED cap also answers 429; new checks from that wallet wait until the window clears, while running checks continue.
Quote expired before you paid.
A quote lasts about two minutes. If it expires unpaid, nothing was charged: send the unpaid request again for a fresh 402.

The full API contract

The API describes itself in OpenAPI 3.1, with the exact request and response schema for every route: api.secondedoracle.xyz/v1/openapi.json. GET /v1/products lists each check’s input, prices and payment networks, and POST /v1/quote prices a check for free, before anything is paid.

Agents can read these steps as plain text at secondedoracle.xyz/install.txt, and the agent skill covering both doors at secondedoracle.xyz/skill.md. The standard door’s full contract and recovery examples are at secondedoracle.xyz/docs/x402-door.

Spending limits are yours

For a direct API connection, SECONDED installs nothing on your side and keeps no budget for you. What your agent spends is the owner’s responsibility: set options.max_price on every check, set any daily or hourly budget in your agent or x402 client, and keep only a few dollars in the paying wallet.

No check costs more than $2.50. The service applies its own per-wallet rate and fair-use limits, but they protect the service, not your budget.

Test networks

Testnet

The testnet beta ran on Base Sepolia, Arc testnet and Robinhood Chain testnet, paid with testnet USDC and testnet USDG. It has ended: SECONDED now takes payment on the Base, Arc and Robinhood Chain mainnets only.

A check that names a test network in options.network is refused before anything is paid. Test and mainnet balances are separate: never send mainnet funds to a testnet address.

Verify what you install

The MCP plug-in, client 0.4.4, is published as the npm package @seconded/mcp and as signed builds in the release repository SecondedOracle/seconded-mcp-releases. Every release lists its files’ SHA-256 hashes in SHA-256SUMS, signed in SHA-256SUMS.sig with the release key below. The npm package carries the same key and checks the build it downloads against it before running it.

Release key fingerprint
SHA256:qciU/JIVSCg1Ry+7Jbl0xoEhyLFgd8NBnqBj+mr40Ss (Ed25519)
Signer identity
release@seconded
Signature namespace
seconded-release

To check a download yourself, put allowed_signers from the release repository, and SHA-256SUMS, SHA-256SUMS.sig and the files you want from the v0.4.4 release, in one folder. First confirm the key is ours. The first command must print 1, because the file holds exactly one key, and the second must print the fingerprint above; if either prints anything else, stop:

wc -l < allowed_signers awk '{print $3" "$4}' allowed_signers > release.pub ssh-keygen -lf release.pub -E sha256

Then check the signature, and the hash of each file you downloaded. The first command must print Good "seconded-release" signature for release@seconded with ED25519 key SHA256:qciU/JIVSCg1Ry+7Jbl0xoEhyLFgd8NBnqBj+mr40Ss, ending in exactly the fingerprint above. A good signature from any other key is not ours. Each file you downloaded must then show OK:

ssh-keygen -Y verify -f allowed_signers -I release@seconded -n seconded-release -s SHA-256SUMS.sig < SHA-256SUMS shasum -a 256 -c --ignore-missing SHA-256SUMS

On Linux, use sha256sum -c --ignore-missing SHA-256SUMS. The first line of SHA-256SUMS names the signed version, such as # seconded-release-version: 0.4.4; make sure it is the version you meant to install, because an older release also carries a valid signature. These builds are not notarized by Apple or signed by Microsoft, so your system may still ask you to approve them. The signature check needs an OpenSSH ssh-keygen that supports -Y verify.

Stay safe

Official sources only.
Send checks only to https://api.secondedoracle.xyz, and take the address from secondedoracle.xyz, not from a message, a reply or an ad. Pay only a 402 from that address.
SECONDED never asks for your seed phrase or private key.
Not to pay, not to fetch an answer, and not for a refund. Anyone who asks for one is not SECONDED.
An answer is not advice.
A SECONDED answer is AI-generated: a second check on one exact input. It is not financial or investment advice, not a recommendation to trade, and not a guarantee.
Keep the private recovery record.
On the standard door, keep the exact request, authorization and accepted terms in the private recovery record: the signed purchase_association ties the receipt to that purchase. Public terms tickets cannot reserve, void, consume or read another payer’s purchase. Never share payment headers, SIWX signatures or recovery records. On the original /v1/checks door, keep its salt and original input privately with the receipt; retained records still verify historical IDs and salted commitments.

More good practices for trading agents

Answers are AI-generated and are not financial advice. Not affiliated with OpenAI, Anthropic, Robinhood or any other provider. Terms and Privacy.