{"id":"1b6327bc-6cb1-46d1-8c13-c75db152bb1c","slug":"4amcasino","kind":"mcp","name":"4amcasino","summary":"Provably-fair Texas Hold'em for friend groups — mental poker on ristretto255, a hash-chained ledger, a cyberpunk UI, and a 3D casino world with emotes. Nobody sees a card they shouldn't, not even the","owner":"notpritam","repoUrl":"https://github.com/notpritam/4amcasino","license":"MIT","licenseTier":"permissive","trust":"community","stars":3,"match":null,"fewStars":true,"format":"mcp","createdAt":"2026-08-23T13:41:14.000Z","addedAt":"2026-10-21T09:33:55.524Z","logoUrl":"https://avatars.githubusercontent.com/u/119423845?u=603a474272f9dfe509c8945677e59d858194bfcc&v=4","linkOnly":false,"collection":null,"skillPath":null,"categories":["design-media","cloud-infra","utilities"],"tags":["cryptography","game","mental-poker","poker","react","ristretto255","texas-holdem","typescript"],"runtime":"binary","local":true,"cloudCapable":false,"cloudCapability":"unknown","cloudReadyOnPlatform":false,"needsApiKey":false,"reviewed":false,"syncedAt":"2026-10-26T23:01:42.347Z","sample":false,"url":"https://conduits.dev/tools/4amcasino","language":"TypeScript","transports":["stdio"],"install":{},"requirements":{"env":[],"upstreamMayCharge":false},"tools":null,"readme":"# 4AM Casino\n\n**Provably-fair Texas Hold'em for friend groups. Nobody sees a card they shouldn't — not even the server. Now with a 3D casino you can walk around in.**\n\n[**Play it live →**](https://4amcasino.com) · [How it's fair (60s animated tour)](https://4amcasino.com/fair) · [Give an AI a seat](apps/mcp/README.md) · [MIT licensed](LICENSE)\n\n![The 4AM Casino landing page](docs/media/landing.jpg)\n\nInstead of trusting a server to deal, every player's browser takes part in a\n[mental poker](https://en.wikipedia.org/wiki/Mental_poker) protocol: the deck is encoded as\npoints on the ristretto255 curve, each player masks and shuffles it with a secret per-hand key,\nand every card is opened only by the cooperation of all players. The server coordinates\nmessages and enforces betting rules, but it never holds a masking key and never learns a hole\ncard.\n\nChips are play money. Players buy points from a **bank**; the room's **banker** approves each\npurchase, and every chip movement — buys, pots, bounties, transfers — lands in an append-only,\n**hash-chained ledger** the whole room can verify, so the group settles up outside the app.\nNo real payments, ever.\n\n| The table | The fairness tour |\n| --- | --- |\n| ![A hand in progress on the round isometric table](docs/media/table.png) | ![The animated mental-poker explainer](docs/media/fair.png) |\n\n![The 3D casino: characters around a purple table, slot machines and a roulette wheel behind them](docs/media/world3d.jpg)\n\n## What's inside\n\n**The game.** No-limit Hold'em on a round isometric table where seats arrange themselves\nlive and yours is always bottom-center. A turn timer the banker picks (15s to no-limit),\none-tap quick bets and pre-selected actions so you never stall the table, a blinking\ncan't-miss-it highlight on whoever's turn it is, chip stacks that slide to the pot and sweep\nin at street end, board cards that flip over back-to-face with a cascading flop, big\ndraggable hole cards, auto-deal when the banker is online, winner-reveal choreography with\nplain-English reasoning for why the hand won, full hand replays rebuilt from the signed game\nrecord, sit-out, four card-back colorways and a 4-color deck option, and three themes — the\ndefault cyberpunk terminal look, plus light and dark.\n\n**The world.** Every table has a [three.js](https://threejs.org) casino behind it — hit the\ncube icon and you're standing in it: a purple-neon room with slot machines, a roulette wheel,\na bar (with a cat), and everyone at the table as a customisable character (colors, glow trim,\nheads, hats, victory blasts) that the whole room sees. 26 broadcast emotes from wave to\nlevitate, mischief on tap — shove a friend, slap them, throw a chip at them — fold slumps,\nbust-out explosions you pick yourself, and free camera flight with one-tap presets. Same\nhand, same proofs, just louder.\n\n**The people.** Friends with live presence, table invites (with an opt-in auto-join), public\ntables listed in every lobby or private 6-letter codes, watch-only spectator links where\nviewers can ask to join and the banker admits them, an attached Meet/Zoom link per table,\nvoice chat, table chat with your own quick phrases, and reactions.\n\n**The money.** A banker (plus an optional co-banker) approves buy-ins; every movement is\nhash-chained. Players can send or lend chips to each other between hands. The banker can revert\na purchase, void a single hand, or void a whole table — voided amounts drop out of everyone's\ntotals automatically. Rooms can require a minimum number of hands before someone's winnings\ncount in settle-up. The ledger page renders a full session report: time played, hands, biggest\npot, per-player win/loss bars, and who owes whom.\n\n**The bragging rights.** Global and in-room leaderboards with a chip-leader crown, a cumulative\nwinnings chart in the lobby, a play-style radar mined from your actual hand transcripts\n(loose/aggressive/pressure/showdowns/wins, plus an archetype: shark, rock, maniac, calling\nstation...), one-tap shareable hand-result images, an optional 7-2 offsuit bounty the banker\ncan put up, paid peeks at mucked cards (if the owner agrees), and a private mode that hides\nyour winnings from everyone but the bankers.\n\n**The robots.** [`apps/mcp`](apps/mcp/README.md) ships an MCP server that gives any\nMCP-capable agent (Claude Code, Claude Desktop, ...) a real seat: join by code, buy chips,\nread the table, act. The headless client runs all the cryptography, so the same fairness\nguarantees hold for bots — nobody, not even the server, sees the agent's cards.\n\n## How the cards stay secret\n\nThe live app walks through this with animations at\n[4amcasino.com/fair](https://4amcasino.com/fair). The short version:\n\n- **Shuffle**: each hand, every player in turn multiplies all 52 card points by a secret key\n  and permutes them. After all players have gone, the deck's order is unknown to everyone.\n- **Key commitments + DLEQ proofs**: each player publishes a commitment to their hand key, and\n  every unmask they ever send carries a Chaum–Pedersen proof it used exactly that key. A wrong\n  share is rejected and attributed the moment it arrives — and a showdown reveal cannot claim a\n  different card than the one dealt.\n- **Dealing**: to give you a hole card, all *other* players apply their proven unmasks; you\n  apply yours last, locally. Observers see a point still masked by your key.\n- **Transcripts**: every protocol message is signed (ed25519) and folded into a hash chain.\n  Completed hands are stored and downloadable for offline audit. Rooms can opt into\n  `strict-audit` mode, where everyone reveals their hand key after each hand so the entire\n  shuffle can be re-verified (at the cost of folded cards becoming public afterwards).\n- **Honest about limits**: a malicious *shuffle* is detected and attributed (at open time or on\n  key reveal), not cryptographically prevented — that trade keeps the protocol simple enough\n  for a friends game. And when you fold, your client escrows your per-hand key with the server\n  so the hand survives you closing the tab (the server can then compute your unmask shares,\n  with proofs everyone can verify) — meaning the server *can* see a folder's own two cards\n  after the fold, and nobody else's. Out-of-band collusion (screen sharing) is out of scope, as it is for\n  every protocol. See [`docs/superpowers/specs/`](docs/superpowers/specs/) for the full design\n  and threat model.\n\nYour password never leaves the browser either: the client derives a login key and a separate\ned25519 signing identity from it with domain-separated scrypt, so the server can authenticate\nyou but can never sign or decrypt as you.\n\n## Running it\n\nRequires Node 22+.\n\n```bash\nnpm install\n\n# development (two terminals)\nnpm run dev --workspace @4am/server   # API + WebSocket on :8787\nnpm run dev --workspace @4am/web      # Vite dev server on :5173 (proxies to :8787)\n\n# self-host (one process serves everything)\nnpm run build --workspace @4am/web    # builds the app AND a prebundled server\nnpm run start --workspace @4am/server # serves the built app + API + WS on :8787\n```\n\nState lives in a single SQLite file (`DB_PATH`, default `./4amcasino.db`). Set `PORT` to change\nthe port. Create an account, create a room, share the 6-letter code, buy points, and deal.\n\n## Hosting\n\nThe app is one long-running Node process (HTTP + WebSocket + a SQLite file), so it needs a\nhost that runs real servers — serverless platforms (Vercel/Netlify functions, GitHub Pages)\ncan't run it.\n\n**Render:** this repo ships a [`render.yaml`](render.yaml) blueprint. In the Render dashboard\nchoose **New → Blueprint**, pick this repository, and deploy. On the free tier the service\nsleeps after ~15 min idle and storage is ephemeral (the ledger resets on every deploy); the\n`starter` plan with the 1 GB disk block gives a persistent ledger, which is how\n[4amcasino.com](https://4amcasino.com) runs. The server also supports an optional\nMongoDB snapshot layer (`MONGO_URL`) that continuously backs up and restores the database.\n\nThe primary domain is `4amcasino.com`. Requests to `poker.notpritam.in` receive\na permanent 308 redirect with their path and query preserved. Keep the old\ndomain's DNS and Render custom-domain entry in place so these redirects and\nits HTTPS certificate keep working. Existing MCP configurations should use\n`FOURAM_URL=https://4amcasino.com` to send authenticated requests directly.\n\n**Docker (any VPS, Fly.io, Railway):**\n\n```bash\ndocker build -t 4amcasino .\ndocker run -p 8787:8787 -v 4amcasino-data:/data 4amcasino\n```\n\n**Quick game night without hosting at all:** run it locally (`npm run start --workspace\n@4am/server`) and share a tunnel, e.g. `npx ngrok http 8787` or a\n[Tailscale](https://tailscale.com) address. Friends on the same Wi-Fi can just open\n`http://<your-LAN-IP>:8787`.\n\n## Platform administration\n\nThe platform account opens the dedicated dashboard at `https://admin.4amcasino.com`.\nThe same dashboard is available at `https://4amcasino.com/admin` while the subdomain\nis being connected. Sign in separately on the admin hostname with the existing\nplatform account; ordinary player accounts cannot access its data or controls.\n\n**Platform settings → House cut** changes the rate without a redeploy. The initial\nrate is 0.5%. Choose **All rooms** to change future hands in existing rooms too, or\n**New rooms only** to leave existing room rates alone. The editor records who made\neach change and prevents a stale browser tab from overwriting a newer setting.\nCompleted and running hands keep their original rates. Settings and history are\nincluded in the existing database snapshots. Room qualification requirements are\nlimited to 0–30 hands; older requirements above 30 are reduced automatically.\n\nThe dashboard also includes revenue, user dues, a searchable account directory,\nroom management, and pending requests. Amounts are chips; recorded payments are\nuser-reported, so receipt must still be confirmed separately.\n\nTo connect the admin subdomain on the existing Render service:\n\n1. In Cloudflare, add a **CNAME** record named `admin`, targeting\n   `fouramcasino.onrender.com`, with **DNS only** enabled.\n2. In Render → service → Settings → Custom Domains, add `admin.4amcasino.com`.\n3. Wait for Render to verify DNS and issue its certificate, then check the URL.\n\nThe app already accepts the admin origin and routes its root to administration.\nNo second service or database is needed.\n\n## Repository layout\n\n```\npackages/shared        cards, hand evaluator, betting engine, WS message schemas\npackages/mental-poker  the crypto: group ops, shuffle/unmask, DLEQ proofs, transcripts\napps/server            Fastify + ws + SQLite: auth, rooms, bank/ledger, hand orchestration\napps/web               React (Feature-Sliced Design) + Tailwind v4 client, three themes\napps/mcp               MCP server + headless client: an AI seat at the table\ndocs/                  design spec, implementation plans, screenshots, UI reference\n```\n\n`npm test` runs the whole suite (100+ tests), including an end-to-end test where simulated\nclients play complete hands over WebSocket with the real cryptography, and one where an MCP\nheadless client sits at the table.\n\n## License\n\nMIT — see [LICENSE](LICENSE). Play money only; the stakes are bragging rights.\n"}