@ankimcp/anki-mcp-server 0.18.5 → 0.19.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 (231) hide show
  1. package/README.md +204 -139
  2. package/bin/ankimcp.js +10 -1
  3. package/dist/app-config.service.d.ts +20 -0
  4. package/dist/app-config.service.js +73 -0
  5. package/dist/app-config.service.js.map +1 -0
  6. package/dist/app.module.d.ts +4 -2
  7. package/dist/app.module.js +99 -11
  8. package/dist/app.module.js.map +1 -1
  9. package/dist/bootstrap.d.ts +6 -1
  10. package/dist/bootstrap.js +7 -2
  11. package/dist/bootstrap.js.map +1 -1
  12. package/dist/cli/__tests__/cli-output.manual.d.ts +2 -0
  13. package/dist/cli/__tests__/cli-output.manual.js +14 -0
  14. package/dist/cli/__tests__/cli-output.manual.js.map +1 -0
  15. package/dist/cli/args.d.ts +16 -0
  16. package/dist/{cli.js → cli/args.js} +42 -9
  17. package/dist/cli/args.js.map +1 -0
  18. package/dist/cli/cli-output.d.ts +17 -0
  19. package/dist/cli/cli-output.js +60 -0
  20. package/dist/cli/cli-output.js.map +1 -0
  21. package/dist/cli/index.d.ts +3 -0
  22. package/dist/cli/index.js +20 -0
  23. package/dist/cli/index.js.map +1 -0
  24. package/dist/cli/spinner.d.ts +1 -0
  25. package/dist/cli/spinner.js +16 -0
  26. package/dist/cli/spinner.js.map +1 -0
  27. package/dist/config/config.factory.d.ts +13 -0
  28. package/dist/config/config.factory.js +32 -0
  29. package/dist/config/config.factory.js.map +1 -0
  30. package/dist/config/config.schema.d.ts +31 -0
  31. package/dist/config/config.schema.js +54 -0
  32. package/dist/config/config.schema.js.map +1 -0
  33. package/dist/config/index.d.ts +3 -0
  34. package/dist/config/index.js +11 -0
  35. package/dist/config/index.js.map +1 -0
  36. package/dist/http/guards/origin-validation.guard.d.ts +1 -0
  37. package/dist/http/guards/origin-validation.guard.js +5 -3
  38. package/dist/http/guards/origin-validation.guard.js.map +1 -1
  39. package/dist/main-http.js +23 -11
  40. package/dist/main-http.js.map +1 -1
  41. package/dist/main-stdio.js +10 -9
  42. package/dist/main-stdio.js.map +1 -1
  43. package/dist/main-tunnel.d.ts +1 -0
  44. package/dist/main-tunnel.js +27 -0
  45. package/dist/main-tunnel.js.map +1 -0
  46. package/dist/mcp/clients/anki-connect.client.js +3 -3
  47. package/dist/mcp/clients/anki-connect.client.js.map +1 -1
  48. package/dist/mcp/primitives/essential/index.d.ts +1 -0
  49. package/dist/mcp/primitives/essential/index.js +8 -1
  50. package/dist/mcp/primitives/essential/index.js.map +1 -1
  51. package/dist/mcp/primitives/essential/tools/add-note.tool.d.ts +2 -3
  52. package/dist/mcp/primitives/essential/tools/add-note.tool.js +2 -9
  53. package/dist/mcp/primitives/essential/tools/add-note.tool.js.map +1 -1
  54. package/dist/mcp/primitives/essential/tools/add-notes.tool.d.ts +1 -2
  55. package/dist/mcp/primitives/essential/tools/add-notes.tool.js +2 -23
  56. package/dist/mcp/primitives/essential/tools/add-notes.tool.js.map +1 -1
  57. package/dist/mcp/primitives/essential/tools/add-tags.tool.d.ts +1 -2
  58. package/dist/mcp/primitives/essential/tools/add-tags.tool.js +2 -4
  59. package/dist/mcp/primitives/essential/tools/add-tags.tool.js.map +1 -1
  60. package/dist/mcp/primitives/essential/tools/change-deck.tool.d.ts +1 -2
  61. package/dist/mcp/primitives/essential/tools/change-deck.tool.js +2 -4
  62. package/dist/mcp/primitives/essential/tools/change-deck.tool.js.map +1 -1
  63. package/dist/mcp/primitives/essential/tools/clear-unused-tags.tool.d.ts +1 -2
  64. package/dist/mcp/primitives/essential/tools/clear-unused-tags.tool.js +2 -4
  65. package/dist/mcp/primitives/essential/tools/clear-unused-tags.tool.js.map +1 -1
  66. package/dist/mcp/primitives/essential/tools/collection-stats/collection-stats.tool.d.ts +1 -2
  67. package/dist/mcp/primitives/essential/tools/collection-stats/collection-stats.tool.js +2 -12
  68. package/dist/mcp/primitives/essential/tools/collection-stats/collection-stats.tool.js.map +1 -1
  69. package/dist/mcp/primitives/essential/tools/create-deck.tool.d.ts +1 -2
  70. package/dist/mcp/primitives/essential/tools/create-deck.tool.js +2 -4
  71. package/dist/mcp/primitives/essential/tools/create-deck.tool.js.map +1 -1
  72. package/dist/mcp/primitives/essential/tools/create-model.tool.d.ts +1 -2
  73. package/dist/mcp/primitives/essential/tools/create-model.tool.js +2 -6
  74. package/dist/mcp/primitives/essential/tools/create-model.tool.js.map +1 -1
  75. package/dist/mcp/primitives/essential/tools/deck-stats.tool.d.ts +1 -2
  76. package/dist/mcp/primitives/essential/tools/deck-stats.tool.js +3 -7
  77. package/dist/mcp/primitives/essential/tools/deck-stats.tool.js.map +1 -1
  78. package/dist/mcp/primitives/essential/tools/delete-media-file.tool.d.ts +1 -2
  79. package/dist/mcp/primitives/essential/tools/delete-media-file.tool.js +2 -4
  80. package/dist/mcp/primitives/essential/tools/delete-media-file.tool.js.map +1 -1
  81. package/dist/mcp/primitives/essential/tools/delete-notes.tool.d.ts +2 -3
  82. package/dist/mcp/primitives/essential/tools/delete-notes.tool.js +2 -6
  83. package/dist/mcp/primitives/essential/tools/delete-notes.tool.js.map +1 -1
  84. package/dist/mcp/primitives/essential/tools/find-notes.tool.d.ts +1 -2
  85. package/dist/mcp/primitives/essential/tools/find-notes.tool.js +2 -6
  86. package/dist/mcp/primitives/essential/tools/find-notes.tool.js.map +1 -1
  87. package/dist/mcp/primitives/essential/tools/get-cards.tool.d.ts +1 -2
  88. package/dist/mcp/primitives/essential/tools/get-cards.tool.js +2 -6
  89. package/dist/mcp/primitives/essential/tools/get-cards.tool.js.map +1 -1
  90. package/dist/mcp/primitives/essential/tools/get-due-cards.tool.d.ts +1 -2
  91. package/dist/mcp/primitives/essential/tools/get-due-cards.tool.js +2 -6
  92. package/dist/mcp/primitives/essential/tools/get-due-cards.tool.js.map +1 -1
  93. package/dist/mcp/primitives/essential/tools/get-media-files-names.tool.d.ts +1 -2
  94. package/dist/mcp/primitives/essential/tools/get-media-files-names.tool.js +2 -4
  95. package/dist/mcp/primitives/essential/tools/get-media-files-names.tool.js.map +1 -1
  96. package/dist/mcp/primitives/essential/tools/get-tags.tool.d.ts +1 -2
  97. package/dist/mcp/primitives/essential/tools/get-tags.tool.js +2 -6
  98. package/dist/mcp/primitives/essential/tools/get-tags.tool.js.map +1 -1
  99. package/dist/mcp/primitives/essential/tools/list-decks.tool.d.ts +1 -2
  100. package/dist/mcp/primitives/essential/tools/list-decks.tool.js +2 -4
  101. package/dist/mcp/primitives/essential/tools/list-decks.tool.js.map +1 -1
  102. package/dist/mcp/primitives/essential/tools/model-field-names.tool.d.ts +1 -2
  103. package/dist/mcp/primitives/essential/tools/model-field-names.tool.js +2 -7
  104. package/dist/mcp/primitives/essential/tools/model-field-names.tool.js.map +1 -1
  105. package/dist/mcp/primitives/essential/tools/model-names.tool.d.ts +1 -2
  106. package/dist/mcp/primitives/essential/tools/model-names.tool.js +2 -6
  107. package/dist/mcp/primitives/essential/tools/model-names.tool.js.map +1 -1
  108. package/dist/mcp/primitives/essential/tools/model-styling.tool.d.ts +1 -2
  109. package/dist/mcp/primitives/essential/tools/model-styling.tool.js +2 -6
  110. package/dist/mcp/primitives/essential/tools/model-styling.tool.js.map +1 -1
  111. package/dist/mcp/primitives/essential/tools/notes-info.tool.d.ts +1 -2
  112. package/dist/mcp/primitives/essential/tools/notes-info.tool.js +2 -6
  113. package/dist/mcp/primitives/essential/tools/notes-info.tool.js.map +1 -1
  114. package/dist/mcp/primitives/essential/tools/present-card.tool.d.ts +2 -3
  115. package/dist/mcp/primitives/essential/tools/present-card.tool.js +2 -5
  116. package/dist/mcp/primitives/essential/tools/present-card.tool.js.map +1 -1
  117. package/dist/mcp/primitives/essential/tools/rate-card.tool.d.ts +1 -2
  118. package/dist/mcp/primitives/essential/tools/rate-card.tool.js +2 -5
  119. package/dist/mcp/primitives/essential/tools/rate-card.tool.js.map +1 -1
  120. package/dist/mcp/primitives/essential/tools/remove-tags.tool.d.ts +1 -2
  121. package/dist/mcp/primitives/essential/tools/remove-tags.tool.js +2 -4
  122. package/dist/mcp/primitives/essential/tools/remove-tags.tool.js.map +1 -1
  123. package/dist/mcp/primitives/essential/tools/replace-tags.tool.d.ts +1 -2
  124. package/dist/mcp/primitives/essential/tools/replace-tags.tool.js +2 -4
  125. package/dist/mcp/primitives/essential/tools/replace-tags.tool.js.map +1 -1
  126. package/dist/mcp/primitives/essential/tools/retrieve-media-file.tool.d.ts +1 -2
  127. package/dist/mcp/primitives/essential/tools/retrieve-media-file.tool.js +2 -4
  128. package/dist/mcp/primitives/essential/tools/retrieve-media-file.tool.js.map +1 -1
  129. package/dist/mcp/primitives/essential/tools/review-stats/review-stats.tool.d.ts +1 -2
  130. package/dist/mcp/primitives/essential/tools/review-stats/review-stats.tool.js +2 -8
  131. package/dist/mcp/primitives/essential/tools/review-stats/review-stats.tool.js.map +1 -1
  132. package/dist/mcp/primitives/essential/tools/store-media-file.tool.d.ts +1 -2
  133. package/dist/mcp/primitives/essential/tools/store-media-file.tool.js +2 -4
  134. package/dist/mcp/primitives/essential/tools/store-media-file.tool.js.map +1 -1
  135. package/dist/mcp/primitives/essential/tools/sync.tool.d.ts +1 -2
  136. package/dist/mcp/primitives/essential/tools/sync.tool.js +2 -4
  137. package/dist/mcp/primitives/essential/tools/sync.tool.js.map +1 -1
  138. package/dist/mcp/primitives/essential/tools/update-model-styling.tool.d.ts +2 -3
  139. package/dist/mcp/primitives/essential/tools/update-model-styling.tool.js +2 -6
  140. package/dist/mcp/primitives/essential/tools/update-model-styling.tool.js.map +1 -1
  141. package/dist/mcp/primitives/essential/tools/update-note-fields.tool.d.ts +1 -2
  142. package/dist/mcp/primitives/essential/tools/update-note-fields.tool.js +2 -5
  143. package/dist/mcp/primitives/essential/tools/update-note-fields.tool.js.map +1 -1
  144. package/dist/mcp/primitives/gui/index.d.ts +1 -0
  145. package/dist/mcp/primitives/gui/index.js +8 -1
  146. package/dist/mcp/primitives/gui/index.js.map +1 -1
  147. package/dist/mcp/primitives/gui/tools/gui-add-cards.tool.d.ts +1 -2
  148. package/dist/mcp/primitives/gui/tools/gui-add-cards.tool.js +2 -5
  149. package/dist/mcp/primitives/gui/tools/gui-add-cards.tool.js.map +1 -1
  150. package/dist/mcp/primitives/gui/tools/gui-browse.tool.d.ts +1 -2
  151. package/dist/mcp/primitives/gui/tools/gui-browse.tool.js +2 -4
  152. package/dist/mcp/primitives/gui/tools/gui-browse.tool.js.map +1 -1
  153. package/dist/mcp/primitives/gui/tools/gui-current-card.tool.d.ts +1 -2
  154. package/dist/mcp/primitives/gui/tools/gui-current-card.tool.js +2 -4
  155. package/dist/mcp/primitives/gui/tools/gui-current-card.tool.js.map +1 -1
  156. package/dist/mcp/primitives/gui/tools/gui-deck-browser.tool.d.ts +1 -2
  157. package/dist/mcp/primitives/gui/tools/gui-deck-browser.tool.js +2 -4
  158. package/dist/mcp/primitives/gui/tools/gui-deck-browser.tool.js.map +1 -1
  159. package/dist/mcp/primitives/gui/tools/gui-deck-overview.tool.d.ts +1 -2
  160. package/dist/mcp/primitives/gui/tools/gui-deck-overview.tool.js +2 -4
  161. package/dist/mcp/primitives/gui/tools/gui-deck-overview.tool.js.map +1 -1
  162. package/dist/mcp/primitives/gui/tools/gui-edit-note.tool.d.ts +1 -2
  163. package/dist/mcp/primitives/gui/tools/gui-edit-note.tool.js +2 -4
  164. package/dist/mcp/primitives/gui/tools/gui-edit-note.tool.js.map +1 -1
  165. package/dist/mcp/primitives/gui/tools/gui-select-card.tool.d.ts +1 -2
  166. package/dist/mcp/primitives/gui/tools/gui-select-card.tool.js +2 -4
  167. package/dist/mcp/primitives/gui/tools/gui-select-card.tool.js.map +1 -1
  168. package/dist/mcp/primitives/gui/tools/gui-selected-notes.tool.d.ts +1 -2
  169. package/dist/mcp/primitives/gui/tools/gui-selected-notes.tool.js +2 -4
  170. package/dist/mcp/primitives/gui/tools/gui-selected-notes.tool.js.map +1 -1
  171. package/dist/mcp/primitives/gui/tools/gui-show-answer.tool.d.ts +1 -2
  172. package/dist/mcp/primitives/gui/tools/gui-show-answer.tool.js +2 -4
  173. package/dist/mcp/primitives/gui/tools/gui-show-answer.tool.js.map +1 -1
  174. package/dist/mcp/primitives/gui/tools/gui-show-question.tool.d.ts +1 -2
  175. package/dist/mcp/primitives/gui/tools/gui-show-question.tool.js +2 -4
  176. package/dist/mcp/primitives/gui/tools/gui-show-question.tool.js.map +1 -1
  177. package/dist/mcp/primitives/gui/tools/gui-undo.tool.d.ts +1 -2
  178. package/dist/mcp/primitives/gui/tools/gui-undo.tool.js +2 -4
  179. package/dist/mcp/primitives/gui/tools/gui-undo.tool.js.map +1 -1
  180. package/dist/services/ngrok.service.d.ts +1 -0
  181. package/dist/services/ngrok.service.js +5 -3
  182. package/dist/services/ngrok.service.js.map +1 -1
  183. package/dist/test-fixtures/mock-data.d.ts +8 -0
  184. package/dist/test-fixtures/mock-data.js +8 -0
  185. package/dist/test-fixtures/mock-data.js.map +1 -1
  186. package/dist/tunnel/commands/index.d.ts +3 -0
  187. package/dist/tunnel/commands/index.js +10 -0
  188. package/dist/tunnel/commands/index.js.map +1 -0
  189. package/dist/tunnel/commands/login.command.d.ts +2 -0
  190. package/dist/tunnel/commands/login.command.js +29 -0
  191. package/dist/tunnel/commands/login.command.js.map +1 -0
  192. package/dist/tunnel/commands/logout.command.d.ts +2 -0
  193. package/dist/tunnel/commands/logout.command.js +25 -0
  194. package/dist/tunnel/commands/logout.command.js.map +1 -0
  195. package/dist/tunnel/commands/perform-login.d.ts +9 -0
  196. package/dist/tunnel/commands/perform-login.js +72 -0
  197. package/dist/tunnel/commands/perform-login.js.map +1 -0
  198. package/dist/tunnel/commands/tunnel.command.d.ts +3 -0
  199. package/dist/tunnel/commands/tunnel.command.js +225 -0
  200. package/dist/tunnel/commands/tunnel.command.js.map +1 -0
  201. package/dist/tunnel/credentials.service.d.ts +23 -0
  202. package/dist/tunnel/credentials.service.js +152 -0
  203. package/dist/tunnel/credentials.service.js.map +1 -0
  204. package/dist/tunnel/device-flow.service.d.ts +46 -0
  205. package/dist/tunnel/device-flow.service.js +230 -0
  206. package/dist/tunnel/device-flow.service.js.map +1 -0
  207. package/dist/tunnel/in-memory.transport.d.ts +14 -0
  208. package/dist/tunnel/in-memory.transport.js +63 -0
  209. package/dist/tunnel/in-memory.transport.js.map +1 -0
  210. package/dist/tunnel/index.d.ts +6 -0
  211. package/dist/tunnel/index.js +31 -0
  212. package/dist/tunnel/index.js.map +1 -0
  213. package/dist/tunnel/tunnel-mcp.service.d.ts +15 -0
  214. package/dist/tunnel/tunnel-mcp.service.js +100 -0
  215. package/dist/tunnel/tunnel-mcp.service.js.map +1 -0
  216. package/dist/tunnel/tunnel.client.d.ts +60 -0
  217. package/dist/tunnel/tunnel.client.js +386 -0
  218. package/dist/tunnel/tunnel.client.js.map +1 -0
  219. package/dist/tunnel/tunnel.protocol.d.ts +67 -0
  220. package/dist/tunnel/tunnel.protocol.js +25 -0
  221. package/dist/tunnel/tunnel.protocol.js.map +1 -0
  222. package/dist/version.d.ts +2 -0
  223. package/dist/version.js +21 -0
  224. package/dist/version.js.map +1 -0
  225. package/package.json +31 -22
  226. package/dist/anki-config.service.d.ts +0 -11
  227. package/dist/anki-config.service.js +0 -46
  228. package/dist/anki-config.service.js.map +0 -1
  229. package/dist/cli.d.ts +0 -10
  230. package/dist/cli.js.map +0 -1
  231. package/dist/tsconfig.build.tsbuildinfo +0 -1
package/README.md CHANGED
@@ -1,16 +1,5 @@
1
1
  # Anki MCP Server
2
2
 
3
- > **⚠️ IMPORTANT: Project Renamed (v0.8.2+)**
4
- >
5
- > This project has been renamed and moved:
6
- > - **Package**: `anki-mcp-http` → `@ankimcp/anki-mcp-server`
7
- > - **Commands**: `anki-mcp-http` → `ankimcp` or `anki-mcp-server`
8
- > - **Repository**: `anki-mcp/anki-mcp-desktop` → `ankimcp/anki-mcp-server`
9
- >
10
- > The old `anki-mcp-http` package continues to be published for backward compatibility but is deprecated. Please migrate to the new package.
11
- >
12
- > **[Read more about this change →](https://ankimcp.ai/blog/organization-and-naming-update/)**
13
-
14
3
  [![Tests](https://github.com/ankimcp/anki-mcp-server/actions/workflows/test.yml/badge.svg)](https://github.com/ankimcp/anki-mcp-server/actions/workflows/test.yml)
15
4
  [![npm version](https://badge.fury.io/js/@ankimcp%2Fanki-mcp-server.svg)](https://www.npmjs.com/package/@ankimcp/anki-mcp-server)
16
5
 
@@ -46,38 +35,43 @@ Three representative prompts showing the tool flows this server enables:
46
35
 
47
36
  ## Available Tools
48
37
 
49
- ### Review & Study
50
- - `sync` - Sync with AnkiWeb
51
- - `get_due_cards` - Get cards for review
52
- - `present_card` - Show card for review
53
- - `rate_card` - Rate card performance
54
-
55
- ### Deck Management
56
- - `listDecks` - List all decks with optional statistics
57
- - `deckStats` - Get comprehensive deck statistics (counts, ease/interval distributions)
58
- - `createDeck` - Create a new empty deck (max 2 levels: "Parent::Child")
59
- - `changeDeck` - Move cards to a different deck
60
-
61
- ### Note Management
62
- - `addNote` - Create a single note
63
- - `addNotes` - Create multiple notes in batch (up to 100, partial success supported)
64
- - `findNotes` - Search for notes using Anki query syntax
65
- - `notesInfo` - Get detailed information about notes (fields, tags, CSS)
66
- - `updateNoteFields` - Update existing note fields (CSS-aware, supports HTML)
67
- - `deleteNotes` - Delete notes and their cards
68
-
69
- ### Tag Management
70
- - `getTags` - Discover all tags in the collection (use first to avoid duplication)
71
- - `addTags` - Add space-separated tags to notes
72
- - `removeTags` - Remove space-separated tags from notes
73
- - `replaceTags` - Rename a tag across notes
74
- - `clearUnusedTags` - Remove orphaned tags from the collection (destructive)
75
-
76
- ### Media Management
77
- - `getMediaFilesNames` - List media files with optional pattern filtering
78
- - `retrieveMediaFile` - Download media as base64
79
- - `storeMediaFile` - Upload media from base64 data, file paths, or URLs
80
- - `deleteMediaFile` - Remove media files (destructive)
38
+ The server exposes **42 MCP tools** — 31 essential tools for everyday Anki operations and 11 GUI tools that drive the Anki desktop interface for note editing/creation workflows.
39
+
40
+ ### Essential Tools
41
+
42
+ #### Review & Study
43
+ - `sync` - Sync with AnkiWeb to pull latest data and push changes
44
+ - `get_due_cards` - Get cards that are due for review, optionally filtered by deck
45
+ - `get_cards` - Get cards with flexible filtering by state (due, new, learning, suspended, buried) and deck
46
+ - `present_card` - Show a card for review with its question/front side
47
+ - `rate_card` - Rate card performance (Again, Hard, Good, Easy) and schedule the next review
48
+
49
+ #### Deck Management
50
+ - `listDecks` - List all decks, optionally with per-deck card-count statistics
51
+ - `deckStats` - Get comprehensive statistics for a single deck (counts, ease/interval distributions)
52
+ - `createDeck` - Create a new empty deck (supports `Parent::Child`, max 2 levels)
53
+ - `changeDeck` - Move cards to a different deck (created if it doesn't exist)
54
+
55
+ #### Note Management
56
+ - `addNote` - Create a single note with specified fields and tags
57
+ - `addNotes` - Batch-create up to 100 notes sharing a deck and model (partial success supported)
58
+ - `findNotes` - Search for notes using Anki query syntax (`deck:`, `tag:`, `is:due`, etc.)
59
+ - `notesInfo` - Get detailed information about notes (fields, tags, CSS styling)
60
+ - `updateNoteFields` - Update existing note fields (CSS-aware, supports HTML content)
61
+ - `deleteNotes` - Delete notes and all associated cards (destructive, requires confirmation)
62
+
63
+ #### Tag Management
64
+ - `getTags` - Get all tags in the collection (use first to avoid duplication)
65
+ - `addTags` - Add space-separated tags to specified notes
66
+ - `removeTags` - Remove space-separated tags from specified notes
67
+ - `replaceTags` - Rename a tag across specified notes
68
+ - `clearUnusedTags` - Remove orphaned tags not used by any notes (destructive)
69
+
70
+ #### Media Management
71
+ - `getMediaFilesNames` - List media files in `collection.media`, optionally filtered by pattern
72
+ - `retrieveMediaFile` - Download a media file as base64 content
73
+ - `storeMediaFile` - Upload media from base64 data, an absolute file path, or a URL
74
+ - `deleteMediaFile` - Remove a media file from `collection.media` (destructive)
81
75
 
82
76
  **💡 Best Practice for Images:**
83
77
  - ✅ **Use file paths** (e.g., `/Users/you/image.png`) - Fast and efficient
@@ -86,31 +80,66 @@ Three representative prompts showing the tool flows this server enables:
86
80
 
87
81
  Just tell Claude where the image is, and it will handle the upload automatically using the most efficient method.
88
82
 
89
- ### Model/Template Management
90
- - `modelNames` - List note types
91
- - `modelFieldNames` - Get fields for a note type
92
- - `modelStyling` - Get CSS styling for a note type
83
+ #### Model/Template Management
84
+ - `modelNames` - List all available note types/models
85
+ - `modelFieldNames` - Get field names for a specific note type
86
+ - `modelStyling` - Get CSS styling information for a note type
87
+ - `createModel` - Create a new note type with custom fields, card templates, and CSS (e.g., RTL models)
88
+ - `updateModelStyling` - Update the CSS styling for an existing note type (applies to all its cards)
89
+
90
+ #### Statistics
91
+ - `collection_stats` - Aggregated statistics across all decks with per-deck breakdown
92
+ - `review_stats` - Review history analysis (temporal patterns, retention metrics, study streaks)
93
+
94
+ ### GUI Tools
95
+
96
+ Tools that drive the Anki desktop interface. Intended for note editing/creation and deck-management workflows, **not** for review sessions.
97
+
98
+ - `guiBrowse` - Open the Card Browser and search for cards
99
+ - `guiSelectCard` - Select a specific card in the Card Browser
100
+ - `guiSelectedNotes` - Get IDs of notes currently selected in the Card Browser
101
+ - `guiAddCards` - Open the Add Cards dialog with preset note details
102
+ - `guiEditNote` - Open the note editor for a specific note
103
+ - `guiDeckOverview` - Open the Deck Overview dialog for a specific deck
104
+ - `guiDeckBrowser` - Open the Deck Browser dialog
105
+ - `guiCurrentCard` - Get info about the current card in review mode
106
+ - `guiShowQuestion` - Show the question side of the current card
107
+ - `guiShowAnswer` - Show the answer side of the current card
108
+ - `guiUndo` - Undo the last action in Anki
93
109
 
94
110
  ## Prerequisites
95
111
 
96
112
  - [Anki](https://apps.ankiweb.net/) with [AnkiConnect](https://github.com/FooSoft/anki-connect) plugin installed
97
- - Node.js 20.19.0+
113
+ - Node.js 22.12.0+
98
114
 
99
115
  ## Installation
100
116
 
101
- This server works in two modes:
117
+ There are a few ways to get the server onto your machine. Once it's installed, head to [Connecting an AI Client](#connecting-an-ai-client) to wire it up to your AI assistant — locally or remotely.
118
+
119
+ ### npm (global or npx)
120
+
121
+ The general-purpose way to install the server, suitable for any MCP client that launches it directly.
102
122
 
103
- - **Local mode (STDIO)** - For Claude Desktop on your computer (recommended for most users)
104
- - **Remote mode (HTTP)** - For web-based AI assistants like ChatGPT or Claude.ai
123
+ Install it globally for clients that run the `ankimcp` command:
124
+
125
+ ```bash
126
+ npm install -g @ankimcp/anki-mcp-server
127
+ ```
128
+
129
+ Or run it on demand with no install required:
130
+
131
+ ```bash
132
+ npx @ankimcp/anki-mcp-server
133
+ ```
105
134
 
106
- ### Option 1: MCPB Bundle (Recommended - Local Mode)
135
+ ### MCPB Bundle (Recommended for Claude Desktop)
107
136
 
108
137
  The easiest way to install this MCP server for Claude Desktop:
109
138
 
110
139
  1. Download the latest `.mcpb` bundle from the [Releases](https://github.com/ankimcp/anki-mcp-server/releases) page
111
140
  2. In Claude Desktop, install the extension:
112
- - **Method 1**: Go to Settings → Extensions, then drag and drop the `.mcpb` file
113
- - **Method 2**: Go to Settings → Developer → Extensions → Install Extension, then select the `.mcpb` file
141
+ - **Method 1**: Go to Settings → Extensions, then drag and drop the `.mcpb` file
142
+ - **Method 2**: Go to Settings → Developer → Extensions → Install Extension, then select the `.mcpb` file
114
143
  3. Configure AnkiConnect URL if needed (defaults to `http://localhost:8765`)
115
144
  4. Restart Claude Desktop
116
145
 
@@ -118,16 +147,39 @@ That's it! The bundle includes everything needed to run the server locally.
118
147
 
119
148
  > **For Anthropic MCP Directory reviewers:** a zero-to-integration walkthrough with a pre-populated sample deck lives in [`docs/reviewer-setup.md`](./docs/reviewer-setup.md).
120
149
 
121
- ### Option 2: NPM Package with STDIO (For Other MCP Clients)
150
+ ### Install from Source (for development)
151
+
152
+ For development or advanced usage:
153
+
154
+ ```bash
155
+ npm install
156
+ npm run build
157
+ ```
158
+
159
+ ## Connecting an AI Client
160
+
161
+ There are two ways an AI assistant can reach this server, depending on where the assistant runs:
162
+
163
+ - **[Local](#local)** — the server runs on the same machine as the AI client (Claude Desktop, Cursor, Cline, Zed, or a local browser session). Use **STDIO** for desktop MCP clients, **HTTP** for local web-based tools.
164
+ - **[Remote](#remote)** — a hosted/remote AI (e.g. ChatGPT or Claude.ai in the cloud) needs to reach the Anki running on your local machine. Use the managed **Tunnel** (✅ recommended — authenticated) or, as a lighter-weight unauthenticated alternative, **ngrok**.
122
165
 
123
- Want to use Anki with MCP clients like **Cursor IDE**, **Cline**, or **Zed Editor**? Use the npm package with the `--stdio` flag:
166
+ ### Local
167
+
168
+ The server runs on the same computer as your AI client and talks to AnkiConnect on `localhost`.
169
+
170
+ #### STDIO (primary local integration)
171
+
172
+ STDIO is the standard transport for local desktop MCP clients — **Claude Desktop**, **Cursor IDE**, **Cline**, **Zed Editor**, and others. The client launches the server as a subprocess and communicates over standard input/output.
124
173
 
125
174
  **Supported Clients:**
175
+ - [Claude Desktop](https://claude.ai/download)
126
176
  - [Cursor IDE](https://www.cursor.com/) - AI-powered code editor
127
177
  - [Cline](https://github.com/cline/cline) - VS Code extension for AI assistance
128
178
  - [Zed Editor](https://zed.dev/) - Fast, modern code editor
129
179
  - Other MCP clients that support STDIO transport
130
180
 
181
+ For Claude Desktop, the [MCPB bundle](#mcpb-bundle-recommended-for-claude-desktop) is the easiest path. For other clients, configure the npm package with the `--stdio` flag.
182
+
131
183
  **Configuration - Choose one method:**
132
184
 
133
185
  **Method 1: Using npx (recommended - no installation needed)**
@@ -173,19 +225,11 @@ Then configure:
173
225
  - **Cline**: Accessible via settings UI in VS Code
174
226
  - **Zed Editor**: Install as MCP extension through extension marketplace
175
227
 
176
- For client-specific features and troubleshooting, consult your MCP client's documentation.
177
-
178
- ### Option 3: HTTP Mode (For Remote AI Assistants)
179
-
180
- 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.
228
+ For client-specific features and troubleshooting, consult your MCP client's documentation. See also [Connect to Claude Desktop](#connect-to-claude-desktop-local-mode) for a config that points directly at a built `dist/main-stdio.js`.
181
229
 
182
- **How it works (simple explanation):**
183
- 1. You run a small server on your computer (where Anki is installed)
184
- 2. Use the built-in `--ngrok` flag to automatically create a public tunnel URL
185
- 3. Share that URL with ChatGPT or Claude.ai
186
- 4. Now the AI can talk to your Anki through the internet!
230
+ #### HTTP (local web-based AI)
187
231
 
188
- **New in v0.8.0:** Integrated ngrok support with the `--ngrok` flag - no need to run ngrok separately!
232
+ HTTP mode runs the server as a local web server speaking the MCP Streamable HTTP protocol. It's the transport a web-based AI tool talks to when pointed at your machine, and it's also what the [Remote](#remote) options expose to the outside world. On its own, HTTP mode binds to `localhost` only.
189
233
 
190
234
  **Setup - Choose one method:**
191
235
 
@@ -195,9 +239,6 @@ Want to use Anki with ChatGPT or Claude.ai in your browser? This mode lets you c
195
239
  # Quick start
196
240
  npx @ankimcp/anki-mcp-server
197
241
 
198
- # With ngrok tunnel (recommended for web-based AI)
199
- npx @ankimcp/anki-mcp-server --ngrok
200
-
201
242
  # With custom options
202
243
  npx @ankimcp/anki-mcp-server --port 8080 --host 0.0.0.0
203
244
  npx @ankimcp/anki-mcp-server --anki-connect http://localhost:8765
@@ -212,9 +253,6 @@ npm install -g @ankimcp/anki-mcp-server
212
253
  # Run the server
213
254
  ankimcp
214
255
 
215
- # With ngrok tunnel (recommended for web-based AI)
216
- ankimcp --ngrok
217
-
218
256
  # With custom options
219
257
  ankimcp --port 8080 --host 0.0.0.0
220
258
  ankimcp --anki-connect http://localhost:8765
@@ -228,13 +266,76 @@ npm run build
228
266
  npm run start:prod:http
229
267
  ```
230
268
 
231
- **CLI Options:**
269
+ To make a local HTTP server reachable by a cloud-hosted AI, use one of the [Remote](#remote) options below.
270
+
271
+ ### Remote
272
+
273
+ A hosted/remote AI (such as ChatGPT or Claude.ai running in the cloud) can't reach `localhost` directly. These options expose your **local** Anki to the internet so a remote assistant can talk to it.
274
+
275
+ #### Tunnel (✅ Recommended)
276
+
277
+ > **Recommended remote path — authenticated & secure.** Unlike a raw public port, tunnel mode requires you to log in (OAuth 2.0 device flow), so the endpoint isn't open to anyone who guesses the URL.
278
+
279
+ Tunnel mode lets web-based AI assistants reach your **local** Anki without running your own tunnel. The server connects out to the managed AnkiMCP tunnel service (`wss://tunnel.ankimcp.ai`) over a WebSocket and is assigned a public URL. Authentication is built in — no ngrok account or separate tunnel process required, and you log in once.
280
+
281
+ **Log in (OAuth device flow):**
282
+
283
+ Tunnel mode uses the OAuth 2.0 Device Authorization Grant. Logging in opens your browser automatically to an approval page with the code already embedded in the URL — nothing to type, just approve. (If the browser can't open, the terminal prints a verification URL and code to enter manually as a fallback.) On success, credentials are saved to `~/.ankimcp/credentials.json` (file permissions `0600`).
284
+
285
+ ```bash
286
+ # Pre-authenticate (optional — --tunnel will trigger this automatically if needed)
287
+ ankimcp --login
288
+ npx @ankimcp/anki-mcp-server --login
289
+
290
+ # Clear saved credentials
291
+ ankimcp --logout
292
+ ```
293
+
294
+ **Start the tunnel:**
295
+
296
+ ```bash
297
+ # Connect to the managed tunnel service (wss://tunnel.ankimcp.ai)
298
+ ankimcp --tunnel
299
+ npx @ankimcp/anki-mcp-server --tunnel
300
+
301
+ # Override the tunnel server URL (must be ws:// or wss://) — e.g. for self-hosting
302
+ ankimcp --tunnel wss://my-tunnel.example.com
303
+ ```
304
+
305
+ If no credentials exist, `--tunnel` automatically starts the login flow first, then continues to the tunnel. This auto-login requires an interactive terminal — when stdout is not a TTY (systemd, headless Docker, CI), the server fast-fails and asks you to run `ankimcp --login` first. Once connected, the public tunnel URL is printed; press Ctrl+C to disconnect. Share that URL with your AI assistant.
306
+
307
+ **Tunnel-mode environment variables:**
308
+
309
+ | Variable | Description | Default |
310
+ |----------|-------------|---------|
311
+ | `TUNNEL_SERVER_URL` | Tunnel server WebSocket URL (the `--tunnel`/`--login` flag value overrides this) | `wss://tunnel.ankimcp.ai` |
312
+ | `TUNNEL_AUTH_CLIENT_ID` | OAuth client ID for the device flow. Advanced — only needed when pointing at a self-hosted tunnel/auth service. | (built-in) |
313
+
314
+ The device-flow auth endpoints (`/auth/device`, `/auth/token`) are derived from `TUNNEL_SERVER_URL`, so pointing `--tunnel` (or `TUNNEL_SERVER_URL`) at a different host also moves authentication to that host.
315
+
316
+ **How it works:** Tunnel mode runs the MCP server in-process behind an in-memory transport (`McpModule` is started with no built-in transport). `TunnelMcpService` connects that in-memory transport to the MCP server, and `TunnelClient` bridges it to the remote tunnel service over a WebSocket — relaying MCP requests in and responses out. AnkiConnect is still only ever reached on your local machine.
317
+
318
+ #### ngrok (unauthenticated alternative)
319
+
320
+ If you'd rather expose [local HTTP mode](#http-local-web-based-ai) publicly without an account on the managed tunnel, the built-in `--ngrok` flag launches an [ngrok](https://ngrok.com/) subprocess (`src/services/ngrok.service.ts`) and prints the public URL in the startup banner:
321
+
322
+ ```bash
323
+ # One-time ngrok setup, then:
324
+ ankimcp --ngrok
325
+ ```
326
+
327
+ This route is **unauthenticated** — anyone with the URL can reach your Anki, so it's less secure than [Tunnel](#tunnel--recommended). Prefer Tunnel unless you have a specific reason to manage your own ngrok endpoint. (Requires a global ngrok install and authtoken; the manual two-terminal `ngrok http 3000` setup works too.)
328
+
329
+ ### CLI Options (all modes)
232
330
 
233
331
  ```bash
234
332
  ankimcp [options]
235
333
 
236
334
  Options:
237
335
  --stdio Run in STDIO mode (for MCP clients)
336
+ --tunnel [url] Connect via the managed tunnel (authenticated)
337
+ --login Authenticate for tunnel mode (OAuth device flow)
338
+ --logout Clear saved tunnel credentials
238
339
  -p, --port <port> Port to listen on (HTTP mode, default: 3000)
239
340
  -h, --host <host> Host to bind to (HTTP mode, default: 127.0.0.1)
240
341
  -a, --anki-connect <url> AnkiConnect URL (default: http://localhost:8765)
@@ -246,6 +347,7 @@ Usage with npx (no installation needed):
246
347
  npx @ankimcp/anki-mcp-server # HTTP mode
247
348
  npx @ankimcp/anki-mcp-server --port 8080 # Custom port
248
349
  npx @ankimcp/anki-mcp-server --stdio # STDIO mode
350
+ npx @ankimcp/anki-mcp-server --tunnel # Managed tunnel mode
249
351
  npx @ankimcp/anki-mcp-server --ngrok # HTTP mode with ngrok tunnel
250
352
  npx @ankimcp/anki-mcp-server --read-only # Read-only mode
251
353
 
@@ -254,11 +356,12 @@ Usage with global installation:
254
356
  ankimcp # HTTP mode
255
357
  ankimcp --port 8080 # Custom port
256
358
  ankimcp --stdio # STDIO mode
359
+ ankimcp --tunnel # Managed tunnel mode
257
360
  ankimcp --ngrok # HTTP mode with ngrok tunnel
258
361
  ankimcp --read-only # Read-only mode
259
362
  ```
260
363
 
261
- **Read-Only Mode:**
364
+ ### Read-Only Mode (all modes)
262
365
 
263
366
  The `--read-only` flag prevents any modifications to your Anki collection. When enabled:
264
367
  - All read operations work normally (browsing decks, viewing cards, searching notes)
@@ -297,53 +400,6 @@ Or in MCP client configuration:
297
400
  }
298
401
  ```
299
402
 
300
- **Using with ngrok:**
301
-
302
- **Method 1: Integrated (Recommended - One Command)**
303
-
304
- ```bash
305
- # One-time setup (if you haven't already):
306
- npm install -g ngrok
307
- ngrok config add-authtoken <your-token> # Get token from https://dashboard.ngrok.com
308
-
309
- # Start server with ngrok tunnel in one command:
310
- ankimcp --ngrok
311
-
312
- # The tunnel URL will be displayed in the startup banner
313
- # Example output:
314
- # 🌐 Ngrok tunnel: https://abc123.ngrok-free.app
315
- ```
316
-
317
- **Method 2: Manual (Two Terminals)**
318
-
319
- ```bash
320
- # Terminal 1: Start the server
321
- ankimcp
322
-
323
- # Terminal 2: Create tunnel
324
- ngrok http 3000
325
-
326
- # Copy the ngrok URL (looks like: https://abc123.ngrok-free.app)
327
- # Share this URL with your AI assistant
328
- ```
329
-
330
- **Benefits of `--ngrok` flag:**
331
- - ✅ One command instead of two terminals
332
- - ✅ Automatic cleanup when you press Ctrl+C
333
- - ✅ URL displayed directly in the startup banner
334
- - ✅ Works with custom ports: `ankimcp --port 8080 --ngrok`
335
-
336
- **Security note:** Anyone with your ngrok URL can access your Anki, so keep that URL private!
337
-
338
- ### Option 4: Manual Installation from Source (Local Mode)
339
-
340
- For development or advanced usage:
341
-
342
- ```bash
343
- npm install
344
- npm run build
345
- ```
346
-
347
403
  ## Connect to Claude Desktop (Local Mode)
348
404
 
349
405
  You can configure the server in Claude Desktop by either:
@@ -387,6 +443,7 @@ For more details, see the [official MCP documentation](https://modelcontextproto
387
443
  | `ANKI_CONNECT_API_KEY` | API key if configured in AnkiConnect | - |
388
444
  | `ANKI_CONNECT_TIMEOUT` | Request timeout in ms | `5000` |
389
445
  | `READ_ONLY` | Enable read-only mode (`true` or `1`) | `false` |
446
+ | `TUNNEL_SERVER_URL` | Tunnel server WebSocket URL (tunnel mode only) | `wss://tunnel.ankimcp.ai` |
390
447
  | `MEDIA_ALLOWED_TYPES` | Extra MIME types to allow for file path imports (comma-separated, e.g., `application/pdf`) | - |
391
448
  | `MEDIA_IMPORT_DIR` | Restrict file path imports to this directory | - |
392
449
  | `MEDIA_ALLOWED_HOSTS` | Allow specific private network hosts for URL imports (comma-separated, e.g., `192.168.1.50,my-nas`) | - |
@@ -493,22 +550,22 @@ If you see an error like:
493
550
  Error [ERR_REQUIRE_ESM]: require() of ES Module not supported
494
551
  ```
495
552
 
496
- This means your Node.js version is not supported. The server requires **Node.js 20.19.0+ or 22.12.0+**.
553
+ This means your Node.js version is not supported. The server requires **Node.js 22.12.0+**.
497
554
 
498
- > **Note:** Node.js 21.x is not supported. The `require(esm)` feature was added in Node 22 and backported to Node 20.17+, but was never available in Node 21. See [#16](https://github.com/ankimcp/anki-mcp-server/issues/16) for details.
555
+ > **Note:** The minimum supported runtime is Node.js 22.12.0. Node.js 20 (Iron) reached end-of-life on 2026-04-30 and is no longer supported.
499
556
 
500
557
  **Check your version:**
501
558
  ```bash
502
559
  node --version
503
560
  ```
504
561
 
505
- **Solution:** Update Node.js to version 20.19.0+ or 22.12.0+. You can download it from [nodejs.org](https://nodejs.org/) or use a version manager like [nvm](https://github.com/nvm-sh/nvm).
562
+ **Solution:** Update Node.js to version 22.12.0+. You can download it from [nodejs.org](https://nodejs.org/) or use a version manager like [nvm](https://github.com/nvm-sh/nvm).
506
563
 
507
564
  ## Development
508
565
 
509
566
  ### Transport Modes
510
567
 
511
- This server supports two MCP transport modes via **separate entry points**:
568
+ This server supports three MCP transport modes via **separate entry points**:
512
569
 
513
570
  #### STDIO Mode (Default)
514
571
  - For local MCP clients like Claude Desktop
@@ -526,13 +583,21 @@ This server supports two MCP transport modes via **separate entry points**:
526
583
  - **Default host**: `127.0.0.1` (configurable via `HOST` env var)
527
584
  - **MCP endpoint**: `http://127.0.0.1:3000/` (root path)
528
585
 
586
+ #### Tunnel Mode (Managed WebSocket Tunnel)
587
+ - For web-based AI assistants via the managed AnkiMCP tunnel service, with built-in authentication
588
+ - The MCP server runs in-process behind an in-memory transport; `TunnelMcpService` wires it to the MCP server and `TunnelClient` bridges it to the tunnel service over a WebSocket
589
+ - **Entry point**: `dist/main-tunnel.js`
590
+ - **Run**: `node dist/main-tunnel.js --tunnel` (or `ankimcp --tunnel`)
591
+ - **Auth**: `ankimcp --login` / `ankimcp --logout`; credentials stored at `~/.ankimcp/credentials.json` (`0600`)
592
+ - **Dev**: `npm run start:dev:tunnel` (watch mode, runs `--tunnel --debug`)
593
+
529
594
  #### Building
530
595
 
531
596
  ```bash
532
- npm run build # Builds once, creates dist/ with both entry points
597
+ npm run build # Builds once, creates dist/ with all three entry points
533
598
  ```
534
599
 
535
- Both `main-stdio.js` and `main-http.js` are in the same `dist/` directory. Choose which to run based on your needs.
600
+ `main-stdio.js`, `main-http.js`, and `main-tunnel.js` are all built into the same `dist/` directory. Choose which to run based on your needs.
536
601
 
537
602
  #### HTTP Mode Configuration
538
603
 
@@ -586,7 +651,7 @@ The output file will be named `anki-mcp-server-X.X.X.mcpb` and can be distribute
586
651
  #### What Gets Bundled
587
652
 
588
653
  The MCPB bundle includes:
589
- - Compiled JavaScript (`dist/` directory - includes both entry points)
654
+ - Compiled JavaScript (`dist/` directory - includes all three entry points)
590
655
  - Production dependencies only (`node_modules/` - devDependencies removed by `mcpb clean`)
591
656
  - Package metadata (`package.json`)
592
657
  - Manifest configuration (`manifest.json` - configured to use `main-stdio.js`)
@@ -721,10 +786,10 @@ After saving the config, restart Claude Desktop. The MCP server will now run wit
721
786
  1. Go to **Run → Edit Configurations**
722
787
  2. Click the **+** button and select **Attach to Node.js/Chrome**
723
788
  3. Configure:
724
- - **Name**: `Attach to Anki MCP (Claude Desktop)`
725
- - **Host**: `localhost`
726
- - **Port**: `9229`
727
- - **Attach to**: `Node.js < 8` or `Chrome or Node.js > 6.3` (depending on WebStorm version)
789
+ - **Name**: `Attach to Anki MCP (Claude Desktop)`
790
+ - **Host**: `localhost`
791
+ - **Port**: `9229`
792
+ - **Attach to**: `Node.js < 8` or `Chrome or Node.js > 6.3` (depending on WebStorm version)
728
793
  4. Click **OK**
729
794
  5. Click **Debug** (Shift+F9) to attach
730
795
 
@@ -829,15 +894,15 @@ Coverage reports are generated in the `coverage/` directory.
829
894
  This project follows [Semantic Versioning](https://semver.org/) with a pre-1.0 development approach:
830
895
 
831
896
  - **0.x.x** - Beta/Development versions (current phase)
832
- - **0.1.x** - Bug fixes and patches
833
- - **0.2.0+** - New features or minor improvements
834
- - **Breaking changes** are acceptable in 0.x versions
897
+ - **0.1.x** - Bug fixes and patches
898
+ - **0.2.0+** - New features or minor improvements
899
+ - **Breaking changes** are acceptable in 0.x versions
835
900
 
836
901
  - **1.0.0** - First stable release
837
- - Will be released when the API is stable and tested
838
- - Breaking changes will require major version bumps (2.0.0, etc.)
902
+ - Will be released when the API is stable and tested
903
+ - Breaking changes will require major version bumps (2.0.0, etc.)
839
904
 
840
- **Current Status**: `0.15.1` - Active beta development. Recent features include batch note creation (`addNotes`), integrated ngrok tunneling (`--ngrok` flag), media file management, model/template management, and comprehensive deck statistics. APIs may change based on feedback and testing.
905
+ **Current Status**: `0.19.0` - Active beta development. Recent features include batch note creation (`addNotes`), integrated ngrok tunneling (`--ngrok` flag), media file management, model/template management, and comprehensive deck statistics. APIs may change based on feedback and testing.
841
906
 
842
907
  ### MCPB spec evolution
843
908
 
package/bin/ankimcp.js CHANGED
@@ -16,12 +16,21 @@ if (
16
16
  process.exit(1);
17
17
  }
18
18
 
19
- // Check if --stdio flag is present
19
+ // Determine mode based on CLI flags
20
20
  const isStdioMode = process.argv.includes('--stdio');
21
+ const isTunnelMode = process.argv.some(arg =>
22
+ arg === '--tunnel' ||
23
+ arg.startsWith('--tunnel=') ||
24
+ arg === '--login' ||
25
+ arg === '--logout'
26
+ );
21
27
 
22
28
  if (isStdioMode) {
23
29
  // STDIO mode - for MCP clients like Cursor, Cline, Zed, etc.
24
30
  require('../dist/main-stdio.js');
31
+ } else if (isTunnelMode) {
32
+ // Tunnel mode - for remote MCP access via tunnel service
33
+ require('../dist/main-tunnel.js');
25
34
  } else {
26
35
  // HTTP mode (default) - for web-based AI assistants
27
36
  require('../dist/main-http.js');
@@ -0,0 +1,20 @@
1
+ import { IAnkiConfig } from "./mcp/config/anki-config.interface";
2
+ import type { AppConfig } from "./config";
3
+ export declare class AppConfigService implements IAnkiConfig {
4
+ private readonly config;
5
+ constructor(config: AppConfig);
6
+ get port(): number;
7
+ get host(): string;
8
+ get nodeEnv(): "development" | "production" | "test";
9
+ get isDevelopment(): boolean;
10
+ get isProduction(): boolean;
11
+ get isTest(): boolean;
12
+ get ankiConnectUrl(): string;
13
+ get ankiConnectApiVersion(): number;
14
+ get ankiConnectApiKey(): string | undefined;
15
+ get ankiConnectTimeout(): number;
16
+ get readOnly(): boolean;
17
+ get authClientId(): string;
18
+ get tunnelServerUrl(): string;
19
+ get logLevel(): "debug" | "info" | "warn" | "error";
20
+ }
@@ -0,0 +1,73 @@
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
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.AppConfigService = void 0;
16
+ const common_1 = require("@nestjs/common");
17
+ const config_1 = require("./config");
18
+ const mcpb_workarounds_1 = require("./mcp/utils/mcpb-workarounds");
19
+ let AppConfigService = class AppConfigService {
20
+ config;
21
+ constructor(config) {
22
+ this.config = config;
23
+ }
24
+ get port() {
25
+ return this.config.port;
26
+ }
27
+ get host() {
28
+ return this.config.host;
29
+ }
30
+ get nodeEnv() {
31
+ return this.config.nodeEnv;
32
+ }
33
+ get isDevelopment() {
34
+ return this.nodeEnv === "development";
35
+ }
36
+ get isProduction() {
37
+ return this.nodeEnv === "production";
38
+ }
39
+ get isTest() {
40
+ return this.nodeEnv === "test";
41
+ }
42
+ get ankiConnectUrl() {
43
+ return this.config.ankiConnect.url;
44
+ }
45
+ get ankiConnectApiVersion() {
46
+ return this.config.ankiConnect.apiVersion;
47
+ }
48
+ get ankiConnectApiKey() {
49
+ return (0, mcpb_workarounds_1.sanitizeMcpbConfigValue)(this.config.ankiConnect.apiKey);
50
+ }
51
+ get ankiConnectTimeout() {
52
+ return this.config.ankiConnect.timeout;
53
+ }
54
+ get readOnly() {
55
+ return this.config.readOnly;
56
+ }
57
+ get authClientId() {
58
+ return this.config.auth.clientId;
59
+ }
60
+ get tunnelServerUrl() {
61
+ return this.config.tunnel.serverUrl;
62
+ }
63
+ get logLevel() {
64
+ return this.config.logLevel;
65
+ }
66
+ };
67
+ exports.AppConfigService = AppConfigService;
68
+ exports.AppConfigService = AppConfigService = __decorate([
69
+ (0, common_1.Injectable)(),
70
+ __param(0, (0, common_1.Inject)(config_1.APP_CONFIG)),
71
+ __metadata("design:paramtypes", [Object])
72
+ ], AppConfigService);
73
+ //# sourceMappingURL=app-config.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-config.service.js","sourceRoot":"","sources":["../src/app-config.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAAoD;AAEpD,qCAAsC;AAEtC,mEAAuE;AAOhE,IAAM,gBAAgB,GAAtB,MAAM,gBAAgB;IACsB;IAAjD,YAAiD,MAAiB;QAAjB,WAAM,GAAN,MAAM,CAAW;IAAG,CAAC;IAItE,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;IAC1B,CAAC;IAED,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;IAC1B,CAAC;IAED,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC;IAC7B,CAAC;IAED,IAAI,aAAa;QACf,OAAO,IAAI,CAAC,OAAO,KAAK,aAAa,CAAC;IACxC,CAAC;IAED,IAAI,YAAY;QACd,OAAO,IAAI,CAAC,OAAO,KAAK,YAAY,CAAC;IACvC,CAAC;IAED,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,OAAO,KAAK,MAAM,CAAC;IACjC,CAAC;IAID,IAAI,cAAc;QAChB,OAAO,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC;IACrC,CAAC;IAED,IAAI,qBAAqB;QACvB,OAAO,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC;IAC5C,CAAC;IAED,IAAI,iBAAiB;QACnB,OAAO,IAAA,0CAAuB,EAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IACjE,CAAC;IAED,IAAI,kBAAkB;QACpB,OAAO,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC;IACzC,CAAC;IAID,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC;IAC9B,CAAC;IAID,IAAI,YAAY;QACd,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC;IACnC,CAAC;IAID,IAAI,eAAe;QACjB,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC;IACtC,CAAC;IAID,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC;IAC9B,CAAC;CACF,CAAA;AAtEY,4CAAgB;2BAAhB,gBAAgB;IAD5B,IAAA,mBAAU,GAAE;IAEE,WAAA,IAAA,eAAM,EAAC,mBAAU,CAAC,CAAA;;GADpB,gBAAgB,CAsE5B"}
@@ -1,5 +1,7 @@
1
1
  import { DynamicModule } from "@nestjs/common";
2
+ import { ConfigInput, CliOverrides } from "./config";
2
3
  export declare class AppModule {
3
- static forStdio(): DynamicModule;
4
- static forHttp(): DynamicModule;
4
+ static forStdio(configInput: ConfigInput): DynamicModule;
5
+ static forHttp(configInput: ConfigInput): DynamicModule;
6
+ static forTunnel(cliOverrides?: CliOverrides): DynamicModule;
5
7
  }