Skip to main content
Glama
README.md
# Anki MCP Server

A headless MCP server for Anki flashcards with Google OAuth authentication, deployed on Fly.io.

## Features

- **Deck Management** — Create, list, and delete decks
- **Card Operations** — Add, update, query, suspend/unsuspend cards
- **Model/Note Types** — Manage note types, field configs, templates
- **Tag Operations** — Bulk add/remove tags
- **Media Files** — Store, retrieve, and delete media
- **AnkiWeb Sync** — Full collection + media sync
- **Import/Export** — Import and export `.apkg` packages
- **Review Stats** — Query due cards, intervals, scheduling info
- **Google OAuth** — Secure authentication with email allowlist

## Quick Start

### Prerequisites

- Python 3.10+
- An AnkiWeb account (for sync)
- Google OAuth credentials

### Install

```bash
cd anki-mcp
python -m venv .venv
source .venv/bin/activate
pip install -e .
```

### Configure Environment Variables

```bash
# Google OAuth (required)
export GOOGLE_CLIENT_ID="your-google-client-id.apps.googleusercontent.com"
export GOOGLE_CLIENT_SECRET="your-google-client-secret"

# Allowed users (comma-separated emails)
export ANKI_MCP_ALLOWED_EMAILS="user1@gmail.com,user2@gmail.com"

# AnkiWeb (optional, for sync)
export ANKIWEB_USERNAME="your@email.com"
export ANKIWEB_PASSWORD="your-password"

# Server config
export PORT=8000
export ANKI_MCP_BASE_URL="https://your-domain.com"
```

### Run

```bash
anki-mcp
```

The server starts on port 8000 with:
- **MCP endpoint** at `/mcp` (streamable-http transport)
- **Health check** at `/health`

## Authentication

The server uses Google OAuth via [FastMCP](https://gofastmcp.com/). Only users whose emails are listed in `ANKI_MCP_ALLOWED_EMAILS` can access the server.

### Google OAuth Setup

1. Create a Google Cloud project with an OAuth 2.0 Client ID
2. Add the redirect URI: `https://your-app.fly.dev/auth/callback`
3. Enable the Google+ API (for userinfo access)
4. Set the required scopes: `openid`, `email`

## Deploy to Fly.io

```bash
# Create the app (first time)
fly apps create anki-mcp

# Set secrets
fly secrets set GOOGLE_CLIENT_ID="..."
fly secrets set GOOGLE_CLIENT_SECRET="..."
fly secrets set ANKI_MCP_ALLOWED_EMAILS="zephell@gmail.com,my.buddy.assistant@gmail.com"
fly secrets set ANKIWEB_USERNAME="..."
fly secrets set ANKIWEB_PASSWORD="..."

# Deploy
fly deploy
```

## Available MCP Tools

| Category | Tools |
|----------|-------|
| **Decks** | `get_deck_names`, `get_deck_names_and_ids`, `create_deck`, `delete_decks`, `get_deck_config`, `change_deck` |
| **Models** | `get_model_names`, `get_model_field_names`, `get_model_templates`, `get_model_styling` |
| **Notes** | `add_note`, `find_notes`, `get_notes_info`, `update_note_fields`, `delete_notes`, `cards_to_notes` |
| **Cards** | `find_cards`, `get_cards_info`, `suspend_cards`, `unsuspend_cards`, `are_suspended`, `are_due`, `get_card_intervals` |
| **Tags** | `get_all_tags`, `add_tags`, `remove_tags` |
| **Media** | `get_media_dir_path`, `store_media_file`, `store_media_file_from_path`, `retrieve_media_file`, `delete_media_file` |
| **Sync** | `do_sync`, `do_sync_media`, `get_sync_status` |
| **Import/Export** | `import_package`, `export_package` |
| **Utility** | `get_api_version` |

## Architecture

```
MCP Client → /mcp (streamable-http) → Google OAuth → Anki Tools → Anki Collection
                                         ↓
                                   Email Allowlist
                                         ↓
                                   anki Python package → collection.anki2
```

## Development

```bash
# Run tests
source .venv/bin/activate
pytest

# Lint
ruff check src/ tests/
```

## License

MIT