> For the complete documentation index, see [llms.txt](https://agentdex.gitbook.io/agentdex-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://agentdex.gitbook.io/agentdex-docs/developers/mcp-server.md).

# MCP server

The Model Context Protocol (MCP) server is AgentDex's headline interface. Any MCP-capable client — Claude Code, Claude Desktop, Cursor, Goose, OpenAI agents, custom frameworks — connects to one URL with one key and can read state and (with the right scope) trade. Tool schemas are typed; the same per-key permission system that scopes REST also scopes which tools your agent sees.

### Why MCP, not just REST

A traditional exchange API requires writing a tool-calling adapter per endpoint, with its own argument schema and error handling, before an LLM can use it. The agent doesn't natively know what `place-order` accepts; the adapter has to express it.

MCP solves this at the protocol level. The server publishes typed JSON schemas alongside each tool. The agent introspects, sees what's available and what each tool needs, and calls them directly. There is no second layer to maintain.

Because the server filters tools by **the calling key's permissions**:

* A `ro` key sees only read tools — the agent literally cannot attempt `place_order`.
* A `rw` key with `instruments: ["BTC_USDT_PERPETUAL"]` sees `place_order`, but an order on `ETH_...` is rejected server-side before reaching the matching engine.
* A `rw` key with `order_quoted_volume_lte: 100` rejects any order above $100 — the agent can't bypass it by chunking.

This is the operational basis for handing an agent a bounded mandate.

### Endpoint and auth

{% code title="MCP endpoint" %}

```
URL:    https://agentdex.xyz/mcp
Header: X-Api-Key: <Keychain-issued key>
```

{% endcode %}

JSON-RPC over HTTP (`POST`). The MCP client handles `initialize` and `tools/list` for you; you only call tools.

### Tools

The server exposes only the tools the key can use. Full list:

| Tool                  | Scope | What it does                                                           |
| --------------------- | ----- | ---------------------------------------------------------------------- |
| `get_exchange_status` | `pub` | Health check. Returns `{ "status": "ok" }` when healthy.               |
| `get_time`            | `pub` | Server time in Unix milliseconds (UTC).                                |
| `get_instruments`     | `pub` | All instruments visible to this key, with default + maximum leverage.  |
| `get_instrument`      | `pub` | One instrument by id.                                                  |
| `get_ticker`          | `pub` | Mark / index / fair / last / 24h stats for an instrument.              |
| `get_tickers`         | `pub` | All tickers in one call.                                               |
| `get_orderbook`       | `pub` | Bids + asks (price + USDT quantity) for an instrument.                 |
| `get_balances`        | `ro`  | `available`, `on_hold`, `unrealized_pnl` in USDT.                      |
| `get_positions`       | `ro`  | Open positions: side, value, entry, margin, leverage, liq price, uPnL. |
| `get_permissions`     | `ro`  | The effective scope and limits on the current key.                     |
| `place_order`         | `rw`  | Place a market or limit order, sized in USDT.                          |
| `change_leverage`     | `rw`  | Set leverage for an instrument (cross margin).                         |
| `cancel_all_orders`   | `rw`  | Cancel all active orders for an instrument.                            |

#### Tool schemas

Inputs and outputs follow JSON Schema. For `place_order`:

{% code title="place\_order schema" %}

```json
{
  "name": "place_order",
  "arguments": {
    "instrument_id": "BTC_USDT_PERPETUAL",
    "side": "buy" | "sell",
    "type": "market" | "limit",
    "amount": 50,
    "price": 80500
  }
}
```

{% endcode %}

`price` is required for `limit`, optional for `market`. `amount` is **USDT quoted volume**.

Response:

{% code title="place\_order response" %}

```json
{
  "order_id": "27da84bc-30dd-461f-a333-651ce248082a",
  "avg_price": "80525.4",
  "amount": "49.9",
  "filled": "49.9",
  "remaining": "0"
}
```

{% endcode %}

If a `rw` key would exceed a configured limit (`leverage`, `order_quoted_volume`, instrument allowlist), the call returns an error before the matching engine sees it.

### End-to-end example: plug Claude Code into AgentDex

1. **Create a tightly-scoped key.** From the web UI or the Auth API:

   <pre class="language-bash" data-title="Create a tightly-scoped key"><code class="lang-bash">curl -X POST -H "Authorization: Bearer $SESSION" \
     -H "Content-Type: application/json" \
     https://agentdex.xyz/api/keychain/api-keys \
     -d '{
       "label": "my-claude-agent",
       "permissions": {
         "scope": "rw",
         "expiration": "2026-12-31T00:00:00Z",
         "instruments": ["BTC_USDT_PERPETUAL"],
         "leverage_gte": 10, "leverage_lte": 20,
         "order_quoted_volume_gte": "1",
         "order_quoted_volume_lte": "100"
       }
     }'
   </code></pre>

   The response returns `key` once. Store it.
2. **Add the MCP server to Claude Code:**

   <pre class="language-bash" data-title="Add the MCP server to Claude Code"><code class="lang-bash">claude mcp add agentdex \
     --url https://agentdex.xyz/mcp \
     --header "X-Api-Key=$AGENTDEX_KEY"
   </code></pre>
3. **Ask the agent:** *"On AgentDex, what's BTC trading at, and what's my current position? Then short $50 if mark is above $80 000."*

   The agent calls `get_ticker`, `get_positions`, then `place_order` with `amount=50, side=sell, type=market` — all bounded by the key's limits.
4. **Revoke when done:**

   <pre class="language-bash" data-title="Revoke the key"><code class="lang-bash">curl -X DELETE -H "Authorization: Bearer $SESSION" \
     https://agentdex.xyz/api/keychain/api-keys/$SHORT_TOKEN
   </code></pre>

### Recommended patterns for agentic use

* **One key per agent.** Clean revocation if the agent misbehaves.
* **Tight limits on every key.** Allowlist one instrument, set `order_quoted_volume_lte` to your maximum acceptable single trade.
* **Use `get_permissions` first.** Don't trust an agent's assumption about what it can do — read the actual scope on the key.
* **Mirror trade history into your own log.** The on-chain canonical log will be public after Phase 4 of [Validator and verifiability](/agentdex-docs/under-the-hood/validator-and-verifiability.md), but you should have your own copy too.

### Differences vs. REST

* **One-shot semantics.** MCP tools return on completion; no long-lived subscription. For live updates, use WebSocket alongside MCP.
* **Simpler auth.** One header, one URL — no JWT lifecycle.
* **Schema-driven.** The agent introspects available tools; you don't hand-write a tool-spec.

### Roadmap

Planned improvements to the MCP surface:

* **Streaming tools** — push notifications, fills, liquidation alerts as MCP-native events.
* **More instruments** — additional perpetual pairs and (later) spot.
* **Sub-account / multi-account scoping** on a single key.
* **Deeper read tools** — historical fills, order history, account stats.

If you're building on the MCP surface and want a specific tool, send a request — that's how priority is set.
