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

The Horizon MCP server exposes 105 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]
# or
uv 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 105 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 |
| `market_side` | string | `"yes"` or `"no"` (default: `"yes"`) |

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

#### start_feed

Start a live data feed on the engine. Supports all feed types: Binance WebSocket, Polymarket/Kalshi orderbooks, PredictIt, Manifold, ESPN, NWS, REST JSON path, Chainlink on-chain oracles, and Alpaca stock market data.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `name` | string | required | Feed name (used to query snapshots later) |
| `feed_type` | string | required | `"binance_ws"`, `"polymarket_book"`, `"kalshi_book"`, `"rest"`, `"predictit"`, `"manifold"`, `"espn"`, `"nws"`, `"rest_json_path"`, `"chainlink"`, `"alpaca"` |
| `config_json` | string | `null` | JSON config string for structured feed types |
| `symbol` | string | `null` | Symbol for legacy feeds (e.g., `"btcusdt"` for binance_ws) |
| `url` | string | `null` | URL for REST feeds |
| `interval` | float | `5.0` | Polling interval in seconds |

**Chainlink example:**

```json
{
  "name": "eth_usd",
  "feed_type": "chainlink",
  "config_json": "{\"contract_address\":\"0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419\",\"rpc_url\":\"https://eth.llamarpc.com\"}"
}
```

Returns `{"started": "eth_usd", "feed_type": "chainlink"}` on success.

#### 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.

#### check_feed_health

Check staleness and health of all active feeds.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `stale_threshold` | float | `30.0` | Seconds before a feed is considered stale |

```json
{
  "feeds": {
    "btc": {"name": "btc", "is_stale": false, "age_secs": 2.3, "price": 97234.50, "bid": 97230.00, "ask": 97239.00},
    "eth": {"name": "eth", "is_stale": true, "age_secs": 45.1, "price": 3200.00, "bid": 3199.00, "ask": 3201.00}
  },
  "total_feeds": 2,
  "stale_count": 1,
  "all_stale": false,
  "stale_threshold_secs": 30.0
}
```

#### get_feed_metrics

Get detailed metrics for a specific feed.

| Parameter | Type | Description |
|-----------|------|-------------|
| `name` | string | Feed name |

Returns tick count, latency stats, error count, and uptime for the feed.

#### get_all_feed_metrics

No parameters. Returns metrics for all active feeds.

#### 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 |
| `market_type` | string | `"all"` | `"all"`, `"binary"`, or `"multi"` |

```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

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `market_id` | string | required | Check if YES + NO prices sum to 1.0 |
| `feed_name` | string | `null` | Feed name to check (uses default if null) |

### 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.

### Discovery

#### discover_events

Discover multi-outcome events on Polymarket.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `query` | string | `""` | Search text |
| `limit` | int | `10` | Max results |
| `min_volume` | float | `0.0` | Minimum total volume |

```json
[
  {
    "id": "2024-election",
    "name": "Who wins the 2024 election?",
    "outcome_count": 3,
    "outcomes": [
      {"name": "Trump", "market_id": "trump-win", "yes_price": 0.55},
      {"name": "Biden", "market_id": "biden-win", "yes_price": 0.35}
    ],
    "exchange": "polymarket"
  }
]
```

#### top_markets

Get the highest-volume active markets.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `exchange` | string | `"polymarket"` | `"polymarket"` or `"kalshi"` |
| `limit` | int | `10` | Max results |
| `category` | string | `""` | Category filter |

#### get_market_detail

Get detailed information for a specific market including price history, orderbook, recent trades, and top holders.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `slug_or_id` | string | required | Market slug or condition ID |
| `exchange` | string | `"polymarket"` | `"polymarket"` or `"kalshi"` |

### Wallet Analytics (Polymarket)

All wallet tools use Polymarket's public Data API - no authentication required.

#### get_wallet_trades

Fetch trade history for a wallet address.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `address` | string | - | Wallet address (0x...) |
| `limit` | int | `50` | Max trades |
| `condition_id` | string | `null` | Filter to one market |

#### get_market_trades

Fetch recent trades for a market.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `condition_id` | string | - | Market condition ID |
| `limit` | int | `50` | Max trades |
| `side` | string | `null` | `"BUY"` or `"SELL"` filter |
| `min_size` | float | `0.0` | Minimum USDC size |

#### get_wallet_positions

Fetch open positions for a wallet.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `address` | string | - | Wallet address |
| `limit` | int | `50` | Max positions |
| `sort_by` | string | `"CURRENT"` | TOKENS, CURRENT, INITIAL, CASHPNL, PERCENTPNL, PRICE, AVGPRICE |

#### get_wallet_value

Get total USD value of a wallet's positions.

| Parameter | Type | Description |
|-----------|------|-------------|
| `address` | string | Wallet address |

```json
{"wallet": "0x1234...", "total_value_usd": 12345.67}
```

#### get_wallet_profile

Get public profile for a wallet.

| Parameter | Type | Description |
|-----------|------|-------------|
| `address` | string | Wallet address |

```json
{
  "wallet": "0x1234...",
  "pseudonym": "CryptoTrader",
  "name": "John",
  "bio": "Prediction market enthusiast",
  "x_username": "cryptotrader"
}
```

#### get_top_holders

Get the largest position holders in a market.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `condition_id` | string | - | Market condition ID |
| `limit` | int | `20` | Max holders |

#### analyze_market_flow

Aggregate buy/sell flow analytics for a market.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `condition_id` | string | - | Market condition ID |
| `trade_limit` | int | `500` | Trades to analyze |
| `top_n` | int | `10` | Top buyers/sellers |

```json
{
  "condition_id": "0xabc...",
  "total_trades": 487,
  "buy_volume": 125000.50,
  "sell_volume": 98000.25,
  "net_flow": 27000.25,
  "unique_wallets": 142,
  "top_buyers": [{"wallet": "0x...", "volume": 15000.00}],
  "top_sellers": [{"wallet": "0x...", "volume": 8500.00}]
}
```

### Simulation

#### simulate_portfolio

Run Monte Carlo simulation on the engine's current positions.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `scenarios` | int | `10000` | Number of simulations |
| `seed` | int | `null` | Random seed for reproducibility |

```json
{
  "mean_pnl": 15.20,
  "median_pnl": 12.00,
  "std_dev": 45.30,
  "var_95": -62.50,
  "var_99": -85.10,
  "cvar_95": -71.30,
  "max_loss": -150.00,
  "max_gain": 200.00,
  "win_probability": 0.62,
  "scenarios": 10000
}
```

### Arbitrage

#### execute_arbitrage

Execute an atomic cross-exchange arbitrage trade.

| Parameter | Type | Description |
|-----------|------|-------------|
| `market_id` | string | Market identifier |
| `buy_exchange` | string | Exchange to buy on |
| `sell_exchange` | string | Exchange to sell on |
| `buy_price` | float | Buy leg price |
| `sell_price` | float | Sell leg price |
| `size` | float | Trade size |

Both legs go through the risk pipeline. If the sell leg fails after the buy succeeds, the buy is automatically canceled.

```json
{
  "buy_order_id": "p1",
  "sell_order_id": "p2",
  "market_id": "will-btc-hit-100k",
  "buy_exchange": "kalshi",
  "sell_exchange": "polymarket",
  "buy_price": 0.48,
  "sell_price": 0.52,
  "size": 10.0
}
```

### Quantitative Analytics

#### shannon_entropy

Compute Shannon entropy for a probability estimate.

| Parameter | Type | Description |
|-----------|------|-------------|
| `p` | float | Probability (0-1) |

Returns `{"entropy": 0.934, "probability": 0.65}`.

#### kl_divergence

Compute KL divergence between two probability distributions.

| Parameter | Type | Description |
|-----------|------|-------------|
| `p` | list[float] | True distribution |
| `q` | list[float] | Approximate distribution |

#### hurst_exponent

Compute the Hurst exponent for a price series.

| Parameter | Type | Description |
|-----------|------|-------------|
| `prices` | list[float] | Price series |

Returns `{"hurst": 0.5, "regime": "random walk"}`. Hurst under 0.5 = mean-reverting, over 0.5 = trending.

#### variance_ratio_test

Test for market efficiency using the variance ratio.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `returns` | list[float] | required | Returns series |
| `period` | int | `2` | Holding period |

Returns `{"variance_ratio": ..., "period": 2, "is_efficient": true}`.

#### cornish_fisher_var

Compute Cornish-Fisher Value at Risk and CVaR with skewness/kurtosis correction.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `returns` | list[float] | required | Returns series |
| `confidence` | float | `0.95` | Confidence level |

Returns `{"var": ..., "cvar": ..., "confidence": 0.95, "n_observations": ...}`.

#### prediction_greeks

Compute prediction market Greeks (delta, gamma, theta, vega).

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `price` | float | required | Market price |
| `size` | float | required | Position size |
| `is_yes` | bool | `true` | Yes or No position |
| `t_hours` | float | `24.0` | Hours to expiry |
| `vol` | float | `0.2` | Implied volatility |

Returns `{"delta": ..., "gamma": ..., "theta": ..., "vega": ...}`.

#### deflated_sharpe

Compute the deflated Sharpe ratio p-value to test for backtest overfitting.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `sharpe` | float | required | Observed Sharpe ratio |
| `n_obs` | int | required | Number of observations |
| `n_trials` | int | required | Number of strategies tested |
| `skew` | float | `0.0` | Returns skewness |
| `kurt` | float | `3.0` | Returns kurtosis |

Returns `{"p_value": ..., "is_significant": true, "bonferroni_alpha": ...}`.

#### signal_diagnostics

Run diagnostic tests on a signal (information coefficient, half-life, Hurst).

| Parameter | Type | Description |
|-----------|------|-------------|
| `predictions` | list[float] | Model predictions |
| `outcomes` | list[float] | Actual outcomes |

Returns `{"ic": ..., "half_life": ..., "hurst": ...}`.

#### market_efficiency_test

Test whether a price series is efficient using variance ratio and Hurst exponent.

| Parameter | Type | Description |
|-----------|------|-------------|
| `prices` | list[float] | Price series |

Returns `{"variance_ratio": ..., "hurst": ..., "is_efficient": true}`.

#### stress_test

Run stress test Monte Carlo on the engine's current positions.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `n_simulations` | int | `10000` | Number of scenarios |
| `seed` | int | `null` | Random seed |

Returns error if no open positions, otherwise returns VaR, CVaR, and scenario results.

### Stock Hedging

#### hedge_analysis

Compute hedge ratio, effectiveness, basis risk, and sensitivities between a spot and hedge instrument.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `spot_prices` | list[float] | required | Spot price series |
| `hedge_prices` | list[float] | required | Hedge instrument price series |
| `window` | int | `60` | Rolling window for calculations |
| `position_size` | float | `1.0` | Position size for sensitivity scaling |

```json
{
  "hedge_ratio": 0.85,
  "hedge_effectiveness": 0.72,
  "basis_risk": 0.03,
  "current_correlation": 0.91,
  "optimal_hedge_size": 85.0,
  "sensitivities": {
    "delta": 0.85,
    "gamma": 0.02,
    "cross_gamma": 0.01,
    "correlation_sensitivity": 0.15
  }
}
```

#### hedge_scenario_analysis

Run scenario analysis showing P&L under various spot price moves for a hedged position.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `spot_position` | float | required | Spot position size |
| `spot_price` | float | required | Current spot price |
| `hedge_position` | float | required | Hedge position size |
| `hedge_price` | float | required | Current hedge price |
| `spot_moves` | list[float] | `[-0.20,...,0.20]` | Spot price moves to simulate |
| `correlation` | float | `0.8` | Spot-hedge correlation |
| `hedge_vol` | float | `0.2` | Hedge instrument volatility |
| `spot_vol` | float | `0.2` | Spot instrument volatility |

Returns a list of scenario outcomes with `spot_move_pct`, `hedge_move_pct`, `portfolio_pnl`, `unhedged_pnl`, and `hedge_benefit`.

#### multi_ticker_hedge

Find optimal multi-ticker hedge weights using OLS with Cholesky decomposition.

| Parameter | Type | Description |
|-----------|------|-------------|
| `spot_returns` | list[float] | Spot instrument returns |
| `hedge_returns_matrix` | list[list[float]] | Returns matrix (one row per hedge instrument) |
| `tickers` | list[str] | Hedge instrument tickers |

#### hedge_cost_summary

Get hedge trading cost summary from the running engine. No parameters.

### Account Management

#### horizon_setup

Create a Horizon account and generate an SDK API key. Tries login first (existing user), then signup. Saves the encrypted key to `~/.horizon/credentials.json`.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `email` | string | required | Email address |
| `password` | string | `""` | Account password. Prefers `HORIZON_PASSWORD` env var (recommended to avoid log exposure). |
| `name` | string | `""` | Display name |

<Warning>
The full API key is never returned in the response. Only the prefix is shown. The key is saved encrypted to disk.
</Warning>

```json
{
  "status": "ok",
  "prefix": "hz_sdk_a1b2c3d",
  "credentials_path": "/home/user/.horizon/credentials.json",
  "message": "SDK key saved (encrypted) to /home/user/.horizon/credentials.json. Key prefix: hz_sdk_a1b2c3d..."
}
```

#### horizon_login

Login to an existing Horizon account and generate a new SDK key. Saves the encrypted key to `~/.horizon/credentials.json`. Only the key prefix is returned.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `email` | string | required | Email address |
| `password` | string | `""` | Account password. Prefers `HORIZON_PASSWORD` env var. |

#### horizon_key_status

Check if Horizon SDK credentials are configured. Reports whether a key is set via environment variable or saved credentials file. No parameters.

```json
{
  "has_env_key": false,
  "has_saved_key": true,
  "active_source": "file",
  "prefix": "hz_sdk_a1b2c3d",
  "credentials_path": "/home/user/.horizon/credentials.json"
}
```

## 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.
