UNPKG

@ankimcp/anki-mcp-server

Version:

Model Context Protocol server for Anki - enables AI assistants to interact with your Anki flashcards

137 lines • 6.6 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 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; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; var __param = (this && this.__param) || function (paramIndex, decorator) { return function (target, key) { decorator(target, key, paramIndex); } }; var NotesInfoTool_1; Object.defineProperty(exports, "__esModule", { value: true }); exports.NotesInfoTool = void 0; const common_1 = require("@nestjs/common"); const microservices_1 = require("@nestjs/microservices"); const mcp_nest_1 = require("@rekog/mcp-nest"); const zod_1 = require("zod"); const anki_connect_client_1 = require("../../../clients/anki-connect.client.js"); const anki_utils_1 = require("../../../utils/anki.utils.js"); let NotesInfoTool = NotesInfoTool_1 = class NotesInfoTool { ankiClient; logger = new common_1.Logger(NotesInfoTool_1.name); constructor(ankiClient) { this.ankiClient = ankiClient; } async notesInfo({ notes }) { try { this.logger.log(`Getting information for ${notes.length} note(s)`); const notesData = await this.ankiClient.invoke("notesInfo", { notes: notes, }); if (!notesData || notesData.length === 0) { this.logger.warn("No note information returned"); return (0, anki_utils_1.createErrorResponse)(new Error("No note information found"), { requestedNotes: notes, hint: "The note IDs may be invalid or the notes may have been deleted", }); } const transformedNotes = notesData.map((note) => ({ noteId: note.noteId, modelName: note.modelName, tags: note.tags || [], fields: note.fields || {}, cards: note.cards || [], mod: note.mod, })); const validNotes = transformedNotes.filter((note) => note.noteId); const deletedCount = notes.length - validNotes.length; const message = deletedCount > 0 ? `Retrieved ${validNotes.length} note(s). ${deletedCount} note(s) not found (possibly deleted).` : `Successfully retrieved information for ${validNotes.length} note(s)`; this.logger.log(message); const uniqueModels = [...new Set(validNotes.map((n) => n.modelName))]; return { success: true, notes: validNotes, count: validNotes.length, notFound: deletedCount, requestedIds: notes, message: message, models: uniqueModels, cssNote: "CSS is stored per note type; modelStyling returns it.", hint: validNotes.length > 0 ? "Fields may contain HTML. updateNoteFields modifies content; its changes do not persist for a note that is open in Anki's browser." : "No valid notes found. They may have been deleted.", }; } catch (error) { this.logger.error("Failed to get notes information", error); if (error instanceof Error) { if (error.message.includes("not found")) { return (0, anki_utils_1.createErrorResponse)(error, { requestedNotes: notes, hint: "One or more note IDs are invalid. findNotes returns valid note IDs.", }); } } return (0, anki_utils_1.createErrorResponse)(error, { requestedNotes: notes, hint: "This can happen when Anki is not running or the note IDs are invalid", }); } } }; exports.NotesInfoTool = NotesInfoTool; __decorate([ (0, mcp_nest_1.Tool)({ name: "notesInfo", description: "Get fields, tags, note type (model) name, card IDs and modification time for each note, by note ID (from findNotes). " + "CSS is stored per note type and is not included; modelStyling returns it.", parameters: zod_1.z.object({ notes: zod_1.z .array(zod_1.z.number()) .min(1) .max(100) .describe("Array of note IDs to get information for (max 100 at once for performance). " + "Get these IDs from findNotes tool."), }), outputSchema: zod_1.z.object({ success: zod_1.z.boolean(), notes: zod_1.z.array(zod_1.z.object({ noteId: zod_1.z.number(), modelName: zod_1.z.string(), tags: zod_1.z.array(zod_1.z.string()), fields: zod_1.z.record(zod_1.z.string(), zod_1.z.object({ value: zod_1.z.string(), order: zod_1.z.number() })), cards: zod_1.z.array(zod_1.z.number()), mod: zod_1.z.number().optional(), })), count: zod_1.z.number(), notFound: zod_1.z.number(), requestedIds: zod_1.z.array(zod_1.z.number()), message: zod_1.z.string(), models: zod_1.z.array(zod_1.z.string()), cssNote: zod_1.z.string(), hint: zod_1.z.string(), }), annotations: { title: "Get Notes Info", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false, }, }), __param(0, (0, microservices_1.Payload)()), __metadata("design:type", Function), __metadata("design:paramtypes", [Object]), __metadata("design:returntype", Promise) ], NotesInfoTool.prototype, "notesInfo", null); exports.NotesInfoTool = NotesInfoTool = NotesInfoTool_1 = __decorate([ (0, mcp_nest_1.McpController)(), __metadata("design:paramtypes", [anki_connect_client_1.AnkiConnectClient]) ], NotesInfoTool); //# sourceMappingURL=notes-info.tool.js.map