Skip to main content
Glama
vjsr007
by vjsr007

image-upsert

Store image data (base64 or file path) under a unique key, returning an image ID. Integrates with MCP Index Notes for efficient note management, tagging, and semantic connections.

Instructions

Store an image (base64 data or file path) under a key. Returns image id.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
dataNoBase64-encoded image data (no data: prefix)
fileNoPath to image file to read if data not provided
keyYes
metadataNo
mimeNoMIME type e.g. image/png if data provided

Implementation Reference

  • Executes the image-upsert tool: validates input with ImageUpsertSchema, loads image data from base64 or file path, guesses MIME type if needed, calls db.insertImage, returns the new image ID.
    case 'image-upsert': {
      const parsed = ImageUpsertSchema.parse(args);
      if (!('insertImage' in (db as any))) {
        throw new Error('Image storage not supported in current store implementation');
      }
      const fs = await import('fs');
      let raw: Buffer | null = null;
      if (parsed.data) {
        raw = Buffer.from(parsed.data, 'base64');
      } else if (parsed.file) {
          raw = fs.readFileSync(parsed.file);
      } else {
        throw new Error('Provide data (base64) or file');
      }
      // crude mime guess if not provided
      let mime = parsed.mime;
      if (!mime && parsed.file) {
        const ext = parsed.file.toLowerCase();
        if (ext.endsWith('.png')) mime = 'image/png';
        else if (ext.endsWith('.jpg') || ext.endsWith('.jpeg')) mime = 'image/jpeg';
        else if (ext.endsWith('.gif')) mime = 'image/gif';
        else if (ext.endsWith('.webp')) mime = 'image/webp';
        else mime = 'application/octet-stream';
      }
      if (!mime) mime = 'application/octet-stream';
      const id = (db as any).insertImage({ key: parsed.key, mime, data: raw!, metadata: parsed.metadata });
      return { content: [{ type: 'text', text: JSON.stringify({ id }) }] };
    }
  • Zod input schema for image-upsert tool defining key (required), optional data (base64), file path, mime type, and metadata.
    export const ImageUpsertSchema = z.object({
      key: z.string().min(1, 'key is required'),
      // Either provide raw base64 data (without data:mime prefix) or a file path to read
      data: z.string().optional(),
      file: z.string().optional(),
      mime: z.string().optional(),
      metadata: z.record(z.any()).optional().default({}),
    });
    export type ImageUpsertInput = z.infer<typeof ImageUpsertSchema>;
  • src/mcp.ts:62-75 (registration)
    MCP tool registration defining name 'image-upsert', description, and inputSchema (JSON schema version of the Zod schema).
      name: 'image-upsert',
      description: 'Store an image (base64 data or file path) under a key. Returns image id.',
      inputSchema: {
        type: 'object',
        properties: {
          key: { type: 'string' },
          data: { type: 'string', description: 'Base64-encoded image data (no data: prefix)' },
          file: { type: 'string', description: 'Path to image file to read if data not provided' },
          mime: { type: 'string', description: 'MIME type e.g. image/png if data provided' },
          metadata: { type: 'object' },
        },
        required: ['key'],
      },
    },
  • Database helper method that inserts image record into SQLite 'images' table, storing key, mime, size, metadata (JSON), and binary data (BLOB), returns inserted ID.
    insertImage(img: { key: string; mime: string; data: Buffer; metadata?: any }): number {
      const stmt = this.db.prepare(`INSERT INTO images (key, mime, size, metadata, data) VALUES (@key, @mime, @size, @metadata, @data)`);
      const info = stmt.run({
        key: img.key,
        mime: img.mime,
        size: img.data.length,
        metadata: JSON.stringify(img.metadata ?? {}),
        data: img.data,
      });
      return Number(info.lastInsertRowid);
    }
Behavior2/5

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

With no annotations provided, the description carries full burden for behavioral disclosure. It mentions the return value ('Returns image id') which is helpful, but doesn't describe whether this is a create/update operation, what happens on duplicate keys, authentication requirements, rate limits, or error conditions. For a mutation tool with zero annotation coverage, this is insufficient.

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 just two sentences that efficiently convey the core functionality and return value. Every word earns its place with zero waste or redundancy.

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 5 parameters, no annotations, and no output schema, the description is incomplete. It doesn't explain the upsert behavior (create vs update), doesn't clarify parameter relationships (data vs file), and provides minimal guidance on usage. The return value is mentioned but not fully described.

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 60% (3 of 5 parameters have descriptions). The description adds minimal value beyond the schema - it mentions 'base64 data or file path' which aligns with the 'data' and 'file' parameters, but doesn't explain the 'key', 'metadata', or 'mime' parameters beyond what's in the schema. Baseline 3 is appropriate given moderate 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 ('Store an image') and resource ('under a key'), and distinguishes from siblings like image-get and image-delete by specifying it's for storage/upsert operations. However, it doesn't explicitly differentiate from image-export or explain what 'upsert' means versus pure creation.

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 like image-get or image-delete. It mentions the return value but doesn't explain when image-upsert is appropriate versus other image or index tools in the sibling list.

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