scopa-mcp-server
Serves a read-only web view of the game state, allowing spectators to monitor the game via HTTP.
Used as an append-only event log and pub/sub system for game state synchronization, enabling turn-based coordination and live spectator updates.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@scopa-mcp-serverstart a 2-player game"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Scopa MCP Server
A Model Context Protocol (MCP) stdio server that manages the state for
a two-player (or 2–4 player) game of Italian Scopa, with an
append-only Redis event log, low-latency wait synchronisation via
Redis Pub/Sub, a live spectator mode, an LLM opponent driven by the
Anthropic SDK, and a read-only web view.
Each player runs as its own python main.py --game=<id> --player=<A|B|C|D>
process. The processes do not talk to each other directly — they
coordinate through an event log in Redis. Game state is fully
reconstructable by replaying the log, so any process can be killed and
restarted without losing the game.
Rules implemented
Neapolitan deck (40 cards, values 1–10 with Knave=8, Knight=9, King=10):
Player A leads every round.
Initial deal of 3 cards per player + 4 on the table. If the would-be table contains three or more Kings, the shuffle is discarded and a new one is drawn.
Forced capture: you cannot trail a card if any capture is possible.
Single-match priority: if a single table card matches the played card's value, you cannot take a multi-card subset that sums to it.
Scopa (clearing the table) gives +1 point, except on the very last play of the round.
Round end: any cards left on the table go to the last player who captured. Round scoring awards 1 point each for most-cards, most-coins, settebello (7 of Coins), and primiera, plus the scopa points accrued during the round.
First player to reach 11 wins the game. Ties at the top force another round.
Architecture
Player A process Player B process Spectator process
(python main.py (python main.py (python main.py
--game=g --player=A) --game=g --player=B) --game=g --spectate)
│ │ │
└─────────────┬───────────┴────────────┬─────────────┘
│ │
Redis LIST Redis Pub/Sub
scopa:{g}:events scopa:{g}:events
(append-only event log) (push seq numbers)Single source of truth = the event log. The engine
(scopa/engine.py) is a pure state machine: given a fresh
ScopaGame() and the full list of events, it always reaches the same
state. There are only two event types:
shuffle — payload carries the full 40-card deck order; the engine deals from it and discards if ≥3 Kings land on the table.
play — payload carries
player,card_index(1-based into the hand at the time of the move) andcapture(1-based table indices). The engine applies the play, handles mid-round refills, and runs end-of-round scoring from these alone.
Concurrency:
Turn ordering is derived from the event log; a process refuses to append a
playunless its replayed state says it's this player's turn.Shuffle lock: at the start of each round, only one process must generate the shuffle.
RedisStore.acquire_shuffle_lockusesSET NX EX; the loser sleeps briefly and resyncs.waitis push-based: the tool subscribes to the pub/sub channel and returns the instant the other player appends an event. No polling.Spectator runs the same replay+subscribe loop but is read-only.
Running it
1. Redis (local Docker is easiest on Windows)
docker run -d -p 6379:6379 --name scopa-redis redis:alpine2. Python deps
python -m venv .venv
source .venv/Scripts/activate # or .venv/bin/activate on macOS/Linux
pip install -e . redis aiohttp python-dotenvRequires Python 3.11+.
3. Two-player greedy test
bash run_test.shSpawns two MCP subprocesses, plays a full game with a deterministic greedy strategy, and prints every status read and every play.
4. Wait-driven test with a live spectator
bash run_wait_test.shTwo players run as concurrent asyncio tasks, each blocked on the
wait tool until it's their turn. A third subprocess joins in
--spectate mode and writes a live snapshot log to
spectator_<game>.log.
5. LLM opponent (Claude Haiku)
# put your key in .env first: echo 'ANTHROPIC_API_KEY=sk-...' > .env
# terminal 1
python play_greedy.py --game=llm_demo --player=A
# terminal 2
python python/chat.py --game-id=llm_demo
# or: bash llm_play.sh llm_demoThe LLM is driven through the Anthropic SDK's native tool-use
protocol. python/chat.py spawns an MCP subprocess for player B,
converts the MCP tool list to the Anthropic tool schema, and then
loops: wait → status → play. It does not use any LangChain /
LangGraph layer.
6. 3–4 players
python test_multi.py -n 4The engine is generalised over an N-player tuple (2–4). main.py
takes --players=A,B,C,D on the first process to kick off a
multi-player game; later processes pick the player list up from the
Redis meta hash.
7. Read-only web view
python main.py --game=web_demo --player=A --web
# → http://127.0.0.1:19000/ (port = 19000 + offset(player))Meta-refreshing HTML that shows the current hand, the table, the
per-player scores, and the most recent move, as seen from the running
player's seat. Deliberately bare-bones: the MCP status tool is still
the authoritative read path.
MCP tools exposed by main.py
Tool | Purpose |
| Returns the human-readable view of the hand, the table, the scores and whose turn it is. |
| Play a card. |
| Block until it is this player's turn. Returns the most recent opponent move. |
| Full move history so far (available to both players and |
Event log inspection
You can read the raw log of any running game directly from Redis:
docker exec -it scopa-redis redis-cli LRANGE 'scopa:<game_id>:events' 0 -1Files
Path | Role |
| Neapolitan deck and primiera scoring table |
| Pure Scopa state machine driven by events |
| Async Redis event store with pub/sub and shuffle lock |
| Read-only aiohttp view |
| MCP stdio server + argument parsing |
| Two-player greedy test runner |
| Wait-driven two-player test + live spectator |
| 3–4 player greedy test runner |
| Single-player greedy driver (useful as the opponent when the other player is the LLM) |
| Claude-driven LLM opponent over the Anthropic SDK |
Known limitations
Redis persistence is disabled by default; stopping the container drops the game state. That is intentional for demos.
The greedy test player is deliberately unsophisticated — it is a harness for the server, not a strong opponent.
The web view uses 2s meta-refresh rather than WebSockets; this keeps the server simple and well-behaved on Windows.
No pytest suite per se — the three end-to-end test scripts are the regression coverage for the engine and the MCP server. A proper unit-test suite for the capture/scopa/primiera edge cases would be a good next step.
This server cannot be installed
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/Seboostian02/scopa-mcp-server'
If you have feedback or need assistance with the MCP directory API, please join our Discord server