@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
@@ -0,0 +1,111 @@
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 NotesInfoTool_1;
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.NotesInfoTool = void 0;
14
+ const common_1 = require("@nestjs/common");
15
+ const mcp_nest_1 = require("@rekog/mcp-nest");
16
+ const zod_1 = require("zod");
17
+ const anki_connect_client_1 = require("../../../clients/anki-connect.client");
18
+ const anki_utils_1 = require("../../../utils/anki.utils");
19
+ let NotesInfoTool = NotesInfoTool_1 = class NotesInfoTool {
20
+ ankiClient;
21
+ logger = new common_1.Logger(NotesInfoTool_1.name);
22
+ constructor(ankiClient) {
23
+ this.ankiClient = ankiClient;
24
+ }
25
+ async notesInfo({ notes }, context) {
26
+ try {
27
+ this.logger.log(`Getting information for ${notes.length} note(s)`);
28
+ await context.reportProgress({ progress: 25, total: 100 });
29
+ const notesData = await this.ankiClient.invoke("notesInfo", {
30
+ notes: notes,
31
+ });
32
+ await context.reportProgress({ progress: 75, total: 100 });
33
+ if (!notesData || notesData.length === 0) {
34
+ this.logger.warn("No note information returned");
35
+ await context.reportProgress({ progress: 100, total: 100 });
36
+ return (0, anki_utils_1.createErrorResponse)(new Error("No note information found"), {
37
+ requestedNotes: notes,
38
+ hint: "The note IDs may be invalid or the notes may have been deleted",
39
+ });
40
+ }
41
+ const transformedNotes = notesData.map((note) => ({
42
+ noteId: note.noteId,
43
+ modelName: note.modelName,
44
+ tags: note.tags || [],
45
+ fields: note.fields || {},
46
+ cards: note.cards || [],
47
+ mod: note.mod,
48
+ }));
49
+ const validNotes = transformedNotes.filter((note) => note.noteId);
50
+ const deletedCount = notes.length - validNotes.length;
51
+ await context.reportProgress({ progress: 100, total: 100 });
52
+ const message = deletedCount > 0
53
+ ? `Retrieved ${validNotes.length} note(s). ${deletedCount} note(s) not found (possibly deleted).`
54
+ : `Successfully retrieved information for ${validNotes.length} note(s)`;
55
+ this.logger.log(message);
56
+ const uniqueModels = [...new Set(validNotes.map((n) => n.modelName))];
57
+ return (0, anki_utils_1.createSuccessResponse)({
58
+ success: true,
59
+ notes: validNotes,
60
+ count: validNotes.length,
61
+ notFound: deletedCount,
62
+ requestedIds: notes,
63
+ message: message,
64
+ models: uniqueModels,
65
+ cssNote: "Each note model has its own CSS styling. Use modelStyling tool to get CSS for specific models.",
66
+ hint: validNotes.length > 0
67
+ ? "Fields may contain HTML. Use updateNoteFields to modify content. Do not view notes in Anki browser while updating."
68
+ : "No valid notes found. They may have been deleted.",
69
+ });
70
+ }
71
+ catch (error) {
72
+ this.logger.error("Failed to get notes information", error);
73
+ if (error instanceof Error) {
74
+ if (error.message.includes("not found")) {
75
+ return (0, anki_utils_1.createErrorResponse)(error, {
76
+ requestedNotes: notes,
77
+ hint: "One or more note IDs are invalid. Use findNotes to get valid note IDs.",
78
+ });
79
+ }
80
+ }
81
+ return (0, anki_utils_1.createErrorResponse)(error, {
82
+ requestedNotes: notes,
83
+ hint: "Make sure Anki is running and the note IDs are valid",
84
+ });
85
+ }
86
+ }
87
+ };
88
+ exports.NotesInfoTool = NotesInfoTool;
89
+ __decorate([
90
+ (0, mcp_nest_1.Tool)({
91
+ name: "notesInfo",
92
+ description: "Get detailed information about specific notes including all fields, tags, model info, and CSS styling. " +
93
+ "Use this after findNotes to get complete note data. Includes CSS for proper rendering awareness.",
94
+ parameters: zod_1.z.object({
95
+ notes: zod_1.z
96
+ .array(zod_1.z.number())
97
+ .min(1)
98
+ .max(100)
99
+ .describe("Array of note IDs to get information for (max 100 at once for performance). " +
100
+ "Get these IDs from findNotes tool."),
101
+ }),
102
+ }),
103
+ __metadata("design:type", Function),
104
+ __metadata("design:paramtypes", [Object, Object]),
105
+ __metadata("design:returntype", Promise)
106
+ ], NotesInfoTool.prototype, "notesInfo", null);
107
+ exports.NotesInfoTool = NotesInfoTool = NotesInfoTool_1 = __decorate([
108
+ (0, common_1.Injectable)(),
109
+ __metadata("design:paramtypes", [anki_connect_client_1.AnkiConnectClient])
110
+ ], NotesInfoTool);
111
+ //# sourceMappingURL=notes-info.tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notes-info.tool.js","sourceRoot":"","sources":["../../../../../src/mcp/primitives/essential/tools/notes-info.tool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,84 @@
1
+ import type { Context } from "@rekog/mcp-nest";
2
+ import { AnkiConnectClient } from "@/mcp/clients/anki-connect.client";
3
+ export declare class PresentCardTool {
4
+ private readonly ankiClient;
5
+ private readonly logger;
6
+ constructor(ankiClient: AnkiConnectClient);
7
+ presentCard({ card_id, show_answer }: {
8
+ card_id: number;
9
+ show_answer?: boolean;
10
+ }, context: Context): Promise<{
11
+ [x: string]: unknown;
12
+ content: ({
13
+ [x: string]: unknown;
14
+ type: "text";
15
+ text: string;
16
+ _meta?: {
17
+ [x: string]: unknown;
18
+ } | undefined;
19
+ } | {
20
+ [x: string]: unknown;
21
+ type: "image";
22
+ data: string;
23
+ mimeType: string;
24
+ _meta?: {
25
+ [x: string]: unknown;
26
+ } | undefined;
27
+ } | {
28
+ [x: string]: unknown;
29
+ type: "audio";
30
+ data: string;
31
+ mimeType: string;
32
+ _meta?: {
33
+ [x: string]: unknown;
34
+ } | undefined;
35
+ } | {
36
+ [x: string]: unknown;
37
+ type: "resource_link";
38
+ name: string;
39
+ uri: string;
40
+ _meta?: {
41
+ [x: string]: unknown;
42
+ } | undefined;
43
+ mimeType?: string | undefined;
44
+ title?: string | undefined;
45
+ description?: string | undefined;
46
+ icons?: {
47
+ [x: string]: unknown;
48
+ src: string;
49
+ mimeType?: string | undefined;
50
+ sizes?: string[] | undefined;
51
+ }[] | undefined;
52
+ } | {
53
+ [x: string]: unknown;
54
+ type: "resource";
55
+ resource: {
56
+ [x: string]: unknown;
57
+ text: string;
58
+ uri: string;
59
+ _meta?: {
60
+ [x: string]: unknown;
61
+ } | undefined;
62
+ mimeType?: string | undefined;
63
+ } | {
64
+ [x: string]: unknown;
65
+ uri: string;
66
+ blob: string;
67
+ _meta?: {
68
+ [x: string]: unknown;
69
+ } | undefined;
70
+ mimeType?: string | undefined;
71
+ };
72
+ _meta?: {
73
+ [x: string]: unknown;
74
+ } | undefined;
75
+ })[];
76
+ _meta?: {
77
+ [x: string]: unknown;
78
+ } | undefined;
79
+ structuredContent?: {
80
+ [x: string]: unknown;
81
+ } | undefined;
82
+ isError?: boolean | undefined;
83
+ }>;
84
+ }
@@ -0,0 +1,100 @@
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 PresentCardTool_1;
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.PresentCardTool = void 0;
14
+ const common_1 = require("@nestjs/common");
15
+ const mcp_nest_1 = require("@rekog/mcp-nest");
16
+ const zod_1 = require("zod");
17
+ const anki_connect_client_1 = require("../../../clients/anki-connect.client");
18
+ const anki_utils_1 = require("../../../utils/anki.utils");
19
+ let PresentCardTool = PresentCardTool_1 = class PresentCardTool {
20
+ ankiClient;
21
+ logger = new common_1.Logger(PresentCardTool_1.name);
22
+ constructor(ankiClient) {
23
+ this.ankiClient = ankiClient;
24
+ }
25
+ async presentCard({ card_id, show_answer }, context) {
26
+ try {
27
+ const showAnswer = show_answer || false;
28
+ this.logger.log(`Retrieving card ${card_id} for presentation (show_answer: ${showAnswer})`);
29
+ await context.reportProgress({ progress: 25, total: 100 });
30
+ const cardsInfo = await this.ankiClient.invoke("cardsInfo", {
31
+ cards: [card_id],
32
+ });
33
+ if (!cardsInfo || cardsInfo.length === 0) {
34
+ this.logger.warn(`Card not found: ${card_id}`);
35
+ return (0, anki_utils_1.createErrorResponse)(new Error(`Card with ID ${card_id} not found`), { cardId: card_id });
36
+ }
37
+ await context.reportProgress({ progress: 75, total: 100 });
38
+ const card = cardsInfo[0];
39
+ const { front, back } = (0, anki_utils_1.extractCardContent)(card.fields);
40
+ const cardType = (0, anki_utils_1.getCardType)(card.type);
41
+ const presentation = {
42
+ cardId: card.cardId,
43
+ front: front || card.question || "",
44
+ deckName: card.deckName,
45
+ modelName: card.modelName,
46
+ tags: card.tags || [],
47
+ currentInterval: card.interval || 0,
48
+ easeFactor: card.factor || 2500,
49
+ reviews: card.reps || 0,
50
+ lapses: card.lapses || 0,
51
+ cardType,
52
+ noteId: card.note,
53
+ };
54
+ if (showAnswer) {
55
+ presentation.back = back || card.answer || "";
56
+ }
57
+ await context.reportProgress({ progress: 100, total: 100 });
58
+ this.logger.log(`Retrieved card ${card_id} for presentation`);
59
+ const response = {
60
+ success: true,
61
+ card: presentation,
62
+ };
63
+ if (!showAnswer) {
64
+ response.instruction =
65
+ "Question shown. Wait for user's answer, then use show_answer=true";
66
+ }
67
+ else {
68
+ response.instruction =
69
+ "Answer revealed. Evaluate response and suggest rating, then wait for user confirmation";
70
+ }
71
+ return (0, anki_utils_1.createSuccessResponse)(response);
72
+ }
73
+ catch (error) {
74
+ this.logger.error(`Failed to retrieve card ${card_id}`, error);
75
+ return (0, anki_utils_1.createErrorResponse)(error, { cardId: card_id });
76
+ }
77
+ }
78
+ };
79
+ exports.PresentCardTool = PresentCardTool;
80
+ __decorate([
81
+ (0, mcp_nest_1.Tool)({
82
+ name: "present_card",
83
+ description: 'Retrieve a card\'s content for review. WORKFLOW: 1) Show question, 2) Wait for user answer, 3) Show answer with show_answer=true, 4) Evaluate and suggest rating (1-4), 5) Wait for user confirmation ("ok"/"next" = accept, or they provide different rating), 6) Only then use rate_card',
84
+ parameters: zod_1.z.object({
85
+ card_id: zod_1.z.number().describe("The ID of the card to retrieve"),
86
+ show_answer: zod_1.z
87
+ .boolean()
88
+ .default(false)
89
+ .describe("Whether to include the answer/back content in the response"),
90
+ }),
91
+ }),
92
+ __metadata("design:type", Function),
93
+ __metadata("design:paramtypes", [Object, Object]),
94
+ __metadata("design:returntype", Promise)
95
+ ], PresentCardTool.prototype, "presentCard", null);
96
+ exports.PresentCardTool = PresentCardTool = PresentCardTool_1 = __decorate([
97
+ (0, common_1.Injectable)(),
98
+ __metadata("design:paramtypes", [anki_connect_client_1.AnkiConnectClient])
99
+ ], PresentCardTool);
100
+ //# sourceMappingURL=present-card.tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"present-card.tool.js","sourceRoot":"","sources":["../../../../../src/mcp/primitives/essential/tools/present-card.tool.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,2CAAoD;AACpD,8CAAuC;AAEvC,6BAAwB;AACxB,8EAAsE;AAEtE,0DAKgC;AAMzB,IAAM,eAAe,uBAArB,MAAM,eAAe;IAGG;IAFZ,MAAM,GAAG,IAAI,eAAM,CAAC,iBAAe,CAAC,IAAI,CAAC,CAAC;IAE3D,YAA6B,UAA6B;QAA7B,eAAU,GAAV,UAAU,CAAmB;IAAG,CAAC;IAcxD,AAAN,KAAK,CAAC,WAAW,CACf,EAAE,OAAO,EAAE,WAAW,EAA8C,EACpE,OAAgB;QAEhB,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,WAAW,IAAI,KAAK,CAAC;YAExC,IAAI,CAAC,MAAM,CAAC,GAAG,CACb,mBAAmB,OAAO,mCAAmC,UAAU,GAAG,CAC3E,CAAC;YACF,MAAM,OAAO,CAAC,cAAc,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;YAG3D,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,MAAM,CAAa,WAAW,EAAE;gBACtE,KAAK,EAAE,CAAC,OAAO,CAAC;aACjB,CAAC,CAAC;YAEH,IAAI,CAAC,SAAS,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACzC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,mBAAmB,OAAO,EAAE,CAAC,CAAC;gBAC/C,OAAO,IAAA,gCAAmB,EACxB,IAAI,KAAK,CAAC,gBAAgB,OAAO,YAAY,CAAC,EAC9C,EAAE,MAAM,EAAE,OAAO,EAAE,CACpB,CAAC;YACJ,CAAC;YAED,MAAM,OAAO,CAAC,cAAc,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;YAE3D,MAAM,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;YAC1B,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,IAAA,+BAAkB,EAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACxD,MAAM,QAAQ,GAAG,IAAA,wBAAW,EAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAGxC,MAAM,YAAY,GAAqB;gBACrC,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,KAAK,EAAE,KAAK,IAAI,IAAI,CAAC,QAAQ,IAAI,EAAE;gBACnC,QAAQ,EAAE,IAAI,CAAC,QAAQ;gBACvB,SAAS,EAAE,IAAI,CAAC,SAAS;gBACzB,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,EAAE;gBACrB,eAAe,EAAE,IAAI,CAAC,QAAQ,IAAI,CAAC;gBACnC,UAAU,EAAE,IAAI,CAAC,MAAM,IAAI,IAAI;gBAC/B,OAAO,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC;gBACvB,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,CAAC;gBACxB,QAAQ;gBACR,MAAM,EAAE,IAAI,CAAC,IAAI;aAClB,CAAC;YAGF,IAAI,UAAU,EAAE,CAAC;gBACf,YAAY,CAAC,IAAI,GAAG,IAAI,IAAI,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC;YAChD,CAAC;YAED,MAAM,OAAO,CAAC,cAAc,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;YAC5D,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,kBAAkB,OAAO,mBAAmB,CAAC,CAAC;YAE9D,MAAM,QAAQ,GAAQ;gBACpB,OAAO,EAAE,IAAI;gBACb,IAAI,EAAE,YAAY;aACnB,CAAC;YAEF,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,QAAQ,CAAC,WAAW;oBAClB,mEAAmE,CAAC;YACxE,CAAC;iBAAM,CAAC;gBACN,QAAQ,CAAC,WAAW;oBAClB,wFAAwF,CAAC;YAC7F,CAAC;YAED,OAAO,IAAA,kCAAqB,EAAC,QAAQ,CAAC,CAAC;QACzC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,2BAA2B,OAAO,EAAE,EAAE,KAAK,CAAC,CAAC;YAC/D,OAAO,IAAA,gCAAmB,EAAC,KAAK,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;QACzD,CAAC;IACH,CAAC;CACF,CAAA;AA1FY,0CAAe;AAiBpB;IAZL,IAAA,eAAI,EAAC;QACJ,IAAI,EAAE,cAAc;QACpB,WAAW,EACT,4RAA4R;QAC9R,UAAU,EAAE,OAAC,CAAC,MAAM,CAAC;YACnB,OAAO,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,gCAAgC,CAAC;YAC9D,WAAW,EAAE,OAAC;iBACX,OAAO,EAAE;iBACT,OAAO,CAAC,KAAK,CAAC;iBACd,QAAQ,CAAC,4DAA4D,CAAC;SAC1E,CAAC;KACH,CAAC;;;;kDAyED;0BAzFU,eAAe;IAD3B,IAAA,mBAAU,GAAE;qCAI8B,uCAAiB;GAH/C,eAAe,CA0F3B"}
@@ -0,0 +1,84 @@
1
+ import type { Context } from "@rekog/mcp-nest";
2
+ import { AnkiConnectClient } from "@/mcp/clients/anki-connect.client";
3
+ export declare class RateCardTool {
4
+ private readonly ankiClient;
5
+ private readonly logger;
6
+ constructor(ankiClient: AnkiConnectClient);
7
+ rateCard({ card_id, rating }: {
8
+ card_id: number;
9
+ rating: number;
10
+ }, context: Context): Promise<{
11
+ [x: string]: unknown;
12
+ content: ({
13
+ [x: string]: unknown;
14
+ type: "text";
15
+ text: string;
16
+ _meta?: {
17
+ [x: string]: unknown;
18
+ } | undefined;
19
+ } | {
20
+ [x: string]: unknown;
21
+ type: "image";
22
+ data: string;
23
+ mimeType: string;
24
+ _meta?: {
25
+ [x: string]: unknown;
26
+ } | undefined;
27
+ } | {
28
+ [x: string]: unknown;
29
+ type: "audio";
30
+ data: string;
31
+ mimeType: string;
32
+ _meta?: {
33
+ [x: string]: unknown;
34
+ } | undefined;
35
+ } | {
36
+ [x: string]: unknown;
37
+ type: "resource_link";
38
+ name: string;
39
+ uri: string;
40
+ _meta?: {
41
+ [x: string]: unknown;
42
+ } | undefined;
43
+ mimeType?: string | undefined;
44
+ title?: string | undefined;
45
+ description?: string | undefined;
46
+ icons?: {
47
+ [x: string]: unknown;
48
+ src: string;
49
+ mimeType?: string | undefined;
50
+ sizes?: string[] | undefined;
51
+ }[] | undefined;
52
+ } | {
53
+ [x: string]: unknown;
54
+ type: "resource";
55
+ resource: {
56
+ [x: string]: unknown;
57
+ text: string;
58
+ uri: string;
59
+ _meta?: {
60
+ [x: string]: unknown;
61
+ } | undefined;
62
+ mimeType?: string | undefined;
63
+ } | {
64
+ [x: string]: unknown;
65
+ uri: string;
66
+ blob: string;
67
+ _meta?: {
68
+ [x: string]: unknown;
69
+ } | undefined;
70
+ mimeType?: string | undefined;
71
+ };
72
+ _meta?: {
73
+ [x: string]: unknown;
74
+ } | undefined;
75
+ })[];
76
+ _meta?: {
77
+ [x: string]: unknown;
78
+ } | undefined;
79
+ structuredContent?: {
80
+ [x: string]: unknown;
81
+ } | undefined;
82
+ isError?: boolean | undefined;
83
+ }>;
84
+ }
@@ -0,0 +1,101 @@
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 RateCardTool_1;
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.RateCardTool = void 0;
14
+ const common_1 = require("@nestjs/common");
15
+ const mcp_nest_1 = require("@rekog/mcp-nest");
16
+ const zod_1 = require("zod");
17
+ const anki_connect_client_1 = require("../../../clients/anki-connect.client");
18
+ const anki_utils_1 = require("../../../utils/anki.utils");
19
+ let RateCardTool = RateCardTool_1 = class RateCardTool {
20
+ ankiClient;
21
+ logger = new common_1.Logger(RateCardTool_1.name);
22
+ constructor(ankiClient) {
23
+ this.ankiClient = ankiClient;
24
+ }
25
+ async rateCard({ card_id, rating }, context) {
26
+ try {
27
+ if (!Number.isInteger(rating) || rating < 1 || rating > 4) {
28
+ return (0, anki_utils_1.createErrorResponse)(new Error("Invalid rating. Must be 1 (Again), 2 (Hard), 3 (Good), or 4 (Easy)"), { cardId: card_id, attemptedRating: rating });
29
+ }
30
+ this.logger.log(`Rating card ${card_id} with rating ${rating}`);
31
+ await context.reportProgress({ progress: 25, total: 100 });
32
+ const answers = [
33
+ {
34
+ cardId: card_id,
35
+ ease: rating,
36
+ },
37
+ ];
38
+ const result = await this.ankiClient.invoke("answerCards", {
39
+ answers,
40
+ });
41
+ if (!result) {
42
+ throw new Error(`Failed to rate card ${card_id}`);
43
+ }
44
+ const ratingDesc = (0, anki_utils_1.getRatingDescription)(rating);
45
+ this.logger.log(`Card ${card_id} rated as ${ratingDesc}`);
46
+ await context.reportProgress({ progress: 75, total: 100 });
47
+ const cardsInfo = await this.ankiClient.invoke("cardsInfo", {
48
+ cards: [card_id],
49
+ });
50
+ let nextReview = null;
51
+ if (cardsInfo && cardsInfo.length > 0) {
52
+ const card = cardsInfo[0];
53
+ nextReview = {
54
+ interval: card.interval || 0,
55
+ due: card.due || 0,
56
+ factor: card.factor || 2500,
57
+ };
58
+ }
59
+ await context.reportProgress({ progress: 100, total: 100 });
60
+ return (0, anki_utils_1.createSuccessResponse)({
61
+ success: true,
62
+ cardId: card_id,
63
+ rating: rating,
64
+ ratingDescription: ratingDesc,
65
+ message: `Card successfully rated as ${ratingDesc}`,
66
+ nextReview,
67
+ });
68
+ }
69
+ catch (error) {
70
+ this.logger.error(`Failed to rate card ${card_id}`, error);
71
+ return (0, anki_utils_1.createErrorResponse)(error, {
72
+ cardId: card_id,
73
+ attemptedRating: rating,
74
+ hint: "Make sure Anki is running and the card exists",
75
+ });
76
+ }
77
+ }
78
+ };
79
+ exports.RateCardTool = RateCardTool;
80
+ __decorate([
81
+ (0, mcp_nest_1.Tool)({
82
+ name: "rate_card",
83
+ description: "Submit a rating for a card to update Anki's spaced repetition scheduling. Use this ONLY after the user confirms or modifies your suggested rating. Do not rate automatically without user input.",
84
+ parameters: zod_1.z.object({
85
+ card_id: zod_1.z.number().describe("The ID of the card to rate"),
86
+ rating: zod_1.z
87
+ .number()
88
+ .min(1)
89
+ .max(4)
90
+ .describe("The rating for the card (use the user's choice, not your suggestion): 1=Again (failed), 2=Hard, 3=Good, 4=Easy"),
91
+ }),
92
+ }),
93
+ __metadata("design:type", Function),
94
+ __metadata("design:paramtypes", [Object, Object]),
95
+ __metadata("design:returntype", Promise)
96
+ ], RateCardTool.prototype, "rateCard", null);
97
+ exports.RateCardTool = RateCardTool = RateCardTool_1 = __decorate([
98
+ (0, common_1.Injectable)(),
99
+ __metadata("design:paramtypes", [anki_connect_client_1.AnkiConnectClient])
100
+ ], RateCardTool);
101
+ //# sourceMappingURL=rate-card.tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-card.tool.js","sourceRoot":"","sources":["../../../../../src/mcp/primitives/essential/tools/rate-card.tool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,81 @@
1
+ import type { Context } from "@rekog/mcp-nest";
2
+ import { AnkiConnectClient } from "@/mcp/clients/anki-connect.client";
3
+ export declare class SyncTool {
4
+ private readonly ankiClient;
5
+ private readonly logger;
6
+ constructor(ankiClient: AnkiConnectClient);
7
+ sync(_args: Record<string, never>, context: Context): Promise<{
8
+ [x: string]: unknown;
9
+ content: ({
10
+ [x: string]: unknown;
11
+ type: "text";
12
+ text: string;
13
+ _meta?: {
14
+ [x: string]: unknown;
15
+ } | undefined;
16
+ } | {
17
+ [x: string]: unknown;
18
+ type: "image";
19
+ data: string;
20
+ mimeType: string;
21
+ _meta?: {
22
+ [x: string]: unknown;
23
+ } | undefined;
24
+ } | {
25
+ [x: string]: unknown;
26
+ type: "audio";
27
+ data: string;
28
+ mimeType: string;
29
+ _meta?: {
30
+ [x: string]: unknown;
31
+ } | undefined;
32
+ } | {
33
+ [x: string]: unknown;
34
+ type: "resource_link";
35
+ name: string;
36
+ uri: string;
37
+ _meta?: {
38
+ [x: string]: unknown;
39
+ } | undefined;
40
+ mimeType?: string | undefined;
41
+ title?: string | undefined;
42
+ description?: string | undefined;
43
+ icons?: {
44
+ [x: string]: unknown;
45
+ src: string;
46
+ mimeType?: string | undefined;
47
+ sizes?: string[] | undefined;
48
+ }[] | undefined;
49
+ } | {
50
+ [x: string]: unknown;
51
+ type: "resource";
52
+ resource: {
53
+ [x: string]: unknown;
54
+ text: string;
55
+ uri: string;
56
+ _meta?: {
57
+ [x: string]: unknown;
58
+ } | undefined;
59
+ mimeType?: string | undefined;
60
+ } | {
61
+ [x: string]: unknown;
62
+ uri: string;
63
+ blob: string;
64
+ _meta?: {
65
+ [x: string]: unknown;
66
+ } | undefined;
67
+ mimeType?: string | undefined;
68
+ };
69
+ _meta?: {
70
+ [x: string]: unknown;
71
+ } | undefined;
72
+ })[];
73
+ _meta?: {
74
+ [x: string]: unknown;
75
+ } | undefined;
76
+ structuredContent?: {
77
+ [x: string]: unknown;
78
+ } | undefined;
79
+ isError?: boolean | undefined;
80
+ }>;
81
+ }
@@ -0,0 +1,61 @@
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 SyncTool_1;
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.SyncTool = void 0;
14
+ const common_1 = require("@nestjs/common");
15
+ const mcp_nest_1 = require("@rekog/mcp-nest");
16
+ const zod_1 = require("zod");
17
+ const anki_connect_client_1 = require("../../../clients/anki-connect.client");
18
+ const anki_utils_1 = require("../../../utils/anki.utils");
19
+ let SyncTool = SyncTool_1 = class SyncTool {
20
+ ankiClient;
21
+ logger = new common_1.Logger(SyncTool_1.name);
22
+ constructor(ankiClient) {
23
+ this.ankiClient = ankiClient;
24
+ }
25
+ async sync(_args, context) {
26
+ try {
27
+ this.logger.log("Synchronizing Anki collection with AnkiWeb");
28
+ await context.reportProgress({ progress: 25, total: 100 });
29
+ await this.ankiClient.invoke("sync");
30
+ this.logger.log("Anki sync completed successfully");
31
+ await context.reportProgress({ progress: 100, total: 100 });
32
+ return (0, anki_utils_1.createSuccessResponse)({
33
+ success: true,
34
+ message: "Successfully synchronized with AnkiWeb",
35
+ timestamp: new Date().toISOString(),
36
+ });
37
+ }
38
+ catch (error) {
39
+ this.logger.error("Failed to sync with AnkiWeb", error);
40
+ return (0, anki_utils_1.createErrorResponse)(error, {
41
+ hint: "Make sure Anki is running and you are logged into AnkiWeb",
42
+ });
43
+ }
44
+ }
45
+ };
46
+ exports.SyncTool = SyncTool;
47
+ __decorate([
48
+ (0, mcp_nest_1.Tool)({
49
+ name: "sync",
50
+ description: "Synchronize local Anki collection with AnkiWeb. IMPORTANT: Always sync at the START of a review session (before getting cards) and at the END when user indicates they are done. This ensures data consistency across devices.",
51
+ parameters: zod_1.z.object({}),
52
+ }),
53
+ __metadata("design:type", Function),
54
+ __metadata("design:paramtypes", [Object, Object]),
55
+ __metadata("design:returntype", Promise)
56
+ ], SyncTool.prototype, "sync", null);
57
+ exports.SyncTool = SyncTool = SyncTool_1 = __decorate([
58
+ (0, common_1.Injectable)(),
59
+ __metadata("design:paramtypes", [anki_connect_client_1.AnkiConnectClient])
60
+ ], SyncTool);
61
+ //# sourceMappingURL=sync.tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.tool.js","sourceRoot":"","sources":["../../../../../src/mcp/primitives/essential/tools/sync.tool.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,2CAAoD;AACpD,8CAAuC;AAEvC,6BAAwB;AACxB,8EAAsE;AACtE,0DAGgC;AAMzB,IAAM,QAAQ,gBAAd,MAAM,QAAQ;IAGU;IAFZ,MAAM,GAAG,IAAI,eAAM,CAAC,UAAQ,CAAC,IAAI,CAAC,CAAC;IAEpD,YAA6B,UAA6B;QAA7B,eAAU,GAAV,UAAU,CAAmB;IAAG,CAAC;IAQxD,AAAN,KAAK,CAAC,IAAI,CAAC,KAA4B,EAAE,OAAgB;QACvD,IAAI,CAAC;YACH,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,4CAA4C,CAAC,CAAC;YAC9D,MAAM,OAAO,CAAC,cAAc,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;YAG3D,MAAM,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YAErC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;YACpD,MAAM,OAAO,CAAC,cAAc,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;YAE5D,OAAO,IAAA,kCAAqB,EAAC;gBAC3B,OAAO,EAAE,IAAI;gBACb,OAAO,EAAE,wCAAwC;gBACjD,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;aACpC,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,6BAA6B,EAAE,KAAK,CAAC,CAAC;YAExD,OAAO,IAAA,gCAAmB,EAAC,KAAK,EAAE;gBAChC,IAAI,EAAE,2DAA2D;aAClE,CAAC,CAAC;QACL,CAAC;IACH,CAAC;CACF,CAAA;AAnCY,4BAAQ;AAWb;IANL,IAAA,eAAI,EAAC;QACJ,IAAI,EAAE,MAAM;QACZ,WAAW,EACT,gOAAgO;QAClO,UAAU,EAAE,OAAC,CAAC,MAAM,CAAC,EAAE,CAAC;KACzB,CAAC;;;;oCAwBD;mBAlCU,QAAQ;IADpB,IAAA,mBAAU,GAAE;qCAI8B,uCAAiB;GAH/C,QAAQ,CAmCpB"}