Skip to main content
Glama
SakethSripada

KalTrader MCP

README.md
# KalTrader

Let Claude, ChatGPT, or any other MCP client use your Kalshi account.

Ask your assistant things like:

> Put a resting buy order for 20 contracts at 40 cents on that market.

> What are the best odds on Kalshi for the Fed cutting rates in September?

> Look at my open positions and tell me which ones are underwater.

> Paper trade $50 across the best events right now, then check on it tomorrow.

Not affiliated with Kalshi.

## Setup

You need [Node.js 22 or newer](https://nodejs.org). 

Run the below command in your terminal.
```
npx kaltrader setup
```

That opens a page in your browser. Pick the demo exchange or the real one, paste your Kalshi API key, and click the app you want to connect. Restart that app and you are done.

To get a Kalshi API key: go to your [Kalshi account settings](https://kalshi.com/account/profile), open the API keys section, and create a key. Kalshi shows you the key ID and downloads a private key file once. You need both.

The setup page can connect these automatically:

- Claude Desktop
- Claude Code
- Cursor
- Windsurf

For anything else, the page gives you a block of JSON to paste into that app's config.

## Where your key goes

Your Kalshi private key never goes into a chat, a config file, or over the internet. The setup page runs on your own machine and talks to nothing but the process that started it.

The key is encrypted with AES-256-GCM and written to `~/.kaltrader/credentials.enc`. The key that decrypts it is held by your operating system:

| Platform | Where |
| --- | --- |
| macOS | Keychain |
| Windows | DPAPI, tied to your Windows login |
| Linux | The secret service, through `secret-tool` |

If none of those exist, which mostly means a server or a container, the encryption key falls back to a file only your user account can read. Setup and `doctor` both tell you when that happens.

Before saving anything, setup makes a real signed request to Kalshi. If Kalshi rejects the key, nothing is stored. That catches the most common mistake, which is using a demo key against production.

To remove everything from your machine:

```
npx kaltrader logout
```

That deletes the local copy. Delete the key in Kalshi's dashboard too if you are done with it.

## Guardrails

You are giving an AI assistant the ability to spend your money. A few settings limit how much damage a misunderstanding can do.

**Start on the demo exchange.** It works the same way with play money. This is the default.

```
npx kaltrader config --environment demo
```

**Read-only mode.** The assistant can see markets and your account but cannot place, change, or cancel orders. Write endpoints are not just blocked, they are not offered.

```
npx kaltrader config --read-only true
```

**A per-order dollar limit.** Any single order risking more than this is refused before it leaves your machine. For a buy, the risk is the price paid. For a sell, it is the rest of the dollar, because Kalshi contracts settle at either $1.00 or $0.00.

```
npx kaltrader config --max-order-usd 25
```

None of this replaces watching what your assistant does. Check your open orders on Kalshi.

## Paper trading

Simulated portfolios, priced off the live exchange. Nothing reaches Kalshi: no order is placed, no money moves, and the position exists only in `~/.kaltrader/paper.json`.

> Paper trade $50. Find three markets you think are mispriced and put money on them.

> How is my paper portfolio doing?

This is not Kalshi's demo exchange. Demo needs its own account and has its own thin, separate order book, so a strategy that works there tells you little. Paper trading reads the real production book, fills against real resting orders, charges Kalshi's usual fees, and pays out when the real market settles. The only fiction is that your order was never actually there.

Four tools, always loaded:

- `kalshi_paper_order` places a simulated order. Market orders walk the real book and pay the taker fee. Limit orders fill whatever crosses and leave the rest resting.
- `kalshi_paper_portfolio` values everything against live prices: cash, each position marked at what it could be sold for, realized and unrealized P&L, fees, and total return.
- `kalshi_paper_cancel` cancels a resting order.
- `kalshi_paper_reset` starts a portfolio over with a new balance, or deletes it.

Name a portfolio to run several at once and compare them:

> Run the same $100 two ways: one paper portfolio buying favourites, one buying longshots.

Nothing runs in the background, because an MCP server has nowhere to run it. A portfolio catches up when you look at it: asking for the portfolio is what settles finished markets, fills resting orders, and re-marks positions. Ask your assistant to check in every morning and you get the same effect.

What is simulated honestly: fills against real book depth, Kalshi's 7% trading fee on taker fills, cash reserved against resting orders, positions netting through zero when you flip sides, and settlement at $1.00 or $0.00. What is not: queue position, trades that happen between two checks, per-series fee schedules, and the fact that your own order would have moved the book.

Positions are marked at the bid, which is what you could actually sell for, not the midpoint. On a wide spread that looks pessimistic. It is the honest number.

Read-only mode does not disable this, and neither does the per-order limit. Both exist to stop real money moving, and paper trading never moves any. To switch it off entirely:

```
npx kaltrader config --paper false
```

## Toolsets

Kalshi has 137 endpoints. Loading all of them at once costs your assistant about 40,000 tokens before it has done anything, so related endpoints are grouped and only four groups are on by default.

```
npx kaltrader toolsets
```

```
  on   markets           23  Markets, events, series, order books, trades, candlesticks, and search.
  on   exchange           4  Exchange status, trading hours, and fee change announcements.
  on   portfolio         14  Balance, positions, fills, settlements, deposits, withdrawals, and subaccounts.
  on   orders            10  Place, amend, decrease, and cancel orders, plus queue positions.
  off  order-groups       7  Order groups, which cap total exposure across a set of orders.
  off  historical         8  Settled markets, trades, fills, orders, and positions older than the live cutoff.
  off  live-data          5  Live sports scores, game stats, and milestone data attached to markets.
  off  multivariate       4  Multivariate event collections and combined-outcome markets.
  off  communications    18  Requests for quote, quotes, and block trade proposals.
  off  account            8  API keys, rate limit tiers, and endpoint costs.
  off  fcm                2  Futures commission merchant orders and positions.
  off  perps             34  Perpetual futures: margin markets, orders, positions, funding, and risk.
```

Turn on what you need, or all of it:

```
npx kaltrader config --toolsets markets,orders,portfolio,perps
npx kaltrader config --toolsets all
```

Switching a group off does not put those endpoints out of reach. Four tools are always loaded and cover the whole API:

- `kalshi_list_endpoints` searches all 137 by keyword.
- `kalshi_describe_endpoint` shows the fields one endpoint takes.
- `kalshi_call_endpoint` calls any of them.
- `kalshi_server_info` reports how the server is set up, which is the first thing to check when something fails.

There is also `kalshi_stream_collect`, which connects to Kalshi's WebSocket feed, listens for a few seconds, and returns what arrived. Useful for watching an order book move. It is a one-shot capture, since a tool call cannot stay subscribed.

Every endpoint is listed in [docs/endpoints.md](docs/endpoints.md).

## ChatGPT

ChatGPT connectors only talk to public HTTPS addresses. They cannot reach your computer, so this takes an extra step.

Run the server over HTTP:

```
npx kaltrader http
```

It prints a connection token. Then put it behind a public address, for example with [cloudflared](https://developers.cloudflare.com/cloudflare-tunnel/):

```
cloudflared tunnel --url http://127.0.0.1:8765
```

Give ChatGPT the HTTPS address it prints with `/mcp` on the end, and the token as a bearer header. If ChatGPT will only accept a URL, put the token in the path instead: `https://your-tunnel/<token>/mcp`.

While that tunnel is open, anyone with the address and the token can trade on your account. Turn it off when you are finished. Read-only mode is a sensible pairing here.

## Commands

```
kaltrader                    Run the server over stdio. This is what AI apps call.
kaltrader setup              Open the browser page to save a key and connect an app.
kaltrader http [--port N]    Run the server over HTTP, for remote clients.
kaltrader doctor             Check the saved key, the config, and the connection to Kalshi.
kaltrader config [flags]     Show or change settings.
kaltrader toolsets           List the endpoint groups.
kaltrader install <app>      Add the server to an app's config file.
kaltrader logout             Delete every saved key from this computer.
```

When something is not working, start with `doctor`. It prints where your settings live, which storage backend holds your key, and whether Kalshi accepts it right now.

## Environment variables

Useful for containers and CI, where there is no keychain and no browser.

| Variable | Does what |
| --- | --- |
| `KALSHI_API_KEY_ID` | API key ID. Skips the keystore entirely. |
| `KALSHI_PRIVATE_KEY` | The private key itself. Escaped `\n` is fine. |
| `KALSHI_PRIVATE_KEY_FILE` | Path to the private key file, instead of the above. |
| `KALTRADER_ENVIRONMENT` | `demo` or `production`. |
| `KALTRADER_TOOLSETS` | Comma-separated list, or `all`. |
| `KALTRADER_READ_ONLY` | `true` to block every write. |
| `KALTRADER_MAX_ORDER_USD` | Per-order dollar limit. |
| `KALTRADER_PAPER_TRADING` | `false` to drop the paper trading tools. |
| `KALTRADER_HOME` | Where settings live. Defaults to `~/.kaltrader`. |
| `KALTRADER_LOG_LEVEL` | `debug`, `info`, `warn`, or `error`. |

## How it is built

The tool list is generated from Kalshi's own OpenAPI specs, which are checked into [specs/](specs/). A build step turns every operation into an MCP tool with a JSON Schema for its arguments. Nothing is hand-written per endpoint, so when Kalshi adds something, refreshing the spec picks it up.

Arguments are checked against that schema before a request goes out. A missing required field comes back as a sentence naming the field, rather than a 400 from Kalshi that the assistant has to guess at.

Requests are signed with RSA-PSS over `timestamp + method + path`, which is what Kalshi expects. Every request gets signed when a key is loaded, including public endpoints, because rate limits are per account and unsigned traffic shares a smaller pool.

More detail in [docs/architecture.md](docs/architecture.md) and [docs/security.md](docs/security.md).

## Working on it

```
git clone https://github.com/SakethSripada/KalTraderMCP
cd KalTraderMCP
npm install
npm run build
npm test
```

```
npm run specs:refresh    Re-download Kalshi's API specs
npm run build:spec       Regenerate the tool table from them
npm run typecheck        Types only
```

To point an AI app at your working copy instead of the published package, use `node /path/to/repo/dist/cli.js` as the command.

## A word on risk

Prediction market contracts can settle at zero. An AI assistant will occasionally misread a market, a ticker, or you. Use the demo exchange until you trust what you are seeing, keep the per-order limit low when you switch to real money, and look at your account yourself.

This project is not affiliated with, endorsed by, or connected to Kalshi.

## License

MIT. See [LICENSE](LICENSE).

TDQS

B3.4/5.0

Scored across 60 tools

Disambiguation5/5

Each tool has a clearly distinct resource+action combination. The GET endpoints are differentiated by resource type (markets, events, series, orders, etc.), and write operations (create, amend, cancel, decrease, transfer) are scoped to specific resources. The paper trading tools are explicitly marked as simulated, and the meta tools (list/describe/call endpoint) serve a unique discovery purpose, so there is no meaningful ambiguity.

Naming Consistency4/5

The majority of tools follow a consistent get_* or verb_noun pattern (e.g., kalshi_get_market, kalshi_create_order_v2). However, there are minor deviations: 'kalshi_paper_order' and 'kalshi_paper_portfolio' lack a verb prefix, 'kalshi_stream_collect' reverses the verb, and 'kalshi_intra_exchange_instance_transfer' is a noun phrase. These are few relative to the total and do not significantly impede readability.

Tool Count1/5

With 60 tools, this server far exceeds the well-scoped threshold. Many endpoints could be served by the generic kalshi_call_endpoint or consolidated into parameterized tools. The count is an extreme mismatch for typical tool-set expectations and likely overwhelms an agent.

Completeness5/5

The tool surface is exceptionally complete for the Kalshi trading API, covering market data, order management (create, amend, cancel, decrease, batch), portfolio (balance, positions, fills, settlements), subaccounts, and paper trading. The generic kalshi_call_endpoint ensures that even endpoints without dedicated tools are accessible, leaving no obvious gaps.

Maintenance

ActivitySlowing
ResponsivenessNo issues