PokerData
Server Details
GTO poker solver data: NLHE/PLO preflop ranges, postflop strategy, EV. 6-max NL preflop free.
- Status
- Healthy
- Uptime
- 99.8% over 22 days
- Last Tested
- Transport
- Streamable HTTP · MCP 2025-11-25
- URL
- Repository
- hft-studio/pokerdata-mcp
- GitHub Stars
- 0
- ChatGPT
- –
- Claude
- –
TDQS
Scored across 32 tools
Several tools have closely related purposes, such as get_range vs get_postflop_range and get_node vs get_postflop_node, which could cause misselection. Descriptions provide guidance (e.g., 'Preferred tool for...'), but the overlap among preflop/postflop range and node tools remains a risk. Multiple listing tools (list_datasets, list_games, list_spots) also have subtle distinctions that require careful reading.
All tool names follow a consistent snake_case verb_noun pattern (e.g., get_range, list_games, compare_strategies, upload_hand_history). The few possessive 'my' forms (list_my_opponents, list_my_requests) remain within the same convention. No mixed casing or vague verb styles are present.
With 32 tools, the surface is heavy for a single server, even though the domain is broad (preflop, postflop, hand history, opponents, requests, queue). Several tools serve niche or non-functional features (e.g., enqueue_solve, get_queued_solve, list_queued_solves for a disabled solver queue), increasing the count without clear justification.
The tool set covers preflop ranges/nodes, postflop solver data, hand history upload/analysis, opponent tracking, and request filing, which are the core workflows. Minor gaps exist, such as no tool to update or delete requests, cancel queued solves, or fetch a single hand's full details, but these are workaroundable and not central.
Available Tools
32 toolscompare_strategiesCompare two strategiesARead-onlyIdempotentInspect
Preferred tool for differences between two preflop or postflop contexts. The server fetches both strategies and returns action-frequency/EV deltas plus the largest postflop combo changes, avoiding two large node payloads.
| Name | Required | Description | Default |
|---|---|---|---|
| anteBb | No | Requested ante in bb. nlmtt8 models a 1bb BB-ante; other positive antes return unsupported coverage. | |
| domain | Yes | Preflop contexts use game/stack/history/hand. Postflop contexts use pack/board/path/combo. | |
| format | No | Requested poker format. "cash" uses the cash trees. "mtt" is supported only for preflop chip-EV against game nlmtt8; ICM, PKO, and satellite remain unsupported. | |
| baseline | Yes | The context deltas are measured from. One side of the comparison. Preflop contexts use game, stack, history and optional hand; postflop contexts use pack, board, path and optional combo. | |
| objective | No | Requested optimization objective. chip_ev is supported for nlmtt8 preflop. ICM, PKO, and satellite return unsupported coverage. | |
| comboLimit | No | Maximum largest-changing combos for aggregate postflop comparisons (default 12, maximum 50) | |
| comparison | Yes | The context deltas are measured to. One side of the comparison. Preflop contexts use game, stack, history and optional hand; postflop contexts use pack, board, path and optional combo. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | No | Both snapshots, the per-action frequency and EV deltas, and the largest combo changes for postflop comparisons. Null when the request is unsupported. |
| context | No | Canonical context the answer belongs to (variant, format, stacks, positions, board, path). Null when the request is unsupported. |
| coverage | No | Whether the request was answered exactly, aggregated, or refused as out of coverage. |
| warnings | No | Caveats that must survive into any answer built on this result. |
| schemaVersion | No | Envelope version, currently "1.0". |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish read-only, idempotent, non-destructive behavior, so the description's job is added context — and it delivers: the server does the fetching for both sides and returns action-frequency/EV deltas plus the largest postflop combo changes. It does not mention unsupported-coverage error behavior, but that is documented per-parameter in the schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, zero waste, with the primary recommendation ('Preferred tool') front-loaded before the explanation of what the server returns.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex two-nested-object comparison tool with an output schema, the description covers what the tool does and what it returns at a high level, leaving type/constraint detail to the thorough schema. Minor gap: it does not flag the cross-side consistency rules (same game, matching hand/combo presence) that make calls fail, though those live in the schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, with enums and nested baseline/comparison objects fully documented in-schema. The description adds no parameter-level meaning (e.g. how baseline vs comparison asymmetry matters, or when comboLimit applies), so baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: computes differences between two preflop or postflop contexts. It also distinguishes itself functionally from the single-node siblings by noting it avoids fetching two large node payloads, though it never names those siblings (get_node / get_postflop_node) directly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'Preferred tool for differences between two preflop or postflop contexts' plus the note that it avoids two large node payloads implicitly tells the agent to use this instead of two separate node fetches. There is no explicit when-not guidance or named alternative, so it falls short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
enqueue_solveRecord a solve requestADestructiveInspect
Record a heads-up postflop solve request. Required: title, board, pot (bb), effective_stack (bb). The job stays pending: solver dispatch and billing are not configured, so this does not start a solve.
| Name | Required | Description | Default |
|---|---|---|---|
| pot | Yes | Starting pot in big blinds. | |
| tags | No | Free-form tags stored with the job. | |
| board | Yes | Board to solve, e.g. "3h 3d 2s". | |
| title | Yes | Label for the job, 1 to 120 characters. | |
| ip_range | No | In-position range in the same weights format. | |
| add_allin | No | Add an all-in branch alongside the bet sizes. | |
| bet_sizes | No | Bet sizes as fractions of the pot, e.g. [0.33, 0.75]. | |
| oop_range | No | Out-of-position range as hand-class weights, e.g. "AA:1,AKs:0.42". Defaults are left to the solver config. | |
| iterations | No | Requested solver iterations, 50 to 5000. | |
| effective_stack | Yes | Effective stack behind, in big blinds. | |
| max_aggressions | No | Raises allowed per street, 1 to 4. |
Output Schema
| Name | Required | Description |
|---|---|---|
| pot | No | Pot in big blinds. |
| board | No | Board for the requested solve. |
| title | No | Title given when the job was recorded. |
| reason | No | Why the job does not start a solve. |
| status | No | "pending", "running", "done", or "failed". |
| dispatch | No | Always "not_configured". |
| queue_id | No | Id for get_queued_solve. |
| createdAt | No | ISO timestamp the job was recorded. |
| solution_id | No | Always null while dispatch is disabled. |
| effective_stack | No | Effective stack in big blinds. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds critical behavioral context beyond the annotations: 'The job stays pending: solver dispatch and billing are not configured, so this does not start a solve.' This is a crucial disclosure that a mutation-like enqueue operation will not actually trigger compute or incur cost, which an agent must know to set correct user expectations. Annotations only say destructiveHint=true and openWorldHint=false, which are less informative here.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tightly written sentences with zero waste. The most important caveat (that this does not start a solve) is front-loaded in the second sentence, and required parameters are listed clearly. Every phrase earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For an 11-parameter mutation tool with an output schema, the description covers the essential behavioral caveat and required fields. However, it doesn't explain what the output schema returns or whether the enqueued job can be retrieved later, which would round out the picture. The core information is present, but a small gap remains around post-enqueue workflow.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, with each parameter documented in the input schema. The description lists the four required parameters (title, board, pot, effective_stack) but adds no extra semantic detail beyond what the schema already provides. Baseline 3 is appropriate when the schema does the heavy lifting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Record a heads-up postflop solve request.' This clearly distinguishes it from read-only siblings like get_queued_solve or list_queued_solves, and the addition of 'heads-up postflop' narrows the scope enough for an agent to know exactly what kind of solve is being enqueued.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage through 'Record a ... solve request' but does not state when to use this tool versus alternatives like list_queued_solves or get_queued_solve. It also doesn't say what happens after enqueueing or how to retrieve the record. No explicit when/when-not guidance is provided.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
explain_comboExplain a postflop comboARead-onlyIdempotentInspect
Preferred tool for exact NLHE postflop hand questions. Returns a canonical context, exact action mix, action EV/loss when available, made-hand and draw classification, blocker facts, and same-rank-class suit comparisons. The server computes evidence; the agent should phrase causality as interpretation.
| Name | Required | Description | Default |
|---|---|---|---|
| pack | Yes | Pack id from list_postflop_packs. Use a sizingTrees packId to pick the tree: the pack id for 75% pot on the flop, or "<pack>-flop33" for 33%. | |
| path | No | Exact childSegment path from get_postflop_node, e.g. ["Check", "Bet 5.5"]. Empty for the root. | |
| board | Yes | Board in spaced form, e.g. "6s 4h 2s" | |
| combo | Yes | Required exact two-card combo, e.g. As5s | |
| anteBb | No | Requested ante in bb. nlmtt8 models a 1bb BB-ante; other positive antes return unsupported coverage. | |
| format | No | Requested poker format. "cash" uses the cash trees. "mtt" is supported only for preflop chip-EV against game nlmtt8; ICM, PKO, and satellite remain unsupported. | |
| objective | No | Requested optimization objective. chip_ev is supported for nlmtt8 preflop. ICM, PKO, and satellite return unsupported coverage. | |
| comparisonLimit | No | Maximum same-rank-class suit comparisons (default 6, maximum 12) |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | No | Recommendation, made-hand and draw classification, blockers, the exact action mix with EV, and same-rank-class suit comparisons. Null when the request is unsupported. |
| context | No | Canonical context the answer belongs to (variant, format, stacks, positions, board, path). Null when the request is unsupported. |
| coverage | No | Whether the request was answered exactly, aggregated, or refused as out of coverage. |
| warnings | No | Caveats that must survive into any answer built on this result. |
| schemaVersion | No | Envelope version, currently "1.0". |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already declare a safe, idempotent, read-only, closed-world read. Beyond that, the description adds real behavioral guidance: EV/loss is only returned 'when available,' and the explicit instruction that the server computes evidence while the agent should phrase causality as interpretation is a meaningful guardrail not captured by structured fields.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences, front-loaded with the primary use case, followed by the return payload and a behavioral caveat. No filler, though the enumerated return list is somewhat dense.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, the description needn't restate return values, and the parameter-level guidance lives in a fully described schema. The added note on framing causality as interpretation rounds out an otherwise complete definition for this domain-specific analysis tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all eight parameters — including the pack/path/board/combo mechanics and the anteBb/format/objective coverage caveats — are already documented in the schema. The description adds no additional parameter-level detail, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource ('explain' a 'postflop combo') and lists exactly what the tool returns (action mix, EV/loss, hand and draw classification, blocker facts, suit comparisons). It is clearly a per-combo solver explanation, but it never names a sibling (e.g. get_hand_results, get_postflop_node, compare_strategies) to differentiate itself.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It positions itself as the 'preferred tool for exact NLHE postflop hand questions,' which implies the usage context, and the schema notes tie parameters back to list_postflop_packs and get_postflop_node. However, there is no explicit when-not and no named alternative for adjacent tasks such as comparing strategies or fetching a whole node.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_handsFind my handsARead-onlyIdempotentInspect
Find hands the account has uploaded. Returns hand_id, session_id, handAt, position, cards, game, board, potType, street lines, and netBb. Solver grade buckets are not filled. If this account has no hands, offer the hosted upload page from get_upload_link (https://pokerdata.io/upload) instead of asking the user to paste histories into chat.
| Name | Required | Description | Default |
|---|---|---|---|
| sort | Yes | Row order: newest first, largest win first, or largest loss first (the default). | biggest_loss |
| limit | Yes | Hands to return, 1 to 50. | |
| filter | No | Hand-level filters, all optional. | |
| game_type | No | Only hands of this game type. Matches hole-card count. | |
| session_id | No | Only hands from this upload session (see list_my_sessions). | |
| table_size | No | Only hands dealt at tables of this many seats. | |
| gto_vs_3bet_bucket | No | Solver grade bucket for hero's action vs a 3-bet. Grades are not computed, so any value matches nothing rather than inventing a frequency. | |
| gto_plo5_rfi_bucket | No | Solver grade bucket for PLO5 raise-first-in. Grades are not computed, so any value matches nothing. |
Output Schema
| Name | Required | Description |
|---|---|---|
| gto | No | Always "not graded": solver grades are not attached. |
| hint | No | Where to upload hands when the account has none. |
| hands | No | Matching hands, sorted as requested. |
| total | No | Matching hands before the limit. |
| gtoNote | No | Why a solver-grade filter matches nothing. |
| returned | No | Hands in this response. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnlyHint, idempotentHint, non-destructive), so the bar is lower. The description still adds real behavioral value: solver grade buckets are not filled, and the explicit fallback when the account has no hands. It omits pagination/truncation behavior and the fact that sort defaults to biggest_loss.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, front-loaded with the core purpose before details, with no filler. The enumeration of return fields is long but useful; the grade-bucket sentence is partly redundant with the schema descriptions.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, return values need not be explained, yet the key behavioral edge cases (empty account, unfilled grade buckets affecting the gto_* filters) are covered. An agent has enough to call it correctly and handle the zero-result path.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents sort, limit, filter fields, and both gto bucket params. The description's note that grade buckets 'are not filled' restates the schema's own caveat rather than adding new meaning. Baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource and scopes it precisely ('hands the account has uploaded'), then enumerates the returned fields (hand_id, session_id, handAt, position, cards, game, board, potType, street lines, netBb). It does not explicitly contrast with the nearest sibling (list_my_sessions, get_hand_results), but the scope is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a concrete routing rule for the empty-result case: offer get_upload_link's hosted upload page rather than asking the user to paste histories into chat. That names an alternative tool and the condition that selects it, though it offers no guidance on when to prefer this over sibling retrieval tools in the normal case.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_board_reportReport on board texturesARead-onlyIdempotentInspect
Preferred tool for board-texture heuristics. Aggregates action frequencies and range/action composition across solved boards in one postflop pack. Results explicitly report sample breadth and use equal weight per board.
| Name | Required | Description | Default |
|---|---|---|---|
| pack | Yes | Pack id from list_postflop_packs. Use a sizingTrees packId to pick the tree: the pack id for 75% pot on the flop, or "<pack>-flop33" for 33%. | |
| path | No | Exact childSegment path from get_postflop_node, e.g. ["Check", "Bet 5.5"]. Empty for the root. | |
| anteBb | No | Requested ante in bb. nlmtt8 models a 1bb BB-ante; other positive antes return unsupported coverage. | |
| format | No | Requested poker format. "cash" uses the cash trees. "mtt" is supported only for preflop chip-EV against game nlmtt8; ICM, PKO, and satellite remain unsupported. | |
| filters | No | Texture filters applied to the pack's solved boards. All optional; omit for every board. | |
| objective | No | Requested optimization objective. chip_ev is supported for nlmtt8 preflop. ICM, PKO, and satellite return unsupported coverage. | |
| boardLimit | No | Maximum matching boards to analyze (default and maximum 50) | |
| representativeLimit | No | Maximum representative boards returned (default 12, maximum 20) |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | No | Action frequencies and range composition aggregated across solved boards, with equal weight per board, plus representative boards. Null when the request is unsupported. |
| context | No | Canonical context the answer belongs to (variant, format, stacks, positions, board, path). Null when the request is unsupported. |
| coverage | No | Whether the request was answered exactly, aggregated, or refused as out of coverage. |
| warnings | No | Caveats that must survive into any answer built on this result. |
| schemaVersion | No | Envelope version, currently "1.0". |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only, idempotent, non-destructive behavior, so the bar is low. The description adds genuinely non-obvious methodology: results report sample breadth and weight each board equally, which matters for interpreting the aggregate. It does not mention rate limits or cost.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, front-loaded with the usage claim followed by the mechanism and the statistical caveat. Every sentence carries information an agent would not get from the schema or annotations.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return-shape explanation is not needed, and annotations carry the safety profile. With 100% schema coverage the remaining burden is light, and the description covers purpose, usage fit, and weighting methodology. It stops short of clarifying how it relates to the node-level siblings for related questions.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all 8 parameters including the nested filters object and the pack/path relationship. The description adds only the scoping phrase "one postflop pack" and no format or syntax detail beyond the schema. Baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific action (aggregates action frequencies and range/action composition) on a specific resource (solved boards in one postflop pack), which distinguishes it from node-level siblings like get_postflop_node. It positions itself as the texture-heuristic tool but never names the sibling it displaces, so an agent still has to infer the boundary.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
"Preferred tool for board-texture heuristics" gives a clear use context: reach for this when aggregating across many boards rather than inspecting one node. The pack parameter also routes the agent to list_postflop_packs. There is no explicit when-not statement or named alternative.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_configGet table configurationARead-onlyIdempotentInspect
Table for one preflop game and stack, in big blinds: seats, stacks, blinds (sb 0.5, bb 1), ante, antePostedBy, stackIncludesAnte, openSizes (first-in raise-to), evUnit, evBaseline. Convergence is not published. stackIncludesAnte is true: the named depth is the starting stack and the 1bb BB ante is posted from it. openSizes at 40bb is open 2.2x (listing 2.2bb; node decodes code 40034 to 2.19bb) and SB 2.8x (2.8bb). 10bb is all-in/fold versus 50bb stacks, so stacks is null there. evs on nodes are small blinds relative to fold. Example: get_config({ game: "nlmtt8", stack: 40 }).
| Name | Required | Description | Default |
|---|---|---|---|
| game | Yes | "nl" = no-limit hold'em 6-max cash (169-grid hands, per-hand EV in small blinds), "nl9" = no-limit hold'em 9-max cash, "nlmtt8" = no-limit hold'em 8-max MTT chip-EV (10–300bb, 1bb BB-ante; Fold/Call/Limp/AI/Open/3B tokens), "nlh8-hydra" = no-limit hold'em 8-max MTT chip-EV with a classic 0.1bb ante from every seat (10, 20, 30, 60bb; same tokens as nlmtt8), "nlh8-icm" = no-limit hold'em 8-max MTT with ICM: one stack table per scenario (near the money, 33 or 35 left of 200, 30 paid; final table, 8 left), uneven stacks, 0.125bb ante from every seat, EVs in tournament dollars; pass scenario (list_games lists them; stack alone works only where one table has that depth); get_node only, "nlhu" = no-limit hold'em heads-up for the title, chip-EV, both players at the stack (1–40bb), 0.125bb ante each, SB on the button; get_node only, "plo" = pot-limit Omaha 6-max cash (4-card), "plo5" = pot-limit Omaha 5-card 6-max (100bb, 1.2bb ante), "plo9" = pot-limit Omaha 9-max cash, "plo6hu" = 6-card Omaha heads-up (BTN vs BB, 100bb). Cash trees are not tournament, ICM, PKO, or satellite solves. nlmtt8, nlh8-hydra and nlhu are chip-EV; only nlh8-icm is ICM. | |
| stack | Yes | Stack depth in big blinds, e.g. 40 |
Output Schema
| Name | Required | Description |
|---|---|---|
| ante | No | Ante in big blinds. |
| game | No | Game id. |
| seats | No | Seats in action order. |
| stack | No | Stack depth in big blinds. |
| units | No | Unit labels for stack, stacks, blinds, ante, openSizes, and evs. |
| blinds | No | Blinds in big blinds. |
| evUnit | No | EV unit, "sb". |
| stacks | No | Starting stacks per seat. Null where the depth is solved against a different stack (10bb all-in/fold versus 50bb). |
| openSizes | No | First-in raise-to sizes, by seat, with label and sizeBb. |
| evBaseline | No | What EV is measured against, "fold". |
| antePostedBy | No | Seat that posts the ante. |
| schemaVersion | No | Payload version, 1. |
| stackIncludesAnte | No | True when the named depth already contains the ante. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only, idempotent, closed-world behavior. The description goes further by disclosing that convergence is unpublished, that stackIncludesAnte changes how the stack depth is interpreted, that openSizes codes like 40034 decode to 2.19bb, and that stacks is null at 10bb versus 50bb.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The paragraph is front-loaded with purpose and fields and has no filler. It is dense and quite specific, with parenthetical examples, but it remains a single block rather than a structured list.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present and annotations covering safety, the description supplies the key data caveats and an example invocation. It could say more about discovery via list_games or when to use this before get_node, but for a config reader it is largely complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the game enum already documents every game variant in detail. The description adds a stack nuance (starting stack and BB ante interaction) and an example call, but it does not add much beyond the schema for choosing game or stack.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening phrase 'Table for one preflop game and stack, in big blinds' names the resource and its dimensions, and the field list clarifies what configuration is returned. It does not explicitly contrast with get_node or list_games, so sibling differentiation is left to the agent.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No sentence states when to call get_config versus get_node or list_games; the only invocation help is an example call. The agent can infer it is for retrieving table configuration, but there are no exclusions or prerequisites.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_exploitabilityGet preflop exploitabilityARead-onlyIdempotentInspect
Preflop exploitability for a game. No preflop dataset publishes exploitability, convergence, or iteration counts. The answer is not available; this tool never fills in a number.
| Name | Required | Description | Default |
|---|---|---|---|
| game | Yes | Preflop game id to report on, e.g. "nl" or "nlmtt8". Any known game answers "not available". |
Output Schema
| Name | Required | Description |
|---|---|---|
| game | No | Game id, echoed. |
| reason | No | Why no number is returned. |
| status | No | Always "not available". |
| dataset | No | Dataset the game maps to, or null when unknown. |
| available | No | Always false. |
| iterations | No | Always null. |
| convergence | No | Always null. |
| exploitability | No | Always null: no figure is published or estimated. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, non-destructive), so the description's job is to add behavior beyond that. It does: it explains why the answer is unavailable (no preflop dataset publishes exploitability, convergence, or iteration counts) and guarantees the tool will never fabricate a number. The only gap is not stating whether the response is an empty result or an explicit "not available" payload.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, front-loaded with the resource and immediately followed by the critical caveat. Every sentence earns its place; nothing is repeated from the schema or annotations.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, the description need not explain return values, and it covers the essential oddity of the tool thoroughly. It is only incomplete in not pointing the agent toward an alternative path for computing exploitability.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and there is a single parameter, whose description already explains that any known game yields "not available". The description adds nothing further about the game id format or valid values. Baseline 3 is appropriate when the schema carries the parameter semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names the resource (preflop exploitability for a given game) and, unusually, its defining behavior: it reports that no dataset publishes this metric rather than a value. An agent can immediately tell this apart from siblings like get_hand_results or compare_strategies. It is slightly weakened by being a noun phrase rather than stating a retrieval action, but the intent is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It implicitly tells the agent not to call this expecting a number ("The answer is not available; this tool never fills in a number"), which is meaningful usage guidance for a dead-end lookup. However, it names no alternative for actually obtaining exploitability (e.g., enqueue_solve), and gives no explicit when-to-use / when-not-to-use framing. Guidance is implied rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_hand_resultsGet my results curveARead-onlyIdempotentInspect
Per-hand cumulative results for a winnings curve. points is [{ hand, bb }], oldest to newest, downsampled. Pass session_id for one session. If this account has no hands, offer the hosted upload page from get_upload_link (https://pokerdata.io/upload) instead of asking the user to paste histories into chat.
| Name | Required | Description | Default |
|---|---|---|---|
| max_points | Yes | Points on the curve after downsampling, 2 to 200. | |
| session_id | No | Only this upload session's hands. Omit for the whole account. |
Output Schema
| Name | Required | Description |
|---|---|---|
| hint | No | Where to upload hands when the account has none. |
| netBb | No | Final cumulative result in big blinds. |
| points | No | Downsampled curve, oldest to newest. |
| totalHands | No | Hands behind the curve. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare the safe read-only/idempotent profile, so the bar is lower. The description still adds real value beyond them: the curve is downsampled, ordered oldest to newest, and formats points as [{ hand, bb }], plus empty-state guidance to route to the upload page.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the purpose, then output shape, then the one parameter, then the empty-state fallback. Dense but every sentence carries information; slightly compressed with the inline backtick notation.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, the description doesn't need to explain returns, yet it usefully summarizes the curve format. Empty-account behavior is covered, so an agent has enough to call and recover from the zero-hands case.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so both parameters are already documented. The description restates session_id scoping ('Pass session_id for one session') but adds no syntax or behavior beyond the schema; the points format described is output, not a parameter. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb+resource: a per-hand cumulative results curve of winnings. It is distinguishable from siblings like get_session_summary or get_tournament_results by the per-hand granularity, though it doesn't explicitly contrast itself with those tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives clear context: pass session_id to scope to one session, and instructs the agent to fall back to the upload page from get_upload_link when the account has no hands. It stops short of explicitly naming alternative tools for aggregated stats.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_nodeGet preflop decision nodeARead-onlyIdempotentInspect
Actions available at a decision node. history is an action path ending in the position about to act, e.g. "UTG_60%_HJ". sizeBb is the raise-to in big blinds and sizePctPot is the percent of the pot after calling (nlmtt8 40bb Open 40034 is 2.19bb; the pack label is 2.2x). evs are small blinds relative to fold. Compact mode returns action totals; add hand for its exact mixed strategy. full=true is full=1: all 169 hold'em hands with explicit 0, and no invented EVs.
| Name | Required | Description | Default |
|---|---|---|---|
| full | No | Hold'em only. When true, each action includes all 169 hands with weight 0 where the bundle omitted the hand. EVs stay only where the bundle scored them. | |
| game | Yes | "nl" = no-limit hold'em 6-max cash (169-grid hands, per-hand EV in small blinds), "nl9" = no-limit hold'em 9-max cash, "nlmtt8" = no-limit hold'em 8-max MTT chip-EV (10–300bb, 1bb BB-ante; Fold/Call/Limp/AI/Open/3B tokens), "nlh8-hydra" = no-limit hold'em 8-max MTT chip-EV with a classic 0.1bb ante from every seat (10, 20, 30, 60bb; same tokens as nlmtt8), "nlh8-icm" = no-limit hold'em 8-max MTT with ICM: one stack table per scenario (near the money, 33 or 35 left of 200, 30 paid; final table, 8 left), uneven stacks, 0.125bb ante from every seat, EVs in tournament dollars; pass scenario (list_games lists them; stack alone works only where one table has that depth); get_node only, "nlhu" = no-limit hold'em heads-up for the title, chip-EV, both players at the stack (1–40bb), 0.125bb ante each, SB on the button; get_node only, "plo" = pot-limit Omaha 6-max cash (4-card), "plo5" = pot-limit Omaha 5-card 6-max (100bb, 1.2bb ante), "plo9" = pot-limit Omaha 9-max cash, "plo6hu" = 6-card Omaha heads-up (BTN vs BB, 100bb). Cash trees are not tournament, ICM, PKO, or satellite solves. nlmtt8, nlh8-hydra and nlhu are chip-EV; only nlh8-icm is ICM. | |
| hand | No | Optional hand/class | |
| stack | Yes | Stack depth in big blinds | |
| detail | No | Response detail. "compact" is the default and removes bulk maps; use "full" only when exact complete data is required. | |
| history | Yes | Action path ending in a position | |
| minFreq | No | Trim per-action ranges | |
| scenario | No | nlh8-icm only: the stack table, e.g. "33left-avg40-big-btn" (list_games lists them). Needed when several tables share the stack. |
Output Schema
| Name | Required | Description |
|---|---|---|
| game | No | Preflop game id, e.g. "nl" or "nlmtt8". |
| hand | No | The requested hand, when one was asked for. |
| hint | No | How to narrow, page, or widen the same query. |
| spot | No | Action path ending in an action, echoed from the request. |
| actor | No | Position to act at this node. |
| stack | No | Stack depth in big blinds. |
| units | No | Unit labels: stack and sizeBb in bb, evs in sb. |
| evUnit | No | EV unit, "sb". |
| actions | No | Actions at the node. |
| history | No | Action path ending in the acting position. |
| version | No | Dataset version where the bundle publishes one. |
| evBaseline | No | What EV is measured against, "fold". |
| schemaVersion | No | Payload version, 1. |
| continuingHands | No | Hand classes that continue past this node. |
| continuingCombos | No | Combos that continue past this node. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The readOnly/idempotent annotations already cover the safety profile, so the description's added value is the return-shape disclosure: compact returns action totals, adding `hand` yields the exact mixed strategy, and full=true fills in all 169 hands with weight 0 rather than fabricated EVs. That is useful, but the prose is terse and partly restates the schema's own `full` description rather than adding new behavioral context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
It is front-loaded with the core purpose and is dense rather than padded, which suits a domain-heavy tool. Some clauses are cryptic without external context ('nlmtt8 40bb Open 40034 is 2.19bb', 'full=true is full=1') and read as notes rather than explanation.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With 8 params, 100% schema coverage, and an output schema, the description covers the remaining burden well: action-path format, EV units (small blinds relative to fold), sizing units, and the compact-vs-hand-vs-full distinction. An agent can call this correctly without further guessing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Coverage is already 100%, so baseline is 3, but the description genuinely adds meaning the schema lacks: the `history` format is illustrated ('UTG_60%_HJ'), sizeBb is defined as raise-to in big blinds, and sizePctPot as percent of pot after calling with a worked example. The `hand` and `minFreq` parameters, however, get no such elaboration.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb+resource: 'Actions available at a decision node,' which tells an agent exactly what is returned. It does not, however, name the sibling get_postflop_node or otherwise state that this covers preflop only (that distinction lives only in the title), so an agent must infer the boundary itself.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied rather than stated: 'add `hand` for its exact mixed strategy' and 'full=true is full=1' hint at when to escalate detail, but there is no explicit when-to-use/when-not and no routing to siblings like get_postflop_node, get_range, or compare_strategies.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_opponent_limp_rangeGet an opponent's limp rangeARead-onlyIdempotentInspect
Shown-hand first-in limp range: 169-class counts of hole cards villains showed after an open limp. Pass position for one seat. Sample is showdown-only. This is not a solver range.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | Yes | Hole-card classes to return, most frequent first, 1 to 169. | |
| position | No | Only limps from these seats. | |
| game_type | No | Only hands of this game type. | |
| session_id | No | Only hands from this upload session. | |
| table_size | No | Only hands dealt at tables of this many seats. | |
| opponent_id | No | Only this opponent's limps (see list_my_opponents). Omit for every tracked villain. |
Output Schema
| Name | Required | Description |
|---|---|---|
| note | No | That the sample is showdown-only and the counts are observations. |
| sample | No | Shown limped hands behind the counts. |
| classes | No | Observed classes, most frequent first. Counts, not solver frequencies. |
| classesByPosition | No | Seat label to that seat's observed classes. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, non-destructive), so the bar is lower; the description nonetheless adds substantive caveats beyond them — the sample is showdown-only and shown-hand only, and it is not a solver-derived range. It does not discuss sample-size thresholds or filtering behavior, but the added context is meaningful.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight clauses, front-loaded with what the tool returns, then the invocation hint, then the two caveats. Telegraphic but every clause carries information; no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present the description need not explain return values, and it supplies the key interpretive caveats (showdown-only, not a solver range). For a 6-parameter filterable analytics tool whose schema is fully documented, this is close to complete, though a note on sparsity/sample confidence would help.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so every one of the 6 parameters is already documented in the schema. The description only adds 'Pass position for one seat', which sits slightly awkwardly against the schema's array-of-seats semantics and provides marginal extra meaning. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a precise verb+resource (observed limp range) plus the exact output form (169-class hole-card counts) and the population (hole cards villains showed after an open limp). The closing 'This is not a solver range' explicitly separates it from solver-range siblings such as get_range and get_postflop_range.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied rather than stated: the solver-range disclaimer and 'Sample is showdown-only' hint at when the data is appropriate, and 'Pass position for one seat' is a light invocation hint. However, no explicit when-to-use/when-not conditions or named alternative tools are given beyond the negation.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_opponent_notesGet opponent notesARead-onlyIdempotentInspect
Leak notes computed from uploaded hands for one opponent, with the sample size on each line.
| Name | Required | Description | Default |
|---|---|---|---|
| opponent_id | Yes | Opponent id from list_my_opponents. |
Output Schema
| Name | Required | Description |
|---|---|---|
| error | No | Present instead of a payload when the request named something that does not exist. No figure is estimated in its place. |
| notes | No | Notes, or a single line saying the sample is too small. |
| opponent_id | No | Opponent id, echoed. |
| display_name | No | Screen name as written in the history. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, non-destructive, closed-world), so the bar is lower. The description still adds real context beyond them: notes are derived from uploaded hands, and every line carries its own sample size, which tells the agent how to interpret the output.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence with no filler; the scope ('one opponent') and the output characteristic ('sample size on each line') both land immediately.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present and annotations carrying the safety profile, the description only needs to frame the tool's purpose, which it does. The implicit dependency on prior hand uploads is hinted at but not spelled out, leaving a small gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and there is only one parameter, whose schema description already routes to list_my_opponents. The description adds no further parameter detail, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific resource (leak notes) with its scope ('for one opponent') and origin ('computed from uploaded hands'), which is clear and distinct from the range/report siblings. It does not explicitly contrast itself with any sibling tool, so it stops short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied rather than stated: the phrase 'computed from uploaded hands' hints that hand histories must exist first, and the schema points to list_my_opponents for the id. There is no explicit when-to-use/when-not guidance or named alternative.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_postflop_nodeGet postflop solver nodeARead-onlyIdempotentInspect
One postflop solver node: the acting player's strategy for every hand class, the legal next segments, board, reach and the reach-weighted action split. Walk deeper by appending a returned childSegment (an action like "Bet 5.5" or a runout like "deal:7c") to path.
| Name | Required | Description | Default |
|---|---|---|---|
| pack | Yes | Pack id from list_postflop_packs. Use a sizingTrees packId to pick the tree: the pack id for 75% pot on the flop, or "<pack>-flop33" for 33%. | |
| path | No | Segments from the root, e.g. ["Check", "Bet 5.5"]. Empty for the root node. | |
| board | Yes | Board in spaced form, e.g. "3h 3d 2s" | |
| combo | No | Optional exact combo, e.g. AsKh (PLO5: five cards, as listed in the node's hands) | |
| limit | No | Maximum representative compact combos (default 40, maximum 200) | |
| detail | No | Response detail. "compact" is the default and removes bulk maps; use "full" only when exact complete data is required. |
Output Schema
| Name | Required | Description |
|---|---|---|
| hint | No | How to narrow, page, or widen the same query. |
| node | No | Full detail: the stored node. Null at a chance point, where runouts hang directly under the path. |
| path | No | Segments walked from the root to this node. |
| board | No | Board at this node. |
| combo | No | The requested combo, when one was asked for. |
| hands | No | Compact rows in `columns` order, or the full per-combo strategy objects in full detail. |
| potBb | No | Pot at this node in big blinds. |
| reach | No | Full detail: the acting player's per-combo reach. |
| actions | No | Actions at the node with their reach-weighted frequency. |
| columns | No | Column order for `hands`: combo, reach, frequencies, evBb, evLossBb, actionEvBb. |
| summary | No | What the compact range left out, so nothing looks complete when it is sampled. |
| actionFreqs | No | Full detail: aggregate frequency per action. |
| actingPlayer | No | 0 for out of position, 1 for in position. |
| childSegments | No | Append one of these to `path` to walk deeper. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive, closed-world, so the safety profile is covered. The description adds real behavioral context beyond that: the node is reachable/expandable via path+childSegment, and the default compact detail 'removes bulk maps' while 'full' is reserved for exact complete data — useful trade-off disclosure.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two dense sentences with no filler, front-loading what the node returns before the traversal instruction. It is efficient, though poker-domain jargon ('childSegment', 'reach-weighted action split') keeps it slightly heavy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, the description needn't explain return values, and annotations plus 100% schema coverage carry most of the structured load. It covers content, traversal and detail trade-offs; the only real gap is not routing the agent away from the superficially similar get_node sibling.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so all six parameters including pack, path, board, combo, limit and the detail enum are already documented in the schema. The description reinforces how path works (appending a childSegment) but adds little per-parameter meaning beyond what the schema provides; baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource (get a postflop solver node) and enumerates exactly what one node contains: per-hand-class strategy, legal next segments, board, reach and reach-weighted action split. The 'postflop' qualifier separates it from generic siblings, but it never distinguishes itself from the sibling get_node, which is the one an agent could easily confuse it with.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The second sentence explains the traversal pattern — append a returned childSegment to `path` to go deeper — which is genuinely useful usage guidance. However, it gives no explicit when-to-use/when-not guidance against alternatives like get_node, get_postflop_range, or get_hand_results, leaving the agent to infer the boundary.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_postflop_rangeGet postflop action rangeARead-onlyIdempotentInspect
The range a player takes one flop action with, from a solved pack: hand-class weights ("AA:1,AKs:0.42,...", same format as the preflop ranges) after every earlier flop action on the path. path ends in the action whose range you want, e.g. ["Check", "Bet 1.8", "Call 1.8"] for the check-call range. Bet-size tree. "33" = 33% pot on the flop, then 75% pot on the turn and river, plus all-in. "75" = 75% pot on every street, plus all-in. Compact and full detail apply to the other range tools; this returns the action range itself.
| Name | Required | Description | Default |
|---|---|---|---|
| hand | No | Optional exact combo (AsKh) or hand class (AKs) for one frequency instead of reading the whole range. | |
| pack | Yes | Pack id from list_postflop_packs | |
| path | Yes | Flop actions ending in the action whose range you want | |
| tree | Yes | Bet-size tree. "33" = 33% pot on the flop, then 75% pot on the turn and river, plus all-in. "75" = 75% pot on every street, plus all-in. PLO5 packs are solved on "33" only. | |
| board | Yes | Flop, e.g. "3h 3d 2s" | |
| minFreq | No | Drop classes at or below this weight. Default 0. |
Output Schema
| Name | Required | Description |
|---|---|---|
| hand | No | The requested hand, when one was asked for. |
| pack | No | Pack id the range was read from, after tree resolution. |
| path | No | Flop actions, ending in the action asked for. |
| tree | No | Bet-size tree, "33" or "75". |
| board | No | Canonical board as stored in the pack. |
| error | No | Present instead of a payload when the request named something that does not exist. No figure is estimated in its place. |
| range | No | Hand-class weights as "AA:1,AKs:0.42,…", the preflop range format. |
| action | No | The action whose range this is. |
| summary | No | What the compact range left out, so nothing looks complete when it is sampled. |
| weights | No | Hand class to frequency. An omitted class has weight 0. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, so safety is covered. The description adds useful behavioral context – the hand-class weight return format and how the path accumulates prior actions – but says nothing about pagination, cost, or failure modes for an invalid path.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
It is reasonably front-loaded, but the tree explanation ('33' = 33% pot on the flop...) restates the schema's tree description almost verbatim, duplicating structured data rather than adding new information. A sentence could be trimmed without loss.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present the return shape needn't be described, and annotations carry the safety profile. Between the path example and tree semantics, the agent has enough to call a 6-param tool correctly; only explicit sibling routing is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% so the baseline is 3, but the description adds real value with a concrete path example (['Check','Bet 1.8','Call 1.8']) and distinguishes the tree enum behavior ('33' vs '75'), which helps the agent construct valid values beyond reading the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('the range a player takes one flop action with, from a solved pack') and clarifies it returns the action range itself rather than the compact/full-detail ranges of the other range tools. It differentiates from siblings only loosely ('the other range tools'), so it falls just short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The path-accumulation semantics ('after every earlier flop action on the path') and the worked example imply when to use it, but the description never names a concrete alternative tool or states an explicit when-not-to-use condition versus get_range or get_postflop_node. Usage is inferable rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_queued_solveGet a queued solveARead-onlyIdempotentInspect
Look up one queued solve for this account. status is pending, running, done, or failed. solution_id is null until a worker exists.
| Name | Required | Description | Default |
|---|---|---|---|
| queue_id | Yes | Queue id returned by enqueue_solve. |
Output Schema
| Name | Required | Description |
|---|---|---|
| pot | No | Pot in big blinds. |
| board | No | Board for the requested solve. |
| title | No | Title given when the job was recorded. |
| reason | No | Why the job does not start a solve. |
| status | No | "pending", "running", "done", or "failed". |
| dispatch | No | Always "not_configured". |
| queue_id | No | Id for get_queued_solve. |
| createdAt | No | ISO timestamp the job was recorded. |
| solution_id | No | Always null while dispatch is disabled. |
| effective_stack | No | Effective stack in big blinds. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, non-destructive), and the description adds genuine context beyond them: the valid status values and the fact that solution_id stays null until a worker exists. It does not state whether polling is expected or at what cadence.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, front-loaded with the action and then the state/model semantics. Every sentence carries new information with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, the return shape needn't be re-explained, and annotations cover safety. The only gap is routing guidance relative to list_queued_solves, which the description leaves to inference.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so queue_id is fully documented in the schema as 'Queue id returned by enqueue_solve'. The description's added detail (status, solution_id) concerns returned fields, not the parameter, so the baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Look up one queued solve') and the 'one' implicitly distinguishes it from the list_queued_solves sibling. It does not explicitly name that sibling, so an agent still has to infer the single-vs-list split.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Scoping is implied by 'for this account' and 'one queued solve', but there is no explicit when-to-use guidance or named alternative (e.g. list_queued_solves) to route the agent. Usage must be inferred from the singular framing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_rangeGet preflop rangeARead-onlyIdempotentInspect
The GTO range for one spot. spot is an action path of POSITION_ACTION pairs ending in the action whose range you want, e.g. NLHE cash "UTG_60%_HJ_Call", nlmtt8 "UTG_Open", or PLO "UTG_Open_HJ_3B". Add hand for one exact frequency and EV. Compact mode is default; PLO returns representative pure/mixed hands unless a hand is specified; plo5 returns the top hands by EV that take the action (limit up to 500 compact, 2000 full).
| Name | Required | Description | Default |
|---|---|---|---|
| game | Yes | "nl" = no-limit hold'em 6-max cash (169-grid hands, per-hand EV in small blinds), "nl9" = no-limit hold'em 9-max cash, "nlmtt8" = no-limit hold'em 8-max MTT chip-EV (10–300bb, 1bb BB-ante; Fold/Call/Limp/AI/Open/3B tokens), "nlh8-hydra" = no-limit hold'em 8-max MTT chip-EV with a classic 0.1bb ante from every seat (10, 20, 30, 60bb; same tokens as nlmtt8), "nlh8-icm" = no-limit hold'em 8-max MTT with ICM: one stack table per scenario (near the money, 33 or 35 left of 200, 30 paid; final table, 8 left), uneven stacks, 0.125bb ante from every seat, EVs in tournament dollars; pass scenario (list_games lists them; stack alone works only where one table has that depth); get_node only, "nlhu" = no-limit hold'em heads-up for the title, chip-EV, both players at the stack (1–40bb), 0.125bb ante each, SB on the button; get_node only, "plo" = pot-limit Omaha 6-max cash (4-card), "plo5" = pot-limit Omaha 5-card 6-max (100bb, 1.2bb ante), "plo9" = pot-limit Omaha 9-max cash, "plo6hu" = 6-card Omaha heads-up (BTN vs BB, 100bb). Cash trees are not tournament, ICM, PKO, or satellite solves. nlmtt8, nlh8-hydra and nlhu are chip-EV; only nlh8-icm is ICM. | |
| hand | No | Optional hand/class, e.g. AKs or (KA)(KA) | |
| spot | Yes | Action path ending in an action | |
| limit | No | Maximum compact rows to return (default 120, maximum 500). | |
| stack | Yes | Stack depth in big blinds, e.g. 100 | |
| detail | No | Response detail. "compact" is the default and removes bulk maps; use "full" only when exact complete data is required. | |
| minFreq | No | Drop hands at or below this weight (PLO ranges are large) |
Output Schema
| Name | Required | Description |
|---|---|---|
| ev | No | Full detail: EV of the requested hand in small blinds. |
| evs | No | Hand class to EV, only where the solved bundle scored the hand. |
| evSb | No | EV of the requested hand in small blinds. |
| freq | No | Full detail: frequency of the requested hand. |
| game | No | Preflop game id, e.g. "nl" or "nlmtt8". |
| hand | No | The requested hand, when one was asked for. |
| hint | No | How to narrow, page, or widen the same query. |
| kind | No | plo5: the action family. |
| spot | No | Action path ending in an action, echoed from the request. |
| actor | No | Position to act at this node. |
| hands | No | Hand classes in the range. |
| range | No | Compact rows in `columns` order. |
| stack | No | Stack depth in big blinds. |
| action | No | plo5: the action the range belongs to. |
| combos | No | Combos in the range. |
| columns | No | Column order for `range`: hand, frequency, evSb. |
| history | No | Action path ending in the acting position. |
| summary | No | What the compact range left out, so nothing looks complete when it is sampled. |
| version | No | Dataset version where the bundle publishes one. |
| weights | No | Hand class to frequency. An omitted class has weight 0. |
| frequency | No | Frequency of the requested hand, 0 to 1. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only, idempotent, non-destructive, closed-world behavior, so the description's added value is the output-shape disclosure: compact mode strips bulk maps, PLO returns representative pure/mixed hands unless a hand is named, and plo5 is truncated to top-EV hands with 500/2000 row caps. That is real behavioral context beyond the structured fields, though it doesn't state output format or error behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Dense and front-loaded: the core definition comes first, then spot syntax, then the optional-hand behavior, then the compact/PLO/plo5 variations. It is information-packed rather than padded, though the final sentence strings three separate behaviors together and is slightly hard to parse.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values needn't be spelled out, and the description covers the format-specific quirks an agent must know (PLO hand truncation, plo5 row caps, compact vs full). The main residual gap is that the heavily conditional game semantics — especially nlh8-icm needing a scenario — live entirely in the schema's `game` description rather than the tool description.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 100% schema coverage the baseline is 3, but the description actually earns above baseline by giving concrete `spot` path examples across three game formats ("UTG_60%_HJ_Call", "UTG_Open", "UTG_Open_HJ_3B"), which the schema only describes vaguely as "Action path ending in an action". It also clarifies the `hand` purpose (single frequency and EV) and the plo5 limit semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The first sentence states a specific verb+resource (return the GTO range for one spot) and the examples immediately establish that this is a preflop, position-action-path lookup. It doesn't explicitly contrast itself with the sibling get_postflop_range or get_node, so it falls short of a 5, but an agent can tell what it returns.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives useful invocation guidance — add `hand` for a single frequency/EV, compact is the default and full only when exact complete data is required, and `minFreq` behavior is implied. It never says when to prefer this over get_node or get_postflop_range, so usage is implied rather than explicitly routed.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_range_metadataGet range index metadataARead-onlyIdempotentInspect
Index metadata for one preflop game, stack, and path: bundle stats for hold'em/PLO bundles, or the matching node row for plo5 and plo6hu. Does not return a strategy and does not invent exploitability.
| Name | Required | Description | Default |
|---|---|---|---|
| game | Yes | Preflop game id, e.g. "nl", "nl9", "nlmtt8", "nlh8-hydra", "plo", "plo9", "plo5", "plo6hu". | |
| path | Yes | Action path, e.g. UTG_Open or LJ_Fold. Use (root) or empty for the plo5 root. | |
| stack | Yes | Stack depth in big blinds, e.g. 100. |
Output Schema
| Name | Required | Description |
|---|---|---|
| game | No | Game id, echoed. |
| note | No | What the match means, or that nothing was estimated. |
| path | No | Action path, echoed. |
| rows | No | Matching index rows. |
| actor | No | Acting position read off the path. |
| error | No | Present instead of a payload when the request named something that does not exist. No figure is estimated in its place. |
| match | No | "bundle", "node", or "none". |
| stack | No | Stack depth in big blinds, echoed. |
| dataset | No | Dataset the game maps to. |
| preflopExploitability | No | Always "not available". |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive, closed-world behavior, so the safety profile is covered. The description adds genuine extra context: the return payload branches by game type (bundle stats for hold'em/PLO vs. a node row for plo5/plo6hu) and it explicitly disclaims two things it does not do.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences with the payload behavior front-loaded and the exclusions second; every clause carries information. Slightly dense with domain jargon ('bundle stats', 'plo6hu') but no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
A read-only, single-shot lookup with full schema descriptions, rich annotations, and an output schema, so return-format explanation is not needed. The description covers the one non-obvious element (game-dependent payload) and the boundary conditions; only an explicit sibling pointer is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with per-parameter examples ('nl', 'plo5', 'UTG_Open', '100'), so the schema already carries the meaning. The description restates the three required inputs without adding format or validity detail beyond them, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a concrete verb and resource ('Index metadata for one preflop game, stack, and path') and further specifies the output shape per game family (bundle stats vs. node row). It also fences itself off from the more obvious sibling by declaring it 'does not return a strategy', which is what get_range presumably does, though it never names that alternative.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear when-not guidance by excluding strategy and exploitability outputs, which tells the agent when to prefer get_range or get_exploitability instead. However, no alternative tool is named and there is no positive statement of the use case that selects this tool over list_games/get_node.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_session_summarySummarize a sessionARead-onlyIdempotentInspect
One uploaded session's headline numbers: hero, game type, start and end times, hands played, net result in big blinds, and HUD rates (VPIP, PFR, 3-bet, open limp) as percentages with the sample size. Use it after list_my_sessions to report how a session went; use get_hand_results for its winnings curve and find_hands for individual hands. Returns an error for an unknown session id. Any key works, free trial included, and it never counts against the allowance. If this account has no hands, offer the hosted upload page from get_upload_link (https://pokerdata.io/upload) instead of asking the user to paste histories into chat.
| Name | Required | Description | Default |
|---|---|---|---|
| session_id | Yes | Session id from list_my_sessions. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | No | Session id. |
| hud | No | HUD rates over this session, as percentages. |
| hero | No | Hero name in the history. |
| error | No | Present instead of a payload when the request named something that does not exist. No figure is estimated in its place. |
| hands | No | Hands in the session. |
| netBb | No | Session result in big blinds. |
| endedAt | No | Last hand timestamp. |
| game_type | No | Game type: "NLHE", "PLO", "PLO5", or "PLO6". |
| startedAt | No | First hand timestamp. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive and closed-world, but the description adds genuinely non-obvious behavior: it errors on an unknown session id, it never counts against the allowance, and free-trial keys work. The upload-page fallback is a useful behavioral cue, though the quota/free-trial remark is slightly promotional rather than operational.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The core sentence is well front-loaded, but enumerating every returned field is redundant given the output schema exists, and the 'Any key works, free trial included' clause plus the upload-page paragraph drift toward product messaging rather than invocation guidance.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values needn't be explained, yet the description helpfully covers the error path for an unknown id and the empty-account fallback. It is nearly complete for a single-parameter read tool; only minor padding weakens it.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The single session_id parameter is already fully documented in the schema (100% coverage, uuid format with pattern) and points back to list_my_sessions. The description adds nothing about the parameter itself, so the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('One uploaded session's headline numbers') and enumerates the exact fields returned (hero, game type, times, hands, net bb, HUD rates). It explicitly distinguishes itself from get_hand_results and find_hands, which cover the winnings curve and individual hands respectively.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Names the sequencing ('Use it after list_my_sessions to report how a session went') and routes the agent to the correct alternatives for adjacent needs (get_hand_results for winnings curve, find_hands for individual hands). It also gives an explicit fallback when the account has no hands.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_startedGet startedARead-onlyIdempotentInspect
Start here with a new user. Returns the short set of questions to ask them (game, format, stakes, goal), a menu of what PokerData can do with the tools for each, what is free without a key, and how to file a feature or data request. Free, no key needed.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| access | No | What is free and what needs a key. |
| requests | No | How to file a feature or data request. |
| signedIn | No | Whether this connection carries a key or a signed-in account. |
| askTheUser | No | Questions to ask a new user once, briefly. |
| notCovered | No | Formats that are not covered, and to offer a request instead. |
| capabilities | No | What the server can do, grouped by goal. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive/openWorld=false, so the safety profile is covered. The description adds genuinely useful behavioral context beyond that: the call is free and requires no API key, which matters for an agent deciding whether it can invoke it during setup.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single dense but well front-loaded sentence with the key instruction ('Start here with a new user') up front. The parenthetical enumerations add useful specificity, though the sentence is packed enough that it reads more like a checklist than clean prose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return structure need not be spelled out, yet the description still summarizes the payload. For a zero-param, read-only onboarding tool, an agent has everything needed to call it and understand the result.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so there is nothing for the description to clarify; baseline 4 applies. The description correctly avoids inventing parameter guidance that does not exist.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states concretely what the tool returns: a short set of onboarding questions (game, format, stakes, goal), a menu of PokerData capabilities mapped to tools, free-tier info, and how to file requests. It is clearly distinguishable from data-fetching siblings like get_config or list_datasets, though the verb itself ('Get started') is not a precise verb+resource.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'Start here with a new user' gives clear context for when to invoke it, and no other sibling serves an onboarding role, so there is effectively no alternative to name. It stops short of explicitly saying when NOT to use it (e.g., for returning users who already know the flow).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_tournament_resultsGet my tournament resultsARead-onlyIdempotentInspect
MTT results imported from tournament summary files. Money is in cents. Hand histories are not a source of buy-ins or prizes. If this account has no hands, offer the hosted upload page from get_upload_link (https://pokerdata.io/upload) instead of asking the user to paste histories into chat.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | Yes | Tournament summaries to include, 1 to 500. |
Output Schema
| Name | Required | Description |
|---|---|---|
| roi | No | Return on investment as a ratio, or null. |
| note | No | Present when no tournament summaries have been uploaded. |
| itmPct | No | Share of tournaments that cashed, 0 to 1, or null. |
| recent | No | Tournaments, newest first. |
| buyInCents | No | Total buy-ins, or null when one buy-in is unknown. |
| tournaments | No | Tournament summaries counted. |
| receivedCents | No | Total prize money received. |
| netProfitCents | No | Received minus buy-ins, or null when a buy-in is unknown. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, non-destructive, closed-world), so the description correctly spends its words on added context: money is denominated in cents and hand histories are not a source of buy-ins or prizes. This is meaningful data-shape information beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four short sentences, front-loaded with what the data is, then units and caveats, then the fallback workflow. No filler, though the upload-link sentence is long enough that it could be tightened.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return-value explanation is unnecessary, and the description covers provenance, currency units, and a fallback path. It does not state what happens when there are zero tournaments (as opposed to zero hands), a minor gap for a single-parameter read tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% for the single `limit` parameter (1–500, default 200), so the schema fully documents it. The description adds nothing about the limit or result windowing, which is the expected baseline-3 outcome when the schema does the heavy lifting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description identifies the resource and its provenance ("MTT results imported from tournament summary files"), which tells an agent this returns tournament-level results rather than hand results. It is clear but does not explicitly contrast with siblings like get_hand_results or get_session_summary.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives a concrete conditional workflow: when the account has no hands, offer the hosted upload page from get_upload_link instead of asking for pasted histories. That is real usage guidance, though there is no explicit when-to-use framing versus other results tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_tree_docsGet tree documentationARead-onlyIdempotentInspect
Tree documentation for one dataset: coverage note from the shipped README and per-stack bundle or node counts from the shipped index. Does not read or modify range bytes.
| Name | Required | Description | Default |
|---|---|---|---|
| dataset | Yes | Dataset id from list_datasets, e.g. "nl/v2", "nl9", "nlmtt8", "plo", "plo9", "plo5", "plo6hu". |
Output Schema
| Name | Required | Description |
|---|---|---|
| error | No | Present instead of a payload when the request named something that does not exist. No figure is estimated in its place. |
| source | No | File the coverage note came from. |
| stacks | No | Per-stack counts. |
| dataset | No | Dataset id, echoed. |
| coverage | No | Coverage row from the shipped README. |
| preflopExploitability | No | Always "not available". |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint/idempotentHint/destructiveHint=false and closed-world, so the safety profile is covered. The description adds real scope detail beyond that: it clarifies the payload comes only from the shipped README and shipped index, and explicitly that range bytes are neither read nor modified. That scoping is meaningful added context, though no auth, staleness or paging behavior is mentioned.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two compact sentences, front-loaded with what the tool returns, followed by a scope-limiting exclusion. Every clause carries information and nothing is redundant.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter, read-only tool with full annotations and an output schema, the description needn't explain return values, and it adequately covers content and scope. It is essentially complete, with only the absence of any when-to-use guidance keeping it from a 5.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There is a single parameter (dataset) at 100% schema description coverage, with the schema supplying concrete id examples. The description contributes only "for one dataset", adding no format or constraint beyond what the schema already documents, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb+resource (documentation for one dataset's tree) and enumerates exactly what the payload contains: a coverage note from the shipped README and per-stack bundle/node counts from the shipped index. This is far more specific than a tautology. However, it never names a sibling it should be preferred over (e.g. get_range or get_range_metadata), so sibling differentiation is left implicit.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The clause "Does not read or modify range bytes" gives a negative boundary that implicitly routes an agent wanting actual range data to a sibling like get_range. But there is no positive statement of when to reach for this tool and no alternative is named, so guidance is merely implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_upload_linkGet the hand-upload linkARead-onlyIdempotentInspect
Primary hand-upload path. Returns https://pokerdata.io/upload on this origin, with a short-lived signed token for the caller's account when signing is configured. Hand the URL to the user. Pasting histories into chat is the fallback.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| url | No | URL to hand to the user, signed when signing is configured. |
| primary | No | Always true: this is the primary upload path. |
| resource | No | MCP resource URI that returns the same payload. |
| expiresAt | No | When the signed token expires, or null when unsigned. |
| tokenAttached | No | Whether the URL carries a signed token for this account. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint and destructiveHint=false, so the safety profile is covered. The description contributes real extra context beyond that: the token is short-lived, signed, tied to the caller's account, and only present 'when signing is configured.' It does not explain what happens when signing is absent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four short sentences, front-loaded with the essential fact (this is the primary upload path) followed by return details and the action to take. No filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return-value documentation is not required, and the annotations carry the safety profile. The description covers purpose, returned URL, token behavior, and the fallback action. Missing only the edge case where signing is not configured.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so the baseline is 4 and there is no parameter meaning to add. The description correctly focuses on output rather than inventing inputs.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific outcome: returns the https://pokerdata.io/upload URL with a signed token for the caller's account. It is clear this is the link-acquisition tool and not the actual upload. It does not name the closest sibling (upload_hand_history) or explain the relationship, so it falls short of full sibling differentiation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a clear directive: 'Hand the URL to the user,' and frames pasting histories into chat as 'the fallback,' which implies this link is the preferred path. No explicit when-not conditions or named alternatives among the sibling tools, but the usage context is unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_datasetsList solved datasetsARead-onlyIdempotentInspect
List preflop datasets in the shipped tree documentation (stacks, positions, whether each bundle was analyzed). Preflop exploitability is not available.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| readme | No | How to read one dataset's write-up. |
| source | No | Where the documentation came from, "data/tree-docs". |
| datasets | No | Documented datasets. |
| generated | No | Date the documentation was generated. |
| preflopExploitability | No | Always "not available": no preflop dataset publishes it. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare this a safe, read-only, idempotent, closed-world read, so the safety profile is covered. The description adds value beyond them by describing the content each entry carries and by flagging the key limitation (no preflop exploitability), which prevents the agent from misusing the results.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with the resource and scope front-loaded and the limitation trailing. Every clause carries information (what is listed, where it lives, what fields appear, what is unavailable) with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists so return values need not be spelled out, and annotations cover the safety profile; the description supplies the remaining needed context (scope, per-entry content, one absence). Only the differentiation from sibling listing tools is left implicit.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so there is nothing for the description to disambiguate; the baseline for a no-parameter tool applies. No parameter semantics are missing or contradicted.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (List) and resource (preflop datasets) and adds scope: they live in the shipped tree documentation, and it enumerates what each entry conveys (stacks, positions, analyzed status). It does not name or distinguish itself from similar siblings such as list_postflop_packs or get_tree_docs, so an agent must infer the boundary.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no explicit when-to-use guidance and no alternatives named among a large family of list_* siblings. The closing caveat 'Preflop exploitability is not available' hints at what the tool cannot do, but it is not framed as routing guidance, leaving usage to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_gamesList covered gamesARead-onlyIdempotentInspect
Discover covered stack depths and positions. Call this before low-level preflop queries. "nl" = no-limit hold'em 6-max cash (169-grid hands, per-hand EV in small blinds), "nl9" = no-limit hold'em 9-max cash, "nlmtt8" = no-limit hold'em 8-max MTT chip-EV (10–300bb, 1bb BB-ante; Fold/Call/Limp/AI/Open/3B tokens), "nlh8-hydra" = no-limit hold'em 8-max MTT chip-EV with a classic 0.1bb ante from every seat (10, 20, 30, 60bb; same tokens as nlmtt8), "nlh8-icm" = no-limit hold'em 8-max MTT with ICM: one stack table per scenario (near the money, 33 or 35 left of 200, 30 paid; final table, 8 left), uneven stacks, 0.125bb ante from every seat, EVs in tournament dollars; pass scenario (list_games lists them; stack alone works only where one table has that depth); get_node only, "nlhu" = no-limit hold'em heads-up for the title, chip-EV, both players at the stack (1–40bb), 0.125bb ante each, SB on the button; get_node only, "plo" = pot-limit Omaha 6-max cash (4-card), "plo5" = pot-limit Omaha 5-card 6-max (100bb, 1.2bb ante), "plo9" = pot-limit Omaha 9-max cash, "plo6hu" = 6-card Omaha heads-up (BTN vs BB, 100bb). Cash trees are not tournament, ICM, PKO, or satellite solves. nlmtt8, nlh8-hydra and nlhu are chip-EV; only nlh8-icm is ICM.
| Name | Required | Description | Default |
|---|---|---|---|
| detail | No | Response detail. "compact" is the default and removes bulk maps; use "full" only when exact complete data is required. |
Output Schema
| Name | Required | Description |
|---|---|---|
| _coverage | No | Formats and objectives this server does and does not answer. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations, which already declare read-only, idempotent, and non-destructive behavior, the description discloses substantive behavioral constraints: which games are chip-EV vs ICM, which variants are get_node only, and what the game codes cover. This is exactly the extra context needed to avoid misinterpretation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The key instruction is front-loaded, and the extensive game-code enumeration is mostly necessary for disambiguation. However, the long run-on paragraph is dense and could be more structurally organized, which keeps it from a 5.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given one optional parameter, full schema coverage, rich annotations, and an output schema, the description supplies the coverage matrix and game-mode constraints an agent needs. No important invocation or interpretation detail appears to be missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There is only one parameter, detail, and schema description coverage is 100%, so the schema already explains the compact/full enum. The description does not add further parameter semantics, making the baseline 3 appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states a specific verb and resource: discover/list covered games, stack depths, and positions, with detailed game-code meanings. It distinguishes itself from low-level query tools via 'Call this before low-level preflop queries,' but does not explicitly differentiate itself from listing siblings such as list_datasets or list_spots.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives explicit usage context: call this before low-level preflop queries, and notes game-specific restrictions such as get_node only for nlh8-icm and nlhu. It also clarifies that cash trees are not tournament/ICM/PKO/satellite solves, though it does not name alternative listing tools directly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_library_solutionsList my saved solutionsARead-onlyIdempotentInspect
Finished postflop solutions saved for this account. None are marked done while dispatch is disabled.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | Yes | Solutions to return, 1 to 50. |
Output Schema
| Name | Required | Description |
|---|---|---|
| note | No | Why no solution is marked done. |
| solutions | No | Empty while solver dispatch is disabled. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false and openWorldHint=false, so safety and determinism are covered without the description. The description adds one genuine behavioral caveat – 'None are marked done while dispatch is disabled' – which tells the agent results may lack a completed status depending on system state, though the phrasing is cryptic and the return format/pagination is left to the output schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences with no filler, and the resource scope is front-loaded ahead of the state caveat. The second sentence is terse to the point of ambiguity but does convey information rather than padding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only list tool with full annotations, complete parameter schema and an output schema, the description supplies the essential scope plus a state caveat. Nothing critical is missing, though the dispatch caveat is underexplained.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the single 'limit' parameter is fully documented with range and default in the schema. The description adds no additional meaning about the limit, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific resource with a qualifier: 'Finished postflop solutions saved for this account.' The word 'finished' implicitly distinguishes it from list_queued_solves and get_queued_solve, so an agent can separate the completed-solution listing from the pending one. It is clear but does not explicitly name the sibling it excludes.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by the phrase 'finished postflop solutions' – an agent can infer this is the tool for browsing already-computed results rather than queued work. However, there is no explicit when-to-use statement and no named alternative (e.g., list_queued_solves) to route to for unfinished solves.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_my_opponentsList my opponentsARead-onlyIdempotentInspect
Tracked opponents from uploaded hands. Each row has handCount, handsVsHero, and heroBb100Vs. Pass name to find one villain.
| Name | Required | Description | Default |
|---|---|---|---|
| hero | No | Only hands where this hero name was seated. | |
| name | No | Case-insensitive substring of the opponent's screen name. | |
| sort | Yes | Row order: most hands, most recent, or by hero's bb/100 against them (toughest = worst for hero). | hands |
| limit | Yes | Opponents to return, 1 to 500. | |
| game_type | No | Only hands of this game type, e.g. "NLHE" or "PLO". | |
| min_hands | Yes | Drop opponents seen in fewer hands than this. |
Output Schema
| Name | Required | Description |
|---|---|---|
| opponents | No | Opponents, sorted as requested. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, non-destructive and closed-world, so the safety profile is fully covered. The description adds the shape of each returned row (handCount, handsVsHero, heroBb100Vs), which is useful behavioral context, but says nothing about defaults, caps, or empty-result behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, front-loaded with the data source before the row shape and the filter hint; nothing is wasted. Slight deduction because the row field names are dropped without context, leaving the reader to interpret heroBb100Vs on their own.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present the description need not explain returns, and the schema fully covers all six parameters plus required/minimum constraints. For a read-only list tool this is close to complete; the missing piece is any hint about the typical workflow connecting this to the per-opponent siblings.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and every parameter is documented in-schema, including the sort enum semantics and the 1-500 limit range, so the baseline is 3. The description only echoes the name filter ('find one villain') and does not add meaning beyond the schema, e.g. how it interacts with hero or min_hands.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific resource and scope: tracked opponents derived from uploaded hands, which an agent can distinguish from session/hand-level siblings. It does not explicitly name a sibling, so it stops short of a 5, but the verb+resource pairing is clear.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The only guidance is 'Pass name to find one villain,' which implies a lookup use case but gives no when-to-use versus when-not-to-use, and no routing to alternatives like get_opponent_notes for notes on a specific villain. Usage is implied rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_my_requestsList my requestsARead-onlyIdempotentInspect
List the feature and data requests this account has filed, newest first, with their status. Free with any key.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum requests to return (default 20, maximum 100). |
Output Schema
| Name | Required | Description |
|---|---|---|
| requests | No | Filed requests. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive and closed-world behavior, so the safety profile is covered structurally. The description adds real context beyond that: results are ordered newest first, status is included, and access is free with any key (an auth/cost hint). It omits pagination/truncation behavior, which keeps it short of a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One compact sentence with the core action front-loaded, followed by a short access clause that earns its place. No filler or repetition of the title.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Output schema exists, so return-shape explanation is unnecessary; the annotation set covers safety semantics; the single parameter is fully documented in the schema; and the description supplies ordering and access context. Nothing an agent needs to select or call this tool is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There is a single optional parameter and schema description coverage is 100%, so the schema already explains the default (20) and maximum (100) for limit. The description adds nothing about limit, which matches the baseline of 3 when the schema does the work.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description gives a specific verb (List), a specific resource (feature and data requests filed by this account), plus ordering and status inclusion. It is clearly distinguishable from the sibling submit_request, which files rather than retrieves requests.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by the name and description: call this to see requests you have filed. There is no explicit statement of when to prefer it over another tool or when it is not applicable, and submit_request is never named as the counterpart for creating requests.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_my_sessionsList my sessionsARead-onlyIdempotentInspect
Recent uploaded sessions, newest first: id, hero, game type, dates, hands, and net result. game_type matches hole-card count. If this account has no hands, offer the hosted upload page from get_upload_link (https://pokerdata.io/upload) instead of asking the user to paste histories into chat.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | Yes | Sessions to return, 1 to 50. | |
| game_type | No | Only sessions containing this game type. |
Output Schema
| Name | Required | Description |
|---|---|---|
| hint | No | Where to upload hands when the account has none. |
| sessions | No | Sessions, newest first. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish read-only, idempotent, non-destructive behavior, so the description is free to add other context — and it does: newest-first ordering and the empty-state fallback flow. It does not mention pagination or result-size behavior, a minor gap for a listing tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the core purpose and return fields, then the fallback instruction. Efficient and free of filler, though the second sentence packs two distinct ideas into one line.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so field-level return explanation is optional, yet the description still names key fields and the sort order. Combined with the empty-account fallback, an agent has enough to call this correctly, with only pagination behavior unaddressed.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds real meaning beyond the schema by explaining that 'game_type matches hole-card count', which clarifies the NLHE/PLO/PLO5/PLO6 enum semantics. The limit parameter is left entirely to the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Specific verb+resource ('Recent uploaded sessions') with a clear scope signal ('newest first') and an enumeration of returned fields, which separates it from detail-oriented siblings like get_session_summary. It stops short of explicitly naming the sibling it differs from, so it is clear but not fully self-differentiating.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit conditional routing for the empty-account case: fall back to get_upload_link rather than asking the user to paste histories. That is a concrete when-to-use rule, but there is no guidance on when to prefer this list view over get_session_summary or find_hands for detail.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_postflop_packsList postflop packsARead-onlyIdempotentInspect
Every solved postflop pack: preflop line, positions (OOP vs IP), stack, pot, the bet-size trees it is solved under, and the solved boards. Boards use the spaced form ("3h 3d 2s"). NLHE packs list sizingTrees: "75" (75% pot every street, the pack id itself) and "33" (33% pot on the flop, then 75%, under the <pack>-flop33 id); every postflop tool accepts either tree's packId. PLO5 packs (ids starting plo5-) solve one 33% flop tree, flop decisions only. Compact output lists board names per pack. Pass pack (the 75% id or the -flop33 id) for that tree's per-board detail and per-flop exploitability where the index publishes a number. Missing exploitability is omitted, never estimated. Pass variant to list only NLHE or PLO5 packs. Call this before get_postflop_node.
| Name | Required | Description | Default |
|---|---|---|---|
| pack | No | One pack id (75% id or the -flop33 id): per-board detail and that tree's exploitability | |
| detail | No | Response detail. "compact" is the default and removes bulk maps; use "full" only when exact complete data is required. | |
| variant | No | Only packs of this game: nlhe (hold'em) or plo5 (five-card Omaha) |
Output Schema
| Name | Required | Description |
|---|---|---|
| hint | No | How to narrow, page, or widen the same query. |
| packs | No | Packs matching `variant` and `pack`. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, and the description adds substantial domain behavior on top: pack-id conventions for the 75% vs '-flop33' trees, the PLO5 single-tree restriction, and the policy that missing exploitability is omitted rather than estimated. It also discloses that 'compact' removes bulk maps, which materially affects what an agent receives.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The opening sentence is well front-loaded with the full content of a pack, and nearly every clause carries information. However, the remainder is a dense run-on that mixes parameter semantics and output-mode behavior into one block, which would benefit from structure.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained; the description nonetheless clarifies the compact/full distinction and exploitability omission. For a filtered-list tool with 100% schema coverage and clear annotations, nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description goes beyond the schema by explaining what the `pack` ids actually mean (75% id vs `<pack>-flop33`), that every postflop tool accepts either tree's packId, and what detail levels retain or drop, adding real domain semantics the schema cannot express.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Every solved postflop pack') and enumerates exactly what each entry contains (preflop line, positions, stack, pot, sizing trees, solved boards). It is clearly distinguishable from sibling list/get tools and explicitly positions itself relative to get_postflop_node.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives strong usage direction: 'Call this before get_postflop_node' establishes the workflow, and it explains how to use `variant` and `pack` to narrow the listing. It does not state when this tool should be skipped in favor of a sibling list tool (e.g., list_datasets), so it stops short of explicit when-not guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_queued_solvesList my queued solvesARead-onlyIdempotentInspect
List this account's solver-queue jobs, newest first. Jobs are not dispatched.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | Yes | Jobs to return, 1 to 50. |
Output Schema
| Name | Required | Description |
|---|---|---|
| solves | No | Queued jobs. None are dispatched. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive, and closed-world, so safety is covered. The description adds two things annotations cannot convey: result ordering (newest first) and that queued jobs are not dispatched, which tells the agent this is passive inspection rather than a trigger.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences with no waste. The resource and scope lead, and the non-dispatch caveat follows immediately where it is most useful.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return shape need not be described, and annotations cover the safety profile. The description supplies scope and ordering; the only minor gap is no mention of how the queue relates to enqueue_solve or of pagination beyond the limit parameter.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the single 'limit' parameter is fully documented in the schema (range 1-50, default 20). The description adds no syntax or default information beyond that, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Specific verb+resource ('List this account's solver-queue jobs') plus ordering ('newest first'). It does not name the adjacent siblings get_queued_solve (singular fetch) or enqueue_solve, so an agent must infer the boundary itself, but the scope is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied by the verb and the scoping phrase 'this account's'; there is no explicit when-to-use statement and no pointer to get_queued_solve for single-job retrieval or enqueue_solve for adding jobs. The closest thing to guidance is the behavioral note that jobs are not dispatched.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_spotsSearch preflop spotsARead-onlyIdempotentInspect
Search valid decision nodes for a stack depth, tagged by depth (1 = RFI, 2 = vs open, 3 = 3-bet pots, …). Compact mode is paginated; use depth, contains, and offset to narrow results without loading thousands of paths. plo9 has no spot index: walk it with get_node from history "UTG".
| Name | Required | Description | Default |
|---|---|---|---|
| game | Yes | "nl" = no-limit hold'em 6-max cash (169-grid hands, per-hand EV in small blinds), "nl9" = no-limit hold'em 9-max cash, "nlmtt8" = no-limit hold'em 8-max MTT chip-EV (10–300bb, 1bb BB-ante; Fold/Call/Limp/AI/Open/3B tokens), "nlh8-hydra" = no-limit hold'em 8-max MTT chip-EV with a classic 0.1bb ante from every seat (10, 20, 30, 60bb; same tokens as nlmtt8), "nlh8-icm" = no-limit hold'em 8-max MTT with ICM: one stack table per scenario (near the money, 33 or 35 left of 200, 30 paid; final table, 8 left), uneven stacks, 0.125bb ante from every seat, EVs in tournament dollars; pass scenario (list_games lists them; stack alone works only where one table has that depth); get_node only, "nlhu" = no-limit hold'em heads-up for the title, chip-EV, both players at the stack (1–40bb), 0.125bb ante each, SB on the button; get_node only, "plo" = pot-limit Omaha 6-max cash (4-card), "plo5" = pot-limit Omaha 5-card 6-max (100bb, 1.2bb ante), "plo9" = pot-limit Omaha 9-max cash, "plo6hu" = 6-card Omaha heads-up (BTN vs BB, 100bb). Cash trees are not tournament, ICM, PKO, or satellite solves. nlmtt8, nlh8-hydra and nlhu are chip-EV; only nlh8-icm is ICM. | |
| depth | No | Optional decision depth filter | |
| limit | No | Maximum compact rows to return (default 120, maximum 500). | |
| stack | Yes | Stack depth in big blinds | |
| detail | No | Response detail. "compact" is the default and removes bulk maps; use "full" only when exact complete data is required. | |
| offset | No | Compact pagination offset | |
| contains | No | Optional case-insensitive history substring filter |
Output Schema
| Name | Required | Description |
|---|---|---|
| game | No | Game id. |
| hint | No | How to narrow, page, or widen the same query. |
| spots | No | This page of decision nodes. |
| stack | No | Stack depth in big blinds. |
| total | No | Spots in the dataset for this stack. |
| offset | No | Offset this page started at. |
| matched | No | Spots left after the depth and contains filters. |
| returned | No | Spots in this page. |
| nextOffset | No | Offset for the next page, or null at the end. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already declare this as a read-only, idempotent, non-destructive, closed-world operation. The description adds meaningful behavior beyond that: compact mode is paginated, large result sets should be narrowed, and plo9 has no spot index. It does not discuss return shape, but an output schema exists.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is short and front-loads the core action before pagination advice and the plo9 exception. Every sentence carries useful information, though the plo9 instruction is somewhat abrupt and could be clearer in context.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given rich annotations, complete schema coverage, and an output schema, the description provides enough context to call the tool correctly. It covers pagination, depth tagging, narrowing filters, and the important plo9 exception. Remaining gaps are minor because structured fields already carry much of the detail.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema does most parameter documentation. The description still adds value by explaining the depth tag meanings (1 = RFI, 2 = vs open, 3 = 3-bet pots) and by recommending depth, contains, and offset for narrowing results. It does not add much for game, stack, limit, or detail beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: searching valid preflop decision nodes by stack depth, with depth tags. It also names the get_node alternative for plo9, giving useful sibling differentiation, though the core phrase 'spots' is only implicitly the decision-node index.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It clearly explains the main usage pattern: use depth, contains, and offset to narrow results and avoid loading thousands of paths. It also gives an explicit when-not case for plo9 by directing users to get_node. It does not broadly compare against all sibling search/get tools, but the practical guidance is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
submit_requestFile a feature or data requestADestructiveInspect
File a feature request or data request for the user, after telling them their question isn't covered and they agree. kind "data" is missing coverage (a game, format, stack depth, spot, or solve); kind "feature" is a missing capability (a tool, filter, export, or endpoint). Free with any key; the PokerData team reads every one.
| Name | Required | Description | Default |
|---|---|---|---|
| kind | Yes | "data" for missing coverage, "feature" for a missing capability. | |
| details | No | Anything else that helps: game, format, stakes, stack depths, positions, how they would use it. | |
| summary | Yes | One line saying what the user wants, e.g. "9-max MTT preflop at 25bb with ICM". | |
| question | No | The user's original question that couldn't be answered, verbatim if possible. |
Output Schema
| Name | Required | Description |
|---|---|---|
| message | No | What happens next, to relay to the user. |
| request | No | One feature or data request. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=false, destructiveHint=true, idempotentHint=false, but the description leaves the destructive/non-idempotent character unexplained (no rate limits, no duplicate-request behavior). It does add two facts beyond the structured data: the call is free with any key, and a human team reads every submission, which is genuinely useful context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four compact sentences, front-loaded with the action and its precondition, then the kind distinctions and the cost/human-review note. Slight overlap with the enum descriptions in the schema, but no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a non-idempotent write tool with a full schema and an output schema, the description covers what it does, when to invoke it, how the two kinds differ, and the cost/expectation of submission. What is missing is anything about the consequence of calling it (destructiveHint) or how to follow up, but the core invocation needs are covered.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description goes further by enumerating what counts as "data" (game, format, stack depth, spot, solve) versus "feature" (tool, filter, export, endpoint), which is meaningfully more than the enum's one-line schema description. The remaining parameters (details, summary, question) are left to the schema, which already documents them well.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource ("File a feature request or data request") and immediately disambiguates the two variants, defining what each kind means. An agent can distinguish this from list_my_requests and every read-oriented sibling without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives an explicit precondition: file only after telling the user their question isn't covered and they agree. That is strong guidance on when to use it, but it never states when not to use it or which sibling to reach for first (e.g. list_my_requests to check status).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
upload_hand_historyUpload a hand historyADestructiveInspect
Secondary upload path for a small paste. Prefer get_upload_link and the hosted /upload page. Runs the same ingestion pipeline and returns hands parsed, tournaments parsed, and errors. Does not grade solver frequencies.
| Name | Required | Description | Default |
|---|---|---|---|
| text | Yes | Raw hand history or tournament summary text. | |
| filename | No | Name to record for the paste. Defaults to "paste.txt". |
Output Schema
| Name | Required | Description |
|---|---|---|
| errors | No | Parse errors, if any. |
| filename | No | Filename recorded for the paste. |
| persisted | No | Always false: nothing is written to durable storage. |
| sessionId | No | Session id for the stored hands, or null when nothing parsed. |
| handsParsed | No | Hands parsed. |
| persistence | No | Where the hands live, "process_memory". |
| tournamentsParsed | No | Tournament summaries parsed. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare the safety profile (readOnlyHint=false, destructiveHint=true, idempotentHint=false), so the description's job is to add context — and it does: same ingestion pipeline as the primary path, returns parsed hand/tournament counts plus errors, and a negative scope statement ('does not grade solver frequencies'). It never explains why destructiveHint is true (e.g., whether a re-upload duplicates or overwrites data), which is the main remaining gap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three compact sentences with the most important routing fact ('Secondary upload path... Prefer get_upload_link') front-loaded. The sentence enumerating return fields is arguably redundant given an output schema exists, but nothing is padded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, return values need not be spelled out, and annotations carry the safety profile; the description supplies the pipeline identity, the routing rule, and the solver-grading exclusion. Only the destructive semantics and any duplicate-upload behavior remain unaddressed.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so both parameters (text, filename with its default) are already fully documented in the schema. The description adds only the vague size qualifier 'small paste' and no format guidance, so the baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('upload a hand history') plus its role in the system ('secondary upload path for a small paste', 'runs the same ingestion pipeline'). It explicitly distinguishes itself from the sibling get_upload_link and the hosted /upload page, so the agent can tell them apart without opening schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes the agent to the preferred alternative ('Prefer get_upload_link and the hosted /upload page') and states the qualifying condition ('a small paste'). What is missing is a hard boundary — how small is 'small', and whether this path is ever required rather than merely discouraged.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
5 tool updates
- Changed
compare_strategies2 fields changed- changed
Input schema / properties / baseline / properties / game / enumPrevious value: -[ - "nl", - "nl9", - "nlmtt8", - "nlh8-hydra", - "plo", - "plo5", - "plo9", - "plo6hu" -]New value: +[ + "nl", + "nl9", + "nlmtt8", + "nlh8-hydra", + "nlh8-icm", + "nlhu", + "plo", + "plo5", + "plo9", + "plo6hu" +] - changed
Input schema / properties / comparison / properties / game / enumPrevious value: -[ - "nl", - "nl9", - "nlmtt8", - "nlh8-hydra", - "plo", - "plo5", - "plo9", - "plo6hu" -]New value: +[ + "nl", + "nl9", + "nlmtt8", + "nlh8-hydra", + "nlh8-icm", + "nlhu", + "plo", + "plo5", + "plo9", + "plo6hu" +]
- Changed
get_config2 fields changed- changed
Input schema / properties / game / descriptionPrevious value: -"\"nl\" = no-limit hold'em 6-max cash (169-grid hands, per-hand EV in small blinds), \"nl9\" = no-limit hold'em 9-max cash, \"nlmtt8\" = no-limit hold'em 8-max MTT chip-EV (10–300bb, 1bb BB-ante; Fold/Call/Limp/AI/Open/3B tokens), \"nlh8-hydra\" = no-limit hold'em 8-max MTT chip-EV with a classic 0.1bb ante from every seat (10, 20, 30, 60bb; same tokens as nlmtt8), \"plo\" = pot-limit Omaha 6-max cash (4-card), \"plo5\" = pot-limit Omaha 5-card 6-max (100bb, 1.2bb ante), \"plo9\" = pot-limit Omaha 9-max cash, \"plo6hu\" = 6-card Omaha heads-up (BTN vs BB, 100bb). Cash trees are not tournament, ICM, PKO, or satellite solves. nlmtt8 is chip-EV only."New value: +"\"nl\" = no-limit hold'em 6-max cash (169-grid hands, per-hand EV in small blinds), \"nl9\" = no-limit hold'em 9-max cash, \"nlmtt8\" = no-limit hold'em 8-max MTT chip-EV (10–300bb, 1bb BB-ante; Fold/Call/Limp/AI/Open/3B tokens), \"nlh8-hydra\" = no-limit hold'em 8-max MTT chip-EV with a classic 0.1bb ante from every seat (10, 20, 30, 60bb; same tokens as nlmtt8), \"nlh8-icm\" = no-limit hold'em 8-max MTT with ICM: one stack table per scenario (near the money, 33 or 35 left of 200, 30 paid; final table, 8 left), uneven stacks, 0.125bb ante from every seat, EVs in tournament dollars; pass scenario (list_games lists them; stack alone works only where one table has that depth); get_node only, \"nlhu\" = no-limit hold'em heads-up for the title, chip-EV, both players at the stack (1–40bb), 0.125bb ante each, SB on the button; get_node only, \"plo\" = pot-limit Omaha 6-max cash (4-card), \"plo5\" = pot-limit Omaha 5-card 6-max (100bb, 1.2bb ante), \"plo9\" = pot-limit Omaha 9-max cash, \"plo6hu\" = 6-card Omaha heads-up (BTN vs BB, 100bb). Cash trees are not tournament, ICM, PKO, or satellite solves. nlmtt8, nlh8-hydra and nlhu are chip-EV; only nlh8-icm is ICM." - changed
Input schema / properties / game / enumPrevious value: -[ - "nl", - "nl9", - "nlmtt8", - "nlh8-hydra", - "plo", - "plo5", - "plo9", - "plo6hu" -]New value: +[ + "nl", + "nl9", + "nlmtt8", + "nlh8-hydra", + "nlh8-icm", + "nlhu", + "plo", + "plo5", + "plo9", + "plo6hu" +]
- Changed
get_node3 fields changed- changed
Input schema / properties / game / descriptionPrevious value: -"\"nl\" = no-limit hold'em 6-max cash (169-grid hands, per-hand EV in small blinds), \"nl9\" = no-limit hold'em 9-max cash, \"nlmtt8\" = no-limit hold'em 8-max MTT chip-EV (10–300bb, 1bb BB-ante; Fold/Call/Limp/AI/Open/3B tokens), \"nlh8-hydra\" = no-limit hold'em 8-max MTT chip-EV with a classic 0.1bb ante from every seat (10, 20, 30, 60bb; same tokens as nlmtt8), \"plo\" = pot-limit Omaha 6-max cash (4-card), \"plo5\" = pot-limit Omaha 5-card 6-max (100bb, 1.2bb ante), \"plo9\" = pot-limit Omaha 9-max cash, \"plo6hu\" = 6-card Omaha heads-up (BTN vs BB, 100bb). Cash trees are not tournament, ICM, PKO, or satellite solves. nlmtt8 is chip-EV only."New value: +"\"nl\" = no-limit hold'em 6-max cash (169-grid hands, per-hand EV in small blinds), \"nl9\" = no-limit hold'em 9-max cash, \"nlmtt8\" = no-limit hold'em 8-max MTT chip-EV (10–300bb, 1bb BB-ante; Fold/Call/Limp/AI/Open/3B tokens), \"nlh8-hydra\" = no-limit hold'em 8-max MTT chip-EV with a classic 0.1bb ante from every seat (10, 20, 30, 60bb; same tokens as nlmtt8), \"nlh8-icm\" = no-limit hold'em 8-max MTT with ICM: one stack table per scenario (near the money, 33 or 35 left of 200, 30 paid; final table, 8 left), uneven stacks, 0.125bb ante from every seat, EVs in tournament dollars; pass scenario (list_games lists them; stack alone works only where one table has that depth); get_node only, \"nlhu\" = no-limit hold'em heads-up for the title, chip-EV, both players at the stack (1–40bb), 0.125bb ante each, SB on the button; get_node only, \"plo\" = pot-limit Omaha 6-max cash (4-card), \"plo5\" = pot-limit Omaha 5-card 6-max (100bb, 1.2bb ante), \"plo9\" = pot-limit Omaha 9-max cash, \"plo6hu\" = 6-card Omaha heads-up (BTN vs BB, 100bb). Cash trees are not tournament, ICM, PKO, or satellite solves. nlmtt8, nlh8-hydra and nlhu are chip-EV; only nlh8-icm is ICM." - changed
Input schema / properties / game / enumPrevious value: -[ - "nl", - "nl9", - "nlmtt8", - "nlh8-hydra", - "plo", - "plo5", - "plo9", - "plo6hu" -]New value: +[ + "nl", + "nl9", + "nlmtt8", + "nlh8-hydra", + "nlh8-icm", + "nlhu", + "plo", + "plo5", + "plo9", + "plo6hu" +] - added
Input schema / properties / scenarioAdded value: +{ + "description": "nlh8-icm only: the stack table, e.g. \"33left-avg40-big-btn\" (list_games lists them). Needed when several tables share the stack.", + "type": "string" +}
- Changed
get_range2 fields changed- changed
Input schema / properties / game / descriptionPrevious value: -"\"nl\" = no-limit hold'em 6-max cash (169-grid hands, per-hand EV in small blinds), \"nl9\" = no-limit hold'em 9-max cash, \"nlmtt8\" = no-limit hold'em 8-max MTT chip-EV (10–300bb, 1bb BB-ante; Fold/Call/Limp/AI/Open/3B tokens), \"nlh8-hydra\" = no-limit hold'em 8-max MTT chip-EV with a classic 0.1bb ante from every seat (10, 20, 30, 60bb; same tokens as nlmtt8), \"plo\" = pot-limit Omaha 6-max cash (4-card), \"plo5\" = pot-limit Omaha 5-card 6-max (100bb, 1.2bb ante), \"plo9\" = pot-limit Omaha 9-max cash, \"plo6hu\" = 6-card Omaha heads-up (BTN vs BB, 100bb). Cash trees are not tournament, ICM, PKO, or satellite solves. nlmtt8 is chip-EV only."New value: +"\"nl\" = no-limit hold'em 6-max cash (169-grid hands, per-hand EV in small blinds), \"nl9\" = no-limit hold'em 9-max cash, \"nlmtt8\" = no-limit hold'em 8-max MTT chip-EV (10–300bb, 1bb BB-ante; Fold/Call/Limp/AI/Open/3B tokens), \"nlh8-hydra\" = no-limit hold'em 8-max MTT chip-EV with a classic 0.1bb ante from every seat (10, 20, 30, 60bb; same tokens as nlmtt8), \"nlh8-icm\" = no-limit hold'em 8-max MTT with ICM: one stack table per scenario (near the money, 33 or 35 left of 200, 30 paid; final table, 8 left), uneven stacks, 0.125bb ante from every seat, EVs in tournament dollars; pass scenario (list_games lists them; stack alone works only where one table has that depth); get_node only, \"nlhu\" = no-limit hold'em heads-up for the title, chip-EV, both players at the stack (1–40bb), 0.125bb ante each, SB on the button; get_node only, \"plo\" = pot-limit Omaha 6-max cash (4-card), \"plo5\" = pot-limit Omaha 5-card 6-max (100bb, 1.2bb ante), \"plo9\" = pot-limit Omaha 9-max cash, \"plo6hu\" = 6-card Omaha heads-up (BTN vs BB, 100bb). Cash trees are not tournament, ICM, PKO, or satellite solves. nlmtt8, nlh8-hydra and nlhu are chip-EV; only nlh8-icm is ICM." - changed
Input schema / properties / game / enumPrevious value: -[ - "nl", - "nl9", - "nlmtt8", - "nlh8-hydra", - "plo", - "plo5", - "plo9", - "plo6hu" -]New value: +[ + "nl", + "nl9", + "nlmtt8", + "nlh8-hydra", + "nlh8-icm", + "nlhu", + "plo", + "plo5", + "plo9", + "plo6hu" +]
- Changed
list_spots2 fields changed- changed
Input schema / properties / game / descriptionPrevious value: -"\"nl\" = no-limit hold'em 6-max cash (169-grid hands, per-hand EV in small blinds), \"nl9\" = no-limit hold'em 9-max cash, \"nlmtt8\" = no-limit hold'em 8-max MTT chip-EV (10–300bb, 1bb BB-ante; Fold/Call/Limp/AI/Open/3B tokens), \"nlh8-hydra\" = no-limit hold'em 8-max MTT chip-EV with a classic 0.1bb ante from every seat (10, 20, 30, 60bb; same tokens as nlmtt8), \"plo\" = pot-limit Omaha 6-max cash (4-card), \"plo5\" = pot-limit Omaha 5-card 6-max (100bb, 1.2bb ante), \"plo9\" = pot-limit Omaha 9-max cash, \"plo6hu\" = 6-card Omaha heads-up (BTN vs BB, 100bb). Cash trees are not tournament, ICM, PKO, or satellite solves. nlmtt8 is chip-EV only."New value: +"\"nl\" = no-limit hold'em 6-max cash (169-grid hands, per-hand EV in small blinds), \"nl9\" = no-limit hold'em 9-max cash, \"nlmtt8\" = no-limit hold'em 8-max MTT chip-EV (10–300bb, 1bb BB-ante; Fold/Call/Limp/AI/Open/3B tokens), \"nlh8-hydra\" = no-limit hold'em 8-max MTT chip-EV with a classic 0.1bb ante from every seat (10, 20, 30, 60bb; same tokens as nlmtt8), \"nlh8-icm\" = no-limit hold'em 8-max MTT with ICM: one stack table per scenario (near the money, 33 or 35 left of 200, 30 paid; final table, 8 left), uneven stacks, 0.125bb ante from every seat, EVs in tournament dollars; pass scenario (list_games lists them; stack alone works only where one table has that depth); get_node only, \"nlhu\" = no-limit hold'em heads-up for the title, chip-EV, both players at the stack (1–40bb), 0.125bb ante each, SB on the button; get_node only, \"plo\" = pot-limit Omaha 6-max cash (4-card), \"plo5\" = pot-limit Omaha 5-card 6-max (100bb, 1.2bb ante), \"plo9\" = pot-limit Omaha 9-max cash, \"plo6hu\" = 6-card Omaha heads-up (BTN vs BB, 100bb). Cash trees are not tournament, ICM, PKO, or satellite solves. nlmtt8, nlh8-hydra and nlhu are chip-EV; only nlh8-icm is ICM." - changed
Input schema / properties / game / enumPrevious value: -[ - "nl", - "nl9", - "nlmtt8", - "nlh8-hydra", - "plo", - "plo5", - "plo9", - "plo6hu" -]New value: +[ + "nl", + "nl9", + "nlmtt8", + "nlh8-hydra", + "nlh8-icm", + "nlhu", + "plo", + "plo5", + "plo9", + "plo6hu" +]
3 tool updates
- Added
get_started - Added
list_my_requests - Added
submit_request
29 tool updates
- Changed
compare_strategies15 fields changed- added
Input schema / properties / baseline / descriptionAdded value: +"The context deltas are measured from. One side of the comparison. Preflop contexts use game, stack, history and optional hand; postflop contexts use pack, board, path and optional combo." - added
Input schema / properties / baseline / properties / board / descriptionAdded value: +"Postflop only. Board in spaced form, e.g. \"3h 3d 2s\"." - added
Input schema / properties / baseline / properties / combo / descriptionAdded value: +"Postflop only. Exact two-card combo, e.g. As5s. Provide it in both contexts or neither." - added
Input schema / properties / baseline / properties / game / descriptionAdded value: +"Preflop only. Both sides must name the same game." - added
Input schema / properties / baseline / properties / hand / descriptionAdded value: +"Preflop only. One hand or class, e.g. AKs. Provide it in both contexts or neither; PLO comparisons require it." - added
Input schema / properties / baseline / properties / history / descriptionAdded value: +"Preflop only. Action path ending in the position about to act, e.g. \"UTG_60%_HJ\"." - added
Input schema / properties / baseline / properties / stack / descriptionAdded value: +"Preflop only. Stack depth in big blinds." - added
Input schema / properties / comparison / descriptionAdded value: +"The context deltas are measured to. One side of the comparison. Preflop contexts use game, stack, history and optional hand; postflop contexts use pack, board, path and optional combo." - added
Input schema / properties / comparison / properties / board / descriptionAdded value: +"Postflop only. Board in spaced form, e.g. \"3h 3d 2s\"." - added
Input schema / properties / comparison / properties / combo / descriptionAdded value: +"Postflop only. Exact two-card combo, e.g. As5s. Provide it in both contexts or neither." - added
Input schema / properties / comparison / properties / game / descriptionAdded value: +"Preflop only. Both sides must name the same game." - added
Input schema / properties / comparison / properties / hand / descriptionAdded value: +"Preflop only. One hand or class, e.g. AKs. Provide it in both contexts or neither; PLO comparisons require it." - added
Input schema / properties / comparison / properties / history / descriptionAdded value: +"Preflop only. Action path ending in the position about to act, e.g. \"UTG_60%_HJ\"." - added
Input schema / properties / comparison / properties / stack / descriptionAdded value: +"Preflop only. Stack depth in big blinds." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "Coverage-first envelope: coverage and context describe the answer, result carries it.", + "properties": { + "context": { + "description": "Canonical context the answer belongs to (variant, format, stacks, positions, board, path). Null when the request is unsupported.", + "type": [ + "object", + "null" + ] + }, + "coverage": { + "description": "Whether the request was answered exactly, aggregated, or refused as out of coverage.", + "properties": { + "analyzedBoards": { + "description": "Boards actually read at the requested path.", + "type": "integer" + }, + "available": { + "description": "What is published instead.", + "type": "string" + }, + "dataClass": { + "description": "\"solver\", \"solver_aggregate\", or \"solver_comparison\".", + "type": "string" + }, + "generatedAt": { + "description": "When the pack was generated.", + "type": "string" + }, + "hasEv": { + "description": "Whether the pack ships per-combo EV.", + "type": "boolean" + }, + "matchingBoards": { + "description": "Boards matching the texture filters.", + "type": "integer" + }, + "objective": { + "description": "\"solver_ev\", \"cash_game_ev\", or \"chip_ev\".", + "type": "string" + }, + "omittedByLimit": { + "description": "Matching boards dropped by boardLimit.", + "type": "integer" + }, + "reason": { + "description": "Why the request is out of coverage.", + "type": "string" + }, + "requested": { + "description": "The format, objective, ante, or pack that was asked for.", + "type": "object" + }, + "solveQuality": { + "description": "Published exploitability and iteration counts. Omitted, never estimated, when the pack does not publish them.", + "type": "object" + }, + "source": { + "description": "Pack, board, path, generation time, and solve quality.", + "type": "object" + }, + "status": { + "description": "\"exact\", \"aggregated_report\", or \"unsupported\". Treat \"unsupported\" as a hard stop.", + "type": "string" + }, + "unavailableAtPath": { + "description": "Selected boards with no node at the path.", + "type": "integer" + } + }, + "type": "object" + }, + "result": { + "description": "Both snapshots, the per-action frequency and EV deltas, and the largest combo changes for postflop comparisons. Null when the request is unsupported.", + "type": [ + "object", + "null" + ] + }, + "schemaVersion": { + "description": "Envelope version, currently \"1.0\".", + "type": "string" + }, + "warnings": { + "description": "Caveats that must survive into any answer built on this result.", + "items": { + "description": "One caveat about how the result may be used.", + "type": "string" + }, + "type": "array" + } + }, + "type": "object" +}
- Changed
enqueue_solve12 fields changed- added
Input schema / properties / add_allin / descriptionAdded value: +"Add an all-in branch alongside the bet sizes." - added
Input schema / properties / bet_sizes / descriptionAdded value: +"Bet sizes as fractions of the pot, e.g. [0.33, 0.75]." - added
Input schema / properties / board / descriptionAdded value: +"Board to solve, e.g. \"3h 3d 2s\"." - added
Input schema / properties / effective_stack / descriptionAdded value: +"Effective stack behind, in big blinds." - added
Input schema / properties / ip_range / descriptionAdded value: +"In-position range in the same weights format." - added
Input schema / properties / iterations / descriptionAdded value: +"Requested solver iterations, 50 to 5000." - added
Input schema / properties / max_aggressions / descriptionAdded value: +"Raises allowed per street, 1 to 4." - added
Input schema / properties / oop_range / descriptionAdded value: +"Out-of-position range as hand-class weights, e.g. \"AA:1,AKs:0.42\". Defaults are left to the solver config." - added
Input schema / properties / pot / descriptionAdded value: +"Starting pot in big blinds." - added
Input schema / properties / tags / descriptionAdded value: +"Free-form tags stored with the job." - added
Input schema / properties / title / descriptionAdded value: +"Label for the job, 1 to 120 characters." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "One recorded solve request. Dispatch is not configured, so a job stays pending and never gets a solution id.", + "properties": { + "board": { + "description": "Board for the requested solve.", + "type": "string" + }, + "createdAt": { + "description": "ISO timestamp the job was recorded.", + "type": "string" + }, + "dispatch": { + "description": "Always \"not_configured\".", + "type": "string" + }, + "effective_stack": { + "description": "Effective stack in big blinds.", + "type": "number" + }, + "pot": { + "description": "Pot in big blinds.", + "type": "number" + }, + "queue_id": { + "description": "Id for get_queued_solve.", + "type": "integer" + }, + "reason": { + "description": "Why the job does not start a solve.", + "type": "string" + }, + "solution_id": { + "description": "Always null while dispatch is disabled.", + "type": [ + "string", + "null" + ] + }, + "status": { + "description": "\"pending\", \"running\", \"done\", or \"failed\".", + "type": "string" + }, + "title": { + "description": "Title given when the job was recorded.", + "type": "string" + } + }, + "type": "object" +}
- Changed
explain_combo1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "Coverage-first envelope: coverage and context describe the answer, result carries it.", + "properties": { + "context": { + "description": "Canonical context the answer belongs to (variant, format, stacks, positions, board, path). Null when the request is unsupported.", + "type": [ + "object", + "null" + ] + }, + "coverage": { + "description": "Whether the request was answered exactly, aggregated, or refused as out of coverage.", + "properties": { + "analyzedBoards": { + "description": "Boards actually read at the requested path.", + "type": "integer" + }, + "available": { + "description": "What is published instead.", + "type": "string" + }, + "dataClass": { + "description": "\"solver\", \"solver_aggregate\", or \"solver_comparison\".", + "type": "string" + }, + "generatedAt": { + "description": "When the pack was generated.", + "type": "string" + }, + "hasEv": { + "description": "Whether the pack ships per-combo EV.", + "type": "boolean" + }, + "matchingBoards": { + "description": "Boards matching the texture filters.", + "type": "integer" + }, + "objective": { + "description": "\"solver_ev\", \"cash_game_ev\", or \"chip_ev\".", + "type": "string" + }, + "omittedByLimit": { + "description": "Matching boards dropped by boardLimit.", + "type": "integer" + }, + "reason": { + "description": "Why the request is out of coverage.", + "type": "string" + }, + "requested": { + "description": "The format, objective, ante, or pack that was asked for.", + "type": "object" + }, + "solveQuality": { + "description": "Published exploitability and iteration counts. Omitted, never estimated, when the pack does not publish them.", + "type": "object" + }, + "source": { + "description": "Pack, board, path, generation time, and solve quality.", + "type": "object" + }, + "status": { + "description": "\"exact\", \"aggregated_report\", or \"unsupported\". Treat \"unsupported\" as a hard stop.", + "type": "string" + }, + "unavailableAtPath": { + "description": "Selected boards with no node at the path.", + "type": "integer" + } + }, + "type": "object" + }, + "result": { + "description": "Recommendation, made-hand and draw classification, blockers, the exact action mix with EV, and same-rank-class suit comparisons. Null when the request is unsupported.", + "type": [ + "object", + "null" + ] + }, + "schemaVersion": { + "description": "Envelope version, currently \"1.0\".", + "type": "string" + }, + "warnings": { + "description": "Caveats that must survive into any answer built on this result.", + "items": { + "description": "One caveat about how the result may be used.", + "type": "string" + }, + "type": "array" + } + }, + "type": "object" +}
- Changed
find_hands10 fields changed- changed
Input schema / properties / filter / anyOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "facedLimp": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } - ] - }, - "facedThreeBet": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } - ] - }, - "flopBetPctPot": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "max": { - "anyOf": [ - { - "description": "Exclusive upper bound, % of pot.", - "minimum": 0, - "type": "number" - }, - { - "type": "null" - } - ] - }, - "min": { - "anyOf": [ - { - "description": "Inclusive lower bound, % of pot.", - "minimum": 0, - "type": "number" - }, - { - "type": "null" - } - ] - } - }, - "type": "object" - }, - { - "type": "null" - } - ] - }, - "flopFacedBetPctPot": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "max": { - "anyOf": [ - { - "description": "Exclusive upper bound, % of pot.", - "minimum": 0, - "type": "number" - }, - { - "type": "null" - } - ] - }, - "min": { - "anyOf": [ - { - "description": "Inclusive lower bound, % of pot.", - "minimum": 0, - "type": "number" - }, - { - "type": "null" - } - ] - } - }, - "type": "object" - }, - { - "type": "null" - } - ] - }, - "flopFirstAction": { - "anyOf": [ - { - "items": { - "enum": [ - "check", - "bet", - "call", - "fold", - "raise" - ], - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "flopFirstResponseToBet": { - "anyOf": [ - { - "items": { - "enum": [ - "check", - "bet", - "call", - "fold", - "raise" - ], - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "foldedToThreeBet": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } - ] - }, - "isIpVsPfr": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } - ] - }, - "isPfr": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } - ] - }, - "limped": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } - ] - }, - "pfr": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } - ] - }, - "position": { - "anyOf": [ - { - "items": { - "enum": [ - "UTG", - "UTG1", - "UTG2", - "MP", - "LJ", - "HJ", - "CO", - "BTN", - "SB", - "BB" - ], - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "rfi": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } - ] - }, - "rfiOpp": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } - ] - }, - "riverBetPctPot": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "max": { - "anyOf": [ - { - "description": "Exclusive upper bound, % of pot.", - "minimum": 0, - "type": "number" - }, - { - "type": "null" - } - ] - }, - "min": { - "anyOf": [ - { - "description": "Inclusive lower bound, % of pot.", - "minimum": 0, - "type": "number" - }, - { - "type": "null" - } - ] - } - }, - "type": "object" - }, - { - "type": "null" - } - ] - }, - "riverFacedBetPctPot": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "max": { - "anyOf": [ - { - "description": "Exclusive upper bound, % of pot.", - "minimum": 0, - "type": "number" - }, - { - "type": "null" - } - ] - }, - "min": { - "anyOf": [ - { - "description": "Inclusive lower bound, % of pot.", - "minimum": 0, - "type": "number" - }, - { - "type": "null" - } - ] - } - }, - "type": "object" - }, - { - "type": "null" - } - ] - }, - "riverFirstAction": { - "anyOf": [ - { - "items": { - "enum": [ - "check", - "bet", - "call", - "fold", - "raise" - ], - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "riverFirstResponseToBet": { - "anyOf": [ - { - "items": { - "enum": [ - "check", - "bet", - "call", - "fold", - "raise" - ], - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "sawFlop": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } - ] - }, - "sawShowdown": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } - ] - }, - "threeBet": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } - ] - }, - "turnBetPctPot": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "max": { - "anyOf": [ - { - "description": "Exclusive upper bound, % of pot.", - "minimum": 0, - "type": "number" - }, - { - "type": "null" - } - ] - }, - "min": { - "anyOf": [ - { - "description": "Inclusive lower bound, % of pot.", - "minimum": 0, - "type": "number" - }, - { - "type": "null" - } - ] - } - }, - "type": "object" - }, - { - "type": "null" - } - ] - }, - "turnFacedBetPctPot": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "max": { - "anyOf": [ - { - "description": "Exclusive upper bound, % of pot.", - "minimum": 0, - "type": "number" - }, - { - "type": "null" - } - ] - }, - "min": { - "anyOf": [ - { - "description": "Inclusive lower bound, % of pot.", - "minimum": 0, - "type": "number" - }, - { - "type": "null" - } - ] - } - }, - "type": "object" - }, - { - "type": "null" - } - ] - }, - "turnFirstAction": { - "anyOf": [ - { - "items": { - "enum": [ - "check", - "bet", - "call", - "fold", - "raise" - ], - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "turnFirstResponseToBet": { - "anyOf": [ - { - "items": { - "enum": [ - "check", - "bet", - "call", - "fold", - "raise" - ], - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "vpip": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } - ] - }, - "vsThreeBetAction": { - "anyOf": [ - { - "description": "Opener's action vs a 3-bet: fold, call, or raise (4-bet).", - "items": { - "enum": [ - "fold", - "call", - "raise" - ], - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "wasSrp": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } - ] - }, - "wasThreeBetPot": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } - ] - }, - "wonAtShowdown": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } - ] - } - }, - "type": "object" - }, - { - "type": "null" - } -]New value: +[ + { + "additionalProperties": false, + "description": "Hand-level filters. Every field is optional; null means the filter is not applied.", + "properties": { + "facedLimp": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Hero acted after an opponent's open limp." + }, + "facedThreeBet": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Hero's open was 3-bet." + }, + "flopBetPctPot": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "max": { + "anyOf": [ + { + "minimum": 0, + "type": "number" + }, + { + "type": "null" + } + ], + "description": "Exclusive upper bound, % of pot." + }, + "min": { + "anyOf": [ + { + "minimum": 0, + "type": "number" + }, + { + "type": "null" + } + ], + "description": "Inclusive lower bound, % of pot." + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "Size of hero's flop bet, as % of pot." + }, + "flopFacedBetPctPot": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "max": { + "anyOf": [ + { + "minimum": 0, + "type": "number" + }, + { + "type": "null" + } + ], + "description": "Exclusive upper bound, % of pot." + }, + "min": { + "anyOf": [ + { + "minimum": 0, + "type": "number" + }, + { + "type": "null" + } + ], + "description": "Inclusive lower bound, % of pot." + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "Size of the flop bet hero faced, as % of pot." + }, + "flopFirstAction": { + "anyOf": [ + { + "items": { + "enum": [ + "check", + "bet", + "call", + "fold", + "raise" + ], + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Hero's first action on the flop." + }, + "flopFirstResponseToBet": { + "anyOf": [ + { + "items": { + "enum": [ + "check", + "bet", + "call", + "fold", + "raise" + ], + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Hero's first action facing a flop bet." + }, + "foldedToThreeBet": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Hero folded to a 3-bet." + }, + "isIpVsPfr": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Hero was in position against the preflop raiser." + }, + "isPfr": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Hero was the preflop raiser." + }, + "limped": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Hero open-limped." + }, + "pfr": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Hero raised preflop." + }, + "position": { + "anyOf": [ + { + "items": { + "enum": [ + "UTG", + "UTG1", + "UTG2", + "MP", + "LJ", + "HJ", + "CO", + "BTN", + "SB", + "BB" + ], + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Keep hands where hero sat in one of these seats." + }, + "rfi": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Hero raised first in." + }, + "rfiOpp": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Hero had a raise-first-in opportunity (folded to hero)." + }, + "riverBetPctPot": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "max": { + "anyOf": [ + { + "minimum": 0, + "type": "number" + }, + { + "type": "null" + } + ], + "description": "Exclusive upper bound, % of pot." + }, + "min": { + "anyOf": [ + { + "minimum": 0, + "type": "number" + }, + { + "type": "null" + } + ], + "description": "Inclusive lower bound, % of pot." + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "Size of hero's river bet, as % of pot." + }, + "riverFacedBetPctPot": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "max": { + "anyOf": [ + { + "minimum": 0, + "type": "number" + }, + { + "type": "null" + } + ], + "description": "Exclusive upper bound, % of pot." + }, + "min": { + "anyOf": [ + { + "minimum": 0, + "type": "number" + }, + { + "type": "null" + } + ], + "description": "Inclusive lower bound, % of pot." + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "Size of the river bet hero faced, as % of pot." + }, + "riverFirstAction": { + "anyOf": [ + { + "items": { + "enum": [ + "check", + "bet", + "call", + "fold", + "raise" + ], + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Hero's first action on the river." + }, + "riverFirstResponseToBet": { + "anyOf": [ + { + "items": { + "enum": [ + "check", + "bet", + "call", + "fold", + "raise" + ], + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Hero's first action facing a river bet." + }, + "sawFlop": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Hero saw a flop." + }, + "sawShowdown": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Hand reached showdown." + }, + "threeBet": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Hero 3-bet." + }, + "turnBetPctPot": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "max": { + "anyOf": [ + { + "minimum": 0, + "type": "number" + }, + { + "type": "null" + } + ], + "description": "Exclusive upper bound, % of pot." + }, + "min": { + "anyOf": [ + { + "minimum": 0, + "type": "number" + }, + { + "type": "null" + } + ], + "description": "Inclusive lower bound, % of pot." + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "Size of hero's turn bet, as % of pot." + }, + "turnFacedBetPctPot": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "max": { + "anyOf": [ + { + "minimum": 0, + "type": "number" + }, + { + "type": "null" + } + ], + "description": "Exclusive upper bound, % of pot." + }, + "min": { + "anyOf": [ + { + "minimum": 0, + "type": "number" + }, + { + "type": "null" + } + ], + "description": "Inclusive lower bound, % of pot." + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "Size of the turn bet hero faced, as % of pot." + }, + "turnFirstAction": { + "anyOf": [ + { + "items": { + "enum": [ + "check", + "bet", + "call", + "fold", + "raise" + ], + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Hero's first action on the turn." + }, + "turnFirstResponseToBet": { + "anyOf": [ + { + "items": { + "enum": [ + "check", + "bet", + "call", + "fold", + "raise" + ], + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Hero's first action facing a turn bet." + }, + "vpip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Hero put money in voluntarily." + }, + "vsThreeBetAction": { + "anyOf": [ + { + "items": { + "enum": [ + "fold", + "call", + "raise" + ], + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Opener's action vs a 3-bet: fold, call, or raise (4-bet)." + }, + "wasSrp": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Hand was a single-raised pot." + }, + "wasThreeBetPot": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Hand was a 3-bet pot." + }, + "wonAtShowdown": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Hero won at showdown." + } + }, + "type": "object" + }, + { + "type": "null" + } +] - added
Input schema / properties / filter / descriptionAdded value: +"Hand-level filters, all optional." - added
Input schema / properties / game_type / descriptionAdded value: +"Only hands of this game type. Matches hole-card count." - added
Input schema / properties / gto_plo5_rfi_bucket / descriptionAdded value: +"Solver grade bucket for PLO5 raise-first-in. Grades are not computed, so any value matches nothing." - added
Input schema / properties / gto_vs_3bet_bucket / descriptionAdded value: +"Solver grade bucket for hero's action vs a 3-bet. Grades are not computed, so any value matches nothing rather than inventing a frequency." - added
Input schema / properties / limit / descriptionAdded value: +"Hands to return, 1 to 50." - added
Input schema / properties / session_id / descriptionAdded value: +"Only hands from this upload session (see list_my_sessions)." - added
Input schema / properties / sort / descriptionAdded value: +"Row order: newest first, largest win first, or largest loss first (the default)." - added
Input schema / properties / table_size / descriptionAdded value: +"Only hands dealt at tables of this many seats." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "Hands this account has uploaded.", + "properties": { + "gto": { + "description": "Always \"not graded\": solver grades are not attached.", + "type": "string" + }, + "gtoNote": { + "description": "Why a solver-grade filter matches nothing.", + "type": "string" + }, + "hands": { + "description": "Matching hands, sorted as requested.", + "items": { + "description": "One uploaded hand.", + "properties": { + "board": { + "description": "Board as dealt.", + "type": [ + "string", + "null" + ] + }, + "cards": { + "description": "Hero's hole cards.", + "type": [ + "string", + "null" + ] + }, + "flop": { + "description": "Flop action lines.", + "items": { + "description": "One flop action line.", + "type": "string" + }, + "type": "array" + }, + "game": { + "description": "Game type: \"NLHE\", \"PLO\", \"PLO5\", or \"PLO6\".", + "type": "string" + }, + "gto_plo5_rfi_bucket": { + "description": "Solver grade bucket. Not filled: grades are not computed.", + "type": [ + "string", + "null" + ] + }, + "gto_status": { + "description": "Always \"not_graded\": no solver frequency is attached to uploaded hands.", + "type": "string" + }, + "gto_vs_3bet_bucket": { + "description": "Solver grade bucket. Not filled: grades are not computed.", + "type": [ + "string", + "null" + ] + }, + "handAt": { + "description": "Hand timestamp as written in the history.", + "type": [ + "string", + "null" + ] + }, + "hand_id": { + "description": "Stable id for this hand.", + "type": "string" + }, + "netBb": { + "description": "Hero's result in big blinds.", + "type": "number" + }, + "position": { + "description": "Hero's seat, e.g. BTN.", + "type": [ + "string", + "null" + ] + }, + "potType": { + "description": "Preflop pot type, e.g. \"srp\" or \"3bet\".", + "type": [ + "string", + "null" + ] + }, + "preflop": { + "description": "Preflop action lines.", + "items": { + "description": "One preflop action line.", + "type": "string" + }, + "type": "array" + }, + "river": { + "description": "River action lines.", + "items": { + "description": "One river action line.", + "type": "string" + }, + "type": "array" + }, + "session_id": { + "description": "Upload session the hand came from.", + "type": "string" + }, + "source_hand_id": { + "description": "Hand id printed by the original site.", + "type": [ + "string", + "null" + ] + }, + "table_size": { + "description": "Seats at the table.", + "type": [ + "number", + "null" + ] + }, + "timezone": { + "description": "Timezone label from the history.", + "type": [ + "string", + "null" + ] + }, + "turn": { + "description": "Turn action lines.", + "items": { + "description": "One turn action line.", + "type": "string" + }, + "type": "array" + }, + "vsThreeBetAction": { + "description": "Hero's action facing a 3-bet: \"fold\", \"call\", or \"raise\".", + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + "hint": { + "description": "Where to upload hands when the account has none.", + "type": "string" + }, + "returned": { + "description": "Hands in this response.", + "type": "integer" + }, + "total": { + "description": "Matching hands before the limit.", + "type": "integer" + } + }, + "type": "object" +}
- Changed
get_board_report7 fields changed- added
Input schema / properties / filters / descriptionAdded value: +"Texture filters applied to the pack's solved boards. All optional; omit for every board." - added
Input schema / properties / filters / properties / connectivity / descriptionAdded value: +"How many board cards sit inside one five-rank straight window." - added
Input schema / properties / filters / properties / highCard / descriptionAdded value: +"Exact highest board rank." - added
Input schema / properties / filters / properties / highCardClass / descriptionAdded value: +"Highest board rank bucketed: ace, ten through king, seven through nine, or lower." - added
Input schema / properties / filters / properties / pairedness / descriptionAdded value: +"Rank repetition on the board." - added
Input schema / properties / filters / properties / suitTexture / descriptionAdded value: +"Most cards of one suit on the board. A three-card monotone flop is monotone." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "Coverage-first envelope: coverage and context describe the answer, result carries it.", + "properties": { + "context": { + "description": "Canonical context the answer belongs to (variant, format, stacks, positions, board, path). Null when the request is unsupported.", + "type": [ + "object", + "null" + ] + }, + "coverage": { + "description": "Whether the request was answered exactly, aggregated, or refused as out of coverage.", + "properties": { + "analyzedBoards": { + "description": "Boards actually read at the requested path.", + "type": "integer" + }, + "available": { + "description": "What is published instead.", + "type": "string" + }, + "dataClass": { + "description": "\"solver\", \"solver_aggregate\", or \"solver_comparison\".", + "type": "string" + }, + "generatedAt": { + "description": "When the pack was generated.", + "type": "string" + }, + "hasEv": { + "description": "Whether the pack ships per-combo EV.", + "type": "boolean" + }, + "matchingBoards": { + "description": "Boards matching the texture filters.", + "type": "integer" + }, + "objective": { + "description": "\"solver_ev\", \"cash_game_ev\", or \"chip_ev\".", + "type": "string" + }, + "omittedByLimit": { + "description": "Matching boards dropped by boardLimit.", + "type": "integer" + }, + "reason": { + "description": "Why the request is out of coverage.", + "type": "string" + }, + "requested": { + "description": "The format, objective, ante, or pack that was asked for.", + "type": "object" + }, + "solveQuality": { + "description": "Published exploitability and iteration counts. Omitted, never estimated, when the pack does not publish them.", + "type": "object" + }, + "source": { + "description": "Pack, board, path, generation time, and solve quality.", + "type": "object" + }, + "status": { + "description": "\"exact\", \"aggregated_report\", or \"unsupported\". Treat \"unsupported\" as a hard stop.", + "type": "string" + }, + "unavailableAtPath": { + "description": "Selected boards with no node at the path.", + "type": "integer" + } + }, + "type": "object" + }, + "result": { + "description": "Action frequencies and range composition aggregated across solved boards, with equal weight per board, plus representative boards. Null when the request is unsupported.", + "type": [ + "object", + "null" + ] + }, + "schemaVersion": { + "description": "Envelope version, currently \"1.0\".", + "type": "string" + }, + "warnings": { + "description": "Caveats that must survive into any answer built on this result.", + "items": { + "description": "One caveat about how the result may be used.", + "type": "string" + }, + "type": "array" + } + }, + "type": "object" +}
- Changed
get_config1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "Table setup for one preflop game and stack, in big blinds. Convergence is not published.", + "properties": { + "ante": { + "description": "Ante in big blinds.", + "type": "number" + }, + "antePostedBy": { + "description": "Seat that posts the ante.", + "type": [ + "string", + "null" + ] + }, + "blinds": { + "description": "Blinds in big blinds.", + "properties": { + "bb": { + "description": "Big blind, 1.", + "type": "number" + }, + "sb": { + "description": "Small blind, 0.5.", + "type": "number" + } + }, + "type": "object" + }, + "evBaseline": { + "description": "What EV is measured against, \"fold\".", + "type": "string" + }, + "evUnit": { + "description": "EV unit, \"sb\".", + "type": "string" + }, + "game": { + "description": "Game id.", + "type": "string" + }, + "openSizes": { + "description": "First-in raise-to sizes, by seat, with label and sizeBb.", + "type": "object" + }, + "schemaVersion": { + "description": "Payload version, 1.", + "type": "number" + }, + "seats": { + "description": "Seats in action order.", + "items": { + "description": "Seat label.", + "type": "string" + }, + "type": "array" + }, + "stack": { + "description": "Stack depth in big blinds.", + "type": "number" + }, + "stackIncludesAnte": { + "description": "True when the named depth already contains the ante.", + "type": "boolean" + }, + "stacks": { + "description": "Starting stacks per seat. Null where the depth is solved against a different stack (10bb all-in/fold versus 50bb).", + "items": { + "description": "Starting stack in big blinds.", + "type": "number" + }, + "type": [ + "array", + "null" + ] + }, + "units": { + "description": "Unit labels for stack, stacks, blinds, ante, openSizes, and evs.", + "type": "object" + } + }, + "type": "object" +}
- Changed
get_exploitability2 fields changed- added
Input schema / properties / game / descriptionAdded value: +"Preflop game id to report on, e.g. \"nl\" or \"nlmtt8\". Any known game answers \"not available\"." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "Preflop exploitability for one game. No preflop dataset publishes one, so the answer is always unavailable and never a number.", + "properties": { + "available": { + "description": "Always false.", + "type": "boolean" + }, + "convergence": { + "description": "Always null.", + "type": [ + "number", + "null" + ] + }, + "dataset": { + "description": "Dataset the game maps to, or null when unknown.", + "type": [ + "string", + "null" + ] + }, + "exploitability": { + "description": "Always null: no figure is published or estimated.", + "type": [ + "number", + "null" + ] + }, + "game": { + "description": "Game id, echoed.", + "type": "string" + }, + "iterations": { + "description": "Always null.", + "type": [ + "number", + "null" + ] + }, + "reason": { + "description": "Why no number is returned.", + "type": "string" + }, + "status": { + "description": "Always \"not available\".", + "type": "string" + } + }, + "type": "object" +}
- Changed
get_hand_results3 fields changed- added
Input schema / properties / max_points / descriptionAdded value: +"Points on the curve after downsampling, 2 to 200." - added
Input schema / properties / session_id / descriptionAdded value: +"Only this upload session's hands. Omit for the whole account." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "Cumulative result per hand, for a winnings curve.", + "properties": { + "hint": { + "description": "Where to upload hands when the account has none.", + "type": "string" + }, + "netBb": { + "description": "Final cumulative result in big blinds.", + "type": "number" + }, + "points": { + "description": "Downsampled curve, oldest to newest.", + "items": { + "description": "One point on the curve.", + "properties": { + "bb": { + "description": "Cumulative result in big blinds.", + "type": "number" + }, + "hand": { + "description": "Hand number, oldest first.", + "type": "integer" + } + }, + "type": "object" + }, + "type": "array" + }, + "totalHands": { + "description": "Hands behind the curve.", + "type": "integer" + } + }, + "type": "object" +}
- Changed
get_node1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "Every action at one preflop decision node.", + "properties": { + "actions": { + "description": "Actions at the node.", + "items": { + "description": "One action available at a preflop node.", + "properties": { + "action": { + "description": "Action token, e.g. \"Fold\", \"Open\", \"3B\".", + "type": "string" + }, + "combos": { + "description": "Combos that take this action.", + "type": "number" + }, + "evSb": { + "description": "EV in small blinds for the requested hand, if scored.", + "type": [ + "number", + "null" + ] + }, + "evs": { + "additionalProperties": { + "description": "EV in small blinds relative to folding.", + "type": "number" + }, + "description": "Hand class to EV, only where the solved bundle scored the hand.", + "type": "object" + }, + "frequency": { + "description": "Frequency for the requested hand, or the action total.", + "type": "number" + }, + "kind": { + "description": "Action family, e.g. \"fold\", \"call\", \"raise\".", + "type": [ + "string", + "null" + ] + }, + "sizeBb": { + "description": "Raise-to size in big blinds, for raising actions.", + "type": "number" + }, + "sizePctPot": { + "description": "Raise size as a percent of the pot after calling.", + "type": "number" + }, + "weights": { + "additionalProperties": { + "description": "Action frequency from 0 to 1.", + "type": "number" + }, + "description": "Hand class to frequency. An omitted class has weight 0.", + "type": "object" + } + }, + "type": "object" + }, + "type": "array" + }, + "actor": { + "description": "Position to act at this node.", + "type": "string" + }, + "continuingCombos": { + "description": "Combos that continue past this node.", + "type": "number" + }, + "continuingHands": { + "description": "Hand classes that continue past this node.", + "type": "number" + }, + "evBaseline": { + "description": "What EV is measured against, \"fold\".", + "type": "string" + }, + "evUnit": { + "description": "EV unit, \"sb\".", + "type": "string" + }, + "game": { + "description": "Preflop game id, e.g. \"nl\" or \"nlmtt8\".", + "type": "string" + }, + "hand": { + "description": "The requested hand, when one was asked for.", + "type": "string" + }, + "hint": { + "description": "How to narrow, page, or widen the same query.", + "type": "string" + }, + "history": { + "description": "Action path ending in the acting position.", + "type": "string" + }, + "schemaVersion": { + "description": "Payload version, 1.", + "type": "number" + }, + "spot": { + "description": "Action path ending in an action, echoed from the request.", + "type": "string" + }, + "stack": { + "description": "Stack depth in big blinds.", + "type": "number" + }, + "units": { + "description": "Unit labels: stack and sizeBb in bb, evs in sb.", + "type": "object" + }, + "version": { + "description": "Dataset version where the bundle publishes one.", + "type": "number" + } + }, + "type": "object" +}
- Changed
get_opponent_limp_range7 fields changed- added
Input schema / properties / game_type / descriptionAdded value: +"Only hands of this game type." - added
Input schema / properties / limit / descriptionAdded value: +"Hole-card classes to return, most frequent first, 1 to 169." - added
Input schema / properties / opponent_id / descriptionAdded value: +"Only this opponent's limps (see list_my_opponents). Omit for every tracked villain." - added
Input schema / properties / position / descriptionAdded value: +"Only limps from these seats." - added
Input schema / properties / session_id / descriptionAdded value: +"Only hands from this upload session." - added
Input schema / properties / table_size / descriptionAdded value: +"Only hands dealt at tables of this many seats." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "Shown-hand first-in limp range from uploaded hands. Observed counts, not a solver range.", + "properties": { + "classes": { + "description": "Observed classes, most frequent first. Counts, not solver frequencies.", + "items": { + "description": "One observed hole-card class.", + "properties": { + "count": { + "description": "Times the class was shown.", + "type": "integer" + }, + "hand": { + "description": "169-grid class, e.g. AKs.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "classesByPosition": { + "additionalProperties": { + "description": "Observed classes, most frequent first. Counts, not solver frequencies.", + "items": { + "description": "One observed hole-card class.", + "properties": { + "count": { + "description": "Times the class was shown.", + "type": "integer" + }, + "hand": { + "description": "169-grid class, e.g. AKs.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "description": "Seat label to that seat's observed classes.", + "type": "object" + }, + "note": { + "description": "That the sample is showdown-only and the counts are observations.", + "type": "string" + }, + "sample": { + "description": "Shown limped hands behind the counts.", + "type": "integer" + } + }, + "type": "object" +}
- Changed
get_opponent_notes2 fields changed- added
Input schema / properties / opponent_id / descriptionAdded value: +"Opponent id from list_my_opponents." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "Leak notes computed from uploaded hands for one opponent.", + "properties": { + "display_name": { + "description": "Screen name as written in the history.", + "type": "string" + }, + "error": { + "description": "Present instead of a payload when the request named something that does not exist. No figure is estimated in its place.", + "type": "string" + }, + "notes": { + "description": "Notes, or a single line saying the sample is too small.", + "items": { + "description": "One note, with the sample size it rests on.", + "type": "string" + }, + "type": "array" + }, + "opponent_id": { + "description": "Opponent id, echoed.", + "type": "string" + } + }, + "type": "object" +}
- Changed
get_postflop_node1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "One postflop solver node: the acting player's strategy and the legal next segments.", + "properties": { + "actingPlayer": { + "description": "0 for out of position, 1 for in position.", + "type": [ + "integer", + "null" + ] + }, + "actionFreqs": { + "description": "Full detail: aggregate frequency per action.", + "items": { + "description": "Reach-weighted frequency for the action at this index.", + "type": "number" + }, + "type": "array" + }, + "actions": { + "description": "Actions at the node with their reach-weighted frequency.", + "items": { + "description": "One action available at a postflop node.", + "properties": { + "action": { + "description": "Action segment including its size, e.g. \"Bet 5.5\".", + "type": "string" + }, + "actionType": { + "description": "Action label without the size.", + "type": "string" + }, + "addBb": { + "description": "Chips this action adds, in big blinds.", + "type": "number" + }, + "comparisonKey": { + "description": "Size-normalised action key used to line two nodes up, e.g. \"Bet 75% pot\".", + "type": "string" + }, + "evBb": { + "description": "Action EV in big blinds where the pack publishes it.", + "type": [ + "number", + "null" + ] + }, + "evLossBb": { + "description": "EV given up against the best action, in big blinds.", + "type": [ + "number", + "null" + ] + }, + "frequency": { + "description": "Reach-weighted frequency from 0 to 1.", + "type": "number" + }, + "label": { + "description": "Action label, e.g. \"Check\", \"Bet\", \"Call\".", + "type": "string" + }, + "sizePotPct": { + "description": "Bet size as a percent of the pot, bets only.", + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + "board": { + "anyOf": [ + { + "description": "Board in spaced form.", + "type": "string" + }, + { + "description": "Cards visible at this node.", + "items": { + "description": "One card.", + "type": "string" + }, + "type": "array" + } + ], + "description": "Board at this node." + }, + "childSegments": { + "description": "Append one of these to `path` to walk deeper.", + "items": { + "description": "An action like \"Bet 5.5\" or a runout like \"deal:7c\".", + "type": "string" + }, + "type": "array" + }, + "columns": { + "description": "Column order for `hands`: combo, reach, frequencies, evBb, evLossBb, actionEvBb.", + "items": { + "description": "Column name.", + "type": "string" + }, + "type": "array" + }, + "combo": { + "description": "The requested combo, when one was asked for.", + "type": "string" + }, + "hands": { + "description": "Compact rows in `columns` order, or the full per-combo strategy objects in full detail.", + "items": { + "anyOf": [ + { + "description": "One compact row.", + "type": "array" + }, + { + "description": "One combo's stored strategy.", + "type": "object" + } + ] + }, + "type": "array" + }, + "hint": { + "description": "How to narrow, page, or widen the same query.", + "type": "string" + }, + "node": { + "description": "Full detail: the stored node. Null at a chance point, where runouts hang directly under the path.", + "type": [ + "object", + "null" + ] + }, + "path": { + "description": "Segments walked from the root to this node.", + "items": { + "description": "One segment from the root.", + "type": "string" + }, + "type": [ + "array", + "null" + ] + }, + "potBb": { + "description": "Pot at this node in big blinds.", + "type": [ + "number", + "null" + ] + }, + "reach": { + "description": "Full detail: the acting player's per-combo reach.", + "items": { + "description": "A combo and its reach weight.", + "type": "array" + }, + "type": "array" + }, + "summary": { + "description": "What the compact range left out, so nothing looks complete when it is sampled.", + "properties": { + "classes": { + "description": "Postflop: hand classes with reach at the node.", + "type": "integer" + }, + "matchingHands": { + "description": "plo5: classes that take the action before the cut.", + "type": "integer" + }, + "minFreq": { + "description": "plo5: the frequency floor applied.", + "type": "number" + }, + "mixedHands": { + "description": "Classes strictly between 0.005 and 0.995.", + "type": "integer" + }, + "mixedInReturned": { + "description": "plo5: mixed classes among the returned rows.", + "type": "integer" + }, + "nonzeroHands": { + "description": "Hand classes with a frequency above 0.", + "type": "integer" + }, + "omitted": { + "description": "Rows dropped by the compact cut.", + "type": "integer" + }, + "pureHands": { + "description": "Classes at frequency 0.995 or higher.", + "type": "integer" + }, + "pureInReturned": { + "description": "plo5: pure classes among the returned rows.", + "type": "integer" + }, + "returned": { + "description": "Rows in this response.", + "type": "integer" + } + }, + "type": "object" + } + }, + "type": "object" +}
- Changed
get_postflop_range4 fields changed- added
Input schema / properties / hand / descriptionAdded value: +"Optional exact combo (AsKh) or hand class (AKs) for one frequency instead of reading the whole range." - added
Input schema / properties / minFreq / descriptionAdded value: +"Drop classes at or below this weight. Default 0." - added
Input schema / properties / tree / descriptionAdded value: +"Bet-size tree. \"33\" = 33% pot on the flop, then 75% pot on the turn and river, plus all-in. \"75\" = 75% pot on every street, plus all-in. PLO5 packs are solved on \"33\" only." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "The range a player takes one flop action with, as hand-class weights.", + "properties": { + "action": { + "description": "The action whose range this is.", + "type": "string" + }, + "board": { + "description": "Canonical board as stored in the pack.", + "type": "string" + }, + "error": { + "description": "Present instead of a payload when the request named something that does not exist. No figure is estimated in its place.", + "type": "string" + }, + "hand": { + "description": "The requested hand, when one was asked for.", + "properties": { + "frequency": { + "description": "Reach-weighted frequency from 0 to 1.", + "type": "number" + }, + "hand": { + "description": "Hand or class the frequency belongs to.", + "type": "string" + } + }, + "type": "object" + }, + "pack": { + "description": "Pack id the range was read from, after tree resolution.", + "type": "string" + }, + "path": { + "description": "Flop actions, ending in the action asked for.", + "items": { + "description": "One flop action.", + "type": "string" + }, + "type": "array" + }, + "range": { + "description": "Hand-class weights as \"AA:1,AKs:0.42,…\", the preflop range format.", + "type": "string" + }, + "summary": { + "description": "What the compact range left out, so nothing looks complete when it is sampled.", + "properties": { + "classes": { + "description": "Postflop: hand classes with reach at the node.", + "type": "integer" + }, + "matchingHands": { + "description": "plo5: classes that take the action before the cut.", + "type": "integer" + }, + "minFreq": { + "description": "plo5: the frequency floor applied.", + "type": "number" + }, + "mixedHands": { + "description": "Classes strictly between 0.005 and 0.995.", + "type": "integer" + }, + "mixedInReturned": { + "description": "plo5: mixed classes among the returned rows.", + "type": "integer" + }, + "nonzeroHands": { + "description": "Hand classes with a frequency above 0.", + "type": "integer" + }, + "omitted": { + "description": "Rows dropped by the compact cut.", + "type": "integer" + }, + "pureHands": { + "description": "Classes at frequency 0.995 or higher.", + "type": "integer" + }, + "pureInReturned": { + "description": "plo5: pure classes among the returned rows.", + "type": "integer" + }, + "returned": { + "description": "Rows in this response.", + "type": "integer" + } + }, + "type": "object" + }, + "tree": { + "description": "Bet-size tree, \"33\" or \"75\".", + "type": "string" + }, + "weights": { + "additionalProperties": { + "description": "Action frequency from 0 to 1.", + "type": "number" + }, + "description": "Hand class to frequency. An omitted class has weight 0.", + "type": "object" + } + }, + "type": "object" +}
- Changed
get_queued_solve2 fields changed- added
Input schema / properties / queue_id / descriptionAdded value: +"Queue id returned by enqueue_solve." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "One recorded solve request. Dispatch is not configured, so a job stays pending and never gets a solution id.", + "properties": { + "board": { + "description": "Board for the requested solve.", + "type": "string" + }, + "createdAt": { + "description": "ISO timestamp the job was recorded.", + "type": "string" + }, + "dispatch": { + "description": "Always \"not_configured\".", + "type": "string" + }, + "effective_stack": { + "description": "Effective stack in big blinds.", + "type": "number" + }, + "pot": { + "description": "Pot in big blinds.", + "type": "number" + }, + "queue_id": { + "description": "Id for get_queued_solve.", + "type": "integer" + }, + "reason": { + "description": "Why the job does not start a solve.", + "type": "string" + }, + "solution_id": { + "description": "Always null while dispatch is disabled.", + "type": [ + "string", + "null" + ] + }, + "status": { + "description": "\"pending\", \"running\", \"done\", or \"failed\".", + "type": "string" + }, + "title": { + "description": "Title given when the job was recorded.", + "type": "string" + } + }, + "type": "object" +}
- Changed
get_range1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "One action's range: hand-class frequencies, and EV where the bundle scored it.", + "properties": { + "action": { + "description": "plo5: the action the range belongs to.", + "type": "string" + }, + "actor": { + "description": "Position to act at this node.", + "type": "string" + }, + "columns": { + "description": "Column order for `range`: hand, frequency, evSb.", + "items": { + "description": "Column name.", + "type": "string" + }, + "type": "array" + }, + "combos": { + "description": "Combos in the range.", + "type": "number" + }, + "ev": { + "description": "Full detail: EV of the requested hand in small blinds.", + "type": [ + "number", + "null" + ] + }, + "evSb": { + "description": "EV of the requested hand in small blinds.", + "type": [ + "number", + "null" + ] + }, + "evs": { + "additionalProperties": { + "description": "EV in small blinds relative to folding.", + "type": "number" + }, + "description": "Hand class to EV, only where the solved bundle scored the hand.", + "type": "object" + }, + "freq": { + "description": "Full detail: frequency of the requested hand.", + "type": "number" + }, + "frequency": { + "description": "Frequency of the requested hand, 0 to 1.", + "type": "number" + }, + "game": { + "description": "Preflop game id, e.g. \"nl\" or \"nlmtt8\".", + "type": "string" + }, + "hand": { + "description": "The requested hand, when one was asked for.", + "type": "string" + }, + "hands": { + "description": "Hand classes in the range.", + "type": "number" + }, + "hint": { + "description": "How to narrow, page, or widen the same query.", + "type": "string" + }, + "history": { + "description": "Action path ending in the acting position.", + "type": "string" + }, + "kind": { + "description": "plo5: the action family.", + "type": "string" + }, + "range": { + "description": "Compact rows in `columns` order.", + "items": { + "description": "One row: hand, frequency, EV in small blinds or null.", + "type": "array" + }, + "type": "array" + }, + "spot": { + "description": "Action path ending in an action, echoed from the request.", + "type": "string" + }, + "stack": { + "description": "Stack depth in big blinds.", + "type": "number" + }, + "summary": { + "description": "What the compact range left out, so nothing looks complete when it is sampled.", + "properties": { + "classes": { + "description": "Postflop: hand classes with reach at the node.", + "type": "integer" + }, + "matchingHands": { + "description": "plo5: classes that take the action before the cut.", + "type": "integer" + }, + "minFreq": { + "description": "plo5: the frequency floor applied.", + "type": "number" + }, + "mixedHands": { + "description": "Classes strictly between 0.005 and 0.995.", + "type": "integer" + }, + "mixedInReturned": { + "description": "plo5: mixed classes among the returned rows.", + "type": "integer" + }, + "nonzeroHands": { + "description": "Hand classes with a frequency above 0.", + "type": "integer" + }, + "omitted": { + "description": "Rows dropped by the compact cut.", + "type": "integer" + }, + "pureHands": { + "description": "Classes at frequency 0.995 or higher.", + "type": "integer" + }, + "pureInReturned": { + "description": "plo5: pure classes among the returned rows.", + "type": "integer" + }, + "returned": { + "description": "Rows in this response.", + "type": "integer" + } + }, + "type": "object" + }, + "version": { + "description": "Dataset version where the bundle publishes one.", + "type": "number" + }, + "weights": { + "additionalProperties": { + "description": "Action frequency from 0 to 1.", + "type": "number" + }, + "description": "Hand class to frequency. An omitted class has weight 0.", + "type": "object" + } + }, + "type": "object" +}
- Changed
get_range_metadata3 fields changed- added
Input schema / properties / game / descriptionAdded value: +"Preflop game id, e.g. \"nl\", \"nl9\", \"nlmtt8\", \"nlh8-hydra\", \"plo\", \"plo9\", \"plo5\", \"plo6hu\"." - added
Input schema / properties / stack / descriptionAdded value: +"Stack depth in big blinds, e.g. 100." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "Index metadata for one preflop game, stack, and path. Never a strategy, and never an invented exploitability.", + "properties": { + "actor": { + "description": "Acting position read off the path.", + "type": [ + "string", + "null" + ] + }, + "dataset": { + "description": "Dataset the game maps to.", + "type": "string" + }, + "error": { + "description": "Present instead of a payload when the request named something that does not exist. No figure is estimated in its place.", + "type": "string" + }, + "game": { + "description": "Game id, echoed.", + "type": "string" + }, + "match": { + "description": "\"bundle\", \"node\", or \"none\".", + "type": "string" + }, + "note": { + "description": "What the match means, or that nothing was estimated.", + "type": "string" + }, + "path": { + "description": "Action path, echoed.", + "type": "string" + }, + "preflopExploitability": { + "description": "Always \"not available\".", + "type": "string" + }, + "rows": { + "description": "Matching index rows.", + "items": { + "description": "One index row.", + "properties": { + "analyzed": { + "description": "Whether the row was analyzed.", + "type": "boolean" + }, + "decisionNodes": { + "description": "Decision nodes.", + "type": [ + "number", + "null" + ] + }, + "edges": { + "description": "Edges.", + "type": [ + "number", + "null" + ] + }, + "format": { + "description": "Format label.", + "type": "string" + }, + "freqSumChecks": { + "description": "Frequency-sum checks run.", + "type": [ + "number", + "null" + ] + }, + "freqSumOff": { + "description": "Checks that came out off.", + "type": [ + "number", + "null" + ] + }, + "gzBytes": { + "description": "Compressed size in bytes.", + "type": [ + "number", + "null" + ] + }, + "hasRaiseMeta": { + "description": "Whether raise metadata is stored.", + "type": "boolean" + }, + "key": { + "description": "Row key.", + "type": "string" + }, + "manifestEdgeCount": { + "description": "Edge count from the manifest.", + "type": [ + "number", + "null" + ] + }, + "maxActions": { + "description": "Most actions on any node.", + "type": [ + "number", + "null" + ] + }, + "position": { + "description": "Acting position.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "stack": { + "description": "Stack depth in big blinds, echoed.", + "type": "number" + } + }, + "type": "object" +}
- Changed
get_session_summary2 fields changed- added
Input schema / properties / session_id / descriptionAdded value: +"Session id from list_my_sessions." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "Headline numbers and HUD rates for one uploaded session.", + "properties": { + "endedAt": { + "description": "Last hand timestamp.", + "type": [ + "string", + "null" + ] + }, + "error": { + "description": "Present instead of a payload when the request named something that does not exist. No figure is estimated in its place.", + "type": "string" + }, + "game_type": { + "description": "Game type: \"NLHE\", \"PLO\", \"PLO5\", or \"PLO6\".", + "type": "string" + }, + "hands": { + "description": "Hands in the session.", + "type": "integer" + }, + "hero": { + "description": "Hero name in the history.", + "type": "string" + }, + "hud": { + "description": "HUD rates over this session, as percentages.", + "properties": { + "limp": { + "description": "Open limp, percent.", + "type": "number" + }, + "pfr": { + "description": "Preflop raise, percent.", + "type": "number" + }, + "sample": { + "description": "Hands the rates are computed over.", + "type": "integer" + }, + "threeBet": { + "description": "3-bet, percent.", + "type": "number" + }, + "vpip": { + "description": "Voluntarily put money in pot, percent.", + "type": "number" + } + }, + "type": "object" + }, + "id": { + "description": "Session id.", + "type": "string" + }, + "netBb": { + "description": "Session result in big blinds.", + "type": "number" + }, + "startedAt": { + "description": "First hand timestamp.", + "type": [ + "string", + "null" + ] + } + }, + "type": "object" +}
- Changed
get_tournament_results2 fields changed- added
Input schema / properties / limit / descriptionAdded value: +"Tournament summaries to include, 1 to 500." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "MTT results from uploaded tournament summaries. Money is in cents.", + "properties": { + "buyInCents": { + "description": "Total buy-ins, or null when one buy-in is unknown.", + "type": [ + "number", + "null" + ] + }, + "itmPct": { + "description": "Share of tournaments that cashed, 0 to 1, or null.", + "type": [ + "number", + "null" + ] + }, + "netProfitCents": { + "description": "Received minus buy-ins, or null when a buy-in is unknown.", + "type": [ + "number", + "null" + ] + }, + "note": { + "description": "Present when no tournament summaries have been uploaded.", + "type": "string" + }, + "receivedCents": { + "description": "Total prize money received.", + "type": "number" + }, + "recent": { + "description": "Tournaments, newest first.", + "items": { + "description": "One tournament.", + "properties": { + "buyInCents": { + "description": "Buy-in in cents.", + "type": [ + "number", + "null" + ] + }, + "fieldSize": { + "description": "Entrants.", + "type": [ + "number", + "null" + ] + }, + "finish": { + "description": "Finishing place.", + "type": [ + "number", + "null" + ] + }, + "game": { + "description": "Game label from the summary.", + "type": [ + "string", + "null" + ] + }, + "id": { + "description": "Row id.", + "type": "string" + }, + "receivedCents": { + "description": "Prize received in cents.", + "type": [ + "number", + "null" + ] + }, + "sourceId": { + "description": "Tournament id from the summary file.", + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + "roi": { + "description": "Return on investment as a ratio, or null.", + "type": [ + "number", + "null" + ] + }, + "tournaments": { + "description": "Tournament summaries counted.", + "type": "integer" + } + }, + "type": "object" +}
- Changed
get_tree_docs1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "Tree documentation and per-stack counts for one dataset.", + "properties": { + "coverage": { + "description": "Coverage row from the shipped README.", + "type": "string" + }, + "dataset": { + "description": "Dataset id, echoed.", + "type": "string" + }, + "error": { + "description": "Present instead of a payload when the request named something that does not exist. No figure is estimated in its place.", + "type": "string" + }, + "preflopExploitability": { + "description": "Always \"not available\".", + "type": "string" + }, + "source": { + "description": "File the coverage note came from.", + "type": "string" + }, + "stacks": { + "description": "Per-stack counts.", + "items": { + "description": "One stack depth of the dataset.", + "properties": { + "analyzed": { + "description": "Analyzed rows at this depth.", + "type": "integer" + }, + "bundles": { + "description": "Bundles at this depth, for per-bundle datasets.", + "items": { + "description": "One bundle.", + "properties": { + "analyzed": { + "description": "Whether the bundle was analyzed.", + "type": "boolean" + }, + "decisionNodes": { + "description": "Decision nodes in the bundle.", + "type": [ + "number", + "null" + ] + }, + "edges": { + "description": "Edges in the bundle.", + "type": [ + "number", + "null" + ] + }, + "gzBytes": { + "description": "Compressed size in bytes.", + "type": [ + "number", + "null" + ] + }, + "key": { + "description": "Bundle key.", + "type": "string" + }, + "position": { + "description": "Acting position the bundle covers.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "decisionNodes": { + "description": "Decision nodes across the bundles.", + "type": [ + "number", + "null" + ] + }, + "edges": { + "description": "Edges across the bundles.", + "type": [ + "number", + "null" + ] + }, + "formats": { + "description": "Formats at this depth.", + "items": { + "description": "Format label.", + "type": "string" + }, + "type": "array" + }, + "hasRaiseMeta": { + "description": "Whether raise metadata is stored.", + "type": "boolean" + }, + "note": { + "description": "How to read the rows at this depth.", + "type": "string" + }, + "positions": { + "description": "Positions at this depth.", + "items": { + "description": "Seat label.", + "type": "string" + }, + "type": "array" + }, + "rows": { + "description": "Index rows at this depth.", + "type": "integer" + }, + "sampleKeys": { + "description": "Sample keys, for per-node datasets.", + "items": { + "description": "A node key.", + "type": "string" + }, + "type": "array" + }, + "stackBb": { + "description": "Stack depth in big blinds.", + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + } + }, + "type": "object" +}
- Changed
get_upload_link1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "Hosted upload page for hand histories.", + "properties": { + "expiresAt": { + "description": "When the signed token expires, or null when unsigned.", + "type": [ + "string", + "null" + ] + }, + "primary": { + "description": "Always true: this is the primary upload path.", + "type": "boolean" + }, + "resource": { + "description": "MCP resource URI that returns the same payload.", + "type": "string" + }, + "tokenAttached": { + "description": "Whether the URL carries a signed token for this account.", + "type": "boolean" + }, + "url": { + "description": "URL to hand to the user, signed when signing is configured.", + "type": "string" + } + }, + "type": "object" +}
- Changed
list_datasets1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "Preflop datasets in the shipped tree documentation.", + "properties": { + "datasets": { + "description": "Documented datasets.", + "items": { + "description": "One dataset.", + "properties": { + "analyzed": { + "description": "Rows whose bundle was analyzed.", + "type": "integer" + }, + "formats": { + "description": "Formats in the index.", + "items": { + "description": "Format label.", + "type": "string" + }, + "type": "array" + }, + "id": { + "description": "Dataset id to pass to get_tree_docs, e.g. \"nl/v2\".", + "type": "string" + }, + "perNode": { + "description": "True when index rows are per node rather than per bundle.", + "type": "boolean" + }, + "positions": { + "description": "Positions with index rows.", + "items": { + "description": "Seat label.", + "type": "string" + }, + "type": "array" + }, + "rows": { + "description": "Index rows for the dataset.", + "type": "integer" + }, + "stacks": { + "description": "Covered stack depths.", + "items": { + "description": "Stack depth in big blinds.", + "type": "number" + }, + "type": "array" + } + }, + "type": "object" + }, + "type": "array" + }, + "generated": { + "description": "Date the documentation was generated.", + "type": "string" + }, + "preflopExploitability": { + "description": "Always \"not available\": no preflop dataset publishes it.", + "type": "string" + }, + "readme": { + "description": "How to read one dataset's write-up.", + "type": "string" + }, + "source": { + "description": "Where the documentation came from, \"data/tree-docs\".", + "type": "string" + } + }, + "type": "object" +}
- Changed
list_games1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "additionalProperties": { + "description": "One game id to its covered stacks and positions. Full detail adds the bundle manifest fields.", + "properties": { + "bundleCount": { + "description": "Bundles in the dataset.", + "type": "integer" + }, + "error": { + "description": "Upstream status code when a game did not answer.", + "type": "number" + }, + "game": { + "description": "Game id.", + "type": "string" + }, + "generatedAt": { + "description": "When the dataset was generated.", + "type": "string" + }, + "positions": { + "description": "Covered positions.", + "items": { + "description": "Seat label.", + "type": "string" + }, + "type": "array" + }, + "stacks": { + "description": "Covered stack depths.", + "items": { + "description": "Stack depth in big blinds.", + "type": "number" + }, + "type": "array" + }, + "version": { + "description": "Dataset version.", + "type": "number" + } + }, + "type": "object" + }, + "description": "Coverage for every preflop game, plus what this server does not solve.", + "properties": { + "_coverage": { + "description": "Formats and objectives this server does and does not answer.", + "properties": { + "format": { + "description": "Supported formats: cash and mtt_chip_ev.", + "items": { + "description": "A supported format.", + "type": "string" + }, + "type": "array" + }, + "supportedObjectives": { + "description": "Objectives that return data.", + "items": { + "description": "A supported objective.", + "type": "string" + }, + "type": "array" + }, + "supportedTournament": { + "description": "The one certified tournament tree.", + "properties": { + "anteBb": { + "description": "BB ante in big blinds, 1.", + "type": "number" + }, + "format": { + "description": "Always \"mtt\".", + "type": "string" + }, + "game": { + "description": "Game id, \"nlmtt8\".", + "type": "string" + }, + "objective": { + "description": "Always \"chip_ev\".", + "type": "string" + }, + "tableSize": { + "description": "Seats, 8.", + "type": "integer" + } + }, + "type": "object" + }, + "unsupported": { + "description": "ICM, PKO, satellites, 9-max MTT, tournament and multiway postflop.", + "items": { + "description": "A request type with no published data.", + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + } + }, + "type": "object" +}
- Changed
list_library_solutions2 fields changed- added
Input schema / properties / limit / descriptionAdded value: +"Solutions to return, 1 to 50." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "Finished postflop solutions saved for this account.", + "properties": { + "note": { + "description": "Why no solution is marked done.", + "type": "string" + }, + "solutions": { + "description": "Empty while solver dispatch is disabled.", + "items": { + "description": "One finished solution.", + "type": "object" + }, + "type": "array" + } + }, + "type": "object" +}
- Changed
list_my_opponents7 fields changed- added
Input schema / properties / game_type / descriptionAdded value: +"Only hands of this game type, e.g. \"NLHE\" or \"PLO\"." - added
Input schema / properties / hero / descriptionAdded value: +"Only hands where this hero name was seated." - added
Input schema / properties / limit / descriptionAdded value: +"Opponents to return, 1 to 500." - added
Input schema / properties / min_hands / descriptionAdded value: +"Drop opponents seen in fewer hands than this." - added
Input schema / properties / name / descriptionAdded value: +"Case-insensitive substring of the opponent's screen name." - added
Input schema / properties / sort / descriptionAdded value: +"Row order: most hands, most recent, or by hero's bb/100 against them (toughest = worst for hero)." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "Opponents tracked across this account's uploaded hands.", + "properties": { + "opponents": { + "description": "Opponents, sorted as requested.", + "items": { + "description": "One opponent.", + "properties": { + "cbetFaced": { + "description": "Flop c-bets the opponent faced.", + "type": "integer" + }, + "cbetFold": { + "description": "Those c-bets the opponent folded to.", + "type": "integer" + }, + "displayName": { + "description": "Screen name as written in the history.", + "type": "string" + }, + "gameTypes": { + "description": "Game types seen.", + "items": { + "description": "Game type.", + "type": "string" + }, + "type": "array" + }, + "handCount": { + "description": "Hands the opponent appears in.", + "type": "integer" + }, + "handsVsHero": { + "description": "Hands played against hero.", + "type": "integer" + }, + "heroBb100Vs": { + "description": "Hero's bb/100 in hands against this opponent.", + "type": [ + "number", + "null" + ] + }, + "heroes": { + "description": "Hero accounts that faced this opponent.", + "items": { + "description": "Hero name.", + "type": "string" + }, + "type": "array" + }, + "id": { + "description": "Opponent id for get_opponent_notes.", + "type": "string" + }, + "lastSeen": { + "description": "Most recent hand timestamp.", + "type": [ + "string", + "null" + ] + }, + "net": { + "description": "Hero's net big blinds in those hands.", + "type": "number" + }, + "notes": { + "description": "Leak notes.", + "items": { + "description": "One leak note with its sample size.", + "type": "string" + }, + "type": "array" + }, + "notesCount": { + "description": "Leak notes available.", + "type": "integer" + } + }, + "type": "object" + }, + "type": "array" + } + }, + "type": "object" +}
- Changed
list_my_sessions3 fields changed- added
Input schema / properties / game_type / descriptionAdded value: +"Only sessions containing this game type." - added
Input schema / properties / limit / descriptionAdded value: +"Sessions to return, 1 to 50." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "Recent uploaded sessions, newest first.", + "properties": { + "hint": { + "description": "Where to upload hands when the account has none.", + "type": "string" + }, + "sessions": { + "description": "Sessions, newest first.", + "items": { + "description": "One upload session.", + "properties": { + "endedAt": { + "description": "Last hand timestamp.", + "type": [ + "string", + "null" + ] + }, + "filename": { + "description": "Uploaded filename.", + "type": "string" + }, + "game_type": { + "description": "Dominant game type in the session.", + "type": "string" + }, + "game_types": { + "description": "Every game type in the session.", + "items": { + "description": "Game type.", + "type": "string" + }, + "type": "array" + }, + "hands": { + "description": "Hands in the session.", + "type": "integer" + }, + "hero": { + "description": "Hero name in the history.", + "type": "string" + }, + "id": { + "description": "Session id.", + "type": "string" + }, + "netBb": { + "description": "Session result in big blinds.", + "type": "number" + }, + "startedAt": { + "description": "First hand timestamp.", + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + } + }, + "type": "object" +}
- Changed
list_postflop_packs1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "Solved postflop packs and their boards.", + "properties": { + "hint": { + "description": "How to narrow, page, or widen the same query.", + "type": "string" + }, + "packs": { + "description": "Packs matching `variant` and `pack`.", + "items": { + "description": "One solved pack.", + "properties": { + "actionEvCoverage": { + "description": "How action EV is reconstructed, and for how many boards.", + "type": "object" + }, + "boardCount": { + "description": "Solved boards in the pack.", + "type": "integer" + }, + "boards": { + "description": "Board names in the pack list, or per-board detail when one `pack` was requested.", + "items": { + "anyOf": [ + { + "description": "Board in spaced form, e.g. \"3h 3d 2s\".", + "type": "string" + }, + { + "description": "One solved board.", + "properties": { + "actionEv": { + "description": "Whether per-action EV can be reconstructed here.", + "type": "object" + }, + "board": { + "description": "Board in spaced form.", + "type": "string" + }, + "exploitabilityPct": { + "description": "Published exploitability as a percent of the pot. Omitted when the index has no number.", + "type": "number" + }, + "exploitabilityTree": { + "description": "Which tree the exploitability belongs to.", + "type": "string" + }, + "iterations": { + "description": "Published solver iterations.", + "type": "integer" + }, + "queryable": { + "description": "Whether nodes can be walked.", + "type": "boolean" + }, + "river": { + "description": "Whether the river is solved.", + "type": "boolean" + }, + "trees": { + "description": "Trees this board is solved under.", + "items": { + "description": "\"75\" or \"33\".", + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + } + ] + }, + "type": "array" + }, + "effStackBb": { + "description": "Effective stack behind, in big blinds.", + "type": "number" + }, + "exploitability": { + "description": "\"published\" or \"not available\" for this tree. Never estimated.", + "type": "string" + }, + "generatedAt": { + "description": "When the pack was generated.", + "type": "string" + }, + "hasEv": { + "description": "Whether combos carry EV.", + "type": "boolean" + }, + "id": { + "description": "Pack id to pass as `pack`.", + "type": "string" + }, + "ipPos": { + "description": "In-position seat.", + "type": "string" + }, + "oopPos": { + "description": "Out-of-position seat.", + "type": "string" + }, + "potBb": { + "description": "Starting pot in big blinds.", + "type": "number" + }, + "preflopLine": { + "description": "Preflop line the pack starts from.", + "type": "string" + }, + "queryableBoards": { + "description": "Boards whose nodes can be walked.", + "type": "integer" + }, + "sizingTrees": { + "description": "Bet-size trees; either packId is accepted by every postflop tool.", + "items": { + "description": "One bet-size tree of this pack.", + "properties": { + "betSizing": { + "description": "What the tree bets on each street.", + "type": "string" + }, + "boards": { + "description": "Boards solved under the tree.", + "type": "integer" + }, + "missing": { + "description": "Boards the tree does not cover.", + "items": { + "description": "A board absent from this tree.", + "type": "string" + }, + "type": "array" + }, + "packId": { + "description": "Pack id that addresses this tree.", + "type": "string" + }, + "tree": { + "description": "\"75\" or \"33\".", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "stackBb": { + "description": "Starting stack in big blinds.", + "type": "number" + }, + "title": { + "description": "Human title.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + } + }, + "type": "object" +}
- Changed
list_queued_solves2 fields changed- added
Input schema / properties / limit / descriptionAdded value: +"Jobs to return, 1 to 50." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "This account's solver-queue jobs, newest first.", + "properties": { + "solves": { + "description": "Queued jobs. None are dispatched.", + "items": { + "description": "One recorded solve request. Dispatch is not configured, so a job stays pending and never gets a solution id.", + "properties": { + "board": { + "description": "Board for the requested solve.", + "type": "string" + }, + "createdAt": { + "description": "ISO timestamp the job was recorded.", + "type": "string" + }, + "dispatch": { + "description": "Always \"not_configured\".", + "type": "string" + }, + "effective_stack": { + "description": "Effective stack in big blinds.", + "type": "number" + }, + "pot": { + "description": "Pot in big blinds.", + "type": "number" + }, + "queue_id": { + "description": "Id for get_queued_solve.", + "type": "integer" + }, + "reason": { + "description": "Why the job does not start a solve.", + "type": "string" + }, + "solution_id": { + "description": "Always null while dispatch is disabled.", + "type": [ + "string", + "null" + ] + }, + "status": { + "description": "\"pending\", \"running\", \"done\", or \"failed\".", + "type": "string" + }, + "title": { + "description": "Title given when the job was recorded.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + } + }, + "type": "object" +}
- Changed
list_spots1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "Valid decision nodes for one game and stack, paginated.", + "properties": { + "game": { + "description": "Game id.", + "type": "string" + }, + "hint": { + "description": "How to narrow, page, or widen the same query.", + "type": "string" + }, + "matched": { + "description": "Spots left after the depth and contains filters.", + "type": "integer" + }, + "nextOffset": { + "description": "Offset for the next page, or null at the end.", + "type": [ + "integer", + "null" + ] + }, + "offset": { + "description": "Offset this page started at.", + "type": "integer" + }, + "returned": { + "description": "Spots in this page.", + "type": "integer" + }, + "spots": { + "description": "This page of decision nodes.", + "items": { + "description": "One decision node.", + "properties": { + "actor": { + "description": "Position to act.", + "type": "string" + }, + "depth": { + "description": "Decision depth: 1 = RFI, 2 = vs open, 3 = 3-bet pots.", + "type": "integer" + }, + "history": { + "description": "Action path ending in the acting position.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "stack": { + "description": "Stack depth in big blinds.", + "type": "number" + }, + "total": { + "description": "Spots in the dataset for this stack.", + "type": "integer" + } + }, + "type": "object" +}
- Changed
upload_hand_history2 fields changed- added
Input schema / properties / filename / descriptionAdded value: +"Name to record for the paste. Defaults to \"paste.txt\"." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "Result of ingesting one pasted hand history.", + "properties": { + "errors": { + "description": "Parse errors, if any.", + "items": { + "description": "One parse error.", + "type": "string" + }, + "type": "array" + }, + "filename": { + "description": "Filename recorded for the paste.", + "type": "string" + }, + "handsParsed": { + "description": "Hands parsed.", + "type": "integer" + }, + "persisted": { + "description": "Always false: nothing is written to durable storage.", + "type": "boolean" + }, + "persistence": { + "description": "Where the hands live, \"process_memory\".", + "type": "string" + }, + "sessionId": { + "description": "Session id for the stored hands, or null when nothing parsed.", + "type": [ + "string", + "null" + ] + }, + "tournamentsParsed": { + "description": "Tournament summaries parsed.", + "type": "integer" + } + }, + "type": "object" +}
29 tool updates
- First observed
compare_strategies - First observed
enqueue_solve - First observed
explain_combo - First observed
find_hands - First observed
get_board_report - First observed
get_config - First observed
get_exploitability - First observed
get_hand_results - First observed
get_node - First observed
get_opponent_limp_range - First observed
get_opponent_notes - First observed
get_postflop_node - First observed
get_postflop_range - First observed
get_queued_solve - First observed
get_range - First observed
get_range_metadata - First observed
get_session_summary - First observed
get_tournament_results - First observed
get_tree_docs - First observed
get_upload_link - First observed
list_datasets - First observed
list_games - First observed
list_library_solutions - First observed
list_my_opponents - First observed
list_my_sessions - First observed
list_postflop_packs - First observed
list_queued_solves - First observed
list_spots - First observed
upload_hand_history
Publisher details
- Operator
- Unknown
- Operator website
- https://pokerdata.io/ · Publisher source
- Vendor relationship
- First-party
- Documentation
- https://docs.pokerdata.io/llm-tools · Publisher source
- Trust center
- Not applicable
- Restrictions
- No key needed for the tool list and 6-max NL cash preflop (200 calls a day per IP). Every other tool needs a pdk_ API key from https://pokerdata.io/app/api. A free trial key covers 100 calls with no card, and paid plans start at $100/month. Commercial use requires the Enterprise plan.
Related MCP Connectors
Exact Texas Hold'em equity and hand analysis, every runout enumerated. Free, no API key.
All-in outcome rankings with live depth, fees, verified rules, EV checks, and track records.
Live Texas Hold'em for AI agents. The tools teach the rules; the bluffing is up to your model.
Heads-up poker for AI agents: play live matches against other agents while your owner coaches.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables interaction with the TexasSolver poker solver to run game theory optimal (GTO) poker calculations, load preflop ranges, and build game trees with structured parameters for analyzing poker hands and strategies.MIT
- AlicenseNot gradedqualityBmaintenanceEnables heads-up Texas Hold'em river analysis by exposing exact showdown equity/call EV and restricted-tree CFR+ solve frequencies/action EVs through MCP tools. It is intended for post-session review, not live or unconstrained GTO decisions.MIT
- AlicenseAqualityDmaintenanceEnables simulated multi-table No-Limit Texas Hold'em study and decision-support, allowing users to practice against bots and get equity/pot-odds/preflop-chart advice.12MIT
- AlicenseAqualityBmaintenanceMCP server for the Pokerai API providing solver-grade GTO strategy for 6-max No-Limit Hold'em, exposed as tools for LLM agents like Claude and Cursor.5708 npmMIT
Glama MCP Gateway
Add one secure layer between your agents and this server.