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;
      }
    }
Behavior2/5

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

No annotations are provided, so the description carries the full burden of behavioral disclosure. It mentions the upsert operation and return value, but fails to describe critical traits like whether this requires specific permissions, if updates are idempotent, what happens on conflicts, or any rate limits. For a mutation tool with zero annotation coverage, this leaves significant gaps in understanding its behavior.

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 extremely concise with two sentences that are front-loaded: the first states the core action and resource, and the second specifies the return value. There is no wasted text, making it efficient and easy to parse.

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?

Given the complexity (6 parameters with nested objects, no output schema, and no annotations), the description is incomplete. It doesn't cover parameter meanings, behavioral details like error handling or side effects, or how the return value relates to the operation. For a mutation tool with rich input schema but low documentation, this leaves the agent under-informed.

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

Parameters2/5

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

Schema description coverage is low at 17%, with only the 'id' parameter having a description. The tool description adds no information about parameters beyond what's implied by the name (e.g., 'key' and 'content' are required, 'backup' is an object). It doesn't explain the meaning of 'metadata', 'tags', or the 'backup' object's purpose, failing to compensate for the poor 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 ('Create or update'), the resource ('a note under a key'), and the outcome ('Returns the note id'), making the purpose specific and understandable. However, it doesn't explicitly differentiate from sibling tools like 'graph-node-upsert' or 'image-upsert', which might handle similar upsert operations on different resources, so it misses full sibling distinction.

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?

The description provides no guidance on when to use this tool versus alternatives, such as 'index-query' for reading notes or 'index-delete' for removal. It lacks context on prerequisites, like whether the key must exist, or exclusions, such as when to use 'graph-node-upsert' instead for graph-related data.

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

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