https://xcatcher.top/api/v1/mcp/Authorization: Bearer xc_live_...Accept: application/json/mcp/health
Agents should call these tools by exact name:
# Agent loop (high level)
# - Use Remote MCP tools for task operations
# - Use REST for the final file download
# 0) tool list (optional)
tools/list
# 1) create task (side effect)
create_crawl_task(users=[...], mode="normal|deep", idempotency_key="stable-key")
if error.code == "PAYMENT_REQUIRED":
# 2) payment_required contains quote_id and accepts (base/solana)
q = error.details.payment_required
quote_id = q.quote_id
# 3) pay on chain:
# - base: send USDC on Base to accepts.base.payTo, amount >= accepts.base.maxAmountRequired
# - sol : send USDC SPL to accepts.solana.payTo, amount >= accepts.solana.maxAmountRequired
# record tx proof:
# - base proof: txHash
# - sol proof: signature
# 4) build PAYMENT-SIGNATURE = base64(utf8 json)
payment_signature_b64 = b64json({
"x402Version": 1,
"scheme": "exact",
"network": "eip155:8453" or "solana:mainnet",
"payload": { "txHash": "..."} or { "signature": "..." }
})
# 5) top up (side effect)
x402_topup(quote_id=quote_id, payment_signature_b64=payment_signature_b64)
# 6) retry create with SAME idempotency_key
create_crawl_task(... same idempotency_key ...)
# 7) poll
while true:
s = get_task_status(task_id)
if s.ok and s.has_result: break
sleep(5)
# 8) get download URL (still requires Bearer when downloading)
u = get_result_download_url(task_id)
# 9) download file with REST:
# GET /api/v1/tasks/{task_id}/download (Authorization: Bearer ...)
BASE="https://xcatcher.top"
API_KEY="xc_live_xxx"
# MCP = JSON-RPC over HTTP
# MUST include Accept: application/json
curl -sS -X POST "$BASE/mcp/" \
-H "Authorization: Bearer $API_KEY" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' | jq .
import os
# ADK import compat
try:
from google.adk.tools.mcp_tool import McpToolset, StreamableHTTPConnectionParams
except Exception:
from google.adk.tools.mcp_tool import MCPToolset as McpToolset # type: ignore
from google.adk.tools.mcp_tool import StreamableHTTPConnectionParams # type: ignore
toolset = McpToolset(
connection_params=StreamableHTTPConnectionParams(
url="https://xcatcher.top/mcp",
headers={
"Authorization": "Bearer xc_live_xxx",
"Accept": "application/json",
},
),
tool_filter=[
"create_crawl_task",
"x402_topup",
"get_task_status",
"get_result_download_url",
"cancel_task",
],
)
The topup proof is sent as HTTP header PAYMENT-SIGNATURE. The value is base64(UTF-8 JSON).
{
"x402Version": 1,
"scheme": "exact",
"network": "eip155:8453",
"payload": {
"txHash": "0x...base_transaction_hash..."
}
}
{
"x402Version": 1,
"scheme": "exact",
"network": "solana:mainnet",
"payload": {
"signature": "5v...solana_tx_signature...pQ"
}
}
Two steps: GET quote → pay → POST topup. Topup credits points to the current Bearer key.
BASE="https://xcatcher.top"
API_KEY="xc_live_xxx"
POINTS=100
# 1) Quote
QUOTE_JSON=$(curl -s "$BASE/api/v1/x402/quote?points=$POINTS")
echo "$QUOTE_JSON"
# 2) Pay on Base:
# - send USDC to quote.accepts.base.payTo
# - amount >= quote.accepts.base.maxAmountRequired (atomic, 6 decimals)
QUOTE_ID="q_xxx"
BASE_TXHASH="0x...your_base_tx_hash..."
# 3) PAYMENT-SIGNATURE = base64(json)
PAYMENT_SIGNATURE_B64=$(jq -nc --arg tx "$BASE_TXHASH" \
'{"x402Version":1,"scheme":"exact","network":"eip155:8453","payload":{"txHash":$tx}}' \
| base64 -w 0)
# 4) Top up CURRENT key
curl -s -X POST "$BASE/api/v1/x402/topup" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-H "PAYMENT-SIGNATURE: $PAYMENT_SIGNATURE_B64" \
-d "{\"quote_id\":\"$QUOTE_ID\"}"
# 5) Verify points
curl -s "$BASE/api/v1/me" -H "Authorization: Bearer $API_KEY"
BASE="https://xcatcher.top"
API_KEY="xc_live_xxx"
POINTS=100
# 1) Quote
curl -s "$BASE/api/v1/x402/quote?points=$POINTS"
# 2) Pay on Solana:
# - send USDC SPL to quote.accepts.solana.payTo
QUOTE_ID="q_xxx"
SOL_TX_SIG="5v...your_solana_signature...pQ"
# 3) PAYMENT-SIGNATURE = base64(json)
PAYMENT_SIGNATURE_B64=$(jq -nc --arg sig "$SOL_TX_SIG" \
'{"x402Version":1,"scheme":"exact","network":"solana:mainnet","payload":{"signature":$sig}}' \
| base64 -w 0)
# 4) Top up CURRENT key
curl -s -X POST "$BASE/api/v1/x402/topup" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-H "PAYMENT-SIGNATURE: $PAYMENT_SIGNATURE_B64" \
-d "{\"quote_id\":\"$QUOTE_ID\"}"
# 5) Verify
curl -s "$BASE/api/v1/me" -H "Authorization: Bearer $API_KEY"
# Health check (public, no auth) curl -s "https://xcatcher.top/mcp/health"
This is a compact summary that agents can copy and parse.
{
"base_url": "https://xcatcher.top",
"rest_base": "https://xcatcher.top/api/v1",
"mcp_url": "https://xcatcher.top/mcp/",
"auth": {
"type": "bearer",
"header": "Authorization",
"format": "Bearer xc_live_..."
},
"mcp_required_headers": {
"Accept": "application/json",
"Content-Type": "application/json"
},
"tools": [
{"name":"create_crawl_task","side_effect":true,"inputs":["users[]","mode","idempotency_key"],"on_402":"PAYMENT_REQUIRED"},
{"name":"x402_topup","side_effect":true,"inputs":["quote_id","payment_signature_b64"]},
{"name":"get_task_status","read_only":true,"inputs":["task_id"]},
{"name":"get_result_download_url","read_only":true,"inputs":["task_id"]},
{"name":"cancel_task","side_effect":true,"inputs":["task_id"]}
],
"x402": {
"quote": {"method":"GET","path":"/api/v1/x402/quote?points="},
"topup": {"method":"POST","path":"/api/v1/x402/topup","header":"PAYMENT-SIGNATURE"},
"payment_signature_format": "base64(utf8 json)",
"base_network": "eip155:8453",
"solana_network": "solana:mainnet",
"base_proof": {"payload_key":"txHash"},
"solana_proof": {"payload_key":"signature"}
},
"download": {
"method": "GET",
"path": "/api/v1/tasks//download",
"note": "download always requires the same Bearer token"
}
}
Use REST when you just want simple HTTP calls. Workflow is the same: create task → poll → download.
BASE="https://xcatcher.top"
# 1) Register -> returns api_key (xc_live_...)
curl -s -X POST "$BASE/api/v1/auth/register" \
-H "Content-Type: application/json" \
-d '{"username":"YOUR_USERNAME","password":"YOUR_PASSWORD"}'
# 2) Login -> returns api_key (may revoke old key)
curl -s -X POST "$BASE/api/v1/auth/login" \
-H "Content-Type: application/json" \
-d '{"username":"YOUR_USERNAME","password":"YOUR_PASSWORD"}'
API_KEY="xc_live_xxx"
# 3) Check points
curl -s "$BASE/api/v1/me" -H "Authorization: Bearer $API_KEY"
# 4) Create task (may return 402 + PAYMENT-REQUIRED)
curl -s -X POST "$BASE/api/v1/tasks" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"mode":"normal","users":["elonmusk","naval"],"idempotency_key":"rest-req-001"}'
BASE="https://xcatcher.top"
API_KEY="xc_live_xxx"
TASK_ID=10136
# Poll
curl -s "$BASE/api/v1/tasks/$TASK_ID" -H "Authorization: Bearer $API_KEY"
# Download (xlsx stream)
curl -L -o "task_${TASK_ID}.xlsx" \
-H "Authorization: Bearer $API_KEY" \
"$BASE/api/v1/tasks/$TASK_ID/download"
When you create a task with insufficient points, you get HTTP 402. The server also returns a quote (for x402):
HTTP/1.1 402 Payment Required
PAYMENT-REQUIRED: <base64(json)>
{
"success": false,
"msg": "payment required",
"payment_required": {
"quote_id": "q_...",
"accepts": {
"base": {"network":"eip155:8453", "payTo":"0x...", "asset":"0xUSDC", "maxAmountRequired":"..."},
"solana": {"network":"solana:mainnet","payTo":"...", "asset":"USDC_MINT","maxAmountRequired":"..."}
},
"expires_in": 600,
"recommend_points": 100,
"short_points": 37,
"task_cost_points": 50,
"balance_points": 13,
"next_step": {
"topup_endpoint": "/api/v1/x402/topup",
"note": "Send PAYMENT-SIGNATURE then call /api/v1/x402/topup with the same Bearer token; retry /api/v1/tasks with the same idempotency_key."
}
}
}