Back to .md Directory

Document DB (MCP Server) Requirements Specification

Specifies a local vector server for Japanese documents using OpenAI embeddings and sqlite-vec, exposed as MCP tools for insert/find/delete.

May 2, 2026
0 downloads
2 views
ai agent mcp openai
View source

What this file does

Specifies a local vector server for Japanese documents using OpenAI embeddings and sqlite-vec, exposed as MCP tools for insert/find/delete.

When to use it

  • Building an MCP server that stores and searches Japanese text with embeddings
  • Migrating from sqlite-vss to sqlite-vec for vector storage
  • Implementing a local-only document database for AI agents
  • Creating a reference spec for a vector search tool with chunking and batch embedding

Assumes this stack

Node.js 20 LTSTypeScript 5 strictsqlite-vec 0.1.xOpenAI text-embedding-3-smallMCP 0.4pino

Document DB (MCP Server) Requirements Specification

Version 2.0 — 2025-06-18 Full migration to sqlite-vec 0.1 series


1. Purpose

Implement a local-only vector server that stores Japanese documents using OpenAI Embeddings + sqlite-vec and allows AI agents to perform insert / find / delete operations via Model Context Protocol (MCP). All legacy sqlite-vss dependencies are deprecated and replaced with the successor sqlite-vec (vec0 virtual table approach).


2. Technology Stack

CategoryTechnologyNotes
RuntimeNode.js 20 LTS
LanguageTypeScript 5 (strict)
Vector DBsqlite-vec 0.1.x<br>vec0 virtual table<br>distance_metric = cosine (github.com, alexgarcia.xyz)
EmbeddingOpenAI text-embedding-3-small (1536 dims)
MCPMCP 0.4 – JSON-RPC 2.0 (HTTP + stdio)
Loggingpino (JSON / dev uses pino-pretty)
MigrationSQL files + TS runner
LicenseMIT
OSmacOS / Linux (Windows not supported)

3. MCP "tools"

Toolparams (JSON Schema)result
create_database{ db_name:string }{ success:boolean, db_path:string }
insert_document{ text:string, metadata?:object, db_name?:string }{ doc_id:string, chunk_count:int }
find_similar_documents{ text:string, top_k?:int (default 10), db_name?:string }[ { chunk_id, doc_id, text, score } ]
delete_document{ doc_id:string, db_name?:string }{ deleted_chunks:int }
  • Manifest is published via GET /tools.
  • JSON-RPC error.code examples: "NOT_FOUND", "INVALID_REQUEST".

4. Data Schema (sqlite-vec)

-- Minimal schema. While embedding could be primary key, we adopt ULID row ID.
CREATE VIRTUAL TABLE chunks USING vec0(
  chunk_id     TEXT       PRIMARY KEY,         -- ULID
  doc_id       TEXT       NOT NULL,            -- Document ID
  chunk_index  INTEGER    NOT NULL,            -- 0,1,2…
  text         TEXT       AUXILIARY,           -- Original text for similarity results (+ for non-indexed)
  metadata     JSON       AUXILIARY,
  embedding    FLOAT[1536]  DISTANCE_METRIC=cosine
);
  • The vec0 virtual table itself contains the index and search logic, so no additional CREATE INDEX is needed (alexgarcia.xyz).

  • Load extension on boot

    import * as sqliteVec from "sqlite-vec";      // npm i sqlite-vec
    import Database from "better-sqlite3";
    const db = new Database("./data/vector.db");
    sqliteVec.load(db);                           // ← Required
    

5. Business Flow

OperationSteps
create_db1. Create database directory if needed<br>2. Initialize SQLite database with migrations<br>3. Load sqlite-vec extension<br>4. Return success status and path
insert1. Select target database (db_name or default)<br>2. doc_id = ULID()<br>3. Split max 100k chars by periods/newlines (700 chars + overlap 100)<br>4. Batch embed with OpenAI (≤100 chunks)<br>5. Bulk INSERT INTO chunks (…) VALUES …
find1. Select target database (db_name or default)<br>2. Embed query<br>3. sql SELECT chunk_id, doc_id, text, distance FROM chunks WHERE embedding MATCH ? AND k = :top_k;<br>4. Return distance as score
delete1. Select target database (db_name or default)<br>2. BEGIN; DELETE FROM chunks WHERE doc_id=?; COMMIT;<br>3. Verify and return deletion count using changes()

For MATCH ?, bind Float32Array.buffer or use vec_f32('[…]').


6. Migration

6.1 migrations/001_init.sql

PRAGMA foreign_keys = ON;

-- sqlite-vec vec0 virtual table
CREATE VIRTUAL TABLE chunks USING vec0(
  chunk_id     TEXT PRIMARY KEY,
  doc_id       TEXT NOT NULL,
  chunk_index  INTEGER NOT NULL,
  text         TEXT AUXILIARY,
  metadata     JSON AUXILIARY,
  embedding    FLOAT[1536] DISTANCE_METRIC=cosine
);

6.2 scripts/migrate.ts (Excerpt)

Change – Always call sqliteVec.load(db) after opening DB.

import * as sqliteVec from "sqlite-vec";
const db = new Database(DB_PATH);
sqliteVec.load(db);        // ← New
db.pragma("journal_mode = WAL");
…

7. Configuration

KeyDefaultDescription
OPENAI_API_KEY.env
dbPath./data/vector.dbDefault SQLite path
dbDirectory./data/Directory for multiple databases
chunkSize700Character count
chunkOverlap100Character count
defaultTopK10Similar search count
deleteMode"hard"Reserved field

Database Naming Convention

  • Default database: vectors.db (used when db_name is not specified)
  • Custom databases: {db_name}.db (created in dbDirectory)
  • Database names must be valid filenames (alphanumeric, underscore, hyphen allowed)

8. Non-Functional Requirements

ItemDetails
PerformanceP95 < 300 ms (10k chunks, M1 Mac)
Scalabilitysqlite-vec uses brute-force KNN only. Consider ANN for >1M chunks (docs.sqlitecloud.io)
Observabilitypino: processing time for insert/find/delete + OpenAI call time
TestingJest: chunker・delete 404・E2E (insert→find→delete)
CIGitHub Actions (lint→test→build)

9. Directory Structure

/project-root
├─ src/
│  ├─ server.ts          # Fastify + MCP
│  ├─ tools/             # insert, find, delete
│  ├─ db.ts              # sqlite-vec loader & wrapper
│  ├─ embed.ts           # OpenAI embeddings
│  ├─ chunker.ts         # Japanese text splitting
│  └─ manifest.ts        # /tools JSON
├─ migrations/001_init.sql
├─ scripts/migrate.ts
├─ tests/
├─ .env.example
├─ README.md
└─ LICENSE (MIT)

10. Change History

VersionDateMajor Changes
2.02025-06-18Full migration to sqlite-vec 0.1 series (updated schema, queries, load procedures)
1.22025-06-18Added initial migration procedures
1.12025-06-18Added delete_document
1.02025-06-18MCP insert / find specification
0.92025-06-18Initial version

This completes the latest specification based on the successor engine sqlite-vec.

What's inside

10 sections, 4 MCP tool definitions, 1 SQL schema, 1 business flow table, 1 migration script excerpt

Change this for your project

  • Replace OPENAI_API_KEY with your own API key
  • Replace ./data/vector.db with your desired default database path
  • Replace chunkSize: 700 and chunkOverlap: 100 with your preferred values
  • Replace defaultTopK: 10 with your preferred default

Where it goes

Keep in docs/ or alongside the feature. Agents read it to implement against a defined contract.

Worth borrowing

  • Using ULID as primary key for chunks instead of embedding vector
  • Splitting documents by periods/newlines with overlap for chunking
  • Separating migration SQL files from TypeScript runner scripts

Related Documents