anki-workflow-mcp
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
Deterministic validation & state layer for the Anki flashcard generation workflow. Tools are tagged by domain: validate, mechanics, state, pipeline, media, compiler, tables, triage, hierarchy. Prompts: phase_rules(phase) provides guidance per pipeline phase. Resources: schema://card-draft, schema://manifesto, schema://report, vocab://classes. The LLM writes; the MCP judges, counts, and records.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": true
} |
| logging | {} |
| prompts | {
"listChanged": true
} |
| resources | {
"subscribe": false,
"listChanged": true
} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| validate_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). |
| validate_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). |
| validate_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). |
| validate_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. |
| validate_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). |
| validate_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). |
| validate_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. |
| validate_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). |
| validate_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). |
| cards_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. |
| card_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. |
| batch_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'. |
| card_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. |
| media_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. |
| csv_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. |
| sanitize_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. |
| batch_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. |
| count_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. |
| manifesto_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. |
| manifesto_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. |
| manifesto_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'). |
| manifesto_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). |
| manifesto_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). |
| taxonomy_checkB | Check tags against the Manifesto taxonomy. tags: space-separated list. Returns ok/unregistered/depth/format per tag. |
| id_ledger_queryB | Query the ID ledger. filters: comma-separated values like 'batch=B01', 'status=active', 'type=QA'. Returns matching ID entries and a summary. |
| catalog_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. |
| image_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. |
| image_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. |
| image_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. |
| image_reportC | Summary report across one or more catalogs: totals, figures, tables, noise, sync ratios. |
| table_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}. |
| table_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}. |
| validate_tables_fieldB | Validate HTML table syntax, mobile screen constraints, and check for markdown table leaks. Returns {status: 'PASS'|'FAIL', diagnostics: list}. |
| pipeline_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. |
| pipeline_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. |
| review_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'. |
| gap_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. |
| export_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. |
| deck_auditB | Full deck health audit: orphan IDs, phantom IDs, batch integrity, and coverage summary. |
| corpus_loadB | Persist source material into the deck's corpus directory for later triage. |
| corpus_triageB | Score source material for flashcard potential. Pass inline text or a stored label. |
| corpus_coverageB | Compare corpus vocabulary against the deck Manifesto to identify coverage gaps. |
| corpus_digestC | Unified triage + coverage report for all corpus files in the deck. |
| topic_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). |
| topic_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. |
| deck_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. |
| deck_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'). |
| deck_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. |
| deck_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. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
| phase_rules | Regras da fase atual do pipeline de flashcards |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
| CardDraft Schema | JSON Schema do CardDraft para geração de cards clínicos |
| Manifesto Schema | JSON Schema do Manifesto de governança |
| Semantic CSS Classes | Cheatsheet das classes semânticas CSS do AnkiMBR |
| ValidationReport Schema | JSON Schema do relatório de validação |
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.