@mhalder/qdrant-mcp-server 1.1.0 → 1.2.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/CHANGELOG.md +87 -69
- package/CONTRIBUTING.md +81 -92
- package/README.md +99 -634
- package/biome.json +34 -0
- package/build/embeddings/sparse.d.ts +40 -0
- package/build/embeddings/sparse.d.ts.map +1 -0
- package/build/embeddings/sparse.js +105 -0
- package/build/embeddings/sparse.js.map +1 -0
- package/build/embeddings/sparse.test.d.ts +2 -0
- package/build/embeddings/sparse.test.d.ts.map +1 -0
- package/build/embeddings/sparse.test.js +69 -0
- package/build/embeddings/sparse.test.js.map +1 -0
- package/build/index.js +130 -30
- package/build/index.js.map +1 -1
- package/build/qdrant/client.d.ts +21 -2
- package/build/qdrant/client.d.ts.map +1 -1
- package/build/qdrant/client.js +131 -17
- package/build/qdrant/client.js.map +1 -1
- package/build/qdrant/client.test.js +429 -21
- package/build/qdrant/client.test.js.map +1 -1
- package/examples/README.md +78 -253
- package/examples/basic/README.md +19 -72
- package/examples/filters/README.md +55 -155
- package/examples/hybrid-search/README.md +199 -0
- package/examples/knowledge-base/README.md +36 -98
- package/examples/rate-limiting/README.md +81 -290
- package/package.json +1 -1
- package/src/embeddings/sparse.test.ts +87 -0
- package/src/embeddings/sparse.ts +127 -0
- package/src/index.ts +161 -57
- package/src/qdrant/client.test.ts +544 -56
- package/src/qdrant/client.ts +162 -22
- package/vitest.config.ts +3 -3
- package/docs/test_report.md +0 -259
package/README.md
CHANGED
|
@@ -3,97 +3,51 @@
|
|
|
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
|
-
- **
|
|
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
|
+
- **Hybrid Search**: Combine semantic and keyword search for better results
|
|
14
|
+
- **Semantic Search**: Natural language search with metadata filtering
|
|
15
|
+
- **Rate Limiting**: Intelligent throttling with exponential backoff
|
|
16
|
+
- **Full CRUD**: Create, search, and manage collections and documents
|
|
27
17
|
|
|
28
|
-
|
|
18
|
+
## Quick Start
|
|
29
19
|
|
|
30
|
-
|
|
31
|
-
- Cohere API key
|
|
32
|
-
- Voyage AI API key
|
|
20
|
+
### Prerequisites
|
|
33
21
|
|
|
34
|
-
|
|
22
|
+
- Node.js 20+
|
|
23
|
+
- Docker and Docker Compose
|
|
35
24
|
|
|
36
|
-
|
|
25
|
+
### Installation
|
|
37
26
|
|
|
38
27
|
```bash
|
|
39
|
-
|
|
28
|
+
# Clone and install
|
|
29
|
+
git clone https://github.com/mhalder/qdrant-mcp-server.git
|
|
40
30
|
cd qdrant-mcp-server
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
2. Install dependencies:
|
|
44
|
-
|
|
45
|
-
```bash
|
|
46
31
|
npm install
|
|
47
|
-
```
|
|
48
32
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
```bash
|
|
33
|
+
# Start services and pull model
|
|
52
34
|
docker compose up -d
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
4. Pull the Ollama embedding model:
|
|
56
|
-
|
|
57
|
-
```bash
|
|
58
35
|
docker exec ollama ollama pull nomic-embed-text
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
5. Build the project:
|
|
62
36
|
|
|
63
|
-
|
|
37
|
+
# Build
|
|
64
38
|
npm run build
|
|
65
39
|
```
|
|
66
40
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
### Running the Server
|
|
41
|
+
### Configuration
|
|
70
42
|
|
|
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):**
|
|
43
|
+
Add to `~/.claude/claude_code_config.json`:
|
|
88
44
|
|
|
89
45
|
```json
|
|
90
46
|
{
|
|
91
47
|
"mcpServers": {
|
|
92
48
|
"qdrant": {
|
|
93
49
|
"command": "node",
|
|
94
|
-
"args": [
|
|
95
|
-
"/home/YOUR_USERNAME/projects/active/qdrant-mcp-server/build/index.js"
|
|
96
|
-
],
|
|
50
|
+
"args": ["/path/to/qdrant-mcp-server/build/index.js"],
|
|
97
51
|
"env": {
|
|
98
52
|
"QDRANT_URL": "http://localhost:6333",
|
|
99
53
|
"EMBEDDING_BASE_URL": "http://localhost:11434"
|
|
@@ -103,612 +57,123 @@ Add this to your Claude Code configuration file at `~/.claude/claude_code_config
|
|
|
103
57
|
}
|
|
104
58
|
```
|
|
105
59
|
|
|
106
|
-
**
|
|
60
|
+
**Using a different provider:**
|
|
107
61
|
|
|
108
62
|
```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
|
-
}
|
|
63
|
+
"env": {
|
|
64
|
+
"EMBEDDING_PROVIDER": "openai", // or "cohere", "voyage"
|
|
65
|
+
"OPENAI_API_KEY": "sk-...", // provider-specific API key
|
|
66
|
+
"QDRANT_URL": "http://localhost:6333"
|
|
163
67
|
}
|
|
164
68
|
```
|
|
165
69
|
|
|
166
|
-
|
|
70
|
+
Restart after making changes.
|
|
167
71
|
|
|
168
|
-
|
|
72
|
+
See [Advanced Configuration](#advanced-configuration) section below for all options.
|
|
169
73
|
|
|
170
|
-
##
|
|
74
|
+
## Tools
|
|
171
75
|
|
|
172
|
-
###
|
|
76
|
+
### Collection Management
|
|
173
77
|
|
|
174
|
-
|
|
78
|
+
| Tool | Description |
|
|
79
|
+
| --------------------- | -------------------------------------------------------------------- |
|
|
80
|
+
| `create_collection` | Create collection with specified distance metric (Cosine/Euclid/Dot) |
|
|
81
|
+
| `list_collections` | List all collections |
|
|
82
|
+
| `get_collection_info` | Get collection details and statistics |
|
|
83
|
+
| `delete_collection` | Delete collection and all documents |
|
|
175
84
|
|
|
176
|
-
|
|
85
|
+
### Document Operations
|
|
177
86
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
Create a collection named "my-docs"
|
|
185
|
-
```
|
|
87
|
+
| Tool | Description |
|
|
88
|
+
| ------------------ | ----------------------------------------------------------------------------- |
|
|
89
|
+
| `add_documents` | Add documents with automatic embedding (supports string/number IDs, metadata) |
|
|
90
|
+
| `semantic_search` | Natural language search with optional metadata filtering |
|
|
91
|
+
| `hybrid_search` | Hybrid search combining semantic and keyword (BM25) search with RRF |
|
|
92
|
+
| `delete_documents` | Delete specific documents by ID |
|
|
186
93
|
|
|
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
|
|
94
|
+
### Resources
|
|
299
95
|
|
|
300
96
|
- `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:**
|
|
97
|
+
- `qdrant://collection/{name}` - Collection details
|
|
334
98
|
|
|
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
|
-
```
|
|
99
|
+
## Examples
|
|
341
100
|
|
|
342
|
-
|
|
101
|
+
See [examples/](examples/) directory for detailed guides:
|
|
343
102
|
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
103
|
+
- **[Basic Usage](examples/basic/)** - Create collections, add documents, search
|
|
104
|
+
- **[Knowledge Base](examples/knowledge-base/)** - Structured documentation with metadata
|
|
105
|
+
- **[Advanced Filtering](examples/filters/)** - Complex boolean filters
|
|
106
|
+
- **[Rate Limiting](examples/rate-limiting/)** - Batch processing with cloud providers
|
|
347
107
|
|
|
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
|
|
108
|
+
## Advanced Configuration
|
|
366
109
|
|
|
367
110
|
### Environment Variables
|
|
368
111
|
|
|
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.
|
|
112
|
+
| Variable | Description | Default |
|
|
113
|
+
| ----------------------------------- | -------------------------------------- | --------------------- |
|
|
114
|
+
| `EMBEDDING_PROVIDER` | "ollama", "openai", "cohere", "voyage" | ollama |
|
|
115
|
+
| `QDRANT_URL` | Qdrant server URL | http://localhost:6333 |
|
|
116
|
+
| `EMBEDDING_MODEL` | Model name | Provider-specific |
|
|
117
|
+
| `EMBEDDING_BASE_URL` | Custom API URL | Provider-specific |
|
|
118
|
+
| `EMBEDDING_MAX_REQUESTS_PER_MINUTE` | Rate limit | Provider-specific |
|
|
119
|
+
| `EMBEDDING_RETRY_ATTEMPTS` | Retry count | 3 |
|
|
120
|
+
| `EMBEDDING_RETRY_DELAY` | Initial retry delay (ms) | 1000 |
|
|
121
|
+
| `OPENAI_API_KEY` | OpenAI API key | - |
|
|
122
|
+
| `COHERE_API_KEY` | Cohere API key | - |
|
|
123
|
+
| `VOYAGE_API_KEY` | Voyage AI API key | - |
|
|
124
|
+
|
|
125
|
+
### Provider Comparison
|
|
126
|
+
|
|
127
|
+
| Provider | Models | Dimensions | Rate Limit | Notes |
|
|
128
|
+
| ---------- | --------------------------------------------------------------- | -------------- | ---------- | -------------------- |
|
|
129
|
+
| **Ollama** | `nomic-embed-text` (default), `mxbai-embed-large`, `all-minilm` | 768, 1024, 384 | None | Local, no API key |
|
|
130
|
+
| **OpenAI** | `text-embedding-3-small` (default), `text-embedding-3-large` | 1536, 3072 | 3500/min | Cloud API |
|
|
131
|
+
| **Cohere** | `embed-english-v3.0` (default), `embed-multilingual-v3.0` | 1024 | 100/min | Multilingual support |
|
|
132
|
+
| **Voyage** | `voyage-2` (default), `voyage-large-2`, `voyage-code-2` | 1024, 1536 | 300/min | Code-specialized |
|
|
133
|
+
|
|
134
|
+
**Note:** Ollama models require `docker exec ollama ollama pull <model-name>` before use.
|
|
476
135
|
|
|
477
136
|
## Troubleshooting
|
|
478
137
|
|
|
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
|
|
138
|
+
| Issue | Solution |
|
|
139
|
+
| ---------------------- | ---------------------------------------------------------------------------- |
|
|
140
|
+
| **Qdrant not running** | `docker compose up -d` |
|
|
141
|
+
| **Collection missing** | Create collection first before adding documents |
|
|
142
|
+
| **Ollama not running** | Verify with `curl http://localhost:11434`, start with `docker compose up -d` |
|
|
143
|
+
| **Model missing** | `docker exec ollama ollama pull nomic-embed-text` |
|
|
144
|
+
| **Rate limit errors** | Adjust `EMBEDDING_MAX_REQUESTS_PER_MINUTE` to match your provider tier |
|
|
145
|
+
| **API key errors** | Verify correct API key in environment configuration |
|
|
146
|
+
| **Filter errors** | Ensure Qdrant filter format, check field names match metadata |
|
|
546
147
|
|
|
547
148
|
## Development
|
|
548
149
|
|
|
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
150
|
```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
|
|
151
|
+
npm run dev # Development with auto-reload
|
|
152
|
+
npm run build # Production build
|
|
153
|
+
npm run type-check # TypeScript validation
|
|
154
|
+
npm test # Run test suite
|
|
155
|
+
npm run test:coverage # Coverage report
|
|
605
156
|
```
|
|
606
157
|
|
|
607
|
-
###
|
|
158
|
+
### Testing
|
|
608
159
|
|
|
609
|
-
|
|
160
|
+
**422 tests** (376 unit + 46 functional) with **98%+ coverage**:
|
|
610
161
|
|
|
611
|
-
**Unit Tests
|
|
162
|
+
- **Unit Tests**: QdrantManager (21), Ollama (31), OpenAI (25), Cohere (29), Voyage (31), Factory (32), MCP Server (19)
|
|
163
|
+
- **Functional Tests**: Live API integration, end-to-end workflows (46)
|
|
612
164
|
|
|
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.
|
|
165
|
+
**CI/CD**: GitHub Actions runs build, type-check, and tests on Node.js 20 & 22 for every push/PR.
|
|
653
166
|
|
|
654
167
|
## Contributing
|
|
655
168
|
|
|
656
|
-
Contributions
|
|
169
|
+
Contributions welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for:
|
|
657
170
|
|
|
658
|
-
- Code of conduct
|
|
659
171
|
- Development workflow
|
|
660
|
-
-
|
|
661
|
-
-
|
|
662
|
-
- Testing requirements
|
|
663
|
-
|
|
664
|
-
### Quick Start for Contributors
|
|
172
|
+
- Conventional commit format (`feat:`, `fix:`, `BREAKING CHANGE:`)
|
|
173
|
+
- Testing requirements (run `npm test`, `npm run type-check`, `npm run build`)
|
|
665
174
|
|
|
666
|
-
|
|
175
|
+
**Automated releases**: Semantic versioning via conventional commits - `feat:` → minor, `fix:` → patch, `BREAKING CHANGE:` → major.
|
|
667
176
|
|
|
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
|
-
```
|
|
177
|
+
## License
|
|
713
178
|
|
|
714
|
-
|
|
179
|
+
MIT - see [LICENSE](LICENSE) file.
|