anki-mcp-http 0.7.1 ā 0.8.1
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.
- package/LICENSE +5 -19
- package/README.md +152 -35
- package/bin/ankimcp.js +0 -0
- package/dist/anki-config.service.d.ts +2 -2
- package/dist/anki-config.service.js +4 -4
- package/dist/app.module.d.ts +1 -1
- package/dist/app.module.js +7 -7
- package/dist/app.module.js.map +1 -1
- package/dist/bootstrap.d.ts +1 -1
- package/dist/bootstrap.js +4 -4
- package/dist/cli.d.ts +2 -1
- package/dist/cli.js +41 -27
- package/dist/cli.js.map +1 -1
- package/dist/http/guards/origin-validation.guard.d.ts +1 -1
- package/dist/http/guards/origin-validation.guard.js +5 -5
- package/dist/main-http.js +16 -2
- package/dist/main-http.js.map +1 -1
- package/dist/main-stdio.js +2 -2
- package/dist/mcp/clients/__mocks__/anki-connect.client.js +1 -1
- package/dist/mcp/clients/anki-connect.client.d.ts +1 -1
- package/dist/mcp/clients/anki-connect.client.js +7 -7
- package/dist/mcp/config/anki-config.interface.js +1 -1
- package/dist/mcp/primitives/essential/index.d.ts +26 -26
- package/dist/mcp/primitives/essential/index.js +1 -4
- package/dist/mcp/primitives/essential/index.js.map +1 -1
- package/dist/mcp/primitives/essential/prompts/review-session.prompt.js +5 -5
- package/dist/mcp/primitives/essential/prompts/review-session.prompt.js.map +1 -1
- package/dist/mcp/primitives/essential/prompts/twenty-rules.prompt/index.js +10 -8
- package/dist/mcp/primitives/essential/prompts/twenty-rules.prompt/index.js.map +1 -1
- package/dist/mcp/primitives/essential/resources/system-info.resource.js +12 -12
- package/dist/mcp/primitives/essential/tools/add-note.tool.d.ts +3 -3
- package/dist/mcp/primitives/essential/tools/add-note.tool.js +27 -30
- package/dist/mcp/primitives/essential/tools/add-note.tool.js.map +1 -1
- package/dist/mcp/primitives/essential/tools/create-deck.tool.d.ts +2 -2
- package/dist/mcp/primitives/essential/tools/create-deck.tool.js +15 -15
- package/dist/mcp/primitives/essential/tools/create-deck.tool.js.map +1 -1
- package/dist/mcp/primitives/essential/tools/create-model.tool.d.ts +3 -3
- package/dist/mcp/primitives/essential/tools/create-model.tool.js +20 -18
- package/dist/mcp/primitives/essential/tools/create-model.tool.js.map +1 -1
- package/dist/mcp/primitives/essential/tools/delete-notes.tool.d.ts +2 -2
- package/dist/mcp/primitives/essential/tools/delete-notes.tool.js +22 -22
- package/dist/mcp/primitives/essential/tools/delete-notes.tool.js.map +1 -1
- package/dist/mcp/primitives/essential/tools/find-notes.tool.d.ts +2 -2
- package/dist/mcp/primitives/essential/tools/find-notes.tool.js +14 -14
- package/dist/mcp/primitives/essential/tools/find-notes.tool.js.map +1 -1
- package/dist/mcp/primitives/essential/tools/get-due-cards.tool.d.ts +2 -2
- package/dist/mcp/primitives/essential/tools/get-due-cards.tool.js +17 -15
- package/dist/mcp/primitives/essential/tools/get-due-cards.tool.js.map +1 -1
- package/dist/mcp/primitives/essential/tools/list-decks.tool.d.ts +2 -2
- package/dist/mcp/primitives/essential/tools/list-decks.tool.js +10 -10
- package/dist/mcp/primitives/essential/tools/list-decks.tool.js.map +1 -1
- package/dist/mcp/primitives/essential/tools/mediaActions/actions/deleteMediaFile.action.d.ts +1 -1
- package/dist/mcp/primitives/essential/tools/mediaActions/actions/deleteMediaFile.action.js +3 -3
- package/dist/mcp/primitives/essential/tools/mediaActions/actions/getMediaFilesNames.action.d.ts +1 -1
- package/dist/mcp/primitives/essential/tools/mediaActions/actions/getMediaFilesNames.action.js +1 -1
- package/dist/mcp/primitives/essential/tools/mediaActions/actions/getMediaFilesNames.action.js.map +1 -1
- package/dist/mcp/primitives/essential/tools/mediaActions/actions/retrieveMediaFile.action.d.ts +1 -1
- package/dist/mcp/primitives/essential/tools/mediaActions/actions/retrieveMediaFile.action.js +3 -3
- package/dist/mcp/primitives/essential/tools/mediaActions/actions/storeMediaFile.action.d.ts +1 -1
- package/dist/mcp/primitives/essential/tools/mediaActions/actions/storeMediaFile.action.js +7 -7
- package/dist/mcp/primitives/essential/tools/mediaActions/actions/storeMediaFile.action.js.map +1 -1
- package/dist/mcp/primitives/essential/tools/mediaActions/index.d.ts +5 -5
- package/dist/mcp/primitives/essential/tools/mediaActions/mediaActions.tool.d.ts +3 -3
- package/dist/mcp/primitives/essential/tools/mediaActions/mediaActions.tool.js +23 -17
- package/dist/mcp/primitives/essential/tools/mediaActions/mediaActions.tool.js.map +1 -1
- package/dist/mcp/primitives/essential/tools/model-field-names.tool.d.ts +2 -2
- package/dist/mcp/primitives/essential/tools/model-field-names.tool.js +20 -17
- package/dist/mcp/primitives/essential/tools/model-field-names.tool.js.map +1 -1
- package/dist/mcp/primitives/essential/tools/model-names.tool.d.ts +3 -3
- package/dist/mcp/primitives/essential/tools/model-names.tool.js +13 -11
- package/dist/mcp/primitives/essential/tools/model-names.tool.js.map +1 -1
- package/dist/mcp/primitives/essential/tools/model-styling.tool.d.ts +2 -2
- package/dist/mcp/primitives/essential/tools/model-styling.tool.js +11 -11
- package/dist/mcp/primitives/essential/tools/model-styling.tool.js.map +1 -1
- package/dist/mcp/primitives/essential/tools/notes-info.tool.d.ts +2 -2
- package/dist/mcp/primitives/essential/tools/notes-info.tool.js +19 -19
- package/dist/mcp/primitives/essential/tools/notes-info.tool.js.map +1 -1
- package/dist/mcp/primitives/essential/tools/present-card.tool.d.ts +2 -2
- package/dist/mcp/primitives/essential/tools/present-card.tool.js +11 -11
- package/dist/mcp/primitives/essential/tools/present-card.tool.js.map +1 -1
- package/dist/mcp/primitives/essential/tools/rate-card.tool.d.ts +2 -2
- package/dist/mcp/primitives/essential/tools/rate-card.tool.js +19 -14
- package/dist/mcp/primitives/essential/tools/rate-card.tool.js.map +1 -1
- package/dist/mcp/primitives/essential/tools/sync.tool.d.ts +3 -3
- package/dist/mcp/primitives/essential/tools/sync.tool.js +8 -8
- package/dist/mcp/primitives/essential/tools/sync.tool.js.map +1 -1
- package/dist/mcp/primitives/essential/tools/update-model-styling.tool.d.ts +2 -2
- package/dist/mcp/primitives/essential/tools/update-model-styling.tool.js +19 -19
- package/dist/mcp/primitives/essential/tools/update-model-styling.tool.js.map +1 -1
- package/dist/mcp/primitives/essential/tools/update-note-fields.tool.d.ts +3 -3
- package/dist/mcp/primitives/essential/tools/update-note-fields.tool.js +32 -32
- package/dist/mcp/primitives/essential/tools/update-note-fields.tool.js.map +1 -1
- package/dist/mcp/primitives/gui/index.d.ts +17 -17
- package/dist/mcp/primitives/gui/index.js.map +1 -1
- package/dist/mcp/primitives/gui/tools/gui-add-cards.tool.d.ts +2 -2
- package/dist/mcp/primitives/gui/tools/gui-add-cards.tool.js +22 -22
- package/dist/mcp/primitives/gui/tools/gui-add-cards.tool.js.map +1 -1
- package/dist/mcp/primitives/gui/tools/gui-browse.tool.d.ts +3 -3
- package/dist/mcp/primitives/gui/tools/gui-browse.tool.js +15 -14
- package/dist/mcp/primitives/gui/tools/gui-browse.tool.js.map +1 -1
- package/dist/mcp/primitives/gui/tools/gui-current-card.tool.d.ts +3 -3
- package/dist/mcp/primitives/gui/tools/gui-current-card.tool.js +13 -13
- package/dist/mcp/primitives/gui/tools/gui-current-card.tool.js.map +1 -1
- package/dist/mcp/primitives/gui/tools/gui-deck-browser.tool.d.ts +3 -3
- package/dist/mcp/primitives/gui/tools/gui-deck-browser.tool.js +12 -12
- package/dist/mcp/primitives/gui/tools/gui-deck-browser.tool.js.map +1 -1
- package/dist/mcp/primitives/gui/tools/gui-deck-overview.tool.d.ts +2 -2
- package/dist/mcp/primitives/gui/tools/gui-deck-overview.tool.js +15 -12
- package/dist/mcp/primitives/gui/tools/gui-deck-overview.tool.js.map +1 -1
- package/dist/mcp/primitives/gui/tools/gui-edit-note.tool.d.ts +2 -2
- package/dist/mcp/primitives/gui/tools/gui-edit-note.tool.js +13 -12
- package/dist/mcp/primitives/gui/tools/gui-edit-note.tool.js.map +1 -1
- package/dist/mcp/primitives/gui/tools/gui-select-card.tool.d.ts +2 -2
- package/dist/mcp/primitives/gui/tools/gui-select-card.tool.js +18 -15
- package/dist/mcp/primitives/gui/tools/gui-select-card.tool.js.map +1 -1
- package/dist/mcp/primitives/gui/tools/gui-selected-notes.tool.d.ts +3 -3
- package/dist/mcp/primitives/gui/tools/gui-selected-notes.tool.js +15 -14
- package/dist/mcp/primitives/gui/tools/gui-selected-notes.tool.js.map +1 -1
- package/dist/mcp/primitives/gui/tools/gui-show-answer.tool.d.ts +3 -3
- package/dist/mcp/primitives/gui/tools/gui-show-answer.tool.js +15 -15
- package/dist/mcp/primitives/gui/tools/gui-show-answer.tool.js.map +1 -1
- package/dist/mcp/primitives/gui/tools/gui-show-question.tool.d.ts +3 -3
- package/dist/mcp/primitives/gui/tools/gui-show-question.tool.js +15 -15
- package/dist/mcp/primitives/gui/tools/gui-show-question.tool.js.map +1 -1
- package/dist/mcp/primitives/gui/tools/gui-undo.tool.d.ts +3 -3
- package/dist/mcp/primitives/gui/tools/gui-undo.tool.js +15 -15
- package/dist/mcp/primitives/gui/tools/gui-undo.tool.js.map +1 -1
- package/dist/mcp/types/anki.types.d.ts +2 -2
- package/dist/mcp/utils/anki.utils.d.ts +3 -3
- package/dist/mcp/utils/anki.utils.js +42 -38
- package/dist/mcp/utils/anki.utils.js.map +1 -1
- package/dist/mcp/utils/markdown.utils.js +16 -12
- package/dist/mcp/utils/markdown.utils.js.map +1 -1
- package/dist/mcp/utils/mcpb-workarounds.js +2 -2
- package/dist/mcp/utils/mcpb-workarounds.js.map +1 -1
- package/dist/services/ngrok.service.d.ts +15 -0
- package/dist/services/ngrok.service.js +120 -0
- package/dist/services/ngrok.service.js.map +1 -0
- package/dist/test-fixtures/mock-data.d.ts +2 -2
- package/dist/test-fixtures/mock-data.js +46 -46
- package/dist/test-fixtures/mock-data.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +12 -7
|
@@ -24,31 +24,31 @@ let GuiUndoTool = GuiUndoTool_1 = class GuiUndoTool {
|
|
|
24
24
|
}
|
|
25
25
|
async guiUndo(_args, context) {
|
|
26
26
|
try {
|
|
27
|
-
this.logger.log(
|
|
27
|
+
this.logger.log("Undoing last action in Anki");
|
|
28
28
|
await context.reportProgress({ progress: 50, total: 100 });
|
|
29
|
-
const success = await this.ankiClient.invoke(
|
|
29
|
+
const success = await this.ankiClient.invoke("guiUndo");
|
|
30
30
|
await context.reportProgress({ progress: 100, total: 100 });
|
|
31
31
|
if (!success) {
|
|
32
|
-
this.logger.warn(
|
|
32
|
+
this.logger.warn("Nothing to undo");
|
|
33
33
|
return (0, anki_utils_1.createSuccessResponse)({
|
|
34
34
|
success: true,
|
|
35
35
|
undone: false,
|
|
36
|
-
message:
|
|
37
|
-
hint:
|
|
36
|
+
message: "Nothing to undo",
|
|
37
|
+
hint: "There are no recent actions to undo in Anki.",
|
|
38
38
|
});
|
|
39
39
|
}
|
|
40
|
-
this.logger.log(
|
|
40
|
+
this.logger.log("Last action undone successfully");
|
|
41
41
|
return (0, anki_utils_1.createSuccessResponse)({
|
|
42
42
|
success: true,
|
|
43
43
|
undone: true,
|
|
44
|
-
message:
|
|
45
|
-
hint:
|
|
44
|
+
message: "Last action undone successfully",
|
|
45
|
+
hint: "The previous action has been reversed. Check Anki GUI to verify.",
|
|
46
46
|
});
|
|
47
47
|
}
|
|
48
48
|
catch (error) {
|
|
49
|
-
this.logger.error(
|
|
49
|
+
this.logger.error("Failed to undo action", error);
|
|
50
50
|
return (0, anki_utils_1.createErrorResponse)(error, {
|
|
51
|
-
hint:
|
|
51
|
+
hint: "Make sure Anki is running and the GUI is visible",
|
|
52
52
|
});
|
|
53
53
|
}
|
|
54
54
|
}
|
|
@@ -56,11 +56,11 @@ let GuiUndoTool = GuiUndoTool_1 = class GuiUndoTool {
|
|
|
56
56
|
exports.GuiUndoTool = GuiUndoTool;
|
|
57
57
|
__decorate([
|
|
58
58
|
(0, mcp_nest_1.Tool)({
|
|
59
|
-
name:
|
|
60
|
-
description:
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
59
|
+
name: "guiUndo",
|
|
60
|
+
description: "Undo the last action or card in Anki. Returns true if undo succeeded, false otherwise. " +
|
|
61
|
+
"IMPORTANT: Only use when user explicitly requests undoing an action. " +
|
|
62
|
+
"This tool is for note editing/creation workflows, NOT for review sessions. " +
|
|
63
|
+
"Use this to undo mistakes in note creation, editing, or card management.",
|
|
64
64
|
parameters: zod_1.z.object({}),
|
|
65
65
|
}),
|
|
66
66
|
__metadata("design:type", Function),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gui-undo.tool.js","sourceRoot":"","sources":["../../../../../src/mcp/primitives/gui/tools/gui-undo.tool.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,2CAAoD;AACpD,8CAAuC;AAEvC,6BAAwB;AACxB,8EAAsE;AACtE,
|
|
1
|
+
{"version":3,"file":"gui-undo.tool.js","sourceRoot":"","sources":["../../../../../src/mcp/primitives/gui/tools/gui-undo.tool.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,2CAAoD;AACpD,8CAAuC;AAEvC,6BAAwB;AACxB,8EAAsE;AACtE,0DAGgC;AAMzB,IAAM,WAAW,mBAAjB,MAAM,WAAW;IAGO;IAFZ,MAAM,GAAG,IAAI,eAAM,CAAC,aAAW,CAAC,IAAI,CAAC,CAAC;IAEvD,YAA6B,UAA6B;QAA7B,eAAU,GAAV,UAAU,CAAmB;IAAG,CAAC;IAWxD,AAAN,KAAK,CAAC,OAAO,CAAC,KAA4B,EAAE,OAAgB;QAC1D,IAAI,CAAC;YACH,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAC;YAC/C,MAAM,OAAO,CAAC,cAAc,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;YAG3D,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,MAAM,CAAU,SAAS,CAAC,CAAC;YAEjE,MAAM,OAAO,CAAC,cAAc,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;YAE5D,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;gBACpC,OAAO,IAAA,kCAAqB,EAAC;oBAC3B,OAAO,EAAE,IAAI;oBACb,MAAM,EAAE,KAAK;oBACb,OAAO,EAAE,iBAAiB;oBAC1B,IAAI,EAAE,8CAA8C;iBACrD,CAAC,CAAC;YACL,CAAC;YAED,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC;YAEnD,OAAO,IAAA,kCAAqB,EAAC;gBAC3B,OAAO,EAAE,IAAI;gBACb,MAAM,EAAE,IAAI;gBACZ,OAAO,EAAE,iCAAiC;gBAC1C,IAAI,EAAE,kEAAkE;aACzE,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,uBAAuB,EAAE,KAAK,CAAC,CAAC;YAElD,OAAO,IAAA,gCAAmB,EAAC,KAAK,EAAE;gBAChC,IAAI,EAAE,kDAAkD;aACzD,CAAC,CAAC;QACL,CAAC;IACH,CAAC;CACF,CAAA;AAlDY,kCAAW;AAchB;IATL,IAAA,eAAI,EAAC;QACJ,IAAI,EAAE,SAAS;QACf,WAAW,EACT,yFAAyF;YACzF,uEAAuE;YACvE,6EAA6E;YAC7E,0EAA0E;QAC5E,UAAU,EAAE,OAAC,CAAC,MAAM,CAAC,EAAE,CAAC;KACzB,CAAC;;;;0CAoCD;sBAjDU,WAAW;IADvB,IAAA,mBAAU,GAAE;qCAI8B,uCAAiB;GAH/C,WAAW,CAkDvB"}
|
|
@@ -85,7 +85,7 @@ export interface AnkiConnectResponse<T = any> {
|
|
|
85
85
|
}
|
|
86
86
|
export interface NoteOptions {
|
|
87
87
|
allowDuplicate?: boolean;
|
|
88
|
-
duplicateScope?:
|
|
88
|
+
duplicateScope?: "deck" | "collection";
|
|
89
89
|
duplicateScopeOptions?: {
|
|
90
90
|
deckName?: string;
|
|
91
91
|
checkChildren?: boolean;
|
|
@@ -166,7 +166,7 @@ export interface GuiCurrentCardInfo {
|
|
|
166
166
|
export interface GuiBrowseParams {
|
|
167
167
|
query: string;
|
|
168
168
|
reorderCards?: {
|
|
169
|
-
order:
|
|
169
|
+
order: "ascending" | "descending";
|
|
170
170
|
columnId: string;
|
|
171
171
|
};
|
|
172
172
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { CallToolResult } from
|
|
2
|
-
import { AnkiCard } from
|
|
1
|
+
import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
2
|
+
import { AnkiCard } from "../types/anki.types";
|
|
3
3
|
export declare function cleanHtml(html: string): string;
|
|
4
|
-
export declare function extractCardContent(fields: AnkiCard[
|
|
4
|
+
export declare function extractCardContent(fields: AnkiCard["fields"]): {
|
|
5
5
|
front: string;
|
|
6
6
|
back: string;
|
|
7
7
|
};
|
|
@@ -13,24 +13,24 @@ const anki_types_1 = require("../types/anki.types");
|
|
|
13
13
|
const anki_connect_client_1 = require("../clients/anki-connect.client");
|
|
14
14
|
function cleanHtml(html) {
|
|
15
15
|
return html
|
|
16
|
-
.replace(/<[^>]*>/g,
|
|
17
|
-
.replace(/ /g,
|
|
18
|
-
.replace(/&/g,
|
|
19
|
-
.replace(/</g,
|
|
20
|
-
.replace(/>/g,
|
|
16
|
+
.replace(/<[^>]*>/g, "")
|
|
17
|
+
.replace(/ /g, " ")
|
|
18
|
+
.replace(/&/g, "&")
|
|
19
|
+
.replace(/</g, "<")
|
|
20
|
+
.replace(/>/g, ">")
|
|
21
21
|
.replace(/"/g, '"')
|
|
22
22
|
.replace(/'/g, "'")
|
|
23
|
-
.replace(/\n\s*\n/g,
|
|
23
|
+
.replace(/\n\s*\n/g, "\n")
|
|
24
24
|
.trim();
|
|
25
25
|
}
|
|
26
26
|
function extractCardContent(fields) {
|
|
27
|
-
let front =
|
|
28
|
-
let back =
|
|
27
|
+
let front = "";
|
|
28
|
+
let back = "";
|
|
29
29
|
if (!fields) {
|
|
30
30
|
return { front, back };
|
|
31
31
|
}
|
|
32
|
-
const frontFieldNames = [
|
|
33
|
-
const backFieldNames = [
|
|
32
|
+
const frontFieldNames = ["Front", "ę£é¢", "Question", "Text"];
|
|
33
|
+
const backFieldNames = ["Back", "čé¢", "Answer", "Extra", "Back Extra"];
|
|
34
34
|
for (const fieldName of frontFieldNames) {
|
|
35
35
|
if (fields[fieldName]) {
|
|
36
36
|
front = fields[fieldName].value;
|
|
@@ -44,8 +44,7 @@ function extractCardContent(fields) {
|
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
46
|
if (!front && !back) {
|
|
47
|
-
const fieldEntries = Object.entries(fields)
|
|
48
|
-
.sort((a, b) => a[1].order - b[1].order);
|
|
47
|
+
const fieldEntries = Object.entries(fields).sort((a, b) => a[1].order - b[1].order);
|
|
49
48
|
if (fieldEntries.length > 0) {
|
|
50
49
|
front = fieldEntries[0][1].value;
|
|
51
50
|
}
|
|
@@ -55,50 +54,55 @@ function extractCardContent(fields) {
|
|
|
55
54
|
}
|
|
56
55
|
return {
|
|
57
56
|
front: cleanHtml(front),
|
|
58
|
-
back: cleanHtml(back)
|
|
57
|
+
back: cleanHtml(back),
|
|
59
58
|
};
|
|
60
59
|
}
|
|
61
60
|
function getCardType(type) {
|
|
62
61
|
switch (type) {
|
|
63
|
-
case anki_types_1.CardType.New:
|
|
64
|
-
|
|
65
|
-
case anki_types_1.CardType.
|
|
66
|
-
|
|
67
|
-
|
|
62
|
+
case anki_types_1.CardType.New:
|
|
63
|
+
return "new";
|
|
64
|
+
case anki_types_1.CardType.Learning:
|
|
65
|
+
return "learning";
|
|
66
|
+
case anki_types_1.CardType.Review:
|
|
67
|
+
return "review";
|
|
68
|
+
case anki_types_1.CardType.Relearning:
|
|
69
|
+
return "relearning";
|
|
70
|
+
default:
|
|
71
|
+
return "unknown";
|
|
68
72
|
}
|
|
69
73
|
}
|
|
70
74
|
function getNoteType(modelName) {
|
|
71
75
|
const lowerName = modelName.toLowerCase();
|
|
72
|
-
if (lowerName.includes(
|
|
73
|
-
if (lowerName.includes(
|
|
74
|
-
return
|
|
76
|
+
if (lowerName.includes("basic")) {
|
|
77
|
+
if (lowerName.includes("reverse")) {
|
|
78
|
+
return "Basic (and reversed card)";
|
|
75
79
|
}
|
|
76
|
-
return
|
|
80
|
+
return "Basic";
|
|
77
81
|
}
|
|
78
|
-
if (lowerName.includes(
|
|
79
|
-
return
|
|
82
|
+
if (lowerName.includes("cloze")) {
|
|
83
|
+
return "Cloze";
|
|
80
84
|
}
|
|
81
|
-
return
|
|
85
|
+
return "Custom";
|
|
82
86
|
}
|
|
83
87
|
function getRatingDescription(rating) {
|
|
84
88
|
switch (rating) {
|
|
85
89
|
case anki_types_1.CardRating.Again:
|
|
86
|
-
return
|
|
90
|
+
return "Again (failed to recall)";
|
|
87
91
|
case anki_types_1.CardRating.Hard:
|
|
88
|
-
return
|
|
92
|
+
return "Hard (recalled with difficulty)";
|
|
89
93
|
case anki_types_1.CardRating.Good:
|
|
90
|
-
return
|
|
94
|
+
return "Good (recalled with some effort)";
|
|
91
95
|
case anki_types_1.CardRating.Easy:
|
|
92
|
-
return
|
|
96
|
+
return "Easy (recalled instantly)";
|
|
93
97
|
default:
|
|
94
|
-
return
|
|
98
|
+
return "Unknown";
|
|
95
99
|
}
|
|
96
100
|
}
|
|
97
101
|
function createSuccessResponse(data) {
|
|
98
102
|
return {
|
|
99
103
|
content: [
|
|
100
104
|
{
|
|
101
|
-
type:
|
|
105
|
+
type: "text",
|
|
102
106
|
text: JSON.stringify(data, null, 2),
|
|
103
107
|
},
|
|
104
108
|
],
|
|
@@ -107,7 +111,7 @@ function createSuccessResponse(data) {
|
|
|
107
111
|
function createErrorResponse(error, context) {
|
|
108
112
|
const errorData = {
|
|
109
113
|
success: false,
|
|
110
|
-
error: error instanceof Error ? error.message :
|
|
114
|
+
error: error instanceof Error ? error.message : "Unknown error occurred",
|
|
111
115
|
};
|
|
112
116
|
if (error instanceof anki_connect_client_1.AnkiConnectError) {
|
|
113
117
|
if (error.action) {
|
|
@@ -120,7 +124,7 @@ function createErrorResponse(error, context) {
|
|
|
120
124
|
return {
|
|
121
125
|
content: [
|
|
122
126
|
{
|
|
123
|
-
type:
|
|
127
|
+
type: "text",
|
|
124
128
|
text: JSON.stringify(errorData, null, 2),
|
|
125
129
|
},
|
|
126
130
|
],
|
|
@@ -130,17 +134,17 @@ function createErrorResponse(error, context) {
|
|
|
130
134
|
function formatInterval(days) {
|
|
131
135
|
if (days < 1) {
|
|
132
136
|
const hours = Math.round(days * 24);
|
|
133
|
-
return `${hours} hour${hours !== 1 ?
|
|
137
|
+
return `${hours} hour${hours !== 1 ? "s" : ""}`;
|
|
134
138
|
}
|
|
135
139
|
if (days < 30) {
|
|
136
|
-
return `${Math.round(days)} day${days !== 1 ?
|
|
140
|
+
return `${Math.round(days)} day${days !== 1 ? "s" : ""}`;
|
|
137
141
|
}
|
|
138
142
|
if (days < 365) {
|
|
139
143
|
const months = Math.round(days / 30);
|
|
140
|
-
return `${months} month${months !== 1 ?
|
|
144
|
+
return `${months} month${months !== 1 ? "s" : ""}`;
|
|
141
145
|
}
|
|
142
|
-
const years = Math.round(days / 365 * 10) / 10;
|
|
143
|
-
return `${years} year${years !== 1 ?
|
|
146
|
+
const years = Math.round((days / 365) * 10) / 10;
|
|
147
|
+
return `${years} year${years !== 1 ? "s" : ""}`;
|
|
144
148
|
}
|
|
145
149
|
function parseDeckStats(stats) {
|
|
146
150
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"anki.utils.js","sourceRoot":"","sources":["../../../src/mcp/utils/anki.utils.ts"],"names":[],"mappings":";;AAWA,8BAWC;AAKD,
|
|
1
|
+
{"version":3,"file":"anki.utils.js","sourceRoot":"","sources":["../../../src/mcp/utils/anki.utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,25 +8,29 @@ const unified_1 = require("unified");
|
|
|
8
8
|
const remark_parse_1 = __importDefault(require("remark-parse"));
|
|
9
9
|
const unist_util_visit_1 = require("unist-util-visit");
|
|
10
10
|
function nodeToString(node) {
|
|
11
|
-
if (node.type ===
|
|
11
|
+
if (node.type === "text") {
|
|
12
12
|
return node.value;
|
|
13
13
|
}
|
|
14
|
-
if (node.type ===
|
|
14
|
+
if (node.type === "inlineCode") {
|
|
15
15
|
return `\`${node.value}\``;
|
|
16
16
|
}
|
|
17
|
-
if (
|
|
18
|
-
return node.children
|
|
17
|
+
if ("children" in node && Array.isArray(node.children)) {
|
|
18
|
+
return node.children
|
|
19
|
+
.map((child) => nodeToString(child))
|
|
20
|
+
.join("");
|
|
19
21
|
}
|
|
20
|
-
if (
|
|
22
|
+
if ("value" in node && typeof node.value === "string") {
|
|
21
23
|
return node.value;
|
|
22
24
|
}
|
|
23
|
-
return
|
|
25
|
+
return "";
|
|
24
26
|
}
|
|
25
27
|
function extractHeadingText(node) {
|
|
26
|
-
if (
|
|
27
|
-
return node.children
|
|
28
|
+
if ("children" in node && Array.isArray(node.children)) {
|
|
29
|
+
return node.children
|
|
30
|
+
.map((child) => nodeToString(child))
|
|
31
|
+
.join("");
|
|
28
32
|
}
|
|
29
|
-
return
|
|
33
|
+
return "";
|
|
30
34
|
}
|
|
31
35
|
function parseMarkdownSections(markdown) {
|
|
32
36
|
const tree = (0, unified_1.unified)().use(remark_parse_1.default).parse(markdown);
|
|
@@ -34,9 +38,9 @@ function parseMarkdownSections(markdown) {
|
|
|
34
38
|
let currentHeading = null;
|
|
35
39
|
let currentContent = [];
|
|
36
40
|
(0, unist_util_visit_1.visit)(tree, (node) => {
|
|
37
|
-
if (node.type ===
|
|
41
|
+
if (node.type === "heading" && node.depth === 1) {
|
|
38
42
|
if (currentHeading) {
|
|
39
|
-
sections[currentHeading] = currentContent.join(
|
|
43
|
+
sections[currentHeading] = currentContent.join("\n").trim();
|
|
40
44
|
}
|
|
41
45
|
currentHeading = extractHeadingText(node);
|
|
42
46
|
currentContent = [];
|
|
@@ -49,7 +53,7 @@ function parseMarkdownSections(markdown) {
|
|
|
49
53
|
}
|
|
50
54
|
});
|
|
51
55
|
if (currentHeading) {
|
|
52
|
-
sections[currentHeading] = currentContent.join(
|
|
56
|
+
sections[currentHeading] = currentContent.join("\n").trim();
|
|
53
57
|
}
|
|
54
58
|
return sections;
|
|
55
59
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"markdown.utils.js","sourceRoot":"","sources":["../../../src/mcp/utils/markdown.utils.ts"],"names":[],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"markdown.utils.js","sourceRoot":"","sources":["../../../src/mcp/utils/markdown.utils.ts"],"names":[],"mappings":";;;;;AAsEA,sDAgCC;AAtGD,qCAAkC;AAClC,gEAAuC;AACvC,uDAAyC;AAezC,SAAS,YAAY,CAAC,IAAiB;IACrC,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QACzB,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IACD,IAAI,IAAI,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;QAC/B,OAAO,KAAK,IAAI,CAAC,KAAK,IAAI,CAAC;IAC7B,CAAC;IACD,IAAI,UAAU,IAAI,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;QACvD,OAAO,IAAI,CAAC,QAAQ;aACjB,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,YAAY,CAAC,KAAoB,CAAC,CAAC;aAClD,IAAI,CAAC,EAAE,CAAC,CAAC;IACd,CAAC;IACD,IAAI,OAAO,IAAI,IAAI,IAAI,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;QACtD,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC;AAKD,SAAS,kBAAkB,CAAC,IAAiB;IAC3C,IAAI,UAAU,IAAI,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;QACvD,OAAO,IAAI,CAAC,QAAQ;aACjB,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,YAAY,CAAC,KAAoB,CAAC,CAAC;aAClD,IAAI,CAAC,EAAE,CAAC,CAAC;IACd,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC;AAyBD,SAAgB,qBAAqB,CAAC,QAAgB;IACpD,MAAM,IAAI,GAAG,IAAA,iBAAO,GAAE,CAAC,GAAG,CAAC,sBAAW,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAS,CAAC;IAChE,MAAM,QAAQ,GAAqB,EAAE,CAAC;IAEtC,IAAI,cAAc,GAAkB,IAAI,CAAC;IACzC,IAAI,cAAc,GAAa,EAAE,CAAC;IAElC,IAAA,wBAAK,EAAC,IAAI,EAAE,CAAC,IAAI,EAAE,EAAE;QACnB,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,KAAK,KAAK,CAAC,EAAE,CAAC;YAEhD,IAAI,cAAc,EAAE,CAAC;gBACnB,QAAQ,CAAC,cAAc,CAAC,GAAG,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;YAC9D,CAAC;YAGD,cAAc,GAAG,kBAAkB,CAAC,IAAmB,CAAC,CAAC;YACzD,cAAc,GAAG,EAAE,CAAC;QACtB,CAAC;aAAM,IAAI,cAAc,EAAE,CAAC;YAE1B,MAAM,OAAO,GAAG,YAAY,CAAC,IAAmB,CAAC,CAAC;YAClD,IAAI,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC;gBACnB,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;YACtC,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAC;IAGH,IAAI,cAAc,EAAE,CAAC;QACnB,QAAQ,CAAC,cAAc,CAAC,GAAG,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;IAC9D,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.sanitizeMcpbConfigValue = sanitizeMcpbConfigValue;
|
|
4
4
|
function sanitizeMcpbConfigValue(value) {
|
|
5
|
-
if (!value || value.trim() ===
|
|
5
|
+
if (!value || value.trim() === "") {
|
|
6
6
|
return undefined;
|
|
7
7
|
}
|
|
8
|
-
if (value.startsWith(
|
|
8
|
+
if (value.startsWith("${") && value.endsWith("}")) {
|
|
9
9
|
return undefined;
|
|
10
10
|
}
|
|
11
11
|
return value;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcpb-workarounds.js","sourceRoot":"","sources":["../../../src/mcp/utils/mcpb-workarounds.ts"],"names":[],"mappings":";;AA0BA,
|
|
1
|
+
{"version":3,"file":"mcpb-workarounds.js","sourceRoot":"","sources":["../../../src/mcp/utils/mcpb-workarounds.ts"],"names":[],"mappings":";;AA0BA,0DAaC;AAbD,SAAgB,uBAAuB,CACrC,KAAyB;IAEzB,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QAClC,OAAO,SAAS,CAAC;IACnB,CAAC;IAGD,IAAI,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QAClD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface NgrokTunnelInfo {
|
|
2
|
+
publicUrl: string;
|
|
3
|
+
apiUrl: string;
|
|
4
|
+
}
|
|
5
|
+
export declare class NgrokService {
|
|
6
|
+
private process;
|
|
7
|
+
private cleanupHandlersRegistered;
|
|
8
|
+
start(port: number): Promise<NgrokTunnelInfo>;
|
|
9
|
+
private isNgrokInstalled;
|
|
10
|
+
private waitForNgrok;
|
|
11
|
+
private getTunnelUrl;
|
|
12
|
+
private registerCleanupHandlers;
|
|
13
|
+
private cleanup;
|
|
14
|
+
getWebInterfaceUrl(): string;
|
|
15
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
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.NgrokService = void 0;
|
|
7
|
+
const child_process_1 = require("child_process");
|
|
8
|
+
const http_1 = __importDefault(require("http"));
|
|
9
|
+
class NgrokService {
|
|
10
|
+
process = null;
|
|
11
|
+
cleanupHandlersRegistered = false;
|
|
12
|
+
async start(port) {
|
|
13
|
+
if (!(await this.isNgrokInstalled())) {
|
|
14
|
+
throw new Error("ngrok is not installed.\n" +
|
|
15
|
+
"Install it with: npm install -g ngrok\n" +
|
|
16
|
+
"Or download from: https://ngrok.com/download\n" +
|
|
17
|
+
"Then setup auth: ngrok config add-authtoken <your-token>");
|
|
18
|
+
}
|
|
19
|
+
this.process = (0, child_process_1.spawn)("ngrok", ["http", port.toString()], {
|
|
20
|
+
stdio: "pipe",
|
|
21
|
+
});
|
|
22
|
+
if (!this.cleanupHandlersRegistered) {
|
|
23
|
+
this.registerCleanupHandlers();
|
|
24
|
+
this.cleanupHandlersRegistered = true;
|
|
25
|
+
}
|
|
26
|
+
this.process.on("error", (err) => {
|
|
27
|
+
throw new Error(`Failed to start ngrok: ${err.message}`);
|
|
28
|
+
});
|
|
29
|
+
this.process.on("exit", (code, _signal) => {
|
|
30
|
+
if (code !== 0 && code !== null) {
|
|
31
|
+
console.error(`ngrok exited with code ${code}`);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
await this.waitForNgrok();
|
|
35
|
+
const publicUrl = await this.getTunnelUrl();
|
|
36
|
+
return {
|
|
37
|
+
publicUrl,
|
|
38
|
+
apiUrl: "http://localhost:4040",
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
async isNgrokInstalled() {
|
|
42
|
+
return new Promise((resolve) => {
|
|
43
|
+
const check = (0, child_process_1.spawn)("which", ["ngrok"]);
|
|
44
|
+
check.on("close", (code) => resolve(code === 0));
|
|
45
|
+
check.on("error", () => resolve(false));
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
async waitForNgrok(maxAttempts = 20, delayMs = 500) {
|
|
49
|
+
for (let i = 0; i < maxAttempts; i++) {
|
|
50
|
+
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
51
|
+
try {
|
|
52
|
+
await this.getTunnelUrl();
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
throw new Error("ngrok failed to start in time.\n" +
|
|
59
|
+
"Make sure you have configured your auth token:\n" +
|
|
60
|
+
"ngrok config add-authtoken <your-token>");
|
|
61
|
+
}
|
|
62
|
+
async getTunnelUrl() {
|
|
63
|
+
return new Promise((resolve, reject) => {
|
|
64
|
+
http_1.default
|
|
65
|
+
.get("http://localhost:4040/api/tunnels", (res) => {
|
|
66
|
+
let data = "";
|
|
67
|
+
res.on("data", (chunk) => (data += chunk));
|
|
68
|
+
res.on("end", () => {
|
|
69
|
+
try {
|
|
70
|
+
const response = JSON.parse(data);
|
|
71
|
+
const tunnel = response.tunnels?.find((t) => t.proto === "https");
|
|
72
|
+
const publicUrl = tunnel?.public_url;
|
|
73
|
+
if (publicUrl) {
|
|
74
|
+
resolve(publicUrl);
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
reject(new Error("No HTTPS tunnel found in ngrok API response"));
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
catch (err) {
|
|
81
|
+
reject(new Error(`Failed to parse ngrok API response: ${err}`));
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
})
|
|
85
|
+
.on("error", (err) => {
|
|
86
|
+
reject(new Error(`Failed to connect to ngrok API: ${err.message}`));
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
registerCleanupHandlers() {
|
|
91
|
+
process.on("SIGINT", () => {
|
|
92
|
+
console.log("\n\nš Shutting down ngrok tunnel...");
|
|
93
|
+
this.cleanup();
|
|
94
|
+
process.exit(0);
|
|
95
|
+
});
|
|
96
|
+
process.on("SIGTERM", () => {
|
|
97
|
+
this.cleanup();
|
|
98
|
+
process.exit(0);
|
|
99
|
+
});
|
|
100
|
+
process.on("exit", () => {
|
|
101
|
+
this.cleanup();
|
|
102
|
+
});
|
|
103
|
+
process.on("uncaughtException", (err) => {
|
|
104
|
+
console.error("Uncaught exception:", err);
|
|
105
|
+
this.cleanup();
|
|
106
|
+
process.exit(1);
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
cleanup() {
|
|
110
|
+
if (this.process && !this.process.killed) {
|
|
111
|
+
this.process.kill("SIGTERM");
|
|
112
|
+
this.process = null;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
getWebInterfaceUrl() {
|
|
116
|
+
return "http://localhost:4040";
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
exports.NgrokService = NgrokService;
|
|
120
|
+
//# sourceMappingURL=ngrok.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ngrok.service.js","sourceRoot":"","sources":["../../src/services/ngrok.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -53,7 +53,7 @@ export declare const mockNotes: {
|
|
|
53
53
|
};
|
|
54
54
|
export declare const mockDecks: {
|
|
55
55
|
withStats: {
|
|
56
|
-
|
|
56
|
+
"1651445861967": {
|
|
57
57
|
deck_id: number;
|
|
58
58
|
name: string;
|
|
59
59
|
new_count: number;
|
|
@@ -61,7 +61,7 @@ export declare const mockDecks: {
|
|
|
61
61
|
review_count: number;
|
|
62
62
|
total_in_deck: number;
|
|
63
63
|
};
|
|
64
|
-
|
|
64
|
+
"1651445861968": {
|
|
65
65
|
deck_id: number;
|
|
66
66
|
name: string;
|
|
67
67
|
new_count: number;
|