# https://github.com/ankimcp/anki-mcp-server 项目说明书

生成时间：2026-05-31 19:46:39 UTC

## 目录

- [项目介绍](#page-introduction)
- [安装与配置](#page-installation)
- [系统架构](#page-architecture)
- [传输模式](#page-transport-modes)
- [核心工具参考](#page-tool-reference)
- [GUI 工具集](#page-gui-tools)
- [故障排除](#page-troubleshooting)
- [命令行参考](#page-cli-reference)
- [安全特性](#page-security)
- [开发指南](#page-development)

<a id='page-introduction'></a>

## 项目介绍

### 相关页面

相关主题：[安装与配置](#page-installation), [系统架构](#page-architecture)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [manifest.json](https://github.com/ankimcp/anki-mcp-server/blob/main/manifest.json)
- [package.json](https://github.com/ankimcp/anki-mcp-server/blob/main/package.json)
- [server.json](https://github.com/ankimcp/anki-mcp-server/blob/main/server.json)
- [src/mcp/types/anki.types.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/mcp/types/anki.types.ts)
- [src/mcp/config/anki-config.interface.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/mcp/config/anki-config.interface.ts)
- [CLAUDE.md](https://github.com/ankimcp/anki-mcp-server/blob/main/CLAUDE.md)
- [CHANGELOG.md](https://github.com/ankimcp/anki-mcp-server/blob/main/CHANGELOG.md)
- [src/mcp/utils/markdown.utils.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/mcp/utils/markdown.utils.ts)
</details>

# 项目介绍

## 概述

Anki MCP Server 是一个基于 Model Context Protocol (MCP) 的 Anki 间隔重复记忆应用服务端。该项目使 AI 助手能够与 Anki 进行自然语言交互，实现学习辅助、卡片管理、复习调度等功能。

资料来源：[manifest.json:3-6]()

## 核心功能

### 主要能力

| 功能类别 | 具体功能 |
|---------|---------|
| 复习管理 | 获取到期卡片、呈现卡片、评分卡片、同步 |
| 笔记操作 | 添加笔记、批量添加笔记、编辑笔记、删除笔记 |
| 模型管理 | 创建笔记类型、获取字段名称、获取样式、更新样式 |
| 牌组管理 | 获取牌组列表、管理牌组 |
| 媒体文件 | 存储媒体文件、获取媒体文件 |
| 统计信息 | 集合级统计、复习统计 |

资料来源：[manifest.json:25-48]()

### 技术架构

该项目采用 NestJS 框架构建，基于 MCP 协议实现与 AI 助手的通信，通过 AnkiConnect 插件与 Anki 桌面应用交互。

```mermaid
graph TD
    A[AI 助手] -->|MCP 协议| B[Anki MCP Server]
    B -->|HTTP API| C[AnkiConnect 插件]
    C --> D[Anki 桌面应用]
    
    B --> E[STDIO 传输]
    B --> F[Streamable HTTP 传输]
    B --> G[ngrok 隧道]
```

资料来源：[CLAUDE.md:1-20]()

## 项目结构

```
anki-mcp-server/
├── src/
│   ├── mcp/
│   │   ├── clients/          # AnkiConnect HTTP 客户端
│   │   ├── config/           # 配置接口
│   │   ├── types/            # TypeScript 类型定义
│   │   ├── utils/            # 工具函数
│   │   └── primitives/
│   │       ├── essential/    # 核心工具
│   │       └── gui/          # GUI 交互工具
│   └── main.ts               # 应用入口
├── bin/                      # CLI 入口脚本
├── dist/                     # 编译输出
├── package.json
└── server.json               # MCP 服务器配置
```

资料来源：[CLAUDE.md:1-15]()

## 模块系统

项目采用 NestJS 的模块化设计，通过依赖注入组织各个功能模块：

```mermaid
graph LR
    A[AppModule] --> B[McpModule]
    A --> C[McpPrimitivesAnkiEssentialModule]
    A --> D[McpPrimitivesAnkiGuiModule]
    
    B --> E[STDIO / HTTP 传输]
    C --> F[核心工具集]
    D --> G[GUI 交互工具]
```

### 核心模块

| 模块 | 职责 |
|-----|------|
| `McpModule` | MCP 协议传输层，支持 STDIO 和 Streamable HTTP |
| `McpPrimitivesAnkiEssentialModule` | 核心工具：复习、笔记、牌组管理等 |
| `McpPrimitivesAnkiGuiModule` | GUI 工具：浏览窗口、卡片选择等 |

资料来源：[CLAUDE.md:18-25]()

## 工具系统

### 工具定义模式

所有 MCP 工具遵循统一的实现模式：

```typescript
// 1. Zod schema 用于输入验证
// 2. @Injectable() 类注入 AnkiConnectClient
// 3. @Tool() 装饰器定义工具元数据
// 4. execute() 方法调用 ankiClient.invoke()
// 5. 成功返回匹配 outputSchema 的原始对象
// 6. 错误返回 createErrorResponse()
```

资料来源：[CLAUDE.md:42-52]()

### 工具注解

每个工具在 `@Tool` 装饰器中声明注解：

| 注解 | 说明 |
|-----|------|
| `readOnlyHint` | 标识是否为只读操作 |
| `destructiveHint` | 标识是否为破坏性操作 |
| `idempotentHint` | 标识是否为幂等操作 |

资料来源：[CLAUDE.md:54-55]()

## 配置选项

### IAnkiConfig 接口

| 配置项 | 类型 | 默认值 | 说明 |
|-------|------|-------|------|
| `ankiConnectUrl` | string | `'http://localhost:8765'` | AnkiConnect 服务地址 |
| `ankiConnectApiVersion` | number | `6` | API 版本 |
| `ankiConnectApiKey` | string | - | 认证密钥（可选） |
| `ankiConnectTimeout` | number | `5000` | 请求超时（毫秒） |
| `readOnly` | boolean | `false` | 只读模式，阻止所有写入操作 |

资料来源：[src/mcp/config/anki-config.interface.ts:5-30]()

### 只读模式

只读模式通过 `readOnly` 配置项启用，可阻止所有写入操作，防止意外修改 Anki 牌组。此功能响应社区需求（#18），为需要限制 MCP 服务器操作权限的用户提供解决方案。

资料来源：[src/mcp/config/anki-config.interface.ts:25-26]()

## 传输方式

### 支持的传输协议

| 传输方式 | 说明 | 使用场景 |
|---------|------|---------|
| STDIO | 标准输入输出 | Claude Desktop、本地 CLI |
| Streamable HTTP | HTTP 长连接 | 远程访问、Web 集成 |
| ngrok 隧道 | 公共 URL 访问 | 无公网 IP 的远程访问 |

资料来源：[CLAUDE.md:8-10]()

### 启动方式

```bash
# STDIO 模式（默认）
npx -y @ankimcp/anki-mcp-server --stdio

# HTTP 模式
npx -y @ankimcp/anki-mcp-server --http

# ngrok 隧道模式
npx -y @ankimcp/anki-mcp-server --ngrok
```

## 数据类型

### 核心类型定义

```typescript
interface AddNoteParams {
  deckName: string;           // 目标牌组
  modelName: string;         // 笔记类型（Basic、Cloze 等）
  fields: Record<string, string>;  // 字段键值对
  tags?: string[];           // 标签数组
  options?: NoteOptions;     // 重复检查选项
}

interface Model {
  name: string;              // 模型名称
  id: number;                // 唯一标识符
  css: string;               // CSS 样式
  fields: string[];          // 字段名称数组
}

interface NoteInfo {
  noteId: number;            // 笔记 ID
  modelName: string;          // 使用的模型
  tags: string[];             // 标签
  fields: Record<string, { value: string; order: number }>;
  cards: number[];            // 关联的卡片 ID
}
```

资料来源：[src/mcp/types/anki.types.ts:25-50]()

## 依赖项

### 核心依赖

| 依赖 | 版本 | 用途 |
|-----|------|-----|
| `@nestjs/core` | ^11.x | 核心框架 |
| `@modelcontextprotocol/sdk` | 1.29.0 | MCP 协议实现 |
| `ky` | ^1.14.3 | HTTP 客户端 |
| `zod` | ^4.x | 数据验证 |
| `pino` | ^10.x | 日志记录 |
| `commander` | ^14.x | CLI 解析 |

### 已知兼容性问题

**Node.js 版本要求**：项目需要 Node.js 20.19+ 或更高版本。由于 `ky` 是纯 ESM 包，不支持 Node.js 21.x（该版本未包含 `require(esm)` 功能）。

资料来源：[package.json:1-50]()

## 安全特性

### 媒体操作安全

v0.15.1 版本引入了多层安全验证：

- **路径遍历防护**：防止通过 `storeMediaFile` 路径参数读取任意文件
- **SSRF 防护**：防止通过 URL 参数发起服务端请求伪造攻击
- **MIME 类型白名单**：验证上传文件的实际类型

此安全加固由 [Hideaki Takahashi](https://github.com/Koukyosyumei) 报告并修复。

资料来源：[CHANGELOG.md:1-10]()

## 版本历史

| 版本 | 主要变更 |
|-----|---------|
| 0.18.x | 最新稳定版，支持隧道功能 |
| 0.15.x | 媒体安全加固 |
| 0.14.x | 批量添加笔记、牌组统计 |
| 0.8.x | 早期版本，存在 ESM 兼容性问题 |

资料来源：[CHANGELOG.md:1-25]()

## 快速开始

### 前置要求

1. 安装 Anki 桌面应用
2. 安装 AnkiConnect 插件（插件编号 2055492159）
3. 确保 Node.js >= 20.19

### 安装步骤

```bash
# 通过 npx 运行
npx -y @ankimcp/anki-mcp-server --stdio

# 或全局安装
npm install -g @ankimcp/anki-mcp-server
```

### Claude Desktop 配置

```json
{
  "mcpServers": {
    "anki": {
      "command": "npx",
      "args": ["-y", "@ankimcp/anki-mcp-server", "--stdio"]
    }
  }
}
```

## 社区反馈

### 高优先级功能请求

| Issue | 功能 | 状态 |
|-------|------|------|
| #22 | 创建卡片超时问题 | 建议使用 `addNotes` 批量操作 |
| #21 | 批量创建卡片性能 | `addNotes` 工具已可用 |
| #19 | changeDeck 和 reposition 工具 | 规划中 |
| #14 | 牌组和集合级统计 | 部分可用 |

资料来源：[社区上下文]()

## 相关资源

- 官网：https://ankimcp.ai
- 文档：https://github.com/ankimcp/anki-mcp-server#readme
- 问题反馈：https://github.com/ankimcp/anki-mcp-server/issues
- 隐私政策：https://ankimcp.ai/privacy/

资料来源：[manifest.json:10-15]()

---

<a id='page-installation'></a>

## 安装与配置

### 相关页面

相关主题：[项目介绍](#page-introduction), [命令行参考](#page-cli-reference), [故障排除](#page-troubleshooting)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [package.json](https://github.com/ankimcp/anki-mcp-server/blob/main/package.json)
- [manifest.json](https://github.com/ankimcp/anki-mcp-server/blob/main/manifest.json)
- [server.json](https://github.com/ankimcp/anki-mcp-server/blob/main/server.json)
- [CLAUDE.md](https://github.com/ankimcp/anki-mcp-server/blob/main/CLAUDE.md)
- [src/mcp/clients/anki-connect.client.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/mcp/clients/anki-connect.client.ts)
</details>

# 安装与配置

Anki MCP Server 是一个基于 Model Context Protocol (MCP) 的服务器，为 Anki 间隔重复记忆应用提供 AI 交互能力。本页面详细说明该服务器的安装前置条件、多种安装方式、配置选项以及各客户端集成方法。

## 系统要求

### 运行时环境

| 组件 | 最低版本要求 | 推荐版本 | 备注 |
|------|-------------|---------|------|
| Node.js | >=20.19.0 | 20.x LTS | **禁止使用 Node 21.x**，该版本存在 `ERR_REQUIRE_ESM` 兼容性问题 |
| npm | 最新稳定版 | 最新稳定版 | 用于全局安装或本地依赖管理 |
| Anki | 2.1.x | 2.1.50+ | 桌面版，必须安装 AnkiConnect 插件 |
| AnkiConnect | 最新版本 | 最新版本 | Anki 插件，版本号 6.0.0+ |

**重要提示**：Node.js 21.x 版本不支持 ESM 模块的 CommonJS 导入方式，会导致 `ky` 依赖库加载失败，产生 `ERR_REQUIRE_ESM` 错误。如果当前系统使用 Node 21.x，请降级至 Node 20.19+ 或升级至 Node 22+。资料来源：[package.json:dependencies]() 和 [issues/#17](https://github.com/ankimcp/anki-mcp-server/issues/17)

### AnkiConnect 插件安装

1. 启动 Anki 桌面应用
2. 进入 **Tools → Add-ons → Get Add-ons**
3. 在代码框中输入插件编号：`2055492159`
4. 点击 **OK** 安装插件
5. 重启 Anki 确保插件生效

插件安装后，AnkiConnect 默认监听 `http://127.0.0.1:8765` 端口。资料来源：[manifest.json](https://github.com/ankimcp/anki-mcp-server/blob/main/manifest.json)

## 安装方式

### 方式一：全局安装 (npm)

```bash
npm install -g @ankimcp/anki-mcp-server
```

安装完成后，使用以下命令启动：

```bash
# STDIO 模式（适用于 Claude Desktop 等 MCP 客户端）
anki-mcp --stdio

# HTTP 模式（适用于 Web 集成）
anki-mcp --http

# Ngrok 隧道模式（适用于远程访问）
anki-mcp --ngrok
```

资料来源：[package.json:bin](https://github.com/ankimcp/anki-mcp-server/blob/main/package.json)

### 方式二：npx 临时运行

无需预先安装，直接通过 npx 运行：

```bash
# STDIO 模式
npx -y @ankimcp/anki-mcp-server --stdio
```

**注意**：使用 npx 时，首次运行会临时下载并执行，可能存在网络延迟。资料来源：[issues/#16](https://github.com/ankimcp/anki-mcp-server/issues/16)

### 方式三：Docker 部署

对于需要隔离环境的用户，可通过 Docker 运行：

```dockerfile
FROM node:20-slim
RUN npm install -g @ankimcp/anki-mcp-server
CMD ["anki-mcp", "--stdio"]
```

运行容器时需将 AnkiConnect 端口映射到宿主机：

```bash
docker run -p 8765:8765 anki-mcp-container
```

## 传输模式

Anki MCP Server 支持三种传输模式，适用于不同的使用场景：

```mermaid
graph TD
    A[Anki MCP Server] --> B[STDIO 模式]
    A --> C[HTTP 模式]
    A --> D[Ngrok 隧道模式]
    
    B --> B1[Claude Desktop]
    B --> B2[Cursor]
    B --> B3[其他 MCP 客户端]
    
    C --> C1[Web 应用集成]
    C --> C2[自定义 HTTP 客户端]
    
    D --> D1[ngrok 隧道]
    D --> D2[远程访问]
    
    style B fill:#90EE90
    style C fill:#87CEEB
    style D fill:#FFB6C1
```

### STDIO 模式

标准输入/输出模式，适合本地 MCP 客户端集成，如 Claude Desktop、VS Code 等。

```bash
anki-mcp --stdio
```

配置文件示例 (`~/.claude/desktops/claude_desktop_config.json`)：

```json
{
  "mcpServers": {
    "anki": {
      "command": "npx",
      "args": ["-y", "@ankimcp/anki-mcp-server", "--stdio"],
      "env": {
        "ANKI_CONNECT_URL": "http://127.0.0.1:8765"
      }
    }
  }
}
```

资料来源：[server.json](https://github.com/ankimcp/anki-mcp-server/blob/main/server.json)

### HTTP 模式

HTTP 服务器模式，适合需要远程访问或 Web 集成的场景。

```bash
anki-mcp --http --port 8080
```

| 参数 | 默认值 | 说明 |
|------|-------|------|
| `--port` | 8080 | HTTP 服务监听端口 |
| `--host` | 127.0.0.1 | 绑定地址（建议仅本地使用） |

### Ngrok 隧道模式

通过 ngrok 创建公网可访问的隧道，适合需要远程访问 Anki 的场景。

```bash
anki-mcp --ngrok --api-key YOUR_NGROK_API_KEY
```

**前提条件**：
- 已安装 ngrok 并配置 API Key
- ngrok 版本 >= 3.0

**已知问题**：部分 ngrok 3.24.x 版本可能存在启动问题，如遇此情况可降级至 7.0 版本。资料来源：[issues/#9](https://github.com/ankimcp/anki-mcp-server/issues/9)

## 环境变量配置

| 环境变量 | 默认值 | 说明 |
|---------|-------|------|
| `ANKI_CONNECT_URL` | `http://127.0.0.1:8765` | AnkiConnect API 地址 |
| `ANKI_CONNECT_TIMEOUT` | `30000` | 请求超时时间（毫秒） |
| `ANKI_CONNECT_RETRIES` | `3` | 失败重试次数 |
| `DEBUG` | `false` | 启用调试日志输出 |

### AnkiConnect 连接配置

AnkiConnect 默认配置位于 Anki 插件设置中，主要参数：

| 参数 | 默认值 | 说明 |
|------|-------|------|
| API Key | 空 | 可选的安全认证密钥 |
| 允许来源 | `["127.0.0.1", "localhost"]` | CORS 允许的来源地址 |
| 最大并发请求 | 6 | 同时处理的最大请求数 |

## 客户端集成

### Claude Desktop 配置

在 Claude Desktop 配置文件中添加以下内容：

```json
{
  "mcpServers": {
    "anki": {
      "command": "npx",
      "args": ["-y", "@ankimcp/anki-mcp-server", "--stdio"],
      "env": {
        "ANKI_CONNECT_URL": "http://127.0.0.1:8765",
        "ANKI_CONNECT_TIMEOUT": "30000"
      }
    }
  }
}
```

配置文件位置：
- **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
- **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
- **Linux**: `~/.config/Claude/claude_desktop_config.json`

**已知问题**：某些 Claude Desktop 版本可能存在 MCP 服务器配置兼容性问题，如安装后无法启动，请确保使用最新版本的 Claude Desktop。资料来源：[issues/#10](https://github.com/ankimcp/anki-mcp-server/issues/10)

### VS Code MCP 扩展配置

使用 VS Code 的 MCP 扩展时，在 VS Code 设置中添加：

```json
{
  "mcpServers": {
    "anki": {
      "command": "npx",
      "args": ["-y", "@ankimcp/anki-mcp-server", "--stdio"]
    }
  }
}
```

### Cursor IDE 配置

在 Cursor 的 MCP 设置中配置：

```json
{
  "mcpServers": {
    "anki": {
      "command": "npx",
      "args": ["-y", "@ankimcp/anki-mcp-server", "--stdio"]
    }
  }
}
```

## 架构概览

```mermaid
graph LR
    A[MCP 客户端<br/>Claude/VS Code] --> B[Anki MCP Server]
    B --> C[AnkiConnect Client<br/>ky HTTP]
    C --> D[AnkiConnect API]
    D --> E[Anki 应用]
    
    B --> F[NestJS IoC 容器]
    F --> G[MCP Tools]
    F --> H[MCP Resources]
    F --> I[MCP Prompts]
    
    style C fill:#FFD700
    style E fill:#87CEEB
```

## 常见问题排查

### ERR_REQUIRE_ESM 错误

**症状**：启动时报 `Error [ERR_REQUIRE_ESM]: require() of ES Module` 错误

**原因**：Node.js 版本不兼容，当前使用 Node 21.x

**解决方案**：
```bash
# 检查 Node 版本
node --version

# 切换到 Node 20.x
nvm install 20
nvm use 20
```

资料来源：[issues/#12](https://github.com/ankimcp/anki-mcp-server/issues/12)

### AnkiConnect 连接超时

**症状**：创建卡片时频繁超时

**原因**：AnkiConnect 单线程 Qt 事件循环无法处理高并发请求

**解决方案**：
- 批量操作时使用 `addNotes` 而非多次 `addNote`
- 降低请求频率
- 确保 Anki 窗口未最小化或被遮挡

资料来源：[issues/#22](https://github.com/ankimcp/anki-mcp-server/issues/22)

### Ngrok 启动失败

**症状**：`failed to start ngrok` 错误

**解决方案**：
1. 确认 ngrok 已正确安装并配置 API Key
2. 尝试降级 ngrok 版本：`npx anki-mcp-http@0.7.0`

资料来源：[issues/#9](https://github.com/ankimcp/anki-mcp-server/issues/9)

## 安全注意事项

1. **网络隔离**：默认情况下，AnkiConnect 仅允许本地连接（127.0.0.1）
2. **API Key**：在公共网络环境下使用 HTTP 模式，建议配置 API Key
3. **媒体文件**：服务器包含媒体路径遍历和 SSRF 攻击防护机制
4. **只读模式**：生产环境中可考虑使用只读模式限制写操作

资料来源：[v0.15.1 release notes](https://github.com/ankimcp/anki-mcp-server/releases/tag/v0.15.1) 和 [issues/#18](https://github.com/ankimcp/anki-mcp-server/issues/18)

---

<a id='page-architecture'></a>

## 系统架构

### 相关页面

相关主题：[传输模式](#page-transport-modes), [核心工具参考](#page-tool-reference)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/app.module.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/app.module.ts)
- [src/bootstrap.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/bootstrap.ts)
- [src/mcp/clients/anki-connect.client.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/mcp/clients/anki-connect.client.ts)
- [src/anki-config.service.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/anki-config.service.ts)
- [src/mcp/config/anki-config.interface.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/mcp/config/anki-config.interface.ts)
- [src/mcp/types/anki.types.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/mcp/types/anki.types.ts)
- [src/mcp/utils/anki.utils.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/mcp/utils/anki.utils.ts)
- [src/mcp/primitives/essential/tools/get-tags.tool.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/mcp/primitives/essential/tools/get-tags.tool.ts)
- [package.json](https://github.com/ankimcp/anki-mcp-server/blob/main/package.json)
- [CLAUDE.md](https://github.com/ankimcp/anki-mcp-server/blob/main/CLAUDE.md)
</details>

# 系统架构

## 概述

anki-mcp-server 是一个基于 Model Context Protocol (MCP) 的 Anki 间隔重复闪卡应用服务器。它允许 AI 助手（如 Claude）与 Anki 进行自然语言交互，实现复习会话、卡组管理、笔记创建与编辑等功能。

核心架构采用 **NestJS** 框架构建，通过 **AnkiConnect** 插件与 Anki 桌面应用通信，支持 STDIO 和 HTTP 两种传输模式。

## 技术栈

| 层级 | 技术/框架 | 版本要求 |
|------|----------|---------|
| 运行时 | Node.js | ≥20.19.0（明确排除 21.x） |
| 框架 | NestJS | ^11.x |
| MCP 协议 | @modelcontextprotocol/sdk | 精确版本 1.29.0 |
| HTTP 客户端 | ky | ^1.14.3（ESM 专有） |
| 数据验证 | Zod | ^4.3.6（非 v3） |
| 日志 | pino | ^10.3.1 |

> **注意**：Node 21.x 不被支持，因为 `require(esm)` 功能在 Node 21 中不存在（该功能在 Node 22 和 Node 20.17+ 中才被引入）。用户报告在 Node 21 环境下会遇到 `ERR_REQUIRE_ESM` 错误。资料来源：[package.json](https://github.com/ankimcp/anki-mcp-server/blob/main/package.json)

## 整体架构图

```mermaid
graph TB
    subgraph "MCP 客户端 (AI Agent)"
        A[Claude Desktop / VS Code / 其他 MCP 客户端]
    end

    subgraph "anki-mcp-server"
        B[入口层<br/>bootstrap.ts]
        C[传输层<br/>STDIO / HTTP]
        D[核心模块<br/>AppModule]
        E[MCP 协议层<br/>@rekog/mcp-nest]
        F[业务层<br/>Primitives Modules]
        G[通信层<br/>AnkiConnectClient]
    end

    subgraph "外部服务"
        H[AnkiConnect 插件]
        I[Anki 桌面应用]
    end

    A -->|MCP 协议| B
    B --> C
    C --> D
    D --> E
    E --> F
    F --> G
    G -->|HTTP| H
    H --> I
```

## 模块系统

### 核心模块结构

项目采用 NestJS 的模块化架构，核心模块包括：

```typescript
AppModule.forStdio()   // STDIO 传输模式
AppModule.forHttp()    // HTTP 传输模式
```

### 模块依赖关系

```mermaid
graph LR
    subgraph "传输层"
        A[STDIO 传输]
        B[HTTP 传输]
    end

    subgraph "核心层"
        C[McpModule]
        D[McpPrimitivesAnkiEssentialModule]
        E[McpPrimitivesAnkiGuiModule]
    end

    subgraph "工具层"
        F[Review 工具]
        G[Deck 工具]
        H[Note 工具]
        I[Media 工具]
        J[GUI 工具]
    end

    A --> C
    B --> C
    C --> D
    C --> E
    D --> F
    D --> G
    D --> H
    D --> I
    E --> J
```

### 工具分类

项目中的 MCP 工具分为两大类：

| 类别 | 模块 | 说明 | 权限级别 |
|-----|------|------|---------|
| Essential | `McpPrimitivesAnkiEssentialModule` | 核心复习、笔记操作 | 普通权限 |
| GUI | `McpPrimitivesAnkiGuiModule` | 需要用户确认的界面操作 | 需用户批准 |

Essential 工具包括：

- `sync` - 与 AnkiWeb 同步
- `get_due_cards` - 获取待复习卡片
- `get_cards` - 按状态获取卡片
- `present_card` - 展示卡片问题面
- `rate_card` - 评分卡片
- `addNote` / `addNotes` - 创建笔记
- `modelNames` / `modelFieldNames` - 获取笔记类型信息
- `getTags` - 获取所有标签
- `modelStyling` / `updateModelStyling` - 样式管理
- `createModel` - 创建笔记类型

GUI 工具包括：

- `guiBrowse` - 打开卡片浏览器
- `guiSelectCard` - 选择卡片
- `guiSelectedNotes` - 获取选中笔记

> 用户请求功能：工具权限控制（只读模式）是一个被关注的功能需求，详见 [Issue #18](https://github.com/ankimcp/anki-mcp-server/issues/18)

## 核心组件

### 1. AnkiConnectClient

`AnkiConnectClient` 是与 Anki 通信的核心 HTTP 客户端：

| 特性 | 说明 |
|-----|------|
| 协议 | HTTP POST |
| 默认地址 | http://127.0.0.1:8765 |
| 请求库 | ky（ESM） |
| 重试机制 | 内置重试逻辑 |
| 只读守卫 | 可配置的 read-only guard |

关键文件：[src/mcp/clients/anki-connect.client.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/mcp/clients/anki-connect.client.ts)

```typescript
// 核心调用模式
class AnkiConnectClient {
  invoke<T>(action: AnkiAction, params?: Record<string, unknown>): Promise<T>
  // 支持重试和错误处理
}
```

### 2. 配置系统

配置系统采用分层设计：

```mermaid
graph TB
    A[命令行参数 / 环境变量]
    B[AnkiConfigService]
    C[IAnkiConfig 接口]
    D[注入令牌 ANKI_CONFIG]
    
    A --> B
    B --> C
    C --> D
```

**IAnkiConfig 接口** 定义：

| 配置项 | 类型 | 说明 | 默认值 |
|-------|------|------|-------|
| `host` | string | AnkiConnect 主机地址 | 127.0.0.1 |
| `port` | number | AnkiConnect 端口 | 8765 |
| `readOnly` | boolean | 只读模式 | false |
| `retries` | number | 重试次数 | 3 |

关键文件：
- [src/anki-config.service.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/anki-config.service.ts)
- [src/mcp/config/anki-config.interface.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/mcp/config/anki-config.interface.ts)

### 3. 工具模式 (Tool Pattern)

所有 MCP 工具遵循统一的实现模式：

```mermaid
graph LR
    A[Zod 输入验证] --> B[Tool 装饰器]
    B --> C[execute 方法]
    C --> D[调用 AnkiConnectClient]
    D --> E[返回结果或错误]
```

**标准工具结构**：

```typescript
// 1. Zod schema 用于输入验证
// 2. @Injectable() 类注入 AnkiConnectClient
// 3. @Tool 装饰器定义元数据
// 4. execute() 方法执行业务逻辑
```

关键文件：[src/mcp/primitives/essential/tools/get-tags.tool.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/mcp/primitives/essential/tools/get-tags.tool.ts)

**工具响应格式**：

| 场景 | 返回方式 | 说明 |
|-----|---------|------|
| 成功路径 | 返回原始对象 | 匹配 `outputSchema`，handler 自动包装 |
| 错误路径 | `createErrorResponse()` | 返回 `isError: true`，绕过 schema 验证 |

### 4. 类型系统

核心类型定义位于 `anki.types.ts`：

| 类型 | 用途 |
|-----|------|
| `AddNoteParams` | 添加笔记参数 |
| `Model` | 笔记类型信息 |
| `NoteInfo` | 笔记详细信息 |
| `AnkiCard` | 卡片信息 |
| `CardRating` | 评分枚举 |

关键文件：[src/mcp/types/anki.types.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/mcp/types/anki.types.ts)

## 传输模式

### STDIO 模式

适用于命令行和桌面 AI 客户端（如 Claude Desktop）：

```bash
npx -y @ankimcp/anki-mcp-server --stdio
```

### HTTP 模式

支持远程访问和 ngrok 隧道：

```bash
# 本地 HTTP
npx -y @ankimcp/anki-mcp-server --http

# 带 ngrok 隧道
npx -y @ankimcp/anki-mcp-server --tunnel
```

> 注意：用户报告 ngrok 在某些版本下可能启动失败（[Issue #9](https://github.com/ankimcp/anki-mcp-server/issues/9)）

## 数据流

### 笔记创建流程

```mermaid
sequenceDiagram
    participant AI as AI Agent
    participant MCP as anki-mcp-server
    participant ACC as AnkiConnectClient
    participant AK as AnkiConnect
    participant AN as Anki

    AI->>MCP: addNote / addNotes
    MCP->>ACC: invoke("addNotes")
    ACC->>AK: HTTP POST
    AK->>AN: 创建笔记
    AN-->>AK: 响应
    AK-->>ACC: 结果
    ACC-->>MCP: 格式化响应
    MCP-->>AI: 成功/错误
```

> 批量操作：建议使用 `addNotes` 而非多个 `addNote` 调用，因为 AnkiConnect 基于 Qt 单线程事件循环，并行调用可能导致超时（[Issue #22](https://github.com/ankimcp/anki-mcp-server/issues/22)、[Issue #21](https://github.com/ankimcp/anki-mcp-server/issues/21)）

### 复习流程

```mermaid
graph LR
    A[获取待复习卡片] --> B[展示问题]
    B --> C[用户响应]
    C --> D{评分}
    D -->|Again| E[标记失败]
    D -->|Hard| F[标记困难]
    D -->|Good| G[标记成功]
    D -->|Easy| H[标记简单]
    E --> I[安排下次复习]
    F --> I
    G --> I
    H --> I
```

## 入口与引导

### bootstrap.ts

启动流程：

```typescript
// 1. 创建 NestJS 应用
// 2. 读取配置
// 3. 选择传输模式 (STDIO/HTTP)
// 4. 初始化 MCP 模块
// 5. 启动监听
```

关键文件：[src/bootstrap.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/bootstrap.ts)

### AppModule 结构

```typescript
@Module({
  imports: [
    // MCP 核心模块
    McpModule.forRoot(),           // STDIO 或 STREAMABLE_HTTP
    McpPrimitivesAnkiEssentialModule.forRoot(),
    McpPrimitivesAnkiGuiModule.forRoot(),
  ],
  providers: [
    // 显式声明的工具列表
    // ESSENTIAL_MCP_TOOLS
    // GUI_MCP_TOOLS
  ],
})
export class AppModule {}
```

> MCP-Nest 1.9.0+ 要求工具必须同时在 `AppModule.providers` 中声明。资料来源：[CLAUDE.md](https://github.com/ankimcp/anki-mcp-server/blob/main/CLAUDE.md)

## 安全机制

### 媒体操作安全

v0.15.1 版本引入了多层安全验证：

| 安全措施 | 说明 |
|---------|------|
| MIME 类型白名单 | 验证文件类型 |
| 路径遍历防护 | 防止通过路径参数读取任意文件 |
| SSRF 防护 | 防止通过 URL 参数发起请求 |

此修复由 [Hideaki Takahashi](https://github.com/Koukyosyumei) 报告，详见 [Release v0.15.1](https://github.com/ankimcp/anki-mcp-server/releases/tag/v0.15.1)

### 只读模式

可通过配置启用只读模式，限制所有写操作：

| 配置项 | 效果 |
|-------|------|
| `readOnly: true` | 禁止创建、修改、删除笔记 |

## AnkiConnect 已知特性

项目中记录了以下 AnkiConnect 上游行为：

| 行为 | 影响 |
|-----|------|
| `updateNoteFields` 在笔记打开时静默失败 | 请求返回 200 但字段未保存 |
| Model CSS 是按笔记类型的 | 使用 `modelStyling` 获取 |
| `sync` 需要桌面应用登录 AnkiWeb | 无 API 路径可认证 |
| `deleteNotes` 不可逆且级联删除 | 需显式 `confirmDeletion: true` |

资料来源：[CLAUDE.md](https://github.com/ankimcp/anki-mcp-server/blob/main/CLAUDE.md)

## 依赖关系

### 关键生产依赖

| 依赖 | 版本 | 用途 |
|-----|------|------|
| @nestjs/core | ^11.x | NestJS 框架核心 |
| @modelcontextprotocol/sdk | 1.29.0 | MCP 协议实现 |
| @rekog/mcp-nest | - | MCP-Nest 集成 |
| ky | ^1.14.3 | HTTP 客户端（ESM） |
| zod | ^4.3.6 | 数据验证 |
| pino | ^10.3.1 | 日志框架 |
| passport | ^0.7.0 | 认证中间件 |

### 开发依赖

| 依赖 | 用途 |
|-----|------|
| @anthropic-ai/mcpb | MCPB 配置 |
| @nestjs/cli | NestJS CLI |
| @nestjs/testing | 测试框架 |
| typescript | TypeScript 编译器 |

## 项目结构

```
anki-mcp-server/
├── src/
│   ├── app.module.ts           # 主应用模块
│   ├── bootstrap.ts            # 启动入口
│   ├── anki-config.service.ts  # 配置服务
│   └── mcp/
│       ├── clients/
│       │   └── anki-connect.client.ts  # AnkiConnect 通信客户端
│       ├── config/
│       │   └── anki-config.interface.ts # 配置接口
│       ├── types/
│       │   └── anki.types.ts   # 类型定义
│       ├── utils/
│       │   ├── anki.utils.ts   # 工具函数
│       │   └── markdown.utils.ts # Markdown 处理
│       └── primitives/
│           ├── essential/      # 核心工具
│           │   ├── tools/      # 工具实现
│           │   └── prompts/    # 提示词模板
│           └── gui/            # GUI 工具
├── package.json
└── tsconfig.json
```

## 版本信息

| 版本 | 说明 |
|-----|------|
| 当前版本 | 0.18.5 |
| 最新测试版本 | v0.18.5-tunnel.2 |
| 语义化版本 | 主版本 0（Beta 阶段） |

详见 [CHANGELOG.md](https://github.com/ankimcp/anki-mcp-server/blob/main/CHANGELOG.md)

---

<a id='page-transport-modes'></a>

## 传输模式

### 相关页面

相关主题：[系统架构](#page-architecture), [安装与配置](#page-installation), [命令行参考](#page-cli-reference)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/main-stdio.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/main-stdio.ts)
- [src/main-http.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/main-http.ts)
- [src/http/guards/origin-validation.guard.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/http/guards/origin-validation.guard.ts)
- [src/services/ngrok.service.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/services/ngrok.service.ts)
- [src/mcp/clients/anki-connect.client.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/mcp/clients/anki-connect.client.ts)
</details>

# 传输模式

Anki MCP Server 支持两种主要的传输模式，用于 MCP 客户端与服务器之间的通信。正确选择传输模式对于集成、部署和安全性都有重要影响。

## 概述

| 传输模式 | 用途 | 适用场景 | 安全级别 |
|---------|------|----------|----------|
| **STDIO** | 标准输入输出 | Claude Desktop、本地集成 | 高（本地通信） |
| **HTTP + Ngrok** | HTTP 远程访问 | 远程客户端、跨网络访问 | 中（需 Ngrok 配置） |

## STDIO 模式

STDIO（标准输入/输出）是 MCP 协议的默认传输方式，适用于本地进程间通信。

### 工作原理

```mermaid
graph LR
    A["MCP 客户端<br/>(Claude Desktop)"] -->|stdin| B["Anki MCP Server<br/>(子进程)"]
    B -->|stdout| A
    B --> C["AnkiConnect API<br/>(localhost:8765)"]
    C --> D["Anki 应用"]
```

### 启动命令

```bash
# 通过 npx 直接运行
npx -y @ankimcp/anki-mcp-server --stdio

# 或指定特定版本
npx -y @ankimcp/anki-mcp-server@latest --stdio
```

### 源码实现

**入口文件**：`src/main-stdio.ts`

STDIO 模式使用 NestJS 框架的模块系统初始化服务：

```typescript
// 伪代码示例
AppModule.forStdio()
  .then(() => bootstrap())
```

资料来源：[src/main-stdio.ts:1-50](https://github.com/ankimcp/anki-mcp-server/blob/main/src/main-stdio.ts)

### 配置方式

在 Claude Desktop 配置文件中添加 STDIO 传输：

```json
{
  "mcpServers": {
    "anki-mcp": {
      "command": "npx",
      "args": ["-y", "@ankimcp/anki-mcp-server", "--stdio"],
      "env": {
        "ANKI_HOST": "localhost",
        "ANKI_PORT": "8765"
      }
    }
  }
}
```

## HTTP 模式

HTTP 传输模式提供基于 HTTP 的远程访问能力，支持 MCP Streamable HTTP 规范。

### 工作原理

```mermaid
graph TD
    A["MCP 客户端"] -->|HTTPS| B["Ngrok Tunnel"]
    B -->|HTTP| C["Anki MCP Server"]
    C --> D["AnkiConnect API"]
    D --> E["Anki 应用"]
    
    F["本地客户端"] -->|HTTP| C
```

### 启动命令

```bash
# 基本 HTTP 模式
npx -y @ankimcp/anki-mcp-server --http

# 带 Ngrok 隧道的远程访问
npx -y @ankimcp/anki-mcp-server --http --ngrok

# 指定端口
npx -y @ankimcp/anki-mcp-server --http --port 8080

# 带认证令牌
npx -y @ankimcp/anki-mcp-server --http --auth-token <TOKEN>
```

### 源码实现

**入口文件**：`src/main-http.ts`

HTTP 模式使用 `AppModule.forHttp()` 初始化，提供完整的 HTTP 服务器支持：

```typescript
// 伪代码示例
AppModule.forHttp({
  port: 8080,
  ngrok: process.env.USE_NGROK === 'true',
  authToken: process.env.AUTH_TOKEN
})
```

资料来源：[src/main-http.ts:1-80](https://github.com/ankimcp/anki-mcp-server/blob/main/src/main-http.ts)

### HTTP 服务配置参数

| 参数 | 环境变量 | 默认值 | 说明 |
|------|----------|--------|------|
| 端口 | `PORT` | `8080` | HTTP 服务器监听端口 |
| Host | `HOST` | `0.0.0.0` | 绑定地址 |
| Ngrok | `USE_NGROK` | `false` | 是否启用 Ngrok 隧道 |
| 认证令牌 | `AUTH_TOKEN` | 无 | HTTP 认证令牌 |
| Anki 地址 | `ANKI_HOST` | `localhost` | AnkiConnect 服务地址 |
| Anki 端口 | `ANKI_PORT` | `8765` | AnkiConnect 服务端口 |

## Ngrok 隧道服务

Ngrok 提供安全的公共 URL 用于远程访问本地 MCP 服务器。

### 服务实现

```typescript
// 伪代码示例 - NgrokService
class NgrokService {
  async startTunnel(port: number): Promise<string> {
    // 1. 启动 ngrok 进程
    // 2. 轮询 ngrok API 获取公网 URL
    // 3. 返回 HTTPS 端点 URL
    return ngrokUrl;
  }
}
```

资料来源：[src/services/ngrok.service.ts:1-100](https://github.com/ankimcp/anki-mcp-server/blob/main/src/services/ngrok.service.ts)

### Ngrok 配置要求

1. **安装 Ngrok**：需要预先安装 ngrok CLI 工具
2. **认证**：配置 ngrok auth token（用于持久化隧道）
3. **版本注意**：推荐使用 ngrok 3.x 版本

### 已知问题

社区反馈 `#9` 指出 Ngrok 在某些版本上可能启动失败：

> "ngrok fails to start with latest version... I was able to work around this by using version 7.0"

如遇问题，可尝试降级或使用 `npx anki-mcp-http@0.7.0`。

## 安全机制

### 来源验证

HTTP 模式包含来源验证保护，防止 DNS 重绑定攻击：

```typescript
@Injectable()
export class OriginValidationGuard implements CanActivate {
  canActivate(context: ExecutionContext): boolean {
    // 验证请求来源
    // 防止 DNS rebinding 攻击
  }
}
```

资料来源：[src/http/guards/origin-validation.guard.ts:1-50](https://github.com/ankimcp/anki-mcp-server/blob/main/src/http/guards/origin-validation.guard.ts)

### 认证机制

HTTP 模式支持令牌认证：

```bash
# 设置认证令牌
export AUTH_TOKEN="your-secret-token"

# 启动服务
npx -y @ankimcp/anki-mcp-server --http
```

客户端连接时需要在请求头中包含令牌：

```
Authorization: Bearer <your-secret-token>
```

### 只读模式

社区功能请求 `#18` 建议添加只读模式，可限制服务器仅执行读取操作：

```bash
npx -y @ankimcp/anki-mcp-server --stdio --read-only
```

该功能可以防止意外修改 Anki 数据，适合学习和浏览场景。

## 传输模式选择指南

```mermaid
graph TD
    A["选择传输模式"] --> B{使用场景}
    B -->|Claude Desktop| C["STDIO 模式"]
    B -->|VS Code| C
    B -->|远程访问| D["HTTP + Ngrok"]
    B -->|本地开发| E{"需要 Ngrok?"}
    E -->|是| F["HTTP + Ngrok"]
    E -->|否| G["HTTP 模式"]
    
    C --> H["高安全性<br/>本地通信"]
    F --> I["中等安全性<br/>公网访问"]
    G --> J["中等安全性<br/>内网访问"]
```

### 性能考虑

| 模式 | 延迟 | 并发支持 | 适用卡组规模 |
|------|------|----------|-------------|
| STDIO | 极低 | 单一客户端 | 任何规模 |
| HTTP | 低 | 多客户端 | 任何规模 |
| HTTP + Ngrok | 中等（网络延迟） | 多客户端 | 建议配合 `addNotes` 批量操作 |

社区问题 `#22` 报告了大量创建卡片时的超时问题，建议在批量操作时使用 `addNotes` 工具而非多次调用 `addNote`。

## 模块系统

根据 CLAUDE.md 的模块架构，两种传输模式共享核心功能：

```
AppModule.forStdio() / forHttp()
  ├─ McpModule.forRoot()          # 传输层
  ├─ McpPrimitivesAnkiEssentialModule.forRoot()  # 核心工具
  └─ McpPrimitivesAnkiGuiModule.forRoot()         # GUI工具
```

资料来源：[CLAUDE.md 模块系统章节](https://github.com/ankimcp/anki-mcp-server/blob/main/CLAUDE.md)

## 命令行参数参考

| 参数 | 模式 | 说明 |
|------|------|------|
| `--stdio` | STDIO | 启用标准输入输出传输 |
| `--http` | HTTP | 启用 HTTP 传输 |
| `--port <num>` | HTTP | 指定 HTTP 端口 |
| `--ngrok` | HTTP | 启用 Ngrok 隧道 |
| `--auth-token <token>` | HTTP | 设置认证令牌 |
| `--read-only` | 通用 | 限制为只读操作 |

## 故障排除

### STDIO 常见问题

| 问题 | 解决方案 |
|------|----------|
| `ERR_REQUIRE_ESM` | 确认 Node.js 版本 >= 20.19（项目已排除 21.x） |
| 连接超时 | 确保 AnkiConnect 插件已安装并运行 |

### HTTP 常见问题

| 问题 | 解决方案 |
|------|----------|
| Ngrok 启动失败 | 检查 ngrok 安装和认证状态 |
| 连接被拒绝 | 确认端口未被占用，检查防火墙设置 |

### Node.js 版本要求

项目要求 Node.js >= 20.19，明确排除 21.x 版本（社区问题 `#17`）：

> "users on Node 21.x get `ERR_REQUIRE_ESM` because the `require(esm)` feature doesn't exist in Node 21"

---

<a id='page-tool-reference'></a>

## 核心工具参考

### 相关页面

相关主题：[GUI 工具集](#page-gui-tools), [系统架构](#page-architecture)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/mcp/primitives/essential/tools/add-note.tool.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/mcp/primitives/essential/tools/add-note.tool.ts)
- [src/mcp/primitives/essential/tools/add-notes.tool.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/mcp/primitives/essential/tools/add-notes.tool.ts)
- [src/mcp/primitives/essential/tools/find-notes.tool.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/mcp/primitives/essential/tools/find-notes.tool.ts)
- [src/mcp/primitives/essential/tools/deck-stats.tool.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/mcp/primitives/essential/tools/deck-stats.tool.ts)
- [src/mcp/primitives/essential/tools/get-tags.tool.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/mcp/primitives/essential/tools/get-tags.tool.ts)
- [src/mcp/primitives/essential/tools/store-media-file.tool.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/mcp/primitives/essential/tools/store-media-file.tool.ts)
- [src/mcp/primitives/essential/tools/sync.tool.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/mcp/primitives/essential/tools/sync.tool.ts)
- [src/mcp/types/anki.types.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/mcp/types/anki.types.ts)
- [src/mcp/utils/anki.utils.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/mcp/utils/anki.utils.ts)
</details>

# 核心工具参考

## 概述

Anki MCP Server 的核心工具是实现 AI 助手与 Anki 闪卡应用交互的基础组件。所有工具均通过 `AnkiConnectClient` 与 AnkiConnect 插件通信，利用 NestJS 依赖注入和 `@rekog/mcp-nest` 框架自动发现和注册。

核心工具按照功能分为以下几类：

| 类别 | 工具数量 | 主要用途 |
|------|----------|----------|
| 笔记管理 | 4 | 创建、查询、更新、删除笔记 |
| 复习管理 | 5 | 获取待复习卡片、显示卡片、评分 |
| 卡组管理 | 2 | 获取卡组列表、卡组统计 |
| 模型管理 | 4 | 列表字段、样式、创建模型 |
| 媒体管理 | 2 | 存储媒体文件、检索笔记媒体 |
| 标签管理 | 1 | 获取所有标签 |
| 同步管理 | 1 | AnkiWeb 同步 |

资料来源：[manifest.json:manifest.json.tools]()

## 工具架构

### 工具实现模式

所有核心工具遵循统一的实现模式：

```mermaid
graph TD
    A[MCP Client 调用工具] --> B[@Tool 装饰器]
    B --> C[Zod 参数校验]
    C --> D[execute 方法执行]
    D --> E[AnkiConnectClient.invoke]
    E --> F{成功?}
    F -->|是| G[返回原始对象]
    F -->|否| H[createErrorResponse]
    G --> I[mcp-nest 自动包装]
    H --> J[返回错误结果]
```

工具类结构如下：

```typescript
@Injectable()
export class SomeTool {
  constructor(private readonly ankiClient: AnkiConnectClient) {}

  @Tool({
    name: "toolName",
    description: "工具描述",
    parameters: z.object({ /* 参数 schema */ }),
    outputSchema: z.object({ /* 输出 schema */ }),
    annotations: {
      readOnlyHint: boolean,
      destructiveHint: boolean,
      idempotentHint?: boolean
    }
  })
  async execute(params: SomeParams, context: Context) {
    // 实现逻辑
  }
}
```

资料来源：[CLAUDE.md](https://github.com/ankimcp/anki-mcp-server/blob/main/CLAUDE.md)

### 错误处理机制

工具错误处理使用 `createErrorResponse` 函数，返回 `CallToolResult` 类型，绕过 outputSchema 验证：

```typescript
return createErrorResponse(error, {
  hint: "错误提示信息"
});
```

资料来源：[src/mcp/utils/anki.utils.ts:anki.utils.ts.createErrorResponse]()

## 笔记管理工具

### addNote - 创建单条笔记

创建单条笔记到指定卡组，使用前需要确保理解卡片创建的最佳实践。

**参数定义：**

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| deckName | string | 是 | 目标卡组名称 |
| modelName | string | 是 | 笔记类型（如 "Basic", "Cloze"） |
| fields | Record<string, string> | 是 | 字段名到值的映射 |
| tags | string[] | 否 | 标签数组 |
| options | NoteOptions | 否 | 重复检查等选项 |

**重要提示：**
- 批量创建时推荐使用 `addNotes` 工具，单独调用 `addNote` 会产生多次 HTTP 请求
- 如果需要创建多条卡片，应使用 `addNotes` 批量操作以提高性能

**重复检查选项：**

```typescript
interface NoteOptions {
  checkDuplicate: boolean;      // 是否检查重复
  duplicateScope: string;       // 检查范围："deck" | "deckAndNotes"
  duplicateScopeDeckId?: number;
  duplicateScopeOptions?: {
    checkAllModels?: boolean;
  };
}
```

资料来源：[src/mcp/primitives/essential/tools/add-note.tool.ts]()
资料来源：[src/mcp/types/anki.types.ts:AddNoteParams]()

**社区反馈：**
用户报告创建卡片时遇到 AnkiConnect 超时问题，建议批量操作使用 `addNotes` 而非多次调用 `addNote`。参见 Issue #22。

### addNotes - 批量创建笔记

批量创建多条笔记，显著提高大量卡片创建效率。

**设计背景：**
Claude Desktop 等 MCP 客户端会并行触发多个 `addNote` 调用，这会压垮 AnkiConnect 的单线程 Qt 事件循环。`addNotes` 工具专门为此场景设计。

**参数结构：**

```typescript
interface AddNotesParams {
  notes: Array<{
    deckName: string;
    modelName: string;
    fields: Record<string, string>;
    tags?: string[];
    options?: NoteOptions;
  }>;
}
```

**返回结果：**

```typescript
{
  success: boolean;
  results: Array<{
    index: number;
    success: boolean;
    error?: string;
    noteId?: number;
  }>;
  added: number;
  failed: number;
}
```

资料来源：[src/mcp/primitives/essential/tools/add-notes.tool.ts]()
资料来源：[Issue #23](https://github.com/ankimcp/anki-mcp-server/issues/23)

### findNotes - 搜索笔记

通过查询条件搜索笔记。

**查询参数：**

| 参数 | 类型 | 说明 |
|------|------|------|
| query | string | Anki 查询语法字符串 |
| limit | number | 最大返回数量（默认 100）|

**Anki 查询语法示例：**

```
deck:FDNY-CAPTAIN tag:10-codes
"Code 1"  // 全文搜索
is:new     // 新卡片
is:due     // 到期卡片
```

资料来源：[src/mcp/primitives/essential/tools/find-notes.tool.ts]()

### updateNoteFields - 更新笔记字段

更新已有笔记的字段内容。

**参数：**

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| note | number | 是 | 笔记 ID |
| fields | Record<string, string> | 是 | 要更新的字段 |

**注意事项：**
如果目标笔记在 Anki 浏览窗口中打开，`updateNoteFields` 会静默失败（请求返回 200 但字段未保存）。这是上游 AnkiConnect 的行为。

资料来源：[CLAUDE.md - Upstream AnkiConnect Quirks]()

### deleteNotes - 删除笔记

永久删除指定笔记及其所有关联卡片。

**参数：**

```typescript
{
  notes: number[];        // 笔记 ID 数组
  confirmDeletion: true;  // 必须设置为 true
}
```

**安全提示：**
- 此操作不可逆，会级联删除笔记的所有卡片
- 工具注释标记 `destructiveHint: true`

资料来源：[manifest.json:deleteNotes]()

## 复习管理工具

### getDueCards - 获取到期卡片

获取需要复习的卡片。

```typescript
{
  deck?: string;  // 可选卡组过滤
}
```

返回卡片结构包含：卡片 ID、笔记 ID、卡片类型、到期时间、间隔、难度等。

资料来源：[src/mcp/types/anki.types.ts:AnkiCard]()

### getCards - 灵活卡片筛选

按状态和卡组筛选卡片。

**状态选项：**

| 状态 | 说明 |
|------|------|
| due | 到期需要复习 |
| new | 新卡片 |
| learning | 学习中的卡片 |
| suspended | 暂停的卡片 |
| buried | 隐藏的卡片 |

### presentCard - 显示卡片问题

显示卡片正面内容供复习使用。

### rateCard - 评分卡片

对复习的卡片进行评分并安排下次复习时间。

**评分选项：**

| 评分 | 说明 |
|------|------|
| Again | 完全忘记，需要重新学习 |
| Hard | 记得但很困难 |
| Good | 正常回忆 |
| Easy | 太简单了 |

## 卡组管理工具

### deckNames - 列出所有卡组

返回 Anki 中所有卡组的名称列表。

### deckStats - 卡组统计信息

获取指定卡组的详细统计数据。

**参数：**

```typescript
{
  deck: string;           // 卡组名称
  includeRevLogs?: boolean; // 包含复习日志
  days?: number;          // 统计天数（默认 30）
}
```

**返回数据：**

```typescript
{
  deck: string;
  date: string;
  cards: {
    total: number;
    new: number;
    learning: number;
    mature: number;
  };
  reviews: number;
  averageTime: number;
  retention?: number;
  breakdown?: {
    again: number;
    hard: number;
    good: number;
    easy: number;
  };
}
```

**功能特性：**
- 支持子卡组统计（默认包含子卡组数据）
- 可选包含复习日志用于详细分析
- 支持自定义统计时间范围

资料来源：[src/mcp/primitives/essential/tools/deck-stats.tool.ts]()

## 模型管理工具

### modelNames - 列出笔记类型

返回所有可用的笔记类型/模型名称列表。

### modelFieldNames - 获取字段名

获取指定笔记类型的字段名称列表。

```typescript
{
  modelName: string;  // 模型名称
}
```

### modelStyling - 获取 CSS 样式

获取笔记类型的 CSS 样式信息。

**用途：**
- 查看当前样式
- 为 RTL（从右到左）语言（希伯来语、阿拉伯语等）添加样式支持
- 自定义卡片外观

### createModel - 创建笔记类型

创建自定义笔记类型，包含字段、卡片模板和 CSS 样式。

```typescript
{
  model: {
    name: string;
    inOrderFields: string[];      // 字段列表
    css: string;                  // CSS 样式
    isCloze: boolean;             // 是否为填空模板
    cardTemplates?: Array<{
      Name: string;
      Question: string;          // 正面模板
      Answer: string;            // 反面模板
    }>;
  };
}
```

**注意：**
Model CSS 是按笔记类型共享的，不是按笔记单独设置。使用 `notesInfo` 可获取笔记使用的模型。

资料来源：[CLAUDE.md - Upstream AnkiConnect Quirks]()

## 标签管理工具

### getTags - 获取所有标签

获取 Anki 集合中的所有标签列表。

**参数：**

| 参数 | 类型 | 说明 |
|------|------|------|
| pattern | string | 可选的过滤模式（大小写不敏感）|

**返回结构：**

```typescript
{
  success: boolean;
  tags: string[];        // 标签列表
  total: number;         // 总数
  message: string;
  filtered?: boolean;    // 是否被过滤
  totalUnfiltered?: number; // 过滤前的总数
}
```

**使用场景：**
- AI 代理在创建笔记前发现现有标签
- 防止标签重复（如 "roman-empire" vs "roman_empire"）
- 维护标签命名一致性

**社区需求：**
此工具是为了解决 Issue #13 中用户反馈的问题：AI 代理无法看到现有标签，导致标签不一致。

资料来源：[src/mcp/primitives/essential/tools/get-tags.tool.ts]()
资料来源：[Issue #13](https://github.com/ankimcp/anki-mcp-server/issues/13)

## 媒体管理工具

### storeMediaFile - 存储媒体文件

将媒体文件存储到 Anki 集合中。

**安全特性（v0.15.1+）：**
- MIME 类型白名单验证
- 路径遍历攻击防护
- SSRF 风险防护

**参数：**

```typescript
{
  path: string;      // 文件路径或 URL
  name: string;      // 目标文件名
  source: "path" | "url";  // 来源类型
}
```

**支持的 MIME 类型：**
图像、音频、视频等常见格式。

**安全修复：**
v0.15.1 版本修复了路径遍历漏洞，该漏洞可能允许通过 `storeMediaFile` 路径参数进行任意文件读取，以及通过 URL 参数的 SSRF 风险。

资料来源：[src/mcp/primitives/essential/tools/store-media-file.tool.ts]()
资料来源：[v0.15.1 Release Notes](https://github.com/ankimcp/anki-mcp-server/releases/tag/v0.15.1)

## 同步管理工具

### sync - AnkiWeb 同步

与 AnkiWeb 同步以获取最新数据并推送更改。

**前置条件：**
桌面版 Anki 必须已登录 AnkiWeb 账户。MCP 服务器没有 API 路径来进行身份验证。

**错误处理：**
如果未登录，会返回提示建议检查 Anki 连接设置。

资料来源：[src/mcp/primitives/essential/tools/sync.tool.ts]()
资料来源：[CLAUDE.md - Upstream AnkiConnect Quirks]()

## 工具权限控制

### 只读模式

可通过 `--read-only` 全局标志限制所有写操作，防止意外修改 Anki 卡组。

**受影响的工具：**
- addNote / addNotes
- updateNoteFields
- deleteNotes
- createModel
- updateModelStyling
- sync（需要写权限）

**社区需求：**
参见 Issue #18：用户希望配置工具权限以防止 AI 意外修改卡组。

## 常用工作流

### 创建批量卡片

```mermaid
graph TD
    A[开始] --> B[获取可用标签<br>getTags]
    B --> C[确认标签列表]
    C --> D[获取卡组名称<br>deckNames]
    D --> E[确认目标卡组]
    E --> F[获取模型字段<br>modelFieldNames]
    F --> G[构建笔记数据]
    G --> H[批量创建笔记<br>addNotes]
    H --> I{成功?}
    I -->|是| J[完成]
    I -->|否| K[检查错误]
    K --> G
```

### 复习工作流

```mermaid
graph TD
    A[开始复习] --> B[获取到期卡片<br>getDueCards]
    B --> C{有到期卡片?}
    C -->|否| Z[完成]
    C -->|是| D[获取卡片详情]
    D --> E[显示问题<br>presentCard]
    E --> F[用户回忆]
    F --> G[显示答案]
    G --> H[用户评分]
    H --> I[rateCard]
    I --> J{继续复习?}
    J -->|是| D
    J -->|否| K[可选: sync]
    K --> Z
```

## 类型定义参考

### AnkiCard - 卡片类型

```typescript
interface AnkiCard {
  cardId: number;      // 卡片 ID
  fields: Record<string, { value: string; order: number }>;
  buttons: string[];  // 评分按钮 ["Again", "Hard", "Good", "Easy"]
  css: string;
  front: string;       // 清理后的正面内容
  back: string;        // 清理后的背面内容
  cardType: CardType;  // "new" | "learning" | "review" | "relearning"
  interval: number;    // 间隔（天）
  due: number;         // Unix 时间戳
  dueString: string;
  lapses: number;      // 遗忘次数
  reps: number;        // 复习次数
  leftToday: number;
  newToday: number;
  reviewedToday: number;
  remaining: number;
}
```

资料来源：[src/mcp/types/anki.types.ts:AnkiCard]()

### CardRating - 评分枚举

```typescript
enum CardRating {
  Again = 1,  // 重新学习
  Hard = 2,   // 困难
  Good = 3,   // 良好
  Easy = 4    // 简单
}
```

## 最佳实践

### 卡片创建

1. **使用批量工具**：创建多条卡片时使用 `addNotes` 而非多次调用 `addNote`
2. **预先验证**：使用 `getTags` 和 `modelFieldNames` 确认目标结构
3. **标签一致性**：建立统一的标签命名规范，避免重复

### 复习流程

1. **定期同步**：复习后使用 `sync` 保持与 AnkiWeb 同步
2. **批量评分**：连续复习时批量使用 `rateCard`
3. **状态检查**：使用 `getCards` 检查不同状态的卡片

### 性能优化

| 场景 | 建议 |
|------|------|
| 大量卡片创建 | 使用 `addNotes` 批量创建 |
| 标签发现 | 使用 `getTags` 一次性获取，避免重复查询 |
| 卡组统计 | 设置合理的 `days` 参数避免返回过多数据 |
| 媒体上传 | 验证文件类型，使用 `source: "path"` 避免网络请求 |

## 相关文档

- [CLAUDE.md](https://github.com/ankimcp/anki-mcp-server/blob/main/CLAUDE.md) - 开发指南和架构说明
- [CHANGELOG.md](https://github.com/ankimcp/anki-mcp-server/blob/main/CHANGELOG.md) - 版本变更记录
- [Issue #21](https://github.com/ankimcp/anki-mcp-server/issues/21) - 批量创建功能讨论
- [Issue #22](https://github.com/ankimcp/anki-mcp-server/issues/22) - 卡片创建超时问题
- [Issue #23](https://github.com/ankimcp/anki-mcp-server/issues/23) - addNotes 批量操作引导

---

<a id='page-gui-tools'></a>

## GUI 工具集

### 相关页面

相关主题：[核心工具参考](#page-tool-reference), [系统架构](#page-architecture)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/mcp/primitives/gui/index.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/mcp/primitives/gui/index.ts)
- [src/mcp/primitives/gui/tools/gui-browse.tool.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/mcp/primitives/gui/tools/gui-browse.tool.ts)
- [src/mcp/primitives/gui/tools/gui-show-question.tool.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/mcp/primitives/gui/tools/gui-show-question.tool.ts)
- [src/mcp/primitives/gui/tools/gui-show-answer.tool.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/mcp/primitives/gui/tools/gui-show-answer.tool.ts)
- [src/mcp/primitives/gui/tools/gui-current-card.tool.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/mcp/primitives/gui/tools/gui-current-card.tool.ts)
- [src/mcp/primitives/gui/tools/gui-selected-notes.tool.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/mcp/primitives/gui/tools/gui-selected-notes.tool.ts)
</details>

# GUI 工具集

## 概述

GUI 工具集是 anki-mcp-server 中用于与 Anki 桌面应用程序图形界面进行交互的工具模块。与核心复习工具不同，GUI 工具需要用户的显式操作批准，因为它们会打开或操作 Anki 的图形界面组件。这些工具主要用于笔记编辑和创建工作流，而非复习会话。

根据 CLAUDE.md 的规范，GUI 工具必须包含双重警告：
- **"IMPORTANT: Only use when user explicitly requests..."**
- **"This tool is for note editing/creation workflows, NOT for review sessions"**

资料来源：[CLAUDE.md]()

## 架构设计

### 模块结构

GUI 工具集采用 NestJS 模块化架构，通过 `McpPrimitivesAnkiGuiModule` 统一管理所有 GUI 相关工具。

```mermaid
graph TD
    A[McpPrimitivesAnkiGuiModule] --> B[Browser Tools]
    A --> C[Dialog Tools]
    A --> D[Utility Tools]
    
    B --> B1[GuiBrowseTool]
    B --> B2[GuiSelectCardTool]
    B --> B3[GuiSelectedNotesTool]
    
    C --> C1[GuiAddCardsTool]
    C --> C2[GuiEditNoteTool]
    C --> C3[GuiDeckOverviewTool]
    C --> C4[GuiDeckBrowserTool]
    
    D --> D1[GuiCurrentCardTool]
    D --> D2[GuiShowQuestionTool]
    D --> D3[GuiShowAnswerTool]
    D --> D4[GuiUndoTool]
```

### 工具分类

| 分类 | 用途 | 典型场景 |
|------|------|----------|
| **Browser Tools** | 卡片浏览器操作 | 搜索、选择笔记 |
| **Dialog Tools** | 对话框交互 | 添加卡片、编辑笔记、查看牌组 |
| **Utility Tools** | 界面状态查询 | 查看当前卡片、显示问答、撤销操作 |

资料来源：[src/mcp/primitives/gui/index.ts:1-50]()

## 浏览器工具

### GuiBrowseTool

用于打开 Anki 的卡片浏览器并搜索指定的卡片。此工具不执行复习会话相关的操作。

```typescript
@Tool({
  name: "guiBrowse",
  description: "Open Anki Card Browser and search for cards...",
  annotations: {
    title: "Browse Cards",
    readOnlyHint: false,
    destructiveHint: false
  }
})
```

**输入参数：**

| 参数 | 类型 | 必需 | 说明 |
|------|------|------|------|
| query | string | 是 | Anki 搜索查询语法 |

**使用限制：**
- 仅用于笔记编辑/创建工作流
- 不适用于复习会话

资料来源：[src/mcp/primitives/gui/tools/gui-browse.tool.ts]()

### GuiSelectCardTool

在卡片浏览器中选中指定 ID 的卡片，用于笔记编辑流程中的卡片定位。

### GuiSelectedNotesTool

获取卡片浏览器中当前选中的笔记 ID 列表，返回结果为笔记 ID 数组。

**输出结构：**

```typescript
outputSchema: z.object({
  noteIds: z.array(z.number())
})
```

资料来源：[src/mcp/primitives/gui/tools/gui-selected-notes.tool.ts]()

## 对话框工具

### GuiAddCardsTool

打开 Anki 的添加卡片对话框，允许用户通过图形界面添加新卡片。

### GuiEditNoteTool

打开笔记编辑器，允许用户编辑现有笔记的内容和标签。

**关键约束：**
根据 CLAUDE.md 的说明，`updateNoteFields` 在目标笔记已在 Anki 浏览窗口中打开时会静默失败，请求返回 200 但字段不会保存。

### GuiDeckOverviewTool

打开指定牌组的概览界面。

### GuiDeckBrowserTool

打开牌组浏览器界面。

## 实用工具

### GuiCurrentCardTool

获取当前在 Anki 界面中显示的卡片信息。

```mermaid
sequenceDiagram
    Client->>GuiCurrentCardTool: 请求当前卡片
    GuiCurrentCardTool->>AnkiConnectClient: invoke('guiCurrentCard')
    AnkiConnectClient->>Anki: 获取当前卡片
    Anki-->>AnkiConnectClient: 卡片数据
    AnkiConnectClient-->>GuiCurrentCardTool: CardInfo
    GuiCurrentCardTool-->>Client: { cardId, front, back, ... }
```

资料来源：[src/mcp/primitives/gui/tools/gui-current-card.tool.ts]()

### GuiShowQuestionTool

显示卡片的问答面（问题/正面），在复习流程中呈现问题给用户。

### GuiShowAnswerTool

显示卡片的答案面（回答/背面），在复习流程中呈现答案给用户。

```typescript
@Tool({
  name: "guiShowAnswer",
  description: "Show the answer (back) of a card...",
  annotations: {
    title: "Show Answer",
    readOnlyHint: true,
    destructiveHint: false
  }
})
```

资料来源：[src/mcp/primitives/gui/tools/gui-show-answer.tool.ts]()

### GuiUndoTool

撤销 Anki 中的最后一次操作。

## 工具注解

所有 GUI 工具都必须在 `@Tool` 装饰器中声明 `annotations`，包含以下属性：

| 注解 | 类型 | 说明 |
|------|------|------|
| `title` | string | 工具的可读标题 |
| `readOnlyHint` | boolean | 是否为只读操作 |
| `destructiveHint` | boolean | 是否为破坏性操作 |
| `idempotentHint` | boolean | (可选) 操作是否幂等 |

资料来源：[CLAUDE.md]()

## 安全考虑

### 用户批准机制

GUI 工具通过 AnkiConnect API 与 Anki 桌面应用交互，用户在 Anki 中的操作（如打开编辑器、选择卡片）需要用户显式批准。这提供了一层保护，防止 AI 代理在用户不知情的情况下修改笔记。

### 读/写模式

根据 issue #18 的功能请求，用户希望配置可配置的工具有限权限（只读模式）。GUI 工具集中的写操作工具（如 `GuiEditNoteTool`）在只读模式下应被禁用。

### 区分复习和工作流

文档明确区分了两种使用场景：

| 场景 | 适用工具 | 工具描述 |
|------|----------|----------|
| 复习会话 | `presentCard`, `rate_card` | 核心复习工具 |
| 笔记编辑/创建 | GUI 工具 | 需要用户界面交互 |

资料来源：[manifest.json](https://github.com/ankimcp/anki-mcp-server/blob/main/manifest.json), [issue #18](https://github.com/ankimcp/anki-mcp-server/issues/18)

## 与核心工具的区别

| 特性 | 核心复习工具 | GUI 工具集 |
|------|--------------|------------|
| 传输方式 | STDIO/Streamable HTTP | 需要 Anki 桌面应用运行 |
| 用户批准 | 自动执行 | 需要用户界面操作 |
| 适用场景 | 自动化复习 | 笔记编辑/创建工作流 |
| 依赖 | AnkiConnect API | AnkiConnect API + GUI 交互 |

## 错误处理

GUI 工具使用统一的错误响应格式：

```typescript
return createErrorResponse(error, {
  context: "额外错误上下文信息",
  hint: "用户可执行的修复建议"
});
```

错误处理会捕获常见的失败场景，如：
- Anki 未运行
- 指定的卡片/笔记不存在
- 网络连接问题

资料来源：[src/mcp/utils/anki.utils.ts]()

## 模块导出

`src/mcp/primitives/gui/index.ts` 统一导出所有 GUI 相关的工具和类型：

```typescript
// Tools - Browser
export { GuiBrowseTool } from "./tools/gui-browse.tool";
export { GuiSelectCardTool } from "./tools/gui-select-card.tool";
export { GuiSelectedNotesTool } from "./tools/gui-selected-notes.tool";

// Tools - Dialog
export { GuiAddCardsTool } from "./tools/gui-add-cards.tool";
export { GuiEditNoteTool } from "./tools/gui-edit-note.tool";
export { GuiDeckOverviewTool } from "./tools/gui-deck-overview.tool";
export { GuiDeckBrowserTool } from "./tools/gui-deck-browser.tool";

// Tools - Utility
export { GuiCurrentCardTool } from "./tools/gui-current-card.tool";
export { GuiShowQuestionTool } from "./tools/gui-show-question.tool";
export { GuiShowAnswerTool } from "./tools/gui-show-answer.tool";
export { GuiUndoTool } from "./tools/gui-undo.tool";
```

资料来源：[src/mcp/primitives/gui/index.ts:9-30]()

---

<a id='page-troubleshooting'></a>

## 故障排除

### 相关页面

相关主题：[安装与配置](#page-installation), [命令行参考](#page-cli-reference), [安全特性](#page-security)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/mcp/clients/anki-connect.client.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/mcp/clients/anki-connect.client.ts)
- [src/mcp/utils/anki.utils.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/mcp/utils/anki.utils.ts)
- [src/mcp/utils/media-validation.utils.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/mcp/utils/media-validation.utils.ts)
- [package.json](https://github.com/ankimcp/anki-mcp-server/blob/main/package.json)
- [CLAUDE.md](https://github.com/ankimcp/anki-mcp-server/blob/main/CLAUDE.md)
- [CHANGELOG.md](https://github.com/ankimcp/anki-mcp-server/blob/main/CHANGELOG.md)
</details>

# 故障排除

本页面汇总了 anki-mcp-server 使用过程中常见的错误场景、根本原因分析以及解决方案。所有错误处理逻辑均基于源代码中的实际实现。

## 常见错误与解决方案

### 1. ERR_REQUIRE_ESM 启动崩溃

**错误信息：**
```
Error [ERR_REQUIRE_ESM]: require() of ES Module...
```

**影响版本：** v0.8.5 及更早版本  
**根本原因：** `ky` 是一个纯 ESM 模块，在 Node.js 21.x 环境下无法通过 CommonJS 的 `require()` 加载。

**解决方案：**

| 操作 | 说明 |
|------|------|
| 升级 Node.js | 升级到 Node.js 22.x 或 Node.js 20.17+ |
| 检查版本 | 运行 `node --version` 确认版本 |

项目 `package.json` 中已明确声明 `engines` 字段要求 Node.js >= 20.19.0：

```json
"engines": {
  "node": ">=20.19.0"
}
```

资料来源：[package.json:38](https://github.com/ankimcp/anki-mcp-server/blob/main/package.json)

### 2. AnkiConnect 超时错误

**错误信息：**
```
AnkiConnect request timeout
```

**社区反馈：** Issue #22 报告在批量创建卡片时频繁出现超时。  
**根本原因：** AnkiConnect 基于 Qt 单线程事件循环，高并发请求会导致响应延迟。

**解决方案：**

1. **使用批量操作工具** - 优先使用 `addNotes` 而非多次调用 `addNote`：

```typescript
// 正确方式：批量添加
addNotes({
  notes: [
    { deckName: "MyDeck", modelName: "Basic", fields: {...} },
    { deckName: "MyDeck", modelName: "Basic", fields: {...} }
  ]
})

// 避免：连续多次调用
for (const note of notes) {
  addNote(note) // 每次调用都产生网络往返
}
```

2. **检查 Anki 运行状态** - 确保 Anki 应用程序正在运行且 AnkiConnect 插件已启用

3. **增加超时配置** - 在 AnkiConnect 设置中调整超时时间

资料来源：[CLAUDE.md](https://github.com/ankimcp/anki-mcp-server/blob/main/CLAUDE.md) (Upstream AnkiConnect Quirks 部分)

### 3. Ngrok 隧道启动失败

**错误信息：**
```
failed to start ngrok
```

**社区反馈：** Issue #9 报告 ngrok 3.24.0-msix 版本与服务器不兼容。  
**解决方案：** 使用 ngrok v7.0 或更高版本：

```bash
npx anki-mcp-http@0.7.0
```

### 4. 卡片创建时字段为空被拒绝

**社区反馈：** Issue #20 报告部分笔记类型的字段是可选的，但工具拒绝空字段。

**当前行为：** 系统会验证必填字段，阻止创建包含空值的笔记。

**建议方案：**
- 检查笔记类型定义，确认哪些字段是可选的
- 如需支持空字段，可考虑使用 `updateNoteFields` 事后清空

## 错误处理架构

### 错误响应生成流程

```mermaid
graph TD
    A[AnkiConnect 请求] --> B{请求成功?}
    B -->|是| C[返回原始数据]
    B -->|否| D[捕获 AnkiConnectError]
    D --> E{错误类型识别}
    E -->|模型未找到| F[生成错误提示<br/>使用 modelNames 获取可用模型]
    E -->|笔记未找到| G[生成错误提示<br/>检查笔记ID]
    E -->|其他错误| H[通用错误信息]
    F --> I[createErrorResponse]
    G --> I
    H --> I
    I --> J[返回 CallToolResult<br/>isError: true]
```

`createErrorResponse` 函数负责将各种错误场景转换为统一的 MCP 错误响应格式：

```typescript
// src/mcp/utils/anki.utils.ts
export function createErrorResponse(
  error: AnkiConnectError,
  context?: Record<string, string>
): CallToolResult {
  return {
    content: [
      {
        type: "text",
        text: formatAnkiError(error, context),
      },
    ],
    isError: true,
  };
}
```

资料来源：[src/mcp/utils/anki.utils.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/mcp/utils/anki.utils.ts)

### AnkiConnect 客户端重试机制

```mermaid
graph LR
    A[MCP Tool 调用] --> B[ky HTTP Client]
    B --> C{请求成功?}
    C -->|是| D[返回结果]
    C -->|否| E{重试次数 < 3?}
    E -->|是| F[等待后重试]
    F --> B
    E -->|否| G[抛出 AnkiConnectError]
```

客户端实现了自动重试机制，默认最多重试 3 次：

```typescript
// src/mcp/clients/anki-connect.client.ts
export class AnkiConnectClient {
  async invoke<T>(action: string, params?: Record<string, unknown>): Promise<T> {
    // ... 重试逻辑实现
  }
}
```

资料来源：[src/mcp/clients/anki-connect.client.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/mcp/clients/anki-connect.client.ts)

## AnkiConnect 上游特性与限制

以下行为属于 AnkiConnect 本身的特性，anki-mcp-server 无法绕过：

| 行为 | 描述 | 规避方案 |
|------|------|----------|
| `updateNoteFields` 在笔记打开时静默失败 | 在 Anki 浏览器中打开笔记后更新不会生效 | 更新前关闭浏览器或切换笔记 |
| Model CSS 是按笔记类型共享的 | 所有使用同一模型的卡片共享 CSS | 使用 `modelStyling` 获取，`updateNoteFields` 保留内联样式 |
| `sync` 需要桌面应用登录 | 无法通过 API 路径认证 | 确保 Anki 已登录 AnkiWeb |
| `deleteNotes` 不可逆 | 删除笔记会级联删除所有关联卡片 | 必须设置 `confirmDeletion: true` |

资料来源：[CLAUDE.md](https://github.com/ankimcp/anki-mcp-server/blob/main/CLAUDE.md)

## 安全验证错误

### 媒体文件安全

v0.15.1 版本后添加了多层安全验证：

| 验证类型 | 攻击场景 | 处理方式 |
|----------|----------|----------|
| MIME 类型检查 | 上传恶意文件绕过扩展名 | 白名单验证 |
| 路径遍历检查 | 通过 `../` 读取任意文件 | 规范化路径后验证 |
| SSRF 检查 | 通过 URL 参数访问内网资源 | URL 源验证 |

验证失败时会返回安全错误：

```typescript
// src/mcp/utils/media-validation.utils.ts
export function validateMediaPath(path: string): ValidationResult {
  // 路径遍历检测
  // MIME 类型白名单验证
  // 返回验证结果
}
```

资料来源：[src/mcp/utils/media-validation.utils.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/mcp/utils/media-validation.utils.ts)

## 调试步骤

### 1. 环境检查

```bash
# 检查 Node.js 版本
node --version

# 检查 anki-mcp-server 版本
npx @ankimcp/anki-mcp-server --version

# 验证 Anki 运行状态
curl http://localhost:8765 -d '{"action": "version", "version": 6}'
```

### 2. 启用调试日志

项目使用 Pino 进行日志记录：

```bash
# 启动服务并查看详细日志
DEBUG=pino:* npx @ankimcp/anki-mcp-server --stdio
```

### 3. MCP Inspector 调试

使用 MCP Inspector 检查工具调用：

```bash
npx @modelcontextprotocol/inspector \
  npx @ankimcp/anki-mcp-server --stdio
```

## 版本历史问题

| 版本 | 问题 | 状态 |
|------|------|------|
| v0.8.5 | ERR_REQUIRE_ESM 在 Node 21.x | **已修复** - Node >= 20.19.0 |
| v0.15.1 | 媒体路径遍历漏洞 | **已修复** - 安全验证 |
| v0.14.0 | 批量添加工具缺失 | **已修复** - `addNotes` 工具 |
| v0.18.5-tunnel.2 | ngrok 兼容性问题 | **持续改进** |

资料来源：[CHANGELOG.md](https://github.com/ankimcp/anki-mcp-server/blob/main/CHANGELOG.md)

## 获取帮助

如果以上方案无法解决您的问题：

1. **检查 GitHub Issues** - 搜索类似问题的解决方案
   - [ERR_REQUIRE_ESM 相关](https://github.com/ankimcp/anki-mcp-server/issues/16)
   - [AnkiConnect 超时相关](https://github.com/ankimcp/anki-mcp-server/issues/22)

2. **提交新 Issue** - 请包含以下信息：
   - 操作系统和 Node.js 版本
   - anki-mcp-server 版本
   - Anki 版本和 AnkiConnect 插件版本
   - 完整的错误日志
   - 重现步骤

---

<a id='page-cli-reference'></a>

## 命令行参考

### 相关页面

相关主题：[安装与配置](#page-installation), [故障排除](#page-troubleshooting)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/cli.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/cli.ts)
- [package.json](https://github.com/ankimcp/anki-mcp-server/blob/main/package.json)
- [README.md](https://github.com/ankimcp/anki-mcp-server/blob/main/README.md)
- [CLAUDE.md](https://github.com/ankimcp/anki-mcp-server/blob/main/CLAUDE.md)
- [src/mcp/primitives/essential/tools/sync.tool.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/mcp/primitives/essential/tools/sync.tool.ts)
</details>

# 命令行参考

Anki MCP Server 提供多种命令行启动方式，支持 STDIO 传输和 HTTP 隧道两种主要模式。本页面详细说明所有可用的命令行选项、配置参数和使用场景。

## 概述

Anki MCP Server 是一个基于 Model Context Protocol (MCP) 的 Anki 闪卡应用程序服务器。它通过 AnkiConnect 插件与 Anki 通信，使 AI 助手能够与用户的 Anki 集合进行交互。

**支持的运行模式：**

| 模式 | 传输协议 | 典型用途 |
|------|----------|----------|
| STDIO | 标准输入输出 | Claude Desktop、VS Code 等 MCP 客户端 |
| HTTP + Ngrok | Streamable HTTP + 隧道 | 远程访问、跨网络连接 |

## 安装与前置条件

### 前置要求

- **Node.js**: `>=20.19.0`（Node 21.x 不支持，详见 [Issue #17](https://github.com/ankimcp/anki-mcp-server/issues/17)）
- **Anki**: 已安装并运行
- **AnkiConnect 插件**: 在 Anki 中安装（插件 ID: `2055492159`）

### 安装方式

```bash
# 全局安装
npm install -g @ankimcp/anki-mcp-server

# 或使用 npx 直接运行
npx -y @ankimcp/anki-mcp-server --stdio
```

## STDIO 模式

STDIO 模式是 MCP 客户端（如 Claude Desktop）的标准连接方式。

### 基本语法

```bash
anki-mcp --stdio
```

### 选项参数

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `--stdio` | boolean | false | 启用 STDIO 传输模式 |
| `--anki-port` | number | 8765 | AnkiConnect HTTP 服务端口 |
| `--anki-host` | string | "127.0.0.1" | AnkiConnect 主机地址 |
| `--read-only` | boolean | false | 启用只读模式，禁用所有写操作 |
| `--timeout` | number | 30 | 请求超时时间（秒） |
| `--log-level` | string | "info" | 日志级别 (trace, debug, info, warn, error) |
| `--verbose` | boolean | false | 启用详细日志输出 |

### 完整示例

```bash
# 标准启动
anki-mcp --stdio

# 自定义 AnkiConnect 连接
anki-mcp --stdio --anki-port 8765 --anki-host 127.0.0.1

# 只读模式（社区功能请求 - Issue #18）
anki-mcp --stdio --read-only

# 启用调试日志
anki-mcp --stdio --log-level debug --verbose
```

### Claude Desktop 配置

在 `claude_desktop_config.json` 中配置：

```json
{
  "mcpServers": {
    "anki": {
      "command": "npx",
      "args": ["-y", "@ankimcp/anki-mcp-server", "--stdio"],
      "env": {}
    }
  }
}
```

## HTTP 隧道模式

HTTP 隧道模式通过 Ngrok 创建公共 URL，支持远程访问 Anki MCP Server。

### 基本语法

```bash
anki-mcp --tunnel
```

### 隧道模式选项

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `--tunnel` | boolean | false | 启用 Ngrok 隧道模式 |
| `--tunnel-port` | number | 8080 | 本地 HTTP 服务端口 |
| `--auth-token` | string | - | Ngrok 认证令牌 |
| `--domain` | string | - | Ngrok 自定义域名 |

### Ngrok 认证配置

首次使用隧道模式需要配置 Ngrok 认证：

1. 注册 [Ngrok 账号](https://ngrok.com/)
2. 获取 Authtoken
3. 配置 Ngrok：

```bash
ngrok config add-authtoken <YOUR_AUTH_TOKEN>
```

### 完整示例

```bash
# 基本隧道启动
anki-mcp --tunnel

# 自定义本地端口
anki-mcp --tunnel --tunnel-port 9090

# 使用 Ngrok authtoken
anki-mcp --tunnel --auth-token <YOUR_TOKEN>
```

**注意**: Ngrok 模式曾报告启动问题（见 [Issue #9](https://github.com/ankimcp/anki-mcp-server/issues/9)），如遇 "failed to start ngrok" 错误，建议检查 Ngrok 版本。

## 只读模式

只读模式是社区请求的功能（[Issue #18](https://github.com/ankimcp/anki-mcp-server/issues/18)），用于限制 MCP 服务器的操作权限，防止意外修改 Anki 集合。

### 启用方式

```bash
anki-mcp --stdio --read-only
```

### 只读模式的限制

启用后，以下操作将被阻止：

| 操作类型 | 受影响工具 |
|----------|------------|
| 创建笔记 | `addNote`, `addNotes` |
| 更新笔记 | `updateNoteFields` |
| 删除笔记 | `deleteNotes` |
| 管理牌组 | `createDeck`, `deleteDeck` |
| 管理模板 | `createModel`, `updateModelStyling` |
| 复习操作 | `rateCard` |
| 媒体操作 | `storeMediaFile` |

### 允许的操作（只读）

- `get_due_cards` - 获取到期卡片
- `get_cards` - 获取卡片信息
- `present_card` - 展示卡片
- `modelNames` - 列出模板
- `modelFieldNames` - 获取字段名
- `getTags` - 获取标签列表
- `guiBrowse` - 浏览窗口
- 统计工具

## 环境变量

除命令行参数外，部分配置也可通过环境变量设置：

| 变量名 | 说明 | 对应参数 |
|--------|------|----------|
| `ANKI_PORT` | AnkiConnect 端口 | `--anki-port` |
| `ANKI_HOST` | AnkiConnect 主机 | `--anki-host` |
| `ANKI_TIMEOUT` | 请求超时（秒） | `--timeout` |
| `LOG_LEVEL` | 日志级别 | `--log-level` |
| `READ_ONLY` | 只读模式 | `--read-only` |

## 连接架构

```mermaid
graph TD
    subgraph "MCP 客户端"
        A[Claude Desktop / VS Code]
    end
    
    subgraph "Anki MCP Server"
        B[CLI 解析层]
        C[传输层]
        D[业务逻辑层]
    end
    
    subgraph "AnkiConnect"
        E[HTTP 服务]
        F[Anki 应用]
    end
    
    A -->|MCP 协议| B
    B --> C
    C -->|STDIO 或 HTTP| D
    D -->|JSON-RPC| E
    E -->|API| F
    
    style A fill:#e1f5fe
    style F fill:#c8e6c9
    style D fill:#fff3e0
```

## 常见问题与故障排除

### ERR_REQUIRE_ESM 错误

**问题**: Node.js 21.x 用户遇到启动崩溃（[Issue #12](https://github.com/ankimcp/anki-mcp-server/issues/12)、[Issue #16](https://github.com/ankimcp/anki-mcp-server/issues/16)）

**原因**: 项目依赖的 `ky` 库是纯 ESM 模块，Node.js 21.x 不支持此加载方式

**解决方案**:
- 降级至 Node.js 20.19+ 或升级至 Node.js 22+
- 或使用 npx 自动获取兼容版本

### AnkiConnect 超时

**问题**: 创建卡片时频繁超时（[Issue #22](https://github.com/ankimcp/anki-mcp-server/issues/22)）

**原因**: AnkiConnect 基于 Qt 单线程事件循环，高并发请求会导致排队

**解决方案**:
- 使用 `addNotes` 批量创建而非多次 `addNote` 调用
- 增加 `--timeout` 参数值
- 检查 Anki 是否正在执行同步操作

### Ngrok 启动失败

**问题**: Ngrok 隧道模式启动失败（[Issue #9](https://github.com/ankimcp/anki-mcp-server/issues/9)）

**解决方案**:
- 验证 Ngrok authtoken 配置正确
- 检查 Ngrok 版本（建议 3.x）
- 确认防火墙允许 Ngrok 出站连接

## 退出码

| 退出码 | 含义 |
|--------|------|
| 0 | 正常退出 |
| 1 | 一般错误（参数错误、连接失败等） |
| 2 | AnkiConnect 连接失败 |
| 130 | 收到 SIGINT (Ctrl+C) 中断信号 |

## 相关文档

- [MCP 工具参考](./mcp-tools.md) - 完整工具列表与参数说明
- [安全配置](./security.md) - 媒体安全、路径遍历防护
- [API 参考](./api-reference.md) - AnkiConnect API 封装

---

<a id='page-security'></a>

## 安全特性

### 相关页面

相关主题：[故障排除](#page-troubleshooting), [命令行参考](#page-cli-reference)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/mcp/utils/media-validation.utils.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/mcp/utils/media-validation.utils.ts)
- [src/http/guards/origin-validation.guard.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/http/guards/origin-validation.guard.ts)
- [src/mcp/clients/anki-connect.client.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/mcp/clients/anki-connect.client.ts)
- [SECURITY.md](https://github.com/ankimcp/anki-mcp-server/blob/main/SECURITY.md)
- [src/http/strategies/api-key.strategy.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/http/strategies/api-key.strategy.ts)
- [src/config/anki-config.interface.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/config/anki-config.interface.ts)
</details>

# 安全特性

Anki MCP Server 实现了多层次的安全机制，用于保护用户数据免受恶意请求、路径遍历攻击、服务器端请求伪造（SSRF）等安全威胁。本页面详细说明服务器的安全架构、实现机制和配置选项。

## 架构概览

Anki MCP Server 的安全体系由以下几个核心模块组成：

```mermaid
graph TD
    A[客户端请求] --> B{传输层}
    B --> C[STDIO 传输]
    B --> D[HTTP 传输]
    D --> E[来源验证守卫]
    E --> F[API Key 认证]
    D --> G[媒体文件操作]
    G --> H[媒体安全验证]
    H --> I{MIME 类型检查}
    H --> J{路径规范化检查}
    H --> K{URL 参数验证}
    I --> L[允许列表验证]
    J --> M[禁止遍历序列]
    K --> N[DNS 重绑定防护]
    
    style A fill:#e1f5fe
    style L fill:#c8e6c9
    style M fill:#c8e6c9
    style N fill:#c8e6c9
```

## 媒体安全验证

### 概述

v0.15.1 版本引入了媒体操作的安全加固，针对 `storeMediaFile` 工具的路径遍历漏洞和 URL 参数的 SSRF 风险实施了多层验证。该安全更新由安全研究员 [Hideaki Takahashi](https://github.com/Koukyosyumei) 报告。

资料来源：[SECURITY.md](https://github.com/ankimcp/anki-mcp-server/blob/main/SECURITY.md)

### MIME 类型白名单

媒体文件上传必须通过 MIME 类型白名单验证。服务器仅允许预定义的安全文件类型：

| 类型分类 | 允许的 MIME 类型 |
|---------|-----------------|
| 图片 | `image/jpeg`, `image/png`, `image/gif`, `image/webp`, `image/svg+xml` |
| 音频 | `audio/mpeg`, `audio/wav`, `audio/ogg`, `audio/flac` |
| 视频 | `video/mp4`, `video/webm`, `video/ogg` |
| 文档 | `application/pdf` |

```typescript
// src/mcp/utils/media-validation.utils.ts
export const ALLOWED_MIME_TYPES = [
  // Images
  "image/jpeg",
  "image/png",
  "image/gif",
  "image/webp",
  "image/svg+xml",
  // Audio
  "audio/mpeg",
  "audio/wav",
  "audio/ogg",
  "audio/flac",
  // Video
  "video/mp4",
  "video/webm",
  "video/ogg",
  // Documents
  "application/pdf",
] as const;
```

资料来源：[src/mcp/utils/media-validation.utils.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/mcp/utils/media-validation.utils.ts)

### 路径遍历防护

`storeMediaFile` 工具实现了路径规范化检查，防止攻击者通过 `../` 等序列访问用户目录之外的敏感文件：

```typescript
export function isPathSafe(filePath: string): boolean {
  const normalized = path.normalize(filePath);
  return (
    !normalized.includes("..") &&
    path.isAbsolute(filePath) === false &&
    !normalized.startsWith("/")
  );
}
```

关键检查规则：
- 禁止路径中包含 `..` 遍历序列
- 不允许绝对路径
- 禁止以 `/` 开头的路径

资料来源：[src/mcp/utils/media-validation.utils.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/mcp/utils/media-validation.utils.ts)

### SSRF 防护

对于通过 URL 参数传入的媒体文件，服务器实施以下防护措施：

1. **URL 协议验证**：仅允许 `http://` 和 `https://` 协议
2. **DNS 重绑定保护**：验证 `Host` 头部，防止私有 IP 地址范围访问
3. **重定向限制**：验证最终请求目标，防止重定向到内部网络

```typescript
// src/mcp/utils/media-validation.utils.ts
export function validateUrlSafety(url: string): boolean {
  try {
    const parsed = new URL(url);
    if (!["http:", "https:"].includes(parsed.protocol)) {
      return false;
    }
    // Additional DNS rebinding protection
    return !isPrivateIpRange(parsed.hostname);
  } catch {
    return false;
  }
}
```

资料来源：[src/mcp/utils/media-validation.utils.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/mcp/utils/media-validation.utils.ts)

## HTTP 传输安全

### 来源验证守卫

HTTP 传输模式使用来源验证守卫（Origin Validation Guard）防止跨站请求攻击：

```typescript
// src/http/guards/origin-validation.guard.ts
@Injectable()
export class OriginValidationGuard implements CanActivate {
  canActivate(context: ExecutionContext): boolean {
    const request = context.switchToHttp().getRequest();
    const origin = request.headers.origin;
    
    // Validate against allowed origins
    const allowedOrigins = this.configService.getAllowedOrigins();
    if (!allowedOrigins.includes(origin)) {
      throw new ForbiddenException('Invalid origin');
    }
    return true;
  }
}
```

资料来源：[src/http/guards/origin-validation.guard.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/http/guards/origin-validation.guard.ts)

### API Key 认证

HTTP 端点使用 JWT API Key 进行身份验证：

```typescript
// src/http/strategies/api-key.strategy.ts
@Injectable()
export class ApiKeyStrategy extends PassportStrategy(Strategy, 'api-key') {
  constructor(private configService: ConfigService) {
    super({
      jwtFromRequest: ExtractJwt.fromAuthHeaderWithScheme('Bearer'),
      secretOrKey: configService.getApiKeySecret(),
    });
  }
}
```

资料来源：[src/http/strategies/api-key.strategy.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/http/strategies/api-key.strategy.ts)

## 只读模式

用户可以通过命令行参数启用只读模式，防止 MCP 服务器执行任何写入操作：

```bash
npx @ankimcp/anki-mcp-server --read-only --stdio
```

资料来源：[src/config/anki-config.interface.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/config/anki-config.interface.ts)

### 配置接口

```typescript
export interface IAnkiConfig {
  readonly?: boolean;
  ankiHost?: string;
  ankiPort?: number;
  // ... other config options
}
```

只读模式会阻止以下操作：
- 创建笔记 (`addNote`, `addNotes`)
- 更新笔记字段 (`updateNoteFields`)
- 删除笔记 (`deleteNotes`)
- 存储媒体文件 (`storeMediaFile`)
- 创建卡牌模板 (`createModel`)

资料来源：[src/mcp/clients/anki-connect.client.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/mcp/clients/anki-connect.client.ts)

## 工具注解与权限控制

每个 MCP 工具都通过注解（annotations）声明其安全属性：

| 注解类型 | 说明 | 示例 |
|---------|------|------|
| `readOnlyHint` | 标识只读操作 | `true` 或 `false` |
| `destructiveHint` | 标识破坏性操作 | `true` 或 `false` |
| `idempotentHint` | 标识幂等操作 | `true` 或 `false` |

```typescript
// 示例：storeMediaFile 工具注解
annotations: {
  readOnlyHint: false,
  destructiveHint: false,
  idempotentHint: false,
},
```

资料来源：[src/mcp/clients/anki-connect.client.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/mcp/clients/anki-connect.client.ts)

## 安全报告

Anki MCP Server 遵循负责任的安全披露原则。如需报告安全漏洞，请参考 [SECURITY.md](https://github.com/ankimcp/anki-mcp-server/blob/main/SECURITY.md)。

## 已知限制

| 问题编号 | 描述 | 当前状态 |
|---------|------|---------|
| #18 | 缺少细粒度工具权限配置（per-tool control） | 功能请求中 |
| #22 | 批量创建卡片时可能触发 AnkiConnect 超时 | 建议使用 `addNotes` 批量工具 |

---

<a id='page-development'></a>

## 开发指南

### 相关页面

相关主题：[系统架构](#page-architecture), [安装与配置](#page-installation)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [package.json](https://github.com/ankimcp/anki-mcp-server/blob/main/package.json)
- [CLAUDE.md](https://github.com/ankimcp/anki-mcp-server/blob/main/CLAUDE.md)
- [tsconfig.json](https://github.com/ankimcp/anki-mcp-server/blob/main/tsconfig.json)
- [src/mcp/primitives/essential/tools/sync.tool.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/mcp/primitives/essential/tools/sync.tool.ts)
- [src/mcp/primitives/essential/tools/get-tags.tool.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/mcp/primitives/essential/tools/get-tags.tool.ts)
- [src/mcp/types/anki.types.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/mcp/types/anki.types.ts)
- [src/mcp/utils/anki.utils.ts](https://github.com/ankimcp/anki-mcp-server/blob/main/src/mcp/utils/anki.utils.ts)
</details>

# 开发指南

本指南面向希望为 anki-mcp-server 项目贡献代码、扩展功能或深入了解项目架构的开发者。anki-mcp-server 是一个基于 Model Context Protocol (MCP) 的 Anki 间隔重复记忆应用服务器，使 AI 助手能够与 Anki 进行自然语言交互。

## 环境要求与项目设置

### Node.js 版本要求

项目明确要求 **Node.js >= 20.19.0** 且 **< 21.0.0**。Node 21.x 由于缺少 `require(esm)` 特性支持会导致 `ERR_REQUIRE_ESM` 错误。

```json
"engines": {
  "node": ">=20.19.0 <21.0.0"
}
```

资料来源：[package.json:7-9]()

### 核心依赖

| 依赖包 | 版本 | 用途 |
|--------|------|------|
| `@modelcontextprotocol/sdk` | 精确版本 1.29.0 | MCP 协议实现 |
| `zod` | ^4.3.6 | 数据验证（注意：使用 v4 而非 v3） |
| `ky` | ^1.14.3 | HTTP 客户端（ESM 模块） |
| `@rekog/mcp-nest` | - | MCP-Nest 框架 |
| `@nestjs/common` | - | NestJS 核心 |

资料来源：[package.json:31-62]()

### 开发脚本

```bash
# 构建项目
npm run build

# STDIO 模式开发（热重载）
npm run start:dev:stdio

# HTTP 模式开发（热重载）
npm run start:dev:http

# 生产环境启动
npm run start:prod:stdio
npm run start:prod:http

# 代码检查与格式化
npm run lint
npm run format

# 测试
npm run test
```

资料来源：[package.json:17-28]()

## 项目架构概览

```
anki-mcp-server/
├── src/
│   ├── main-stdio.ts           # STDIO 传输入口
│   ├── main-http.ts           # HTTP 传输入口
│   ├── main-tunnel.ts         # Ngrok 隧道入口
│   ├── app.module.ts          # 根模块
│   ├── config/                # 配置相关
│   │   ├── anki-config.interface.ts  # 配置接口
│   │   └── anki-config.loader.ts      # 配置加载器
│   ├── services/              # 服务层
│   │   └── ngrok.service.ts  # Ngrok 隧道管理
│   └── mcp/                   # MCP 核心模块
│       ├── clients/           # AnkiConnect HTTP 客户端
│       ├── config/           # MCP 配置
│       ├── types/            # 共享类型定义
│       ├── utils/            # 工具函数
│       └── primitives/       # 工具、提示词、资源
│           ├── essential/    # 核心工具
│           └── gui/          # GUI 交互工具
├── test/                     # 测试文件
├── scripts/                  # 构建脚本
└── bin/                      # CLI 入口
```

资料来源：[CLAUDE.md:1-22]()

### 传输模式架构

项目支持三种传输模式：

```mermaid
graph TD
    A[客户端] --> B{传输模式}
    B -->|stdio| C[main-stdio.ts]
    B -->|http| D[main-http.ts]
    B -->|tunnel| E[main-tunnel.ts + Ngrok]
    
    C --> F[McpModule STDIO]
    D --> G[McpModule STREAMABLE_HTTP]
    E --> G
    E --> H[NgrokService]
    
    F --> I[AnkiConnect Client]
    G --> I
    H --> J[AnkiConnect]
    
    I --> K[Anki 桌面应用]
    J --> K
```

## 模块系统

### 应用模块结构

```typescript
AppModule.forStdio() / forHttp()
  → McpModule.forRoot()           // STDIO 或 STREAMABLE_HTTP 传输
  → McpPrimitivesAnkiEssentialModule.forRoot()  // 核心工具
  → McpPrimitivesAnkiGuiModule.forRoot()       // GUI 工具
```

资料来源：[CLAUDE.md:24-31]()

### 模块发现机制

所有工具、提示词和资源通过 `@rekog/mcp-nest` 自动发现。MCP-Nest 1.9.0+ 要求工具同时在 `AppModule.providers` 中声明（参见 `ESSENTIAL_MCP_TOOLS` 和 `GUI_MCP_TOOLS` 数组）。

## 工具开发规范

### 标准工具结构

每个 MCP 工具应遵循以下模式：

```typescript
// 1. Zod schema 用于输入验证
// 2. @Injectable() 类注入 AnkiConnectClient
// 3. @Tool 装饰器定义元数据
// 4. execute() 方法调用 AnkiConnectClient.invoke()
// 5. 成功返回匹配 outputSchema 的原始对象
// 6. 错误返回 createErrorResponse()
```

资料来源：[CLAUDE.md:67-75]()

### 最小工具示例

```typescript
import { Injectable, Logger } from "@nestjs/common";
import { Tool } from "@rekog/mcp-nest";
import { z } from "zod";
import { AnkiConnectClient } from "@/mcp/clients/anki-connect.client";
import { createErrorResponse } from "@/mcp/utils/anki.utils";

@Injectable()
export class SyncTool {
  private readonly logger = new Logger(SyncTool.name);

  constructor(private readonly ankiClient: AnkiConnectClient) {}

  @Tool({
    name: "sync",
    description: "Sync with AnkiWeb to get latest data and push changes",
    parameters: z.object({}),
    outputSchema: z.object({
      success: z.boolean(),
      message: z.string(),
    }),
    annotations: {
      title: "Sync Collection",
      readOnlyHint: false,
      destructiveHint: false,
      idempotentHint: false,
    },
  })
  async execute() {
    try {
      const result = await this.ankiClient.invoke("sync", {});
      return result;
    } catch (error) {
      return createErrorResponse(error, {
        hint: "Make sure Anki is running and logged into AnkiWeb.",
      });
    }
  }
}
```

资料来源：[src/mcp/primitives/essential/tools/sync.tool.ts]()

### @Tool 装饰器参数

| 参数 | 类型 | 说明 |
|------|------|------|
| `name` | string | 工具唯一名称 |
| `description` | string | 工具描述，用于 AI 理解功能 |
| `parameters` | ZodSchema | 输入参数验证 schema |
| `outputSchema` | ZodSchema | 输出数据结构 schema |
| `annotations` | object | 包含 `readOnlyHint`、`destructiveHint`、`idempotentHint` |

### outputSchema 与错误处理

- **成功路径**：返回匹配 `outputSchema` 的原始对象，MCP-Nest handler 自动验证并包装
- **错误路径**：使用 `createErrorResponse()` 返回，跳过 outputSchema 验证

```typescript
// 错误响应示例
return createErrorResponse(error, {
  modelName,
  hint: "Model not found. Use modelNames tool to see available models.",
});
```

资料来源：[CLAUDE.md:53-62]()

### GUI 工具特殊要求

GUI 工具位于 `src/mcp/primitives/gui/`，必须包含双重警告：

1. "IMPORTANT: Only use when user explicitly requests..."
2. "This tool is for note editing/creation workflows, NOT for review sessions"

## 数据类型定义

### 核心类型

```typescript
// 添加笔记参数
interface AddNoteParams {
  deckName: string;                    // 目标牌组
  modelName: string;                   // 笔记类型
  fields: Record<string, string>;      // 字段键值对
  tags?: string[];                     // 可选标签
  options?: NoteOptions;                // 重复检查选项
}

// 笔记类型/模型信息
interface Model {
  name: string;      // 模型名称
  id: number;        // 唯一标识符
  css: string;       // CSS 样式
  fields: string[];  // 字段名称数组
}

// 笔记详细信息
interface NoteInfo {
  noteId: number;
  modelName: string;
  tags: string[];
  fields: Record<string, { value: string; order: number }>;
  cards: number[];
  mod: number;
}
```

资料来源：[src/mcp/types/anki.types.ts]()

## 工具函数

### 错误响应创建

```typescript
import { createErrorResponse } from "@/mcp/utils/anki.utils";

// 返回 CallToolResult，isError: true，绕过 outputSchema 验证
return createErrorResponse(error, {
  field: "value",
  hint: "Helpful error message",
});
```

资料来源：[src/mcp/utils/anki.utils.ts:1-10]()

### HTML 清理

```typescript
import { cleanHtml } from "@/mcp/utils/anki.utils";

// 移除 HTML 标签并解码 HTML 实体
const cleanText = cleanHtml(html);
```

### Markdown 解析

```typescript
import { parseMarkdownSections } from "@/mcp/utils/markdown.utils";

// 按 H1 标题分割 Markdown 内容
const sections = parseMarkdownSections(markdown);
// 返回: { "Description": "...", "Content": "..." }
```

## 路径别名配置

项目配置了 TypeScript 路径别名：

| 别名 | 指向 |
|------|------|
| `@/*` | `src/*` |
| `@test/*` | `test/*` |

```typescript
// 示例导入
import { AnkiConnectClient } from "@/mcp/clients/anki-connect.client";
import { Something } from "@test/helpers";
```

资料来源：[CLAUDE.md:88-91]()

## 测试策略

项目采用三层测试策略，根据变更类型选择合适的测试级别：

```mermaid
graph LR
    A[变更类型] --> B{选择测试}
    B -->|工具逻辑| C[单元测试]
    B -->|集成流程| D[集成测试]
    B -->|端到端| E[E2E 测试]
```

### 测试目录结构

```
test/
├── unit/           # 单元测试
├── integration/    # 集成测试
└── e2e/           # 端到端测试
```

## 常见陷阱与限制

### AnkiConnect 上游行为

项目中标注了以下上游行为，开发时需要注意：

| 行为 | 说明 | 处理方式 |
|------|------|----------|
| `updateNoteFields` 静默失败 | 目标笔记在浏览窗口打开时不保存 | 在工具描述中警告用户 |
| Model CSS 是按笔记类型而非按笔记 | 获取 CSS 用 `modelStyling`，判断模型用 `notesInfo` | 更新笔记时保留内联样式 |
| `sync` 依赖桌面应用登录状态 | 无 API 路径进行身份验证 | 返回提示性错误信息 |
| `deleteNotes` 不可逆且级联删除 | 所有相关卡片一并删除 | 要求 `confirmDeletion: true` |

资料来源：[CLAUDE.md:40-50]()

### Zod 版本注意

项目使用 **Zod v4**（`zod@^4.x`），**不是** v3。Zod 4 有不同的 API：

- 使用 `z.interface()` 而非 `z.object()`（在某些场景）
- 错误处理方式不同

```typescript
// Zod v4 正确用法
const schema = z.object({
  name: z.string(),
  age: z.number(),
});
```

## Claude Desktop 集成

### 安装配置

在 Claude Desktop 配置文件 (`~/.config/Claude/claude_desktop_config.json`) 中添加：

```json
{
  "mcpServers": {
    "anki-mcp-server": {
      "command": "npx",
      "args": ["-y", "@ankimcp/anki-mcp-server"],
      "env": {
        "ANKI_HOST": "127.0.0.1",
        "ANKI_PORT": "8765"
      }
    }
  }
}
```

### 环境变量

| 变量 | 默认值 | 说明 |
|------|--------|------|
| `ANKI_HOST` | 127.0.0.1 | AnkiConnect 主机地址 |
| `ANKI_PORT` | 8765 | AnkiConnect 端口 |
| `ANKI_READ_ONLY` | false | 只读模式标志 |

## 社区已知问题

开发时需注意以下社区反馈的问题：

| Issue | 状态 | 说明 |
|-------|------|------|
| #22: 创建卡片超时 | 已知 | AnkiConnect 单线程 Qt 事件循环在高并发下超时 |
| #21: 批量创建性能 | 功能请求 | `addNotes` 批量工具已提供，建议优先使用 |
| #20: 空字段处理 | 已知 | 当前对空字段有检查，可选字段场景受限 |
| #16: ERR_REQUIRE_ESM | 已修复 | Node 21.x 不支持，已排除在 engines 范围外 |

资料来源：[community_context](#top-community-issues-by-engagement)

## 代码规范

### ESLint 配置

项目使用 ESLint 进行代码检查，配置文件位于 `eslint.config.mjs`。

### Prettier 格式化

```bash
# 格式化所有源码
npm run format
```

### TypeScript 配置

- `strict: true` - 严格类型检查
- `module: "nodenext"` - Node.js ESM 支持
- `target: "ES2023"` - 编译目标

## 发布流程

项目使用语义化版本控制，当前处于 0.x.x beta 阶段，允许破坏性变更。

发布通过 GitHub Actions 自动完成，发布说明由合并的 PR 自动生成。

```bash
# 构建并发布
npm run build
npm publish
```

资料来源：[CHANGELOG.md](https://github.com/ankimcp/anki-mcp-server/blob/main/CHANGELOG.md)

## 扩展开发清单

新增工具时的检查清单：

- [ ] 创建 `*.tool.ts` 文件于 `src/mcp/primitives/essential/` 或 `src/mcp/primitives/gui/`
- [ ] 定义 Zod 输入/输出 schema
- [ ] 使用 `@Injectable()` 和 `@Tool()` 装饰器
- [ ] 在 `ESSENTIAL_MCP_TOOLS` 或 `GUI_MCP_TOOLS` 数组中注册
- [ ] 添加单元测试
- [ ] 更新 `manifest.json` 工具列表（如需要）
- [ ] 更新本开发指南文档

---

<!-- evidence_pipeline_checked: true -->
<!-- evidence_injected: true -->

---

## Doramagic 踩坑日志

项目：ankimcp/anki-mcp-server

摘要：发现 14 个潜在踩坑项，其中 0 个为 high/blocking；最高优先级：安装坑 - 来源证据：Anki mcp for mcp clients fails with 'ERR_REQUIRE_ESM'。

## 1. 安装坑 · 来源证据：Anki mcp for mcp clients fails with 'ERR_REQUIRE_ESM'

- 严重度：medium
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个安装相关的待验证问题：Anki mcp for mcp clients fails with 'ERR_REQUIRE_ESM'
- 对用户的影响：可能增加新用户试用和生产接入成本。
- 建议检查：来源显示可能已有修复、规避或版本变化，说明书中必须标注适用版本。
- 防护动作：不得脱离来源链接放大为确定性结论；需要标注适用版本和复核状态。
- 证据：community_evidence:github | cevd_7f29acec242e48c9b9a28ff2585734d3 | https://github.com/ankimcp/anki-mcp-server/issues/12 | 来源讨论提到 node 相关条件，需在安装/试用前复核。

## 2. 安装坑 · 来源证据：Crash on startup: ERR_REQUIRE_ESM when requiring 'ky'

- 严重度：medium
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个安装相关的待验证问题：Crash on startup: ERR_REQUIRE_ESM when requiring 'ky'
- 对用户的影响：可能阻塞安装或首次运行。
- 建议检查：来源显示可能已有修复、规避或版本变化，说明书中必须标注适用版本。
- 防护动作：不得脱离来源链接放大为确定性结论；需要标注适用版本和复核状态。
- 证据：community_evidence:github | cevd_66dcd7ebe4a842228360620571d902f5 | https://github.com/ankimcp/anki-mcp-server/issues/16 | 来源讨论提到 node 相关条件，需在安装/试用前复核。

## 3. 安装坑 · 来源证据：Feature Request: Deck and Collection Level Statistics

- 严重度：medium
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个安装相关的待验证问题：Feature Request: Deck and Collection Level Statistics
- 对用户的影响：可能增加新用户试用和生产接入成本。
- 建议检查：来源显示可能已有修复、规避或版本变化，说明书中必须标注适用版本。
- 防护动作：不得脱离来源链接放大为确定性结论；需要标注适用版本和复核状态。
- 证据：community_evidence:github | cevd_e49f272712124771bc55365bbe3ad1cc | https://github.com/ankimcp/anki-mcp-server/issues/14 | 来源讨论提到 npm 相关条件，需在安装/试用前复核。

## 4. 安装坑 · 来源证据：Not possible to install Anki MCP 0.8.4 to latest Claude Desktop Claude 1.0.1307 (1ed883)

- 严重度：medium
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个安装相关的待验证问题：Not possible to install Anki MCP 0.8.4 to latest Claude Desktop Claude 1.0.1307 (1ed883)
- 对用户的影响：可能增加新用户试用和生产接入成本。
- 建议检查：来源显示可能已有修复、规避或版本变化，说明书中必须标注适用版本。
- 防护动作：不得脱离来源链接放大为确定性结论；需要标注适用版本和复核状态。
- 证据：community_evidence:github | cevd_82a572d18c7b4eac9facb5ff06652bc5 | https://github.com/ankimcp/anki-mcp-server/issues/10 | 来源类型 github_issue 暴露的待验证使用条件。

## 5. 安装坑 · 来源证据：ngrok fails to start with latest version

- 严重度：medium
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个安装相关的待验证问题：ngrok fails to start with latest version
- 对用户的影响：可能增加新用户试用和生产接入成本。
- 建议检查：来源显示可能已有修复、规避或版本变化，说明书中必须标注适用版本。
- 防护动作：不得脱离来源链接放大为确定性结论；需要标注适用版本和复核状态。
- 证据：community_evidence:github | cevd_bd4f26c6db6b4db8adc1436a457ff69a | https://github.com/ankimcp/anki-mcp-server/issues/9 | 来源讨论提到 npm 相关条件，需在安装/试用前复核。

## 6. 配置坑 · 来源证据：Explicitly exclude Node 21.x in engines field

- 严重度：medium
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个配置相关的待验证问题：Explicitly exclude Node 21.x in engines field
- 对用户的影响：可能增加新用户试用和生产接入成本。
- 建议检查：来源显示可能已有修复、规避或版本变化，说明书中必须标注适用版本。
- 防护动作：不得脱离来源链接放大为确定性结论；需要标注适用版本和复核状态。
- 证据：community_evidence:github | cevd_0a42c043dbad4d93a4731734d006fa08 | https://github.com/ankimcp/anki-mcp-server/issues/17 | 来源讨论提到 node 相关条件，需在安装/试用前复核。

## 7. 能力坑 · 能力判断依赖假设

- 严重度：medium
- 证据强度：source_linked
- 发现：README/documentation is current enough for a first validation pass.
- 对用户的影响：假设不成立时，用户拿不到承诺的能力。
- 建议检查：将假设转成下游验证清单。
- 防护动作：假设必须转成验证项；没有验证结果前不能写成事实。
- 证据：capability.assumptions | mcp_registry:ai.ankimcp/anki-mcp-server:0.18.5 | https://registry.modelcontextprotocol.io/v0.1/servers/ai.ankimcp%2Fanki-mcp-server/versions/0.18.5 | README/documentation is current enough for a first validation pass.

## 8. 运行坑 · 来源证据：getting lots of timeouts creating cards

- 严重度：medium
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个运行相关的待验证问题：getting lots of timeouts creating cards
- 对用户的影响：可能增加新用户试用和生产接入成本。
- 建议检查：来源显示可能已有修复、规避或版本变化，说明书中必须标注适用版本。
- 防护动作：不得脱离来源链接放大为确定性结论；需要标注适用版本和复核状态。
- 证据：community_evidence:github | cevd_92310c7e5cea46d48a7643da19e2d5a6 | https://github.com/ankimcp/anki-mcp-server/issues/22 | 来源类型 github_issue 暴露的待验证使用条件。

## 9. 维护坑 · 维护活跃度未知

- 严重度：medium
- 证据强度：source_linked
- 发现：未记录 last_activity_observed。
- 对用户的影响：新项目、停更项目和活跃项目会被混在一起，推荐信任度下降。
- 建议检查：补 GitHub 最近 commit、release、issue/PR 响应信号。
- 防护动作：维护活跃度未知时，推荐强度不能标为高信任。
- 证据：evidence.maintainer_signals | mcp_registry:ai.ankimcp/anki-mcp-server:0.18.5 | https://registry.modelcontextprotocol.io/v0.1/servers/ai.ankimcp%2Fanki-mcp-server/versions/0.18.5 | last_activity_observed missing

## 10. 安全/权限坑 · 下游验证发现风险项

- 严重度：medium
- 证据强度：source_linked
- 发现：no_demo
- 对用户的影响：下游已经要求复核，不能在页面中弱化。
- 建议检查：进入安全/权限治理复核队列。
- 防护动作：下游风险存在时必须保持 review/recommendation 降级。
- 证据：downstream_validation.risk_items | mcp_registry:ai.ankimcp/anki-mcp-server:0.18.5 | https://registry.modelcontextprotocol.io/v0.1/servers/ai.ankimcp%2Fanki-mcp-server/versions/0.18.5 | no_demo; severity=medium

## 11. 安全/权限坑 · 存在评分风险

- 严重度：medium
- 证据强度：source_linked
- 发现：no_demo
- 对用户的影响：风险会影响是否适合普通用户安装。
- 建议检查：把风险写入边界卡，并确认是否需要人工复核。
- 防护动作：评分风险必须进入边界卡，不能只作为内部分数。
- 证据：risks.scoring_risks | mcp_registry:ai.ankimcp/anki-mcp-server:0.18.5 | https://registry.modelcontextprotocol.io/v0.1/servers/ai.ankimcp%2Fanki-mcp-server/versions/0.18.5 | no_demo; severity=medium

## 12. 安全/权限坑 · 来源证据：Feature: Configurable tool permissions (read-only mode)

- 严重度：medium
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题：Feature: Configurable tool permissions (read-only mode)
- 对用户的影响：可能阻塞安装或首次运行。
- 建议检查：来源显示可能已有修复、规避或版本变化，说明书中必须标注适用版本。
- 防护动作：不得脱离来源链接放大为确定性结论；需要标注适用版本和复核状态。
- 证据：community_evidence:github | cevd_65de282533484baf95eaa214c669167b | https://github.com/ankimcp/anki-mcp-server/issues/18 | 来源类型 github_issue 暴露的待验证使用条件。

## 13. 维护坑 · issue/PR 响应质量未知

- 严重度：low
- 证据强度：source_linked
- 发现：issue_or_pr_quality=unknown。
- 对用户的影响：用户无法判断遇到问题后是否有人维护。
- 建议检查：抽样最近 issue/PR，判断是否长期无人处理。
- 防护动作：issue/PR 响应未知时，必须提示维护风险。
- 证据：evidence.maintainer_signals | mcp_registry:ai.ankimcp/anki-mcp-server:0.18.5 | https://registry.modelcontextprotocol.io/v0.1/servers/ai.ankimcp%2Fanki-mcp-server/versions/0.18.5 | issue_or_pr_quality=unknown

## 14. 维护坑 · 发布节奏不明确

- 严重度：low
- 证据强度：source_linked
- 发现：release_recency=unknown。
- 对用户的影响：安装命令和文档可能落后于代码，用户踩坑概率升高。
- 建议检查：确认最近 release/tag 和 README 安装命令是否一致。
- 防护动作：发布节奏未知或过期时，安装说明必须标注可能漂移。
- 证据：evidence.maintainer_signals | mcp_registry:ai.ankimcp/anki-mcp-server:0.18.5 | https://registry.modelcontextprotocol.io/v0.1/servers/ai.ankimcp%2Fanki-mcp-server/versions/0.18.5 | release_recency=unknown

<!-- canonical_name: ankimcp/anki-mcp-server; human_manual_source: deepwiki_human_wiki -->
