anki-mcp
README.md
# anki-mcp
MCP server that exposes [Anki](https://apps.ankiweb.net/) as tools for Claude and other LLM clients. Powered by [AnkiConnect](https://foosoft.net/projects/anki-connect/).
Create notes, search your collection, review due cards, manage decks, track retention — all from your LLM client.
## Prerequisites
1. **Anki** must be running on the local machine.
2. **AnkiConnect** add-on must be installed: Anki → Tools → Add-ons → Get Add-ons → code `2055492159`.
- Default port: `8765`. Do not change it.
3. Node.js 18+.
## Quick start
```bash
npm install
npm run build # tsc → dist/
npm start # stdio transport
```
Development (no build step):
```bash
npm run dev # tsx src/index.ts
```
## Claude Desktop integration
Add to `claude_desktop_config.json`:
```json
{
"mcpServers": {
"anki": {
"command": "node",
"args": ["/absolute/path/to/anki_mcp/dist/index.js"]
}
}
}
```
## Available tools
| Tool | Description |
|---|---|
| `create_notes` | Create Basic or Cloze notes. Supports batch. |
| `search_notes` | Search with Anki browser syntax. Returns up to `limit` notes (default 50). Field search: `Front:*keyword*`. |
| `update_note` | Edit note fields in place by note ID. Preserves all card scheduling data. |
| `add_tags` | Add tags to notes by note ID. Supports `::` hierarchy. |
| `remove_tags` | Remove tags from notes by note ID. |
| `delete_notes` | Delete notes by ID (also deletes associated cards). |
| `move_notes` | Move notes to another deck (resolves note IDs → card IDs internally). |
| `create_deck` | Create deck or subdeck (`Parent::Child::Grandchild`). |
| `list_decks` | List all decks with due/new/learn counts. |
| `get_due_cards` | Get cards due for review in a deck (default limit 20, max 100). Returns `due` field. |
| `submit_answer` | Record answer for a card: 1=Again, 2=Hard, 3=Good, 4=Easy. |
| `reschedule_cards` | Postpone cards by N days. days=0 = due today. |
| `suspend_cards` | Suspend (hide) or unsuspend cards. Never scheduled but not deleted. |
| `forget_cards` | Reset cards to new state. Wipes scheduling; preserves note content and tags. |
| `get_insights` | Retention stats, overdue count, mature/young cards for a deck or all decks. |
| `sync` | Trigger AnkiWeb sync. |
## AnkiConnect conventions
- **ID types**: Note IDs and card IDs are different namespaces. Never pass note IDs where card IDs are expected.
- **Deck names**: Use `::` for hierarchy. Double-quotes in deck names must be escaped (`\"`).
- **Search syntax**: Anki browser syntax — `is:due`, `is:new`, `prop:due<0` (overdue), `deck:"Name"`, `tag:foo`, `nid:123`.
- **Error handling**: All AnkiConnect failures throw `AnkiConnectError(action, message)`. MCP SDK surfaces these to the client as tool errors.
## Architecture
```
src/
ankiconnect.ts — HTTP client, branded ID types, AnkiConnectError
tools/
notes.ts — create / search / update / delete / move notes + tag management
decks.ts — create / list / delete decks
study.ts — get due cards / submit answer / reschedule / suspend / forget
insights.ts — retention stats
index.ts — McpServer wiring (registerTool), stdio transport
```
## Performance notes
- `search_notes`: always pass a narrow query + explicit `limit` to avoid large payloads.
- `get_insights` on large collections calls `cardsInfo` in 500-card chunks sequentially; expect ~1s per 500 cards.
- `get_insights` without a deck argument fans out `cardReviews` to every deck — adds one request per deck.
## License
MIT
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessSyncing