Skip to main content

AnkiConnect Server

Python 3.12+ PyPI Docker FastAPI

Headless AnkiConnect-compatible REST API server with AnkiWeb sync support and MCP server integration.

❓ Problem & Solution

Problem: Traditional AnkiConnect requires the Anki desktop app running, works only on localhost, and can't be deployed to servers.

Solution: This headless server provides direct collection access without Anki desktop, supports remote deployment, and includes automatic AnkiWeb sync.

✨ Features

  • Server Deployment - Run on VPS, Raspberry Pi, or cloud without GUI
  • AI Integration - MCP server for AI assistant access to your cards
  • Full AnkiConnect API Compatibility - Version 6 API with all standard actions
  • Headless Operation - No Qt/GUI required, perfect for servers and containers
  • AnkiWeb Sync - Automatic synchronization with AnkiWeb (optional)
  • MCP Server - Model Context Protocol integration for AI assistants

📋 Table of Contents

⚙️ Configuration

Set environment variables before running the server:

Variable Required Default Description
ANKICONNECT_COLLECTION_PATH No temp path Path to your .anki2 collection file
ANKICONNECT_PORT No 8765 Server port
ANKICONNECT_BIND No 127.0.0.1 Bind address (use 0.0.0.0 for external access)
ANKICONNECT_ANKIWEB_USER No - AnkiWeb username (required for sync)
ANKICONNECT_ANKIWEB_PASS No - AnkiWeb password (required for sync)
ANKICONNECT_ANKIWEB_URL No - Custom sync server URL (optional)

Example .env File

# Required: Path to your Anki collection
ANKICONNECT_COLLECTION_PATH=/path/to/collection.anki2

# Optional: Server configuration
ANKICONNECT_PORT=8765
ANKICONNECT_BIND=127.0.0.1

# Optional: AnkiWeb sync credentials
ANKICONNECT_ANKIWEB_USER=your@email.com
ANKICONNECT_ANKIWEB_PASS=your_password

# Optional: Custom sync server
ANKICONNECT_ANKIWEB_URL=https://your-sync-server.com

🚀 Usage

Quick Start with uvx (No Installation)

# Run the API server
ANKICONNECT_COLLECTION_PATH=/path/to/collection.anki2 \
ANKICONNECT_ANKIWEB_USER=your@email.com \
ANKICONNECT_ANKIWEB_PASS=your_password \
uvx anki-connect-server api

# Run the MCP server
ANKICONNECT_COLLECTION_PATH=/path/to/collection.anki2 \
ANKICONNECT_ANKIWEB_USER=your@email.com \
ANKICONNECT_ANKIWEB_PASS=your_password \
uvx anki-connect-server mcp

📚 API Reference

The server exposes a single POST endpoint at /api that accepts AnkiConnect-style JSON requests.

Request Format

{
  "action": "actionName",
  "version": 6,
  "params": {
    "param1": "value1",
    "param2": "value2"
  }
}

Response Format

{
  "result": <action_result>,
  "error": null
}

On error:

{
  "result": null,
  "error": "Error message"
}

Examples

Get Deck Names

curl -X POST http://localhost:8765/api \
  -H "Content-Type: application/json" \
  -d '{"action": "deckNames", "version": 6}'

Create a Deck

curl -X POST http://localhost:8765/api \
  -H "Content-Type: application/json" \
  -d '{"action": "createDeck", "version": 6, "params": {"deck": "My New Deck"}}'

Add a Note

curl -X POST http://localhost:8765/api \
  -H "Content-Type: application/json" \
  -d '{
    "action": "addNote",
    "version": 6,
    "params": {
      "note": {
        "deckName": "Default",
        "modelName": "Basic",
        "fields": {
          "Front": "Hello",
          "Back": "World"
        },
        "tags": ["api"]
      }
    }
  }'

Store Media from a URL (no base64 needed)

storeMediaFile accepts base64 data, a url to download, or a server-side path. When several are given, data takes precedence over url, which takes precedence over path.

# Download audio from a dictionary on the server side (~100-byte request)
curl -X POST http://localhost:8765/api \
  -H "Content-Type: application/json" \
  -d '{
    "action": "storeMediaFile",
    "version": 6,
    "params": {
      "filename": "sky_us.ogg",
      "url": "https://commons.wikimedia.org/wiki/Special:FilePath/En-us-sky.ogg"
    }
  }'
# Copy a file already visible to the server (e.g. a mounted volume)
curl -X POST http://localhost:8765/api \
  -H "Content-Type: application/json" \
  -d '{
    "action": "storeMediaFile",
    "version": 6,
    "params": {"filename": "sky.mp3", "path": "/data/media-in/sky.mp3"}
  }'

Then reference the stored file in a note field with [sound:sky_us.ogg].

Sync with AnkiWeb

curl -X POST http://localhost:8765/api \
  -H "Content-Type: application/json" \
  -d '{"action": "sync", "version": 6}'

Batch Multiple Actions

curl -X POST http://localhost:8765/api \
  -H "Content-Type: application/json" \
  -d '{
    "action": "multi",
    "version": 6,
    "params": {
      "actions": [
        {"action": "deckNames", "params": {}},
        {"action": "modelNames", "params": {}}
      ]
    }
  }'

Supported Actions

Misc

  • version - Get API version
  • sync - Sync with AnkiWeb
  • syncStatus - Get sync status
  • syncMedia - Sync media only
  • multi - Execute multiple actions
  • importPackage - Import .apkg file
  • exportPackage - Export deck to .apkg

Decks

  • deckNames - Get all deck names
  • deckNamesAndIds - Get deck names with IDs
  • createDeck - Create a new deck
  • deleteDecks - Delete decks
  • changeDeck - Move cards to different deck
  • getDecks - Get decks for cards
  • getDeckConfig - Get deck configuration
  • saveDeckConfig - Save deck configuration
  • setDeckConfigId - Assign config to decks
  • cloneDeckConfigId - Clone deck config
  • removeDeckConfigId - Remove deck config

Models

  • modelNames - Get all model names
  • modelNamesAndIds - Get model names with IDs
  • modelFieldNames - Get field names for model
  • modelFieldsOnTemplates - Get fields used in templates
  • createModel - Create a new note model
  • modelTemplates - Get card templates
  • modelStyling - Get CSS styling
  • updateModelTemplates - Update templates
  • updateModelStyling - Update CSS

Notes

  • addNote - Add a single note
  • addNotes - Add multiple notes
  • canAddNotes - Check if notes can be added
  • updateNoteFields - Update note fields
  • findNotes - Search for notes
  • notesInfo - Get note details
  • deleteNotes - Delete notes
  • addTags - Add tags to notes
  • removeTags - Remove tags from notes
  • getTags - Get all tags

Cards

  • findCards - Search for cards
  • cardsToNotes - Get note IDs from card IDs
  • cardsInfo - Get card details
  • suspend - Suspend cards
  • unsuspend - Unsuspend cards
  • areSuspended - Check if cards are suspended
  • areDue - Check if cards are due
  • getIntervals - Get card intervals

Media

  • getMediaDirPath - Get media directory path
  • storeMediaFile - Store a media file (base64 data, url, or server-side path)
  • retrieveMediaFile - Retrieve a media file
  • deleteMediaFile - Delete a media file

🤖 MCP Server

The server includes a Model Context Protocol (MCP) integration for AI assistants.

Starting the MCP Server

ANKICONNECT_COLLECTION_PATH=/path/to/collection.anki2 \
ANKICONNECT_ANKIWEB_USER=your@email.com \
ANKICONNECT_ANKIWEB_PASS=your_password \
uvx anki-connect-server mcp

Transports: stdio vs http

The MCP server supports two transports via --transport:

Transport Flag Behavior
stdio (default) --transport stdio One process per client connection. The MCP client (e.g. Claude Desktop, Hermes) spawns a new process for each session.
http --transport http A single long-lived server holds the collection and serves all clients over HTTP.
# stdio (default)
uvx anki-connect-server mcp

# http
uvx anki-connect-server mcp --transport http

⚠️ Concurrent MCP processes and the "already open" error

The Anki collection is a single-writer SQLite database: only one process can hold the lock at a time. The default stdio transport spawns a new process per client connection, so if your MCP client (Hermes, Claude Desktop, etc.) starts a new process before the previous one has exited, you will see:

anki.errors.DBError: Anki already open, or media currently syncing.

This is a SQLite lock contention error, not a media-sync issue — despite what the message says.

Workarounds:

  1. Use HTTP transport (recommended for multi-client setups):

    uvx anki-connect-server mcp --transport http
    # Server runs on http://127.0.0.1:8765/mcp
    

    Configure your MCP client to connect to the HTTP endpoint instead of spawning a stdio process. Only one process holds the collection and serves all connections.

  2. Leave ANKICONNECT_COLLECTION_PATH unset. When not configured, each process gets a random temp collection (anki-connect-server-<random>.anki2), so concurrent processes don't contend for the same file. Note: each process will have its own empty collection — set the path explicitly if you need a shared collection.

  3. Ensure only one process is running. If you stick with stdio, make sure your MCP client kills the previous process before starting a new one.

Available MCP Tools

  • get_deck_names - Get all deck names
  • get_deck_names_and_ids - Get decks with IDs
  • create_deck - Create a new deck
  • delete_decks - Delete decks
  • get_model_names - Get all model names
  • get_model_field_names - Get fields for a model
  • create_model - Create a note model (fields + card templates)
  • model_add_field / model_remove_field / model_rename_field / model_reposition_field - Manage model fields
  • update_note_fields - Update fields of an existing note
  • add_note - Add a new note
  • find_notes - Search for notes
  • get_notes_info - Get note details
  • delete_notes - Delete notes
  • find_cards - Search for cards
  • get_cards_info - Get card details
  • suspend_cards / unsuspend_cards - Manage card suspension
  • are_suspended / are_due - Check card status
  • get_card_intervals - Get card intervals
  • get_all_tags - Get all tags
  • add_tags / remove_tags - Manage tags
  • get_media_dir_path - Get media directory
  • store_media_file / retrieve_media_file / delete_media_file - Media operations (store_media_file accepts base64 data, url, or server-side path)
  • change_deck - Move cards between decks
  • cards_to_notes - Convert card IDs to note IDs
  • get_deck_config - Get deck configuration
  • get_model_templates / get_model_styling - Model customization
  • update_model_templates / update_model_styling - Edit model templates/CSS
  • get_api_version - Get API version
  • import_package / export_package - Import/export decks
  • sync / sync_media / get_sync_status - Sync operations

Adding to Claude Desktop

Option A — stdio (default, one process per session):

Add to your claude_desktop_config.json:

{
  "mcpServers": {
    "anki-connect-server": {
      "command": "uvx",
      "args": ["anki-connect-server", "mcp"],
      "env": {
        "ANKICONNECT_COLLECTION_PATH": "/path/to/collection.anki2",
        "ANKICONNECT_ANKIWEB_USER": "your@email.com",
        "ANKICONNECT_ANKIWEB_PASS": "your_password"
      }
    }
  }
}

Option B — http (single long-lived server, avoids lock contention):

First start the HTTP server (e.g. as a systemd service or background process):

uvx anki-connect-server mcp --transport http

Then point your MCP client at http://127.0.0.1:8765/mcp.

🐳 Docker

Using Pre-built Image

docker run -d \
  -p 8765:8765 \
  -v /path/to/collection.anki2:/data/collection.anki2 \
  -e ANKICONNECT_COLLECTION_PATH=/data/collection.anki2 \
  -e ANKICONNECT_ANKIWEB_USER=your@email.com \
  -e ANKICONNECT_ANKIWEB_PASS=your_password \
  --name anki-connect-server \
  glechic/anki-connect-server:latest

Docker Compose

version: '3.8'

services:
  anki-connect-server:
    image: glechic/anki-connect-server:latest
    ports:
      - "8765:8765"
    volumes:
      - ./collection.anki2:/data/collection.anki2
    environment:
      - ANKICONNECT_COLLECTION_PATH=/data/collection.anki2
      - ANKICONNECT_ANKIWEB_USER=${ANKIWEB_USER}
      - ANKICONNECT_ANKIWEB_PASS=${ANKIWEB_PASS}
    restart: unless-stopped

Building from Source

docker build -t anki-connect-server .

Metadata

Release files for anki-connect-server 0.4.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for anki-connect-server 0.4.0
File Size Uploaded
anki_connect_server-0.4.0.tar.gz 44.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for anki-connect-server 0.4.0
File Interpreter ABI Platform
anki_connect_server-0.4.0-py3-none-any.whl Python 3 none any Details

Total release size: 71.6 kB

Release files / anki_connect_server-0.4.0.tar.gz

Download URL anki_connect_server-0.4.0.tar.gz
Size 44.4 kB
Tags Source
SHA-256 checksum
How to use checksums
e22734d870d119b0a2653ac3acdc132ecb2c46509ae1e2f39f6b0aeca53954eb
BLAKE2b-256 checksum
How to use checksums
5694040e1b855661ce0d8a295e9c06460b9aa0caa9adcf8d1995c01e3aa652c7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.7.3

Release files / anki_connect_server-0.4.0-py3-none-any.whl

Download URL anki_connect_server-0.4.0-py3-none-any.whl
Size 27.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d42c0fcd8bdc8e8da7f3a3ff543ff7bd013688e7358314e5dac933fb252127ce
BLAKE2b-256 checksum
How to use checksums
78048661035aecbe3976d9f0d24740f2b784a63a7c3ed99c9685b9e7860f2c97
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.7.3

Release history Release notifications | RSS feed

This release

0.4.0 This release

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page