Skip to main content
Glama
README.md
# Chess Coach Agent — MCP Integration Assignment

An agent that takes a **link to a finished chess game** (lichess.org), fetches the
game through **Playwright MCP**, analyzes it with a local Stockfish through a
**custom Chess Mistake Coach MCP server**, reads/writes the player's training
journal through **Obsidian MCP**, and produces a personalized training plan:
classified mistakes, matching puzzles, and study-resource recommendations.

```
Claude Agent SDK agent
 ├── playwright   MCP (existing #1, stdio via npx)  → fetch game PGN from the link
 ├── obsidian     MCP (existing #2, http, plugin)   → read/write training journal
 ├── coach        MCP (custom, stdio, this repo)    → analyze_game, find_training_puzzles,
 │                                                     recommend_study_resources,
 │                                                     generate_puzzle_from_position
 └── smartsearch  MCP (bonus #4, stdio, vendored)   → semantic search over the vault's
                                                        150-resource library (optional —
                                                        see "Bonus" section below)
```

## Prerequisites

- **Python 3.11+**
- **Node.js 18+** (for Playwright MCP: `npx @playwright/mcp`)
- **Claude Code CLI** installed natively (the Claude Agent SDK launches it;
  on Windows it must be a `claude.exe`, not the npm `.cmd` shim)
- **Stockfish** binary — download from <https://stockfishchess.org/download/>
- **Obsidian** desktop app with the **Local REST API** community plugin
  (`coddingtonbear/obsidian-local-rest-api`, tested with v5.1.0)
- An Anthropic API key (or Claude subscription login) for the Claude Agent SDK

## Installation

```bash
python -m venv .venv
.venv/Scripts/pip install -e ".[dev]"          # Windows
npx --yes playwright install chromium          # browser for Playwright MCP
```

All commands below use `.venv/Scripts/python.exe` explicitly rather than a bare
`python`/`streamlit`, so they work whether or not the venv is activated in your
shell — a bare `streamlit run ...` will pick up whatever Streamlit is first on
your `PATH`, which is usually **not** this project's venv and is missing
`claude-agent-sdk`, causing `ModuleNotFoundError: No module named 'claude_agent_sdk'`.

## Configuration

Copy `.env.example` to `.env` and fill in:

| Variable | Meaning |
|---|---|
| `ANTHROPIC_API_KEY` | Claude Agent SDK credentials (not needed if `claude` CLI is already logged in) |
| `OBSIDIAN_BASE_URL` | Local REST API endpoint, default `http://127.0.0.1:27123` |
| `OBSIDIAN_API_KEY` | From Obsidian → Settings → Local REST API |
| `STOCKFISH_PATH` | Full path to the Stockfish executable |

**Obsidian setup:** open (or create) a dedicated demo vault, install and enable
the *Local REST API* community plugin, enable its **non-encrypted HTTP server**
(port 27123) in the plugin settings, and copy the API key into `.env`. A ready
demo vault with a `Player Profile.md` and a `TrainingLog/` folder is described in
`docs/demo_script.md`.

**Dataset:** `data/puzzles_subset.csv` (1,249 puzzles filtered from the CC0
Lichess puzzle database) ships in the repo, so the custom server needs **no
network access at runtime**. To regenerate it from the full 6M-row database:

```bash
python scripts/prepare_puzzle_dataset.py
```

## Running — two independent processes

**Custom MCP server standalone** (used during the defence to prove process
separation; the agent also spawns its own instance over stdio):

```bash
.venv/Scripts/python.exe -m chess_coach_mcp.server
```

Scripted standalone proof (handshake, tool discovery, one call per tool, plus an
invalid-input error case):

```bash
.venv/Scripts/python.exe scripts/smoke_test_server.py
```

**Agent — CLI** (recommended for the defence/demo, since MCP connections and tool
calls are visible in the terminal):

```bash
.venv/Scripts/python.exe -m chess_coach_agent.cli --game-url "https://lichess.org/787zsVup" --username aanreitaylor
```

Options: `--username <name>` picks your color from the PGN headers;
`--color white|black` forces it.

**Agent — web UI** (recommended for everyday use):

```bash
.venv/Scripts/python.exe -m streamlit run chess_coach_agent/webapp.py
```

Opens a page at `http://localhost:8501` — paste a game link, optionally set your
username/color, click **Analyze**, and watch live progress (MCP connection status,
each tool call) before the results render below:

- the full prose training-plan report;
- one large step-through board per critical moment (`chess_coach_agent/board_render.py`,
  built on `chess.svg`, navigated with ◀ ▶ rather than a row of tiny thumbnails):
  first the move you actually played (🔴), then the engine's plan continuing move by
  move (🟢) — each mistake also carries a short human interpretation (💡) the agent
  writes itself (a `move-notes` block in its response, extracted by the UI — see
  `system_prompt.py`) explaining what the plan achieves and what was concretely worse
  about the move played, not just a centipawn number;
- if `generate_puzzle_from_position` produced a qualifying puzzle, the same
  step-through treatment for its forced winning line;
- if the bonus `smartsearch` connection is up, a short "More to explore" section
  from semantic search over the resource library (see below).

Board and puzzle data come straight from the `analyze_game` /
`generate_puzzle_from_position` tool results captured off the message stream —
nothing is re-derived from the prose report. Both entrypoints share the same
session driver (`chess_coach_agent/core.py`); the web UI is purely a display
layer over it, not a separate implementation.

## Bonus: semantic search over the resource library (4th MCP connection)

Beyond the assignment's required existing + custom servers, this project wires up
a **fourth, optional** MCP connection: local semantic search over the 150-entry
study-resource library (`data/study_resources.json`) and the training journal,
via a vendored, locally-patched build of the community `smart-connections-mcp`
server. It's purely supplementary — the agent still uses the required, deterministic
`coach.recommend_study_resources` tool as its primary recommendation path; semantic
search only adds a few "you might also like" results found by meaning rather than
exact theme tags. See `third_party/smart-connections-mcp/PATCH_NOTES.md` for what
was found, patched, and verified (two real bugs in the upstream package), and
`docs/design_rationale.md` for why this is optional rather than one of the graded
required tools.

One-time setup (after Obsidian + the Smart Connections community plugin are
installed and the vault has been opened at least once):

```bash
cd third_party/smart-connections-mcp
npm install
npx tsc
cd ../..
.venv/Scripts/python.exe scripts/build_smartsearch_index.py
```

If this build step hasn't been run, `smartsearch` is simply omitted from the
agent's MCP connections (not shown as "failed") — everything else still works.

## Documentation

- [`docs/tool_contracts.md`](docs/tool_contracts.md) — full Part C contracts for all
  4 custom tools + the existing-server tools used
- [`docs/design_rationale.md`](docs/design_rationale.md) — why each server/tool,
  trade-offs, limitations
- [`docs/demo_script.md`](docs/demo_script.md) — defence checklist mapped to the
  assignment's required demo steps

## Tests

```bash
.venv/Scripts/python.exe -m pytest
```

Covers move classification thresholds, puzzle filtering, and resource ranking
(pure logic; no engine or network needed).

## Security / operational notes

- No secrets in the repo: the Obsidian API key lives only in `.env` (gitignored).
- The custom server uses only local data at runtime (Stockfish + CSV + JSON).
- Playwright is used read-only against public pages; no logins, no form input.
- Rate limits: the agent makes ~1 page load per run against lichess.org; the
  dataset script downloads one static file from database.lichess.org.

Maintenance

ActivityMaintained
ResponsivenessNo issues