better-qdrant-mcp-server 0.1.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.
Files changed (33) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +124 -0
  3. package/build/index.d.ts +2 -0
  4. package/build/index.js +347 -0
  5. package/build/index.js.map +1 -0
  6. package/build/services/embeddings/base.d.ts +11 -0
  7. package/build/services/embeddings/base.js +16 -0
  8. package/build/services/embeddings/base.js.map +1 -0
  9. package/build/services/embeddings/fastembed.d.ts +11 -0
  10. package/build/services/embeddings/fastembed.js +34 -0
  11. package/build/services/embeddings/fastembed.js.map +1 -0
  12. package/build/services/embeddings/index.d.ts +6 -0
  13. package/build/services/embeddings/index.js +29 -0
  14. package/build/services/embeddings/index.js.map +1 -0
  15. package/build/services/embeddings/ollama.d.ts +10 -0
  16. package/build/services/embeddings/ollama.js +41 -0
  17. package/build/services/embeddings/ollama.js.map +1 -0
  18. package/build/services/embeddings/openai.d.ts +10 -0
  19. package/build/services/embeddings/openai.js +44 -0
  20. package/build/services/embeddings/openai.js.map +1 -0
  21. package/build/services/embeddings/openrouter.d.ts +9 -0
  22. package/build/services/embeddings/openrouter.js +38 -0
  23. package/build/services/embeddings/openrouter.js.map +1 -0
  24. package/build/services/qdrant.d.ts +18 -0
  25. package/build/services/qdrant.js +215 -0
  26. package/build/services/qdrant.js.map +1 -0
  27. package/build/services/text-processing.d.ts +19 -0
  28. package/build/services/text-processing.js +41 -0
  29. package/build/services/text-processing.js.map +1 -0
  30. package/build/types.d.ts +43 -0
  31. package/build/types.js +2 -0
  32. package/build/types.js.map +1 -0
  33. package/package.json +64 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Will Reeves
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,124 @@
1
+ # Better Qdrant MCP Server
2
+
3
+ A Model Context Protocol (MCP) server for enhanced Qdrant vector database functionality. This server provides tools for managing Qdrant collections, adding documents, and performing semantic searches.
4
+
5
+ ## Features
6
+
7
+ - **List Collections**: View all available Qdrant collections
8
+ - **Add Documents**: Process and add documents to a Qdrant collection with various embedding services
9
+ - **Search**: Perform semantic searches across your vector database
10
+ - **Delete Collection**: Remove collections from your Qdrant database
11
+
12
+ ## Installation
13
+
14
+ ```bash
15
+ npm install -g better-qdrant-mcp-server
16
+ ```
17
+
18
+ Or use it directly with npx:
19
+
20
+ ```bash
21
+ npx better-qdrant-mcp-server
22
+ ```
23
+
24
+ ## Configuration
25
+
26
+ The server uses environment variables for configuration. You can set these in a `.env` file in your project root:
27
+
28
+ ```
29
+ # Qdrant Configuration
30
+ QDRANT_URL=http://localhost:6333
31
+ QDRANT_API_KEY=your_api_key_if_needed
32
+
33
+ # Embedding Service API Keys
34
+ OPENAI_API_KEY=your_openai_api_key
35
+ OPENROUTER_API_KEY=your_openrouter_api_key
36
+ OLLAMA_ENDPOINT=http://localhost:11434
37
+ ```
38
+
39
+ ## Supported Embedding Services
40
+
41
+ - **OpenAI**: Requires an API key
42
+ - **OpenRouter**: Requires an API key
43
+ - **Ollama**: Local embedding models (default endpoint: http://localhost:11434)
44
+ - **FastEmbed**: Local embedding models
45
+
46
+ ## Usage with Claude
47
+
48
+ To use this MCP server with Claude, add it to your MCP settings configuration file:
49
+
50
+ ```json
51
+ {
52
+ "mcpServers": {
53
+ "better-qdrant": {
54
+ "command": "npx",
55
+ "args": ["better-qdrant-mcp-server"],
56
+ "env": {
57
+ "QDRANT_URL": "http://localhost:6333",
58
+ "OPENAI_API_KEY": "your_openai_api_key"
59
+ }
60
+ }
61
+ }
62
+ }
63
+ ```
64
+
65
+ ### Example Commands
66
+
67
+ #### List Collections
68
+
69
+ ```
70
+ use_mcp_tool
71
+ server_name: better-qdrant
72
+ tool_name: list_collections
73
+ arguments: {}
74
+ ```
75
+
76
+ #### Add Documents
77
+
78
+ ```
79
+ use_mcp_tool
80
+ server_name: better-qdrant
81
+ tool_name: add_documents
82
+ arguments: {
83
+ "filePath": "/path/to/your/document.pdf",
84
+ "collection": "my-collection",
85
+ "embeddingService": "openai",
86
+ "chunkSize": 1000,
87
+ "chunkOverlap": 200
88
+ }
89
+ ```
90
+
91
+ #### Search
92
+
93
+ ```
94
+ use_mcp_tool
95
+ server_name: better-qdrant
96
+ tool_name: search
97
+ arguments: {
98
+ "query": "your search query",
99
+ "collection": "my-collection",
100
+ "embeddingService": "openai",
101
+ "limit": 5
102
+ }
103
+ ```
104
+
105
+ #### Delete Collection
106
+
107
+ ```
108
+ use_mcp_tool
109
+ server_name: better-qdrant
110
+ tool_name: delete_collection
111
+ arguments: {
112
+ "collection": "my-collection"
113
+ }
114
+ ```
115
+
116
+ ## Requirements
117
+
118
+ - Node.js >= 18.0.0
119
+ - A running Qdrant server (local or remote)
120
+ - API keys for the embedding services you want to use
121
+
122
+ ## License
123
+
124
+ MIT
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/build/index.js ADDED
@@ -0,0 +1,347 @@
1
+ #!/usr/bin/env node
2
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
3
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
4
+ import { CallToolRequestSchema, ErrorCode, ListToolsRequestSchema, McpError, } from '@modelcontextprotocol/sdk/types.js';
5
+ import { config } from 'dotenv';
6
+ import { createQdrantService } from './services/qdrant.js';
7
+ import { createEmbeddingService } from './services/embeddings/index.js';
8
+ import { TextProcessor } from './services/text-processing.js';
9
+ import { v4 as uuidv4 } from 'uuid';
10
+ import { readFileSync } from 'fs';
11
+ // Load environment variables
12
+ config();
13
+ class BetterQdrantServer {
14
+ constructor() {
15
+ this.server = new Server({
16
+ name: 'better-qdrant',
17
+ version: '0.1.0',
18
+ }, {
19
+ capabilities: {
20
+ tools: {},
21
+ },
22
+ });
23
+ // Initialize services
24
+ this.qdrantService = createQdrantService(process.env.QDRANT_URL || 'http://localhost:6333', process.env.QDRANT_API_KEY);
25
+ this.textProcessor = new TextProcessor();
26
+ this.setupToolHandlers();
27
+ // Error handling
28
+ this.server.onerror = (error) => console.error('[MCP Error]', error);
29
+ process.on('SIGINT', async () => {
30
+ await this.server.close();
31
+ process.exit(0);
32
+ });
33
+ }
34
+ isAddDocumentsArgs(args) {
35
+ if (!args || typeof args !== 'object')
36
+ return false;
37
+ const a = args;
38
+ return (typeof a.filePath === 'string' &&
39
+ typeof a.collection === 'string' &&
40
+ typeof a.embeddingService === 'string' &&
41
+ ['openai', 'openrouter', 'fastembed', 'ollama'].includes(a.embeddingService) &&
42
+ (a.chunkSize === undefined || typeof a.chunkSize === 'number') &&
43
+ (a.chunkOverlap === undefined || typeof a.chunkOverlap === 'number'));
44
+ }
45
+ isSearchArgs(args) {
46
+ if (!args || typeof args !== 'object')
47
+ return false;
48
+ const a = args;
49
+ return (typeof a.query === 'string' &&
50
+ typeof a.collection === 'string' &&
51
+ typeof a.embeddingService === 'string' &&
52
+ ['openai', 'openrouter', 'fastembed', 'ollama'].includes(a.embeddingService) &&
53
+ (a.limit === undefined || typeof a.limit === 'number'));
54
+ }
55
+ isDeleteCollectionArgs(args) {
56
+ if (!args || typeof args !== 'object')
57
+ return false;
58
+ const a = args;
59
+ return typeof a.collection === 'string';
60
+ }
61
+ setupToolHandlers() {
62
+ this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
63
+ tools: [
64
+ {
65
+ name: 'list_collections',
66
+ description: 'List all available Qdrant collections',
67
+ inputSchema: {
68
+ type: 'object',
69
+ properties: {},
70
+ required: [],
71
+ },
72
+ },
73
+ {
74
+ name: 'add_documents',
75
+ description: 'Add documents to a Qdrant collection with specified embedding service',
76
+ inputSchema: {
77
+ type: 'object',
78
+ properties: {
79
+ filePath: {
80
+ type: 'string',
81
+ description: 'Path to the file to process',
82
+ },
83
+ collection: {
84
+ type: 'string',
85
+ description: 'Name of the collection to add documents to',
86
+ },
87
+ embeddingService: {
88
+ type: 'string',
89
+ enum: ['openai', 'openrouter', 'fastembed', 'ollama'],
90
+ description: 'Embedding service to use',
91
+ },
92
+ chunkSize: {
93
+ type: 'number',
94
+ description: 'Size of text chunks (optional)',
95
+ },
96
+ chunkOverlap: {
97
+ type: 'number',
98
+ description: 'Overlap between chunks (optional)',
99
+ },
100
+ },
101
+ required: ['filePath', 'collection', 'embeddingService'],
102
+ },
103
+ },
104
+ {
105
+ name: 'search',
106
+ description: 'Search for similar documents in a collection',
107
+ inputSchema: {
108
+ type: 'object',
109
+ properties: {
110
+ query: {
111
+ type: 'string',
112
+ description: 'Search query',
113
+ },
114
+ collection: {
115
+ type: 'string',
116
+ description: 'Name of the collection to search in',
117
+ },
118
+ embeddingService: {
119
+ type: 'string',
120
+ enum: ['openai', 'openrouter', 'fastembed', 'ollama'],
121
+ description: 'Embedding service to use',
122
+ },
123
+ limit: {
124
+ type: 'number',
125
+ description: 'Maximum number of results to return (optional)',
126
+ },
127
+ },
128
+ required: ['query', 'collection', 'embeddingService'],
129
+ },
130
+ },
131
+ {
132
+ name: 'delete_collection',
133
+ description: 'Delete a Qdrant collection',
134
+ inputSchema: {
135
+ type: 'object',
136
+ properties: {
137
+ collection: {
138
+ type: 'string',
139
+ description: 'Name of the collection to delete',
140
+ },
141
+ },
142
+ required: ['collection'],
143
+ },
144
+ },
145
+ ],
146
+ }));
147
+ this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
148
+ switch (request.params.name) {
149
+ case 'list_collections':
150
+ return this.handleListCollections();
151
+ case 'add_documents':
152
+ if (!this.isAddDocumentsArgs(request.params.arguments)) {
153
+ throw new McpError(ErrorCode.InvalidParams, 'Invalid arguments for add_documents');
154
+ }
155
+ return this.handleAddDocuments(request.params.arguments);
156
+ case 'search':
157
+ if (!this.isSearchArgs(request.params.arguments)) {
158
+ throw new McpError(ErrorCode.InvalidParams, 'Invalid arguments for search');
159
+ }
160
+ return this.handleSearch(request.params.arguments);
161
+ case 'delete_collection':
162
+ if (!this.isDeleteCollectionArgs(request.params.arguments)) {
163
+ throw new McpError(ErrorCode.InvalidParams, 'Invalid arguments for delete_collection');
164
+ }
165
+ return this.handleDeleteCollection(request.params.arguments);
166
+ default:
167
+ throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${request.params.name}`);
168
+ }
169
+ });
170
+ }
171
+ async handleListCollections() {
172
+ try {
173
+ const collections = await this.qdrantService.listCollections();
174
+ return {
175
+ content: [
176
+ {
177
+ type: 'text',
178
+ text: JSON.stringify(collections, null, 2),
179
+ },
180
+ ],
181
+ };
182
+ }
183
+ catch (error) {
184
+ console.error('Error in handleListCollections:', error);
185
+ let errorDetails = '';
186
+ if (error instanceof Error) {
187
+ errorDetails = `${error.name}: ${error.message}\nStack: ${error.stack}`;
188
+ }
189
+ else {
190
+ errorDetails = String(error);
191
+ }
192
+ return {
193
+ content: [
194
+ {
195
+ type: 'text',
196
+ text: `Error listing collections: ${errorDetails}`,
197
+ },
198
+ ],
199
+ isError: true,
200
+ };
201
+ }
202
+ }
203
+ async handleAddDocuments(args) {
204
+ try {
205
+ // Configure text processor if custom settings provided
206
+ if (args.chunkSize) {
207
+ this.textProcessor.setChunkSize(args.chunkSize);
208
+ }
209
+ if (args.chunkOverlap) {
210
+ this.textProcessor.setChunkOverlap(args.chunkOverlap);
211
+ }
212
+ // Read and process the file
213
+ const content = readFileSync(args.filePath, 'utf-8');
214
+ const chunks = await this.textProcessor.processFile(content, args.filePath);
215
+ // Create embedding service
216
+ const embeddingService = createEmbeddingService({
217
+ type: args.embeddingService,
218
+ apiKey: process.env[`${args.embeddingService.toUpperCase()}_API_KEY`],
219
+ endpoint: process.env[`${args.embeddingService.toUpperCase()}_ENDPOINT`],
220
+ });
221
+ // Generate embeddings
222
+ const embeddings = await embeddingService.generateEmbeddings(chunks.map(chunk => chunk.text));
223
+ // Create collection if it doesn't exist
224
+ const collections = await this.qdrantService.listCollections();
225
+ if (!collections.includes(args.collection)) {
226
+ await this.qdrantService.createCollection(args.collection, embeddingService.vectorSize);
227
+ }
228
+ // Add documents to collection
229
+ await this.qdrantService.addDocuments(args.collection, chunks.map((chunk, i) => ({
230
+ id: uuidv4(),
231
+ vector: embeddings[i],
232
+ payload: {
233
+ text: chunk.text,
234
+ ...chunk.metadata,
235
+ },
236
+ })));
237
+ return {
238
+ content: [
239
+ {
240
+ type: 'text',
241
+ text: `Successfully processed and added ${chunks.length} chunks to collection ${args.collection}`,
242
+ },
243
+ ],
244
+ };
245
+ }
246
+ catch (error) {
247
+ const errorMessage = error instanceof Error ? error.message : String(error);
248
+ return {
249
+ content: [
250
+ {
251
+ type: 'text',
252
+ text: `Error adding documents: ${errorMessage}`,
253
+ },
254
+ ],
255
+ isError: true,
256
+ };
257
+ }
258
+ }
259
+ async handleSearch(args) {
260
+ try {
261
+ // Create embedding service
262
+ const embeddingService = createEmbeddingService({
263
+ type: args.embeddingService,
264
+ apiKey: process.env[`${args.embeddingService.toUpperCase()}_API_KEY`],
265
+ endpoint: process.env[`${args.embeddingService.toUpperCase()}_ENDPOINT`],
266
+ });
267
+ // Generate query embedding
268
+ const [queryEmbedding] = await embeddingService.generateEmbeddings([args.query]);
269
+ // Search collection
270
+ const results = await this.qdrantService.search(args.collection, queryEmbedding, args.limit);
271
+ // Format the results to only include the payload text
272
+ let responseText = '';
273
+ results.forEach((result, index) => {
274
+ // For documents collection, the text is in result.payload.text
275
+ // For other collections, it might be in different fields
276
+ const text = result.payload.text || result.payload.content || JSON.stringify(result.payload);
277
+ const source = result.payload.source || result.payload.metadata?.source || '';
278
+ const score = result.score.toFixed(2);
279
+ responseText += `Result ${index + 1} (Score: ${score}):\n${text}\n`;
280
+ if (source) {
281
+ responseText += `Source: ${source}\n`;
282
+ }
283
+ responseText += '\n';
284
+ });
285
+ if (responseText === '') {
286
+ responseText = 'No results found.';
287
+ }
288
+ return {
289
+ content: [
290
+ {
291
+ type: 'text',
292
+ text: responseText,
293
+ },
294
+ ],
295
+ };
296
+ }
297
+ catch (error) {
298
+ const errorMessage = error instanceof Error ? error.message : String(error);
299
+ return {
300
+ content: [
301
+ {
302
+ type: 'text',
303
+ text: `Error searching: ${errorMessage}`,
304
+ },
305
+ ],
306
+ isError: true,
307
+ };
308
+ }
309
+ }
310
+ async handleDeleteCollection(args) {
311
+ try {
312
+ // Delete the collection
313
+ await this.qdrantService.deleteCollection(args.collection);
314
+ return {
315
+ content: [
316
+ {
317
+ type: 'text',
318
+ text: `Successfully deleted collection: ${args.collection}`,
319
+ },
320
+ ],
321
+ };
322
+ }
323
+ catch (error) {
324
+ const errorMessage = error instanceof Error ? error.message : String(error);
325
+ return {
326
+ content: [
327
+ {
328
+ type: 'text',
329
+ text: `Error deleting collection: ${errorMessage}`,
330
+ },
331
+ ],
332
+ isError: true,
333
+ };
334
+ }
335
+ }
336
+ async run() {
337
+ const transport = new StdioServerTransport();
338
+ await this.server.connect(transport);
339
+ console.error('Better Qdrant MCP server running on stdio');
340
+ }
341
+ }
342
+ const server = new BetterQdrantServer();
343
+ server.run().catch((error) => {
344
+ console.error('Server error:', error instanceof Error ? error.message : String(error));
345
+ process.exit(1);
346
+ });
347
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import { EmbeddingGenerator } from '../../types.js';
2
+ export declare abstract class BaseEmbeddingService implements EmbeddingGenerator {
3
+ protected apiKey?: string | undefined;
4
+ protected endpoint?: string | undefined;
5
+ protected model?: string | undefined;
6
+ constructor(apiKey?: string | undefined, endpoint?: string | undefined, model?: string | undefined);
7
+ abstract vectorSize: number;
8
+ abstract generateEmbeddings(texts: string[]): Promise<number[][]>;
9
+ protected validateConfig(): void;
10
+ protected requiresApiKey(): boolean;
11
+ }
@@ -0,0 +1,16 @@
1
+ export class BaseEmbeddingService {
2
+ constructor(apiKey, endpoint, model) {
3
+ this.apiKey = apiKey;
4
+ this.endpoint = endpoint;
5
+ this.model = model;
6
+ }
7
+ validateConfig() {
8
+ if (this.requiresApiKey() && !this.apiKey) {
9
+ throw new Error(`${this.constructor.name} requires an API key`);
10
+ }
11
+ }
12
+ requiresApiKey() {
13
+ return true;
14
+ }
15
+ }
16
+ //# sourceMappingURL=base.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.js","sourceRoot":"","sources":["../../../src/services/embeddings/base.ts"],"names":[],"mappings":"AAEA,MAAM,OAAgB,oBAAoB;IACxC,YAAsB,MAAe,EAAY,QAAiB,EAAY,KAAc;QAAtE,WAAM,GAAN,MAAM,CAAS;QAAY,aAAQ,GAAR,QAAQ,CAAS;QAAY,UAAK,GAAL,KAAK,CAAS;IAAG,CAAC;IAKtF,cAAc;QACtB,IAAI,IAAI,CAAC,cAAc,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YAC1C,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,sBAAsB,CAAC,CAAC;QAClE,CAAC;IACH,CAAC;IAES,cAAc;QACtB,OAAO,IAAI,CAAC;IACd,CAAC;CACF"}
@@ -0,0 +1,11 @@
1
+ import { BaseEmbeddingService } from './base.js';
2
+ export declare class FastEmbedService extends BaseEmbeddingService {
3
+ readonly vectorSize = 384;
4
+ private readonly defaultModel;
5
+ private embedder;
6
+ constructor(model?: string);
7
+ private initializeEmbedder;
8
+ generateEmbeddings(texts: string[]): Promise<number[][]>;
9
+ protected requiresApiKey(): boolean;
10
+ protected validateConfig(): void;
11
+ }
@@ -0,0 +1,34 @@
1
+ import { BaseEmbeddingService } from './base.js';
2
+ export class FastEmbedService extends BaseEmbeddingService {
3
+ constructor(model) {
4
+ super(undefined, undefined, model || 'BAAI/bge-small-en');
5
+ // FastEmbed models typically produce 384-dimensional embeddings
6
+ this.vectorSize = 384;
7
+ this.defaultModel = 'BAAI/bge-small-en';
8
+ this.embedder = null;
9
+ }
10
+ async initializeEmbedder() {
11
+ if (!this.embedder) {
12
+ // Dynamic import to handle CommonJS module
13
+ const fastembed = await import('fastembed');
14
+ this.embedder = new fastembed.FastEmbed({
15
+ model: this.model || this.defaultModel
16
+ });
17
+ }
18
+ }
19
+ async generateEmbeddings(texts) {
20
+ await this.initializeEmbedder();
21
+ if (!this.embedder) {
22
+ throw new Error('FastEmbed embedder not initialized');
23
+ }
24
+ const embeddings = await this.embedder.embed(texts);
25
+ return embeddings.map((embedding) => Array.from(embedding));
26
+ }
27
+ requiresApiKey() {
28
+ return false;
29
+ }
30
+ validateConfig() {
31
+ // No validation needed as FastEmbed runs locally
32
+ }
33
+ }
34
+ //# sourceMappingURL=fastembed.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fastembed.js","sourceRoot":"","sources":["../../../src/services/embeddings/fastembed.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAEjD,MAAM,OAAO,gBAAiB,SAAQ,oBAAoB;IAMxD,YAAY,KAAc;QACxB,KAAK,CAAC,SAAS,EAAE,SAAS,EAAE,KAAK,IAAI,mBAAmB,CAAC,CAAC;QAN5D,gEAAgE;QACvD,eAAU,GAAG,GAAG,CAAC;QACT,iBAAY,GAAG,mBAAmB,CAAC;QAC5C,aAAQ,GAAQ,IAAI,CAAC;IAI7B,CAAC;IAEO,KAAK,CAAC,kBAAkB;QAC9B,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnB,2CAA2C;YAC3C,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC;YAC5C,IAAI,CAAC,QAAQ,GAAG,IAAI,SAAS,CAAC,SAAS,CAAC;gBACtC,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,YAAY;aACvC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,KAAK,CAAC,kBAAkB,CAAC,KAAe;QACtC,MAAM,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAChC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;QACxD,CAAC;QAED,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACpD,OAAO,UAAU,CAAC,GAAG,CAAC,CAAC,SAAuB,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;IAC5E,CAAC;IAES,cAAc;QACtB,OAAO,KAAK,CAAC;IACf,CAAC;IAES,cAAc;QACtB,iDAAiD;IACnD,CAAC;CACF"}
@@ -0,0 +1,6 @@
1
+ import { EmbeddingGenerator, EmbeddingServiceConfig } from '../../types.js';
2
+ export declare function createEmbeddingService(config: EmbeddingServiceConfig): EmbeddingGenerator;
3
+ export { OpenAIEmbeddingService } from './openai.js';
4
+ export { OpenRouterEmbeddingService } from './openrouter.js';
5
+ export { OllamaEmbeddingService } from './ollama.js';
6
+ export { FastEmbedService } from './fastembed.js';
@@ -0,0 +1,29 @@
1
+ import { OpenAIEmbeddingService } from './openai.js';
2
+ import { OpenRouterEmbeddingService } from './openrouter.js';
3
+ import { OllamaEmbeddingService } from './ollama.js';
4
+ import { FastEmbedService } from './fastembed.js';
5
+ export function createEmbeddingService(config) {
6
+ switch (config.type) {
7
+ case 'openai':
8
+ if (!config.apiKey) {
9
+ throw new Error('OpenAI API key is required');
10
+ }
11
+ return new OpenAIEmbeddingService(config.apiKey, config.endpoint, config.model);
12
+ case 'openrouter':
13
+ if (!config.apiKey) {
14
+ throw new Error('OpenRouter API key is required');
15
+ }
16
+ return new OpenRouterEmbeddingService(config.apiKey, config.endpoint, config.model);
17
+ case 'ollama':
18
+ return new OllamaEmbeddingService(config.endpoint, config.model);
19
+ case 'fastembed':
20
+ return new FastEmbedService(config.model);
21
+ default:
22
+ throw new Error(`Unknown embedding service type: ${config.type}`);
23
+ }
24
+ }
25
+ export { OpenAIEmbeddingService } from './openai.js';
26
+ export { OpenRouterEmbeddingService } from './openrouter.js';
27
+ export { OllamaEmbeddingService } from './ollama.js';
28
+ export { FastEmbedService } from './fastembed.js';
29
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/services/embeddings/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,0BAA0B,EAAE,MAAM,iBAAiB,CAAC;AAC7D,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAElD,MAAM,UAAU,sBAAsB,CAAC,MAA8B;IACnE,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC;QACpB,KAAK,QAAQ;YACX,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;gBACnB,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;YAChD,CAAC;YACD,OAAO,IAAI,sBAAsB,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;QAElF,KAAK,YAAY;YACf,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;gBACnB,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;YACpD,CAAC;YACD,OAAO,IAAI,0BAA0B,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;QAEtF,KAAK,QAAQ;YACX,OAAO,IAAI,sBAAsB,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;QAEnE,KAAK,WAAW;YACd,OAAO,IAAI,gBAAgB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAE5C;YACE,MAAM,IAAI,KAAK,CAAC,mCAAmC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;IACtE,CAAC;AACH,CAAC;AAED,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,0BAA0B,EAAE,MAAM,iBAAiB,CAAC;AAC7D,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { BaseEmbeddingService } from './base.js';
2
+ export declare class OllamaEmbeddingService extends BaseEmbeddingService {
3
+ readonly vectorSize = 768;
4
+ private readonly defaultModel;
5
+ private readonly defaultEndpoint;
6
+ constructor(endpoint?: string, model?: string);
7
+ generateEmbeddings(texts: string[]): Promise<number[][]>;
8
+ protected requiresApiKey(): boolean;
9
+ protected validateConfig(): void;
10
+ }
@@ -0,0 +1,41 @@
1
+ import axios from 'axios';
2
+ import { BaseEmbeddingService } from './base.js';
3
+ export class OllamaEmbeddingService extends BaseEmbeddingService {
4
+ constructor(endpoint, model) {
5
+ super(undefined, endpoint || 'http://localhost:11434', model || 'nomic-embed-text');
6
+ // Vector size depends on the model
7
+ // nomic-embed-text produces 768-dimensional embeddings
8
+ this.vectorSize = 768;
9
+ this.defaultModel = 'nomic-embed-text';
10
+ this.defaultEndpoint = 'http://localhost:11434';
11
+ this.validateConfig();
12
+ }
13
+ async generateEmbeddings(texts) {
14
+ const embeddings = [];
15
+ // Ollama API requires sequential processing of texts
16
+ for (const text of texts) {
17
+ const response = await axios.post(`${this.endpoint}/api/embeddings`, {
18
+ model: this.model || this.defaultModel,
19
+ prompt: text,
20
+ }, {
21
+ headers: {
22
+ 'Content-Type': 'application/json',
23
+ },
24
+ });
25
+ if (!response.data.embedding || !Array.isArray(response.data.embedding)) {
26
+ throw new Error('Invalid response from Ollama API');
27
+ }
28
+ embeddings.push(response.data.embedding);
29
+ }
30
+ return embeddings;
31
+ }
32
+ requiresApiKey() {
33
+ return false;
34
+ }
35
+ validateConfig() {
36
+ if (!this.endpoint) {
37
+ throw new Error('Ollama endpoint is required');
38
+ }
39
+ }
40
+ }
41
+ //# sourceMappingURL=ollama.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ollama.js","sourceRoot":"","sources":["../../../src/services/embeddings/ollama.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAEjD,MAAM,OAAO,sBAAuB,SAAQ,oBAAoB;IAO9D,YAAY,QAAiB,EAAE,KAAc;QAC3C,KAAK,CAAC,SAAS,EAAE,QAAQ,IAAI,wBAAwB,EAAE,KAAK,IAAI,kBAAkB,CAAC,CAAC;QAPtF,mCAAmC;QACnC,uDAAuD;QAC9C,eAAU,GAAG,GAAG,CAAC;QACT,iBAAY,GAAG,kBAAkB,CAAC;QAClC,oBAAe,GAAG,wBAAwB,CAAC;QAI1D,IAAI,CAAC,cAAc,EAAE,CAAC;IACxB,CAAC;IAED,KAAK,CAAC,kBAAkB,CAAC,KAAe;QACtC,MAAM,UAAU,GAAe,EAAE,CAAC;QAElC,qDAAqD;QACrD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,IAAI,CAC/B,GAAG,IAAI,CAAC,QAAQ,iBAAiB,EACjC;gBACE,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,YAAY;gBACtC,MAAM,EAAE,IAAI;aACb,EACD;gBACE,OAAO,EAAE;oBACP,cAAc,EAAE,kBAAkB;iBACnC;aACF,CACF,CAAC;YAEF,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;gBACxE,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;YACtD,CAAC;YAED,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC3C,CAAC;QAED,OAAO,UAAU,CAAC;IACpB,CAAC;IAES,cAAc;QACtB,OAAO,KAAK,CAAC;IACf,CAAC;IAES,cAAc;QACtB,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;QACjD,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,10 @@
1
+ import { BaseEmbeddingService } from './base.js';
2
+ export declare class OpenAIEmbeddingService extends BaseEmbeddingService {
3
+ readonly vectorSize = 1536;
4
+ private readonly defaultModel;
5
+ private readonly defaultEndpoint;
6
+ constructor(apiKey: string, endpoint?: string, model?: string);
7
+ generateEmbeddings(texts: string[]): Promise<number[][]>;
8
+ protected requiresApiKey(): boolean;
9
+ protected validateConfig(): void;
10
+ }
@@ -0,0 +1,44 @@
1
+ import axios from 'axios';
2
+ import { BaseEmbeddingService } from './base.js';
3
+ export class OpenAIEmbeddingService extends BaseEmbeddingService {
4
+ constructor(apiKey, endpoint, model) {
5
+ super(apiKey, endpoint || 'https://api.openai.com/v1', model || 'text-embedding-ada-002');
6
+ // OpenAI's text-embedding-ada-002 produces 1536-dimensional embeddings
7
+ this.vectorSize = 1536;
8
+ this.defaultModel = 'text-embedding-ada-002';
9
+ this.defaultEndpoint = 'https://api.openai.com/v1';
10
+ this.validateConfig();
11
+ }
12
+ async generateEmbeddings(texts) {
13
+ const response = await axios.post(`${this.endpoint}/embeddings`, {
14
+ input: texts,
15
+ model: this.model || this.defaultModel,
16
+ }, {
17
+ headers: {
18
+ 'Authorization': `Bearer ${this.apiKey}`,
19
+ 'Content-Type': 'application/json',
20
+ },
21
+ });
22
+ if (!response.data.data || !Array.isArray(response.data.data)) {
23
+ throw new Error('Invalid response from OpenAI API');
24
+ }
25
+ return response.data.data.map((item) => {
26
+ if (!item.embedding || !Array.isArray(item.embedding)) {
27
+ throw new Error('Invalid embedding format in OpenAI response');
28
+ }
29
+ return item.embedding;
30
+ });
31
+ }
32
+ requiresApiKey() {
33
+ return true;
34
+ }
35
+ validateConfig() {
36
+ if (!this.apiKey) {
37
+ throw new Error('OpenAI API key is required');
38
+ }
39
+ if (!this.endpoint) {
40
+ throw new Error('OpenAI endpoint is required');
41
+ }
42
+ }
43
+ }
44
+ //# sourceMappingURL=openai.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai.js","sourceRoot":"","sources":["../../../src/services/embeddings/openai.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAEjD,MAAM,OAAO,sBAAuB,SAAQ,oBAAoB;IAM9D,YAAY,MAAc,EAAE,QAAiB,EAAE,KAAc;QAC3D,KAAK,CACH,MAAM,EACN,QAAQ,IAAI,2BAA2B,EACvC,KAAK,IAAI,wBAAwB,CAClC,CAAC;QAVJ,uEAAuE;QAC9D,eAAU,GAAG,IAAI,CAAC;QACV,iBAAY,GAAG,wBAAwB,CAAC;QACxC,oBAAe,GAAG,2BAA2B,CAAC;QAQ7D,IAAI,CAAC,cAAc,EAAE,CAAC;IACxB,CAAC;IAED,KAAK,CAAC,kBAAkB,CAAC,KAAe;QACtC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,IAAI,CAC/B,GAAG,IAAI,CAAC,QAAQ,aAAa,EAC7B;YACE,KAAK,EAAE,KAAK;YACZ,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,YAAY;SACvC,EACD;YACE,OAAO,EAAE;gBACP,eAAe,EAAE,UAAU,IAAI,CAAC,MAAM,EAAE;gBACxC,cAAc,EAAE,kBAAkB;aACnC;SACF,CACF,CAAC;QAEF,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC9D,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;QACtD,CAAC;QAED,OAAO,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAS,EAAE,EAAE;YAC1C,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;gBACtD,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;YACjE,CAAC;YACD,OAAO,IAAI,CAAC,SAAS,CAAC;QACxB,CAAC,CAAC,CAAC;IACL,CAAC;IAES,cAAc;QACtB,OAAO,IAAI,CAAC;IACd,CAAC;IAES,cAAc;QACtB,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;QAChD,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;QACjD,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,9 @@
1
+ import { BaseEmbeddingService } from './base.js';
2
+ export declare class OpenRouterEmbeddingService extends BaseEmbeddingService {
3
+ readonly vectorSize = 1536;
4
+ private readonly defaultModel;
5
+ private readonly defaultEndpoint;
6
+ constructor(apiKey: string, endpoint?: string, model?: string);
7
+ generateEmbeddings(texts: string[]): Promise<number[][]>;
8
+ protected requiresApiKey(): boolean;
9
+ }
@@ -0,0 +1,38 @@
1
+ import axios from 'axios';
2
+ import { BaseEmbeddingService } from './base.js';
3
+ export class OpenRouterEmbeddingService extends BaseEmbeddingService {
4
+ constructor(apiKey, endpoint, model) {
5
+ super(apiKey, endpoint || 'https://openrouter.ai/api/v1', model || 'openai/text-embedding-ada-002');
6
+ // Using OpenAI-compatible model by default, which produces 1536-dimensional embeddings
7
+ this.vectorSize = 1536;
8
+ this.defaultModel = 'openai/text-embedding-ada-002';
9
+ this.defaultEndpoint = 'https://openrouter.ai/api/v1';
10
+ this.validateConfig();
11
+ }
12
+ async generateEmbeddings(texts) {
13
+ const response = await axios.post(`${this.endpoint}/embeddings`, {
14
+ input: texts,
15
+ model: this.model || this.defaultModel,
16
+ }, {
17
+ headers: {
18
+ 'Authorization': `Bearer ${this.apiKey}`,
19
+ 'Content-Type': 'application/json',
20
+ 'HTTP-Referer': 'https://github.com/wreeves/better-qdrant',
21
+ 'X-Title': 'Better Qdrant',
22
+ },
23
+ });
24
+ if (!response.data.data || !Array.isArray(response.data.data)) {
25
+ throw new Error('Invalid response from OpenRouter API');
26
+ }
27
+ return response.data.data.map((item) => {
28
+ if (!item.embedding || !Array.isArray(item.embedding)) {
29
+ throw new Error('Invalid embedding format in OpenRouter response');
30
+ }
31
+ return item.embedding;
32
+ });
33
+ }
34
+ requiresApiKey() {
35
+ return true;
36
+ }
37
+ }
38
+ //# sourceMappingURL=openrouter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openrouter.js","sourceRoot":"","sources":["../../../src/services/embeddings/openrouter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAEjD,MAAM,OAAO,0BAA2B,SAAQ,oBAAoB;IAMlE,YAAY,MAAc,EAAE,QAAiB,EAAE,KAAc;QAC3D,KAAK,CACH,MAAM,EACN,QAAQ,IAAI,8BAA8B,EAC1C,KAAK,IAAI,+BAA+B,CACzC,CAAC;QAVJ,uFAAuF;QAC9E,eAAU,GAAG,IAAI,CAAC;QACV,iBAAY,GAAG,+BAA+B,CAAC;QAC/C,oBAAe,GAAG,8BAA8B,CAAC;QAQhE,IAAI,CAAC,cAAc,EAAE,CAAC;IACxB,CAAC;IAED,KAAK,CAAC,kBAAkB,CAAC,KAAe;QACtC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,IAAI,CAC/B,GAAG,IAAI,CAAC,QAAQ,aAAa,EAC7B;YACE,KAAK,EAAE,KAAK;YACZ,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,YAAY;SACvC,EACD;YACE,OAAO,EAAE;gBACP,eAAe,EAAE,UAAU,IAAI,CAAC,MAAM,EAAE;gBACxC,cAAc,EAAE,kBAAkB;gBAClC,cAAc,EAAE,0CAA0C;gBAC1D,SAAS,EAAE,eAAe;aAC3B;SACF,CACF,CAAC;QAEF,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC9D,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;QAC1D,CAAC;QAED,OAAO,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAS,EAAE,EAAE;YAC1C,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;gBACtD,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;YACrE,CAAC;YACD,OAAO,IAAI,CAAC,SAAS,CAAC;QACxB,CAAC,CAAC,CAAC;IACL,CAAC;IAES,cAAc;QACtB,OAAO,IAAI,CAAC;IACd,CAAC;CACF"}
@@ -0,0 +1,18 @@
1
+ import { QdrantClient } from '@qdrant/js-client-rest';
2
+ import { QdrantService, SearchResult } from '../types.js';
3
+ export declare class DefaultQdrantService implements QdrantService {
4
+ client: QdrantClient;
5
+ private url;
6
+ private apiKey?;
7
+ constructor(client: QdrantClient, url: string, apiKey?: string);
8
+ listCollections(): Promise<string[]>;
9
+ createCollection(name: string, vectorSize: number): Promise<void>;
10
+ addDocuments(collection: string, documents: {
11
+ id: string;
12
+ vector: number[];
13
+ payload: Record<string, any>;
14
+ }[]): Promise<void>;
15
+ deleteCollection(name: string): Promise<void>;
16
+ search(collection: string, vector: number[], limit?: number): Promise<SearchResult[]>;
17
+ }
18
+ export declare function createQdrantService(url: string, apiKey?: string): QdrantService;
@@ -0,0 +1,215 @@
1
+ import { QdrantClient } from '@qdrant/js-client-rest';
2
+ import fetch from 'node-fetch';
3
+ export class DefaultQdrantService {
4
+ constructor(client, url, apiKey) {
5
+ this.client = client;
6
+ this.url = url;
7
+ this.apiKey = apiKey;
8
+ }
9
+ async listCollections() {
10
+ try {
11
+ console.log('Attempting to connect to Qdrant server using direct fetch...');
12
+ // Use direct fetch instead of the client
13
+ const collectionsUrl = `${this.url}/collections`;
14
+ console.log(`Fetching from: ${collectionsUrl}`);
15
+ const response = await fetch(collectionsUrl, {
16
+ method: 'GET',
17
+ headers: {
18
+ 'Content-Type': 'application/json',
19
+ ...(this.apiKey ? { 'api-key': this.apiKey } : {})
20
+ },
21
+ // @ts-ignore - node-fetch supports timeout
22
+ timeout: 5000 // 5 second timeout
23
+ });
24
+ if (!response.ok) {
25
+ throw new Error(`HTTP error! Status: ${response.status}`);
26
+ }
27
+ const data = await response.json();
28
+ console.log('Successfully retrieved collections:', data);
29
+ return data.result.collections.map(c => c.name);
30
+ }
31
+ catch (error) {
32
+ console.error('Error in listCollections:', error);
33
+ if (error instanceof Error) {
34
+ console.error(`${error.name}: ${error.message}`);
35
+ console.error('Stack:', error.stack);
36
+ }
37
+ throw error;
38
+ }
39
+ }
40
+ async createCollection(name, vectorSize) {
41
+ try {
42
+ console.log('Attempting to create Qdrant collection using direct fetch...');
43
+ // Use direct fetch instead of the client
44
+ const createUrl = `${this.url}/collections/${name}`;
45
+ console.log(`Fetching from: ${createUrl}`);
46
+ const response = await fetch(createUrl, {
47
+ method: 'PUT',
48
+ headers: {
49
+ 'Content-Type': 'application/json',
50
+ ...(this.apiKey ? { 'api-key': this.apiKey } : {})
51
+ },
52
+ // @ts-ignore - node-fetch supports timeout
53
+ timeout: 5000, // 5 second timeout
54
+ body: JSON.stringify({
55
+ vectors: {
56
+ size: vectorSize,
57
+ distance: 'Cosine',
58
+ }
59
+ })
60
+ });
61
+ if (!response.ok) {
62
+ throw new Error(`HTTP error! Status: ${response.status}`);
63
+ }
64
+ const data = await response.json();
65
+ console.log('Successfully created collection:', data);
66
+ }
67
+ catch (error) {
68
+ console.error('Error in createCollection:', error);
69
+ if (error instanceof Error) {
70
+ console.error(`${error.name}: ${error.message}`);
71
+ console.error('Stack:', error.stack);
72
+ }
73
+ throw error;
74
+ }
75
+ }
76
+ async addDocuments(collection, documents) {
77
+ try {
78
+ console.log('Attempting to add documents to Qdrant collection using direct fetch...');
79
+ // Use direct fetch instead of the client
80
+ const upsertUrl = `${this.url}/collections/${collection}/points`;
81
+ console.log(`Fetching from: ${upsertUrl}`);
82
+ const points = documents.map(doc => ({
83
+ id: doc.id,
84
+ vector: doc.vector,
85
+ payload: doc.payload,
86
+ }));
87
+ const response = await fetch(upsertUrl, {
88
+ method: 'PUT',
89
+ headers: {
90
+ 'Content-Type': 'application/json',
91
+ ...(this.apiKey ? { 'api-key': this.apiKey } : {})
92
+ },
93
+ // @ts-ignore - node-fetch supports timeout
94
+ timeout: 10000, // 10 second timeout for potentially larger uploads
95
+ body: JSON.stringify({
96
+ points
97
+ })
98
+ });
99
+ if (!response.ok) {
100
+ throw new Error(`HTTP error! Status: ${response.status}`);
101
+ }
102
+ const data = await response.json();
103
+ console.log('Successfully added documents:', data);
104
+ }
105
+ catch (error) {
106
+ console.error('Error in addDocuments:', error);
107
+ if (error instanceof Error) {
108
+ console.error(`${error.name}: ${error.message}`);
109
+ console.error('Stack:', error.stack);
110
+ }
111
+ throw error;
112
+ }
113
+ }
114
+ async deleteCollection(name) {
115
+ try {
116
+ console.log('Attempting to delete Qdrant collection using direct fetch...');
117
+ // Use direct fetch instead of the client
118
+ const deleteUrl = `${this.url}/collections/${name}`;
119
+ console.log(`Fetching from: ${deleteUrl}`);
120
+ const response = await fetch(deleteUrl, {
121
+ method: 'DELETE',
122
+ headers: {
123
+ 'Content-Type': 'application/json',
124
+ ...(this.apiKey ? { 'api-key': this.apiKey } : {})
125
+ },
126
+ // @ts-ignore - node-fetch supports timeout
127
+ timeout: 5000 // 5 second timeout
128
+ });
129
+ if (!response.ok) {
130
+ throw new Error(`HTTP error! Status: ${response.status}`);
131
+ }
132
+ const data = await response.json();
133
+ console.log('Successfully deleted collection:', data);
134
+ }
135
+ catch (error) {
136
+ console.error('Error in deleteCollection:', error);
137
+ if (error instanceof Error) {
138
+ console.error(`${error.name}: ${error.message}`);
139
+ console.error('Stack:', error.stack);
140
+ }
141
+ throw error;
142
+ }
143
+ }
144
+ async search(collection, vector, limit = 10) {
145
+ try {
146
+ console.log('Attempting to search Qdrant collection using direct fetch...');
147
+ // Use direct fetch instead of the client
148
+ const searchUrl = `${this.url}/collections/${collection}/points/search`;
149
+ console.log(`Fetching from: ${searchUrl}`);
150
+ const response = await fetch(searchUrl, {
151
+ method: 'POST',
152
+ headers: {
153
+ 'Content-Type': 'application/json',
154
+ ...(this.apiKey ? { 'api-key': this.apiKey } : {})
155
+ },
156
+ // @ts-ignore - node-fetch supports timeout
157
+ timeout: 5000, // 5 second timeout
158
+ body: JSON.stringify({
159
+ vector,
160
+ limit,
161
+ with_payload: true,
162
+ with_vector: true
163
+ })
164
+ });
165
+ if (!response.ok) {
166
+ throw new Error(`HTTP error! Status: ${response.status}`);
167
+ }
168
+ const data = await response.json();
169
+ console.log('Successfully retrieved search results:', data);
170
+ return data.result.map(result => {
171
+ const searchResult = {
172
+ id: result.id,
173
+ score: result.score,
174
+ payload: result.payload,
175
+ };
176
+ // Only include vector if it's a number array
177
+ if (Array.isArray(result.vector) && result.vector.every(v => typeof v === 'number')) {
178
+ searchResult.vector = result.vector;
179
+ }
180
+ return searchResult;
181
+ });
182
+ }
183
+ catch (error) {
184
+ console.error('Error in search:', error);
185
+ if (error instanceof Error) {
186
+ console.error(`${error.name}: ${error.message}`);
187
+ console.error('Stack:', error.stack);
188
+ }
189
+ throw error;
190
+ }
191
+ }
192
+ }
193
+ export function createQdrantService(url, apiKey) {
194
+ // Parse the URL to handle port correctly
195
+ const urlObj = new URL(url);
196
+ // Create client with explicit host and port if provided
197
+ const clientConfig = {
198
+ host: urlObj.hostname,
199
+ apiKey,
200
+ checkCompatibility: false,
201
+ https: urlObj.protocol === 'https:',
202
+ };
203
+ // Only set port if it's explicitly in the URL
204
+ if (urlObj.port) {
205
+ clientConfig.port = parseInt(urlObj.port, 10);
206
+ }
207
+ // Add path if present
208
+ if (urlObj.pathname !== '/' && urlObj.pathname !== '') {
209
+ clientConfig.prefix = urlObj.pathname;
210
+ }
211
+ console.log('Creating Qdrant client with config:', clientConfig);
212
+ const client = new QdrantClient(clientConfig);
213
+ return new DefaultQdrantService(client, url, apiKey);
214
+ }
215
+ //# sourceMappingURL=qdrant.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"qdrant.js","sourceRoot":"","sources":["../../src/services/qdrant.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ export interface TextChunk {
2
+ text: string;
3
+ metadata: {
4
+ index: number;
5
+ source?: string;
6
+ start?: number;
7
+ end?: number;
8
+ };
9
+ }
10
+ export declare class TextProcessor {
11
+ private chunkSize;
12
+ private chunkOverlap;
13
+ private splitter;
14
+ constructor(chunkSize?: number, chunkOverlap?: number);
15
+ processText(text: string, source?: string): Promise<TextChunk[]>;
16
+ processFile(content: string, filename: string): Promise<TextChunk[]>;
17
+ setChunkSize(size: number): void;
18
+ setChunkOverlap(overlap: number): void;
19
+ }
@@ -0,0 +1,41 @@
1
+ import { RecursiveCharacterTextSplitter } from '@langchain/textsplitters';
2
+ export class TextProcessor {
3
+ constructor(chunkSize = 1000, chunkOverlap = 200) {
4
+ this.chunkSize = chunkSize;
5
+ this.chunkOverlap = chunkOverlap;
6
+ this.splitter = new RecursiveCharacterTextSplitter({
7
+ chunkSize: this.chunkSize,
8
+ chunkOverlap: this.chunkOverlap,
9
+ });
10
+ }
11
+ async processText(text, source) {
12
+ const documents = await this.splitter.createDocuments([text]);
13
+ return documents.map((doc, index) => ({
14
+ text: doc.pageContent,
15
+ metadata: {
16
+ index,
17
+ source,
18
+ start: doc.metadata?.start,
19
+ end: doc.metadata?.end,
20
+ },
21
+ }));
22
+ }
23
+ async processFile(content, filename) {
24
+ return this.processText(content, filename);
25
+ }
26
+ setChunkSize(size) {
27
+ this.chunkSize = size;
28
+ this.splitter = new RecursiveCharacterTextSplitter({
29
+ chunkSize: this.chunkSize,
30
+ chunkOverlap: this.chunkOverlap,
31
+ });
32
+ }
33
+ setChunkOverlap(overlap) {
34
+ this.chunkOverlap = overlap;
35
+ this.splitter = new RecursiveCharacterTextSplitter({
36
+ chunkSize: this.chunkSize,
37
+ chunkOverlap: this.chunkOverlap,
38
+ });
39
+ }
40
+ }
41
+ //# sourceMappingURL=text-processing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text-processing.js","sourceRoot":"","sources":["../../src/services/text-processing.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,8BAA8B,EAAE,MAAM,0BAA0B,CAAC;AAa1E,MAAM,OAAO,aAAa;IAGxB,YACU,YAAoB,IAAI,EACxB,eAAuB,GAAG;QAD1B,cAAS,GAAT,SAAS,CAAe;QACxB,iBAAY,GAAZ,YAAY,CAAc;QAElC,IAAI,CAAC,QAAQ,GAAG,IAAI,8BAA8B,CAAC;YACjD,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,YAAY,EAAE,IAAI,CAAC,YAAY;SAChC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,IAAY,EAAE,MAAe;QAC7C,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QAE9D,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC,GAAa,EAAE,KAAa,EAAE,EAAE,CAAC,CAAC;YACtD,IAAI,EAAE,GAAG,CAAC,WAAW;YACrB,QAAQ,EAAE;gBACR,KAAK;gBACL,MAAM;gBACN,KAAK,EAAE,GAAG,CAAC,QAAQ,EAAE,KAAK;gBAC1B,GAAG,EAAE,GAAG,CAAC,QAAQ,EAAE,GAAG;aACvB;SACF,CAAC,CAAC,CAAC;IACN,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,OAAe,EAAE,QAAgB;QACjD,OAAO,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IAC7C,CAAC;IAED,YAAY,CAAC,IAAY;QACvB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC,QAAQ,GAAG,IAAI,8BAA8B,CAAC;YACjD,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,YAAY,EAAE,IAAI,CAAC,YAAY;SAChC,CAAC,CAAC;IACL,CAAC;IAED,eAAe,CAAC,OAAe;QAC7B,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC;QAC5B,IAAI,CAAC,QAAQ,GAAG,IAAI,8BAA8B,CAAC;YACjD,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,YAAY,EAAE,IAAI,CAAC,YAAY;SAChC,CAAC,CAAC;IACL,CAAC;CACF"}
@@ -0,0 +1,43 @@
1
+ import { QdrantClient } from '@qdrant/js-client-rest';
2
+ export type EmbeddingService = 'openai' | 'openrouter' | 'fastembed' | 'ollama';
3
+ export interface EmbeddingServiceConfig {
4
+ type: EmbeddingService;
5
+ apiKey?: string;
6
+ endpoint?: string;
7
+ model?: string;
8
+ }
9
+ export interface QdrantConfig {
10
+ url: string;
11
+ apiKey?: string;
12
+ }
13
+ export interface ServerConfig {
14
+ qdrant: QdrantConfig;
15
+ embedding: EmbeddingServiceConfig;
16
+ }
17
+ export interface Collection {
18
+ name: string;
19
+ vectorSize: number;
20
+ distance: 'Cosine' | 'Euclid' | 'Dot';
21
+ }
22
+ export interface SearchResult {
23
+ id: string;
24
+ score: number;
25
+ payload: Record<string, any>;
26
+ vector?: number[];
27
+ }
28
+ export interface EmbeddingGenerator {
29
+ generateEmbeddings(texts: string[]): Promise<number[][]>;
30
+ vectorSize: number;
31
+ }
32
+ export interface QdrantService {
33
+ client: QdrantClient;
34
+ listCollections(): Promise<string[]>;
35
+ createCollection(name: string, vectorSize: number): Promise<void>;
36
+ deleteCollection(name: string): Promise<void>;
37
+ addDocuments(collection: string, documents: {
38
+ id: string;
39
+ vector: number[];
40
+ payload: Record<string, any>;
41
+ }[]): Promise<void>;
42
+ search(collection: string, vector: number[], limit?: number): Promise<SearchResult[]>;
43
+ }
package/build/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,64 @@
1
+ {
2
+ "name": "better-qdrant-mcp-server",
3
+ "version": "0.1.0",
4
+ "description": "MCP server for enhanced Qdrant vector database functionality",
5
+ "type": "module",
6
+ "main": "build/index.js",
7
+ "bin": {
8
+ "better-qdrant-mcp-server": "build/index.js"
9
+ },
10
+ "scripts": {
11
+ "build": "tsc && chmod +x build/index.js",
12
+ "start": "node build/index.js",
13
+ "dev": "tsc -w",
14
+ "clean": "rm -rf build",
15
+ "prepare": "npm run build",
16
+ "test": "echo \"No tests yet\""
17
+ },
18
+ "keywords": [
19
+ "mcp",
20
+ "qdrant",
21
+ "vector-database",
22
+ "embeddings",
23
+ "semantic-search",
24
+ "claude",
25
+ "openai",
26
+ "ollama",
27
+ "fastembed"
28
+ ],
29
+ "author": "Will Reeves <will@wredia.com>",
30
+ "license": "MIT",
31
+ "dependencies": {
32
+ "@langchain/community": "^0.3.36",
33
+ "@langchain/textsplitters": "^0.1.0",
34
+ "@modelcontextprotocol/sdk": "^1.7.0",
35
+ "@qdrant/js-client-rest": "^1.7.0",
36
+ "axios": "^1.6.7",
37
+ "dotenv": "^16.4.5",
38
+ "fastembed": "^1.1.0",
39
+ "langchain": "^0.3.19",
40
+ "node-fetch": "^3.3.2",
41
+ "uuid": "^9.0.1"
42
+ },
43
+ "devDependencies": {
44
+ "@types/node": "^20.11.24",
45
+ "@types/uuid": "^9.0.8",
46
+ "typescript": "^5.3.3"
47
+ },
48
+ "engines": {
49
+ "node": ">=18.0.0"
50
+ },
51
+ "files": [
52
+ "build",
53
+ "README.md",
54
+ "LICENSE"
55
+ ],
56
+ "repository": {
57
+ "type": "git",
58
+ "url": "git+https://github.com/wrediam/better-qdrant-mcp-server.git"
59
+ },
60
+ "bugs": {
61
+ "url": "https://github.com/wrediam/better-qdrant-mcp-server/issues"
62
+ },
63
+ "homepage": "https://github.com/wrediam/better-qdrant-mcp-server#readme"
64
+ }