MCP-Server
arcgate
dev.arcgate/arcgate
Öffentlich und erreichbar
MCP 2025-11-25
Was dieses MCP kann
Token search, swap quotes and ready-to-sign swap transactions on Arc, paid per call via x402
Funktionen
Tools
7
Tools
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.
Eingabeschema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {}}
tradeQuote
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).
Eingabeschema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['sell', 'buy', 'amount'], 'properties': {'buy': {'type': 'string', 'maxLength': 128, 'minLength': 1}, 'sell': {'type': 'string', 'maxLength': 128, 'minLength': 1}, 'side': {'enum': ['exactIn', 'exactOut'], 'type': 'string', 'default': 'exactIn'}, 'taker': {'anyOf': [{'type': 'string'}, {'type': 'null'}], 'default': None}, 'amount': {'type': 'string', 'maxLength': 80, 'minLength': 1}, 'ttlSec': {'type': 'integer', 'default': 120, 'maximum': 120, 'minimum': 1, '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)."}, 'venues': {'anyOf': [{'type': 'array', 'items': {'type': 'string', 'maxLength': 64, 'minLength': 1}, 'maxItems': 16}, {'type': 'null'}], 'default': None}, 'maxHops': {'anyOf': [{'type': 'number', 'const': 1}, {'type': 'number', 'const': 2}], 'default': 2}, 'sources': {'type': 'array', 'items': {'type': 'string', 'maxLength': 32, 'minLength': 1}, 'default': ['native'], 'maxItems': 4, 'minItems': 1}, 'maxSplits': {'type': 'integer', 'default': 3, 'maximum': 5, 'minimum': 1}, 'allowSplits': {'type': 'boolean', 'default': True}, 'slippageBps': {'type': 'integer', 'default': 100, 'maximum': 5000, 'minimum': 0}, 'excludeVenues': {'type': 'array', 'items': {'type': 'string', 'maxLength': 64, 'minLength': 1}, 'default': [], 'maxItems': 16}}, 'additionalProperties': False}
tradeReceipt
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.
Eingabeschema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['quoteId', 'txHashes'], 'properties': {'quoteId': {'type': 'string', 'pattern': '^q_[0-9a-f]{16,}$'}, 'txHashes': {'type': 'array', 'items': {'type': 'string', 'pattern': '^0x[0-9a-fA-F]{64}$'}, 'maxItems': 4, 'minItems': 1}}, 'additionalProperties': False}
tradeSearch
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).
Eingabeschema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['query'], 'properties': {'limit': {'type': 'integer', 'default': 10, 'maximum': 25, 'minimum': 1}, 'query': {'type': 'string', 'maxLength': 128, 'minLength': 1}}, 'additionalProperties': False}
tradeSwap
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).
Eingabeschema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['quoteId', 'taker'], 'properties': {'taker': {'type': 'string', 'pattern': '^0x[0-9a-fA-F]{40}$'}, 'quoteId': {'type': 'string', 'pattern': '^q_[0-9a-f]{16,}$'}, 'approval': {'enum': ['permit2', 'approve'], 'type': 'string', 'default': 'permit2'}, 'recipient': {'anyOf': [{'type': 'string', 'pattern': '^0x[0-9a-fA-F]{40}$'}, {'type': 'null'}], 'default': None}, 'deadlineSec': {'type': 'integer', 'default': 60, 'maximum': 600, 'minimum': 10}}, 'additionalProperties': False}
tradeSwapTx
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.
Eingabeschema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['quoteId', 'taker', 'permit'], 'properties': {'taker': {'type': 'string', 'pattern': '^0x[0-9a-fA-F]{40}$'}, 'permit': {'type': 'object', 'required': ['message', 'signature'], 'properties': {'message': {'type': 'object', 'required': ['details', 'spender', 'sigDeadline'], 'properties': {'details': {'type': 'object', 'required': ['token', 'amount', 'expiration', 'nonce'], 'properties': {'nonce': {'type': 'string', 'pattern': '^\\d+$'}, 'token': {'type': 'string', 'pattern': '^0x[0-9a-fA-F]{40}$'}, 'amount': {'type': 'string', 'pattern': '^\\d+$'}, 'expiration': {'type': 'string', 'pattern': '^\\d+$'}}, 'additionalProperties': False}, 'spender': {'type': 'string', 'pattern': '^0x[0-9a-fA-F]{40}$'}, 'sigDeadline': {'type': 'string', 'pattern': '^\\d+$'}}, 'additionalProperties': False}, 'signature': {'type': 'string', 'pattern': '^0x[0-9a-fA-F]+$'}}, 'additionalProperties': False}, 'quoteId': {'type': 'string', 'pattern': '^q_[0-9a-f]{16,}$'}, 'recipient': {'anyOf': [{'type': 'string', 'pattern': '^0x[0-9a-fA-F]{40}$'}, {'type': 'null'}], 'default': None}, 'deadlineSec': {'type': 'integer', 'default': 60, 'maximum': 600, 'minimum': 10}}, '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`.
Eingabeschema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {}}
Verlauf
Letzte Tool-Änderungen
Hinzugefügt
health
3. October 2026 02:40
Hinzugefügt
tradeVenues
3. October 2026 02:40
Hinzugefügt
tradeReceipt
3. October 2026 02:40
Hinzugefügt
tradeSwapTx
3. October 2026 02:40
Hinzugefügt
tradeSwap
3. October 2026 02:40
Hinzugefügt
tradeQuote
3. October 2026 02:40
Hinzugefügt
tradeSearch
3. October 2026 02:40