Skip to main content
Glama
disnet
by disnet

update_note_type

Modify existing note types by updating instructions, descriptions, or metadata fields to adapt note structures for AI collaboration in Flint Note.

Instructions

Update one or more fields of an existing note type

Input Schema

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

Implementation Reference

  • The primary handler function that implements the 'update_note_type' tool. Validates inputs, checks content hash for concurrency control, updates note type description/instructions/metadata schema, validates schema fields, writes updated _description.md file, and returns success/error response.
    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 the 'update_note_type' tool, specifying input parameters including type_name (required), optional updates to description/instructions/schema, required content_hash for safety, and optional vault_id.
      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']
      }
    },
  • Tool dispatch/registration in the MCP CallToolRequestSchema handler switch statement, routing 'update_note_type' calls to the NoteTypeHandlers.handleUpdateNoteType method.
    case 'update_note_type':
      return await this.noteTypeHandlers.handleUpdateNoteType(
        args as unknown as UpdateNoteTypeArgs
      );
  • TypeScript interface defining the expected arguments for the update_note_type handler.
    export interface UpdateNoteTypeArgs {
      type_name: string;
      instructions?: string;
      description?: string;
      metadata_schema?: MetadataFieldDefinition[];
      content_hash: string;
      vault_id?: string;
    }
  • Runtime validation rules for update_note_type tool arguments, ensuring required fields, types, and custom validations are met before handler execution.
    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
      }
    ],
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries full burden. It implies a mutation ('update') but lacks critical behavioral details: it doesn't specify if changes are reversible, what permissions are required, whether it's idempotent, or how conflicts are handled (though 'content_hash' in schema hints at conflict prevention). The description adds minimal value beyond the basic action, leaving significant gaps for a mutation tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, efficient sentence that front-loads the core action ('update') and resource ('note type'), with no wasted words. It clearly communicates the scope ('one or more fields') and target ('existing'), making it easy to parse quickly.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutation tool with 6 parameters, no annotations, and no output schema, the description is insufficient. It lacks behavioral context (e.g., side effects, error handling), usage prerequisites, and output expectations. While the schema covers parameters well, the description doesn't compensate for missing annotations or output details, leaving the agent under-informed for safe invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so parameters are well-documented in the schema. The description adds no specific parameter semantics beyond implying fields can be updated partially ('one or more fields'), which is already suggested by the schema's optional properties. It doesn't explain parameter interactions or usage nuances, meeting the baseline for high schema coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('update') and resource ('existing note type'), specifying it can modify 'one or more fields'. It distinguishes from sibling tools like 'create_note_type' (creation vs. update) and 'update_note' (note vs. note type). However, it doesn't explicitly differentiate from 'update_vault' or other update operations beyond the resource name.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance is provided on when to use this tool versus alternatives. It doesn't mention prerequisites (e.g., note type must exist), exclusions (e.g., cannot update certain fields), or comparisons with siblings like 'create_note_type' for new types or 'update_note' for note content. The description only states what it does, not when to apply it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

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