Skip to main content
Glama

update_note

Modify existing notes in Flint Note by updating content, metadata, or both, supporting single or batch operations with optimistic locking.

Instructions

Update one or more existing notes

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
identifierNoNote identifier in format "type/filename" or full path - only used for single note update
contentNoNew content for the note - only used for single note update
content_hashNoContent hash of the current note for optimistic locking - required for single note update
metadataNoMetadata fields to update - only used for single note update
updatesNoArray of note updates (must specify content, metadata, or both) - used for batch updates
vault_idNoOptional vault ID to operate on. If not provided, uses the current active vault.

Implementation Reference

  • MCP tool handler for 'update_note'. Validates args, handles single or batch updates by calling NoteManager methods (updateNote, updateNoteWithMetadata, batchUpdateNotes), returns JSON result.
    handleUpdateNote = async (args: UpdateNoteArgs) => { // Validate arguments validateToolArgs('update_note', args); const { noteManager } = await this.resolveVaultContext(args.vault_id); // Handle batch updates if updates array is provided if (args.updates) { const result = await noteManager.batchUpdateNotes(args.updates); return { content: [ { type: 'text', text: JSON.stringify(result, null, 2) } ] }; } // Handle single note update // Note: validation already handled by validateToolArgs const identifier = args.identifier!; // Safe after validation const contentHash = args.content_hash!; // Safe after validation let result; if (args.content !== undefined && args.metadata !== undefined) { // Both content and metadata update result = await noteManager.updateNoteWithMetadata( identifier, args.content, args.metadata as NoteMetadata, contentHash ); } else if (args.content !== undefined) { // Content-only update result = await noteManager.updateNote(identifier, args.content, contentHash); } else if (args.metadata !== undefined) { // Metadata-only update const currentNote = await noteManager.getNote(identifier); if (!currentNote) { throw new Error(`Note '${identifier}' not found`); } result = await noteManager.updateNoteWithMetadata( identifier, currentNote.content, args.metadata as NoteMetadata, contentHash ); } else { throw new Error('Either content or metadata must be provided for update'); } return { content: [ { type: 'text', text: JSON.stringify(result, null, 2) } ] }; };
  • Registration of 'update_note' tool in MCP server's CallToolRequestSchema handler switch statement. Routes to NoteHandlers.handleUpdateNote.
    case 'update_note': return await this.noteHandlers.handleUpdateNote( args as unknown as UpdateNoteArgs );
  • Input schema definition for 'update_note' tool advertised in ListToolsRequestSchema response.
    { name: 'update_note', description: 'Update one or more existing notes', inputSchema: { type: 'object', properties: { identifier: { type: 'string', description: 'Note identifier in format "type/filename" or full path - only used for single note update' }, content: { type: 'string', description: 'New content for the note - only used for single note update' }, content_hash: { type: 'string', description: 'Content hash of the current note for optimistic locking - required for single note update' }, metadata: { type: 'object', description: 'Metadata fields to update - only used for single note update', additionalProperties: true }, updates: { type: 'array', items: { type: 'object', properties: { identifier: { type: 'string', description: 'Note identifier in format "type/filename" or full path' }, content: { type: 'string', description: 'New content for the note' }, content_hash: { type: 'string', description: 'Content hash for optimistic locking' }, metadata: { type: 'object', description: 'Metadata fields to update', additionalProperties: true } }, required: ['identifier', 'content_hash'] }, description: 'Array of note updates (must specify content, metadata, or both) - used for batch updates' }, vault_id: { type: 'string', description: 'Optional vault ID to operate on. If not provided, uses the current active vault.' } }, required: [] } },
  • TypeScript interface UpdateNoteArgs defining the input parameters for the update_note tool handler.
    export interface UpdateNoteArgs { identifier?: string; content?: string; metadata?: Record<string, unknown>; content_hash?: string; updates?: Array<{ identifier: string; content?: string; metadata?: Record<string, unknown>; content_hash: string; }>; vault_id?: string; }
  • Core NoteManager.updateNote method: handles content-only updates with optimistic locking via content hash, preserves metadata, updates search index.
    async updateNote( identifier: string, newContent: string, contentHash: string ): Promise<UpdateResult> { try { if (!contentHash) { throw new MissingContentHashError('note update'); } const { typeName: _typeName, filename: _filename, notePath } = this.parseNoteIdentifier(identifier); // Check if note exists try { await fs.access(notePath); } catch { throw new Error(`Note '${identifier}' does not exist`); } // Read current content to preserve metadata const currentContent = await fs.readFile(notePath, 'utf-8'); const parsed = this.parseNoteContent(currentContent); // Validate content hash to prevent conflicts validateContentHash(parsed.content, contentHash); // Update the content while preserving metadata const updatedMetadata = { ...parsed.metadata, updated: new Date().toISOString() }; const updatedContent = this.formatUpdatedNoteContent(updatedMetadata, newContent); // Write updated content await fs.writeFile(notePath, updatedContent, 'utf-8'); // Update search index await this.updateSearchIndex(notePath, updatedContent); return { id: identifier, updated: true, timestamp: updatedMetadata.updated }; } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Unknown error'; throw new Error(`Failed to update note '${identifier}': ${errorMessage}`); } }
  • Core NoteManager.updateNoteWithMetadata: handles content + metadata updates, protects critical fields like title/filename unless bypassed.
    async updateNoteWithMetadata( identifier: string, content: string, metadata: NoteMetadata, contentHash: string, bypassProtection: boolean = false ): Promise<UpdateResult> { try { if (!contentHash) { throw new MissingContentHashError('note metadata update'); } const { typeName: _typeName, filename: _filename, notePath } = this.parseNoteIdentifier(identifier); // Check if note exists try { await fs.access(notePath); } catch { throw new Error(`Note '${identifier}' does not exist`); } // Read current content to preserve existing metadata const currentContent = await fs.readFile(notePath, 'utf-8'); const parsed = this.parseNoteContent(currentContent); // Validate content hash to prevent conflicts validateContentHash(parsed.content, contentHash); // Check for protected fields unless bypassing protection if (!bypassProtection) { this.#validateNoProtectedFields(metadata); } // Merge metadata with existing metadata const updatedMetadata = { ...parsed.metadata, ...metadata, updated: new Date().toISOString() }; // Format content with metadata const formattedContent = this.formatUpdatedNoteContent(updatedMetadata, content); // Write updated content await fs.writeFile(notePath, formattedContent, 'utf-8'); // Update search index await this.updateSearchIndex(notePath, formattedContent); return { id: identifier, updated: true, timestamp: updatedMetadata.updated }; } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Unknown error'; throw new Error(`Failed to update note '${identifier}': ${errorMessage}`); } }

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