> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ravn.exchange/llms.txt
> Use this file to discover all available pages before exploring further.

# MCP Server

> Connect Claude, Cursor, or any MCP client to RAVN's quote/execute/status loop, free, no API key required.

RAVN runs a [Model Context Protocol](https://modelcontextprotocol.io) server that exposes the
Integrator API as native tools. Point any MCP-speaking client at it, and your agent can
discover and call RAVN without you writing any HTTP glue code.

**Endpoint:** `https://app.ravn.exchange/api/mcp`
**Transport:** Streamable HTTP
**Auth:** None required. Every tool works anonymously; pass your own API key as the optional
`apiKey` argument on any tool for a higher rate limit (see [Authentication](/authentication)).
**Cost:** Free. These tools call the same free `/v1/*` endpoints as the REST API, not the
paid [x402 endpoints](/ai-agents/x402-payments).

<Tip>
  Sanity-checking the endpoint with `curl` or a browser? A plain `GET` returns `405 Method Not
    Allowed`, which is expected, not broken. Streamable HTTP MCP servers only speak `POST`; use an
  MCP client to actually call it.
</Tip>

<CardGroup cols={2}>
  <Card title="Add to Claude.ai" icon="link" href="https://claude.ai/customize/connectors?modal=add-custom-connector&connectorName=RAVN&connectorUrl=https%3A%2F%2Fapp.ravn.exchange%2Fapi%2Fmcp">
    One click, no config file editing. Opens Claude.ai's "Add custom connector" dialog with RAVN's
    name and endpoint pre-filled, so you just review and confirm.
  </Card>

  <Card title="Add to Cursor" icon="link" href="cursor://anysphere.cursor-deeplink/mcp/install?name=RAVN&config=eyJ1cmwiOiJodHRwczovL2FwcC5yYXZuLmV4Y2hhbmdlL2FwaS9tY3AifQ%3D%3D">
    One click from a machine with Cursor installed. Opens Cursor's MCP install dialog with RAVN's
    name and endpoint pre-filled.
  </Card>
</CardGroup>

<Note>
  No equivalent deep link exists for Codex CLI yet. It only supports `codex mcp add` for local
  (stdio) servers, and remote HTTP servers like RAVN's have to go in `config.toml` by hand. See
  the Codex tab below.
</Note>

## Connect a client

<CodeGroup>
  ```json Claude Desktop / Claude Code (claude_desktop_config.json / .mcp.json) theme={null}
  {
    "mcpServers": {
      "ravn": {
        "url": "https://app.ravn.exchange/api/mcp"
      }
    }
  }
  ```

  ```json Cursor (.cursor/mcp.json) theme={null}
  {
    "mcpServers": {
      "ravn": {
        "url": "https://app.ravn.exchange/api/mcp"
      }
    }
  }
  ```

  ```toml Codex CLI (~/.codex/config.toml) theme={null}
  [mcp_servers.ravn]
  url = "https://app.ravn.exchange/api/mcp"
  auth = "none"
  ```
</CodeGroup>

Any client that supports remote MCP servers over Streamable HTTP works the same way; there's
nothing to install locally.

Also listed on [MCP.so](https://mcp.so/servers/ravn) (verified), [Glama](https://glama.ai/mcp/connectors/exchange.ravn/ravn),
and [Smithery](https://smithery.ai/servers/team-dgp6/ravn), for agents and clients that discover
servers by browsing an MCP directory instead of a direct config.

## Try it: one prompt, one loop

With the config above added, prompt your client with something like:

> Swap 0.01 ETH on Ethereum to USDC on Base for 0x1234...5678, my wallet address.

A capable MCP client resolves that into:

1. `ravn_quote({ inputChainId: 1, outputChainId: 8453, inputToken: "0xEeee...EEeE", outputToken: "<Base USDC address>", inputAmount: "10000000000000000", userAddress: "0x1234...5678" })` → returns a `quoteToken` plus the priced route.
2. `ravn_execute({ quoteToken })` → returns `{ executionType: "TRANSACTION", quoteToken, transaction: {...} }` for this route (0x Gasless/RFQ-style routes instead return `SIGNATURE`).
3. Your agent signs and sends the returned `transaction` with its own wallet; RAVN never touches it.
4. `ravn_status({ quoteToken: <from step 2>, ref: <tx hash from step 3, or statusRef if step 2 returned one> })`, polled until `status` is terminal (`success`, `refunded`, or `failed`).

No other setup, no API key, no payment. See [Execution Types](/execution-types) for what
`transaction` looks like for each `executionType`, and [Signing: who holds the wallet?](/ai-agents/overview#signing-who-holds-the-wallet)
for how an autonomous agent handles step 3 without a human clicking "confirm."

## Tools

### `ravn_quote`

Get a swap quote, same-chain or cross-chain, across all 17 supported chains including native
Bitcoin and Solana as source or destination. Returns a `quoteToken` to pass to `ravn_execute`,
plus an `executable` flag: false means the quote is a preview only, priced against a
placeholder address rather than the ones you supplied (or didn't), and `ravn_execute` will
reject it with `QUOTE_NOT_EXECUTABLE`.

| Argument | Type | Required | Notes |
| - | - | - | - |
| `inputChainId` | number | yes | See [chain IDs](#chain-ids) below |
| `outputChainId` | number | yes | |
| `inputToken` | string | yes | Contract address, or `0xEeee…EEeE` for the chain's native coin |
| `outputToken` | string | yes | |
| `inputAmount` | string | yes | Positive integer, in the input token's smallest unit (no decimals) |
| `userAddress` | string | yes | Address the input asset will be sent from |
| `destinationAddress` | string | no | Where output should land, if different from `userAddress`. Required here to get an executable quote from Relay (Bitcoin as the source), THORChain (Bitcoin either direction), Across (a Solana-touching route), or Eco (a cross-ecosystem route); omit it there and `executable` comes back false instead of an error |
| `refundAddress` | string | no | Required here for a Bitcoin-source Relay or THORChain quote, for the same reason as `destinationAddress` |
| `slippageBps` | number | no | 1 to 5000. Rift races only when this is omitted |
| `rankingMode` | `"best_output"` \| `"fastest"` | no | Defaults to `best_output` |
| `confidential` | boolean | no | Private settlement through NEAR Intents' Confidential Intents, so deposit and payout can't be linked on-chain. Over MCP only NEAR quotes it (`NO_LIQUIDITY` if it can't, never a public fallback): Houdini Swap needs the end user's IP, user-agent, and country for its compliance rules, which an MCP call doesn't carry, so use [`/quote`](/api-reference/quote) for it |
| `excludeVenues` | string\[] | no | Drop specific venues from this race, for example a risk objection to one or `ravn_health` showing it degraded. Naming a venue that was never eligible for this pair is a no-op, not an error |
| `apiKey` | string | no | Your RAVN API key, if you have one |

Response fields worth knowing about beyond `quoteToken` and `executable`:

| Field | Type | Notes |
| - | - | - |
| `inputUsd` | string \| null | USD value of the input amount, same price source as `gas.usd`. Null when the token can't be priced |
| `outputUsd` | string \| null | USD value of the output amount. Compare against `inputUsd` for price impact |
| `slippage` | object \| null | `bps`, `isFirm`, `guaranteedMin`, and `noMinimum`. When `noMinimum` is true the venue enforces no minimum output, so `bps` is not a protection and the user can receive more or less than quoted: tell them before they send funds |
| `alternatives` | array | Every other venue that raced and produced a usable quote, best output first, each with its own `quoteToken` you can pass to `ravn_execute` instead. Empty when no other venue could serve this pair, or a route was excluded via `excludeVenues` |

### `ravn_execute`

Turn a `quoteToken` from `ravn_quote` into an execution payload.

| Argument | Type | Required | Notes |
| - | - | - | - |
| `quoteToken` | string | yes | |
| `destinationAddress` | string | no | Late-bound recipient. Only Chainflip, Layerswap, Mayan, NEAR Intents, and Rift bind it at execute time; every other venue fixes it at quote time and rejects a different one with `INVALID_REQUEST`, so supply it on `ravn_quote` for those |
| `refundAddress` | string | no | Late-bound refund address, honoured by the same venues as `destinationAddress` |
| `apiKey` | string | no | |

Returns one of three shapes, tagged by `executionType`:

* **`TRANSACTION`**: sign and broadcast yourself
* **`SIGNATURE`**: sign, RAVN submits on your behalf
* **`DEPOSIT`**: send the input asset to a given address (the common case for Bitcoin-source
  swaps; see `ravn_btc_prepare_send` below)

Every shape also carries a `quoteToken`: pass that one, not `ravn_quote`'s, to
`ravn_submit_signature` and `ravn_status` (a two-hop RAVN route is rebound at execute). `DEPOSIT`
always carries a `statusRef` to poll with, and `TRANSACTION` sometimes does.

RAVN never takes custody of funds under any of the three; you always sign or send from your
own wallet.

### `ravn_submit_signature`

For a `SIGNATURE`-type `ravn_execute` result only: submit the signature(s) you collected (over
`typedData`, and `approvalData` if present) to actually place the order. RAVN decodes the venue
from `quoteToken` and routes to the right venue-specific submit path, you never touch a
per-venue endpoint.

| Argument | Type | Required | Notes |
| - | - | - | - |
| `quoteToken` | string | yes | The `quoteToken` `ravn_execute` returned |
| `signature` | string | yes | 0x-hex signature over the `typedData` from `ravn_execute` |
| `approvalSignature` | string | no | 0x Gasless only: signature over `approvalData`, when `ravn_execute` returned one |
| `apiKey` | string | no | |

Returns a `statusRef`, pass it to `ravn_status` as `ref` to poll this swap.

### `ravn_status`

Poll a swap's status.

| Argument | Type | Required | Notes |
| - | - | - | - |
| `quoteToken` | string | yes | The `quoteToken` `ravn_execute` returned, not `ravn_quote`'s |
| `ref` | string | yes | The `statusRef` from `ravn_execute` (`DEPOSIT`, and `TRANSACTION` when present) or from `ravn_submit_signature` (`SIGNATURE`), otherwise the origin tx hash (`TRANSACTION`) |
| `apiKey` | string | no | |

Status is authoritative where the venue exposes it. Jupiter is the one venue that reports
`"unknown"` honestly rather than guessing. Check the response's `tracking` field. Once
terminal, `deliveredAmount` and `txHash` are included when the venue reports them, `txHash` is
only ever populated once the swap is done, never while it's still in flight.

### `ravn_health`

No arguments. Liveness check across every venue RAVN routes through, useful to call before a
swap if you want to know whether a route is degraded ahead of time.

### `ravn_tokens`

RAVN's own listed token registry for one chain. Populate a token picker without hardcoding one.
This is "what RAVN knows about and might route," not a per-pair routability guarantee for any
specific pair, call `ravn_quote` to check that.

| Argument | Type | Required | Notes |
| - | - | - | - |
| `chainId` | number | yes | |
| `apiKey` | string | no | |

Returns an array of `{ symbol, name, address, decimals, chainId, isNative, logoUrl? }`.

### `ravn_tokens_resolve`

Resolve an arbitrary token address to its metadata (symbol, name, decimals) via an on-chain
read, for a paste-any-address flow when the token isn't necessarily on `ravn_tokens`'s list.

| Argument | Type | Required | Notes |
| - | - | - | - |
| `chainId` | number | yes | |
| `address` | string | yes | Token contract address / mint to resolve |
| `apiKey` | string | no | |

Returns `{ token: {...same shape as ravn_tokens's items} }`.

### `ravn_btc_coverage`

For a swap where native BTC is the source, not every token on the destination chain is
reachable. Returns which of `ravn_tokens`'s list on `chainId` a BTC venue can actually route
to, and how many venues serve each, so you can build a token list that matches what will really
quote instead of discovering it one `NO_LIQUIDITY` at a time.

<Note>
  BTC-as-source only. Selling a token **into** BTC isn't restricted the same way (nearly any
  token can be sold into BTC), so this has nothing useful to say about that direction.
</Note>

| Argument | Type | Required | Notes |
| - | - | - | - |
| `chainId` | number | yes | The destination chain to check BTC-source coverage on |
| `apiKey` | string | no | |

Returns `{ chainId, filtered, coverage }`. `coverage` maps a lowercased token address to the
number of BTC venues (1 to 3) that route to it, a token no venue serves is omitted, not listed
at 0. `filtered: false` means the upstream venue lists couldn't be reached right now, treat
that as unknown, not as "nothing routes."

### `ravn_chains`

Every chain RAVN lists a token registry for (see `ravn_tokens`). Static, doesn't change per
request, safe to cache instead of hardcoding a chain table.

No arguments beyond the optional `apiKey`. Returns an array of `{ chainId, name, shortName,
nativeCurrency: { name, symbol, decimals }, explorerUrl, logoUrl? }`.

### `ravn_btc_prepare_send`

Turns a `DEPOSIT`-type `ravn_execute` result into a ready-to-sign Bitcoin transaction (a PSBT),
so your agent doesn't have to implement UTXO selection or fee estimation itself.

| Argument | Type | Required | Notes |
| - | - | - | - |
| `fromAddress` | string | yes | Your Bitcoin address holding the UTXOs to spend; native SegWit (`bc1q…`) or Taproot (`bc1p…`) only |
| `toAddress` | string | yes | The `depositAddress` from `ravn_execute` |
| `amountSats` | string | yes | The `depositAmount` from `ravn_execute`, in satoshis |
| `feeRateSatsPerVb` | number | no | Omit to use mempool.space's current fee estimate |
| `network` | `"mainnet"` \| `"testnet"` | no | Defaults to `mainnet` |

UTXOs and the fee rate are fetched from the public [mempool.space](https://mempool.space) API,
with no keys and no auth required.

<Note>
  RAVN never sees or handles a private key at any point. The response is an unsigned PSBT
  (`psbtBase64`): sign it with your own wallet's key and broadcast it yourself.
</Note>

Only one signature is ever needed. Every RAVN Bitcoin-source venue (Chainflip, Relay, NEAR
Intents, Rift) resolves to a plain, single-recipient payment, not a multi-wallet
UTXO-co-signing ceremony some other aggregators require for their BTC routes.

## Chain IDs

| Chain | ID | | Chain | ID |
| - | - | - | - | - |
| Ethereum | 1 | | Robinhood Chain | 4663 |
| Optimism | 10 | | **Bitcoin** | **-1** |
| BNB Chain | 56 | | **Solana** | **-2** |
| Unichain | 130 | | Monad | 143 |
| Polygon | 137 | | HyperEVM | 999 |
| zkSync | 324 | | Arbitrum | 42161 |
| World Chain | 480 | | Linea | 59144 |
| Base | 8453 | | Avalanche | 43114 |
| Tempo | 4217 | | | |

Bitcoin and Solana use negative sentinel IDs rather than their (non-existent, in Bitcoin's
case) EVM chain IDs. Don't assume 0 or a positive placeholder.

## A full loop, end to end

1. `ravn_quote`: get a `quoteToken`
2. `ravn_execute`: get back `TRANSACTION`, `SIGNATURE`, or `DEPOSIT`
   * `TRANSACTION`: sign and broadcast the returned `transaction` with your own wallet
   * `SIGNATURE`: sign the returned `typedData` (and `approvalData`, if present) with your own
     wallet, then call `ravn_submit_signature` with the signature(s) to actually place the
     order, it returns the `statusRef` to poll next
   * `DEPOSIT`: if the input asset is Bitcoin, `ravn_btc_prepare_send` → sign the PSBT with your
     own wallet → broadcast. Otherwise, send the input asset to the returned address yourself
3. `ravn_status`: poll with `ravn_execute`'s `quoteToken` until terminal


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.