doc2vec 1.1.1 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +111 -15
- package/dist/content-processor.js +748 -0
- package/dist/database.js +507 -0
- package/dist/doc2vec.js +356 -968
- package/dist/embedding-providers.js +157 -0
- package/dist/types.js +2 -0
- package/dist/utils.js +118 -0
- package/package.json +8 -2
- package/Dockerfile +0 -29
- package/config.yaml +0 -167
- package/doc2vec.ts +0 -1734
- package/logger.ts +0 -287
- package/mcp/Dockerfile +0 -14
- package/mcp/README.md +0 -166
- package/mcp/package-lock.json +0 -1754
- package/mcp/package.json +0 -41
- package/mcp/src/index.ts +0 -214
- package/mcp/tsconfig.json +0 -16
- package/tsconfig.json +0 -18
package/mcp/package.json
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "sqlite-vec-mcp-server",
|
|
3
|
-
"version": "1.0.0",
|
|
4
|
-
"description": "MCP Server for querying documentation with sqlite-vec",
|
|
5
|
-
"main": "build/index.js",
|
|
6
|
-
"type": "module",
|
|
7
|
-
"bin": {
|
|
8
|
-
"doc-query": "./build/index.js"
|
|
9
|
-
},
|
|
10
|
-
"scripts": {
|
|
11
|
-
"build": "tsc && chmod 755 build/index.js",
|
|
12
|
-
"start": "node build/index.js",
|
|
13
|
-
"dev": "npm run build && npm start"
|
|
14
|
-
},
|
|
15
|
-
"files": [
|
|
16
|
-
"build"
|
|
17
|
-
],
|
|
18
|
-
"keywords": [
|
|
19
|
-
"mcp",
|
|
20
|
-
"sqlite-vec",
|
|
21
|
-
"vector",
|
|
22
|
-
"search"
|
|
23
|
-
],
|
|
24
|
-
"author": "",
|
|
25
|
-
"license": "ISC",
|
|
26
|
-
"dependencies": {
|
|
27
|
-
"@modelcontextprotocol/sdk": "^1.9.0",
|
|
28
|
-
"better-sqlite3": "^11.8.1",
|
|
29
|
-
"dotenv": "^16.4.7",
|
|
30
|
-
"express": "^5.1.0",
|
|
31
|
-
"openai": "^4.89.0",
|
|
32
|
-
"sqlite-vec": "0.1.7-alpha.2",
|
|
33
|
-
"zod": "^3.24.2"
|
|
34
|
-
},
|
|
35
|
-
"devDependencies": {
|
|
36
|
-
"@types/better-sqlite3": "^7.6.13",
|
|
37
|
-
"@types/express": "^5.0.1",
|
|
38
|
-
"@types/node": "^22.14.0",
|
|
39
|
-
"typescript": "^5.8.3"
|
|
40
|
-
}
|
|
41
|
-
}
|
package/mcp/src/index.ts
DELETED
|
@@ -1,214 +0,0 @@
|
|
|
1
|
-
// src/index.ts
|
|
2
|
-
import 'dotenv/config'; // Load .env file
|
|
3
|
-
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
4
|
-
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
|
|
5
|
-
import express, { Request, Response } from "express";
|
|
6
|
-
import { z } from "zod";
|
|
7
|
-
|
|
8
|
-
import * as sqliteVec from "sqlite-vec";
|
|
9
|
-
import Database, { Database as DatabaseType } from "better-sqlite3";
|
|
10
|
-
import { OpenAI } from 'openai';
|
|
11
|
-
import path from 'path';
|
|
12
|
-
import fs from 'fs'; // Import fs for checking file existence
|
|
13
|
-
|
|
14
|
-
// --- Configuration & Environment Check ---
|
|
15
|
-
|
|
16
|
-
const openAIApiKey = process.env.OPENAI_API_KEY;
|
|
17
|
-
const dbDir = process.env.SQLITE_DB_DIR || __dirname; // Default to current dir if not set
|
|
18
|
-
|
|
19
|
-
if (!openAIApiKey) {
|
|
20
|
-
console.error("Error: OPENAI_API_KEY environment variable is not set.");
|
|
21
|
-
process.exit(1);
|
|
22
|
-
}
|
|
23
|
-
if (!fs.existsSync(dbDir)) {
|
|
24
|
-
console.warn(`Warning: SQLITE_DB_DIR (${dbDir}) does not exist. Databases may not be found.`);
|
|
25
|
-
process.exit(1);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const openai = new OpenAI({
|
|
29
|
-
apiKey: openAIApiKey,
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
export interface QueryResult {
|
|
33
|
-
chunk_id: string;
|
|
34
|
-
distance: number;
|
|
35
|
-
content: string;
|
|
36
|
-
url?: string;
|
|
37
|
-
embedding?: Float32Array | number[];
|
|
38
|
-
[key: string]: unknown;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
async function createEmbeddings(text: string): Promise<number[]> {
|
|
42
|
-
try {
|
|
43
|
-
console.log("Calling OpenAI embeddings API...");
|
|
44
|
-
const startTime = Date.now();
|
|
45
|
-
const response = await openai.embeddings.create({
|
|
46
|
-
model: 'text-embedding-3-large', // Or your preferred model
|
|
47
|
-
input: text,
|
|
48
|
-
});
|
|
49
|
-
const duration = Date.now() - startTime;
|
|
50
|
-
console.log(`OpenAI embeddings received in ${duration}ms.`);
|
|
51
|
-
if (!response.data?.[0]?.embedding) {
|
|
52
|
-
throw new Error("Failed to get embedding from OpenAI response.");
|
|
53
|
-
}
|
|
54
|
-
return response.data[0].embedding;
|
|
55
|
-
} catch (error) {
|
|
56
|
-
console.error("Error creating OpenAI embeddings:", error);
|
|
57
|
-
throw new Error(`Failed to create embeddings: ${error instanceof Error ? error.message : String(error)}`);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
function queryCollection(queryEmbedding: number[], filter: { product_name: string; version?: string }, topK: number = 10): QueryResult[] {
|
|
62
|
-
const dbPath = path.join(dbDir, `${filter.product_name}.db`);
|
|
63
|
-
|
|
64
|
-
if (!fs.existsSync(dbPath)) {
|
|
65
|
-
throw new Error(`Database file not found at ${dbPath}`);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
let db: DatabaseType | null = null;
|
|
69
|
-
try {
|
|
70
|
-
db = new Database(dbPath);
|
|
71
|
-
console.log(`[DB ${dbPath}] Opened connection.`);
|
|
72
|
-
sqliteVec.load(db);
|
|
73
|
-
console.log(`[DB ${dbPath}] sqliteVec loaded.`);
|
|
74
|
-
let query = `
|
|
75
|
-
SELECT
|
|
76
|
-
*,
|
|
77
|
-
distance
|
|
78
|
-
FROM vec_items
|
|
79
|
-
WHERE embedding MATCH @query_embedding`;
|
|
80
|
-
|
|
81
|
-
if (filter.product_name) query += ` AND product_name = @product_name`;
|
|
82
|
-
if (filter.version) query += ` AND version = @version`;
|
|
83
|
-
|
|
84
|
-
query += `
|
|
85
|
-
ORDER BY distance
|
|
86
|
-
LIMIT @top_k;`;
|
|
87
|
-
|
|
88
|
-
const stmt = db.prepare(query);
|
|
89
|
-
console.log(`[DB ${dbPath}] Query prepared. Executing...`);
|
|
90
|
-
const startTime = Date.now();
|
|
91
|
-
const rows = stmt.all({
|
|
92
|
-
query_embedding: new Float32Array(queryEmbedding),
|
|
93
|
-
product_name: filter.product_name,
|
|
94
|
-
version: filter.version,
|
|
95
|
-
top_k: topK,
|
|
96
|
-
});
|
|
97
|
-
const duration = Date.now() - startTime;
|
|
98
|
-
console.log(`[DB ${dbPath}] Query executed in ${duration}ms. Found ${rows.length} rows.`);
|
|
99
|
-
|
|
100
|
-
rows.forEach((row: any) => {
|
|
101
|
-
delete row.embedding;
|
|
102
|
-
})
|
|
103
|
-
|
|
104
|
-
return rows as QueryResult[];
|
|
105
|
-
} catch (error) {
|
|
106
|
-
console.error(`Error querying collection in ${dbPath}:`, error);
|
|
107
|
-
throw new Error(`Database query failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
108
|
-
} finally {
|
|
109
|
-
if (db) {
|
|
110
|
-
db.close();
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
async function queryDocumentation(queryText: string, productName: string, version?: string, limit: number = 4): Promise<{ distance: number, content: string, url?: string }[]> {
|
|
116
|
-
const queryEmbedding = await createEmbeddings(queryText);
|
|
117
|
-
const results = queryCollection(queryEmbedding, { product_name: productName, version: version }, limit);
|
|
118
|
-
return results.map((qr: QueryResult) => ({
|
|
119
|
-
distance: qr.distance,
|
|
120
|
-
content: qr.content,
|
|
121
|
-
...(qr.url && { url: qr.url }),
|
|
122
|
-
}));
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
// --- MCP Server Setup ---
|
|
127
|
-
const serverName = "sqlite-vec-doc-query"; // Store name for logging
|
|
128
|
-
const serverVersion = "1.0.0"; // Store version for logging
|
|
129
|
-
|
|
130
|
-
const server = new McpServer({
|
|
131
|
-
name: serverName,
|
|
132
|
-
version: serverVersion,
|
|
133
|
-
capabilities: {},
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
// --- Define the MCP Tool ---
|
|
137
|
-
server.tool(
|
|
138
|
-
"query-documentation",
|
|
139
|
-
"Query documentation stored in a sqlite-vec database using vector search.",
|
|
140
|
-
{
|
|
141
|
-
queryText: z.string().min(1).describe("The natural language query to search for."),
|
|
142
|
-
productName: z.string().min(1).describe("The name of the product documentation database to search within (e.g., 'my-product'). Corresponds to the DB filename without .db."),
|
|
143
|
-
version: z.string().optional().describe("The specific version of the product documentation (e.g., '1.2.0'). Optional."),
|
|
144
|
-
limit: z.number().int().positive().optional().default(4).describe("Maximum number of results to return. Defaults to 4."),
|
|
145
|
-
},
|
|
146
|
-
async ({ queryText, productName, version, limit }) => {
|
|
147
|
-
console.log(`Received query: text="${queryText}", product="${productName}", version="${version || 'any'}", limit=${limit}`);
|
|
148
|
-
|
|
149
|
-
try {
|
|
150
|
-
const results = await queryDocumentation(queryText, productName, version, limit);
|
|
151
|
-
|
|
152
|
-
if (results.length === 0) {
|
|
153
|
-
return {
|
|
154
|
-
content: [{ type: "text", text: `No relevant documentation found for "${queryText}" in product "${productName}" ${version ? `(version ${version})` : ''}.` }],
|
|
155
|
-
};
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
const formattedResults = results.map((r, index) =>
|
|
159
|
-
[
|
|
160
|
-
`Result ${index + 1}:`,
|
|
161
|
-
` Content: ${r.content}`,
|
|
162
|
-
` Distance: ${r.distance.toFixed(4)}`,
|
|
163
|
-
r.url ? ` URL: ${r.url}` : null,
|
|
164
|
-
"---"
|
|
165
|
-
].filter(line => line !== null).join("\n")
|
|
166
|
-
).join("\n");
|
|
167
|
-
|
|
168
|
-
const responseText = `Found ${results.length} relevant documentation snippets for "${queryText}" in product "${productName}" ${version ? `(version ${version})` : ''}:\n\n${formattedResults}`;
|
|
169
|
-
console.log(`Handler finished processing. Payload size (approx): ${responseText.length} chars. Returning response object...`);
|
|
170
|
-
|
|
171
|
-
return {
|
|
172
|
-
content: [{ type: "text", text: responseText }],
|
|
173
|
-
};
|
|
174
|
-
} catch (error: any) {
|
|
175
|
-
console.error("Error processing 'query-documentation' tool:", error);
|
|
176
|
-
return {
|
|
177
|
-
content: [{ type: "text", text: `Error querying documentation: ${error.message}` }],
|
|
178
|
-
};
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
);
|
|
182
|
-
|
|
183
|
-
const app = express();
|
|
184
|
-
|
|
185
|
-
// to support multiple simultaneous connections we have a lookup object from
|
|
186
|
-
// sessionId to transport
|
|
187
|
-
const transports: {[sessionId: string]: SSEServerTransport} = {};
|
|
188
|
-
|
|
189
|
-
app.get("/sse", async (_: Request, res: Response) => {
|
|
190
|
-
const transport = new SSEServerTransport('/messages', res);
|
|
191
|
-
transports[transport.sessionId] = transport;
|
|
192
|
-
res.on("close", () => {
|
|
193
|
-
delete transports[transport.sessionId];
|
|
194
|
-
});
|
|
195
|
-
await server.connect(transport);
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
app.post("/messages", async (req: Request, res: Response) => {
|
|
199
|
-
const sessionId = req.query.sessionId as string;
|
|
200
|
-
const transport = transports[sessionId];
|
|
201
|
-
if (transport) {
|
|
202
|
-
await transport.handlePostMessage(req, res);
|
|
203
|
-
} else {
|
|
204
|
-
res.status(400).send('No transport found for sessionId');
|
|
205
|
-
}
|
|
206
|
-
});
|
|
207
|
-
|
|
208
|
-
const PORT = process.env.PORT || 3001;
|
|
209
|
-
|
|
210
|
-
const webserver = app.listen(PORT, () => {
|
|
211
|
-
console.log(`Server is running on port ${PORT}`);
|
|
212
|
-
});
|
|
213
|
-
|
|
214
|
-
webserver.keepAliveTimeout = 3000;
|
package/mcp/tsconfig.json
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2022",
|
|
4
|
-
"module": "Node16",
|
|
5
|
-
"moduleResolution": "Node16",
|
|
6
|
-
"outDir": "./build",
|
|
7
|
-
"rootDir": "./src",
|
|
8
|
-
"strict": true,
|
|
9
|
-
"esModuleInterop": true,
|
|
10
|
-
"skipLibCheck": true,
|
|
11
|
-
"forceConsistentCasingInFileNames": true,
|
|
12
|
-
"resolveJsonModule": true
|
|
13
|
-
},
|
|
14
|
-
"include": ["src/**/*"],
|
|
15
|
-
"exclude": ["node_modules", "build"]
|
|
16
|
-
}
|
package/tsconfig.json
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2020",
|
|
4
|
-
"module": "CommonJS",
|
|
5
|
-
"lib": ["es2022", "dom"],
|
|
6
|
-
"declaration": false,
|
|
7
|
-
"sourceMap": false,
|
|
8
|
-
"outDir": "./dist",
|
|
9
|
-
"rootDir": "./",
|
|
10
|
-
"strict": true,
|
|
11
|
-
"esModuleInterop": true,
|
|
12
|
-
"skipLibCheck": true,
|
|
13
|
-
"forceConsistentCasingInFileNames": true,
|
|
14
|
-
"moduleResolution": "node"
|
|
15
|
-
},
|
|
16
|
-
"include": ["**/*.ts"],
|
|
17
|
-
"exclude": ["node_modules", "mcp"]
|
|
18
|
-
}
|