mcp-server-anki
Version:
Model Context Protocol (MCP) server enabling AI assistants (Claude, GPT-4, Gemini, etc.) to interact with Anki flashcards through AnkiConnect.
164 lines • 5.2 kB
JavaScript
/**
* AnkiConnect Client
* Handles communication with the AnkiConnect plugin
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.AnkiConnectClient = void 0;
/**
* AnkiConnect client for communicating with Anki desktop application
*/
class AnkiConnectClient {
constructor(port = 8765, timeout = 5000) {
this.baseUrl = `http://localhost:${port}`;
this.timeout = timeout;
}
/**
* Send a request to AnkiConnect
* @param action - The AnkiConnect action to perform
* @param params - Parameters for the action
* @returns Promise resolving to the action result
*/
async invoke(action, params = {}) {
const requestBody = {
action,
version: 6,
params
};
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
const response = await fetch(this.baseUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(requestBody),
signal: controller.signal
});
clearTimeout(timeoutId);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const result = await response.json();
if (result.error) {
throw new Error(`AnkiConnect error: ${result.error}`);
}
return result.result;
}
/**
* Test connection to AnkiConnect
* @returns Promise resolving to true if connection successful
*/
async testConnection() {
try {
await this.invoke('version');
return true;
}
catch {
return false;
}
}
/**
* Get all deck names
* @returns Promise resolving to array of deck names
*/
async getDeckNames() {
return this.invoke('deckNames');
}
/**
* Get cards in a specific deck
* @param deckName - Name of the deck
* @param limit - Maximum number of cards to return
* @returns Promise resolving to array of card IDs
*/
async getCardsInDeck(deckName, limit) {
let query = `deck:"${deckName}"`;
const cardIds = await this.invoke('findCards', { query });
return limit ? cardIds.slice(0, limit) : cardIds;
}
/**
* Get detailed information about cards
* @param cardIds - Array of card IDs
* @returns Promise resolving to array of card information
*/
async getCardsInfo(cardIds) {
return this.invoke('cardsInfo', { cards: cardIds });
}
/**
* Search for cards using Anki query syntax
* @param query - Anki search query
* @param limit - Maximum number of cards to return
* @returns Promise resolving to array of card IDs
*/
async searchCards(query, limit) {
const cardIds = await this.invoke('findCards', { query });
return limit ? cardIds.slice(0, limit) : cardIds;
}
/**
* Add a new note to Anki
* @param params - Note parameters including deck, model, fields, and tags
* @returns Promise resolving to the new note ID
*/
async addNote(params) {
const noteData = {
note: {
deckName: params.deckName,
modelName: params.modelName,
fields: params.fields,
tags: params.tags || []
}
};
return this.invoke('addNote', noteData);
}
/**
* Get information about a specific note
* @param noteId - The note ID
* @returns Promise resolving to note information
*/
async getNoteInfo(noteId) {
const notes = await this.invoke('notesInfo', { notes: [noteId] });
if (notes.length === 0) {
throw new Error(`Note with ID ${noteId} not found`);
}
return notes[0];
}
/**
* Get all available note types (models)
* @returns Promise resolving to array of model names
*/
async getModelNames() {
return this.invoke('modelNames');
}
/**
* Get field names for a specific model
* @param modelName - Name of the note type/model
* @returns Promise resolving to array of field names
*/
async getModelFieldNames(modelName) {
return this.invoke('modelFieldNames', { modelName });
}
/**
* Update fields of an existing note
* @param noteId - The note ID to update
* @param fields - Object with field names as keys and new values
* @returns Promise resolving to null on success
*/
async updateNoteFields(noteId, fields) {
return this.invoke('updateNoteFields', {
note: {
id: noteId,
fields
}
});
}
/**
* Delete notes by their IDs
* @param noteIds - Array of note IDs to delete
* @returns Promise resolving to null on success
*/
async deleteNotes(noteIds) {
return this.invoke('deleteNotes', { notes: noteIds });
}
}
exports.AnkiConnectClient = AnkiConnectClient;
//# sourceMappingURL=anki-connect.js.map
;