arcgate
Token search, swap quotes and ready-to-sign swap transactions on Arc, paid per call via x402
我該用這個嗎
品質與安全性
根據工具定義與協定合規性的自動化分析。
上下文成本
這是每次將伺服器的工具載入模型上下文時所消耗的約略 token 數量。數量越高,可用於其他工作的注意力就越少。
安裝
一鍵安裝
將以下內容加入你的 `claude_desktop_config.json` 檔案:
{
"mcpServers": {
"arcgate": {
"url": "https://api.arcgate.dev/trade/v1/mcp"
}
}
}遠端端點
https://api.arcgate.dev/trade/v1/mcpstreamable-http它能做什麼
工具清單
工具(7)
🟡tradeSearch(query, limit)
Resolves a ticker, name, prefix or `0x` address to candidate ERC-20 tokens on Arc. - **Cost:** 0.005 USDC per call over x402: the first call gets a 402 with payment requirements in the `PAYMENT-REQUIRED` header (base64 JSON); sign them and retry with a `PAYMENT-SIGNATURE` header carrying the payment payload. - **Key inputs:** `query` (required), `limit` (1-25, default 10). - **Returns:** each match with its verification status, safety verdicts and USDC/hub pools, most relevant first. - **Next:** pass the chosen result's `address` as `sell` or `buy` to POST /trade/v1/quote. Costs 5000 base units (0.005 USDC) per call. Payment goes in params._meta["x402/payment"]; use an x402-aware MCP client (see https://docs.arcgate.dev/#arcgate/description/mcp-for-agents).
輸入結構描述
{
"type": "object",
"properties": {
"query": {
"type": "string",
"minLength": 1,
"maxLength": 128
},
"limit": {
"default": 10,
"type": "integer",
"minimum": 1,
"maximum": 25
}
},
"required": [
"query"
],
"$schema": "http://json-schema.org/draft-07/schema#",
"additionalProperties": false
}🟡tradeQuote(sell, buy, amount, side, slippageBps, ...)
Prices a swap between `sell` and `buy` across the indexed venues and stores it under a `quoteId`. - **Cost:** 0.01 USDC per call over x402: the first call gets a 402 with payment requirements in the `PAYMENT-REQUIRED` header (base64 JSON); sign them and retry with a `PAYMENT-SIGNATURE` header carrying the payment payload. - **`sell` / `buy`:** two different assets (native and ERC-20 USDC count as the same asset; either side may be USDC). Resolve a ticker with POST /trade/v1/search first. - **Response shape:** when one side is USDC, `best.type` is `direct`/`two_hop`/`split` and `best.legs` lists one leg per path actually used; `routes[]` lists every discovery candidate. When neither side is USDC, or when a USDC-side allocation can't be expressed as legs, `best.type` is `graph`, `best.legs` is empty, and the execution plan is in `best.graph`. Both shapes support `side: exactIn` and `exactOut`, and both execute the same way through POST /trade/v1/swap. - **`amount`:** a human-readable decimal string in the token's own units, e.g. "1.5" for 1.5 USDC, not base units. It is the `sell` amount for `side: exactIn` and the `buy` amount for `side: exactOut`. - **Optional:** `side` (exactIn/exactOut), `slippageBps`, split and hop limits, `venues`/`excludeVenues` (ids from GET /trade/v1/venues), `taker`, `ttlSec`. - **Executability:** POST /trade/v1/swap executes every quote through ArcgateRouter. `best.executable` is `false`, with warning `graph_execution_unavailable`, when no ArcgateRouter is configured (or, for an Aerodrome edge, no Aerodrome router), or when the operator has disabled a selected path's venue - even with both routers configured. In that last case, POST /trade/v1/swap may still fall back to an executable candidate the quote already priced instead of failing outright. - **Readiness:** name the wallet that will trade in `taker` and the answer carries `readiness`, read at the quote's block: whether that wallet holds the input (`balance`), which approval or Permit2 signature POST /trade/v1/swap will need (`approval` for the default permit2, `approve` for `approval: "approve"`), enough native USDC for gas (`gas`), and whether this call's x402 payer can pay the swap fee (`fees`). `totalCostUsdc` is the swap fee plus gas: what finishing costs. When `ready` is false, `next` is `stop`. Without `taker` there is no `readiness`. - **Lifetime:** the `quoteId` is good for `ttlSec` seconds (default and max 120). - **Next:** POST /trade/v1/swap with the returned `quoteId`. Costs 10000 base units (0.01 USDC) per call. Payment goes in params._meta["x402/payment"]; use an x402-aware MCP client (see https://docs.arcgate.dev/#arcgate/description/mcp-for-agents).
輸入結構描述
{
"type": "object",
"properties": {
"sell": {
"type": "string",
"minLength": 1,
"maxLength": 128
},
"buy": {
"type": "string",
"minLength": 1,
"maxLength": 128
},
"amount": {
"type": "string",
"minLength": 1,
"maxLength": 80
},
"side": {
"default": "exactIn",
"type": "string",
"enum": [
"exactIn",
"exactOut"
]
},
"slippageBps": {
"default": 100,
"type": "integer",
"minimum": 0,
"maximum": 5000
},
"maxSplits": {
"default": 3,
"type": "integer",
"minimum": 1,
"maximum": 5
},
"allowSplits": {
"default": true,
"type": "boolean"
},
"maxHops": {
"default": 2,
"anyOf": [
{
"type": "number",
"const": 1
},
{
"type": "number",
"const": 2
}
]
},
"venues": {
"default": null,
"anyOf": [
{
"maxItems": 16,
"type": "array",
"items": {
"type": "string",
"minLength": 1,
"maxLength": 64
}
},
{
"type": "null"
}
]
},
"excludeVenues": {
"default": [],
"maxItems": 16,
"type": "array",
"items": {
"type": "string",
"minLength": 1,
"maxLength": 64
}
},
"sources": {
"default": [
"native"
],
"minItems": 1,
"maxItems": 4,
"type": "array",
"items": {
"type": "string",
"minLength": 1,
"maxLength": 32
}
},
"taker": {
"default": null,
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"ttlSec": {
"description": "How long the stored quote (and this response's expiresAt) stays live, in seconds (1-120, default 120). A caller may shorten it to re-quote sooner; it can never lengthen past 120s. Safe to shorten or leave at default: POST /trade/v1/swap always re-quotes and re-simulates at the current block and 409s quote_stale below the stored minAmountOut, so this bounds staleness risk, not price risk. The on-chain execution deadline is a separate parameter (deadlineSec, POST /trade/v1/swap).",
"default": 120,
"type": "integer",
"minimum": 1,
"maximum": 120
}
},
"required": [
"sell",
"buy",
"amount"
],
"$schema": "http://json-schema.org/draft-07/schema#",
"additionalProperties": false
}🟡tradeSwap(quoteId, taker, recipient, deadlineSec, approval)
Turns a stored quote into unsigned transactions for the taker to sign and send. arcgate never signs, broadcasts or holds funds. - **Cost:** 0.01 USDC under $1,000; 0.05 USDC from $1,000 to $10,000; above that 0.05 USDC plus 0.5 bps of the amount over $10,000, capped at 5 USDC, size-tiered by the quote's USD notional (the USDC side for a USDC pair, or a token-to-token quote's USD valuation; a quote with no valuation prices at tier 1), over x402 (402 with `PAYMENT-REQUIRED`, retry with `PAYMENT-SIGNATURE`). Charged once per quote: POST /trade/v1/swap/tx, the Permit2 second round below, is free. - **Key inputs:** `quoteId` (from POST /trade/v1/quote), `taker`; optional `recipient` (defaults to `taker`), `deadlineSec`, `approval`. Never `permit` - that belongs to POST /trade/v1/swap/tx; sending one here is 400 `invalid_request` (the strict schema rejects the unknown key). - **Every quote executes through ArcgateRouter:** it is always the Permit2 `spender` and the ERC-20 `approve` spender below. When every source pool of the route being executed trades native USDC, the swap is funded by `value` instead - no approval transaction and no signature at all. - **Permit2 (default, one or two calls):** - Returns `transactions` - an unlimited ERC-20 `approve(Permit2, type(uint256).max)` first, if the token's ERC-20 allowance to Permit2 is below the amount, then the swap, which carries an empty Permit2 signature and is only directly sendable as-is when a Permit2 allowance to ArcgateRouter already covers the amount, in which case `signatures` is empty too. Otherwise it also returns `signatures: [{ kind: "permit2", typedData }]`; sign `typedData` with the taker's key (EIP-712, e.g. viem's `signTypedData`). - **Sign, then call POST /trade/v1/swap/tx** with the same `quoteId`, `taker` and `recipient`, and `permit: { message: typedData.message, signature }`, while the quote is live: free, because this call already paid the swap fee. The first call to it that succeeds uses the round up; a failed one doesn't. - Send that response's `transactions` in order. - **`approval: "approve"` (one call):** returns at most one ERC-20 `approve(ArcgateRouter, amountIn)` transaction instead of a permit to sign - an exact amount, never Permit2, never a signature - and only when the taker's current allowance is below it. - **Freshness:** the quote lives for the `ttlSec` the quote call asked for (default/max 120s); after that `quoteId` is 410 `quote_expired`. Every call re-quotes and re-simulates at the current block and returns 409 `quote_stale` when the fresh re-quote fails or falls below the stored `minAmountOut`, when the pre-flight simulation reverts on slippage, or when the simulated delivery is below `minAmountOut`. A 409 or 410 carries a free fresh quote in `quote`, with `next: "requote"`: the original quote request (same amount, tokens, side, `slippageBps` and venues, default `ttlSec`) quoted again through the same pipeline, exactly as POST /trade/v1/quote answers it; when the original named a `taker`, the fresh quote is for this call's `taker`, the wallet swapping now. Nothing executes on it: check its price, `safety.verdict` and `readiness`, then swap its `quoteId`. When the fresh quote can't be traded (`no_route`, `insufficient_liquidity`, `unsupported_venue` or `buy_reverts`, a `cannot_sell` or `illiquid` verdict, not executable, or the taker isn't ready) the answer is `next: "stop"` with no `quote`, and `error.hint` says why. One fresh quote per paid quote: a second 409/410 for the same `quoteId`, a quote that itself came from a 409/410, or a quote expired over 5 minutes ago gets plain `requote` with no `quote`, as does one whose re-quote couldn't run or failed on the server's side; then quote again yourself. - **Fallback:** A stored route on a disabled/undeployed venue falls back to the best executable candidate the quote already priced (warning `route_not_executable`), or 422 `not_executable` when no such candidate exists, none re-quotes, or no ArcgateRouter is configured at all. - **Attempts:** a quote gets at most 5 failed calls here; the next call on that `quoteId` is 429 `swap_attempts_exhausted` (`next: "requote"`), answered without running the swap pipeline. A failed call is a 409, a 410 (its fresh quote may run), a 422, 500 or 503, or a successful pipeline whose payment settlement or delivery fails. An attempt stays reserved until its 200 is delivered (after settlement when paid); that delivery, a 404, or a 400 (at parse, or a reserved `taker`/`recipient`) uses none. A delivered 200 does not reset this quote's previous failures. POST /trade/v1/swap/tx counts its own, per permit round. - **Next:** a 200 with `signatures` non-empty needs POST /trade/v1/swap/tx before sending anything (`next: "sign_permit"`); otherwise sign and send `transactions` in order, then confirm the fill with POST /trade/v1/receipt (free). Costs 0.01 USDC under $1,000; 0.05 USDC from $1,000 to $10,000; above that 0.05 USDC plus 0.5 bps of the amount over $10,000, capped at 5 USDC; the exact amount for your quoteId comes back in the payment-required result. Payment goes in params._meta["x402/payment"]; use an x402-aware MCP client (see https://docs.arcgate.dev/#arcgate/description/mcp-for-agents).
輸入結構描述
{
"type": "object",
"properties": {
"quoteId": {
"type": "string",
"pattern": "^q_[0-9a-f]{16,}$"
},
"taker": {
"type": "string",
"pattern": "^0x[0-9a-fA-F]{40}$"
},
"recipient": {
"default": null,
"anyOf": [
{
"type": "string",
"pattern": "^0x[0-9a-fA-F]{40}$"
},
{
"type": "null"
}
]
},
"deadlineSec": {
"default": 60,
"type": "integer",
"minimum": 10,
"maximum": 600
},
"approval": {
"default": "permit2",
"type": "string",
"enum": [
"permit2",
"approve"
]
}
},
"required": [
"quoteId",
"taker"
],
"$schema": "http://json-schema.org/draft-07/schema#",
"additionalProperties": false
}🟡tradeSwapTx(quoteId, taker, recipient, deadlineSec, permit)
The free Permit2 second round: finishes a POST /trade/v1/swap call whose `signatures` asked the taker to sign a Permit2 `PermitSingle`. - **Cost:** free, never x402-gated - a payment header, if one is sent anyway, is ignored and nobody is charged. Only reachable once, right after the paid call that opened it. - **Key inputs:** the SAME `quoteId`, `taker` and `recipient` (defaults to `taker`) as the paid POST /trade/v1/swap call, plus `deadlineSec` and the required `permit: { message: signatures[0].typedData.message, signature }` (sign `typedData` with the taker's key, EIP-712, e.g. viem's `signTypedData`). `permit` accepts only `message` and `signature`, end to end - any other field, at any level, is 400 `invalid_request` at parse. The service rebuilds the Permit2 domain itself and checks the signer, spender, token, amount, nonce and both deadlines: a mismatched spender or token, or an amount below `amountIn` (a larger amount is accepted), is 400 `invalid_request`; a stale nonce, an expired `sigDeadline`/`expiration`, or an invalid signature (verified via ERC-1271 on chain for a contract taker) is 422 `swap_reverts`. A contract taker can swap, but POST /trade/v1/receipt only reads transactions the taker sends itself, so it answers `invalid_request` for a Safe, ERC-4337 or batching EIP-7702 wallet: check your own transaction receipt instead. - **No pending round:** 409 `no_pending_swap` when this `quoteId`/`taker`/`recipient` never paid, named a different taker or recipient, or already used its one free call - call POST /trade/v1/swap first, which is paid and returns the permit this call takes. - **Freshness:** re-quotes and re-simulates exactly like POST /trade/v1/swap, and can answer the SAME 410 `quote_expired`/409 `quote_stale` it would - but never with a fresh `quote` (issue #124's free re-quote is /trade/v1/swap's own paid-quote courtesy, not this free route's). - **Attempts:** a permit round (`quoteId`, `taker`, `recipient`) gets at most 5 failed calls; the next one is 429 `swap_attempts_exhausted` (`next: "requote"`), answered without running the swap pipeline. A failed call is a 400 from the permit checks above, a 409, 422, 500 or 503, or an undelivered 200; a delivered 200, a 400 at parse, a 404, a 410 or `no_pending_swap` uses none. Failed POST /trade/v1/swap calls don't count here. A new POST /trade/v1/swap permit response resets this round's attempts only once delivered (after settlement when paid). - **Next:** sign and send `transactions` in order, then confirm the fill with POST /trade/v1/receipt (free). This is the last call in search -> quote -> swap -> swap/tx.
輸入結構描述
{
"type": "object",
"properties": {
"quoteId": {
"type": "string",
"pattern": "^q_[0-9a-f]{16,}$"
},
"taker": {
"type": "string",
"pattern": "^0x[0-9a-fA-F]{40}$"
},
"recipient": {
"default": null,
"anyOf": [
{
"type": "string",
"pattern": "^0x[0-9a-fA-F]{40}$"
},
{
"type": "null"
}
]
},
"deadlineSec": {
"default": 60,
"type": "integer",
"minimum": 10,
"maximum": 600
},
"permit": {
"type": "object",
"properties": {
"message": {
"type": "object",
"properties": {
"details": {
"type": "object",
"properties": {
"token": {
"type": "string",
"pattern": "^0x[0-9a-fA-F]{40}$"
},
"amount": {
"type": "string",
"pattern": "^\\d+$"
},
"expiration": {
"type": "string",
"pattern": "^\\d+$"
},
"nonce": {
"type": "string",
"pattern": "^\\d+$"
}
},
"required": [
"token",
"amount",
"expiration",
"nonce"
],
"additionalProperties": false
},
"spender": {
"type": "string",
"pattern": "^0x[0-9a-fA-F]{40}$"
},
"sigDeadline": {
"type": "string",
"pattern": "^\\d+$"
}
},
"required": [
"details",
"spender",
"sigDeadline"
],
"additionalProperties": false
},
"signature": {
"type": "string",
"pattern": "^0x[0-9a-fA-F]+$"
}
},
"required": [
"message",
"signature"
],
"additionalProperties": false
}
},
"required": [
"quoteId",
"taker",
"permit"
],
"$schema": "http://json-schema.org/draft-07/schema#",
"additionalProperties": false
}🟡tradeReceipt(quoteId, txHashes)
Tells you whether the transactions POST /trade/v1/swap returned did what the quote promised, once you've sent them. It only reads the chain. - **Cost:** free, never x402-gated. - **Key inputs:** `quoteId` (the one you called POST /trade/v1/swap with) and `txHashes`, the 1 to 4 transactions you sent for it: the swap, and any approvals. It answers for a quote /trade/v1/swap handed transactions for in the last hour, else 404 `swap_not_found`, and only for that quote's transactions, sent from its `taker`: an approval to the input token, or a swap to ArcgateRouter whose deadline one of the quote's /trade/v1/swap or /trade/v1/swap/tx answers issued and whose output goes to its `recipient`, else 400 `invalid_request`. - **Smart-contract wallets:** a Safe, an ERC-4337 account or a batching EIP-7702 wallet sends its transaction from an executor or bundler, or to itself, not from the taker to ArcgateRouter, so this answers 400 `invalid_request` for it. Check that transaction's own receipt and your wallet's success event instead. - **Returns:** `result`, from the swap transactions. One that filled decides it: `pass` when `delivered` is at least `minAmountOut`, else `fail` (a round 1 that reverted doesn't undo a round 2 that filled). With none filled: `pending` while one is not mined yet, else `fail`: it reverted or was never mined by 60s after its deadline (status `expired`, or `not_found` when the chain never saw it). Approvals are listed but don't change the result. `delivered` is what `recipient` received of `token` (the output), read from the swap transaction's Transfer logs, in base units. Also `block`, each transaction's `status`, and `reason`, one sentence on a fail or pending. The first result from a mined swap is final: asking again returns it. - **Limits:** one chain read per quote every 5s (the same `txHashes` inside that get the last answer; other hashes get 429 `receipt_rate_limited` with `retryAfterSec`), and at most 132 per quote (then 429 `receipt_reads_exhausted`, for good). - **Next:** `pass`: tell the user what they bought (`delivered` of `token`). `fail`: follow `next`: `requote` when no swap transaction succeeded (nothing filled; quote again), `stop` when one did (tell them `reason`, and don't trade again). `pending`: ask again in a few seconds.
輸入結構描述
{
"type": "object",
"properties": {
"quoteId": {
"type": "string",
"pattern": "^q_[0-9a-f]{16,}$"
},
"txHashes": {
"minItems": 1,
"maxItems": 4,
"type": "array",
"items": {
"type": "string",
"pattern": "^0x[0-9a-fA-F]{64}$"
}
}
},
"required": [
"quoteId",
"txHashes"
],
"$schema": "http://json-schema.org/draft-07/schema#",
"additionalProperties": false
}🟡tradeVenues
Lists the DEX venues, hub tokens and launchpads this deployment indexes. - **Cost:** free, never x402-gated. - **Returns:** each venue with an `executable` flag, hubs and launchpads. - **Next:** use venue ids in POST /trade/v1/quote's `venues` / `excludeVenues`.
輸入結構描述
{
"type": "object",
"properties": {},
"$schema": "http://json-schema.org/draft-07/schema#"
}🟡health
Reports whether the service is up, with its diagnostics. - **Cost:** free, never x402-gated. - **Returns:** DB import health, rule set version, the deployed commit, cache/RPC/spend counters and the payer-identity mode. - **Next:** call before search/quote/swap to check the service is up.
輸入結構描述
{
"type": "object",
"properties": {},
"$schema": "http://json-schema.org/draft-07/schema#"
}社群
證據