anki-workflow-mcp
Provides tools for validating, compiling, and registering Anki flashcards, including CSV, Cloze, QA, hints, media, taxonomy, cross-reference checks, ID manifests, and export synchronization for Anki-compatible workflows.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@anki-workflow-mcp Create and validate five QA flashcards about cell division."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
anki-workflow-mcp
Servidor MCP para validar, compilar e registrar flashcards Anki: o LLM escreve; o servidor verifica estrutura, conta e registra. Compatível com os campos QA/Cloze e as convenções de apresentação AnkiMBR; templates, mídia e coleções não são distribuídos aqui.
Recursos
Validação CSV, Cloze, hints, QA, notas, imagens, tabelas, taxonomia e referências cruzadas.
Manifesto transacional, registro de IDs, recibos de conteúdo e exportação com locks e recuperação de falhas.
Catálogos de mídia, namespacing e sincronização para destino explicitamente configurado.
Perfis descritivos que separam contexto, recuperação obrigatória e explicação opcional; não certificam correção clínica ou qualidade pedagógica.
Triagem determinística e integração opcional com provedores externos, somente quando configurados.
Related MCP server: Anki MCP Server
Instalação
Requer Python 3.12–3.14; CI em Python 3.13. Instale o uv e execute:
uv tool install --python 3.13 "git+https://github.com/Gugart43/anki-workflow-mcp-public.git"
anki-workflow-mcpO comando inicia o transporte stdio; configure seu cliente MCP para executar anki-workflow-mcp. Evite mensagens próprias em stdout, reservado ao protocolo. A branch pode evoluir; para instalação reproduzível, fixe um SHA revisado em vez da branch.
Desenvolvimento
git clone https://github.com/Gugart43/anki-workflow-mcp-public.git
cd anki-workflow-mcp-public
uv sync --extra dev --frozen
uv run ruff check src tests
uv run ruff format --check src tests
uv run pytest --cov=anki_mcp --cov-fail-under=70
uv run --with mypy mypy src --ignore-missing-importsOrganização
.github/workflows/ CI Linux e Windows
src/anki_mcp/ servidor, modelos, checks, estado e ferramentas MCP
tests/ testes de regressão, sem datasets ou coleções pessoais
docs/ arquitetura, segurança e limites dos perfisEscopo público
Esta distribuição começa com histórico novo. Não inclui estudos privados, corpus, exports, logs, backups, templates extraídos, dados de Anki ou configurações de infraestrutura. Exemplos/testes são demonstrações técnicas, não recomendações médicas. Uma revisão de segurança reduz riscos, mas não oferece garantia absoluta. Não use dados de pacientes para testes ou envie conteúdo confidencial a provedores externos.
Available Tools
49 toolsbatch_auto_fixBatch Auto FixA
Automatically repair and sanitize an entire draft CSV block (QA or Cloze). Enforces canonical header, repairs unescaped pipes and newlines in long free-text fields, escapes clinical inequalities (< 10, > 50) and bare '&', converts basic markdown, and auto-closes simple unclosed tags. Returns fixed_csv, fixes_applied, and residual diagnostics.
Inputs: csv_text (required), note_type (required). Returns: object
batch_patch_draftBatch Patch DraftC
Apply a surgical patch directly to a CardDraft within a persistent batch staging file. staging_path: path to drafts.jsonl or .staging_{batch_id}/drafts.jsonl. card_index: 0-based index of card to update. patch_json: JSON string with 'updates'.
Inputs: card_index (required), patch_json (required), staging_path (required), timeout_s. Returns: object
card_patch_applyCard Patch ApplyB
Apply a surgical patch or field updates to a single CardDraft JSON object. Allows repairing a failed card in isolation without regenerating the entire batch. card_json: JSON string of CardDraft. patch_json: JSON string with 'updates' dictionary.
Inputs: card_json (required), patch_json (required). Returns: object
card_quarantineCard QuarantineB
Partition invalid cards out of the active batch into a quarantine record. Allows the remaining valid cards to advance through G3 export under PARTIAL_PASS. drafts_json: list of CardDraft objects. failed_indices: 0-based indices of cards to isolate.
Inputs: drafts_json (required), failed_indices (required), reason. Returns: object
cards_compile_draftsCards Compile DraftsB
Compile a list of structured CardDraft JSON objects into AnkiMBR-compliant QA and Cloze CSV blocks. Applies deterministic HTML escaping, sequential cloze renumbering (c1..cN), ID leak purging, markdown table conversion, and pipe-delimiter escaping. Accepts a JSON string of a list or {'cards': [...]}. Returns qa_csv, cloze_csv, and compilation stats.
Inputs: drafts_json (required), auto_renumber, auto_purge_ids, default_campo_estudo. Returns: object
catalog_loadCatalog LoadB
Load and index an extractor catalog (catalog.json, anki_catalog.csv, catalog.md, or central_images.json) into active memory and optionally register it in the deck's manifesto.json. Returns counts of figures, tables, valid clinical items, filtered extraction noise, and version hash.
Inputs: catalog_path (required), deck_dir. Returns: object
corpus_coverageCorpus CoverageB
Compare corpus vocabulary against the deck Manifesto to identify coverage gaps.
Inputs: deck_dir (required). Returns: object
corpus_digestCorpus DigestC
Unified triage + coverage report for all corpus files in the deck.
Inputs: deck_dir (required). Returns: object
corpus_loadCorpus LoadB
Persist source material into the deck's corpus directory for later triage.
Inputs: text (required), label (required), deck_dir (required). Returns: object
corpus_triageCorpus TriageB
Score source material for flashcard potential. Pass inline text or a stored label.
Inputs: deck_dir (required), text, label. Returns: object
count_batch_cardsCount Batch CardsA
Count the Anki card budget for a batch. QA notes = 1 card each. Cloze notes: each distinct cN index = 1 card. Returns qa_cards, cloze_notes, cloze_indices (expanded count), total, within_limit (≤20), excess, and ext_batch_suggested if over the limit.
Inputs: qa_csv (required), cloze_csv (required), batch_id. Returns: object
csv_build_rowCsv Build RowA
Build a single, guaranteed-safe pipe-delimited CSV row from a list of field values. Applies all formatting-guide rules: newlines→, pipe→|, inequalities→</>, bare &→& without double-escaping, while preserving valid HTML tags. fields must match the note type: 7 values for QA, 6 for Cloze. Returns the safe CSV line string.
Inputs: fields (required). Returns: object
deck_auditDeck AuditB
Full deck health audit: orphan IDs, phantom IDs, batch integrity, and coverage summary.
Inputs: deck_dir (required). Returns: object
deck_hierarchy_addDeck Hierarchy AddB
Add a new subdeck to the 02_MEDICINA_AnkiMBR hierarchy and persist the update immediately. subdeck_path: the full or relative subdeck path to add (e.g. '02_MEDICINA_AnkiMBR::Ciclo Clínico::Oftalmologia::Catarata'). Automatically creates all missing parent levels in the hierarchy.
Inputs: subdeck_path (required), root_deck. Returns: object
deck_hierarchy_getDeck Hierarchy GetB
Get the registered deck hierarchy for 02_MEDICINA_AnkiMBR. filter_prefix: optional sub-path filter (e.g. '02_MEDICINA_AnkiMBR::Ciclo Clínico::Neurologia'). max_depth: max nesting level to include (default 10). format_tree: if true, returns an ASCII/Unicode visual tree instead of list.
Inputs: max_depth, format_tree, filter_prefix. Returns: object
deck_hierarchy_searchDeck Hierarchy SearchB
Search the 02_MEDICINA_AnkiMBR hierarchy for subdecks matching a keyword or topic. query: search string (e.g. 'Catarata', 'Neurologia', 'Glaucoma', 'Esclerose'). root_deck: root prefix to restrict to (default '02_MEDICINA_AnkiMBR').
Inputs: query (required), root_deck. Returns: object
deck_hierarchy_syncDeck Hierarchy SyncB
Synchronize deck hierarchy from the live Anki SQLite database collection.anki2. Safely handles running Anki locks and merges with any manually added subdecks.
Inputs: root_deck, anki_collection_path. Returns: object
export_finalExport FinalA
Final transactional export of a validated batch; the SOLE writer of the final CSV files and of the Manifesto post-export. Requires the content_hash returned by pipeline_gate_check / validate_batch on PASS. Order: receipt check and full re-validation (read-only) → under one deck lock: ID checks, staged writes, replace, manifesto save; any failure rolls files back. Re-running with the same receipt on an exported batch returns ALREADY_EXPORTED and writes nothing. Parameters: deck_dir; batch_id; qa_csv; cloze_csv; receipt_hash; new_ids_json (JSON array of {id, batch, type, status, topic, anchor}); new_topics_json (JSON array of strings); changelog_json (JSON array of changelog objects); topic_slug (optional, e.g. 'EscleroseMultipla'); write_to_deck_root (also copy into the deck root, default True). Writes: deck_dir/exports/{batch_id}[_{topic_slug}]_QA.csv and _Cloze.csv.
Inputs: qa_csv (required), batch_id (required), deck_dir (required), cloze_csv (required), +6 more. Returns: object
gap_requestGap RequestA
Log a gap or unresolved decision point that halts the pipeline. Per the Gap Request Protocol in anki-card-generator: when the pipeline encounters a decision without a governing rule, it MUST halt and log here instead of inventing ad-hoc rules. deck_dir: deck folder path. batch_id: e.g. 'B07'. gap_description: clear description of the decision needed. context: relevant snippet or options. Returns a gap_id and logs it to the Manifesto suggestion queue.
Inputs: batch_id (required), deck_dir (required), gap_description (required), context. Returns: object
id_ledger_queryId Ledger QueryB
Query the ID ledger. filters: comma-separated values like 'batch=B01', 'status=active', 'type=QA'. Returns matching ID entries and a summary.
Inputs: deck_dir (required), filters. Returns: object
image_candidatesImage CandidatesB
Rank and retrieve relevant figure and table entries from an extractor catalog. Uses token-based, accent-insensitive clinical matching across title, caption, tags, and filename, automatically filtering out extraction noise (dummy captions, copyright headers, tiny logos). item_type: 'all' | 'figure' | 'table'. Returns ranked candidates with ready-to-use namespaced filename, table dimensions, and HTML.
Inputs: query (required), catalog_path (required), item_type, max_results, +1 more. Returns: object
image_namespaceImage NamespaceB
Apply the slug prefix to convert a raw filename to its Anki-safe namespaced form. Avoids double-prefixing when extractor filenames already contain the document prefix.
Inputs: slug (required), filename (required). Returns: object
image_reportImage ReportC
Summary report across one or more catalogs: totals, figures, tables, noise, sync ratios.
Inputs: catalog_paths (required), collection_media_dir. Returns: object
image_syncImage SyncB
Check consistency between a catalog and Anki collection.media. If apply=True, executes transactional copying of missing files (under their namespaced name) to collection.media, skipping noise entries unless copy_noise=True.
Inputs: catalog_path (required), apply, copy_noise, only_filenames, +1 more. Returns: object
manifesto_commitManifesto CommitA
Sole writer of the Manifesto. Commits a batch's data transactionally. Requires a valid receipt (content_hash from validate_batch PASS). Parameters: deck_dir, batch_id, receipt_hash, qa_csv, cloze_csv (for receipt verification), new_ids (JSON array of IDEntry dicts), new_topics (JSON array of strings), new_tags (comma-separated), changelog_entries (JSON array), queue_updates (JSON array of strings to add).
Inputs: qa_csv (required), batch_id (required), deck_dir (required), cloze_csv (required), +7 more. Returns: object
manifesto_importManifesto ImportB
Import a legacy manifesto.md into manifesto.json format. Parses the markdown file and creates manifesto.json. deck_dir: folder containing the manifesto.md. manifesto_md_name: filename (default 'manifesto.md'). Reports all parsed sections and any parsing issues.
Inputs: deck_dir (required), manifesto_md_name. Returns: object
manifesto_initManifesto InitA
Initialize a new manifesto.json for a deck. deck_dir: absolute path to the deck folder. campo_estudo: e.g. 'Medicina::Neurologia::ELA'. deck_slug: short identifier (e.g. 'ela'). taxonomy_root: root tag (e.g. 'ELA'). Will NOT overwrite an existing manifesto.json.
Inputs: deck_dir (required), deck_slug (required), campo_estudo (required), taxonomy_root (required). Returns: object
manifesto_plan_setManifesto Plan SetB
Register the top-down total card budget plan for a topic into the Manifesto before drafting. Enforces that the TOTAL quantity of cards is planned before complete production, chunked strictly into batches of 20 (MAX_BATCH = 20).
Inputs: deck_dir (required), total_planned (required), batches_planned (required), rationale, +2 more. Returns: object
manifesto_stateManifesto StateA
Read the current state of the Manifesto. deck_dir: absolute path to the deck folder. sections: comma-separated subset to return ('all', 'ids', 'topics', 'taxonomy', 'catalogs', 'changelog', 'queue', 'batches').
Inputs: deck_dir (required), sections. Returns: object
media_figure_buildMedia Figure BuildB
Construct a standardized AnkiMBR tag with clinical caption. Ensures semantic container formatting (class='anki-figure') without inline styles. Supports optional title and context_link to connect the image/table to the card's clinical concept.
Inputs: filename (required), style, title, caption, +2 more. Returns: object
pipeline_gate_checkPipeline Gate CheckA
Evaluate all gate checks for a pipeline phase without advancing the state. A PASS records the receipt for the batch (content_hash); a FAIL or INCOMPLETE invalidates any earlier receipt for that phase. Also returns read-only information_profiles (3-layer breakdown per row, excluded from receipt hash; length-only signals are advisory WARN, never blocking). deck_dir: deck folder (manifesto + anki_catalog.csv). batch_id: e.g. 'B07'. phase: drafted|curated|enriched|illustrated|validated. qa_csv / cloze_csv: full CSV texts. detail: 'compact' (default; diagnostics aggregated by code with affected rows) or 'full' (every check). Verdict: PASS | INCOMPLETE (a check could not run; no receipt) | FAIL.
Inputs: phase (required), qa_csv (required), batch_id (required), deck_dir (required), +2 more. Returns: object
pipeline_phase_advancePipeline Phase AdvanceA
Advance a batch through the pipeline state machine. deck_dir: absolute path to the deck folder. batch_id: e.g. 'B07'. Leaving a phase requires the receipt recorded by a PASS of pipeline_gate_check(phase=). receipt_hash is optional; if given it must equal that recorded receipt. Allowed transitions: started→drafted→curated→enriched→illustrated→validated→exported.
Inputs: batch_id (required), deck_dir (required), receipt_hash. Returns: object
review_batchReview BatchB
One-shot batch review: runs every check over QA + Cloze CSVs and returns an aggregated report with fix hints, read-only information_profiles (separating retrieved target, necessary context, and optional explanation; semantic_review_required=True; no automatic QA->Cloze conversion; excluded from receipt hash), and the receipt (content_hash on PASS). If deck_dir is given and batch_id is registered, the gate is recorded like pipeline_gate_check. detail: 'compact' (default) or 'full'.
Inputs: qa_csv (required), cloze_csv (required), phase, detail, +2 more. Returns: object
sanitize_card_fieldSanitize Card FieldA
Sanitize a single card field: converts mathematical/clinical inequalities (< 10, > 50, <=, >=) to HTML entities (<, >, ≤, ≥), bare & to &, pipes to |, newlines to , while strictly preserving valid HTML tags (, , , , , , , ). Returns sanitized string and list of fixes applied.
Inputs: text (required), is_images_field, convert_markdown. Returns: object
table_buildTable BuildB
Validate a TableSpec JSON string, render it to single-line HTML without inline styles, and run table checks. Returns {status: 'PASS'|'FAIL', html: str, diagnostics: list}.
Inputs: spec_json (required). Returns: object
table_from_markdownTable From MarkdownA
Convert GitHub-style markdown tables in text (with raw or escaped pipes, separated by newlines or ) into HTML tables. Returns {status: 'PASS'|'FAIL', text: str, tables_converted: int, diagnostics: list}.
Inputs: text (required). Returns: object
taxonomy_checkTaxonomy CheckB
Check tags against the Manifesto taxonomy. tags: space-separated list. Returns ok/unregistered/depth/format per tag.
Inputs: tags (required), deck_dir (required). Returns: object
topic_budget_planTopic Budget PlanC
Calculate top-down total card budget for a topic based on source text and clinical decisions. Plans total cards upfront and chunks strictly into batches of 20 (MAX_BATCH = 20).
Inputs: deck_dir (required), text, label, batch_size, +1 more. Returns: object
topic_triage_calibrateTopic Triage CalibrateC
Calibrate topic flashcard budget via Sectional HCT with JEV System 1 & Must-Cover Matrix. Slices source into clinical sections, computes expected cards (EV), and partitions into batches <= 20.
Inputs: text, label, domain, use_jev, +3 more. Returns: object
validate_batchValidate BatchA
Full batch validation: runs every export-validator check over a complete QA CSV + Cloze CSV pair. Returns a ValidationReport with a verdict: PASS (content_hash = receipt), INCOMPLETE (some check could not run; see skipped; no receipt) or FAIL, plus read-only information_profiles (3-layer profile per row with note_type and row; excluded from receipt hash; length-only signals are advisory WARN). taxonomy_tags: space-separated registered tags. active_ids / current_batch_ids: comma-separated. catalog_filenames: comma-separated namespaced image filenames (needed to verify sources; without it, image-bearing rows are reported as skipped).
Inputs: qa_csv (required), batch_id (required), cloze_csv (required), active_ids, +4 more. Returns: object
validate_clozeValidate ClozeA
Validate cloze syntax in a 'Sentença' field value. Checks: sequential c1..cN indices (operational cap 3; each index creates a separate Anki card with other indices visible), no nested deletions, boundary/length advisory WARN signals (length alone never proves atomicity and a single gap can hide a list). Returns: status, detected indices, card_count (= distinct cN), diagnostics, and information_profile (per-index 3-layer breakdown, candidate_items, 6-question checklist; read-only, no quality score).
Inputs: sentence (required), row. Returns: object
validate_crossrefsValidate CrossrefsB
Check cross-references in any field text. active_ids and current_batch_ids are comma-separated ID strings. XREF.BROKEN is emitted for IDs that do not resolve.
Inputs: text (required), row, field, active_ids, +1 more. Returns: object
validate_csv_structureValidate Csv StructureB
Validate the structural integrity of a QA or Cloze CSV block. Checks: header match, column count, raw pipes, raw newlines, HTML entities, forbidden tags, MathJax balance, and UTF-8 BOM. note_type must be 'QA' (7 fields) or 'CL' (6 fields).
Inputs: csv_text (required), note_type (required). Returns: object
validate_hintsValidate HintsB
Validate hints in a cloze sentence '{{cN::target::hint}}'. Checks: HINT.SYNONYM (high overlap), HINT.ELIMINATION (binary alternatives), HINT.ROOT_LEAK (target root in hint), HINT.FORMAT (empty hint).
Inputs: sentence (required), row. Returns: object
validate_images_fieldValidate Images FieldA
Validate the 'Imagens Relacionadas' HTML field. Checks: IMG.CAP_OVER (>3), IMG.PHANTOM (src not in catalog), IMG.NAMESPACE (invalid slug prefix), IMG.DUP_IN_CARD, IMG.STRUCTURE ( malformed), IMG.CAPTION (empty/noisy). catalog_filenames: comma-separated list of valid namespaced filenames. Without it, a field containing returns status INCOMPLETE (phantom unverifiable).
Inputs: html (required), row, catalog_filenames. Returns: object
validate_notesValidate NotesB
Validate the 'Notas Adicionais' optional explanation field (same unit, authorized source; empty/short notes allowed with no minimum volume and variable depth). Checks: NOTE.METADATA (CRITICAL), NOTE.DUP_ANSWER_WARN (normalized HTML/entity/punctuation exact repeat), NOTE.EXAM_ONLY_WARN (exam mention without explanation), NOTE.LENGTH_WARN, NOTE.STYLE_WARN. Returns information_profile (note_type='QA', prompt_available=False limitation noted).
Inputs: notes (required), row, answer, max_length. Returns: object
validate_qaValidate QaA
Validate a QA pair (stem + answer), separating retrieved recall target from necessary stem context (stem context length is not extra recall; length-only checks emit WARN, never CRITICAL). Checks: QA.CARDINALITY (≥3 items → review unit, split independent recalls or move optional details to notes; no automatic QA->Cloze conversion), QA.YESNO, QA.MC_EMBED, QA.CONTEXT_WARN, QA.NUMBER_UNIT. Returns information_profile with candidate_items, evidence, and 6-question editorial checklist.
Inputs: resposta (required), enunciado (required), row. Returns: object
validate_tables_fieldValidate Tables FieldB
Validate HTML table syntax, mobile screen constraints, and check for markdown table leaks. Returns {status: 'PASS'|'FAIL', diagnostics: list}.
Inputs: html (required), row, face, field. Returns: object
validate_tags_fieldValidate Tags FieldA
Validate the 'Etiquetas' field. Checks: TAG.FORMAT (spaces/invalid chars), TAG.DEPTH (>4 levels), TAG.UNREGISTERED (against provided taxonomy). taxonomy_tags: space-separated string of all registered tags (or empty to skip taxonomy check).
Inputs: tags_field (required), row, taxonomy_tags. Returns: object
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 49 tools
Several clusters have overlapping boundaries: validate_batch, review_batch, pipeline_gate_check and validate_csv_structure all appear to run the same validation suite over CSVs, while topic_budget_plan, topic_triage_calibrate and manifesto_plan_set all compute a card budget plan. Sanitization/compilation is similarly split across csv_build_row, sanitize_card_field, batch_auto_fix and cards_compile_drafts, and card_patch_apply vs batch_patch_draft, manifesto_commit vs export_final require careful reading to distinguish.
All names are snake_case and human-readable, but the ordering convention is mixed: verb_noun (validate_cloze, cards_compile_drafts, build-style csv_build_row) coexists with noun_first (corpus_coverage, topic_budget_plan, image_sync, deck_audit, card_quarantine). The inconsistency is not fatal but makes prefix-based grouping unreliable.
49 tools is far above a comfortable surface for an agent to select from reliably, and the count is inflated by near-duplicate validators and budget planners. The domain is genuinely multi-stage, but a tighter set of aggregate tools plus narrower ones would serve better.
The surface is unusually complete for its domain: corpus ingestion and triage, manifesto lifecycle, field-level and batch validation, compilation, image catalog/sync, deck hierarchy management, gated pipeline advancement and transactional export. Only minor gaps exist, such as no batch enumeration/rollback or card-preview tool separate from the validators.
Maintenance
Related MCP Connectors
Read, write, and conversationally review open-source flashcards through split read/write MCP tools.
Build study flashcards and exam-prep decks from your AI chat, all stored locally.
Generate contextual prompts and reusable agent skills, evaluate prompts with the 16-dimension Prompt Score, and manage saved work in PromptDrive. Twelve MCP tools also provide authorized access to private Memory for source-grounded answers. Connect over Streamable HTTP using OAuth 2.1 and PKCE. Generation consumes account quota and automatically saves successful results; Memory access follows account permissions and plan limits.
Spaced-repetition flashcards your AI writes, quizzes you on by voice, and schedules with FSRS.
Related MCP Servers
- FlicenseNot gradedqualityAmaintenanceExposes Anki flashcard collections to AI assistants via MCP, enabling AI-powered study sessions, card creation, deck management, and review workflows. Supports comprehensive collection operations including search, media management, and note type customization.100-
- AlicenseAqualityDmaintenanceEnables AI assistants to manage Anki flashcard collections by creating, searching, and updating cards through a standardized interface. It supports media handling, batch operations, and review scheduling via the AnkiConnect add-on.62MIT
- FlicenseBqualityCmaintenanceEnables AI assistants to directly manage Anki flashcards, decks, notetypes, tags, and media, with support for batch operations, searches, and deck exports via file-based input/output.23-
- AlicenseNot gradedqualityAmaintenanceEnables AI clients to create spaced-repetition flashcards from material being learned, quiz users aloud, grade answers, and schedule reviews using the FSRS algorithm through a self-hosted MCP server.8AGPL 3.0