Skip to main content
Glama

update_note_type

Modify one or more fields of an existing note type, including instructions, description, and metadata schema, ensuring version control with content hash for conflict prevention.

Instructions

Update one or more fields of an existing note type

Input Schema

NameRequiredDescriptionDefault
content_hashYesContent hash of the current note type definition to prevent conflicts
descriptionNoNew description for the note type
instructionsNoNew agent instructions for the note type
metadata_schemaNoArray of metadata field definitions
type_nameYesName of the note type to update
vault_idNoOptional vault ID to operate on. If not provided, uses the current active vault.

Input Schema (JSON Schema)

{ "properties": { "content_hash": { "description": "Content hash of the current note type definition to prevent conflicts", "type": "string" }, "description": { "description": "New description for the note type", "type": "string" }, "instructions": { "description": "New agent instructions for the note type", "type": "string" }, "metadata_schema": { "description": "Array of metadata field definitions", "items": { "properties": { "constraints": { "description": "Field constraints", "properties": { "max": { "type": "number" }, "min": { "type": "number" }, "options": { "items": { "type": "string" }, "type": "array" }, "pattern": { "type": "string" } }, "type": "object" }, "default": { "description": "Default value for the field" }, "description": { "description": "Human-readable description of the field", "type": "string" }, "name": { "description": "Field name", "type": "string" }, "required": { "description": "Whether the field is required", "type": "boolean" }, "type": { "description": "Field type", "enum": [ "string", "number", "boolean", "date", "array", "select" ], "type": "string" } }, "required": [ "name", "type" ], "type": "object" }, "type": "array" }, "type_name": { "description": "Name of the note type to update", "type": "string" }, "vault_id": { "description": "Optional vault ID to operate on. If not provided, uses the current active vault.", "type": "string" } }, "required": [ "type_name", "content_hash" ], "type": "object" }

Implementation Reference

  • Main handler function executing the update_note_type tool: validates args, checks content hash, updates description/instructions/schema, writes to file, returns success/error.
    handleUpdateNoteType = async (args: UpdateNoteTypeArgs) => { // Validate arguments validateToolArgs('update_note_type', args); const { noteTypeManager, workspace } = await this.resolveVaultContext(args.vault_id); try { if (!args.content_hash) { throw new Error('content_hash is required for all note type update operations'); } // Validate that at least one field is provided if ( args.instructions === undefined && args.description === undefined && args.metadata_schema === undefined ) { throw new Error( 'At least one field must be provided: instructions, description, or metadata_schema' ); } // Get current note type info const currentInfo = await noteTypeManager.getNoteTypeDescription(args.type_name); // Validate content hash to prevent conflicts const currentHashableContent = createNoteTypeHashableContent({ description: currentInfo.description, agent_instructions: currentInfo.parsed.agentInstructions.join('\n'), metadata_schema: currentInfo.metadataSchema }); const currentHash = generateContentHash(currentHashableContent); if (currentHash !== args.content_hash) { const error = new Error( 'Note type definition has been modified since last read. Please fetch the latest version.' ) as Error & { code: string; current_hash: string; provided_hash: string; }; error.code = 'content_hash_mismatch'; error.current_hash = currentHash; error.provided_hash = args.content_hash; throw error; } // Start with current description let updatedDescription = currentInfo.description; const fieldsUpdated: string[] = []; // Update instructions if provided if (args.instructions) { // Parse instructions from value (can be newline-separated or bullet points) const instructions = args.instructions .split('\n') .map(line => line.trim()) .filter(line => line.length > 0) .map(line => (line.startsWith('-') ? line.substring(1).trim() : line)) .map(line => `- ${line}`) .join('\n'); // Use the current description and replace the agent instructions section updatedDescription = updatedDescription.replace( /## Agent Instructions\n[\s\S]*?(?=\n## |$)/, `## Agent Instructions\n${instructions}\n` ); fieldsUpdated.push('instructions'); } // Update description if provided if (args.description) { updatedDescription = noteTypeManager.formatNoteTypeDescription( args.type_name, args.description ); fieldsUpdated.push('description'); } // Update metadata schema if provided if (args.metadata_schema) { const fields = args.metadata_schema; // Validate each field definition for (let i = 0; i < fields.length; i++) { const field = fields[i]; if (!field || typeof field !== 'object') { throw new Error(`Field at index ${i} must be an object`); } if (!field.name || typeof field.name !== 'string') { throw new Error(`Field at index ${i} must have a valid "name" string`); } if (!field.type || typeof field.type !== 'string') { throw new Error(`Field at index ${i} must have a valid "type" string`); } // Check for protected fields const protectedFields = new Set(['title', 'filename', 'created', 'updated']); if (protectedFields.has(field.name)) { throw new Error( `Cannot define protected field "${field.name}" in metadata schema. ` + `These fields are automatically managed by the system and cannot be redefined.` ); } const validTypes = ['string', 'number', 'boolean', 'date', 'array', 'select']; if (!validTypes.includes(field.type)) { throw new Error( `Field "${field.name}" has invalid type "${field.type}". Valid types: ${validTypes.join(', ')}` ); } // Validate constraints if present if (field.constraints) { if (typeof field.constraints !== 'object') { throw new Error(`Field "${field.name}" constraints must be an object`); } // Validate select field options if (field.type === 'select') { if ( !field.constraints.options || !Array.isArray(field.constraints.options) ) { throw new Error( `Select field "${field.name}" must have constraints.options array` ); } if (field.constraints.options.length === 0) { throw new Error( `Select field "${field.name}" must have at least one option` ); } } // Validate numeric constraints if ( field.constraints.min !== undefined && typeof field.constraints.min !== 'number' ) { throw new Error(`Field "${field.name}" min constraint must be a number`); } if ( field.constraints.max !== undefined && typeof field.constraints.max !== 'number' ) { throw new Error(`Field "${field.name}" max constraint must be a number`); } if ( field.constraints.min !== undefined && field.constraints.max !== undefined && field.constraints.min > field.constraints.max ) { throw new Error( `Field "${field.name}" min constraint cannot be greater than max` ); } // Validate pattern constraint if (field.constraints.pattern !== undefined) { if (typeof field.constraints.pattern !== 'string') { throw new Error( `Field "${field.name}" pattern constraint must be a string` ); } try { new RegExp(field.constraints.pattern); } catch (regexError) { throw new Error( `Field "${field.name}" pattern constraint is not a valid regex: ${regexError instanceof Error ? regexError.message : 'Unknown regex error'}` ); } } } // Validate default values if present if (field.default !== undefined) { const validationError = this.validateDefaultValue( field.name, field.default, field ); if (validationError) { throw new Error(validationError); } } } // Check for duplicate field names const fieldNames = fields.map(f => f.name); const duplicates = fieldNames.filter( (name, index) => fieldNames.indexOf(name) !== index ); if (duplicates.length > 0) { throw new Error(`Duplicate field names found: ${duplicates.join(', ')}`); } // Create MetadataSchema object and generate the schema section const parsedSchema = { fields }; const schemaSection = MetadataSchemaParser.generateSchemaSection(parsedSchema); updatedDescription = updatedDescription.replace( /## Metadata Schema\n[\s\S]*$/, schemaSection ); fieldsUpdated.push('metadata_schema'); } // Write the updated description to the file in note type directory const descriptionPath = path.join( workspace.getNoteTypePath(args.type_name), '_description.md' ); await fs.writeFile(descriptionPath, updatedDescription, 'utf-8'); // Get the updated note type info const result = await noteTypeManager.getNoteTypeDescription(args.type_name); return { content: [ { type: 'text', text: JSON.stringify( { success: true, type_name: args.type_name, fields_updated: fieldsUpdated, updated_info: { name: result.name, purpose: result.parsed.purpose, agent_instructions: result.parsed.agentInstructions } }, null, 2 ) } ] }; } catch (error) { return { content: [ { type: 'text', text: `Error: ${error instanceof Error ? error.message : 'Unknown error'}` } ], isError: true }; } };
  • JSON Schema definition for update_note_type tool inputs including type_name, instructions, description, metadata_schema, content_hash.
    name: 'update_note_type', description: 'Update an existing note type', inputSchema: { type: 'object', properties: { type_name: { type: 'string', description: 'Name of the note type to update' }, description: { type: 'string', description: 'New description for the note type' }, agent_instructions: { type: 'array', items: { type: 'string' }, description: 'New agent instructions for this note type' }, metadata_schema: { type: 'object', properties: { fields: { type: 'array', items: { type: 'object', properties: { name: { type: 'string', description: 'Name of the metadata field' }, type: { type: 'string', enum: ['string', 'number', 'boolean', 'date', 'array', 'select'], description: 'Type of the metadata field' }, description: { type: 'string', description: 'Optional description of the field' }, required: { type: 'boolean', description: 'Whether this field is required' }, constraints: { type: 'object', description: 'Optional field constraints (min, max, options, etc.)' }, default: { description: 'Optional default value for the field' } }, required: ['name', 'type'] } }, version: { type: 'string', description: 'Optional schema version' } }, required: ['fields'], description: 'New metadata schema definition for this note type' }, content_hash: { type: 'string', description: 'Content hash of the note type being updated (for concurrent update protection)' }, vault_id: { type: 'string', description: 'Optional vault ID to operate on. If not provided, uses the current active vault.' } }, required: ['type_name'] } },
  • MCP tool registration: switch case in CallToolRequestSchema handler that routes 'update_note_type' calls to NoteTypeHandlers.handleUpdateNoteType
    case 'update_note_type': return await this.noteTypeHandlers.handleUpdateNoteType( args as unknown as UpdateNoteTypeArgs ); case 'get_note_type_info': return await this.noteTypeHandlers.handleGetNoteTypeInfo( args as unknown as GetNoteTypeInfoArgs );
  • TypeScript interface defining UpdateNoteTypeArgs for the tool.
    export interface UpdateNoteTypeArgs { type_name: string; instructions?: string; description?: string; metadata_schema?: MetadataFieldDefinition[]; content_hash: string; vault_id?: string; }
  • Validation rules for update_note_type tool arguments used in validateToolArgs.
    update_note_type: [ { field: 'type_name', required: true, type: 'string', allowEmpty: false }, { field: 'instructions', required: false, type: 'string', allowEmpty: true }, { field: 'description', required: false, type: 'string', allowEmpty: false }, { field: 'metadata_schema', required: false, type: 'array', allowEmpty: true }, { field: 'content_hash', required: true, type: 'string', allowEmpty: false }, { field: 'vault_id', required: false, type: 'string', allowEmpty: false } ],

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/disnet/flint-note'

If you have feedback or need assistance with the MCP directory API, please join our Discord server