AnkiMCP Server について
Anki 内部でローカル MCP サーバーを動作させるアドオンで、Claude などの AI アシスタントから暗記カードのコレクションを読み取り・編集できます。AI を使った学習やカード管理を行いたいユーザー向けです。
主な機能
- 01既定で 127.0.0.1:3141 で動作するローカル HTTP サーバー
- 02公開 HTTPS トンネルによるリモートアクセス
- 03DNS リバインディング対策としての Host / Origin ヘッダー検証
- 04任意で設定できる Bearer トークン認証
- 05カード統計やフィールド操作のツール(破壊的操作は既定で非表示)
活用シーン
- 01学習中に AI アシスタントでカードを作成・整理する
- 02トンネル経由で別の端末からローカルの Anki コレクションにアクセスする
- 03デッキ内カードのスケジュール統計を一括で取得する
MCP 対応
MCP サーバーとして、Anki のコレクション関連ツールを MCP クライアント(Claude Desktop、Claude Code など)に提供します。接続はローカル HTTP またはトンネル経由です。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
このサーバーのパッケージやリモートエンドポイントはまだ取得できていません。プロジェクトの README の手順に従ってください。
ツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
AnkiMCP Server(アドオン)
Model Context Protocolを通じて、AnkiとAIアシスタントをシームレスに連携します
AnkiMCP Serverは、Model Context Protocol (MCP)を介してコレクションをAIアシスタントに公開するAnkiアドオンです。
これは何ですか?
AnkiMCP ServerはAnki内でローカルMCPサーバーを実行し、ClaudeなどのAIアシスタントがフラッシュカードコレクションを操作できるようにします。これにより、AIを活用した学習セッション、カードの作成、コレクションの管理が可能になります。
ankimcp.aiプロジェクトの一部です。
初回起動時の注意
初回起動時に、このアドオンはPyPIからpydantic_core(約2MB)をダウンロードします。pydantic_coreにはプラットフォーム固有のバイナリ(Windows/macOS/Linux)が含まれており、単一のアドオンファイルにまとめられないため、これが必要です。
2つ目のネイティブ依存関係であるrpds(rpds-py由来)も同様に処理されます。ただし、ダウンロードが発生することはほとんどありません。Ankiには独自のjsonschemaの推移的依存関係としてすでにrpdsが含まれているため、アドオンはそれをインポートするだけです。ダウンロードが行われるのは、そのインポートに失敗するまれなインストール環境に限られます。どちらのダウンロードもAnki独自のデータフォルダー(アドオンのフォルダー外にあるため、すべてのOSでアドオンの更新後も問題なく保持されます)にキャッシュされます。その場所を利用できない場合は、アドオンの_cache/ディレクトリに保存されるため、いずれの場合も毎回の起動時ではなく一度だけダウンロードされます。古いフォルダー内のフォールバックキャッシュが削除されるのは、フォルダー外のキャッシュが正常に利用できること(そこからの読み込みに成功すること)が確認された後だけです。また、ネイティブモジュールがそこから読み込まれている間は、決して変更されません。初回の試行に失敗した場合(オフラインなど)、古いキャッシュが破棄されずにそのまま残ります。
機能
- ローカル HTTP サーバー - デフォルトで
http://127.0.0.1:3141/で実行されます - リモートトンネル - 公開 HTTPS URL を使って、どこからでもコレクションにアクセスできます
- MCP プロトコル - 任意の MCP クライアント(Claude Desktop など)と互換性があります
- 自動起動 - Anki を開くと HTTP サーバーが自動的に起動します
- トンネル対応 - Cloudflare Tunnel、ngrok、または組み込みトンネルで動作します(この方法で HTTP サーバーを公開するには、許可するホスト/オリジンの拡張も必要です)
- DNS リバインディング保護 - HTTP サーバーはデフォルトで、
Host/Originヘッダーをループバック許可リストと照合します。トンネル/リバースプロキシ経由で公開する場合は、許可リストを拡張してください - オプションの API キー -
http_api_keyを使って HTTP トランスポートでAuthorization: Bearerトークンを必須にできます(AnkiConnect 方式。空の場合は無効) - ツールバーインジケーター - 上部ツールバーの
● AnkiMCP項目で、トンネルの接続状態をひと目で確認できます(show_toolbar_indicatorで無効化できます) - 診断ログ - オプトインの
log_to_fileは、ローテーションされる機密情報を伏せたログをuser_files/ankimcp.logに書き込みます。設定には ログフォルダーを開く/診断情報をコピー ボタンがあります - フィールド管理 -
model_field_*ツールでノートタイプのフィールドを追加、名前変更、並べ替えできます(破壊的操作を伴うmodel_field_removeはオプトインが必要です) - カードの一括統計 - 読み取り専用の
cards_statsツールは、サブデッキを含むデッキ全体について、カードごとのコンパクトなスケジューリング指標(タイプ/キュー/間隔/タグ/dueToday)を返します。FSRS に依存しない、分析向けの軽量な一括読み取り機能です - GUI レビューセッション - Anki 独自のレビューウィンドウで、ハンズフリーのレビューができます。
gui_deck_reviewでデッキを開き、gui_answer_cardで回答ボタンを押します。オプトインが必要で、enabled_opt_in_toolsに名前を指定するまで非表示です - MCP ツールのアノテーション - すべてのツールは
title、readOnlyHint、destructiveHint、openWorldHintを宣言します(安全に繰り返せる書き込みツールではidempotentHintも宣言します)。これにより、クライアントは読みやすい名前を表示し、データを変更する呼び出しの前に確認を求められます - クロスプラットフォーム - macOS、Windows、Linux(x64 および ARM)で動作します
インストール
AnkiWeb から(推奨)
- Anki を開き、ツール → アドオン → アドオンを取得... を選択します
- コードを入力します:
124672614 - Anki を再起動します
GitHub Releases から
- Releases から
anki_mcp_server.ankiaddonをダウンロードします - ダブルクリックしてインストールするか、ツール → アドオン → ファイルからインストール... を選択します
- Anki を再起動します
NixOS
flakes を使う場合(推奨)
flake の入力を追加し、ビルド済みパッケージを使用します:
# flake.nix
{
inputs.anki-mcp.url = "github:ankimcp/anki-mcp-server-addon";
outputs = { nixpkgs, anki-mcp, ... }: {
# Option A: Standalone — Anki with the addon pre-installed
environment.systemPackages = [
anki-mcp.packages.${system}.default
];
# Option B: Composable with other addons via overlay
nixpkgs.overlays = [ anki-mcp.overlays.default ];
environment.systemPackages = [
(pkgs.anki.withAddons [ pkgs.ankiAddons.anki-mcp-server ])
];
};
}
flakes を使わない場合
# configuration.nix
{ pkgs, ... }:
let
python3 = pkgs.python3;
ankiMcpPythonDeps = python3.withPackages (ps: with ps; [
mcp pydantic pydantic-settings starlette uvicorn anyio httpx websockets
]);
anki-mcp-server = pkgs.anki-utils.buildAnkiAddon (finalAttrs: {
pname = "anki-mcp-server";
version = "0.20.0";
src = pkgs.fetchFromGitHub {
owner = "ankimcp";
repo = "anki-mcp-server-addon";
rev = "v${finalAttrs.version}";
hash = ""; # nix will tell you the correct hash on first build
};
sourceRoot = "${finalAttrs.src.name}/anki_mcp_server";
});
ankiWithMcp = pkgs.anki.withAddons [ anki-mcp-server ];
ankiWrapped = pkgs.symlinkJoin {
name = "anki-with-mcp";
paths = [ ankiWithMcp ];
nativeBuildInputs = [ pkgs.makeWrapper ];
postBuild = ''
wrapProgram $out/bin/anki \
--prefix PYTHONPATH ':' "${ankiMcpPythonDeps}/${python3.sitePackages}"
'';
};
in
{
environment.systemPackages = [ ankiWrapped ];
}
使用方法
Anki を開くとサーバーが自動的に起動します。ツール → AnkiMCP サーバー設定... で状態を確認できます
Claude Desktop に接続する
Node.js のインストールが必要です。Claude Desktop の設定(macOS の場合は ~/Library/Application Support/Claude/claude_desktop_config.json)に追加します:
{
"mcpServers": {
"anki": {
"command": "npx",
"args": ["mcp-remote", "http://127.0.0.1:3141"]
}
}
}
注: Claude Desktop は JSON 設定で HTTP サーバーをネイティブにサポートしていません。
mcp-remoteが stdio 経由で接続を中継します。
Claude Code に接続する
claude mcp add anki --transport http http://127.0.0.1:3141/
Opencode
opencode mcp add anki --url http://127.0.0.1:3141/
トンネル(リモートアクセス)
組み込みのトンネルを使うと、Anki コレクションに公開 HTTPS URL が割り当てられ、AI アシスタントがどこからでもアクセスできるようになります。ポートフォワーディングやリバースプロキシは必要ありません。コレクションは WebSocket トンネルサーバー(デフォルトは wss://tunnel.ankimcp.ai)を経由して中継されます。ログインには ankimcp.ai のアカウントが必要です。
接続方法:
- ツール -> AnkiMCP Server Settings... を開きます
- Connect Tunnel をクリックします
- ログインしていない場合はログインダイアログが表示されます。ワンタイムコードが表示されるので、Open Browser をクリックして、認証 URL でそのコードを入力します(OAuth 2.0 デバイスフロー)
- 接続されると、公開トンネル URL が表示されます(例:
https://tunnel.ankimcp.ai/e3439277-9d1e-47a1-b961-d193a4590da0) - AI クライアントでは
http://127.0.0.1:3141の代わりに、この URL を使用します
Claude Desktop での使用方法:
Claude Desktop の設定で、localhost の URL をトンネル URL に置き換えます。
{
"mcpServers": {
"anki": {
"command": "npx",
"args": ["mcp-remote", "https://tunnel.ankimcp.ai/<your-tunnel-id>"]
}
}
}
Claude Code での使用方法:
claude mcp add anki --transport http https://tunnel.ankimcp.ai/<your-tunnel-id>
切断とログアウトの違い:
- 切断するとトンネル接続が閉じます。認証情報はディスクに保持されるため、次回の接続時は再ログインせずに再接続できます。
- ログアウトすると認証情報が削除されます。次回の接続時に、再びログインダイアログが表示されます。
トンネル設定フィールド(上級ユーザー/セルフホストユーザー向け):
tunnel_server_url— トンネル中継サーバーの WebSocket URL(デフォルト:wss://tunnel.ankimcp.ai)tunnel_client_id— OAuth クライアント識別子(デフォルト:ankimcp-cli)
認証情報はアドオン専用の user_files/credentials.json に保存されます(アドオンの更新後も保持されます)。AnkiMCP CLI とは共有されません。CLI は ~/.ankimcp/ に独自の認証情報を保持するため、アドオンと CLI にはそれぞれ個別にログインします。ディスク上の形式は両者で同一です。
設定
Anki の ツール → アドオン → AnkiMCP Server → Config から編集します。
{
"http_enabled": true,
"http_port": 3141,
"http_host": "127.0.0.1",
"http_path": "",
"http_allowed_hosts": [],
"http_allowed_origins": [],
"http_api_key": "",
"cors_origins": [],
"cors_expose_headers": ["mcp-protocol-version"],
"disabled_tools": [],
"enabled_destructive_tools": [],
"enabled_opt_in_tools": [],
"max_notes_per_batch": 100,
"tunnel_server_url": "wss://tunnel.ankimcp.ai",
"tunnel_client_id": "ankimcp-cli",
"media_import_dir": "",
"media_allowed_types": [],
"media_allowed_hosts": [],
"show_settings_menu_item": true,
"show_toolbar_indicator": true,
"show_sync_tooltip": true,
"log_to_file": false
}
HTTP サーバーの切り替え
http_enabled 設定は、ローカル HTTP サーバーを実行するかどうかを制御します。false に設定すると、HTTP サーバーは起動せず、トンネル経由の接続のみが利用可能になります。デフォルトは true です。
{
"http_enabled": false
}
トンネルのみを使用し、ローカル HTTP サーバーを待ち受け状態にしたくない場合に便利です。
ツールメニュー項目
Anki の ツール メニューには、デフォルトで AnkiMCP Server Settings… 項目が表示されます。show_settings_menu_item を false に設定すると非表示になります(Anki の再起動後に反映されます)。
{
"show_settings_menu_item": false
}
注:メニュー項目とツールバーインジケーターの両方を非表示にすると、アプリ内で設定ダイアログを開く方法がなくなります。引き続き ツール → アドオン → AnkiMCP Server → Config から設定を編集できます。
ツールバーのステータスインジケーター
Anki の上部ツールバーに常時表示される ● AnkiMCP 項目は、トンネルの接続状態を示します(グレー=オフ、アンバー=接続中、緑=接続済み)。クリックすると設定ダイアログが開きます。デフォルトで表示されます。show_toolbar_indicator を false に設定すると非表示になります(Anki の再起動後に反映されます)。
{
"show_toolbar_indicator": false
}
同期のツールチップ
AI クライアントが同期を開始すると、アドオンは同期の開始時と完了時に、Anki の UI に短時間のモーダルではないツールチップを表示します(例:AnkiMCP: syncing…、AnkiMCP: sync complete)。通常は表示されないバックグラウンド同期を知らせる唯一の視覚的な手がかりです。デフォルトで表示されます。show_sync_tooltip を false に設定すると表示されなくなります。
{
"show_sync_tooltip": false
}
診断ログのファイル出力
log_to_file を true に設定すると、user_files/ankimcp.log にローテーションログが書き込まれます(1ファイルあたり約 1 MB、バックアップ 3 個)。デフォルトではオフです。有効にすると、アドオンの起動時に診断スナップショット(アドオン/Anki/Qt/Python のバージョンに加え、pydantic、mcp、protobuf などの共有ライブラリの実際の出所)が記録されます。これはアドオン間の競合を診断するうえで重要なデータです。シークレット(http_api_key、OAuth トークン、Bearer トークン)は、ディスクに書き込まれる前にマスキングされます。
{
"log_to_file": true
}
設定ダイアログ(Tools → AnkiMCP Server Settings…)には、ログフォルダーを開くボタンと診断情報をコピーボタンがあります(同じスナップショットを、フォーラム投稿に貼り付けられる形式でコピーします)。変更は Anki の再起動後に反映されます。
ツールの無効化
AI クライアントのトークン使用量を減らすため、特定のツールを非表示にできます。
{
"disabled_tools": [
"sync",
"card_bury",
"card_unbury"
]
}
各項目にはツール名を指定します。無効化されたツールは MCP スキーマから完全に削除され、AI クライアントからは見えなくなります。ツール名に誤りがあると、コンソールに警告が表示されます。
0.40.0 へのアップグレード
0.40.0 では、複数のアクションを持つ 4 つのツールが、アクションごとに 1 つのツールへ分割されました。card_management → card_*、tag_management → tag_*、filtered_deck → filtered_deck_*、model_fields → model_field_*(利用可能なツールを参照)。古い設定項目も引き続き動作し、置き換え先を示す非推奨の警告が表示されます。
"card_management:bury"は"card_bury"とまったく同じように動作します(disabled_toolsおよび以下の両方の許可リストで有効です。"model_fields:remove"は引き続きmodel_field_removeを有効にします)。disabled_toolsに古い名前だけの"card_management"を指定すると、すべてのcard_*ツールが無効になります。enabled_destructive_tools/enabled_opt_in_toolsに古い名前だけを指定しても、従来どおり何も有効になりません。
"tool:action" 形式で受け付けられるのは、これらの古い名前だけです。それ以外の "tool:action" 項目は何にも一致せず、警告が表示されます。非推奨の警告は、新しい名前に切り替えるまで、プロファイルを開くたびに(サーバー起動後に)表示されます。警告によってサーバーの起動が遅れることはありません。
エイリアスが適用されるのは設定のみです。クライアント側では古いツールは削除されています。tools/list に card_management などは表示されず、新しいツールはフラットな引数を受け取ります(params ラッパーや action フィールドはありません)。AI クライアントでツールごとの承認を保存している場合、または古いツールを呼び出すスクリプトを使用している場合は、新しいツールを再承認し、呼び出しを更新してください。
破壊的なツール(オプトイン)
破壊的(高リスクな操作)に分類されるツールは、デフォルトではAI クライアントに非表示です。公開するには、enabled_destructive_tools の許可リストに追加します。
{
"enabled_destructive_tools": [
"change_note_type",
"model_field_remove"
]
}
- 各項目には、破壊的なツールの正確な名前を指定します。
disabled_toolsも引き続き適用されます。オプトインしたツールも無効化できます。- 何にも一致しない項目、または破壊的でないツールに一致する項目があると、コンソールに警告が表示されます。
これはサーバー側での適用です。オプトインするまでは、破壊的なツールは MCP スキーマに含まれないため、動作に問題のあるクライアントであっても呼び出すことはできません。現在提供されている破壊的なツールは、change_note_type(選択したすべてのノートのフィールド構成を書き換えます)と model_field_remove(そのノートタイプのすべてのノートから、フィールドとその内容を完全に削除します)です。
オプトインツール
一部のツールは、「破壊的」以外の理由(新機能や実験的な機能など)により、デフォルトではAI クライアントに非表示になっています。enabled_destructive_tools と同じ構文で、enabled_opt_in_tools の許可リストに追加すると公開できます。
{
"enabled_opt_in_tools": [
"gui_answer_card",
"gui_deck_review"
]
}
- 各項目には、オプトインツールの正確な名前を指定します。
disabled_toolsも引き続き適用されます。オプトインしたツールも無効化できます。- 何にも一致しない項目、またはオプトインツールでないものに一致する項目があると、コンソールに警告が表示されます。
現在提供されているオプトイン項目は、gui_deck_review と gui_answer_card です。GUI から操作できるハンズフリーの復習セッション用ツールです。
カスタムパス
http_path を設定すると、MCP エンドポイントをカスタムパスで公開できます。Anki をトンネル(Cloudflare、ngrok)経由で公開する際に、エンドポイントを完全に開放しないために便利です。
{
"http_path": "my-secret-path"
}
サーバーにはルートではなく、http://localhost:3141/my-secret-path/ からアクセスできるようになります。デフォルトの動作にする場合は空のままにしてください。
注: カスタムパスを設定するだけでは、HTTP サーバーをトンネルやリバースプロキシ経由で公開するには不十分です。
http_allowed_hosts/http_allowed_originsも設定する必要があります。設定しない場合、リクエストは拒否されます(ループバック以外のHostには421、ループバック以外のOriginには403)。詳しくは、許可するホストとオリジン(DNS リバインディング対策)をご覧ください。
セキュリティ
ローカル HTTP サーバーは、デフォルトではループバックの Host/Origin 値からのリクエストのみ受け付けるため、通常のローカル利用では設定は不要です。localhost のクライアントはそのまま動作します。以下のセクションでは、サーバーをマシンの外部に公開する場合に利用できるセキュリティ強化策(DNS リバインディング対策の許可リスト、任意の API キー、CORS、メディアのインポート検証)について説明します。
≤ 0.20.0 からアップグレードする場合: トンネルやリバースプロキシ経由でサーバーにアクセスする場合、または 0.0.0.0 にバインドしている場合、リクエストはループバック以外の Host とともに届くようになりました。このホストを許可リストに追加するまで、リクエストは 421 で拒否されます。詳しくは、許可するホストとオリジン(DNS リバインディング対策)をご覧ください。(ブラウザクライアントでは、Origin も許可リストに追加する必要があります。追加しない場合は 403 になります。)通常の localhost 環境には影響ありません。
許可するホストとオリジン(DNS リバインディング対策)
HTTP サーバーでは、MCP SDK 自体のデフォルト値をそのまま複製したループバックの許可リストを組み込み、DNS リバインディング対策を有効にしています。
- ホスト:
127.0.0.1:*、localhost:*、[::1]:* - オリジン:
http://127.0.0.1:*、http://localhost:*、http://[::1]:*
そのため、通常の localhost クライアントはそのまま動作します。これらのデフォルト値について、知っておくとよい点が 2 つあります。
:*パターンはポートを含むホスト(localhost:3141✓)に一致します。ポートのないHostヘッダーは一致しません。これは、サーバーがポート 80 で動作している場合にのみブラウザやクライアントから送信されます。そのため、デフォルト以外の"http_port": 80を設定する場合は、http_allowed_hostsに"localhost"/"127.0.0.1"を明示的に追加する必要があります。- デフォルトのオリジンは**
http://のみ**です。https://localhostのオリジンは対象外のため、http_allowed_originsに追加する必要があります。(Originヘッダーがないリクエストは、ブラウザ以外の MCP クライアントでは通常の状態であり、常に許可されます。)
HTTP サーバーをトンネルやリバースプロキシ(例:ngrok、Cloudflare)経由で公開すると、ループバック以外の Host を伴うリクエスト(421 で拒否)が届きます。また、ブラウザクライアントではループバック以外の Origin を伴うリクエスト(403 で拒否)も届きます。これらを許可するには、許可リストを拡張してください。
{
"http_allowed_hosts": ["myapp.ngrok.io", "myapp.ngrok.io:443"],
"http_allowed_origins": ["https://myapp.example"]
}
http_allowed_hosts— スキームを含まないHostヘッダーの値(例:"myapp.ngrok.io"、"myapp.ngrok.io:443")http_allowed_origins— スキームを含む完全なオリジン(例:"https://myapp.example")
どちらのリストも、組み込みのループバックのデフォルト値に追加されます(デフォルト値は置き換えられません)。他の http_* 設定と同様、変更を反映するには Anki の再起動が必要です。
avishaigo-commits により報告された DNS リバインディングの脆弱性。
API キー(任意の HTTP 認証)
http_api_key は、HTTP トランスポートの上に任意の共有シークレット認証レイヤー(AnkiConnect 方式)を追加します。デフォルトでは 空 で、このレイヤーは無効になり、デフォルトの動作が維持されます。空でない値を設定すると、すべての HTTP リクエストで、その値と一致する Authorization: Bearer <key> ヘッダーを送信する必要があります。一致しない場合、リクエストは 403 で拒否されます。
{
"http_api_key": "a-long-random-secret-key"
}
ヘッダーを送信するようにクライアントを設定してください。Claude Code の場合:
claude mcp add anki --transport http http://127.0.0.1:3141/ --header "Authorization: Bearer a-long-random-secret-key"
mcp-remote の場合(例:Claude Desktop):
{
"mcpServers": {
"anki": {
"command": "npx",
"args": [
"mcp-remote",
"http://127.0.0.1:3141",
"--header",
"Authorization: Bearer a-long-random-secret-key"
]
}
}
}
注意事項:
- HTTP 専用です。 このキーはローカルの HTTP トランスポートにのみ適用されます。トンネルでは独自に OAuth ログインを行うため、
http_api_keyの影響を受けません。 - 置き換えではなく、補完するものです。 DNS リバインディング保護(Allowed Hosts と Origins)と併用するものであり、これに取って代わるものではありません。両方のレイヤーがそれぞれ独立して適用されます。
- トンネルまたはリバースプロキシを介して HTTP サーバーを公開する場合は、
http_pathとhttp_allowed_hostsを組み合わせるのが自然です。シークレットパスでエンドポイントを隠し、許可リストでプロキシホストを許可し、API キーで各リクエストを認証します。 - 長くランダムなキー(16 文字以上)を使用してください。提示されたトークンの先頭と末尾の空白は削除されるため、前後に空白があるキーを設定しても一致しません。
- この設定を変更するには、他の
http_*設定と同様に Anki の再起動が必要です。
CORS 設定
Web ホスト型の MCP Inspector など、ブラウザベースの MCP クライアントを許可するには、許可するオリジンを追加します。
{
"cors_origins": ["https://inspector.example.com", "http://localhost:5173"]
}
すべてのオリジンを許可するには ["*"] を使用します(本番環境では推奨されません)。
注:
cors_originsで許可されたブラウザーオリジンは、http_allowed_originsにも追加する必要があります。CORS と DNS リバインディングの許可リストは別々のレイヤーです。CORS を設定していても、Originがループバック以外で、http_allowed_originsに含まれていない場合は、DNS リバインディング保護によって403で拒否されます。
cors_expose_headers 設定は、ブラウザーが読み取れるレスポンスヘッダーを制御します。デフォルト値(mcp-protocol-version)を設定すると、ブラウザーベースの MCP クライアントがプロトコルバージョンをネゴシエートできます。v0.16.0 以降、サーバーはステートレスモードで実行されるため、mcp-session-id は出力されず、公開する必要もありません。
メディアのセキュリティ
メディアのパストラバーサル脆弱性を責任を持って報告してくださった Hideaki Takahashi(Columbia University)に感謝します。
store_media_file ツールは、パストラバーサル攻撃と SSRF 攻撃を防ぐため、すべての入力を検証します。
- ファイルパス は MIME タイプの確認により、メディアファイル(画像、音声、動画)のみに制限されます
- URL は
http://またはhttps://を使用する必要があり、プライベートネットワークや内部ネットワークを指定できません - ファイル名 はサニタイズされ、パストラバーサル文字列が除去されます
設定による任意の強化:
{
"media_import_dir": "/Users/me/anki-media",
"media_allowed_types": ["application/pdf"],
"media_allowed_hosts": ["192.168.1.50", "my-nas.local"]
}
media_import_dir— ファイルパスからのインポートをこのディレクトリツリー内に制限します(空の場合は制限なし)media_allowed_types— 画像/音声/動画以外の MIME タイプを追加で許可しますmedia_allowed_hosts— プライベートネットワークのブロックを回避できる特定のホストを許可します
利用可能なツール
すべてのツールパラメーターには、MCP 入力スキーマ内に短いdescriptionが含まれています(0.29.0 以降)。そのため、スキーマを表示したりモデルに渡したりするクライアントは、試行錯誤せずに引数の形式を把握できます。ネストされたオブジェクト(例:tag_batch操作、filtered_deck_upsert検索語句)は Pydantic モデル上で説明され、$defsの下に表示されます。
すべてのツールには MCP アノテーションも含まれています(0.31.0 以降):人が読めるtitle、コレクションを変更しないツールの場合は true となるreadOnlyHint、読み取り専用ツールおよび元に戻せてデータが失われない書き込み(add_note、add_notes、create_deck、create_model、store_media_file、tag_add、card_bury、card_unbury、card_suspend、card_unsuspend、card_set_flag、card_change_deck、filtered_deck_empty、filtered_deck_rebuild)では false、それ以外のすべての書き込みツール(データを削除、上書き、または元に戻せない形で変更するツール、あるいは AnkiWeb との完全同期を強制するツール)では true となるdestructiveHint、同じ呼び出しを繰り返してもそれ以上の効果がない書き込みツールのみ true となるidempotentHint(0.32.0 以降。対象はcreate_deck、delete_notes、delete_media_file、set_fsrs_params、card_change_deck、card_bury、card_unbury、card_suspend、card_unsuspend、card_set_flag、すべてのtag_*書き込みツール、filtered_deck_empty、filtered_deck_delete、すべてのmodel_field_*書き込みツール。他のすべてのツールでは省略)、そして AnkiWeb と通信するsyncと URL を取得できるstore_media_fileのみ true となるopenWorldHintです。
0.27.x 以下からのアップグレード: get_due_cardsは、include_answer=trueを渡さない限りbackを返さなくなりました。また、frontは生のフィールドではなく、レンダリングされた質問の HTML になりました。このツールからbackを読み取るクライアントでは、このフラグが必要です。
必須ツール
| ツール | 説明 |
|---|---|
sync | コレクションを AnkiWeb と同期します(非同期ジョブ:sync() で同期を開始し、sync(job_id) でステータスを確認し、sync(job_id, resolve=...) でフル同期の競合を解決します) |
list_decks | コレクション内のすべてのデッキを一覧表示します |
create_deck | 新しいデッキを作成します |
find_notes | Anki の検索構文を使ってノートを検索します。include_first_field=true を指定すると noteLabels 配列({noteId, firstField, truncated, fullLength})が追加され、1 回の呼び出しでノートの検索とラベル付けができます |
notes_info | ノートの詳細情報を取得します。excerpt_chars を指定すると、すべてのフィールド値を指定した文字数に制限し、それぞれに truncated/fullLength のマークを付けます。多数のノートを手軽に調査できます |
add_note | デッキに新しいノートを追加します |
add_notes | 同じデッキとモデルを共有するノートを、max_notes_per_batch(既定値 100)件まで一括追加します。Anki のネイティブ一括 API を使用し、取り消しを一括処理します。一部成功に対応しており、個々の失敗がほかのノートに影響することはありません |
card_reposition | 新しいカードの学習順序を設定します(新しいカードのみが対象です) |
card_change_deck | 必要に応じてデッキを作成し、カードを別のデッキに移動します |
card_bury / card_unbury | カードを明日まで非表示にする/デッキ内で埋められているすべてのカードを元に戻します |
card_suspend / card_unsuspend | カードを無期限に復習対象から除外する/元に戻します |
card_set_flag | 色付きフラグ(0-7)を設定または削除します |
card_set_due_date | 日数 DSL(0、5、5-7、5!)を使ってカードの予定日を変更します |
card_forget | カードを新規状態にリセットします |
tag_add / tag_remove | ノートにタグを一括追加/削除します |
tag_replace | ノートのタグを別のタグに置き換えます |
tag_list | すべてのタグを一覧表示します。省略可能な deck パラメーターを指定すると、指定デッキ(サブデッキを含む)にカードがあるノートのタグのみを一覧表示します |
tag_clear_unused | 孤立したタグを削除します |
tag_batch | 複数のタグ追加/削除操作を 1 回の呼び出しで実行します。一部成功に対応しています |
filtered_deck_upsert | 1~2 個の検索語(Anki の上限)から、フィルターデッキを作成または変更します |
filtered_deck_rebuild | フィルターデッキにカードを再度取り込みます |
filtered_deck_empty | フィルターデッキのカードを元のデッキに戻します |
filtered_deck_delete | フィルターデッキのカードを元のデッキに戻してから、デッキを削除します |
filtered_deck_get_info | 1 回の呼び出しで最大 50 個のデッキ ID を読み取り専用で調査します。検索語、上限、順序、再スケジュールフラグ、カード数を返します。フィルターデッキ以外は is_filtered=false を返し、不明な ID はスキップされて not_found に件数が記録されます |
update_note_fields | 既存のノートのフィールドを更新します。全置換、または old_str/new_str によるパッチの 2 つのモードがあります(フィールド内の検索と置換です。完全に 1 回だけ一致する必要があり、そうでなければ何も書き込まれません) |
update_notes | 複数のノートのフィールドを、1 回の取り消し操作で一括更新します(バックエンド呼び出しは 1 回)。すべての項目を先に検証し、max_notes_per_batch 件までの一部成功に対応しています |
delete_notes | コレクションからノートを削除します |
get_due_cards | 次に復習する期限のカードを取得します(音声モードでは skip_images/skip_audio に対応します)。レンダリング済みの質問のみを返します。include_answer=true を指定しない限り、答えは省略されます |
cards_stats | デッキ(サブデッキを含む)のカードごとのスケジュール統計を一括取得します。タイプ、キュー、間隔、タグ、dueToday などが含まれ、ページ分割に対応しています。FSRS に依存せず、分析向けのコンパクトなデータを返します |
present_card | 復習用のカード内容を取得します |
rate_card | 復習後にカードを評価します(Again/Hard/Good/Easy) |
model_names | 利用可能なノートタイプを一覧表示します |
model_field_names | ノートタイプのフィールド名と説明を取得します |
model_styling | ノートタイプの CSS スタイルを取得します。include_latex=true を指定すると、LaTeX プリアンブル(latex_pre、latex_post、latex_svg)も返します |
update_model_styling | ノートタイプの CSS スタイルを更新します。全置換、または old_str/new_str によるパッチ(完全に 1 回だけ一致する必要があります)に対応しています。LaTeX プリアンブル(latex_pre/latex_post/latex_svg)も書き込めます |
model_templates | ノートタイプ内の各カードタイプについて、表面/裏面の HTML テンプレートを読み取ります |
update_model_templates | 表面/裏面のテンプレート HTML を更新します。全置換、または old_str/new_str によるパッチ(完全に 1 回だけ一致する必要があります)に対応しています。認識できないキー(大文字と小文字を区別)や不明なテンプレート名は事前に拒否し、すべての編集をアトミックに適用します。呼び出しに失敗した場合、モデルは変更されません |
model_field_add / model_field_rename / model_field_reposition | 既存のノートタイプのフィールドを管理します。追加(任意で 0 ベースのインデックスを指定)、名前変更(内容は保持されますが、カードテンプレートは自動更新されません)、並べ替えができます。追加と並べ替えはフィールドの順序番号を変更し、一方向のフル同期を強制します。名前変更のみの場合は強制されません。すべての結果には、書き込み後のコレクションの実際の状態(コレクション全体に適用され、状態が維持されます)を示す will_force_full_sync が含まれます |
model_field_remove | ノートタイプ内のすべてのノートから、フィールドとその内容を削除します。破壊的操作のため、enabled_destructive_tools で有効にしない限り表示されません。一方向のフル同期を強制します |
create_model | 新しいノートタイプを作成します |
change_note_type | 既存のノートを別のノートタイプに移動し、フィールド名に基づいてフィールドを対応付けます({old field: new field or null})。破壊的操作のため、enabled_destructive_tools で有効にしない限り表示されません。2 段階の手順です。dry_run=true で解決済みの計画(対応付け、削除されるフィールド、削除されるカード)を返し、同じ呼び出しを dry_run=false かつ confirm=true で実行すると適用されます。すべてのノートで移行元のノートタイプが同じである必要があります |
store_media_file | Base64、ファイルパス、または URL を使ってメディアファイル(画像/音声)を保存します。ファイルパスはメディアタイプの許可リストに照らして検証され、URL は SSRF 対策の検査を受けます |
get_media_files_names | パターンに一致するメディアファイルを一覧表示します |
delete_media_file | メディアファイルを Anki のゴミ箱に移動します(Check Media で復元できます) |
FSRS ツール
| ツール | 説明 |
|---|---|
get_fsrs_params | デッキプリセットの FSRS スケジューラーパラメーターを取得します |
set_fsrs_params | FSRS パラメーター(重み、希望保持率、最大間隔)を更新します |
get_card_memory_state | カードの FSRS 記憶状態(安定性、難易度、想起可能性)を取得します |
optimize_fsrs_params | Anki 内蔵のオプティマイザーを使用して FSRS パラメーターを最適化します |
GUI ツール
これらのツールは Anki のユーザーインターフェースを操作します。
| ツール | 説明 |
|---|---|
gui_browse | 検索クエリーを指定してカードブラウザーを開きます |
gui_add_cards | カード追加ダイアログを開きます |
gui_edit_note | 特定のノートのノートエディターを開きます |
gui_current_card | 現在表示されているカードの情報を取得します |
gui_show_question | 現在のカードの問題面を表示します |
gui_show_answer | 現在のカードの解答面を表示します |
gui_select_card | レビュアーで特定のカードを選択します |
gui_deck_browser | デッキブラウザーに移動します |
gui_undo | 直前の操作を元に戻します |
gui_deck_review | Anki 独自のレビュアーウィンドウでデッキを開きます。オプトイン — enabled_opt_in_tools でオプトインするまで非表示です |
gui_answer_card | レビュアーに表示されているカードの評価ボタンを押し、ハンズフリーで評価します。オプトイン — enabled_opt_in_tools でオプトインするまで非表示です |
gui_current_card は、デフォルトではノートの answer/fields を返さなくなりました。取得するには include_answer=true を渡してください。
リソース
| リソース | URI | 説明 |
|---|---|---|
system_info | anki://system-info | Anki のバージョン、プロファイル、スケジューラー情報 |
query_syntax | anki://query-syntax | Anki 検索クエリーの構文リファレンス |
schema | anki://schema | データモデルのドキュメント(エンティティ、フィールド、リレーションシップ) |
stats_today | anki://stats/today | 今日の学習統計 |
stats_forecast | anki://stats/forecast | 30 日間の復習予測 |
stats_collection | anki://stats/collection | コレクション全体の統計 |
fsrs_config | anki://fsrs/config | FSRS 設定の概要とパラメーター |
プロンプト
| プロンプト | 説明 |
|---|---|
review_session | ガイド付き復習セッションのワークフローです。引数:deck_name(デフォルトは Default)、card_limit(デフォルトは 20)、review_style — interactive、quick、voice、または gui |
twenty_rules | Piotr Woźniak 博士による Twenty Rules of Formulating Knowledge(SuperMemo)。アシスタント向けのカード作成ガイドです。引数はありません |
要件
- Anki 25.07 以降(Python 3.13 が付属)
- Anki 25.02 以前には Python 3.9 が付属しており、サポート対象外です — MCP SDK には Python 3.10 以降が必要です(#8)
アーキテクチャ
このアドオンは、2 つの独立したトランスポートを備えた MCP サーバーをバックグラウンドスレッドで実行します。ローカル HTTP(FastMCP + uvicorn)とリモートトンネル(メモリー内トランスポートを使用した WebSocket リレー)です。どちらも同じ FastMCP サーバーインスタンスを共有します。すべての Anki 操作は、AnkiConnect と同じ実績のあるパターンに従い、キューシステムを介してメインの Qt スレッドにブリッジされます。
詳細については、Anki アドオン開発ドキュメントをご覧ください。
開発
E2E テストの実行
E2E テストは、headless-anki を使用して Docker 内の実際の Anki インスタンスに対して実行されます。
# Install test dependencies
python -m venv .venv
source .venv/bin/activate
pip install -r requirements-dev.txt
# Build the addon
./package.sh
# Start Anki container
cd .docker && docker compose up -d && cd ..
# Run tests (waits for server automatically)
pytest tests/e2e/ -v
# Stop container
cd .docker && docker compose down
または、Makefile のショートカットを使用してください。
make e2e # Build, start container, run tests, stop
make e2e-up # Just start container
make e2e-test # Just run tests
make e2e-down # Just stop container
CI
E2E テストは、任意のブランチへのプッシュ時と main への PR 時に自動的に実行されます。.github/workflows/e2e.yml をご覧ください。
ライセンス
AGPL-3.0-or-later
リンク
- ankimcp.ai - プロジェクトのホームページ
- MCP Protocol - Model Context Protocol の仕様
- Anki アドオンドキュメント - Anki 公式アドオン開発ドキュメント
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。