@mhalder/qdrant-mcp-server 1.1.0 → 1.1.1
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/CHANGELOG.md +82 -69
- package/CONTRIBUTING.md +81 -92
- package/README.md +97 -634
- package/examples/README.md +63 -253
- package/examples/basic/README.md +18 -72
- package/examples/filters/README.md +55 -155
- package/examples/knowledge-base/README.md +36 -98
- package/examples/rate-limiting/README.md +81 -290
- package/package.json +1 -1
- package/docs/test_report.md +0 -259
package/README.md
CHANGED
|
@@ -3,97 +3,50 @@
|
|
|
3
3
|
[](https://github.com/mhalder/qdrant-mcp-server/actions/workflows/ci.yml)
|
|
4
4
|
[](https://codecov.io/gh/mhalder/qdrant-mcp-server)
|
|
5
5
|
|
|
6
|
-
A Model Context Protocol (MCP) server
|
|
6
|
+
A Model Context Protocol (MCP) server providing semantic search capabilities using Qdrant vector database with multiple embedding providers.
|
|
7
7
|
|
|
8
8
|
## Features
|
|
9
9
|
|
|
10
|
-
- **Zero Setup
|
|
11
|
-
- **
|
|
12
|
-
- **Multiple
|
|
13
|
-
- **
|
|
14
|
-
- **
|
|
15
|
-
- **
|
|
16
|
-
- **Automatic Embeddings**: Converts text to vectors using your choice of embedding provider
|
|
17
|
-
- **Rate Limiting**: Intelligent request throttling with exponential backoff to prevent API rate limit errors
|
|
18
|
-
- **MCP Integration**: Works seamlessly with Claude Code and other MCP clients
|
|
19
|
-
- **Collection Management**: Create, list, and delete vector collections
|
|
20
|
-
- **Document Operations**: Add, search, and delete documents with metadata support
|
|
21
|
-
- **Flexible Configuration**: Easy provider switching via environment variables
|
|
22
|
-
|
|
23
|
-
## Prerequisites
|
|
24
|
-
|
|
25
|
-
- Node.js 20+ (tested on Node.js 20 and 22)
|
|
26
|
-
- Docker and Docker Compose
|
|
10
|
+
- **Zero Setup**: Works out of the box with Ollama - no API keys required
|
|
11
|
+
- **Privacy-First**: Local embeddings and vector storage - data never leaves your machine
|
|
12
|
+
- **Multiple Providers**: Ollama (default), OpenAI, Cohere, and Voyage AI
|
|
13
|
+
- **Semantic Search**: Natural language search with metadata filtering
|
|
14
|
+
- **Rate Limiting**: Intelligent throttling with exponential backoff
|
|
15
|
+
- **Full CRUD**: Create, search, and manage collections and documents
|
|
27
16
|
|
|
28
|
-
|
|
17
|
+
## Quick Start
|
|
29
18
|
|
|
30
|
-
|
|
31
|
-
- Cohere API key
|
|
32
|
-
- Voyage AI API key
|
|
19
|
+
### Prerequisites
|
|
33
20
|
|
|
34
|
-
|
|
21
|
+
- Node.js 20+
|
|
22
|
+
- Docker and Docker Compose
|
|
35
23
|
|
|
36
|
-
|
|
24
|
+
### Installation
|
|
37
25
|
|
|
38
26
|
```bash
|
|
39
|
-
|
|
27
|
+
# Clone and install
|
|
28
|
+
git clone https://github.com/mhalder/qdrant-mcp-server.git
|
|
40
29
|
cd qdrant-mcp-server
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
2. Install dependencies:
|
|
44
|
-
|
|
45
|
-
```bash
|
|
46
30
|
npm install
|
|
47
|
-
```
|
|
48
31
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
```bash
|
|
32
|
+
# Start services and pull model
|
|
52
33
|
docker compose up -d
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
4. Pull the Ollama embedding model:
|
|
56
|
-
|
|
57
|
-
```bash
|
|
58
34
|
docker exec ollama ollama pull nomic-embed-text
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
5. Build the project:
|
|
62
35
|
|
|
63
|
-
|
|
36
|
+
# Build
|
|
64
37
|
npm run build
|
|
65
38
|
```
|
|
66
39
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
### Running the Server
|
|
40
|
+
### Configuration
|
|
70
41
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
```bash
|
|
74
|
-
npm run dev
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
For production:
|
|
78
|
-
|
|
79
|
-
```bash
|
|
80
|
-
node build/index.js
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
### Claude Code Configuration (Linux)
|
|
84
|
-
|
|
85
|
-
Add this to your Claude Code configuration file at `~/.claude/claude_code_config.json`:
|
|
86
|
-
|
|
87
|
-
**Default (Ollama - No API Key Required):**
|
|
42
|
+
Add to `~/.claude/claude_code_config.json`:
|
|
88
43
|
|
|
89
44
|
```json
|
|
90
45
|
{
|
|
91
46
|
"mcpServers": {
|
|
92
47
|
"qdrant": {
|
|
93
48
|
"command": "node",
|
|
94
|
-
"args": [
|
|
95
|
-
"/home/YOUR_USERNAME/projects/active/qdrant-mcp-server/build/index.js"
|
|
96
|
-
],
|
|
49
|
+
"args": ["/path/to/qdrant-mcp-server/build/index.js"],
|
|
97
50
|
"env": {
|
|
98
51
|
"QDRANT_URL": "http://localhost:6333",
|
|
99
52
|
"EMBEDDING_BASE_URL": "http://localhost:11434"
|
|
@@ -103,612 +56,122 @@ Add this to your Claude Code configuration file at `~/.claude/claude_code_config
|
|
|
103
56
|
}
|
|
104
57
|
```
|
|
105
58
|
|
|
106
|
-
**
|
|
59
|
+
**Using a different provider:**
|
|
107
60
|
|
|
108
61
|
```json
|
|
109
|
-
{
|
|
110
|
-
"
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
"args": [
|
|
114
|
-
"/home/YOUR_USERNAME/projects/active/qdrant-mcp-server/build/index.js"
|
|
115
|
-
],
|
|
116
|
-
"env": {
|
|
117
|
-
"EMBEDDING_PROVIDER": "openai",
|
|
118
|
-
"OPENAI_API_KEY": "sk-your-api-key-here",
|
|
119
|
-
"QDRANT_URL": "http://localhost:6333"
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
**With Cohere (Alternative):**
|
|
127
|
-
|
|
128
|
-
```json
|
|
129
|
-
{
|
|
130
|
-
"mcpServers": {
|
|
131
|
-
"qdrant": {
|
|
132
|
-
"command": "node",
|
|
133
|
-
"args": [
|
|
134
|
-
"/home/YOUR_USERNAME/projects/active/qdrant-mcp-server/build/index.js"
|
|
135
|
-
],
|
|
136
|
-
"env": {
|
|
137
|
-
"EMBEDDING_PROVIDER": "cohere",
|
|
138
|
-
"COHERE_API_KEY": "your-cohere-api-key-here",
|
|
139
|
-
"QDRANT_URL": "http://localhost:6333"
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
```
|
|
145
|
-
|
|
146
|
-
**With Voyage AI (Alternative):**
|
|
147
|
-
|
|
148
|
-
```json
|
|
149
|
-
{
|
|
150
|
-
"mcpServers": {
|
|
151
|
-
"qdrant": {
|
|
152
|
-
"command": "node",
|
|
153
|
-
"args": [
|
|
154
|
-
"/home/YOUR_USERNAME/projects/active/qdrant-mcp-server/build/index.js"
|
|
155
|
-
],
|
|
156
|
-
"env": {
|
|
157
|
-
"EMBEDDING_PROVIDER": "voyage",
|
|
158
|
-
"VOYAGE_API_KEY": "your-voyage-api-key-here",
|
|
159
|
-
"QDRANT_URL": "http://localhost:6333"
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
}
|
|
62
|
+
"env": {
|
|
63
|
+
"EMBEDDING_PROVIDER": "openai", // or "cohere", "voyage"
|
|
64
|
+
"OPENAI_API_KEY": "sk-...", // provider-specific API key
|
|
65
|
+
"QDRANT_URL": "http://localhost:6333"
|
|
163
66
|
}
|
|
164
67
|
```
|
|
165
68
|
|
|
166
|
-
|
|
69
|
+
Restart after making changes.
|
|
167
70
|
|
|
168
|
-
|
|
71
|
+
See [Advanced Configuration](#advanced-configuration) section below for all options.
|
|
169
72
|
|
|
170
|
-
##
|
|
73
|
+
## Tools
|
|
171
74
|
|
|
172
|
-
###
|
|
75
|
+
### Collection Management
|
|
173
76
|
|
|
174
|
-
|
|
77
|
+
| Tool | Description |
|
|
78
|
+
| --------------------- | -------------------------------------------------------------------- |
|
|
79
|
+
| `create_collection` | Create collection with specified distance metric (Cosine/Euclid/Dot) |
|
|
80
|
+
| `list_collections` | List all collections |
|
|
81
|
+
| `get_collection_info` | Get collection details and statistics |
|
|
82
|
+
| `delete_collection` | Delete collection and all documents |
|
|
175
83
|
|
|
176
|
-
|
|
84
|
+
### Document Operations
|
|
177
85
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
```
|
|
184
|
-
Create a collection named "my-docs"
|
|
185
|
-
```
|
|
86
|
+
| Tool | Description |
|
|
87
|
+
| ------------------ | ----------------------------------------------------------------------------- |
|
|
88
|
+
| `add_documents` | Add documents with automatic embedding (supports string/number IDs, metadata) |
|
|
89
|
+
| `semantic_search` | Natural language search with optional metadata filtering |
|
|
90
|
+
| `delete_documents` | Delete specific documents by ID |
|
|
186
91
|
|
|
187
|
-
###
|
|
188
|
-
|
|
189
|
-
Add documents to a collection with automatic embedding generation.
|
|
190
|
-
|
|
191
|
-
**Parameters:**
|
|
192
|
-
|
|
193
|
-
- `collection` (string, required): Collection name
|
|
194
|
-
- `documents` (array, required): Array of documents with:
|
|
195
|
-
- `id` (string/number, required): Unique identifier (string IDs are automatically normalized to UUID format)
|
|
196
|
-
- `text` (string, required): Document text content
|
|
197
|
-
- `metadata` (object, optional): Additional metadata
|
|
198
|
-
|
|
199
|
-
**Note:** String IDs are automatically normalized to UUID format for Qdrant compatibility. The normalization is deterministic, so the same string ID will always produce the same UUID.
|
|
200
|
-
|
|
201
|
-
**Example:**
|
|
202
|
-
|
|
203
|
-
```
|
|
204
|
-
Add these documents to "my-docs" collection:
|
|
205
|
-
- id: 1, text: "Introduction to vector databases"
|
|
206
|
-
- id: 2, text: "Semantic search with embeddings"
|
|
207
|
-
```
|
|
208
|
-
|
|
209
|
-
### `semantic_search`
|
|
210
|
-
|
|
211
|
-
Search for documents using natural language.
|
|
212
|
-
|
|
213
|
-
**Parameters:**
|
|
214
|
-
|
|
215
|
-
- `collection` (string, required): Collection to search
|
|
216
|
-
- `query` (string, required): Search query
|
|
217
|
-
- `limit` (number, optional): Max results (default: 5)
|
|
218
|
-
- `filter` (object, optional): Metadata filter in Qdrant format
|
|
219
|
-
|
|
220
|
-
**Filter Format:**
|
|
221
|
-
|
|
222
|
-
The filter parameter accepts Qdrant's native filter format for powerful metadata-based filtering:
|
|
223
|
-
|
|
224
|
-
```json
|
|
225
|
-
{
|
|
226
|
-
"must": [{ "key": "category", "match": { "value": "database" } }]
|
|
227
|
-
}
|
|
228
|
-
```
|
|
229
|
-
|
|
230
|
-
You can also use more complex filters:
|
|
231
|
-
|
|
232
|
-
- **Multiple conditions (AND)**: Use `must` with multiple conditions
|
|
233
|
-
- **Any condition (OR)**: Use `should` with multiple conditions
|
|
234
|
-
- **Negation (NOT)**: Use `must_not` with conditions
|
|
235
|
-
|
|
236
|
-
Example with multiple conditions:
|
|
237
|
-
|
|
238
|
-
```json
|
|
239
|
-
{
|
|
240
|
-
"must": [
|
|
241
|
-
{ "key": "category", "match": { "value": "database" } },
|
|
242
|
-
{ "key": "level", "match": { "value": "beginner" } }
|
|
243
|
-
]
|
|
244
|
-
}
|
|
245
|
-
```
|
|
246
|
-
|
|
247
|
-
**Examples:**
|
|
248
|
-
|
|
249
|
-
Basic search:
|
|
250
|
-
|
|
251
|
-
```
|
|
252
|
-
Search "my-docs" for information about vector databases
|
|
253
|
-
```
|
|
254
|
-
|
|
255
|
-
With single filter:
|
|
256
|
-
|
|
257
|
-
```
|
|
258
|
-
Search "my-docs" for "vector databases" with filter {"must": [{"key": "category", "match": {"value": "technical"}}]}
|
|
259
|
-
```
|
|
260
|
-
|
|
261
|
-
With multiple filters (AND):
|
|
262
|
-
|
|
263
|
-
```
|
|
264
|
-
Search "knowledge-base" for "machine learning" with filter {"must": [{"key": "category", "match": {"value": "ml"}}, {"key": "level", "match": {"value": "advanced"}}]}
|
|
265
|
-
```
|
|
266
|
-
|
|
267
|
-
### `list_collections`
|
|
268
|
-
|
|
269
|
-
List all available collections.
|
|
270
|
-
|
|
271
|
-
### `get_collection_info`
|
|
272
|
-
|
|
273
|
-
Get detailed information about a collection.
|
|
274
|
-
|
|
275
|
-
**Parameters:**
|
|
276
|
-
|
|
277
|
-
- `name` (string, required): Collection name
|
|
278
|
-
|
|
279
|
-
### `delete_collection`
|
|
280
|
-
|
|
281
|
-
Delete a collection and all its documents.
|
|
282
|
-
|
|
283
|
-
**Parameters:**
|
|
284
|
-
|
|
285
|
-
- `name` (string, required): Collection name
|
|
286
|
-
|
|
287
|
-
### `delete_documents`
|
|
288
|
-
|
|
289
|
-
Delete specific documents from a collection.
|
|
290
|
-
|
|
291
|
-
**Parameters:**
|
|
292
|
-
|
|
293
|
-
- `collection` (string, required): Collection name
|
|
294
|
-
- `ids` (array, required): Array of document IDs to delete (string IDs are automatically normalized to UUID format)
|
|
295
|
-
|
|
296
|
-
**Note:** String IDs will be normalized to the same UUID format used when adding documents.
|
|
297
|
-
|
|
298
|
-
## Available Resources
|
|
92
|
+
### Resources
|
|
299
93
|
|
|
300
94
|
- `qdrant://collections` - List all collections
|
|
301
|
-
- `qdrant://collection/{name}` - Collection details
|
|
302
|
-
|
|
303
|
-
## Project Structure
|
|
304
|
-
|
|
305
|
-
```
|
|
306
|
-
qdrant-mcp-server/
|
|
307
|
-
├── src/
|
|
308
|
-
│ ├── index.ts # MCP server implementation
|
|
309
|
-
│ ├── qdrant/
|
|
310
|
-
│ │ └── client.ts # Qdrant client wrapper
|
|
311
|
-
│ └── embeddings/
|
|
312
|
-
│ ├── base.ts # Provider interface and types
|
|
313
|
-
│ ├── factory.ts # Provider factory
|
|
314
|
-
│ ├── openai.ts # OpenAI embeddings provider
|
|
315
|
-
│ ├── cohere.ts # Cohere embeddings provider
|
|
316
|
-
│ ├── voyage.ts # Voyage AI embeddings provider
|
|
317
|
-
│ └── ollama.ts # Ollama embeddings provider
|
|
318
|
-
├── docker-compose.yml # Qdrant Docker setup
|
|
319
|
-
├── .env.example # Environment configuration template
|
|
320
|
-
├── package.json
|
|
321
|
-
├── tsconfig.json
|
|
322
|
-
└── README.md
|
|
323
|
-
```
|
|
324
|
-
|
|
325
|
-
## Example Workflow
|
|
326
|
-
|
|
327
|
-
1. **Create a collection:**
|
|
328
|
-
|
|
329
|
-
```
|
|
330
|
-
Create a collection called "knowledge-base"
|
|
331
|
-
```
|
|
332
|
-
|
|
333
|
-
2. **Add documents:**
|
|
95
|
+
- `qdrant://collection/{name}` - Collection details
|
|
334
96
|
|
|
335
|
-
|
|
336
|
-
Add these documents to knowledge-base:
|
|
337
|
-
- id: "doc1", text: "MCP is a protocol for AI model context", metadata: {"type": "definition", "category": "protocol"}
|
|
338
|
-
- id: "doc2", text: "Vector databases store embeddings for semantic search", metadata: {"type": "definition", "category": "database"}
|
|
339
|
-
- id: "doc3", text: "Qdrant provides high-performance vector similarity search", metadata: {"type": "product", "category": "database"}
|
|
340
|
-
```
|
|
97
|
+
## Examples
|
|
341
98
|
|
|
342
|
-
|
|
99
|
+
See [examples/](examples/) directory for detailed guides:
|
|
343
100
|
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
101
|
+
- **[Basic Usage](examples/basic/)** - Create collections, add documents, search
|
|
102
|
+
- **[Knowledge Base](examples/knowledge-base/)** - Structured documentation with metadata
|
|
103
|
+
- **[Advanced Filtering](examples/filters/)** - Complex boolean filters
|
|
104
|
+
- **[Rate Limiting](examples/rate-limiting/)** - Batch processing with cloud providers
|
|
347
105
|
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
```
|
|
351
|
-
Search knowledge-base for "vector database" with filter {"must": [{"key": "category", "match": {"value": "database"}}]}
|
|
352
|
-
```
|
|
353
|
-
|
|
354
|
-
5. **Get collection information:**
|
|
355
|
-
|
|
356
|
-
```
|
|
357
|
-
Get info about "knowledge-base" collection
|
|
358
|
-
```
|
|
359
|
-
|
|
360
|
-
6. **View all collections:**
|
|
361
|
-
```
|
|
362
|
-
What collections do I have?
|
|
363
|
-
```
|
|
364
|
-
|
|
365
|
-
## Configuration Options
|
|
106
|
+
## Advanced Configuration
|
|
366
107
|
|
|
367
108
|
### Environment Variables
|
|
368
109
|
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
- `text-embedding-3-large` (3072 dims) - Higher quality
|
|
393
|
-
- `text-embedding-ada-002` (1536 dims) - Legacy model
|
|
394
|
-
|
|
395
|
-
Default rate limit: 3500 requests/minute (paid tier)
|
|
396
|
-
|
|
397
|
-
#### Cohere Models
|
|
398
|
-
|
|
399
|
-
- `embed-english-v3.0` (1024 dims, default) - English-optimized
|
|
400
|
-
- `embed-multilingual-v3.0` (1024 dims) - Multi-language support
|
|
401
|
-
- `embed-english-light-v3.0` (384 dims) - Lightweight English model
|
|
402
|
-
- `embed-multilingual-light-v3.0` (384 dims) - Lightweight multilingual model
|
|
403
|
-
|
|
404
|
-
Default rate limit: 100 requests/minute
|
|
405
|
-
|
|
406
|
-
#### Voyage AI Models
|
|
407
|
-
|
|
408
|
-
- `voyage-2` (1024 dims, default) - General purpose
|
|
409
|
-
- `voyage-large-2` (1536 dims) - Enhanced quality
|
|
410
|
-
- `voyage-code-2` (1536 dims) - Code-specialized
|
|
411
|
-
- `voyage-lite-02-instruct` (1024 dims) - Instruction-tuned
|
|
412
|
-
|
|
413
|
-
Default rate limit: 300 requests/minute
|
|
414
|
-
|
|
415
|
-
#### Ollama Models (Local)
|
|
416
|
-
|
|
417
|
-
- `nomic-embed-text` (768 dims, default) - High-quality local embeddings
|
|
418
|
-
- `mxbai-embed-large` (1024 dims) - Larger context window
|
|
419
|
-
- `all-minilm` (384 dims) - Lightweight option
|
|
420
|
-
|
|
421
|
-
Default rate limit: 1000 requests/minute (local, can be adjusted)
|
|
422
|
-
|
|
423
|
-
**Note:** Ollama models must be downloaded first using `ollama pull <model-name>`
|
|
424
|
-
|
|
425
|
-
## Advanced Features
|
|
426
|
-
|
|
427
|
-
### Rate Limiting and Error Handling
|
|
428
|
-
|
|
429
|
-
The server implements robust rate limiting for all embedding providers:
|
|
430
|
-
|
|
431
|
-
**Features:**
|
|
432
|
-
|
|
433
|
-
- **Request Throttling**: Queues requests to stay within provider rate limits (provider-specific defaults)
|
|
434
|
-
- **Exponential Backoff**: Automatically retries failed requests with increasing delays (1s, 2s, 4s, 8s...)
|
|
435
|
-
- **Retry-After Header Support**: Respects provider retry guidance (OpenAI) with validation fallback
|
|
436
|
-
- **Typed Error Handling**: Provider-specific error interfaces for type-safe error detection
|
|
437
|
-
- **Smart Error Detection**: Identifies rate limit errors (429 status) vs other failures
|
|
438
|
-
- **User Feedback**: Clear console messages during retry attempts with estimated wait times
|
|
439
|
-
|
|
440
|
-
**Configuration:**
|
|
441
|
-
|
|
442
|
-
```bash
|
|
443
|
-
# Common settings (apply to all providers)
|
|
444
|
-
EMBEDDING_MAX_REQUESTS_PER_MINUTE=3500 # Adjust based on your provider tier
|
|
445
|
-
EMBEDDING_RETRY_ATTEMPTS=3 # Number of retries before failing
|
|
446
|
-
EMBEDDING_RETRY_DELAY=1000 # Initial delay (doubles each retry)
|
|
447
|
-
```
|
|
448
|
-
|
|
449
|
-
**Provider-Specific Defaults:**
|
|
450
|
-
|
|
451
|
-
- OpenAI: 3500 requests/minute (paid tier)
|
|
452
|
-
- Cohere: 100 requests/minute
|
|
453
|
-
- Voyage AI: 300 requests/minute
|
|
454
|
-
- Ollama: 1000 requests/minute (local, configurable)
|
|
455
|
-
|
|
456
|
-
**Benefits:**
|
|
457
|
-
|
|
458
|
-
- Prevents failed operations during high-volume usage
|
|
459
|
-
- Automatic recovery from temporary API issues
|
|
460
|
-
- Optimized for batch document processing
|
|
461
|
-
- Works seamlessly with both single and batch embedding operations
|
|
462
|
-
- Consistent behavior across all providers
|
|
463
|
-
|
|
464
|
-
### Metadata Filtering
|
|
465
|
-
|
|
466
|
-
The server supports Qdrant's powerful filtering capabilities for refined search results. Filters can be applied to any metadata field stored with your documents.
|
|
467
|
-
|
|
468
|
-
**Supported filter types:**
|
|
469
|
-
|
|
470
|
-
- **Match filters**: Exact value matching for strings, numbers, and booleans
|
|
471
|
-
- **Logical operators**: `must` (AND), `should` (OR), `must_not` (NOT)
|
|
472
|
-
- **Range filters**: Greater than, less than, between (for numeric values)
|
|
473
|
-
- **Nested filters**: Complex boolean expressions
|
|
474
|
-
|
|
475
|
-
See the `semantic_search` tool documentation for filter syntax examples.
|
|
110
|
+
| Variable | Description | Default |
|
|
111
|
+
| ----------------------------------- | -------------------------------------- | --------------------- |
|
|
112
|
+
| `EMBEDDING_PROVIDER` | "ollama", "openai", "cohere", "voyage" | ollama |
|
|
113
|
+
| `QDRANT_URL` | Qdrant server URL | http://localhost:6333 |
|
|
114
|
+
| `EMBEDDING_MODEL` | Model name | Provider-specific |
|
|
115
|
+
| `EMBEDDING_BASE_URL` | Custom API URL | Provider-specific |
|
|
116
|
+
| `EMBEDDING_MAX_REQUESTS_PER_MINUTE` | Rate limit | Provider-specific |
|
|
117
|
+
| `EMBEDDING_RETRY_ATTEMPTS` | Retry count | 3 |
|
|
118
|
+
| `EMBEDDING_RETRY_DELAY` | Initial retry delay (ms) | 1000 |
|
|
119
|
+
| `OPENAI_API_KEY` | OpenAI API key | - |
|
|
120
|
+
| `COHERE_API_KEY` | Cohere API key | - |
|
|
121
|
+
| `VOYAGE_API_KEY` | Voyage AI API key | - |
|
|
122
|
+
|
|
123
|
+
### Provider Comparison
|
|
124
|
+
|
|
125
|
+
| Provider | Models | Dimensions | Rate Limit | Notes |
|
|
126
|
+
| ---------- | --------------------------------------------------------------- | -------------- | ---------- | -------------------- |
|
|
127
|
+
| **Ollama** | `nomic-embed-text` (default), `mxbai-embed-large`, `all-minilm` | 768, 1024, 384 | None | Local, no API key |
|
|
128
|
+
| **OpenAI** | `text-embedding-3-small` (default), `text-embedding-3-large` | 1536, 3072 | 3500/min | Cloud API |
|
|
129
|
+
| **Cohere** | `embed-english-v3.0` (default), `embed-multilingual-v3.0` | 1024 | 100/min | Multilingual support |
|
|
130
|
+
| **Voyage** | `voyage-2` (default), `voyage-large-2`, `voyage-code-2` | 1024, 1536 | 300/min | Code-specialized |
|
|
131
|
+
|
|
132
|
+
**Note:** Ollama models require `docker exec ollama ollama pull <model-name>` before use.
|
|
476
133
|
|
|
477
134
|
## Troubleshooting
|
|
478
135
|
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
docker
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
```bash
|
|
490
|
-
docker compose up -d
|
|
491
|
-
```
|
|
492
|
-
|
|
493
|
-
### Collection doesn't exist
|
|
494
|
-
|
|
495
|
-
Create the collection first before adding documents:
|
|
496
|
-
|
|
497
|
-
```
|
|
498
|
-
Create a collection named "my-collection"
|
|
499
|
-
```
|
|
500
|
-
|
|
501
|
-
### Embedding Provider Errors
|
|
502
|
-
|
|
503
|
-
**OpenAI:**
|
|
504
|
-
|
|
505
|
-
- Verify your API key is correct in `.env`
|
|
506
|
-
- Check your OpenAI account has available credits
|
|
507
|
-
- Ensure you have access to the embedding models
|
|
508
|
-
|
|
509
|
-
**Cohere:**
|
|
510
|
-
|
|
511
|
-
- Verify your Cohere API key is correct
|
|
512
|
-
- Check your Cohere account status and credits
|
|
513
|
-
- Ensure you're using a valid model name
|
|
514
|
-
|
|
515
|
-
**Voyage AI:**
|
|
516
|
-
|
|
517
|
-
- Verify your Voyage API key is correct
|
|
518
|
-
- Check your Voyage AI account status
|
|
519
|
-
- Ensure the base URL is correct (default: https://api.voyageai.com/v1)
|
|
520
|
-
|
|
521
|
-
**Ollama:**
|
|
522
|
-
|
|
523
|
-
- Ensure Ollama is running: `curl http://localhost:11434`
|
|
524
|
-
- Pull the required model: `ollama pull nomic-embed-text`
|
|
525
|
-
- Check the base URL matches your Ollama installation
|
|
526
|
-
|
|
527
|
-
### Rate limit errors
|
|
528
|
-
|
|
529
|
-
The server automatically handles rate limits, but if you see persistent rate limit errors:
|
|
530
|
-
|
|
531
|
-
- Reduce `EMBEDDING_MAX_REQUESTS_PER_MINUTE` to match your provider's tier
|
|
532
|
-
- OpenAI free: 500/min, paid: 3500+/min
|
|
533
|
-
- Cohere: 100/min (adjust based on your plan)
|
|
534
|
-
- Voyage AI: 300/min (adjust based on your plan)
|
|
535
|
-
- Ollama: No limits (local), but adjust based on system capacity
|
|
536
|
-
- Increase `EMBEDDING_RETRY_ATTEMPTS` for more resilient retries
|
|
537
|
-
- Check your provider's dashboard for current usage and limits
|
|
538
|
-
|
|
539
|
-
### Filter errors
|
|
540
|
-
|
|
541
|
-
If you encounter "Bad Request" errors with filters:
|
|
542
|
-
|
|
543
|
-
- Ensure you're using Qdrant's native filter format
|
|
544
|
-
- Check that field names match your metadata exactly
|
|
545
|
-
- Verify the filter structure has proper nesting
|
|
136
|
+
| Issue | Solution |
|
|
137
|
+
| ---------------------- | ---------------------------------------------------------------------------- |
|
|
138
|
+
| **Qdrant not running** | `docker compose up -d` |
|
|
139
|
+
| **Collection missing** | Create collection first before adding documents |
|
|
140
|
+
| **Ollama not running** | Verify with `curl http://localhost:11434`, start with `docker compose up -d` |
|
|
141
|
+
| **Model missing** | `docker exec ollama ollama pull nomic-embed-text` |
|
|
142
|
+
| **Rate limit errors** | Adjust `EMBEDDING_MAX_REQUESTS_PER_MINUTE` to match your provider tier |
|
|
143
|
+
| **API key errors** | Verify correct API key in environment configuration |
|
|
144
|
+
| **Filter errors** | Ensure Qdrant filter format, check field names match metadata |
|
|
546
145
|
|
|
547
146
|
## Development
|
|
548
147
|
|
|
549
|
-
### Development Mode
|
|
550
|
-
|
|
551
|
-
Run in development mode with auto-reload:
|
|
552
|
-
|
|
553
|
-
```bash
|
|
554
|
-
npm run dev
|
|
555
|
-
```
|
|
556
|
-
|
|
557
|
-
### Build
|
|
558
|
-
|
|
559
|
-
Build for production:
|
|
560
|
-
|
|
561
|
-
```bash
|
|
562
|
-
npm run build
|
|
563
|
-
```
|
|
564
|
-
|
|
565
|
-
### Type Checking
|
|
566
|
-
|
|
567
|
-
Run TypeScript type checking without emitting files:
|
|
568
|
-
|
|
569
|
-
```bash
|
|
570
|
-
npm run type-check
|
|
571
|
-
```
|
|
572
|
-
|
|
573
|
-
### Continuous Integration
|
|
574
|
-
|
|
575
|
-
The project uses GitHub Actions for CI/CD:
|
|
576
|
-
|
|
577
|
-
- **Build**: Compiles TypeScript to JavaScript
|
|
578
|
-
- **Type Check**: Validates TypeScript types with strict mode
|
|
579
|
-
- **Test**: Runs all 376 unit tests with 98.27% coverage
|
|
580
|
-
- **Multi-version**: Tests on Node.js 20 and 22
|
|
581
|
-
|
|
582
|
-
The CI workflow runs on every push and pull request to the main branch.
|
|
583
|
-
|
|
584
|
-
## Testing
|
|
585
|
-
|
|
586
|
-
The project includes comprehensive unit and integration tests using Vitest.
|
|
587
|
-
|
|
588
|
-
### Run Tests
|
|
589
|
-
|
|
590
148
|
```bash
|
|
591
|
-
#
|
|
592
|
-
npm
|
|
593
|
-
|
|
594
|
-
# Run
|
|
595
|
-
npm test
|
|
596
|
-
|
|
597
|
-
# Run tests with UI
|
|
598
|
-
npm run test:ui
|
|
599
|
-
|
|
600
|
-
# Run tests with coverage
|
|
601
|
-
npm run test:coverage
|
|
602
|
-
|
|
603
|
-
# Run provider verification tests
|
|
604
|
-
npm run test:providers
|
|
149
|
+
npm run dev # Development with auto-reload
|
|
150
|
+
npm run build # Production build
|
|
151
|
+
npm run type-check # TypeScript validation
|
|
152
|
+
npm test # Run test suite
|
|
153
|
+
npm run test:coverage # Coverage report
|
|
605
154
|
```
|
|
606
155
|
|
|
607
|
-
###
|
|
156
|
+
### Testing
|
|
608
157
|
|
|
609
|
-
|
|
158
|
+
**422 tests** (376 unit + 46 functional) with **98%+ coverage**:
|
|
610
159
|
|
|
611
|
-
**Unit Tests
|
|
160
|
+
- **Unit Tests**: QdrantManager (21), Ollama (31), OpenAI (25), Cohere (29), Voyage (31), Factory (32), MCP Server (19)
|
|
161
|
+
- **Functional Tests**: Live API integration, end-to-end workflows (46)
|
|
612
162
|
|
|
613
|
-
|
|
614
|
-
- **OllamaEmbeddings** (31 tests): Local embedding generation, batch processing, rate limiting - DEFAULT PROVIDER
|
|
615
|
-
- **OpenAIEmbeddings** (25 tests): Cloud embedding generation, batch processing, rate limiting with Retry-After header
|
|
616
|
-
- **CohereEmbeddings** (29 tests): Cohere API integration, batch processing, rate limiting
|
|
617
|
-
- **VoyageEmbeddings** (31 tests): Voyage AI integration, batch processing, rate limiting
|
|
618
|
-
- **Factory Pattern** (32 tests): Provider instantiation, configuration, error handling
|
|
619
|
-
- **MCP Server** (19 tests): Tool schemas, resource URI patterns, and MCP protocol compliance
|
|
620
|
-
|
|
621
|
-
**Functional/Interactive Tests:**
|
|
622
|
-
|
|
623
|
-
- **Live API Integration** (46 tests): Real embedding APIs, production MCP server validation, rate limiting behavior, and end-to-end workflows with real documents
|
|
624
|
-
|
|
625
|
-
**Coverage Highlights:**
|
|
626
|
-
|
|
627
|
-
- ✅ 100% function coverage across all modules
|
|
628
|
-
- ✅ Comprehensive rate limiting tests with timing validation
|
|
629
|
-
- ✅ Typed error handling with OpenAIError interface
|
|
630
|
-
- ✅ Invalid Retry-After header fallback to exponential backoff
|
|
631
|
-
- ✅ Real-world validation with live OpenAI API
|
|
632
|
-
- ✅ Both source and compiled code tested
|
|
633
|
-
|
|
634
|
-
See [`docs/test_report.md`](docs/test_report.md) for detailed test results and coverage analysis.
|
|
635
|
-
|
|
636
|
-
### Writing Tests
|
|
637
|
-
|
|
638
|
-
Tests are located next to the files they test with a `.test.ts` extension:
|
|
639
|
-
|
|
640
|
-
- `src/qdrant/client.test.ts` - Qdrant client wrapper tests
|
|
641
|
-
- `src/embeddings/openai.test.ts` - OpenAI embeddings provider tests
|
|
642
|
-
- `src/index.test.ts` - MCP server integration tests
|
|
643
|
-
|
|
644
|
-
Run tests before committing:
|
|
645
|
-
|
|
646
|
-
```bash
|
|
647
|
-
npm test -- --run
|
|
648
|
-
```
|
|
649
|
-
|
|
650
|
-
## License
|
|
651
|
-
|
|
652
|
-
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
163
|
+
**CI/CD**: GitHub Actions runs build, type-check, and tests on Node.js 20 & 22 for every push/PR.
|
|
653
164
|
|
|
654
165
|
## Contributing
|
|
655
166
|
|
|
656
|
-
Contributions
|
|
167
|
+
Contributions welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for:
|
|
657
168
|
|
|
658
|
-
- Code of conduct
|
|
659
169
|
- Development workflow
|
|
660
|
-
-
|
|
661
|
-
-
|
|
662
|
-
- Testing requirements
|
|
663
|
-
|
|
664
|
-
### Quick Start for Contributors
|
|
170
|
+
- Conventional commit format (`feat:`, `fix:`, `BREAKING CHANGE:`)
|
|
171
|
+
- Testing requirements (run `npm test`, `npm run type-check`, `npm run build`)
|
|
665
172
|
|
|
666
|
-
|
|
173
|
+
**Automated releases**: Semantic versioning via conventional commits - `feat:` → minor, `fix:` → patch, `BREAKING CHANGE:` → major.
|
|
667
174
|
|
|
668
|
-
|
|
669
|
-
npm test -- --run
|
|
670
|
-
```
|
|
671
|
-
|
|
672
|
-
2. **Type check**: Verify no TypeScript errors
|
|
673
|
-
|
|
674
|
-
```bash
|
|
675
|
-
npm run type-check
|
|
676
|
-
```
|
|
677
|
-
|
|
678
|
-
3. **Build**: Confirm the project builds successfully
|
|
679
|
-
|
|
680
|
-
```bash
|
|
681
|
-
npm run build
|
|
682
|
-
```
|
|
683
|
-
|
|
684
|
-
4. **Commit**: Use conventional commit format
|
|
685
|
-
```bash
|
|
686
|
-
git commit -m "feat: add new feature"
|
|
687
|
-
git commit -m "fix: resolve bug"
|
|
688
|
-
```
|
|
689
|
-
|
|
690
|
-
All pull requests will automatically run through CI checks that validate:
|
|
691
|
-
|
|
692
|
-
- TypeScript compilation
|
|
693
|
-
- Type checking
|
|
694
|
-
- Test suite (376 tests, 98.27% coverage)
|
|
695
|
-
- Compatibility with Node.js 20 and 22
|
|
696
|
-
- Conventional commit format
|
|
697
|
-
|
|
698
|
-
### Automated Releases
|
|
699
|
-
|
|
700
|
-
This project uses semantic-release for automated versioning and releases based on conventional commits. Version numbers follow Semantic Versioning based on your commit types:
|
|
701
|
-
|
|
702
|
-
- `feat:` commits trigger minor version bumps (1.x.0)
|
|
703
|
-
- `fix:` commits trigger patch version bumps (1.0.x)
|
|
704
|
-
- Commits with `BREAKING CHANGE:` trigger major version bumps (x.0.0)
|
|
705
|
-
|
|
706
|
-
### Note for Repository Owners
|
|
707
|
-
|
|
708
|
-
After forking or cloning, update the CI badge URL in README.md:
|
|
709
|
-
|
|
710
|
-
```markdown
|
|
711
|
-
[](https://github.com/mhalder/qdrant-mcp-server/actions/workflows/ci.yml)
|
|
712
|
-
```
|
|
175
|
+
## License
|
|
713
176
|
|
|
714
|
-
|
|
177
|
+
MIT - see [LICENSE](LICENSE) file.
|