Kalshi MCP Server

A simple MCP server to interact with prediction market Kalshi

kalshi-mcp-server

An mcp server that allows AI to operate on the prediction market, Kalshi

Implemented Tools

  • get_tags_for_series_categories
    • Calls Kalshi public endpoint: GET /search/tags_by_categories
    • No API key required
  • get_balance
    • Calls Kalshi private endpoint: GET /portfolio/balance
    • Requires API key authentication (KALSHI_API_KEY_ID + KALSHI_API_KEY_PATH)
  • get_subaccount_balances
    • Calls Kalshi private endpoint: GET /portfolio/subaccounts/balances
    • Requires API key authentication (KALSHI_API_KEY_ID + KALSHI_API_KEY_PATH)
  • create_subaccount
    • Calls Kalshi private endpoint: POST /portfolio/subaccounts
    • No arguments
    • Creates a new subaccount (maximum 32 per user)
    • Returns: subaccount_number (int, 1-32)
    • Requires API key authentication (KALSHI_API_KEY_ID + KALSHI_API_KEY_PATH)
  • get_orders
    • Calls Kalshi private endpoint: GET /portfolio/orders
    • Optional arguments:
      • ticker (string; market ticker)
      • event_ticker (string; comma-separated event tickers, maximum 10)
      • status (string: resting|canceled|executed)
      • min_ts/max_ts (int; unix seconds)
      • limit (int, 1-200)
      • cursor (string)
      • subaccount (int, 0-32)
    • Returns portfolio orders (and optional pagination cursor)
    • Requires API key authentication (KALSHI_API_KEY_ID + KALSHI_API_KEY_PATH)
  • get_order
    • Calls Kalshi private endpoint: GET /portfolio/orders/{order_id}
    • Required arguments:
      • order_id (string; the order identifier)
    • Returns a single order object with all order fields
    • Requires API key authentication (KALSHI_API_KEY_ID + KALSHI_API_KEY_PATH)
  • create_order
    • Calls Kalshi private endpoint: POST /portfolio/orders
    • Required arguments:
      • ticker (string; market ticker)
      • side (string: yes|no)
      • action (string: buy|sell)
    • Optional arguments:
      • client_order_id (string; caller-specified order ID)
      • count (int, >=1; contract quantity)
      • count_fp (string; fixed-point contract count)
      • yes_price (int, 1-99; price in cents)
      • no_price (int, 1-99; price in cents)
      • yes_price_dollars (string; yes price in dollars)
      • no_price_dollars (string; no price in dollars)
      • expiration_ts (int; unix timestamp for order expiry)
      • time_in_force (string: fill_or_kill|good_till_canceled|immediate_or_cancel)
      • buy_max_cost (int; maximum cost in cents)
      • sell_position_floor (int; deprecated, only 0 allowed if set)
      • post_only (boolean)
      • reduce_only (boolean)
      • self_trade_prevention_type (string: taker_at_cross|maker)
      • order_group_id (string)
      • cancel_order_on_pause (boolean)
      • subaccount (int, 0-32)
    • Returns created order details
    • Requires API key authentication (KALSHI_API_KEY_ID + KALSHI_API_KEY_PATH)
  • cancel_order
    • Calls Kalshi private endpoint: DELETE /portfolio/orders/{order_id}
    • Required arguments:
      • order_id (string; the order identifier)
    • Optional arguments:
      • subaccount (int, 0-32)
    • Returns the cancelled order object and the number of contracts reduced (reduced_by, reduced_by_fp)
    • Requires API key authentication (KALSHI_API_KEY_ID + KALSHI_API_KEY_PATH)
  • get_positions
    • Calls Kalshi private endpoint: GET /portfolio/positions
    • Optional arguments:
      • cursor (string)
      • limit (int, 1-1000; defaults to 100)
      • count_filter (string; comma-separated from position and/or total_traded)
      • ticker (string; market ticker)
      • event_ticker (string; comma-separated event tickers, maximum 10)
      • subaccount (int, 0-32)
    • Returns portfolio positions with market_positions and event_positions arrays, plus pagination cursor
    • Requires API key authentication (KALSHI_API_KEY_ID + KALSHI_API_KEY_PATH)
  • get_categories
    • Calls Kalshi public endpoint: GET /search/tags_by_categories
    • Returns only the category names
    • No API key required
  • get_tags_for_series_category
    • Calls Kalshi public endpoint: GET /search/tags_by_categories
    • Requires one argument: category (exact category name)
    • Returns tags for the selected category
    • No API key required
  • get_series_list
    • Calls Kalshi public endpoint: GET /series
    • Optional arguments:
      • category (string)
      • tags (string)
      • cursor (string)
      • limit (int, 1-1000)
      • include_product_metadata (boolean)
      • include_volume (boolean)
    • Returns typed series objects from Kalshi response
    • Logs warning/error details when response fields have unexpected types/shapes
    • No API key required
  • get_series_tickers_for_category
    • Pages Kalshi public endpoint: GET /series
    • Required arguments:
      • category (string)
    • Optional arguments:
      • tags (string)
      • limit (int, 1-1000; defaults to 1000)
      • max_pages (int, 1-10000; defaults to 1000)
    • Returns only ticker values across all pages
    • No API key required
  • get_markets
    • Calls Kalshi public endpoint: GET /markets
    • Optional arguments:
      • cursor (string)
      • limit (int, 1-1000)
      • status (string; Kalshi docs list values like unopened|open|paused|closed|settled)
      • tickers (string; comma-separated market tickers)
      • event_ticker (string; comma-separated event tickers)
      • series_ticker (string)
      • mve_filter (string: only|exclude)
      • min_created_ts/max_created_ts (int; unix seconds)
      • min_updated_ts (int; unix seconds)
      • min_close_ts/max_close_ts (int; unix seconds)
      • min_settled_ts/max_settled_ts (int; unix seconds)
    • Returns typed markets from Kalshi response
    • No API key required
  • get_open_markets_for_series
    • Pages Kalshi public endpoint: GET /markets
    • Required arguments:
      • series_ticker (string)
    • Optional arguments:
      • limit (int, 1-1000; defaults to 1000)
      • max_pages (int, 1-10000; defaults to 1000)
    • Forces status=open and returns all markets across all pages
    • No API key required
  • get_open_market_titles_for_series
    • Pages Kalshi public endpoint: GET /markets
    • Required arguments:
      • series_ticker (string)
    • Optional arguments:
      • limit (int, 1-1000; defaults to 1000)
      • max_pages (int, 1-10000; defaults to 1000)
    • Forces status=open and returns only ticker, title, subtitle, yes_sub_title, no_sub_title for each market across all pages
    • No API key required

Configuration

  • KALSHI_API_BASE_URL
    • Default: https://api.elections.kalshi.com/trade-api/v2
  • KALSHI_TIMEOUT_SECONDS
    • Default: 10
  • KALSHI_API_KEY_ID
    • Required for authenticated/private endpoints (for example get_balance)
  • KALSHI_API_KEY_PATH
    • Required for authenticated/private endpoints
    • Path to your Kalshi API private key PEM file
  • .env
    • load_settings() reads a local .env file from the repo root and loads variables when they are not already set in the environment

Run as MCP stdio server

  • Command (installed/editable):
    • python3 -m pip install -e .
    • python3 -m kalshi_mcp.server
  • Command (no install):
    • PYTHONPATH=src python3 -m kalshi_mcp.server
  • Transport:
    • JSON-RPC 2.0 over newline-delimited JSON on stdin/stdout

Development

  • Run unit tests (unittest):
    • python3 -m unittest discover -s tests -p 'test_*.py'
  • Run unit tests (pytest):
    • Install dev deps: python3 -m pip install -r requirements-dev.txt
    • Then: python3 -m pytest -q

Related Servers