Skip to main content
Glama

anki-mcp

MCP server for headless Anki card management. Runs as a sidecar to a sync server (e.g. anki-sync) and writes directly to the same SQLite collection (collection.anki2) that the Anki Desktop client syncs.

LLM agents connect via the Model Context Protocol (streamable-http) and call one of 10 tools: list_decks, create_deck, delete_deck, add_card, add_cloze, find_notes, get_note, update_note, delete_note, add_media.

Built on top of AnswerDotAI/fastanki (vendored under src/fastanki/, version 3.0).

Prerequisites

  • Docker Engine 24+ with Compose v2 (docker compose plugin)

  • An existing Anki Desktop profile whose collection.anki2 you want to manage

  • (Optional) an Anki sync serveranki-mcp is designed to share its collection with one, but it can also run standalone

Related MCP server: Anki MCP Server

Quick start

git clone https://github.com/icem0/anki-mcp.git
cd anki-mcp

# 1. Configure secrets
cp .env.example .env
$EDITOR .env   # set SYNC_USER1, SYNC_USER1_NAME and ANKI_MCP_TOKEN
# ANKI_MCP_TOKEN can be any random string >= 32 chars. Generate with:
#   openssl rand -hex 32

# 2. Build and start
docker compose up -d --build

# 3. Verify the MCP endpoint responds (unauthenticated request returns 401;
#    this is expected — only requests with the correct Bearer token succeed)
curl -s -o /dev/null -w '%{http_code}\n' -X POST http://localhost:8765/mcp
# → 401

# 4. With the token from .env:
TOKEN=$(grep ^ANKI_MCP_TOKEN .env | cut -d= -f2)
curl -s -X POST http://localhost:8765/mcp \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"smoke","version":"0"}}}'

The first list_decks call will return what is currently in collection.anki2 at the path pointed to by FASTANKI_DIR.

Repo layout

anki-mcp/
├── server.py            # FastMCP server, 10 tools
├── src/fastanki/        # vendored fastanki 3.0 (added to sys.path at startup)
├── Dockerfile           # python:3.12-slim + requirements
├── compose.yaml         # 2-service stack: anki-sync + mcp, shared collection volume
├── requirements.txt
├── pyproject.toml       # fastanki metadata
├── .env.example
├── docs/
│   ├── env.md           # complete env-var reference
│   ├── architecture.md  # how the two services share one collection
│   └── deployment.md    # standard docker compose workflow
└── .gitignore

MCP tools

Tool

Args

Returns

list_decks

["Default", "MPA", ...] (sorted)

create_deck(name)

deck name (use :: for nesting)

{name, id} — idempotent, no error if exists

delete_deck(name)

deck name

{name, removed} — deletes deck + subdecks + cards

add_card(deck, fields, model="Basic", tags=None)

deck name, {Field: value}, notetype, space-separated tags

note id

add_cloze(text, deck="Default", back_extra="", tags=None)

cloze text with {{c1::hidden}}

note id

find_notes(deck?, tag?, fields?)

all optional, AND-joined

[{id, tags, fields}]

get_note(note_id)

note id

{id, tags, fields}

update_note(note_id, fields?, tags?, add_tags?)

id + mutators

{ok, id}tags REPLACES, add_tags APPENDS

delete_note(note_id)

note id

{ok, id} — deletes note + its cards

add_media(path, fname=None)

absolute file path, optional rename

stored filename

Environment variables

See docs/env.md for the complete reference. Three values are secrets, all defined in .env.

Architecture

See docs/architecture.md for how anki-sync and anki-mcp share one SQLite collection via a Docker named volume and the FASTANKI_DIR environment variable.

Deployment

See docs/deployment.md for the standard docker compose workflow (build, start, update, inspect).

License

Apache-2.0 (inherited from upstream fastanki).

Maintenance

ActivityMaintained
ResponsivenessResponsive

Related MCP Connectors

Related MCP Servers