anki-mcp-http 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +591 -0
  3. package/bin/ankimcp.js +2 -0
  4. package/dist/anki-config.service.d.ts +10 -0
  5. package/dist/anki-config.service.js +42 -0
  6. package/dist/anki-config.service.js.map +1 -0
  7. package/dist/app.module.d.ts +5 -0
  8. package/dist/app.module.js +74 -0
  9. package/dist/app.module.js.map +1 -0
  10. package/dist/bootstrap.d.ts +3 -0
  11. package/dist/bootstrap.js +39 -0
  12. package/dist/bootstrap.js.map +1 -0
  13. package/dist/cli.d.ts +7 -0
  14. package/dist/cli.js +68 -0
  15. package/dist/cli.js.map +1 -0
  16. package/dist/http/guards/origin-validation.guard.d.ts +7 -0
  17. package/dist/http/guards/origin-validation.guard.js +52 -0
  18. package/dist/http/guards/origin-validation.guard.js.map +1 -0
  19. package/dist/main-http.d.ts +1 -0
  20. package/dist/main-http.js +27 -0
  21. package/dist/main-http.js.map +1 -0
  22. package/dist/main-stdio.d.ts +1 -0
  23. package/dist/main-stdio.js +20 -0
  24. package/dist/main-stdio.js.map +1 -0
  25. package/dist/mcp/clients/__mocks__/anki-connect.client.d.ts +6 -0
  26. package/dist/mcp/clients/__mocks__/anki-connect.client.js +18 -0
  27. package/dist/mcp/clients/__mocks__/anki-connect.client.js.map +1 -0
  28. package/dist/mcp/clients/anki-connect.client.d.ts +15 -0
  29. package/dist/mcp/clients/anki-connect.client.js +145 -0
  30. package/dist/mcp/clients/anki-connect.client.js.map +1 -0
  31. package/dist/mcp/config/anki-config.interface.d.ts +7 -0
  32. package/dist/mcp/config/anki-config.interface.js +5 -0
  33. package/dist/mcp/config/anki-config.interface.js.map +1 -0
  34. package/dist/mcp/primitives/essential/index.d.ts +30 -0
  35. package/dist/mcp/primitives/essential/index.js +125 -0
  36. package/dist/mcp/primitives/essential/index.js.map +1 -0
  37. package/dist/mcp/primitives/essential/prompts/review-session.prompt.d.ts +12 -0
  38. package/dist/mcp/primitives/essential/prompts/review-session.prompt.js +113 -0
  39. package/dist/mcp/primitives/essential/prompts/review-session.prompt.js.map +1 -0
  40. package/dist/mcp/primitives/essential/resources/system-info.resource.d.ts +21 -0
  41. package/dist/mcp/primitives/essential/resources/system-info.resource.js +115 -0
  42. package/dist/mcp/primitives/essential/resources/system-info.resource.js.map +1 -0
  43. package/dist/mcp/primitives/essential/tools/add-note.tool.d.ts +93 -0
  44. package/dist/mcp/primitives/essential/tools/add-note.tool.js +188 -0
  45. package/dist/mcp/primitives/essential/tools/add-note.tool.js.map +1 -0
  46. package/dist/mcp/primitives/essential/tools/create-deck.tool.d.ts +83 -0
  47. package/dist/mcp/primitives/essential/tools/create-deck.tool.js +120 -0
  48. package/dist/mcp/primitives/essential/tools/create-deck.tool.js.map +1 -0
  49. package/dist/mcp/primitives/essential/tools/create-model.tool.d.ts +88 -0
  50. package/dist/mcp/primitives/essential/tools/create-model.tool.js +142 -0
  51. package/dist/mcp/primitives/essential/tools/create-model.tool.js.map +1 -0
  52. package/dist/mcp/primitives/essential/tools/delete-notes.tool.d.ts +84 -0
  53. package/dist/mcp/primitives/essential/tools/delete-notes.tool.js +120 -0
  54. package/dist/mcp/primitives/essential/tools/delete-notes.tool.js.map +1 -0
  55. package/dist/mcp/primitives/essential/tools/find-notes.tool.d.ts +83 -0
  56. package/dist/mcp/primitives/essential/tools/find-notes.tool.js +106 -0
  57. package/dist/mcp/primitives/essential/tools/find-notes.tool.js.map +1 -0
  58. package/dist/mcp/primitives/essential/tools/get-due-cards.tool.d.ts +84 -0
  59. package/dist/mcp/primitives/essential/tools/get-due-cards.tool.js +106 -0
  60. package/dist/mcp/primitives/essential/tools/get-due-cards.tool.js.map +1 -0
  61. package/dist/mcp/primitives/essential/tools/list-decks.tool.d.ts +83 -0
  62. package/dist/mcp/primitives/essential/tools/list-decks.tool.js +117 -0
  63. package/dist/mcp/primitives/essential/tools/list-decks.tool.js.map +1 -0
  64. package/dist/mcp/primitives/essential/tools/model-field-names.tool.d.ts +83 -0
  65. package/dist/mcp/primitives/essential/tools/model-field-names.tool.js +116 -0
  66. package/dist/mcp/primitives/essential/tools/model-field-names.tool.js.map +1 -0
  67. package/dist/mcp/primitives/essential/tools/model-names.tool.d.ts +81 -0
  68. package/dist/mcp/primitives/essential/tools/model-names.tool.js +78 -0
  69. package/dist/mcp/primitives/essential/tools/model-names.tool.js.map +1 -0
  70. package/dist/mcp/primitives/essential/tools/model-styling.tool.d.ts +83 -0
  71. package/dist/mcp/primitives/essential/tools/model-styling.tool.js +93 -0
  72. package/dist/mcp/primitives/essential/tools/model-styling.tool.js.map +1 -0
  73. package/dist/mcp/primitives/essential/tools/notes-info.tool.d.ts +83 -0
  74. package/dist/mcp/primitives/essential/tools/notes-info.tool.js +111 -0
  75. package/dist/mcp/primitives/essential/tools/notes-info.tool.js.map +1 -0
  76. package/dist/mcp/primitives/essential/tools/present-card.tool.d.ts +84 -0
  77. package/dist/mcp/primitives/essential/tools/present-card.tool.js +100 -0
  78. package/dist/mcp/primitives/essential/tools/present-card.tool.js.map +1 -0
  79. package/dist/mcp/primitives/essential/tools/rate-card.tool.d.ts +84 -0
  80. package/dist/mcp/primitives/essential/tools/rate-card.tool.js +96 -0
  81. package/dist/mcp/primitives/essential/tools/rate-card.tool.js.map +1 -0
  82. package/dist/mcp/primitives/essential/tools/sync.tool.d.ts +81 -0
  83. package/dist/mcp/primitives/essential/tools/sync.tool.js +61 -0
  84. package/dist/mcp/primitives/essential/tools/sync.tool.js.map +1 -0
  85. package/dist/mcp/primitives/essential/tools/update-model-styling.tool.d.ts +84 -0
  86. package/dist/mcp/primitives/essential/tools/update-model-styling.tool.js +119 -0
  87. package/dist/mcp/primitives/essential/tools/update-model-styling.tool.js.map +1 -0
  88. package/dist/mcp/primitives/essential/tools/update-note-fields.tool.d.ts +96 -0
  89. package/dist/mcp/primitives/essential/tools/update-note-fields.tool.js +154 -0
  90. package/dist/mcp/primitives/essential/tools/update-note-fields.tool.js.map +1 -0
  91. package/dist/mcp/primitives/gui/index.d.ts +4 -0
  92. package/dist/mcp/primitives/gui/index.js +26 -0
  93. package/dist/mcp/primitives/gui/index.js.map +1 -0
  94. package/dist/mcp/types/anki.types.d.ts +152 -0
  95. package/dist/mcp/types/anki.types.js +18 -0
  96. package/dist/mcp/types/anki.types.js.map +1 -0
  97. package/dist/mcp/utils/anki.utils.d.ts +19 -0
  98. package/dist/mcp/utils/anki.utils.js +153 -0
  99. package/dist/mcp/utils/anki.utils.js.map +1 -0
  100. package/dist/mcp/utils/mcpb-workarounds.d.ts +1 -0
  101. package/dist/mcp/utils/mcpb-workarounds.js +13 -0
  102. package/dist/mcp/utils/mcpb-workarounds.js.map +1 -0
  103. package/dist/test-fixtures/mock-data.d.ts +126 -0
  104. package/dist/test-fixtures/mock-data.js +112 -0
  105. package/dist/test-fixtures/mock-data.js.map +1 -0
  106. package/dist/test-fixtures/test-helpers.d.ts +12 -0
  107. package/dist/test-fixtures/test-helpers.js +24 -0
  108. package/dist/test-fixtures/test-helpers.js.map +1 -0
  109. package/dist/tsconfig.build.tsbuildinfo +1 -0
  110. package/package.json +153 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Anatoly Tarnavsky
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,591 @@
1
+ # Anki MCP Desktop
2
+
3
+ **Beta** - This project is in active development. APIs and features may change.
4
+
5
+ A Model Context Protocol (MCP) server that enables AI assistants to interact with Anki, the spaced repetition flashcard application.
6
+
7
+ Transform your Anki experience with natural language interaction - like having a private tutor. The AI assistant doesn't just present questions and answers; it can explain concepts, make the learning process more engaging and human-like, provide context, and adapt to your learning style. It can create and edit notes on the fly, turning your study sessions into dynamic conversations. More features coming soon!
8
+
9
+ ## Examples and Tutorials
10
+
11
+ For comprehensive guides, real-world examples, and step-by-step tutorials on using this MCP server with Claude Desktop, visit:
12
+
13
+ **[ankimcp.ai](https://ankimcp.ai)** - Complete documentation with practical examples and use cases
14
+
15
+ ## Available Tools
16
+
17
+ ### Review & Study
18
+ - `sync` - Sync with AnkiWeb
19
+ - `get_due_cards` - Get cards for review
20
+ - `present_card` - Show card for review
21
+ - `rate_card` - Rate card performance
22
+
23
+ ### Deck Management
24
+ - `list_decks` - Show available decks
25
+ - `createDeck` - Create new decks
26
+
27
+ ### Note Management
28
+ - `addNote` - Create new notes
29
+ - `findNotes` - Search for notes using Anki query syntax
30
+ - `notesInfo` - Get detailed information about notes (fields, tags, CSS)
31
+ - `updateNoteFields` - Update existing note fields (CSS-aware, supports HTML)
32
+ - `deleteNotes` - Delete notes and their cards
33
+
34
+ ### Model/Template Management
35
+ - `modelNames` - List note types
36
+ - `modelFieldNames` - Get fields for a note type
37
+ - `modelStyling` - Get CSS styling for a note type
38
+
39
+ ## Prerequisites
40
+
41
+ - [Anki](https://apps.ankiweb.net/) with [AnkiConnect](https://github.com/FooSoft/anki-connect) plugin installed
42
+ - Node.js 20+
43
+
44
+ ## Installation
45
+
46
+ This server works in two modes:
47
+
48
+ - **Local mode (STDIO)** - For Claude Desktop on your computer (recommended for most users)
49
+ - **Remote mode (HTTP)** - For web-based AI assistants like ChatGPT or Claude.ai
50
+
51
+ ### Option 1: MCPB Bundle (Recommended - Local Mode)
52
+
53
+ The easiest way to install this MCP server for Claude Desktop:
54
+
55
+ 1. Download the latest `.mcpb` bundle from the [Releases](https://github.com/anki-mcp-organization/anki-mcp-desktop/releases) page
56
+ 2. In Claude Desktop, install the extension:
57
+ - **Method 1**: Go to Settings → Extensions, then drag and drop the `.mcpb` file
58
+ - **Method 2**: Go to Settings → Developer → Extensions → Install Extension, then select the `.mcpb` file
59
+ 3. Configure AnkiConnect URL if needed (defaults to `http://localhost:8765`)
60
+ 4. Restart Claude Desktop
61
+
62
+ That's it! The bundle includes everything needed to run the server locally.
63
+
64
+ ### Option 2: HTTP Mode (For Remote AI Assistants)
65
+
66
+ Want to use Anki with ChatGPT or Claude.ai in your browser? This mode lets you connect web-based AI tools to your local Anki.
67
+
68
+ **How it works (simple explanation):**
69
+ 1. You run a small server on your computer (where Anki is installed)
70
+ 2. You use [ngrok](https://ngrok.com) to create a public URL that forwards to your local server
71
+ 3. You share that URL with ChatGPT or Claude.ai
72
+ 4. Now the AI can talk to your Anki through the internet!
73
+
74
+ **Setup:**
75
+
76
+ ```bash
77
+ # Quick start (using npx - no installation needed)
78
+ npx anki-mcp-http
79
+
80
+ # With custom options
81
+ npx anki-mcp-http --port 8080 --host 0.0.0.0
82
+ npx anki-mcp-http --anki-connect http://localhost:8765
83
+
84
+ # Or install from source
85
+ npm install
86
+ npm run build
87
+ npm run start:prod:http
88
+ ```
89
+
90
+ **CLI Options:**
91
+
92
+ ```bash
93
+ ankimcp [options]
94
+
95
+ Options:
96
+ -p, --port <port> Port to listen on (default: 3000)
97
+ -h, --host <host> Host to bind to (default: 127.0.0.1)
98
+ -a, --anki-connect <url> AnkiConnect URL (default: http://localhost:8765)
99
+ --help Show help message
100
+
101
+ Examples:
102
+ ankimcp # Use all defaults
103
+ ankimcp --port 8080 # Custom port
104
+ ankimcp --host 0.0.0.0 # Listen on all network interfaces
105
+ ```
106
+
107
+ **Using with ngrok:**
108
+
109
+ ```bash
110
+ # 1. Start ankimcp
111
+ npx anki-mcp-http
112
+
113
+ # 2. In another terminal, create a tunnel
114
+ ngrok http 3000
115
+
116
+ # 3. Copy the ngrok URL (looks like: https://abc123.ngrok.io)
117
+ # 4. Share this URL with your AI assistant
118
+ ```
119
+
120
+ **Security note:** Anyone with your ngrok URL can access your Anki, so keep that URL private!
121
+
122
+ ### Option 3: Manual Installation from Source (Local Mode)
123
+
124
+ For development or advanced usage:
125
+
126
+ ```bash
127
+ npm install
128
+ npm run build
129
+ ```
130
+
131
+ ## Connect to Claude Desktop (Local Mode)
132
+
133
+ You can configure the server in Claude Desktop by either:
134
+ - Going to: Settings → Developer → Edit Config
135
+ - Or manually editing the config file
136
+
137
+ ### Configuration
138
+
139
+ Add the following to your Claude Desktop config:
140
+
141
+ ```json
142
+ {
143
+ "mcpServers": {
144
+ "anki-mcp": {
145
+ "command": "node",
146
+ "args": ["/path/to/anki-mcp-desktop/dist/main-stdio.js"],
147
+ "env": {
148
+ "ANKI_CONNECT_URL": "http://localhost:8765"
149
+ }
150
+ }
151
+ }
152
+ }
153
+ ```
154
+
155
+ Replace `/path/to/anki-mcp-desktop` with your actual project path.
156
+
157
+ ### Config File Locations
158
+
159
+ - **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
160
+ - **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
161
+ - **Linux**: `~/.config/Claude/claude_desktop_config.json`
162
+
163
+ For more details, see the [official MCP documentation](https://modelcontextprotocol.io/docs/develop/connect-local-servers).
164
+
165
+ ## Environment Variables (Optional)
166
+
167
+ | Variable | Description | Default |
168
+ |----------|-------------|---------|
169
+ | `ANKI_CONNECT_URL` | AnkiConnect URL | `http://localhost:8765` |
170
+ | `ANKI_CONNECT_API_VERSION` | API version | `6` |
171
+ | `ANKI_CONNECT_API_KEY` | API key if configured in AnkiConnect | - |
172
+ | `ANKI_CONNECT_TIMEOUT` | Request timeout in ms | `5000` |
173
+
174
+ ## Usage Examples
175
+
176
+ ### Searching and Updating Notes
177
+
178
+ ```
179
+ # Search for notes in a specific deck
180
+ findNotes(query: "deck:Spanish")
181
+
182
+ # Get detailed information about notes
183
+ notesInfo(notes: [1234567890, 1234567891])
184
+
185
+ # Update a note's fields (HTML content supported)
186
+ updateNoteFields(note: {
187
+ id: 1234567890,
188
+ fields: {
189
+ "Front": "<b>¿Cómo estás?</b>",
190
+ "Back": "How are you?"
191
+ }
192
+ })
193
+
194
+ # Delete notes (requires confirmation)
195
+ deleteNotes(notes: [1234567890], confirmDeletion: true)
196
+ ```
197
+
198
+ ### Anki Query Syntax Examples
199
+
200
+ The `findNotes` tool supports Anki's powerful query syntax:
201
+
202
+ - `"deck:DeckName"` - All notes in a specific deck
203
+ - `"tag:important"` - Notes with the "important" tag
204
+ - `"is:due"` - Cards that are due for review
205
+ - `"is:new"` - New cards that haven't been studied
206
+ - `"added:7"` - Notes added in the last 7 days
207
+ - `"front:hello"` - Notes with "hello" in the front field
208
+ - `"flag:1"` - Notes with red flag
209
+ - `"prop:due<=2"` - Cards due within 2 days
210
+ - `"deck:Spanish tag:verb"` - Spanish deck notes with verb tag (AND)
211
+ - `"deck:Spanish OR deck:French"` - Notes from either deck
212
+
213
+ ### Important Notes
214
+
215
+ #### CSS and HTML Handling
216
+ - The `notesInfo` tool returns CSS styling information for proper rendering awareness
217
+ - The `updateNoteFields` tool supports HTML content in fields and preserves CSS styling
218
+ - Each note model has its own CSS styling - use `modelStyling` to get model-specific CSS
219
+
220
+ #### Update Warning
221
+ ⚠️ **IMPORTANT**: When using `updateNoteFields`, do NOT view the note in Anki's browser while updating, or the fields will not update properly. Close the browser or switch to a different note before updating.
222
+
223
+ #### Deletion Safety
224
+ The `deleteNotes` tool requires explicit confirmation (`confirmDeletion: true`) to prevent accidental deletions. Deleting a note removes ALL associated cards permanently.
225
+
226
+ ## Development
227
+
228
+ ### Transport Modes
229
+
230
+ This server supports two MCP transport modes via **separate entry points**:
231
+
232
+ #### STDIO Mode (Default)
233
+ - For local MCP clients like Claude Desktop
234
+ - Uses standard input/output for communication
235
+ - **Entry point**: `dist/main-stdio.js`
236
+ - **Run**: `npm run start:prod:stdio` or `node dist/main-stdio.js`
237
+ - **MCPB bundle**: Uses STDIO mode
238
+
239
+ #### HTTP Mode (Streamable HTTP)
240
+ - For remote MCP clients and web-based integrations
241
+ - Uses MCP Streamable HTTP protocol
242
+ - **Entry point**: `dist/main-http.js`
243
+ - **Run**: `npm run start:prod:http` or `node dist/main-http.js`
244
+ - **Default port**: 3000 (configurable via `PORT` env var)
245
+ - **Default host**: `127.0.0.1` (configurable via `HOST` env var)
246
+ - **MCP endpoint**: `http://127.0.0.1:3000/` (root path)
247
+
248
+ #### Building
249
+
250
+ ```bash
251
+ npm run build # Builds once, creates dist/ with both entry points
252
+ ```
253
+
254
+ Both `main-stdio.js` and `main-http.js` are in the same `dist/` directory. Choose which to run based on your needs.
255
+
256
+ #### HTTP Mode Configuration
257
+
258
+ **Environment Variables:**
259
+ - `PORT` - HTTP server port (default: 3000)
260
+ - `HOST` - Bind address (default: 127.0.0.1 for localhost-only)
261
+ - `ALLOWED_ORIGINS` - Comma-separated list of allowed origins for CORS (default: localhost)
262
+ - `LOG_LEVEL` - Logging level (default: info)
263
+
264
+ **Security:**
265
+ - Origin header validation (prevents DNS rebinding attacks)
266
+ - Binds to localhost (127.0.0.1) by default
267
+ - No authentication in current version (OAuth support planned)
268
+
269
+ **Example: Running Modes**
270
+ ```bash
271
+ # Development - STDIO mode (watch mode with auto-rebuild)
272
+ npm run start:dev:stdio
273
+
274
+ # Development - HTTP mode (watch mode with auto-rebuild)
275
+ npm run start:dev:http
276
+
277
+ # Production - STDIO mode
278
+ npm run start:prod:stdio
279
+ # or
280
+ node dist/main-stdio.js
281
+
282
+ # Production - HTTP mode
283
+ npm run start:prod:http
284
+ # or
285
+ PORT=8080 HOST=0.0.0.0 node dist/main-http.js
286
+ ```
287
+
288
+ ### Building an MCPB Bundle
289
+
290
+ To create a distributable MCPB bundle:
291
+
292
+ ```bash
293
+ npm run mcpb:bundle
294
+ ```
295
+
296
+ This command will:
297
+ 1. Sync version from `package.json` to `manifest.json`
298
+ 2. Remove old `.mcpb` files
299
+ 3. Build the TypeScript project
300
+ 4. Package `dist/` and `node_modules/` into an `.mcpb` file
301
+
302
+ The output file will be named `anki-mcp-desktop-0.3.0.mcpb` (or current version) and can be distributed for one-click installation.
303
+
304
+ #### What Gets Bundled
305
+
306
+ The MCPB package includes:
307
+ - Compiled JavaScript (`dist/` directory - includes both entry points)
308
+ - All dependencies (`node_modules/`)
309
+ - Package metadata (`package.json`)
310
+ - Manifest configuration (`manifest.json` - configured to use `main-stdio.js`)
311
+ - Icon (`icon.png`)
312
+
313
+ Source files, tests, and development configs are automatically excluded via `.mcpbignore`.
314
+
315
+ ### Logging in Claude Desktop
316
+
317
+ When running as an MCPB extension in Claude Desktop, logs are written to:
318
+
319
+ **Log Location**: `~/Library/Logs/Claude/` (macOS)
320
+
321
+ The logs are split across multiple files:
322
+ - **main.log** - General Claude Desktop application logs
323
+ - **mcp-server-Anki MCP Server.log** - MCP protocol messages for this extension
324
+ - **mcp.log** - Combined MCP logs from all servers
325
+
326
+ **Note**: The pino logger output (INFO, ERROR, WARN messages from the server code) goes to stderr and appears in the MCP-specific log files. Claude Desktop determines which log file receives which messages, but generally:
327
+ - Application startup and MCP protocol communication → MCP-specific log
328
+ - Server internal logging (pino) → Both MCP-specific log and sometimes main.log
329
+
330
+ To view logs in real-time:
331
+ ```bash
332
+ tail -f ~/Library/Logs/Claude/mcp-server-Anki\ MCP\ Server.log
333
+ ```
334
+
335
+ ### Debugging the MCP Server
336
+
337
+ You can debug the MCP server using the MCP Inspector and attaching a debugger from your IDE (WebStorm, VS Code, etc.).
338
+
339
+ #### Step 1: Configure Debug Server in MCP Inspector
340
+
341
+ The `mcp-inspector-config.json` already includes a debug server configuration:
342
+
343
+ ```json
344
+ {
345
+ "mcpServers": {
346
+ "stdio-server-debug": {
347
+ "type": "stdio",
348
+ "command": "node",
349
+ "args": ["--inspect-brk=9229", "dist/main-stdio.js"],
350
+ "env": {
351
+ "MCP_SERVER_NAME": "anki-mcp-stdio-debug",
352
+ "MCP_SERVER_VERSION": "1.0.0",
353
+ "LOG_LEVEL": "debug"
354
+ },
355
+ "note": "Anki MCP server with debugging enabled on port 9229"
356
+ }
357
+ }
358
+ }
359
+ ```
360
+
361
+ #### Step 2: Start the Debug Server
362
+
363
+ Run the MCP Inspector with the debug server:
364
+
365
+ ```bash
366
+ npm run inspector:debug
367
+ ```
368
+
369
+ This will start the server with Node.js debugging enabled on port 9229 and pause execution at the first line.
370
+
371
+ #### Step 3: Attach Debugger from Your IDE
372
+
373
+ ##### WebStorm
374
+ 1. Go to **Run → Edit Configurations**
375
+ 2. Add a new **Attach to Node.js/Chrome** configuration
376
+ 3. Set the port to `9229`
377
+ 4. Click **Debug** to attach
378
+
379
+ ##### VS Code
380
+ 1. Open the Debug panel (Ctrl+Shift+D / Cmd+Shift+D)
381
+ 2. Select **Debug MCP Server (Attach)** configuration
382
+ 3. Press F5 to attach
383
+
384
+ #### Step 4: Set Breakpoints and Debug
385
+
386
+ Once attached, you can:
387
+ - Set breakpoints in your TypeScript source files
388
+ - Step through code execution
389
+ - Inspect variables and call stack
390
+ - Use the debug console for evaluating expressions
391
+
392
+ The debugger will work with source maps, allowing you to debug the original TypeScript code rather than the compiled JavaScript.
393
+
394
+ ### Debugging with Claude Desktop
395
+
396
+ You can also debug the MCP server while it runs inside Claude Desktop by enabling the Node.js debugger and attaching your IDE.
397
+
398
+ #### Step 1: Configure Claude Desktop for Debugging
399
+
400
+ Update your Claude Desktop config to enable debugging:
401
+
402
+ **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
403
+ **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
404
+ **Linux**: `~/.config/Claude/claude_desktop_config.json`
405
+
406
+ ```json
407
+ {
408
+ "mcpServers": {
409
+ "anki-mcp": {
410
+ "command": "node",
411
+ "args": [
412
+ "--inspect=9229",
413
+ "/Users/anatoly/Developer/git/anki-mcp-organization/anki-mcp-desktop/dist/main-stdio.js"
414
+ ],
415
+ "env": {
416
+ "ANKI_CONNECT_URL": "http://localhost:8765"
417
+ }
418
+ }
419
+ }
420
+ }
421
+ ```
422
+
423
+ **Key change**: Add `--inspect=9229` before the path to `dist/main-stdio.js`
424
+
425
+ **Debug options**:
426
+ - `--inspect=9229` - Start debugger immediately, doesn't block (recommended)
427
+ - `--inspect-brk=9229` - Pause execution until debugger attaches (for debugging startup issues)
428
+
429
+ #### Step 2: Restart Claude Desktop
430
+
431
+ After saving the config, restart Claude Desktop. The MCP server will now run with debugging enabled on port 9229.
432
+
433
+ #### Step 3: Attach Debugger from Your IDE
434
+
435
+ ##### WebStorm
436
+
437
+ 1. Go to **Run → Edit Configurations**
438
+ 2. Click the **+** button and select **Attach to Node.js/Chrome**
439
+ 3. Configure:
440
+ - **Name**: `Attach to Anki MCP (Claude Desktop)`
441
+ - **Host**: `localhost`
442
+ - **Port**: `9229`
443
+ - **Attach to**: `Node.js < 8` or `Chrome or Node.js > 6.3` (depending on WebStorm version)
444
+ 4. Click **OK**
445
+ 5. Click **Debug** (Shift+F9) to attach
446
+
447
+ ##### VS Code
448
+
449
+ 1. Add to `.vscode/launch.json`:
450
+
451
+ ```json
452
+ {
453
+ "version": "0.2.0",
454
+ "configurations": [
455
+ {
456
+ "type": "node",
457
+ "request": "attach",
458
+ "name": "Attach to Anki MCP (Claude Desktop)",
459
+ "port": 9229,
460
+ "skipFiles": ["<node_internals>/**"],
461
+ "sourceMaps": true,
462
+ "outFiles": ["${workspaceFolder}/dist/**/*.js"]
463
+ }
464
+ ]
465
+ }
466
+ ```
467
+
468
+ 2. Open the Debug panel (Ctrl+Shift+D / Cmd+Shift+D)
469
+ 3. Select **Attach to Anki MCP (Claude Desktop)**
470
+ 4. Press F5 to attach
471
+
472
+ #### Step 4: Debug in Real-Time
473
+
474
+ Once attached, you can:
475
+ - Set breakpoints in your TypeScript source files (e.g., `src/mcp/primitives/essential/tools/create-model.tool.ts`)
476
+ - Use Claude Desktop normally - breakpoints will hit when tools are invoked
477
+ - Step through code execution
478
+ - Inspect variables and call stack
479
+ - Use the debug console
480
+
481
+ **Example**: Set a breakpoint in `create-model.tool.ts` at line 119, then ask Claude to create a new model. The debugger will pause at your breakpoint!
482
+
483
+ **Note**: The debugger stays attached as long as Claude Desktop is running. You can detach/reattach anytime without restarting Claude Desktop.
484
+
485
+ ### Build Commands
486
+
487
+ ```bash
488
+ npm run build # Build the project (compile TypeScript to JavaScript)
489
+ npm run start:dev:stdio # STDIO mode with watch (auto-rebuild)
490
+ npm run start:dev:http # HTTP mode with watch (auto-rebuild)
491
+ npm run type-check # Run TypeScript type checking
492
+ npm run lint # Run ESLint
493
+ npm run mcpb:bundle # Sync version, clean, build, and create MCPB bundle
494
+ ```
495
+
496
+ ### NPM Package Testing (Local)
497
+
498
+ Test the npm package locally before publishing:
499
+
500
+ ```bash
501
+ # 1. Create local package
502
+ npm run pack:local # Builds and creates anki-mcp-http-*.tgz
503
+
504
+ # 2. Install globally from local package
505
+ npm run install:local # Installs from ./anki-mcp-http-*.tgz
506
+
507
+ # 3. Test the command
508
+ ankimcp # Runs HTTP server on port 3000
509
+
510
+ # 4. Uninstall when done testing
511
+ npm run uninstall:local # Removes global installation
512
+ ```
513
+
514
+ **How it works:**
515
+ - `npm pack` creates a `.tgz` file identical to what npm publish would create
516
+ - Installing from `.tgz` simulates what users get from `npm install -g ankimcp`
517
+ - This lets you test the full user experience before publishing to npm
518
+
519
+ ### Testing Commands
520
+
521
+ ```bash
522
+ npm test # Run all tests
523
+ npm run test:unit # Run unit tests only
524
+ npm run test:tools # Run tool-specific tests
525
+ npm run test:workflows # Run workflow integration tests
526
+ npm run test:e2e # Run end-to-end tests
527
+ npm run test:cov # Run tests with coverage report
528
+ npm run test:watch # Run tests in watch mode
529
+ npm run test:debug # Run tests with debugger
530
+ npm run test:ci # Run tests for CI (silent, with coverage)
531
+ ```
532
+
533
+ ### Test Coverage
534
+
535
+ The project maintains 70% minimum coverage thresholds for:
536
+ - Branches
537
+ - Functions
538
+ - Lines
539
+ - Statements
540
+
541
+ Coverage reports are generated in the `coverage/` directory.
542
+
543
+ ## Versioning
544
+
545
+ This project follows [Semantic Versioning](https://semver.org/) with a pre-1.0 development approach:
546
+
547
+ - **0.x.x** - Beta/Development versions (current phase)
548
+ - **0.1.x** - Bug fixes and patches
549
+ - **0.2.0+** - New features or minor improvements
550
+ - **Breaking changes** are acceptable in 0.x versions
551
+
552
+ - **1.0.0** - First stable release
553
+ - Will be released when the API is stable and tested
554
+ - Breaking changes will require major version bumps (2.0.0, etc.)
555
+
556
+ **Current Status**: `0.1.0` - Initial beta release. The project is functional but APIs may change based on feedback and testing.
557
+
558
+ ## Similar Projects
559
+
560
+ If you're exploring Anki MCP integrations, here are other projects in this space:
561
+
562
+ ### [scorzeth/anki-mcp-server](https://github.com/scorzeth/anki-mcp-server)
563
+ - **Status**: Appears to be abandoned (no recent updates)
564
+ - Early implementation of Anki MCP integration
565
+
566
+ ### [nailuoGG/anki-mcp-server](https://github.com/nailuoGG/anki-mcp-server)
567
+ - **Approach**: Lightweight, single-file implementation
568
+ - **Architecture**: Procedural code structure with all tools in one file
569
+ - **Good for**: Simple use cases, minimal dependencies
570
+
571
+ **Why this project (anki-mcp-desktop) differs:**
572
+ - **Enterprise-grade architecture**: Built on NestJS with dependency injection
573
+ - **Modular design**: Each tool is a separate class with clear separation of concerns
574
+ - **Maintainability**: Easy to extend with new features without touching existing code
575
+ - **Testing**: Comprehensive test suite with 70% coverage requirement
576
+ - **Type safety**: Strict TypeScript with Zod validation
577
+ - **Error handling**: Robust error handling with helpful user feedback
578
+ - **Production-ready**: Proper logging, progress reporting, and MCPB bundle support
579
+ - **Scalability**: Can easily grow from basic tools to complex workflows
580
+
581
+ **Use case**: If you need a solid foundation for building advanced Anki integrations or plan to extend functionality significantly, this project's architectural approach makes it easier to maintain and scale over time.
582
+
583
+ ## Useful Links
584
+
585
+ - [Model Context Protocol Documentation](https://modelcontextprotocol.io/docs)
586
+ - [AnkiConnect API Documentation](https://git.sr.ht/~foosoft/anki-connect)
587
+ - [Claude Desktop Download](https://claude.ai/download)
588
+ - [Building Desktop Extensions (Anthropic Blog)](https://www.anthropic.com/engineering/desktop-extensions)
589
+ - [MCP Servers Repository](https://github.com/modelcontextprotocol/servers)
590
+ - [NestJS Documentation](https://docs.nestjs.com)
591
+ - [Anki Official Website](https://apps.ankiweb.net/)
package/bin/ankimcp.js ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ require('../dist/main-http.js');
@@ -0,0 +1,10 @@
1
+ import { ConfigService } from '@nestjs/config';
2
+ import { IAnkiConfig } from './mcp/config/anki-config.interface';
3
+ export declare class AnkiConfigService implements IAnkiConfig {
4
+ private configService;
5
+ constructor(configService: ConfigService);
6
+ get ankiConnectUrl(): string;
7
+ get ankiConnectApiVersion(): number;
8
+ get ankiConnectApiKey(): string | undefined;
9
+ get ankiConnectTimeout(): number;
10
+ }
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.AnkiConfigService = void 0;
13
+ const common_1 = require("@nestjs/common");
14
+ const config_1 = require("@nestjs/config");
15
+ const mcpb_workarounds_1 = require("./mcp/utils/mcpb-workarounds");
16
+ let AnkiConfigService = class AnkiConfigService {
17
+ configService;
18
+ constructor(configService) {
19
+ this.configService = configService;
20
+ }
21
+ get ankiConnectUrl() {
22
+ return this.configService.get('ANKI_CONNECT_URL', 'http://localhost:8765');
23
+ }
24
+ get ankiConnectApiVersion() {
25
+ const version = this.configService.get('ANKI_CONNECT_API_VERSION', '6');
26
+ return parseInt(version, 10);
27
+ }
28
+ get ankiConnectApiKey() {
29
+ const apiKey = this.configService.get('ANKI_CONNECT_API_KEY');
30
+ return (0, mcpb_workarounds_1.sanitizeMcpbConfigValue)(apiKey);
31
+ }
32
+ get ankiConnectTimeout() {
33
+ const timeout = this.configService.get('ANKI_CONNECT_TIMEOUT', '5000');
34
+ return parseInt(timeout, 10);
35
+ }
36
+ };
37
+ exports.AnkiConfigService = AnkiConfigService;
38
+ exports.AnkiConfigService = AnkiConfigService = __decorate([
39
+ (0, common_1.Injectable)(),
40
+ __metadata("design:paramtypes", [config_1.ConfigService])
41
+ ], AnkiConfigService);
42
+ //# sourceMappingURL=anki-config.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anki-config.service.js","sourceRoot":"","sources":["../src/anki-config.service.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAA4C;AAC5C,2CAA+C;AAE/C,mEAAuE;AAMhE,IAAM,iBAAiB,GAAvB,MAAM,iBAAiB;IACR;IAApB,YAAoB,aAA4B;QAA5B,kBAAa,GAAb,aAAa,CAAe;IAAG,CAAC;IAEpD,IAAI,cAAc;QAChB,OAAO,IAAI,CAAC,aAAa,CAAC,GAAG,CAC3B,kBAAkB,EAClB,uBAAuB,CACxB,CAAC;IACJ,CAAC;IAED,IAAI,qBAAqB;QACvB,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CACpC,0BAA0B,EAC1B,GAAG,CACJ,CAAC;QACF,OAAO,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAC/B,CAAC;IAED,IAAI,iBAAiB;QACnB,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAS,sBAAsB,CAAC,CAAC;QACtE,OAAO,IAAA,0CAAuB,EAAC,MAAM,CAAC,CAAC;IACzC,CAAC;IAED,IAAI,kBAAkB;QACpB,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CACpC,sBAAsB,EACtB,MAAM,CACP,CAAC;QACF,OAAO,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAC/B,CAAC;CACF,CAAA;AA9BY,8CAAiB;4BAAjB,iBAAiB;IAD7B,IAAA,mBAAU,GAAE;qCAEwB,sBAAa;GADrC,iBAAiB,CA8B7B"}
@@ -0,0 +1,5 @@
1
+ import { DynamicModule } from '@nestjs/common';
2
+ export declare class AppModule {
3
+ static forStdio(): DynamicModule;
4
+ static forHttp(): DynamicModule;
5
+ }