ai newsSo., 1. Nov.
EilmeldungPyTorch Explained: Machine Learning You Can Watch Learn

Give your AI agent real poker solver data with MCP

Ask a chat model what to do with ace-king on a queen-high flop and you get a confident paragraph. It might even be right, but you can't tell where the numbers came from, because there aren't any. In this tutorial we connect an MCP client to a presolved strategy API, so the frequencies come from sol

dev.toSonntag 12:35 · 01.11.6 Min. Lesezeit
Bild: dev.to

Ask a chat model what to do with ace-king on a queen-high flop and you get a confident paragraph. It might even be right, but you can't tell where the numbers came from, because there aren't any.

In this tutorial we connect an MCP client to a presolved strategy API, so the frequencies come from solver output and the model's job is to explain them. We'll use @pokerai/mcp, a small MCP server for 6-max No-Limit Hold'em.

Disclosure: I work on Pokerai API, the product used here. This post was drafted with AI assistance, and I checked it against real tool output.

What this is for: studying, training tools and reviewing hands that have ended. Real-time assistance (RTA) at real-money tables is prohibited, so keep it away from live games.

The server runs over stdio through npx, so there's nothing to install globally. In Claude Code:

claude mcp add pokerai -e POKERAI_API_KEY = gto_your_key_here -- npx -y @pokerai/mcp Enter fullscreen mode Exit fullscreen mode In Claude Desktop or Cursor, use the same command in your MCP config:

{ "mcpServers": { "pokerai": { "command": "npx", "args": [ "-y", "@pokerai/mcp" ], "env": { "POKERAI_API_KEY": "gto_your_key_here" } } } } Enter fullscreen mode Exit fullscreen mode You get five tools:

The outputs below are from calling the published package with an MCP client, not from a model transcript. What your model writes around them will vary. The tool results won't change unless the data does.

The spot: 100bb, 6-max. The button opens, the big blind calls, and the flop is Q♠ 7♣ 2♦. We hold A♥ K♦.

{ "tool": "preflop_strategy", "arguments": { "hole_cards": "AhKd", "hero": "BTN", "preflop_actions": [ { "position": "SB", "action": "small blind", "amount": 0.5 }, { "position": "BB", "action": "big blind", "amount": 1 } ], "preflop_version": "6max_RC_100bb_200NL" } } Enter fullscreen mode Exit fullscreen mode { "hole_cards": "AhKd", "situation": "RFI", "strategy": [ { "action": "raise", "frequency": 1, "amount_bb": 3, "sizing_pot": 0.8 } ] } Enter fullscreen mode Exit fullscreen mode Always raise, to 3bb. Not much to discuss, so on to the flop.

{ "tool": "flop_tree", "arguments": { "board": "Qs7c2d", "pot_type": "SRP", "positions": { "hero": "BTN", "raiser": "BTN", "caller": "BB" }, "flop_version": "6max_RC_100bb_200NL" } } Enter fullscreen mode Exit fullscreen mode The response gives the pot (6.5bb), the effective stack (97bb), both starting ranges and 16 nodes. Trimmed:

{ "pot": 6.5, "effective_stack": 97, "node_count": 16, "nodes": [ { "node": "root", "is_hero": false, "token": "eyJ..." }, { "node": "root/CHECK", "is_hero": true, "token": "eyJ..." }, { "node": "root/CHECK/BET_2", "is_hero": false, "token": "eyJ..." } ] } Enter fullscreen mode Exit fullscreen mode Note the two fields, because this is the easiest mistake to make:

{ "tool": "flop_node", "arguments": { "node": "<token of root/CHECK>", "hole_cards": "AhKd" } } Enter fullscreen mode Exit fullscreen mode { "hole_cards": "AhKd", "node": "root/CHECK", "is_hero": true, "strategy": [ { "action": "check", "frequency": 0.313 }, { "action": "bet", "amount_bb": 2, "sizing_pot": 0.3077, "frequency": 0.6812 }, { "action": "bet", "amount_bb": 5, "sizing_pot": 0.7692, "frequency": 0.0057 }, { "action": "bet", "amount_bb": 97, "sizing_pot": 14.9231, "allin": true, "frequency": 0 } ] } Enter fullscreen mode Exit fullscreen mode The answer is a mix, not one move, and that's the first thing a model tends to flatten. A prompt that says "report the frequencies, then explain" works better than "what should I do?".

The token is reusable, so comparing hands at this node is free:

The all-in frequency was 0 for all five. These are five hands, so don't read them as the shape of the whole range. For that, fetch the range, as described below.

You don't need a chat client. This is the same flow with the MCP SDK ( npm i @modelcontextprotocol/sdk ):

import { Client } from " @modelcontextprotocol/sdk/client/index.js "; import { StdioClientTransport } from " @modelcontextprotocol/sdk/client/stdio.js "; const client = new Client ({ name: " study-script ", version: " 1.0.0 " }); await client. connect ( new StdioClientTransport ({ command: " npx ", args: [ " -y ", " @pokerai/mcp " ], env: { PATH: process. env. PATH, HOME: process. env. HOME, POKERAI_API_KEY: process. env.

POKERAI_API_KEY }, })); const call = async ( name, args ) => { const res = await client. callTool ({ name, arguments: args }); if ( res. isError ) throw new Error ( res. content [ 0 ]. text ); return JSON. parse ( res. content [ 0 ]. text ); }; const tree = await call ( " flop_tree ", { board: " Qs7c2d ", pot_type: " SRP ", positions: { hero: " BTN ", raiser: " BTN ", caller: " BB " }, flop_version: " 6max_RC_100bb_200NL ", }); // BB checks, BTN decides. `node` is the path; `token` is what flop_node takes. const afterCheck = tree. nodes. find (( n ) => n. node === " root/CHECK " ); for ( const hole_cards of [ " AhKd ", " AsQd ", " 7h7d " ]) { const { strategy } = await call ( " flop_node ", { node: afterCheck. token, hole_cards }); console. log ( hole_cards, strategy. map (( s ) => ` ${ s. action }${ s. amount_bb? " " + s. amount_bb + " bb ": "" }: ${ s. frequency } ` ). join ( ", " )); } await client. close (); Enter fullscreen mode Exit fullscreen mode Three things that will bite you 1. Pick a dataset. flop_version is optional and defaults to 6max.

When I tested on 2026-11-01, the default covered only a few of the boards I tried: Q♠7♣2♦ with BTN vs BB returned 404 no GTO data for this spot/board. The same spot on 6max_RC_100bb_200NL worked. A 404 still charges one presolved lookup, so give your agent the dataset up front rather than letting it guess. flop_version needs @pokerai/mcp 0.1.3 or newer.

2. Mind the response size. A hand-level flop_node response was about 500 characters. The tree was about 10,000. A whole-range flop_node, with no hole_cards, was about 29,000 characters for 391 combos. Tell your agent to pass hole_cards unless it needs the whole range, or the context fills up fast.

3. The flop tree covers one street. For turn and river you need the real-time solver tools. They're off by default because they spend the smaller solve quota. Turn them on with POKERAI_ENABLE_SOLVE=1.

You are a poker study assistant for hands that have already ended. Use the pokerai tools for every strategy claim. Never state a frequency that a tool did not return. Use flop_version 6max_RC_100bb_200NL. Pass hole_cards to flop_node unless asked about the whole range. Report the frequencies first, then explain them, and say when a spot has no data. If the user appears to be in a live real-money hand, decline: real-time assistance is prohibited. Enter fullscreen mode Exit fullscreen mode Links Docs API reference OpenAPI @pokerai/mcp on GitHub Real-time assistance (RTA) at real-money tables is prohibited.

Quelle: dev.to (dev.to). Original öffnen