manage_models
Create, modify, and organize Anki note types by managing fields, templates, and styling to customize flashcard structure for effective learning.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| operation | Yes | Model management operation | |
| modelName | No | Model/note type name | |
| fields | No | Field names in order (for create) | |
| templates | No | Card templates (for create) | |
| css | No | CSS styling | |
| isCloze | No | Is cloze deletion type | |
| fieldName | No | Field name | |
| newFieldName | No | New field name (for rename) | |
| fieldIndex | No | Field index position | |
| templateName | No | Template name | |
| template | No | Template content |
Implementation Reference
- src/tools/consolidated.ts:809-964 (handler)The main handler function for the 'manage_models' tool. It handles various operations (list, create, add_field, remove_field, rename_field, add_template, remove_template, update_styling) on Anki note types (models) using the ankiClient.model API.async ({ operation, modelName, fields, templates, css, isCloze, fieldName, newFieldName, fieldIndex, templateName, template, }) => { try { switch (operation) { case 'list': { const models = await ankiClient.model.modelNamesAndIds(); const modelList = Object.entries(models) .map(([name, id]) => ` • ${name} (ID: ${id})`) .join('\n'); return { content: [ { type: 'text', text: `Note Types (${Object.keys(models).length}):\n${modelList}`, }, ], }; } case 'create': { if (!modelName || !fields || !templates) { throw new Error('create requires modelName, fields, and templates'); } const modelParams: any = { modelName, inOrderFields: fields, cardTemplates: templates, }; if (css) modelParams.css = css; if (isCloze !== undefined) modelParams.isCloze = isCloze; const result = await ankiClient.model.createModel(modelParams); return { content: [ { type: 'text', text: `✓ Created note type "${modelName}" (ID: ${result.id})`, }, ], }; } case 'add_field': { if (!modelName || !fieldName || fieldIndex === undefined) { throw new Error('add_field requires modelName, fieldName, and fieldIndex'); } await ankiClient.model.modelFieldAdd({ modelName, fieldName, index: fieldIndex }); return { content: [ { type: 'text', text: `✓ Added field "${fieldName}" to "${modelName}" at position ${fieldIndex}`, }, ], }; } case 'remove_field': { if (!modelName || !fieldName) { throw new Error('remove_field requires modelName and fieldName'); } await ankiClient.model.modelFieldRemove({ modelName, fieldName }); return { content: [ { type: 'text', text: `✓ Removed field "${fieldName}" from "${modelName}"`, }, ], }; } case 'rename_field': { if (!modelName || !fieldName || !newFieldName) { throw new Error('rename_field requires modelName, fieldName, and newFieldName'); } await ankiClient.model.modelFieldRename({ modelName, oldFieldName: fieldName, newFieldName, }); return { content: [ { type: 'text', text: `✓ Renamed field "${fieldName}" to "${newFieldName}" in "${modelName}"`, }, ], }; } case 'add_template': { if (!modelName || !template) { throw new Error('add_template requires modelName and template'); } await ankiClient.model.modelTemplateAdd({ modelName, template }); return { content: [ { type: 'text', text: `✓ Added template to "${modelName}"`, }, ], }; } case 'remove_template': { if (!modelName || !templateName) { throw new Error('remove_template requires modelName and templateName'); } await ankiClient.model.modelTemplateRemove({ modelName, templateName }); return { content: [ { type: 'text', text: `✓ Removed template "${templateName}" from "${modelName}"`, }, ], }; } case 'update_styling': { if (!modelName || !css) { throw new Error('update_styling requires modelName and css'); } await ankiClient.model.updateModelStyling({ model: { name: modelName, css } }); return { content: [ { type: 'text', text: `✓ Updated styling for "${modelName}"`, }, ], }; } default: throw new Error(`Unknown operation: ${operation}`); } } catch (error) { throw new Error( `manage_models failed: ${error instanceof Error ? error.message : String(error)}` ); } }
- src/tools/consolidated.ts:764-808 (schema)Zod schema defining the input parameters for the 'manage_models' tool, including the operation enum and conditional fields for different operations.{ operation: z .enum([ 'list', 'create', 'add_field', 'remove_field', 'rename_field', 'add_template', 'remove_template', 'update_styling', ]) .describe('Model management operation'), modelName: z.string().optional().describe('Model/note type name'), // For create fields: z.array(z.string()).optional().describe('Field names in order (for create)'), templates: z .array( z.object({ Front: z.string(), Back: z.string(), }) ) .optional() .describe('Card templates (for create)'), css: z.string().optional().describe('CSS styling'), isCloze: z.boolean().optional().describe('Is cloze deletion type'), // For field operations fieldName: z.string().optional().describe('Field name'), newFieldName: z.string().optional().describe('New field name (for rename)'), fieldIndex: z.number().optional().describe('Field index position'), // For template operations templateName: z.string().optional().describe('Template name'), template: z .object({ Front: z.string(), Back: z.string(), }) .optional() .describe('Template content'), },
- src/tools/consolidated.ts:762-965 (registration)Registration of the 'manage_models' tool using server.tool(), including schema and handler.server.tool( 'manage_models', { operation: z .enum([ 'list', 'create', 'add_field', 'remove_field', 'rename_field', 'add_template', 'remove_template', 'update_styling', ]) .describe('Model management operation'), modelName: z.string().optional().describe('Model/note type name'), // For create fields: z.array(z.string()).optional().describe('Field names in order (for create)'), templates: z .array( z.object({ Front: z.string(), Back: z.string(), }) ) .optional() .describe('Card templates (for create)'), css: z.string().optional().describe('CSS styling'), isCloze: z.boolean().optional().describe('Is cloze deletion type'), // For field operations fieldName: z.string().optional().describe('Field name'), newFieldName: z.string().optional().describe('New field name (for rename)'), fieldIndex: z.number().optional().describe('Field index position'), // For template operations templateName: z.string().optional().describe('Template name'), template: z .object({ Front: z.string(), Back: z.string(), }) .optional() .describe('Template content'), }, async ({ operation, modelName, fields, templates, css, isCloze, fieldName, newFieldName, fieldIndex, templateName, template, }) => { try { switch (operation) { case 'list': { const models = await ankiClient.model.modelNamesAndIds(); const modelList = Object.entries(models) .map(([name, id]) => ` • ${name} (ID: ${id})`) .join('\n'); return { content: [ { type: 'text', text: `Note Types (${Object.keys(models).length}):\n${modelList}`, }, ], }; } case 'create': { if (!modelName || !fields || !templates) { throw new Error('create requires modelName, fields, and templates'); } const modelParams: any = { modelName, inOrderFields: fields, cardTemplates: templates, }; if (css) modelParams.css = css; if (isCloze !== undefined) modelParams.isCloze = isCloze; const result = await ankiClient.model.createModel(modelParams); return { content: [ { type: 'text', text: `✓ Created note type "${modelName}" (ID: ${result.id})`, }, ], }; } case 'add_field': { if (!modelName || !fieldName || fieldIndex === undefined) { throw new Error('add_field requires modelName, fieldName, and fieldIndex'); } await ankiClient.model.modelFieldAdd({ modelName, fieldName, index: fieldIndex }); return { content: [ { type: 'text', text: `✓ Added field "${fieldName}" to "${modelName}" at position ${fieldIndex}`, }, ], }; } case 'remove_field': { if (!modelName || !fieldName) { throw new Error('remove_field requires modelName and fieldName'); } await ankiClient.model.modelFieldRemove({ modelName, fieldName }); return { content: [ { type: 'text', text: `✓ Removed field "${fieldName}" from "${modelName}"`, }, ], }; } case 'rename_field': { if (!modelName || !fieldName || !newFieldName) { throw new Error('rename_field requires modelName, fieldName, and newFieldName'); } await ankiClient.model.modelFieldRename({ modelName, oldFieldName: fieldName, newFieldName, }); return { content: [ { type: 'text', text: `✓ Renamed field "${fieldName}" to "${newFieldName}" in "${modelName}"`, }, ], }; } case 'add_template': { if (!modelName || !template) { throw new Error('add_template requires modelName and template'); } await ankiClient.model.modelTemplateAdd({ modelName, template }); return { content: [ { type: 'text', text: `✓ Added template to "${modelName}"`, }, ], }; } case 'remove_template': { if (!modelName || !templateName) { throw new Error('remove_template requires modelName and templateName'); } await ankiClient.model.modelTemplateRemove({ modelName, templateName }); return { content: [ { type: 'text', text: `✓ Removed template "${templateName}" from "${modelName}"`, }, ], }; } case 'update_styling': { if (!modelName || !css) { throw new Error('update_styling requires modelName and css'); } await ankiClient.model.updateModelStyling({ model: { name: modelName, css } }); return { content: [ { type: 'text', text: `✓ Updated styling for "${modelName}"`, }, ], }; } default: throw new Error(`Unknown operation: ${operation}`); } } catch (error) { throw new Error( `manage_models failed: ${error instanceof Error ? error.message : String(error)}` ); } } );