@ankimcp/anki-mcp-server 0.8.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 (171) hide show
  1. package/LICENSE +7 -0
  2. package/README.md +756 -0
  3. package/bin/ankimcp.js +12 -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 +84 -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 +9 -0
  14. package/dist/cli.js +114 -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 +42 -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 +32 -0
  35. package/dist/mcp/primitives/essential/index.js +130 -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/prompts/twenty-rules.prompt/content.md +195 -0
  41. package/dist/mcp/primitives/essential/prompts/twenty-rules.prompt/index.d.ts +12 -0
  42. package/dist/mcp/primitives/essential/prompts/twenty-rules.prompt/index.js +89 -0
  43. package/dist/mcp/primitives/essential/prompts/twenty-rules.prompt/index.js.map +1 -0
  44. package/dist/mcp/primitives/essential/resources/system-info.resource.d.ts +21 -0
  45. package/dist/mcp/primitives/essential/resources/system-info.resource.js +115 -0
  46. package/dist/mcp/primitives/essential/resources/system-info.resource.js.map +1 -0
  47. package/dist/mcp/primitives/essential/tools/add-note.tool.d.ts +93 -0
  48. package/dist/mcp/primitives/essential/tools/add-note.tool.js +185 -0
  49. package/dist/mcp/primitives/essential/tools/add-note.tool.js.map +1 -0
  50. package/dist/mcp/primitives/essential/tools/create-deck.tool.d.ts +83 -0
  51. package/dist/mcp/primitives/essential/tools/create-deck.tool.js +121 -0
  52. package/dist/mcp/primitives/essential/tools/create-deck.tool.js.map +1 -0
  53. package/dist/mcp/primitives/essential/tools/create-model.tool.d.ts +88 -0
  54. package/dist/mcp/primitives/essential/tools/create-model.tool.js +144 -0
  55. package/dist/mcp/primitives/essential/tools/create-model.tool.js.map +1 -0
  56. package/dist/mcp/primitives/essential/tools/delete-notes.tool.d.ts +84 -0
  57. package/dist/mcp/primitives/essential/tools/delete-notes.tool.js +120 -0
  58. package/dist/mcp/primitives/essential/tools/delete-notes.tool.js.map +1 -0
  59. package/dist/mcp/primitives/essential/tools/find-notes.tool.d.ts +83 -0
  60. package/dist/mcp/primitives/essential/tools/find-notes.tool.js +106 -0
  61. package/dist/mcp/primitives/essential/tools/find-notes.tool.js.map +1 -0
  62. package/dist/mcp/primitives/essential/tools/get-due-cards.tool.d.ts +84 -0
  63. package/dist/mcp/primitives/essential/tools/get-due-cards.tool.js +108 -0
  64. package/dist/mcp/primitives/essential/tools/get-due-cards.tool.js.map +1 -0
  65. package/dist/mcp/primitives/essential/tools/list-decks.tool.d.ts +83 -0
  66. package/dist/mcp/primitives/essential/tools/list-decks.tool.js +117 -0
  67. package/dist/mcp/primitives/essential/tools/list-decks.tool.js.map +1 -0
  68. package/dist/mcp/primitives/essential/tools/mediaActions/actions/deleteMediaFile.action.d.ts +10 -0
  69. package/dist/mcp/primitives/essential/tools/mediaActions/actions/deleteMediaFile.action.js +18 -0
  70. package/dist/mcp/primitives/essential/tools/mediaActions/actions/deleteMediaFile.action.js.map +1 -0
  71. package/dist/mcp/primitives/essential/tools/mediaActions/actions/getMediaFilesNames.action.d.ts +12 -0
  72. package/dist/mcp/primitives/essential/tools/mediaActions/actions/getMediaFilesNames.action.js +22 -0
  73. package/dist/mcp/primitives/essential/tools/mediaActions/actions/getMediaFilesNames.action.js.map +1 -0
  74. package/dist/mcp/primitives/essential/tools/mediaActions/actions/retrieveMediaFile.action.d.ts +12 -0
  75. package/dist/mcp/primitives/essential/tools/mediaActions/actions/retrieveMediaFile.action.js +29 -0
  76. package/dist/mcp/primitives/essential/tools/mediaActions/actions/retrieveMediaFile.action.js.map +1 -0
  77. package/dist/mcp/primitives/essential/tools/mediaActions/actions/storeMediaFile.action.d.ts +15 -0
  78. package/dist/mcp/primitives/essential/tools/mediaActions/actions/storeMediaFile.action.js +41 -0
  79. package/dist/mcp/primitives/essential/tools/mediaActions/actions/storeMediaFile.action.js.map +1 -0
  80. package/dist/mcp/primitives/essential/tools/mediaActions/index.d.ts +5 -0
  81. package/dist/mcp/primitives/essential/tools/mediaActions/index.js +6 -0
  82. package/dist/mcp/primitives/essential/tools/mediaActions/index.js.map +1 -0
  83. package/dist/mcp/primitives/essential/tools/mediaActions/mediaActions.tool.d.ts +89 -0
  84. package/dist/mcp/primitives/essential/tools/mediaActions/mediaActions.tool.js +141 -0
  85. package/dist/mcp/primitives/essential/tools/mediaActions/mediaActions.tool.js.map +1 -0
  86. package/dist/mcp/primitives/essential/tools/model-field-names.tool.d.ts +83 -0
  87. package/dist/mcp/primitives/essential/tools/model-field-names.tool.js +119 -0
  88. package/dist/mcp/primitives/essential/tools/model-field-names.tool.js.map +1 -0
  89. package/dist/mcp/primitives/essential/tools/model-names.tool.d.ts +81 -0
  90. package/dist/mcp/primitives/essential/tools/model-names.tool.js +80 -0
  91. package/dist/mcp/primitives/essential/tools/model-names.tool.js.map +1 -0
  92. package/dist/mcp/primitives/essential/tools/model-styling.tool.d.ts +83 -0
  93. package/dist/mcp/primitives/essential/tools/model-styling.tool.js +93 -0
  94. package/dist/mcp/primitives/essential/tools/model-styling.tool.js.map +1 -0
  95. package/dist/mcp/primitives/essential/tools/notes-info.tool.d.ts +83 -0
  96. package/dist/mcp/primitives/essential/tools/notes-info.tool.js +111 -0
  97. package/dist/mcp/primitives/essential/tools/notes-info.tool.js.map +1 -0
  98. package/dist/mcp/primitives/essential/tools/present-card.tool.d.ts +84 -0
  99. package/dist/mcp/primitives/essential/tools/present-card.tool.js +100 -0
  100. package/dist/mcp/primitives/essential/tools/present-card.tool.js.map +1 -0
  101. package/dist/mcp/primitives/essential/tools/rate-card.tool.d.ts +84 -0
  102. package/dist/mcp/primitives/essential/tools/rate-card.tool.js +101 -0
  103. package/dist/mcp/primitives/essential/tools/rate-card.tool.js.map +1 -0
  104. package/dist/mcp/primitives/essential/tools/sync.tool.d.ts +81 -0
  105. package/dist/mcp/primitives/essential/tools/sync.tool.js +61 -0
  106. package/dist/mcp/primitives/essential/tools/sync.tool.js.map +1 -0
  107. package/dist/mcp/primitives/essential/tools/update-model-styling.tool.d.ts +84 -0
  108. package/dist/mcp/primitives/essential/tools/update-model-styling.tool.js +119 -0
  109. package/dist/mcp/primitives/essential/tools/update-model-styling.tool.js.map +1 -0
  110. package/dist/mcp/primitives/essential/tools/update-note-fields.tool.d.ts +96 -0
  111. package/dist/mcp/primitives/essential/tools/update-note-fields.tool.js +154 -0
  112. package/dist/mcp/primitives/essential/tools/update-note-fields.tool.js.map +1 -0
  113. package/dist/mcp/primitives/gui/index.d.ts +23 -0
  114. package/dist/mcp/primitives/gui/index.js +94 -0
  115. package/dist/mcp/primitives/gui/index.js.map +1 -0
  116. package/dist/mcp/primitives/gui/tools/gui-add-cards.tool.d.ts +88 -0
  117. package/dist/mcp/primitives/gui/tools/gui-add-cards.tool.js +111 -0
  118. package/dist/mcp/primitives/gui/tools/gui-add-cards.tool.js.map +1 -0
  119. package/dist/mcp/primitives/gui/tools/gui-browse.tool.d.ts +87 -0
  120. package/dist/mcp/primitives/gui/tools/gui-browse.tool.js +99 -0
  121. package/dist/mcp/primitives/gui/tools/gui-browse.tool.js.map +1 -0
  122. package/dist/mcp/primitives/gui/tools/gui-current-card.tool.d.ts +81 -0
  123. package/dist/mcp/primitives/gui/tools/gui-current-card.tool.js +76 -0
  124. package/dist/mcp/primitives/gui/tools/gui-current-card.tool.js.map +1 -0
  125. package/dist/mcp/primitives/gui/tools/gui-deck-browser.tool.d.ts +81 -0
  126. package/dist/mcp/primitives/gui/tools/gui-deck-browser.tool.js +64 -0
  127. package/dist/mcp/primitives/gui/tools/gui-deck-browser.tool.js.map +1 -0
  128. package/dist/mcp/primitives/gui/tools/gui-deck-overview.tool.d.ts +83 -0
  129. package/dist/mcp/primitives/gui/tools/gui-deck-overview.tool.js +88 -0
  130. package/dist/mcp/primitives/gui/tools/gui-deck-overview.tool.js.map +1 -0
  131. package/dist/mcp/primitives/gui/tools/gui-edit-note.tool.d.ts +83 -0
  132. package/dist/mcp/primitives/gui/tools/gui-edit-note.tool.js +80 -0
  133. package/dist/mcp/primitives/gui/tools/gui-edit-note.tool.js.map +1 -0
  134. package/dist/mcp/primitives/gui/tools/gui-select-card.tool.d.ts +83 -0
  135. package/dist/mcp/primitives/gui/tools/gui-select-card.tool.js +90 -0
  136. package/dist/mcp/primitives/gui/tools/gui-select-card.tool.js.map +1 -0
  137. package/dist/mcp/primitives/gui/tools/gui-selected-notes.tool.d.ts +81 -0
  138. package/dist/mcp/primitives/gui/tools/gui-selected-notes.tool.js +83 -0
  139. package/dist/mcp/primitives/gui/tools/gui-selected-notes.tool.js.map +1 -0
  140. package/dist/mcp/primitives/gui/tools/gui-show-answer.tool.d.ts +81 -0
  141. package/dist/mcp/primitives/gui/tools/gui-show-answer.tool.js +74 -0
  142. package/dist/mcp/primitives/gui/tools/gui-show-answer.tool.js.map +1 -0
  143. package/dist/mcp/primitives/gui/tools/gui-show-question.tool.d.ts +81 -0
  144. package/dist/mcp/primitives/gui/tools/gui-show-question.tool.js +74 -0
  145. package/dist/mcp/primitives/gui/tools/gui-show-question.tool.js.map +1 -0
  146. package/dist/mcp/primitives/gui/tools/gui-undo.tool.d.ts +81 -0
  147. package/dist/mcp/primitives/gui/tools/gui-undo.tool.js +74 -0
  148. package/dist/mcp/primitives/gui/tools/gui-undo.tool.js.map +1 -0
  149. package/dist/mcp/types/anki.types.d.ts +180 -0
  150. package/dist/mcp/types/anki.types.js +18 -0
  151. package/dist/mcp/types/anki.types.js.map +1 -0
  152. package/dist/mcp/utils/anki.utils.d.ts +19 -0
  153. package/dist/mcp/utils/anki.utils.js +157 -0
  154. package/dist/mcp/utils/anki.utils.js.map +1 -0
  155. package/dist/mcp/utils/markdown.utils.d.ts +4 -0
  156. package/dist/mcp/utils/markdown.utils.js +60 -0
  157. package/dist/mcp/utils/markdown.utils.js.map +1 -0
  158. package/dist/mcp/utils/mcpb-workarounds.d.ts +1 -0
  159. package/dist/mcp/utils/mcpb-workarounds.js +13 -0
  160. package/dist/mcp/utils/mcpb-workarounds.js.map +1 -0
  161. package/dist/services/ngrok.service.d.ts +15 -0
  162. package/dist/services/ngrok.service.js +120 -0
  163. package/dist/services/ngrok.service.js.map +1 -0
  164. package/dist/test-fixtures/mock-data.d.ts +126 -0
  165. package/dist/test-fixtures/mock-data.js +112 -0
  166. package/dist/test-fixtures/mock-data.js.map +1 -0
  167. package/dist/test-fixtures/test-helpers.d.ts +12 -0
  168. package/dist/test-fixtures/test-helpers.js +24 -0
  169. package/dist/test-fixtures/test-helpers.js.map +1 -0
  170. package/dist/tsconfig.build.tsbuildinfo +1 -0
  171. package/package.json +168 -0
package/bin/ankimcp.js ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env node
2
+
3
+ // Check if --stdio flag is present
4
+ const isStdioMode = process.argv.includes('--stdio');
5
+
6
+ if (isStdioMode) {
7
+ // STDIO mode - for MCP clients like Cursor, Cline, Zed, etc.
8
+ require('../dist/main-stdio.js');
9
+ } else {
10
+ // HTTP mode (default) - for web-based AI assistants
11
+ require('../dist/main-http.js');
12
+ }
@@ -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
+ }
@@ -0,0 +1,84 @@
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 AppModule_1;
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.AppModule = void 0;
11
+ const common_1 = require("@nestjs/common");
12
+ const config_1 = require("@nestjs/config");
13
+ const mcp_nest_1 = require("@rekog/mcp-nest");
14
+ const essential_1 = require("./mcp/primitives/essential");
15
+ const gui_1 = require("./mcp/primitives/gui");
16
+ const anki_config_service_1 = require("./anki-config.service");
17
+ let AppModule = AppModule_1 = class AppModule {
18
+ static forStdio() {
19
+ return {
20
+ module: AppModule_1,
21
+ imports: [
22
+ config_1.ConfigModule.forRoot({
23
+ isGlobal: true,
24
+ cache: true,
25
+ envFilePath: [".env.local", ".env"],
26
+ }),
27
+ mcp_nest_1.McpModule.forRoot({
28
+ name: process.env.MCP_SERVER_NAME || "anki-mcp-server",
29
+ version: process.env.MCP_SERVER_VERSION || "1.0.0",
30
+ transport: mcp_nest_1.McpTransportType.STDIO,
31
+ }),
32
+ essential_1.McpPrimitivesAnkiEssentialModule.forRoot({
33
+ ankiConfigProvider: {
34
+ provide: essential_1.ANKI_CONFIG,
35
+ useClass: anki_config_service_1.AnkiConfigService,
36
+ },
37
+ }),
38
+ gui_1.McpPrimitivesAnkiGuiModule.forRoot({
39
+ ankiConfigProvider: {
40
+ provide: essential_1.ANKI_CONFIG,
41
+ useClass: anki_config_service_1.AnkiConfigService,
42
+ },
43
+ }),
44
+ ],
45
+ providers: [anki_config_service_1.AnkiConfigService],
46
+ };
47
+ }
48
+ static forHttp() {
49
+ return {
50
+ module: AppModule_1,
51
+ imports: [
52
+ config_1.ConfigModule.forRoot({
53
+ isGlobal: true,
54
+ cache: true,
55
+ envFilePath: [".env.local", ".env"],
56
+ }),
57
+ mcp_nest_1.McpModule.forRoot({
58
+ name: process.env.MCP_SERVER_NAME || "anki-mcp-server",
59
+ version: process.env.MCP_SERVER_VERSION || "1.0.0",
60
+ transport: mcp_nest_1.McpTransportType.STREAMABLE_HTTP,
61
+ mcpEndpoint: "/",
62
+ }),
63
+ essential_1.McpPrimitivesAnkiEssentialModule.forRoot({
64
+ ankiConfigProvider: {
65
+ provide: essential_1.ANKI_CONFIG,
66
+ useClass: anki_config_service_1.AnkiConfigService,
67
+ },
68
+ }),
69
+ gui_1.McpPrimitivesAnkiGuiModule.forRoot({
70
+ ankiConfigProvider: {
71
+ provide: essential_1.ANKI_CONFIG,
72
+ useClass: anki_config_service_1.AnkiConfigService,
73
+ },
74
+ }),
75
+ ],
76
+ providers: [anki_config_service_1.AnkiConfigService],
77
+ };
78
+ }
79
+ };
80
+ exports.AppModule = AppModule;
81
+ exports.AppModule = AppModule = AppModule_1 = __decorate([
82
+ (0, common_1.Module)({})
83
+ ], AppModule);
84
+ //# sourceMappingURL=app.module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app.module.js","sourceRoot":"","sources":["../src/app.module.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,2CAAuD;AACvD,2CAA8C;AAC9C,8CAA8D;AAC9D,0DAGoC;AACpC,8CAAkE;AAClE,+DAA0D;AAGnD,IAAM,SAAS,iBAAf,MAAM,SAAS;IAIpB,MAAM,CAAC,QAAQ;QACb,OAAO;YACL,MAAM,EAAE,WAAS;YACjB,OAAO,EAAE;gBAEP,qBAAY,CAAC,OAAO,CAAC;oBACnB,QAAQ,EAAE,IAAI;oBACd,KAAK,EAAE,IAAI;oBACX,WAAW,EAAE,CAAC,YAAY,EAAE,MAAM,CAAC;iBACpC,CAAC;gBAGF,oBAAS,CAAC,OAAO,CAAC;oBAChB,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,iBAAiB;oBACtD,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,OAAO;oBAClD,SAAS,EAAE,2BAAgB,CAAC,KAAK;iBAClC,CAAC;gBAGF,4CAAgC,CAAC,OAAO,CAAC;oBACvC,kBAAkB,EAAE;wBAClB,OAAO,EAAE,uBAAW;wBACpB,QAAQ,EAAE,uCAAiB;qBAC5B;iBACF,CAAC;gBAGF,gCAA0B,CAAC,OAAO,CAAC;oBACjC,kBAAkB,EAAE;wBAClB,OAAO,EAAE,uBAAW;wBACpB,QAAQ,EAAE,uCAAiB;qBAC5B;iBACF,CAAC;aACH;YACD,SAAS,EAAE,CAAC,uCAAiB,CAAC;SAC/B,CAAC;IACJ,CAAC;IAKD,MAAM,CAAC,OAAO;QACZ,OAAO;YACL,MAAM,EAAE,WAAS;YACjB,OAAO,EAAE;gBAEP,qBAAY,CAAC,OAAO,CAAC;oBACnB,QAAQ,EAAE,IAAI;oBACd,KAAK,EAAE,IAAI;oBACX,WAAW,EAAE,CAAC,YAAY,EAAE,MAAM,CAAC;iBACpC,CAAC;gBAGF,oBAAS,CAAC,OAAO,CAAC;oBAChB,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,iBAAiB;oBACtD,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,OAAO;oBAClD,SAAS,EAAE,2BAAgB,CAAC,eAAe;oBAC3C,WAAW,EAAE,GAAG;iBACjB,CAAC;gBAGF,4CAAgC,CAAC,OAAO,CAAC;oBACvC,kBAAkB,EAAE;wBAClB,OAAO,EAAE,uBAAW;wBACpB,QAAQ,EAAE,uCAAiB;qBAC5B;iBACF,CAAC;gBAGF,gCAA0B,CAAC,OAAO,CAAC;oBACjC,kBAAkB,EAAE;wBAClB,OAAO,EAAE,uBAAW;wBACpB,QAAQ,EAAE,uCAAiB;qBAC5B;iBACF,CAAC;aACH;YACD,SAAS,EAAE,CAAC,uCAAiB,CAAC;SAC/B,CAAC;IACJ,CAAC;CACF,CAAA;AAnFY,8BAAS;oBAAT,SAAS;IADrB,IAAA,eAAM,EAAC,EAAE,CAAC;GACE,SAAS,CAmFrB"}
@@ -0,0 +1,3 @@
1
+ import { LoggerService } from "@nestjs/common";
2
+ export declare function createPinoLogger(destination: 1 | 2): import("pino").Logger<never, boolean>;
3
+ export declare function createLoggerService(pinoLogger: any): LoggerService;
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createPinoLogger = createPinoLogger;
4
+ exports.createLoggerService = createLoggerService;
5
+ const pino_1 = require("pino");
6
+ function createPinoLogger(destination) {
7
+ return (0, pino_1.pino)({
8
+ level: process.env.LOG_LEVEL || "info",
9
+ transport: {
10
+ target: "pino-pretty",
11
+ options: {
12
+ destination,
13
+ colorize: true,
14
+ translateTime: "HH:MM:ss Z",
15
+ ignore: "pid,hostname",
16
+ },
17
+ },
18
+ });
19
+ }
20
+ function createLoggerService(pinoLogger) {
21
+ return {
22
+ log: (message, context) => {
23
+ pinoLogger.info({ context }, message);
24
+ },
25
+ error: (message, trace, context) => {
26
+ pinoLogger.error({ context, trace }, message);
27
+ },
28
+ warn: (message, context) => {
29
+ pinoLogger.warn({ context }, message);
30
+ },
31
+ debug: (message, context) => {
32
+ pinoLogger.debug({ context }, message);
33
+ },
34
+ verbose: (message, context) => {
35
+ pinoLogger.trace({ context }, message);
36
+ },
37
+ };
38
+ }
39
+ //# sourceMappingURL=bootstrap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../src/bootstrap.ts"],"names":[],"mappings":";;AASA,4CAaC;AAQD,kDAkBC;AA/CD,+BAA4B;AAQ5B,SAAgB,gBAAgB,CAAC,WAAkB;IACjD,OAAO,IAAA,WAAI,EAAC;QACV,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,MAAM;QACtC,SAAS,EAAE;YACT,MAAM,EAAE,aAAa;YACrB,OAAO,EAAE;gBACP,WAAW;gBACX,QAAQ,EAAE,IAAI;gBACd,aAAa,EAAE,YAAY;gBAC3B,MAAM,EAAE,cAAc;aACvB;SACF;KACF,CAAC,CAAC;AACL,CAAC;AAQD,SAAgB,mBAAmB,CAAC,UAAe;IACjD,OAAO;QACL,GAAG,EAAE,CAAC,OAAY,EAAE,OAAgB,EAAE,EAAE;YACtC,UAAU,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,CAAC;QACxC,CAAC;QACD,KAAK,EAAE,CAAC,OAAY,EAAE,KAAc,EAAE,OAAgB,EAAE,EAAE;YACxD,UAAU,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,OAAO,CAAC,CAAC;QAChD,CAAC;QACD,IAAI,EAAE,CAAC,OAAY,EAAE,OAAgB,EAAE,EAAE;YACvC,UAAU,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,CAAC;QACxC,CAAC;QACD,KAAK,EAAE,CAAC,OAAY,EAAE,OAAgB,EAAE,EAAE;YACxC,UAAU,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,CAAC;QACzC,CAAC;QACD,OAAO,EAAE,CAAC,OAAY,EAAE,OAAgB,EAAE,EAAE;YAC1C,UAAU,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,CAAC;QACzC,CAAC;KACF,CAAC;AACJ,CAAC"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ export interface CliOptions {
2
+ port: number;
3
+ host: string;
4
+ ankiConnect: string;
5
+ ngrok: boolean;
6
+ }
7
+ export declare function checkForUpdates(): void;
8
+ export declare function parseCliArgs(): CliOptions;
9
+ export declare function displayStartupBanner(options: CliOptions, ngrokUrl?: string): void;
package/dist/cli.js ADDED
@@ -0,0 +1,114 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.checkForUpdates = checkForUpdates;
7
+ exports.parseCliArgs = parseCliArgs;
8
+ exports.displayStartupBanner = displayStartupBanner;
9
+ const commander_1 = require("commander");
10
+ const fs_1 = require("fs");
11
+ const path_1 = require("path");
12
+ const update_notifier_1 = __importDefault(require("update-notifier"));
13
+ function getPackageJson() {
14
+ try {
15
+ return JSON.parse((0, fs_1.readFileSync)((0, path_1.join)(__dirname, "../package.json"), "utf-8"));
16
+ }
17
+ catch {
18
+ return { version: "0.0.0", name: "anki-mcp-http" };
19
+ }
20
+ }
21
+ function getVersion() {
22
+ return getPackageJson().version;
23
+ }
24
+ function checkForUpdates() {
25
+ (0, update_notifier_1.default)({ pkg: getPackageJson() }).notify();
26
+ }
27
+ function parseCliArgs() {
28
+ const program = new commander_1.Command();
29
+ program
30
+ .name("ankimcp")
31
+ .description("AnkiMCP Server - Model Context Protocol server for Anki")
32
+ .version(getVersion())
33
+ .option("--stdio", "Run in STDIO mode (for MCP clients like Cursor, Cline, Zed)")
34
+ .option("-p, --port <number>", "Port to listen on (HTTP mode)", "3000")
35
+ .option("-h, --host <address>", "Host to bind to (HTTP mode)", "127.0.0.1")
36
+ .option("-a, --anki-connect <url>", "AnkiConnect URL", "http://localhost:8765")
37
+ .option("--ngrok", "Start ngrok tunnel (requires global ngrok installation)")
38
+ .addHelpText("after", `
39
+ Transport Modes:
40
+ HTTP Mode (default): For web-based AI assistants (ChatGPT, Claude.ai)
41
+ STDIO Mode: For desktop MCP clients (Cursor, Cline, Zed)
42
+
43
+ Examples - HTTP Mode:
44
+ $ anki-mcp-http # Use defaults
45
+ $ anki-mcp-http --port 8080 # Custom port
46
+ $ anki-mcp-http --host 0.0.0.0 --port 3000 # Listen on all interfaces
47
+ $ anki-mcp-http --anki-connect http://localhost:8765
48
+
49
+ Examples - HTTP Mode with Ngrok:
50
+ $ anki-mcp-http --ngrok # Start with ngrok tunnel
51
+ $ anki-mcp-http --port 8080 --ngrok # Custom port + ngrok
52
+ $ anki-mcp-http --host 0.0.0.0 --ngrok # Public host + ngrok
53
+
54
+ Examples - STDIO Mode:
55
+ $ anki-mcp-http --stdio # For use with npx in MCP clients
56
+
57
+ # MCP client configuration (Cursor, Cline, Zed, etc.):
58
+ {
59
+ "mcpServers": {
60
+ "anki-mcp": {
61
+ "command": "npx",
62
+ "args": ["-y", "anki-mcp-http", "--stdio"]
63
+ }
64
+ }
65
+ }
66
+
67
+ Ngrok Setup (one-time):
68
+ 1. Install: npm install -g ngrok
69
+ 2. Get auth token from: https://dashboard.ngrok.com/get-started/your-authtoken
70
+ 3. Setup: ngrok config add-authtoken <your-token>
71
+ 4. Run: anki-mcp-http --ngrok
72
+ `);
73
+ program.parse();
74
+ const options = program.opts();
75
+ return {
76
+ port: parseInt(options.port.toString(), 10),
77
+ host: options.host,
78
+ ankiConnect: options.ankiConnect,
79
+ ngrok: options.ngrok || false,
80
+ };
81
+ }
82
+ function displayStartupBanner(options, ngrokUrl) {
83
+ const version = getVersion();
84
+ const title = `AnkiMCP HTTP Server v${version}`;
85
+ const padding = Math.floor((64 - title.length) / 2);
86
+ const paddedTitle = " ".repeat(padding) + title + " ".repeat(64 - padding - title.length);
87
+ console.log(`
88
+ ╔════════════════════════════════════════════════════════════════╗
89
+ ║${paddedTitle}║
90
+ ╚════════════════════════════════════════════════════════════════╝
91
+
92
+ 🚀 Server running on: http://${options.host}:${options.port}
93
+ 🔌 AnkiConnect URL: ${options.ankiConnect}${ngrokUrl ? `\n🌐 Ngrok tunnel: ${ngrokUrl}` : ""}
94
+
95
+ Configuration:
96
+ • Port: ${options.port} (override: --port 8080)
97
+ • Host: ${options.host} (override: --host 0.0.0.0)
98
+ • AnkiConnect: ${options.ankiConnect}
99
+ (override: --anki-connect http://localhost:8765)${ngrokUrl ? `\n • Ngrok tunnel: ${ngrokUrl}\n • Ngrok dashboard: http://localhost:4040` : ""}
100
+ ${!ngrokUrl
101
+ ? `
102
+ Usage with ngrok:
103
+ 1. Install: npm install -g ngrok
104
+ 2. Setup: ngrok config add-authtoken <your-token>
105
+ 3. Run: anki-mcp-http --ngrok
106
+ `
107
+ : `
108
+ Share this URL with your AI assistant:
109
+ ${ngrokUrl}
110
+ `}
111
+ Run 'anki-mcp-http --help' for more options.
112
+ `);
113
+ }
114
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";;;;;AA0BA,0CAEC;AAED,oCAuEC;AAED,oDAsCC;AA7ID,yCAAoC;AACpC,2BAAkC;AAClC,+BAA4B;AAC5B,sEAA6C;AAS7C,SAAS,cAAc;IACrB,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CACf,IAAA,iBAAY,EAAC,IAAA,WAAI,EAAC,SAAS,EAAE,iBAAiB,CAAC,EAAE,OAAO,CAAC,CAC1D,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC;IACrD,CAAC;AACH,CAAC;AAED,SAAS,UAAU;IACjB,OAAO,cAAc,EAAE,CAAC,OAAO,CAAC;AAClC,CAAC;AAED,SAAgB,eAAe;IAC7B,IAAA,yBAAc,EAAC,EAAE,GAAG,EAAE,cAAc,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC;AACrD,CAAC;AAED,SAAgB,YAAY;IAC1B,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;IAE9B,OAAO;SACJ,IAAI,CAAC,SAAS,CAAC;SACf,WAAW,CAAC,yDAAyD,CAAC;SACtE,OAAO,CAAC,UAAU,EAAE,CAAC;SACrB,MAAM,CACL,SAAS,EACT,6DAA6D,CAC9D;SACA,MAAM,CAAC,qBAAqB,EAAE,+BAA+B,EAAE,MAAM,CAAC;SACtE,MAAM,CAAC,sBAAsB,EAAE,6BAA6B,EAAE,WAAW,CAAC;SAC1E,MAAM,CACL,0BAA0B,EAC1B,iBAAiB,EACjB,uBAAuB,CACxB;SACA,MAAM,CACL,SAAS,EACT,yDAAyD,CAC1D;SACA,WAAW,CACV,OAAO,EACP;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkCL,CACI,CAAC;IAEJ,OAAO,CAAC,KAAK,EAAE,CAAC;IAEhB,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAc,CAAC;IAE3C,OAAO;QACL,IAAI,EAAE,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,EAAE,CAAC;QAC3C,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,KAAK;KAC9B,CAAC;AACJ,CAAC;AAED,SAAgB,oBAAoB,CAClC,OAAmB,EACnB,QAAiB;IAEjB,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,MAAM,KAAK,GAAG,wBAAwB,OAAO,EAAE,CAAC;IAChD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IACpD,MAAM,WAAW,GACf,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,KAAK,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,GAAG,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;IAExE,OAAO,CAAC,GAAG,CAAC;;GAEX,WAAW;;;+BAGiB,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,IAAI;wBACnC,OAAO,CAAC,WAAW,GAAG,QAAQ,CAAC,CAAC,CAAC,2BAA2B,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE;;;0BAGzE,OAAO,CAAC,IAAI;0BACZ,OAAO,CAAC,IAAI;0BACZ,OAAO,CAAC,WAAW;0EAC6B,QAAQ,CAAC,CAAC,CAAC,6BAA6B,QAAQ,iDAAiD,CAAC,CAAC,CAAC,EAAE;EAE9K,CAAC,QAAQ;QACP,CAAC,CAAC;;;;;CAKL;QACG,CAAC,CAAC;;IAEF,QAAQ;CAEZ;;CAEC,CAAC,CAAC;AACH,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { CanActivate, ExecutionContext } from "@nestjs/common";
2
+ export declare class OriginValidationGuard implements CanActivate {
3
+ private readonly allowedOrigins;
4
+ constructor();
5
+ canActivate(context: ExecutionContext): boolean;
6
+ private matchesPattern;
7
+ }
@@ -0,0 +1,52 @@
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.OriginValidationGuard = void 0;
13
+ const common_1 = require("@nestjs/common");
14
+ let OriginValidationGuard = class OriginValidationGuard {
15
+ allowedOrigins;
16
+ constructor() {
17
+ const defaultOrigins = "http://localhost:*,http://127.0.0.1:*,https://localhost:*,https://127.0.0.1:*";
18
+ const originsEnv = process.env.ALLOWED_ORIGINS || defaultOrigins;
19
+ this.allowedOrigins = originsEnv.split(",").map((o) => o.trim());
20
+ }
21
+ canActivate(context) {
22
+ const request = context.switchToHttp().getRequest();
23
+ const origin = request.headers.origin || request.headers.referer;
24
+ if (!origin) {
25
+ return true;
26
+ }
27
+ const isAllowed = this.allowedOrigins.some((allowedOrigin) => this.matchesPattern(origin, allowedOrigin));
28
+ if (!isAllowed) {
29
+ console.warn(`[OriginValidationGuard] Rejected request from unauthorized origin: ${origin}`);
30
+ }
31
+ return isAllowed;
32
+ }
33
+ matchesPattern(origin, pattern) {
34
+ if (origin === pattern) {
35
+ return true;
36
+ }
37
+ if (pattern.includes("*")) {
38
+ const regexPattern = pattern
39
+ .replace(/\./g, "\\.")
40
+ .replace(/\*/g, ".*");
41
+ const regex = new RegExp(`^${regexPattern}$`);
42
+ return regex.test(origin);
43
+ }
44
+ return false;
45
+ }
46
+ };
47
+ exports.OriginValidationGuard = OriginValidationGuard;
48
+ exports.OriginValidationGuard = OriginValidationGuard = __decorate([
49
+ (0, common_1.Injectable)(),
50
+ __metadata("design:paramtypes", [])
51
+ ], OriginValidationGuard);
52
+ //# sourceMappingURL=origin-validation.guard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"origin-validation.guard.js","sourceRoot":"","sources":["../../../src/http/guards/origin-validation.guard.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAA2E;AAiBpE,IAAM,qBAAqB,GAA3B,MAAM,qBAAqB;IACf,cAAc,CAAW;IAE1C;QACE,MAAM,cAAc,GAClB,+EAA+E,CAAC;QAClF,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,cAAc,CAAC;QACjE,IAAI,CAAC,cAAc,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IACnE,CAAC;IAED,WAAW,CAAC,OAAyB;QACnC,MAAM,OAAO,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,UAAU,EAAW,CAAC;QAC7D,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC;QAGjE,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,IAAI,CAAC;QACd,CAAC;QAGD,MAAM,SAAS,GAAG,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,aAAa,EAAE,EAAE,CAC3D,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE,aAAa,CAAC,CAC3C,CAAC;QAEF,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO,CAAC,IAAI,CACV,sEAAsE,MAAM,EAAE,CAC/E,CAAC;QACJ,CAAC;QAED,OAAO,SAAS,CAAC;IACnB,CAAC;IASO,cAAc,CAAC,MAAc,EAAE,OAAe;QAEpD,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;YACvB,OAAO,IAAI,CAAC;QACd,CAAC;QAGD,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YAC1B,MAAM,YAAY,GAAG,OAAO;iBACzB,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC;iBACrB,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;YACxB,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,IAAI,YAAY,GAAG,CAAC,CAAC;YAC9C,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC5B,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;CACF,CAAA;AAzDY,sDAAqB;gCAArB,qBAAqB;IADjC,IAAA,mBAAU,GAAE;;GACA,qBAAqB,CAyDjC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@nestjs/core");
4
+ const app_module_1 = require("./app.module");
5
+ const bootstrap_1 = require("./bootstrap");
6
+ const origin_validation_guard_1 = require("./http/guards/origin-validation.guard");
7
+ const cli_1 = require("./cli");
8
+ const ngrok_service_1 = require("./services/ngrok.service");
9
+ async function bootstrap() {
10
+ (0, cli_1.checkForUpdates)();
11
+ const options = (0, cli_1.parseCliArgs)();
12
+ process.env.PORT = options.port.toString();
13
+ process.env.HOST = options.host;
14
+ process.env.ANKI_CONNECT_URL = options.ankiConnect;
15
+ const pinoLogger = (0, bootstrap_1.createPinoLogger)(1);
16
+ const loggerService = (0, bootstrap_1.createLoggerService)(pinoLogger);
17
+ const app = await core_1.NestFactory.create(app_module_1.AppModule.forHttp(), {
18
+ logger: loggerService,
19
+ bufferLogs: true,
20
+ });
21
+ app.useGlobalGuards(new origin_validation_guard_1.OriginValidationGuard());
22
+ await app.listen(options.port, options.host);
23
+ let ngrokUrl;
24
+ if (options.ngrok) {
25
+ try {
26
+ const ngrokService = new ngrok_service_1.NgrokService();
27
+ const tunnelInfo = await ngrokService.start(options.port);
28
+ ngrokUrl = tunnelInfo.publicUrl;
29
+ }
30
+ catch (err) {
31
+ console.error("\n❌ Failed to start ngrok:");
32
+ console.error(err instanceof Error ? err.message : String(err));
33
+ console.error("\nServer is still running locally without tunnel.\n");
34
+ }
35
+ }
36
+ (0, cli_1.displayStartupBanner)(options, ngrokUrl);
37
+ }
38
+ bootstrap().catch((err) => {
39
+ console.error("Failed to start MCP HTTP server:", err);
40
+ process.exit(1);
41
+ });
42
+ //# sourceMappingURL=main-http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main-http.js","sourceRoot":"","sources":["../src/main-http.ts"],"names":[],"mappings":";;AAAA,uCAA2C;AAC3C,6CAAyC;AACzC,2CAAoE;AACpE,mFAA8E;AAC9E,+BAA4E;AAC5E,4DAAwD;AAExD,KAAK,UAAU,SAAS;IAEtB,IAAA,qBAAe,GAAE,CAAC;IAElB,MAAM,OAAO,GAAG,IAAA,kBAAY,GAAE,CAAC;IAG/B,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;IAC3C,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAChC,OAAO,CAAC,GAAG,CAAC,gBAAgB,GAAG,OAAO,CAAC,WAAW,CAAC;IAGnD,MAAM,UAAU,GAAG,IAAA,4BAAgB,EAAC,CAAC,CAAC,CAAC;IACvC,MAAM,aAAa,GAAG,IAAA,+BAAmB,EAAC,UAAU,CAAC,CAAC;IAGtD,MAAM,GAAG,GAAG,MAAM,kBAAW,CAAC,MAAM,CAAC,sBAAS,CAAC,OAAO,EAAE,EAAE;QACxD,MAAM,EAAE,aAAa;QACrB,UAAU,EAAE,IAAI;KACjB,CAAC,CAAC;IAGH,GAAG,CAAC,eAAe,CAAC,IAAI,+CAAqB,EAAE,CAAC,CAAC;IAEjD,MAAM,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAG7C,IAAI,QAA4B,CAAC;IACjC,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;QAClB,IAAI,CAAC;YACH,MAAM,YAAY,GAAG,IAAI,4BAAY,EAAE,CAAC;YACxC,MAAM,UAAU,GAAG,MAAM,YAAY,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAC1D,QAAQ,GAAG,UAAU,CAAC,SAAS,CAAC;QAClC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,4BAA4B,CAAC,CAAC;YAC5C,OAAO,CAAC,KAAK,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;YAChE,OAAO,CAAC,KAAK,CAAC,qDAAqD,CAAC,CAAC;QACvE,CAAC;IACH,CAAC;IAGD,IAAA,0BAAoB,EAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;AAC1C,CAAC;AAED,SAAS,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACxB,OAAO,CAAC,KAAK,CAAC,kCAAkC,EAAE,GAAG,CAAC,CAAC;IACvD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@nestjs/core");
4
+ const app_module_1 = require("./app.module");
5
+ const bootstrap_1 = require("./bootstrap");
6
+ async function bootstrap() {
7
+ const pinoLogger = (0, bootstrap_1.createPinoLogger)(2);
8
+ const loggerService = (0, bootstrap_1.createLoggerService)(pinoLogger);
9
+ await core_1.NestFactory.createApplicationContext(app_module_1.AppModule.forStdio(), {
10
+ logger: loggerService,
11
+ bufferLogs: true,
12
+ });
13
+ pinoLogger.info("MCP STDIO server started successfully");
14
+ await new Promise(() => { });
15
+ }
16
+ bootstrap().catch((err) => {
17
+ console.error("Failed to start MCP STDIO server:", err);
18
+ process.exit(1);
19
+ });
20
+ //# sourceMappingURL=main-stdio.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main-stdio.js","sourceRoot":"","sources":["../src/main-stdio.ts"],"names":[],"mappings":";;AAAA,uCAA2C;AAC3C,6CAAyC;AACzC,2CAAoE;AAEpE,KAAK,UAAU,SAAS;IAEtB,MAAM,UAAU,GAAG,IAAA,4BAAgB,EAAC,CAAC,CAAC,CAAC;IACvC,MAAM,aAAa,GAAG,IAAA,+BAAmB,EAAC,UAAU,CAAC,CAAC;IAGtD,MAAM,kBAAW,CAAC,wBAAwB,CAAC,sBAAS,CAAC,QAAQ,EAAE,EAAE;QAC/D,MAAM,EAAE,aAAa;QACrB,UAAU,EAAE,IAAI;KACjB,CAAC,CAAC;IAEH,UAAU,CAAC,IAAI,CAAC,uCAAuC,CAAC,CAAC;IAGzD,MAAM,IAAI,OAAO,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;AAC9B,CAAC;AAED,SAAS,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACxB,OAAO,CAAC,KAAK,CAAC,mCAAmC,EAAE,GAAG,CAAC,CAAC;IACxD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,6 @@
1
+ export declare const AnkiConnectClient: jest.Mock<any, any, any>;
2
+ export declare class AnkiConnectError extends Error {
3
+ readonly action?: string | undefined;
4
+ readonly originalError?: string | undefined;
5
+ constructor(message: string, action?: string | undefined, originalError?: string | undefined);
6
+ }
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AnkiConnectError = exports.AnkiConnectClient = void 0;
4
+ exports.AnkiConnectClient = jest.fn().mockImplementation(() => ({
5
+ invoke: jest.fn(),
6
+ }));
7
+ class AnkiConnectError extends Error {
8
+ action;
9
+ originalError;
10
+ constructor(message, action, originalError) {
11
+ super(message);
12
+ this.action = action;
13
+ this.originalError = originalError;
14
+ this.name = "AnkiConnectError";
15
+ }
16
+ }
17
+ exports.AnkiConnectError = AnkiConnectError;
18
+ //# sourceMappingURL=anki-connect.client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anki-connect.client.js","sourceRoot":"","sources":["../../../../src/mcp/clients/__mocks__/anki-connect.client.ts"],"names":[],"mappings":";;;AACa,QAAA,iBAAiB,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC,kBAAkB,CAAC,GAAG,EAAE,CAAC,CAAC;IACnE,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE;CAClB,CAAC,CAAC,CAAC;AAEJ,MAAa,gBAAiB,SAAQ,KAAK;IAGvB;IACA;IAHlB,YACE,OAAe,EACC,MAAe,EACf,aAAsB;QAEtC,KAAK,CAAC,OAAO,CAAC,CAAC;QAHC,WAAM,GAAN,MAAM,CAAS;QACf,kBAAa,GAAb,aAAa,CAAS;QAGtC,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;IACjC,CAAC;CACF;AATD,4CASC"}
@@ -0,0 +1,15 @@
1
+ import type { IAnkiConfig } from "../config/anki-config.interface";
2
+ export declare class AnkiConnectError extends Error {
3
+ readonly action?: string | undefined;
4
+ readonly originalError?: string | undefined;
5
+ constructor(message: string, action?: string | undefined, originalError?: string | undefined);
6
+ }
7
+ export declare class AnkiConnectClient {
8
+ private readonly config;
9
+ private readonly client;
10
+ private readonly apiVersion;
11
+ private readonly apiKey?;
12
+ private readonly logger;
13
+ constructor(config: IAnkiConfig);
14
+ invoke<T = any>(action: string, params?: Record<string, any>): Promise<T>;
15
+ }