Skip to main content
Glama
vjsr007
by vjsr007

index-upsert

Create or update notes under a specific key, enabling indexing, tagging, and metadata management. Supports full-text search and knowledge graph generation for efficient note retrieval and concept relationships.

Instructions

Create or update a note under a key. Returns the note id.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
backupNo
contentYes
idNoOptional note id to update
keyYes
metadataNo
tagsNo

Implementation Reference

  • src/mcp.ts:38-60 (registration)
    Registration of the 'index-upsert' tool in the tools array, including name, description, and input schema definition.
    {
      name: 'index-upsert',
      description: 'Create or update a note under a key. Returns the note id.',
      inputSchema: {
        type: 'object',
        properties: {
          id: { type: 'number', description: 'Optional note id to update' },
          key: { type: 'string' },
          content: { type: 'string' },
          tags: { type: 'array', items: { type: 'string' } },
          metadata: { type: 'object' },
          backup: {
            type: 'object',
            properties: {
              enabled: { type: 'boolean' },
              dir: { type: 'string' },
            },
          },
        },
        required: ['key', 'content'],
        additionalProperties: true,
      },
    },
  • MCP tool handler for 'index-upsert': parses arguments using UpsertSchema, calls db.upsert(), optionally creates backup, and returns the note ID.
    case 'index-upsert': {
      const parsed = UpsertSchema.parse(args);
      const id = db.upsert(parsed);
      if (parsed.backup?.enabled) {
        const file = writeBackup(db.exportAll(), parsed.backup.dir);
        return { content: [{ type: 'text', text: JSON.stringify({ id, backup: file }) }] };
      }
      return { content: [{ type: 'text', text: JSON.stringify({ id }) }] };
    }
  • Zod schema definition for input validation of the upsert operation, extending NoteSchema with optional id and backup.
    export const UpsertSchema = NoteSchema.extend({
      id: z.number().int().positive().optional(),
      backup: BackupOptionsSchema.optional(),
    });
  • Core implementation of upsert in NotesDB (SQLite backend): handles update if id provided, insert otherwise, with JSON serialization for tags/metadata and timestamps.
    upsert(note: Note & { id?: number }): number {
      logger.debug({ note }, 'Upserting note');
      if (note.id) {
        const stmt = this.db.prepare(
          `UPDATE notes SET key=@key, content=@content, tags=@tags, metadata=@metadata, updated_at=datetime('now') WHERE id=@id`
        );
        const info = stmt.run({
          id: note.id,
          key: note.key,
          content: note.content,
          tags: JSON.stringify(note.tags ?? []),
          metadata: JSON.stringify(note.metadata ?? {}),
        });
        if (info.changes === 0) {
          throw new Error(`Note with id ${note.id} not found`);
        }
        return note.id;
      } else {
        const stmt = this.db.prepare(
          `INSERT INTO notes (key, content, tags, metadata) VALUES (@key, @content, @tags, @metadata)`
        );
        const info = stmt.run({
          key: note.key,
          content: note.content,
          tags: JSON.stringify(note.tags ?? []),
          metadata: JSON.stringify(note.metadata ?? {}),
        });
        return Number(info.lastInsertRowid);
      }
    }
  • Fallback in-memory upsert implementation in LiteNotesStore: updates or adds to array, updates MiniSearch index, persists to JSON.
    upsert(note: Note & { id?: number }): number {
      const now = new Date().toISOString();
      if (note.id) {
        const idx = this.notes.findIndex((n) => n.id === note.id);
        if (idx === -1) throw new Error(`Note with id ${note.id} not found`);
        const updated: Note = {
          ...this.notes[idx],
          key: note.key,
          content: note.content,
          tags: note.tags ?? [],
          metadata: note.metadata ?? {},
          updated_at: now,
        };
        this.notes[idx] = updated;
        this.ms.replace(updated);
        this.persist();
        return updated.id!;
      } else {
        const id = this.nextId++;
        const created: Note = {
          id,
          key: note.key,
          content: note.content,
          tags: note.tags ?? [],
          metadata: note.metadata ?? {},
          created_at: now,
          updated_at: now,
        };
        this.notes.push(created);
        this.ms.add(created);
        this.persist();
        return id;
      }
    }

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/vjsr007/mcp-index-notes'

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