---
title: "MCP Server"
description: "Run Horizon as an MCP server for Claude Code, Cursor, Windsurf, VS Code, and Claude Desktop."
icon: "server"
---

The Horizon MCP server exposes 18 trading tools and 2 context resources via the [Model Context Protocol](https://modelcontextprotocol.io). Any MCP-compatible client can connect and trade prediction markets through natural language.

## Installation

```bash
pip install horizon-sdk[mcp]
```

This installs the `mcp` package alongside Horizon. The server is available as both a module and a console script:

<CodeGroup>
```bash Module
python -m horizon.mcp
```

```bash Console script
horizon-mcp
```

```bash HTTP transport
python -m horizon.mcp --http
```
</CodeGroup>

## Architecture

The server lazily initializes a singleton Engine on the first tool call. Configuration comes from environment variables — no config files needed.

The MCP server (`horizon.mcp_server`) exposes 18 tools and 2 resources via FastMCP. It delegates to `horizon.tools` which manages a singleton Engine backed by the Rust core.

## Tools Reference

### Portfolio & Status

#### engine_status

Get the engine's current state.

```json
{
  "running": true,
  "kill_switch_active": false,
  "kill_switch_reason": null,
  "open_orders": 3,
  "active_positions": 2,
  "total_realized_pnl": 12.45,
  "total_unrealized_pnl": -3.20,
  "daily_pnl": 9.25,
  "uptime_secs": 3600
}
```

#### list_positions

Returns all open positions.

```json
[
  {
    "market_id": "will-btc-hit-100k",
    "side": "yes",
    "size": 25.0,
    "avg_entry_price": 0.55,
    "realized_pnl": 0.0,
    "unrealized_pnl": 2.50,
    "exchange": "polymarket"
  }
]
```

#### list_open_orders

Parameters: `market_id` (optional) — filter by market.

#### list_recent_fills

Parameters: `limit` (default: 20) — number of fills to return.

### Trading

#### submit_order

Place a limit order on the engine's configured exchange.

| Parameter | Type | Description |
|-----------|------|-------------|
| `market_id` | string | Market identifier |
| `side` | string | `"buy"` or `"sell"` |
| `price` | float | Probability price (0–1) |
| `size` | float | Number of contracts |

Returns the order ID on success, or `{"error": "..."}` on failure.

```json
{
  "order_id": "p1",
  "market_id": "will-btc-hit-100k",
  "side": "buy",
  "price": 0.55,
  "size": 10.0
}
```

#### cancel_order

Parameters: `order_id` — the ID to cancel.

#### cancel_all_orders

Cancels all open orders across all exchanges. Returns `{"canceled_count": N}`.

#### cancel_market_orders

Parameters: `market_id` — cancel all orders for this market.

### Risk Management

#### activate_kill_switch

Parameters: `reason` — why you're activating it.

<Warning>
This is an emergency stop. It immediately cancels all open orders across all exchanges. Use only in emergencies.
</Warning>

#### deactivate_kill_switch

No parameters. Resumes normal trading.

### Market Data

#### get_feed_snapshot

Parameters: `name` — feed name (as configured in the engine).

```json
{
  "name": "btc",
  "price": 97234.50,
  "bid": 97230.00,
  "ask": 97239.00,
  "volume_24h": 1234567.89,
  "source": "binance_ws",
  "timestamp": 1708185600.123
}
```

#### list_all_feeds

No parameters. Returns all active feed snapshots.

#### discover_markets

Search for prediction markets on an exchange.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `exchange` | string | `"polymarket"` | `"polymarket"` or `"kalshi"` |
| `query` | string | `""` | Search text |
| `limit` | int | `10` | Max results |

```json
[
  {
    "id": "will-btc-hit-100k",
    "name": "Will BTC hit $100k by end of 2025?",
    "slug": "will-btc-hit-100k",
    "exchange": "polymarket",
    "expiry": "2025-12-31T23:59:59Z",
    "active": true
  }
]
```

### Sizing & Analysis

#### kelly_sizing

Compute Kelly-optimal position size.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `prob` | float | — | Your estimated probability (0–1) |
| `price` | float | — | Current market price (0–1) |
| `bankroll` | float | `1000.0` | Total capital |
| `fraction` | float | `0.25` | Kelly fraction (0.25 = quarter Kelly) |
| `max_size` | float | `100.0` | Hard cap on position size |

```json
{
  "optimal_size": 75.0,
  "edge": 0.15,
  "prob": 0.65,
  "price": 0.50,
  "bankroll": 1000.0,
  "fraction": 0.25
}
```

#### check_parity

Parameters: `market_id` — check if YES + NO prices sum to 1.0.

### Contingent Orders

#### add_stop_loss / add_take_profit

| Parameter | Type | Description |
|-----------|------|-------------|
| `market_id` | string | Market identifier |
| `side` | string | `"yes"` or `"no"` |
| `order_side` | string | `"buy"` or `"sell"` |
| `size` | float | Number of contracts |
| `trigger` | float | Trigger price |

#### list_contingent_orders

Returns all pending stop-loss and take-profit orders.

## Resources

The server exposes two MCP resources for context injection:

| URI | Description |
|-----|-------------|
| `horizon://status` | Engine status as JSON |
| `horizon://positions` | Current positions as JSON |

Clients can attach these as context when starting a conversation.

## Error Handling

Every tool returns `{"error": "..."}` on failure instead of crashing the server. Common errors:

| Error | Cause |
|-------|-------|
| `"risk rejection: ..."` | Order blocked by risk pipeline |
| `"order not found: ..."` | Invalid order ID for cancel |
| `"feed not found: ..."` | Unknown feed name |
| `"unknown exchange: ..."` | Invalid exchange in discover |

## Testing

Verify the server starts and responds to the MCP initialize handshake:

```bash
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}' | python -m horizon.mcp
```

You should see a JSON-RPC response with the server's capabilities and tool list.
