Skip to main content

MCP server for Anki collection management

Project description

Shrike

Sometimes you want to work on your Anki collection without opening Anki. That's what Shrike is for. It's a command-line client and an MCP server for your collection, so you can manage cards from a terminal or hand them to an LLM agent.

Shrike works directly on the collection's SQLite database, without using the Anki desktop app or relying on the AnkiConnect bridge. You get:

  • a shrike CLI to browse, create, edit, and delete notes and note types
  • an MCP server exposing the same operations to agents
  • semantic search over your notes, with embeddings computed locally

Requirements

  • Python 3.12 or newer
  • An Anki collection (a collection.anki2 file)

Getting started

Install Shrike from PyPI:

pipx install shrike-mcp   # or: pip install shrike-mcp

The package is shrike-mcp; the command it installs is shrike.

Point Shrike at your collection and start the daemon:

shrike server start --collection ~/path/to/collection.anki2

That starts a background daemon with your collection open. The other shrike commands talk to it, so they don't repeat --collection:

shrike info
shrike note list --deck Default

And when you're done:

shrike server stop

Semantic search

shrike note search finds notes by meaning instead of keywords. It needs two things you supply yourself: a llama-server binary (from llama.cpp) to compute embeddings, and a GGUF embedding model for it to run.

Get llama.cpp by building it or installing it from a package manager; you want the llama-server binary it provides. For the model, any GGUF embedding model works. A small one like all-MiniLM-L6-v2 is a good default: it runs on CPU and is plenty for finding related cards.

Start Shrike with both:

shrike server start --collection ~/path/to/collection.anki2 \
  --llama-server ~/llama.cpp/build/bin/llama-server \
  --embedding-model ~/models/all-MiniLM-L6-v2-Q4_K_M.gguf

If --llama-server or --embedding-model isn't given on the command line or in your config file, Shrike falls back to LLAMA_SERVER_PATH and a llama-server on your PATH for the binary, and to SHRIKE_EMBEDDING_MODEL for the model.

Shrike builds an index of your notes in the background. A large collection takes a little while the first time; search will tell you if it's still indexing. Once it's ready:

shrike note search "electron transport chain"
shrike note search --similar-to 1700000000123

shrike note search also matches your query as exact text, so it finds notes that contain the words literally as well as ones that are semantically close; each result shows you which applied. The exact-text part works even without the embedding service running.

CLI

shrike info summarizes the collection: note types, decks, tags, and scheduling stats.

shrike info
shrike info --types --decks --stats

List and read notes:

shrike note list --deck "Organic Chemistry" --limit 20
shrike note show 1779749914797

Create a note by passing fields with -f:

shrike note create --deck "Japanese::Vocabulary" --type Basic \
  -f Front="読む (よむ)" -f Back="to read"

Cloze notes work the same way; the deletions go in the field:

shrike note create --deck "Systems Design" --type Cloze \
  -f Text="The {{c1::CAP theorem}} says a distributed system can guarantee at most two of {{c2::consistency}}, {{c3::availability}}, and {{c4::partition tolerance}}."

To add notes in bulk, pipe a JSON array to --json-input:

echo '[
  {"deck": "Biochemistry", "note_type": "Basic",
   "fields": {"Front": "What does ATP synthase do?",
              "Back": "Builds ATP from ADP and phosphate, driven by the proton gradient across the inner mitochondrial membrane."},
   "tags": ["metabolism", "mitochondria"]}
]' | shrike note create --json-input

Update fields, edit tags, or delete:

shrike note update 1779749914797 -f Back="to read; to interpret"
shrike note tag 1779749914797 --set verb,jlpt-n5
shrike note delete 1779749914797 --yes

shrike note tag edits a note's tags in one of three modes, and you pick one explicitly:

shrike note tag 1779749914797 --set verb,jlpt-n5         # replace all tags
shrike note tag 1779749914797 --add needs-review         # add, leaving others
shrike note tag 1779749914797 --add jp --remove jp-verb  # add and remove together
shrike note tag 1779749914797 --set ""                   # clear all tags

Fix text across many notes at once with shrike note replace. It needs a scope, previews the changes, and asks before applying:

shrike note replace "teh" "the" --deck "Biology"          # preview, confirm, apply
shrike note replace "colou?r" "color" --regex --tags spelling --dry-run

For tags across the whole collection, shrike tag renames:

shrike tag rename history::ww2 history::wwii   # rename everywhere it appears
shrike tag rename jp japanese --note 1779749914797   # only on these notes

Manage decks with shrike deck:

shrike deck create "Japanese::Vocabulary"      # nested decks use ::
shrike deck rename "Misc::French" "French"      # rename or reparent
shrike deck delete "Old Deck" --yes            # delete (must be empty first)

Anywhere a command takes a deck (including --deck on note commands), you can pass the deck's name, its numeric ID, or #id instead.

Note types have their own commands:

shrike type list
shrike type show Basic
shrike type create --name Vocab --field Word --field Meaning \
  --template 'Card 1:{{Word}}:{{FrontSide}}<hr>{{Meaning}}'

Every command takes --json for scriptable output. See the CLI reference for the full list of commands and flags.

Connect an MCP client

Start the server first (see Getting started). Clients connect to the running daemon at http://127.0.0.1:8372/mcp.

Claude Code connects over streamable HTTP directly:

claude mcp add --transport http shrike http://127.0.0.1:8372/mcp

Claude Desktop and claude.ai native URL connectors require OAuth, which Shrike doesn't implement yet, so connect through the mcp-remote stdio bridge instead. Add this to claude_desktop_config.json (Settings → Developer → Edit Config):

{
  "mcpServers": {
    "shrike": {
      "command": "npx",
      "args": ["mcp-remote", "http://127.0.0.1:8372/mcp", "--allow-http", "--transport", "http-only"]
    }
  }
}

The endpoint is unauthenticated and bound to loopback by default. Before exposing it past 127.0.0.1, read the transport-security and remote-access options in the CLI reference.

MCP Tools

Shrike exposes these MCP tools:

  • collection_info: collection structure, note types, decks, tags, and stats
  • list_notes: filter and retrieve notes by deck, tags, type, IDs, or date
  • search_notes: semantic similarity and exact-substring search over notes
  • collection_query: find notes with a raw Anki search expression (is:due, prop:, …)
  • find_replace_notes: bulk find and replace across note fields in a scoped set
  • migrate_note_type: change notes' note type with a field/template map (preserves history)
  • upsert_notes: create or update notes in bulk
  • upsert_note_types: create or update note type definitions
  • update_note_type_fields: add, remove, rename, or reposition a note type's fields (data-safe)
  • update_note_type_templates: add, remove, rename, or reposition a note type's card templates (data-safe)
  • find_replace_note_types: find and replace text in a note type's template HTML and CSS
  • update_note_type_field_metadata: set a note type's per-field editor metadata (font, size, description)
  • update_note_tags: set, add, or remove tags on a set of notes
  • rename_tag: rename a tag collection-wide or on specific notes
  • upsert_decks: create or rename/reparent decks in bulk
  • delete_decks: delete decks by name, if empty
  • delete_notes: permanently delete notes by ID
  • delete_note_types: delete note types by ID, if no notes use them
  • collection_prune: clean up unused tags, empty notes, and empty cards (previews by default)

The machine schema is whatever the running server advertises via tools/list. docs/mcp-tools.md is the human-readable companion.

Configuration

Shrike reads settings from a YAML file in the platform config directory: ~/.config/shrike/config.yml on Linux, ~/Library/Application Support/shrike/config.yml on macOS. The file is yours to manage; shrike server start never writes it on its own. To save the flags you started with so you don't have to repeat them, pass --save-config and Shrike writes the resolved settings to the file:

shrike server start --collection ~/path/to/collection.anki2 \
  --embedding-model ~/models/all-MiniLM-L6-v2-Q4_K_M.gguf --save-config

Most settings also take an environment variable (SHRIKE_URL, SHRIKE_COLLECTION, SHRIKE_EMBEDDING_MODEL, and more) or a command-line flag. Command-line flags take precedence, then environment variables, then the file. The CLI reference has the full list.

Development

python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"

pytest tests/unit -v                         # unit tests (no server)
pytest tests/integration -v -m integration   # integration tests (real server subprocess)
ruff check src/shrike/
mypy src/shrike/

Contributing

CONTRIBUTING.md covers branching, versioning, releases, and how defects get tracked.

License

AGPL-3.0-or-later

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

shrike_mcp-0.3.5.tar.gz (367.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

shrike_mcp-0.3.5-py3-none-any.whl (149.4 kB view details)

Uploaded Python 3

File details

Details for the file shrike_mcp-0.3.5.tar.gz.

File metadata

  • Download URL: shrike_mcp-0.3.5.tar.gz
  • Upload date:
  • Size: 367.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for shrike_mcp-0.3.5.tar.gz
Algorithm Hash digest
SHA256 0dfbc2f86e55bb998247cfdfab5d56f9c59bd2cdf4958f54fa307a8e55ca6df0
MD5 629f6250ae289d21e17a8b06a7c0fe5b
BLAKE2b-256 ad357ec38dddeeaa61a3bc292d5bb236843efcb5bec50a9266474781911af103

See more details on using hashes here.

Provenance

The following attestation bundles were made for shrike_mcp-0.3.5.tar.gz:

Publisher: release.yml on lathrys-at/shrike

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file shrike_mcp-0.3.5-py3-none-any.whl.

File metadata

  • Download URL: shrike_mcp-0.3.5-py3-none-any.whl
  • Upload date:
  • Size: 149.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for shrike_mcp-0.3.5-py3-none-any.whl
Algorithm Hash digest
SHA256 8f0aad08a639c5822865dc5ecfb60a5c4a83c4d8651b21f00e49fa3f0934af9e
MD5 99d1396adef6f901c4b25bf514f55f65
BLAKE2b-256 7d0b16198459c33368649150dfa9aa15a7c33829efe2fd3684468b0fe00a9f92

See more details on using hashes here.

Provenance

The following attestation bundles were made for shrike_mcp-0.3.5-py3-none-any.whl:

Publisher: release.yml on lathrys-at/shrike

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page