使用说明
Anki MCP Server (Codemode)
An MCP server for AI-powered Anki interaction using a codemode architecture — the AI writes TypeScript code that executes against an injected anki API.
Why Codemode?
This server implements the codemode pattern pioneered by Cloudflare: instead of exposing dozens of discrete MCP tools, we provide a TypeScript API that the AI writes code against.
"LLMs are better at writing code to call APIs than at calling tools directly"
LLMs have been trained on billions of lines of real code, but relatively few synthetic tool-calling examples. Writing await anki.notes.add({...}) is natural — it's just TypeScript.
| Traditional | Codemode |
|---|---|
| 40+ discrete tools | 4 scoped tools |
| Fixed parameters | Full TypeScript flexibility |
| One operation per call | Compose multiple operations |
| Tool explosion as features grow | API grows, tools stay stable |
Benefits:
- Composable — Chain operations without round-trips through the LLM
- Efficient — Results flow through code, not back through the model for each step
- Familiar — Standard patterns the AI already knows from training data
Tools Overview
| Tool | Purpose | Key APIs |
|---|---|---|
anki-create |
Add new content | decks.create, notes.add, notes.addMany |
anki-manage |
Work with existing | notes.find, notes.update, notes.delete, cards.*, tags.* |
anki-review |
Study sessions | gui.*, sync, prompts.reviewSession |
anki-design |
Customize templates | models.create, models.styling, media.*, stats.* |
Prerequisites
- Anki desktop app (must be running)
- AnkiConnect plugin installed in Anki
- Bun runtime
Installation
git clone https://github.com/youruser/anki-mcp-codemode
cd anki-mcp-codemode
bun install
Claude Desktop / MCP Clients
Add to your MCP configuration:
{
"mcpServers": {
"anki": {
"command": "bun",
"args": ["run", "/absolute/path/to/anki-mcp-codemode/src/index.ts"],
"env": {
"ANKI_CONNECT_URL": "http://localhost:8765"
}
}
}
}
Configuration
| Variable | Default | Description |
|---|---|---|
ANKI_TOOLS |
all |
Tools to enable: all or comma-separated (create,manage) |
ANKI_CONNECT_URL |
http://localhost:8765 |
AnkiConnect URL |
ANKI_CONNECT_API_KEY |
— | API key (if configured in AnkiConnect) |
ANKI_CONNECT_TIMEOUT |
10000 |
Request timeout in ms |
MCP_TRANSPORT |
stdio |
stdio or http (Streamable HTTP) |
MCP_HTTP_PORT |
8766 |
Port for HTTP transport |
MCP_HTTP_HOST |
127.0.0.1 |
Bind address; non-localhost requires MCP_HTTP_TOKEN |
MCP_HTTP_TOKEN |
— | Static bearer token required on every HTTP request |
Remote Usage (HTTP Transport)
Run the server over Streamable HTTP instead of stdio:
MCP_TRANSPORT=http MCP_HTTP_TOKEN=your-secret bun run src/index.ts
# → http://127.0.0.1:8766/mcp (health check at /health)
Connect from Claude Code:
claude mcp add --transport http anki http://your-host:8766/mcp \
--header "Authorization: Bearer your-secret"
Notes for remote deployment:
- The server needs a reachable AnkiConnect, which means a running Anki. On a
headless VPS, run Anki Desktop with
QT_QPA_PLATFORM=offscreenand the AnkiConnect addon bound to a reachable address (community Docker images:ankimcp/headless-anki,ThisIsntTheWay/headless-anki). - The HTTP transport runs stateless (fresh session per request, JSON responses), which suits a single-user server behind a VPN/Tailscale.
- Executed code runs in-process with no sandbox — treat the bearer token as full control over the machine, not just the Anki collection, and keep the port off the public internet.
Selective Tool Loading
Only enable the tools you need:
{
"env": {
"ANKI_TOOLS": "create,review"
}
}
Usage Examples
Creating Cards
// List available decks and models
const decks = await anki.decks.list();
const models = await anki.models.list();
console.log({ decks, models });
// Create a deck and add cards
await anki.decks.create("Spanish Vocabulary");
const noteId = await anki.notes.add({
deckName: "Spanish Vocabulary",
modelName: "Basic",
fields: { Front: "Hola", Back: "Hello" },
tags: ["greeting", "beginner"]
});
console.log({ created: noteId });
Batch Operations
// Add multiple cards efficiently
const vocab = [
{ front: "perro", back: "dog" },
{ front: "gato", back: "cat" },
{ front: "pájaro", back: "bird" },
];
const noteIds = await anki.notes.addMany(
vocab.map(v => ({
deckName: "Spanish Vocabulary",
modelName: "Basic",
fields: { Front: v.front, Back: v.back }
}))
);
// null marks a note AnkiConnect refused, usually a duplicate
console.log({ added: noteIds.filter(id => id !== null).length });
Study Session Prompts
// Get the twenty rules prompt for effective card creation
const rules = anki.prompts.twentyRules();
console.log(rules);
API Reference
See docs/API.md for the complete API documentation for each tool.
Development
bun install # Install dependencies
bun run src/index.ts # Run server
bun test # Run tests
bunx tsc --noEmit # Type check
How It Works
- MCP client sends TypeScript code to one of the 4 tools
- Server executes the code with an injected
ankiobject (in-process — trusted-client model, not a security sandbox) - The
ankiobject provides type-safe methods that call AnkiConnect console.log()output is captured and returned to the AI
┌─────────────┐ TypeScript ┌─────────────┐ HTTP ┌─────────────┐
│ AI Agent │ ──── code ────────▶ │ MCP Server │ ────────────▶ │ AnkiConnect │
│ (Claude) │ ◀─── console.log ── │ (Bun) │ ◀──────────── │ (Anki) │
└─────────────┘ └─────────────┘ └─────────────┘
Attribution
This project was inspired by and builds upon concepts from @anthropics/anki-mcp-server (formerly anki-mcp-http). While the implementation is a complete rewrite using a different architecture (Bun + codemode vs NestJS + discrete tools), credit goes to the original authors for pioneering Anki + MCP integration.
License
MIT — Use freely, attribution appreciated.
Third-Party Notices
- Anki® is a registered trademark of Ankitects Pty Ltd. This is an unofficial third-party tool.
- Model Context Protocol (MCP) is an open standard by Anthropic.