Skip to main content
Glama

anki-mcp

An MCP server that gives agents (Claude Code, Claude Desktop, …) access to your local Anki collection via AnkiConnect.

Tool

What it does

list_decks

Decks with counts and source (anki / yanki = synced from Obsidian / mixed)

search_notes

Anki search syntax, paginated compact previews

get_notes

Full content for specific note ids

get_weak_cards

Most-forgotten cards (lapses, then ease), optionally per deck

add_notes

Batch add with validation, dry_run, duplicate check, auto-tag mcp-added, optional free TTS audio; refuses Yanki-owned decks

Skills in .claude/skills/:

  • flashcards routes cards: technical/interview topics become markdown in the Obsidian vault (synced by Yanki), and everything else goes straight to Anki.

  • language-cards (/language-cards <words>) adds vocabulary to the Spanish/French/Latin decks using their note types, with pronunciation audio.

Installation

Requirements

  • macOS (the offline voices and audio conversion use the built-in say and afconvert)

  • uv (brew install uv); it installs Python 3.11+ for you if needed

  • Anki desktop

  • Claude Code

1. Anki + AnkiConnect

  1. In Anki: Tools → Add-ons → Get Add-ons…, enter code 2055492159, and restart Anki.

  2. Keep Anki open whenever you use the server. AnkiConnect listens on http://127.0.0.1:8765.

2. eSpeak NG (for Latin audio)

Google's voices have no real Latin, so Latin uses eSpeak NG's Latin voice. It's robotic, but the pronunciation is correct.

brew install espeak-ng

Check it: espeak-ng --voices=la should list Latin.

3. The server

git clone <this repo> ~/Projects/anki-mcp   # or copy the folder
cd ~/Projects/anki-mcp
uv sync
uv run python scripts/smoke.py              # read-only check over stdio; Anki must be running

4. Register with Claude Code

claude mcp add anki --scope user -- uv --directory /absolute/path/to/anki-mcp run anki-mcp

Then start a new Claude Code session and run /mcp: anki should show as connected. --scope user makes the tools available in every project. The skills only load when Claude Code runs inside this folder, unless you copy .claude/skills/* to ~/.claude/skills/.

Other agents (Claude Desktop, Cursor, VS Code, Codex, Gemini CLI, …)

MCP is agent-agnostic, so any MCP client can run this server. No clone is needed: uvx builds it straight from GitHub. Steps 1–2 (Anki + AnkiConnect, eSpeak) still apply.

The command every client runs:

uvx --from git+https://github.com/ikristina/anki-mcp anki-mcp

GUI apps often don't inherit your shell's PATH. If the server fails to start, replace uvx with its absolute path (which uvx, e.g. /Users/you/.local/bin/uvx).

Claude Desktop (~/Library/Application Support/Claude/claude_desktop_config.json), Cursor (~/.cursor/mcp.json), Windsurf, Gemini CLI (~/.gemini/settings.json), and most other clients use the mcpServers format:

{
  "mcpServers": {
    "anki": {
      "command": "uvx",
      "args": ["--from", "git+https://github.com/ikristina/anki-mcp", "anki-mcp"]
    }
  }
}

VS Code / GitHub Copilot (.vscode/mcp.json) uses servers:

{
  "servers": {
    "anki": {
      "type": "stdio",
      "command": "uvx",
      "args": ["--from", "git+https://github.com/ikristina/anki-mcp", "anki-mcp"]
    }
  }
}

OpenAI Codex CLI (~/.codex/config.toml):

[mcp_servers.anki]
command = "uvx"
args = ["--from", "git+https://github.com/ikristina/anki-mcp", "anki-mcp"]

The tools work the same everywhere. The skills (.claude/skills/) are Claude Code's format; with other agents, copy the relevant SKILL.md body into that agent's rules/instructions file. The skills also encode my deck names and note types, so adapt the tables to your collection.

Optional

  • ANKI_CONNECT_URL, if AnkiConnect isn't on http://127.0.0.1:8765 (claude mcp add anki -e ANKI_CONNECT_URL=http://... -- ...).

  • Obsidian with the Local REST API plugin and an Obsidian MCP server, needed only for the flashcards skill's Yanki path.

Related MCP server: Anki MCP Server

Audio voices

add_notes takes audio: {"field": ..., "voice": ...}. All engines are free:

Voice string

Engine

Needs

Used for

es-MX, fr, de, pt-BR, …

Google Translate (gTTS)

internet

Spanish, French (the same voices HyperTTS's GoogleTranslate service uses)

espeak:la

eSpeak NG

brew install espeak-ng

Latin

macos:Alice (any say -v '?' voice)

macOS say

macOS

natural offline voices

Google files are MP3; the offline engines produce M4A (AAC). Anki plays both.

See LEARNINGS.md for design notes.

Example use

screenshot anki-preview

Available Tools

5 tools
add_notesA

Add one or more notes. Every note gets tagged 'mcp-added' so the user can review them in Anki.

Only for decks with source='anki' (see list_decks); Yanki decks are rejected. Each note is validated first (deck exists, note type exists, field names match, not a duplicate of an existing first field in the same deck). Invalid notes are reported and skipped; valid ones are still added. Prefer one batched call over many single-note calls. Set audio on a note to generate pronunciation (needs internet; skipped in dry_run).

ParametersJSON Schema
NameRequiredDescriptionDefault
notesYes
dry_runNoValidate only; add nothing. Use to preview a batch.
allow_duplicatesNo

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Adds substantial behavior beyond the annotations: automatic 'mcp-added' tagging, per-note validation rules (deck, note type, field names, duplicate first field), partial-success semantics (invalid notes skipped, valid ones still added), and the internet dependency for audio that is skipped in dry_run. With annotations only declaring openWorld/idempotent/destructive hints, this text carries the real behavioral burden well.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the action and the preconditions, then validation behavior, then performance advice, then audio. Every sentence carries actionable information with no filler or repetition of the title.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, and the description does explain that invalid notes are 'reported and skipped', giving a rough sense of the result. It does not detail the shape of validation errors or the response of a successful batch, but for an add tool it is nearly complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 33%, but the description compensates for the important parameters: it explains dry_run ('validate only; add nothing'), the audio pronunciation generation, and batching of the notes array. It leaves allow_duplicates unexplained in the description, which is the one remaining gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb+resource ('Add one or more notes') and immediately describes the user-visible side effect (each note tagged 'mcp-added'). The write semantics clearly separate it from read-only siblings list_decks, search_notes, get_notes, and get_weak_cards, and list_decks is explicitly referenced.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

States the hard precondition (only decks with source='anki'; Yanki decks rejected), points to list_decks for checking, advises batching over many single-note calls, and explains when to use dry_run and audio. Both when-to-use and when-not are covered explicitly.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_notesA
Read-only

Get the full content of specific notes (HTML stripped, not truncated). Get ids from search_notes.

ParametersJSON Schema
NameRequiredDescriptionDefault
note_idsYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and openWorldHint, so safety is covered. The description adds meaningful output-behavior context beyond the annotations: content is HTML-stripped and not truncated, which tells the agent what form the returned note content takes.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two compact sentences with zero waste; the core action and its output guarantee are front-loaded, followed by the id-sourcing hint.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists so return values need not be explained, and the description adds the content-format guarantee plus the id-source workflow. Only the batch-size limit goes unmentioned, a minor gap for a one-parameter tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% for the single note_ids parameter, so the description must compensate. It usefully explains where the ids come from (search_notes) but says nothing about the array nature or the 1-50 item bounds enforced by the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource (get full note content) with clear qualifiers (HTML stripped, not truncated). It distinguishes itself from the sibling search_notes by clarifying that this returns full content while ids come from search.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes the agent to search_notes as the source of note_ids, giving clear context for when to use this tool. It stops short of stating when-not-to-use, but the workflow dependency is well established.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_weak_cardsA
Read-only

Find the cards the user struggles with most: highest lapse count (times forgotten), then lowest ease.

Good for 'quiz me on my weak spots' or deciding which topics need rewritten/extra cards. Suspended cards are excluded.

ParametersJSON Schema
NameRequiredDescriptionDefault
deckNoExact deck name (includes subdecks). Omit for all decks.
limitNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered. The description adds real behavioral context beyond that: the ranking algorithm (lapse count then ease) and the exclusion of suspended cards, which an agent would otherwise not know. Return format is not described, but an output schema exists.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences, front-loaded with the core purpose and ranking rule, followed by usage and an exclusion note. No filler; every sentence carries information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only ranked-query tool with an output schema, the description covers purpose, ranking semantics, usage scenarios, and the suspended-card exclusion. The only gap is that it never addresses the limit parameter, which leaves the agent to rely entirely on the schema's default and bounds.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 50%: 'deck' is documented in the schema ('Exact deck name (includes subdecks). Omit for all decks.') but 'limit' has no description anywhere. The description references no parameters at all, so it fails to compensate for the undocumented limit, its default of 15, or its max of 50.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Find the cards'), and goes further by defining exactly what 'weak' means: highest lapse count, then lowest ease. This distinguishes it from siblings like list_decks and search_notes, which serve different retrieval purposes.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides concrete usage contexts ('quiz me on my weak spots', deciding which topics need rewritten/extra cards), which tells the agent when this tool is the right choice. It does not explicitly name when to prefer a sibling instead, but the sibling set (list_decks, search_notes, get_notes, add_notes) has little functional overlap, so the risk of misrouting is low.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_decksA
Read-only

List all Anki decks with card counts (new / learning / due for review / own cards) and source.

source='yanki': generated from markdown in the user's Obsidian vault by the Yanki plugin. Read and quiz freely, but new cards must be written in Obsidian, not added here. source='anki': native deck, accepts add_notes. source='mixed': holds both kinds (or its subdecks do). add_notes works; prefer Obsidian for technical topics. Subdecks use '::' as the separator, e.g. 'DDIA::04_Transactions'. Counts include subdecks except 'own_cards'.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and openWorldHint=false, so safety is covered. The description adds real behavioral context beyond that: cards generated from an Obsidian vault cannot be created through this server, mixed decks partially accept add_notes, and counts include subdecks except own_cards. It doesn't address ordering or scale, but for a read-only listing that is minor.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded one-line summary of the resource and return shape, followed by compact, labeled source definitions and a separator explanation. Every sentence carries information; nothing is restated from the annotations or name.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple, parameterless read tool with an output schema present, the description covers everything an agent needs: what is listed, what each source value implies for writes, and how deck names decompose. Field-level return formatting is legitimately left to the output schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

There are zero input parameters, so the baseline is 4. The description instead invests in defining the semantics of returned fields (source values, 'own_cards' vs subdeck-inclusive counts) and the '::' subdeck separator with a worked example, which is genuinely useful for interpreting output.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('List all Anki decks') and immediately enumerates what comes back (new/learning/due/own cards plus source), which no sibling provides. The source taxonomy further distinguishes it from search_notes/get_notes/add_notes by making clear this is a deck-inventory tool, not a content tool.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives concrete routing guidance tied to each source value: read/quiz freely for yanki, 'add_notes works' for anki and mixed, and 'prefer Obsidian for technical topics.' It tells the agent when writes will and won't work. It stops short of explicitly saying when to call list_decks instead of get_weak_cards or search_notes, so it's context rather than a full when/when-not rule set.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_notesA
Read-only

Search notes and return compact previews (HTML stripped, fields truncated).

Returns total match count so you can paginate with offset. Use get_notes for full field content.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
queryYesAnki search syntax. Examples: 'deck:Go', '"deck:DDIA::04_Transactions" isolation', 'tag:leetcode', 'front:*heap*', 'added:7' (last 7 days), 'is:due'. Quote deck names containing spaces.
offsetNo

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover readOnlyHint=true and openWorldHint=false, so safety is declared. The description adds real behavioral context beyond them: results are truncated with HTML stripped, and the total match count is returned to support pagination. That is genuinely useful disclosure for a search tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences, each earning its place, with the core behavior front-loaded and the alternative and pagination note trailing. No waste.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description carries the return-value burden and does so (previews, truncation, match count). For a read-only search tool this is nearly complete, though it leaves limit/offset defaults and max results undescribed.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 33% — only 'query' is documented (with rich Anki syntax examples), while 'limit' and 'offset' are bare. The description partially compensates by explaining that the total match count enables offset-based pagination, but says nothing about limit semantics or defaults. Baseline 3 given partial compensation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Search notes') plus the return shape (compact previews, HTML stripped, fields truncated). It explicitly contrasts with the sibling get_notes, so an agent can distinguish them without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides a clear routing rule: use this for search previews, and 'Use get_notes for full field content.' That names the alternative and the condition selecting it. It doesn't cover other siblings (list_decks, get_weak_cards), so it stops short of full when-not guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 5 tool updatesv0.1.0
    • First observedadd_notes
    • First observedget_notes
    • First observedget_weak_cards
    • First observedlist_decks
    • First observedsearch_notes

TDQS

A4.4/5.0

Scored across 5 tools

Disambiguation5/5

Each tool has a clearly distinct purpose: listing decks, searching note previews, retrieving full note content, finding weak cards, and adding notes. search_notes and get_notes are complementary rather than overlapping, and get_weak_cards is a specialized query with a clear scope.

Naming Consistency5/5

All tool names follow a consistent snake_case verb_noun pattern: list_decks, search_notes, get_notes, get_weak_cards, add_notes. There is no mixing of conventions or vague naming.

Tool Count5/5

Five tools are well-scoped for an Anki MCP focused on reviewing decks, searching notes, inspecting cards, finding weak spots, and adding notes. Each tool earns its place without unnecessary bloat.

Completeness4/5

The surface covers core read operations (list/search/get/weak cards) and note creation, which supports the stated quiz-and-add workflow. It lacks update/delete operations for existing notes and deck management, but these are minor gaps for the apparent review-focused purpose.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers