Skip to content

Commit 8eb8267

Browse files
committed
updates
1 parent 034aab1 commit 8eb8267

File tree

1 file changed

+66
-16
lines changed

1 file changed

+66
-16
lines changed

main.go

Lines changed: 66 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -75,11 +75,11 @@ func (a *AnkiMCPServer) registerTools(s *server.MCPServer) {
7575
),
7676
mcp.WithString("front",
7777
mcp.Required(),
78-
mcp.Description("Front side content of the card"),
78+
mcp.Description("Front side content of the card (HTML supported, use [sound:filename] for audio)"),
7979
),
8080
mcp.WithString("back",
8181
mcp.Required(),
82-
mcp.Description("Back side content of the card"),
82+
mcp.Description("Back side content of the card (HTML supported, use [sound:filename] for audio)"),
8383
),
8484
mcp.WithString("model_name",
8585
mcp.Description("Model/note type to use (default: Basic)"),
@@ -128,25 +128,25 @@ func (a *AnkiMCPServer) registerTools(s *server.MCPServer) {
128128
),
129129
mcp.WithString("data",
130130
mcp.Required(),
131-
mcp.Description("Base64 encoded media file data"),
131+
mcp.Description("Media data - either base64 encoded data, a data URI (data:type/subtype;base64,...), or a file path to the media file"),
132132
),
133133
)
134134
s.AddTool(addMediaTool, a.handleAddMedia)
135135

136-
// Tool: Create Card with Media (simplified)
136+
// Tool: Create Card with Media
137137
createCardWithMediaTool := mcp.NewTool("create_card_with_media",
138-
mcp.WithDescription("Create a new Anki card with media attachments"),
138+
mcp.WithDescription("Create a new Anki card with media attachments. Media files are uploaded but not automatically embedded - use [sound:filename] or <img src=\"filename\"> tags in your content"),
139139
mcp.WithString("deck_name",
140140
mcp.Required(),
141141
mcp.Description("Name of the deck to add the card to"),
142142
),
143143
mcp.WithString("front",
144144
mcp.Required(),
145-
mcp.Description("Front side content of the card"),
145+
mcp.Description("Front side content of the card (HTML supported, use [sound:filename] for audio)"),
146146
),
147147
mcp.WithString("back",
148148
mcp.Required(),
149-
mcp.Description("Back side content of the card"),
149+
mcp.Description("Back side content of the card (HTML supported, use [sound:filename] for audio)"),
150150
),
151151
mcp.WithString("model_name",
152152
mcp.Description("Model/note type to use (default: Basic)"),
@@ -155,16 +155,16 @@ func (a *AnkiMCPServer) registerTools(s *server.MCPServer) {
155155
mcp.Description("Tags to add to the card"),
156156
),
157157
mcp.WithString("audio_filename",
158-
mcp.Description("Audio filename to attach"),
158+
mcp.Description("Filename for the audio file (e.g., 'pronunciation.mp3')"),
159159
),
160160
mcp.WithString("audio_data",
161-
mcp.Description("Base64 encoded audio data"),
161+
mcp.Description("Audio data - either base64 encoded audio, a data URI (data:audio/mpeg;base64,...), or a file path to an audio file"),
162162
),
163163
mcp.WithString("image_filename",
164-
mcp.Description("Image filename to attach"),
164+
mcp.Description("Filename for the image file (e.g., 'diagram.png')"),
165165
),
166166
mcp.WithString("image_data",
167-
mcp.Description("Base64 encoded image data"),
167+
mcp.Description("Image data - either base64 encoded image, a data URI (data:image/png;base64,...), or a file path to an image file"),
168168
),
169169
)
170170
s.AddTool(createCardWithMediaTool, a.handleCreateCardWithMedia)
@@ -404,8 +404,14 @@ func (a *AnkiMCPServer) handleAddMedia(ctx context.Context, request mcp.CallTool
404404
return errorResult("data is required and must be a string"), nil
405405
}
406406

407+
// Process the media data (convert from file path if needed)
408+
processedData, err := processMediaData(dataStr)
409+
if err != nil {
410+
return errorResult(fmt.Sprintf("Failed to process media data: %v", err)), nil
411+
}
412+
407413
// Decode base64 data
408-
data, err := base64.StdEncoding.DecodeString(dataStr)
414+
data, err := base64.StdEncoding.DecodeString(processedData)
409415
if err != nil {
410416
return errorResult(fmt.Sprintf("Failed to decode base64 data: %v", err)), nil
411417
}
@@ -474,21 +480,29 @@ func (a *AnkiMCPServer) handleCreateCardWithMedia(ctx context.Context, request m
474480
// Process audio file
475481
if audioFilename, ok := args["audio_filename"].(string); ok && audioFilename != "" {
476482
if audioData, ok := args["audio_data"].(string); ok && audioData != "" {
483+
// Process the audio data (convert from file path if needed)
484+
processedData, err := processMediaData(audioData)
485+
if err != nil {
486+
return errorResult(fmt.Sprintf("Failed to process audio data: %v", err)), nil
487+
}
477488
note.Audio = append(note.Audio, MediaFile{
478489
Filename: audioFilename,
479-
Data: audioData,
480-
Fields: []string{"Front"},
490+
Data: processedData,
481491
})
482492
}
483493
}
484494

485495
// Process image file
486496
if imageFilename, ok := args["image_filename"].(string); ok && imageFilename != "" {
487497
if imageData, ok := args["image_data"].(string); ok && imageData != "" {
498+
// Process the image data (convert from file path if needed)
499+
processedData, err := processMediaData(imageData)
500+
if err != nil {
501+
return errorResult(fmt.Sprintf("Failed to process image data: %v", err)), nil
502+
}
488503
note.Picture = append(note.Picture, MediaFile{
489504
Filename: imageFilename,
490-
Data: imageData,
491-
Fields: []string{"Front"},
505+
Data: processedData,
492506
})
493507
}
494508
}
@@ -597,3 +611,39 @@ func errorResult(message string) *mcp.CallToolResult {
597611
IsError: true,
598612
}
599613
}
614+
615+
// fileToBase64 reads a file and returns its contents as a base64 string
616+
func fileToBase64(filePath string) (string, error) {
617+
data, err := os.ReadFile(filePath)
618+
if err != nil {
619+
return "", fmt.Errorf("failed to read file %s: %w", filePath, err)
620+
}
621+
return base64.StdEncoding.EncodeToString(data), nil
622+
}
623+
624+
// processMediaData handles both base64 data and file paths
625+
// If the input looks like a file path and the file exists, it reads and converts to base64
626+
// If it's a data URI, it extracts the base64 portion
627+
// Otherwise, it assumes the input is already base64 encoded
628+
func processMediaData(data string) (string, error) {
629+
// Check if it's a data URI and extract base64 portion
630+
if strings.HasPrefix(data, "data:") {
631+
parts := strings.Split(data, ",")
632+
if len(parts) == 2 {
633+
return parts[1], nil
634+
}
635+
return "", fmt.Errorf("invalid data URI format")
636+
}
637+
638+
// Check if it's likely a file path (contains / or \ and doesn't look like base64)
639+
if (strings.Contains(data, "/") || strings.Contains(data, "\\")) && !strings.Contains(data, "base64,") {
640+
// Check if file exists
641+
if _, err := os.Stat(data); err == nil {
642+
// File exists, read and convert to base64
643+
return fileToBase64(data)
644+
}
645+
}
646+
647+
// Assume it's already base64 data
648+
return data, nil
649+
}

0 commit comments

Comments
 (0)