CourtVision Rules MCP
by WhitGai
README.md
# CourtVision Rules MCP
  
A [Model Context Protocol](https://modelcontextprotocol.io) server that turns the
official pickleball scoring rules into callable tools, so an LLM tracks a live
match without ever improvising the rules.
Built as part of [CourtVision AI](https://github.com/WhitGai) — an AI
pickleball companion — this is the protocol-layer piece: the small, provably
correct service the model leans on so the conversation stays accurate.
---
## Preview
The same seven rallies, scored four ways — doubles/singles × side-out/rally. One engine, all correct, all unit-tested.

## Why it exists
Pickleball's side-out scoring is exactly the kind of thing language models get
*almost* right. The one-server rule at the start, the server-1-to-server-2
rotation, win-by-two — a model that holds these in its head drifts after a few
turns. The fix is not a better prompt. It is moving the part that must be exact
out of the model and into a tool.
That is the entire MCP thesis in one server, and it doubles as a design rule
this product was built on: **accuracy is the brand.** A wrong call in front of
four players ends the app's life with that crew. So the engine never guesses —
ambiguous input is rejected with an actionable message rather than resolved
silently.
## What it does
Six tools, exposed over MCP:
| Tool | What it does |
|---|---|
| `pickleball_new_match` | Start a doubles match; returns a `match_id` and the opening `0-0-2` call |
| `pickleball_record_rally` | Apply a rally result (`server_won` / `server_lost`) with full side-out logic |
| `pickleball_record_fault` | Record a fault by either team and apply the right transition |
| `pickleball_get_score` | Return the current state and three-number score call |
| `pickleball_undo` | Revert the last rally or fault |
| `pickleball_explain_rule` | Plain-language summary of common rules topics |
State is held server-side, keyed by `match_id`, so a client runs a whole match
across many turns without re-sending the board.
## Architecture
The rules logic and the transport are deliberately separate:
```
pickleball_engine.py pure rules engine, zero dependencies, unit-tested
(doubles + singles, side-out + rally scoring)
server.py thin MCP wrapper: input validation + state registry
tests/ the rules engine's safety net (26 cases)
evaluation/ MCP eval questions an agent must answer using the tools
```
The engine is the load-bearing part, so it lives on its own where it can be
tested in isolation and reused by any surface — the MCP server today, the Match
Mode web app and native clients later.
## Run it
```bash
python -m venv .venv && source .venv/bin/activate
pip install "mcp[cli]"
# run the server (stdio transport)
python server.py
# or inspect it interactively
npx @modelcontextprotocol/inspector python server.py
```
### Use it from Claude Desktop
Add to your `claude_desktop_config.json`:
```json
{
"mcpServers": {
"courtvision-rules": {
"command": "python",
"args": ["/absolute/path/to/courtvision-rules-mcp/server.py"]
}
}
}
```
Then ask Claude: *"Start a pickleball match between the Reds and the Blues. The
Reds win the first rally, then lose the next one — what's the score?"* It will
call the tools and answer `0 1 1`, correctly, every time.
## Tests
```bash
pip install pytest
python -m pytest tests/ -q
```
The tricky cases are pinned: the one-server match start, the
server-1 → server-2 → side-out rotation, win-by-two, and that only the serving
team can score.
## Notes
Rules summaries defer to the current
[USA Pickleball Official Rulebook](https://usapickleball.org/) — this server
computes scoring and explains the common cases; it does not reproduce the
rulebook.
### Formats
Set `match_format` and `scoring` when you start a match:
| `match_format` | `scoring` | Call | Rule |
|---|---|---|---|
| `doubles` | `sideout` | `7 4 2` | Traditional two-server side-out with the one-server opening (the default). |
| `singles` | `sideout` | `7 4` | One server per side; every lost rally is an immediate side-out. Serve court follows score parity. |
| `doubles` | `rally` | `7 4` | A point on every rally; lose your serve and the other side scores **and** takes serve. |
| `singles` | `rally` | `7 4` | Same rally logic, one server per side. |
Doubles side-out remains the default, so existing callers are unaffected. Rally
games are commonly played to 15 or 21, win by 2 — pass `target`/`win_by` to set them.
## License
MIT — see [LICENSE](LICENSE).
## Run as a service (Docker)
```bash
docker build -t courtvision-rules-mcp .
docker run -i --rm courtvision-rules-mcp # stdio transport
```
The server speaks MCP over stdio by default (what Claude Desktop and local MCP
clients use). For a hosted deployment, set `MCP_TRANSPORT=sse` to serve over
HTTP/SSE. Console script after `pip install -e .`: `courtvision-rules-mcp`.
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues