PokerDataGet an API key
Menu

LLM tools & MCP

The API is designed to drop into AI-agent tooling — here's the shape that works.

The preflop ranges API is plain GET + JSON, CORS-open, and key-authenticated with a single header — which makes it a one-liner to expose as an LLM tool call or behind an MCP (Model Context Protocol) server. The free discovery endpoints even let an agent explore coverage before you attach a key.

PokerData also hosts an MCP server at POST https://pokerdata.io/api/mcp — stateless Streamable HTTP. Claude signs in with OAuth. Cursor, the npm stdio bridge, and other clients keep using a Bearer pdk_ key. Point any MCP client at the same URL.

Install in one click

Add to Cursor Install in VS Code

Both buttons install the hosted server. The key is optional: without one, the free 6-max NL cash preflop tools work straight away.

  • Cursor sends Authorization: Bearer ${env:POKERDATA_API_KEY}, so set POKERDATA_API_KEY in your environment or edit the key into ~/.cursor/mcp.json.
  • VS Code asks for your pdk_ key when it starts the server. Leave it blank for the free tools.
  • Claude (claude.ai, Claude Desktop, and Claude Code): add https://pokerdata.io/api/mcp as a custom connector and do not paste an API key. Claude discovers the OAuth server, and a paid tool asks you to sign in with the same PokerData account that owns your API plan. The callback is https://claude.ai/api/mcp/auth_callback. Claude Code uses a loopback callback and the same sign-in.
  • Claude Code, free tools only: claude mcp add --transport http pokerdata https://pokerdata.io/api/mcp (leave out --header). Run /mcp in a session when a paid tool asks you to sign in. A pdk_ header still works if you prefer a key.
  • Other clients that cannot do OAuth keep using Authorization: Bearer pdk_YOUR_KEY.

Get a key at pokerdata.io/app/api.

Tool design that works

Give the model three tools per game, mirroring the API's own decomposition, rather than one mega-tool:

  1. get_spots(stack) → /spots — what decisions exist.
  2. get_node(stack, history, hand?) → /node — what actions a position has, and a hand's mixed strategy.
  3. get_range(stack, spot, hand?) → /range — one action's full range.

This matches how models actually reason about poker questions ("what does HJ do vs a UTG open?" → node; "what's the flatting range?" → range) and keeps each response small enough for a context window — for PLO always set minFreq (e.g. 0.05) in the wrapper.

Tool definition
{
  "name": "get_nl_node",
  "description": "GTO preflop decision for 6-max NLHE. history is an underscore path of POSITION_ACTION pairs ending in the position to act, e.g. UTG_60%_HJ.",
  "input_schema": {
    "type": "object",
    "properties": {
      "stack": { "type": "integer", "enum": [20, 30, 40, 50, 70, 100, 150, 200] },
      "history": { "type": "string" },
      "hand": { "type": "string", "description": "Optional 169-grid class, e.g. AKs" }
    },
    "required": ["stack", "history"]
  }
}
Handler
async function getNlNode(input: { stack: number; history: string; hand?: string }) {
  const url = new URL("https://pokerdata.io/api/v1/ranges/nl/v2/node");
  url.searchParams.set("stack", String(input.stack));
  url.searchParams.set("history", input.history);
  if (input.hand) url.searchParams.set("hand", input.hand);
  const res = await fetch(url, {
    headers: { Authorization: `Bearer ${process.env.PDK_KEY}` },
  });
  return res.json();
}

Tips that save agents grief

  • Return errors to the model. The API's 400/404 messages are written to be actionable; a model that sees them self-corrects the path.
  • Encode nothing by hand. URLSearchParams handles % in NLHE sizes and () in PLO hands correctly.
  • Cache by URL. Responses are immutable in practice; an in-memory map keyed by URL removes most latency and rate-limit pressure.
  • Trim PLO. A full PLO node can exceed 100KB of JSON. minFreq=0.05 keeps it model-sized.
  • Discovery for grounding. Fetch /spots once per stack and inject the valid histories into the system prompt.

Hosted MCP

POST https://pokerdata.io/api/mcp exposes low-level solver retrieval plus three coaching-oriented tools:

ToolUse it for
get_startedFirst contact with a new user: the questions to ask (game, format, stakes, goal) and a menu of what the server does. Free, no key.
submit_request, list_my_requestsWhen a question isn't covered, tell the user and offer to file a feature or data request. Free with any key. Same as POST /api/v1/requests.
explain_comboExact postflop action mix, EV evidence, hand/draw/blocker classification, and suit-combo contrasts.
get_board_reportAction frequencies and range composition aggregated across matching solved textures.
compare_strategiesServer-computed deltas between two preflop or postflop contexts.
list_games, get_config, list_spots, get_node, get_rangeLow-level preflop discovery and retrieval, including nl9, plo5, and plo6hu when that data is published. get_config is the table: seats, ante-inclusive stacks, and nlmtt8 open sizes.
list_datasets, get_tree_docs, get_range_metadata, get_exploitabilityShipped tree documentation. Preflop exploitability is not available.
list_postflop_packs, get_postflop_node, get_postflop_rangePostflop discovery, tree walking, and the range for one flop action. Per-flop exploitability is included only where the pack index has a real number.
find_hands, get_hand_results, list_my_sessions, get_session_summary, get_tournament_results, list_my_opponents, get_opponent_notes, get_opponent_limp_rangeThe caller's uploaded hands. If there are none, offer get_upload_link.
get_upload_link, upload_hand_history/upload is the primary hand-upload path. The paste tool is secondary.
enqueue_solve, get_queued_solve, list_queued_solves, list_library_solutionsSolver queue. Requests are recorded and not dispatched.

Responses default to detail: "compact". Use hand or combo whenever the question names a specific holding; the server then returns only that exact strategy. Compact PLO ranges include summary counts plus representative pure and mixed hands, and compact spot lists are searchable and paginated. Request detail: "full" only when every raw hand or combo is necessary.

Postflop packs are solved under two flop bet sizes. list_postflop_packs lists each pack's sizingTrees: the pack id is the 75% pot tree, and <pack>-flop33 is the tree with a 33% pot flop bet (75% on the turn and river). Every postflop tool accepts either id, so compare_strategies can put the two trees side by side on the same board and path.

Efficient coaching workflow

The server sends operating instructions during MCP initialization. Agents should route an exact-hand question to explain_combo, a texture heuristic to get_board_report, and a "how does X change?" question to compare_strategies. This normally produces one compact tool call instead of fetching multiple complete range maps.

Each coaching tool returns the same evidence envelope:

{
  "schemaVersion": "1.0",
  "coverage": {
    "status": "exact",
    "dataClass": "solver",
    "objective": "solver_ev"
  },
  "context": {},
  "result": {},
  "warnings": []
}

Coverage is part of the answer, not optional metadata:

  • exact means the requested node was solved directly.
  • aggregated_report means a board report summarizes the listed solved boards.
  • unsupported is a hard stop. The agent must disclose the gap rather than substituting another format or objective.

Current published data is cash-game preflop, 8-max MTT chip-EV preflop (nlmtt8, 10–300bb, 1bb BB-ante, stack includes the ante), and heads-up cash-style postflop. Convergence is not published. Open sizes, the 40bb 2.2x → 2.19bb decode and the ante are on the NLHE tournament (8-max) page; EV units (sb, baseline fold) and full=1 are in the ranges contract. GET /api/v1/ranges/nlmtt8/config?stack= returns the same table without a key. It does not support ICM, PKO, satellites, 9-max MTT, tournament postflop, or multiway postflop. Supplying format: "mtt" or objective: "chip_ev" is valid only against game: "nlmtt8" preflop. ICM, PKO, satellite, and other antes return a structured unsupported result.

Combo explanation

{
  "pack": "nlhe-srp-btn-vs-bb-50bb",
  "board": "6s 4h 2d",
  "path": ["Check", "Bet 5.5"],
  "combo": "As5s"
}

The response separates calculated facts—frequencies, EV loss, made hand, draws, blockers, and same-rank-class differences—from interpretation. An agent may explain what those facts suggest, but should not claim that a blocker proves why a solver selected an action. Provenance includes the solve generation timestamp, iterations, and exploitability percentage when those values are present in the published pack index.

Board report

{
  "pack": "nlhe-srp-btn-vs-bb-50bb",
  "path": [],
  "filters": {
    "pairedness": "unpaired",
    "suitTexture": "two_tone",
    "connectivity": "connected",
    "highCardClass": "low"
  }
}

Reports use equal weight per solved board and state how many boards matched, were analyzed, or were unavailable at the requested path. A narrow report is evidence about those boards, not a universal poker rule.

Strategy comparison

{
  "domain": "preflop",
  "baseline": {
    "game": "nl",
    "stack": 50,
    "history": "UTG_Fold_HJ_Fold_CO_Fold_BTN",
    "hand": "A5s"
  },
  "comparison": {
    "game": "nl",
    "stack": 100,
    "history": "UTG_Fold_HJ_Fold_CO_Fold_BTN",
    "hand": "A5s"
  }
}

For postflop, each side uses pack, board, path, and optionally combo. Without a combo, the response includes the largest per-combo frequency changes. With a combo, it compares only that exact holding. Preflop EV values are labeled in small blinds (evSb); postflop values are in big blinds (evBb). Postflop bet actions include both their exact chip addition and a pot-normalized comparison key (for example Bet 50% pot) so equivalent sizes can be compared across different pot sizes.

Responses default to detail: "compact". Use hand or combo whenever the question names a specific holding; the server then returns only that exact strategy. Compact PLO ranges include summary counts plus representative pure and mixed hands, and compact spot lists are searchable and paginated. Request detail: "full" only when every raw hand or combo is necessary.

If you use Poker Study AI, there is also a hosted MCP endpoint over your own study data with a Studio token — see pokerstudy.ai/settings/api. The two compose well: PokerData for "what's GTO here", the study MCP for "what did I actually do".