get_media_file
Retrieve media files from Anki cards by specifying the filename to access images, audio, or other embedded content for card management.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| filename | Yes | Media filename referenced in Anki cards (e.g., "image.png") |
Implementation Reference
- src/tools/consolidated.ts:1177-1265 (handler)The handler function that implements the core logic: validates the filename for security, retrieves the base64-encoded media file content from Anki using ankiClient.media.retrieveMediaFile, determines the MIME type based on file extension, calculates approximate size, and returns appropriate MCP content (image block for images analyzable by AI, or JSON text for other files). Handles errors gracefully.async ({ filename }) => { try { // Validate filename (basic security check) if ( !filename || filename.includes('..') || filename.includes('/') || filename.includes('\\') ) { throw new Error('Invalid filename: must be a simple filename without path traversal'); } // Retrieve the media file from AnkiConnect const base64Content = await ankiClient.media.retrieveMediaFile({ filename }); if (base64Content === false) { return { content: [ { type: 'text', text: JSON.stringify({ error: `File not found: ${filename}`, filename, }), }, ], }; } // Detect MIME type from file extension const extension = filename.split('.').pop()?.toLowerCase() || ''; const mimeType = MIME_TYPES[extension] || 'application/octet-stream'; // Calculate size (approximate from base64 length) const size = Math.floor((base64Content.length * 3) / 4); // Return the file data with metadata const response = { filename, mimeType, base64Data: base64Content, size, }; // For images, return as image content that Claude can analyze // Note: Claude can see the image but it won't display to the user if (mimeType.startsWith('image/')) { return { content: [ { type: 'image', data: base64Content, mimeType, }, { type: 'text', text: `📷 Image: ${filename} Format: ${mimeType} Size: ${(size / 1024).toFixed(1)} KB Note: I can see and analyze this image, but it won't display in the UI. I can describe what I see or answer questions about it.`, }, ], }; } // For non-images, return as text with metadata return { content: [ { type: 'text', text: JSON.stringify(response, null, 2), }, ], }; } catch (error) { return { content: [ { type: 'text', text: JSON.stringify({ error: `Failed to retrieve media file: ${error instanceof Error ? error.message : String(error)}`, filename, }), }, ], }; } }
- src/tools/consolidated.ts:1174-1176 (schema)The input schema using Zod, defining a single required 'filename' parameter as a string with description.{ filename: z.string().describe('Media filename referenced in Anki cards (e.g., "image.png")'), },
- src/tools/consolidated.ts:1172-1173 (registration)The MCP server.tool registration call for the 'get_media_file' tool within the registerConsolidatedTools function.server.tool( 'get_media_file',
- src/tools/consolidated.ts:8-23 (helper)Constant mapping of common file extensions to MIME types, used by the handler to determine the content type for proper rendering.const MIME_TYPES: Record<string, string> = { png: 'image/png', jpg: 'image/jpeg', jpeg: 'image/jpeg', gif: 'image/gif', svg: 'image/svg+xml', webp: 'image/webp', bmp: 'image/bmp', ico: 'image/x-icon', mp3: 'audio/mpeg', wav: 'audio/wav', ogg: 'audio/ogg', mp4: 'video/mp4', webm: 'video/webm', pdf: 'application/pdf', };