A privacy-first, open-source Anki sync server with a first-class REST API and MCP server, enabling seamless LLM-to-Anki workflows. User deck data lives in their own cloud storage (Google Drive, Dropbox, etc.) — this service is stateless infrastructure that never holds user data.
Trademark note: "Anki" is a registered trademark of Ankitects Pty Ltd. This project is not affiliated with or endorsed by Ankitects.
The sync server is compiled locally from sync-platform-cloud/ via Dockerfile.sync.
It authenticates Anki clients against the shared SQLite database and resolves each user's
Google Drive backend. Google OAuth credentials are required.
Before running, register these callback URIs in your OAuth apps:
Google (Cloud Console → APIs & Services → Credentials):
{BETTER_AUTH_URL}/v1/auth/callback/google # sign-in callback
{FRONTEND_URL}/v1/me/storage/connect/google/callback # Google Drive callback
GitHub (optional — Settings → Developer settings → OAuth Apps):
{BETTER_AUTH_URL}/v1/auth/callback/github # sign-in callback
Set TRUSTED_ORIGINS in .env to your frontend URL(s) (comma-separated) so Better Auth accepts
requests from the web UI. Defaults to FRONTEND_URL if unset.
cp .env.example .env # fill in all credentials
docker compose up --buildFirst build:
docker compose up --buildcompiles the Rust sync server from source (~10–20 min on first run). Subsequent starts are instant once the image is cached.
If you're actively developing sync-platform-cloud/ or anki-cloud-sync, rebuild only the
sync image:
docker compose build anki-sync-server
docker compose upTo develop against a local checkout of anki-cloud-sync (instead of fetching git deps):
docker compose -f docker-compose.yml -f docker-compose.dev.yml up --builddocker-compose.dev.yml overrides anki-sync-server to build directly from ../anki-cloud-sync.
Once the stack is running, two endpoints are available:
| URL | Purpose |
|---|---|
http://localhost:3000/openapi.json |
OpenAPI 3.1 spec — import into Postman via Import → Link |
http://localhost:3000/docs |
Scalar interactive UI |
All data endpoints (/v1/decks/*, /v1/notes/*, /v1/cards/*) require an API key:
Authorization: Bearer ak_<your-key>
Generate a key in the web UI under Account → API Keys, or via POST /v1/me/api-keys.
Account management endpoints (/v1/me/*) use the session cookie set by Better Auth after Google or GitHub OAuth login. The auth handler is mounted at /v1/auth/*.
The MCP server lets any LLM (Claude Desktop, API clients) manage your decks and notes directly:
User: "Create flashcards from this discussion"
LLM: "<calls create_notes_bulk> → cards appear in Anki instantly"
Claude Desktop setup — add to ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"anki-cloud": {
"command": "bun",
"args": [
"run",
"/path/to/anki-cloud/mcp/src/index.ts"
],
"env": {
"API_URL": "http://localhost:3000",
"API_KEY": "ak_your_key_here"
}
}
}
}Generate an API key in the web UI under Account → API Keys, replace the path and key, then restart Claude Desktop.
Full setup guide, available tools, and Docker deployment: docs/mcp-integration.md
In Anki: Preferences → Syncing → Self-hosted sync server, set the URL to:
http://localhost:8080
In the web UI, go to Account → Sync Password to generate your Anki sync credentials (one-time setup). Use your account email and the generated password when Anki prompts for login.
Run the setup script to install all required tools (skips anything already present):
./scripts/setup.zsh| Tool | Purpose |
|---|---|
| Bun | TypeScript runtime for REST API, MCP server, web UI |
| Docker Desktop | Full stack via docker compose (install separately) |
Rust ≥ 1.80 + protoc |
Only needed to build anki-cloud-sync from source |
api/ and db/ share a Bun workspace — one install covers both:
bun installweb/ and e2e/ are standalone packages (not in the workspace) — install separately when
working on them:
cd web && bun install # account management UI
cd e2e && bun install # end-to-end tests# REST API (hot-reload)
bun run --hot api/src/index.ts
# Web UI (Vite dev server, http://localhost:5173)
cd web && bun run dev
# E2E tests (requires the full stack running)
cd e2e && bun testapi/ REST API — TypeScript / Hono on Bun (shared workspace with db/ and mcp/)
db/ Drizzle ORM + SQLite schema (@anki-cloud/db)
mcp/ MCP server — wraps REST API, 8 tools for LLM integration
web/ Account management UI (Vite + React) (standalone — cd web && bun install)
e2e/ End-to-end tests (standalone — cd e2e && bun install)
sync-platform-cloud/ Rust crate — CloudAuthProvider + CloudBackendResolver (sync server binary)
docs/ Architecture decisions (ADRs) + narrative docs
scripts/ Dev tooling (setup, SDK generation)
docker-compose.yml Full stack (builds sync server from Dockerfile.sync)
docker-compose.dev.yml Override: build sync server from ../anki-cloud-sync local checkout
Dockerfile.sync Multi-stage build for the Rust sync server binary
.sync-server-version Pinned anki-cloud-sync git tag used by Dockerfile.sync
The sync server traits and backends live in a separate repository:
github.com/danielpmichalski/anki-cloud-sync —
sync-platform-cloud/ implements the AuthProvider and BackendResolver traits against
the shared SQLite database.
Full self-hosting walkthrough (Google OAuth setup, Google Drive, Anki Desktop, Claude Desktop): docs/SELF_HOSTING.md
Full architecture and design decisions: CLAUDE.md
Releases are triggered by pushing a version tag. The workflow builds the API Docker image, pushes it to GHCR, and creates a GitHub Release with auto-generated notes.
git checkout main
git tag v2.0.0
git push origin v2.0.0The Rust sync server (Dockerfile.sync) is not published — self-hosters build it locally
via docker compose up --build.
Elastic License 2.0 (ELv2) — source-available, self-hosting permitted. See LICENSE.