@mhalder/qdrant-mcp-server 1.6.0 → 2.0.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.
@@ -2,28 +2,41 @@ import { QdrantClient } from "@qdrant/js-client-rest";
2
2
  import { beforeEach, describe, expect, it, vi } from "vitest";
3
3
  import { QdrantManager } from "./client.js";
4
4
 
5
+ const mockClient = {
6
+ createCollection: vi.fn().mockResolvedValue({}),
7
+ getCollection: vi.fn().mockResolvedValue({}),
8
+ getCollections: vi.fn().mockResolvedValue({ collections: [] }),
9
+ deleteCollection: vi.fn().mockResolvedValue({}),
10
+ upsert: vi.fn().mockResolvedValue({}),
11
+ search: vi.fn().mockResolvedValue([]),
12
+ retrieve: vi.fn().mockResolvedValue([]),
13
+ delete: vi.fn().mockResolvedValue({}),
14
+ query: vi.fn().mockResolvedValue({ points: [] }),
15
+ };
16
+
5
17
  vi.mock("@qdrant/js-client-rest", () => ({
6
- QdrantClient: vi.fn(),
18
+ QdrantClient: vi.fn().mockImplementation(function () {
19
+ return mockClient;
20
+ }),
7
21
  }));
8
22
 
9
23
  describe("QdrantManager", () => {
10
24
  let manager: QdrantManager;
11
- let mockClient: any;
12
25
 
13
26
  beforeEach(() => {
14
- mockClient = {
15
- createCollection: vi.fn(),
16
- getCollection: vi.fn(),
17
- getCollections: vi.fn(),
18
- deleteCollection: vi.fn(),
19
- upsert: vi.fn(),
20
- search: vi.fn(),
21
- retrieve: vi.fn(),
22
- delete: vi.fn(),
23
- };
24
-
25
- vi.mocked(QdrantClient).mockImplementation(() => mockClient as any);
26
-
27
+ // Reset mocks and restore default implementations
28
+ mockClient.createCollection.mockReset().mockResolvedValue({});
29
+ mockClient.getCollection.mockReset().mockResolvedValue({});
30
+ mockClient.getCollections
31
+ .mockReset()
32
+ .mockResolvedValue({ collections: [] });
33
+ mockClient.deleteCollection.mockReset().mockResolvedValue({});
34
+ mockClient.upsert.mockReset().mockResolvedValue({});
35
+ mockClient.search.mockReset().mockResolvedValue([]);
36
+ mockClient.retrieve.mockReset().mockResolvedValue([]);
37
+ mockClient.delete.mockReset().mockResolvedValue({});
38
+ mockClient.query.mockReset().mockResolvedValue({ points: [] });
39
+ vi.mocked(QdrantClient).mockClear();
27
40
  manager = new QdrantManager("http://localhost:6333");
28
41
  });
29
42
 
@@ -51,41 +64,50 @@ describe("QdrantManager", () => {
51
64
  it("should create a collection with default distance metric", async () => {
52
65
  await manager.createCollection("test-collection", 1536);
53
66
 
54
- expect(mockClient.createCollection).toHaveBeenCalledWith("test-collection", {
55
- vectors: {
56
- size: 1536,
57
- distance: "Cosine",
67
+ expect(mockClient.createCollection).toHaveBeenCalledWith(
68
+ "test-collection",
69
+ {
70
+ vectors: {
71
+ size: 1536,
72
+ distance: "Cosine",
73
+ },
58
74
  },
59
- });
75
+ );
60
76
  });
61
77
 
62
78
  it("should create a collection with custom distance metric", async () => {
63
79
  await manager.createCollection("test-collection", 1536, "Euclid");
64
80
 
65
- expect(mockClient.createCollection).toHaveBeenCalledWith("test-collection", {
66
- vectors: {
67
- size: 1536,
68
- distance: "Euclid",
81
+ expect(mockClient.createCollection).toHaveBeenCalledWith(
82
+ "test-collection",
83
+ {
84
+ vectors: {
85
+ size: 1536,
86
+ distance: "Euclid",
87
+ },
69
88
  },
70
- });
89
+ );
71
90
  });
72
91
 
73
92
  it("should create a hybrid collection with sparse vectors enabled", async () => {
74
93
  await manager.createCollection("test-collection", 1536, "Cosine", true);
75
94
 
76
- expect(mockClient.createCollection).toHaveBeenCalledWith("test-collection", {
77
- vectors: {
78
- dense: {
79
- size: 1536,
80
- distance: "Cosine",
95
+ expect(mockClient.createCollection).toHaveBeenCalledWith(
96
+ "test-collection",
97
+ {
98
+ vectors: {
99
+ dense: {
100
+ size: 1536,
101
+ distance: "Cosine",
102
+ },
81
103
  },
82
- },
83
- sparse_vectors: {
84
- text: {
85
- modifier: "idf",
104
+ sparse_vectors: {
105
+ text: {
106
+ modifier: "idf",
107
+ },
86
108
  },
87
109
  },
88
- });
110
+ );
89
111
  });
90
112
  });
91
113
 
@@ -111,12 +133,20 @@ describe("QdrantManager", () => {
111
133
  describe("listCollections", () => {
112
134
  it("should return list of collection names", async () => {
113
135
  mockClient.getCollections.mockResolvedValue({
114
- collections: [{ name: "collection1" }, { name: "collection2" }, { name: "collection3" }],
136
+ collections: [
137
+ { name: "collection1" },
138
+ { name: "collection2" },
139
+ { name: "collection3" },
140
+ ],
115
141
  });
116
142
 
117
143
  const collections = await manager.listCollections();
118
144
 
119
- expect(collections).toEqual(["collection1", "collection2", "collection3"]);
145
+ expect(collections).toEqual([
146
+ "collection1",
147
+ "collection2",
148
+ "collection3",
149
+ ]);
120
150
  });
121
151
 
122
152
  it("should return empty array when no collections exist", async () => {
@@ -211,7 +241,9 @@ describe("QdrantManager", () => {
211
241
  it("should delete a collection", async () => {
212
242
  await manager.deleteCollection("test-collection");
213
243
 
214
- expect(mockClient.deleteCollection).toHaveBeenCalledWith("test-collection");
244
+ expect(mockClient.deleteCollection).toHaveBeenCalledWith(
245
+ "test-collection",
246
+ );
215
247
  });
216
248
  });
217
249
 
@@ -260,7 +292,7 @@ describe("QdrantManager", () => {
260
292
  const normalizedId = calls[0][1].points[0].id;
261
293
  // Check that it's a valid UUID format
262
294
  expect(normalizedId).toMatch(
263
- /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i
295
+ /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,
264
296
  );
265
297
  // Ensure it's not the original ID
266
298
  expect(normalizedId).not.toBe("my-custom-id");
@@ -268,7 +300,9 @@ describe("QdrantManager", () => {
268
300
 
269
301
  it("should preserve UUID format IDs without modification", async () => {
270
302
  const uuidId = "123e4567-e89b-12d3-a456-426614174000";
271
- const points = [{ id: uuidId, vector: [0.1, 0.2, 0.3], payload: { text: "test" } }];
303
+ const points = [
304
+ { id: uuidId, vector: [0.1, 0.2, 0.3], payload: { text: "test" } },
305
+ ];
272
306
 
273
307
  await manager.addPoints("test-collection", points);
274
308
 
@@ -296,8 +330,10 @@ describe("QdrantManager", () => {
296
330
  },
297
331
  });
298
332
 
299
- await expect(manager.addPoints("test-collection", points)).rejects.toThrow(
300
- 'Failed to add points to collection "test-collection": Vector dimension mismatch'
333
+ await expect(
334
+ manager.addPoints("test-collection", points),
335
+ ).rejects.toThrow(
336
+ 'Failed to add points to collection "test-collection": Vector dimension mismatch',
301
337
  );
302
338
  });
303
339
 
@@ -306,8 +342,10 @@ describe("QdrantManager", () => {
306
342
 
307
343
  mockClient.upsert.mockRejectedValue(new Error("Network error"));
308
344
 
309
- await expect(manager.addPoints("test-collection", points)).rejects.toThrow(
310
- 'Failed to add points to collection "test-collection": Network error'
345
+ await expect(
346
+ manager.addPoints("test-collection", points),
347
+ ).rejects.toThrow(
348
+ 'Failed to add points to collection "test-collection": Network error',
311
349
  );
312
350
  });
313
351
 
@@ -316,8 +354,10 @@ describe("QdrantManager", () => {
316
354
 
317
355
  mockClient.upsert.mockRejectedValue("Unknown error");
318
356
 
319
- await expect(manager.addPoints("test-collection", points)).rejects.toThrow(
320
- 'Failed to add points to collection "test-collection": Unknown error'
357
+ await expect(
358
+ manager.addPoints("test-collection", points),
359
+ ).rejects.toThrow(
360
+ 'Failed to add points to collection "test-collection": Unknown error',
321
361
  );
322
362
  });
323
363
  });
@@ -345,7 +385,11 @@ describe("QdrantManager", () => {
345
385
  { id: 2, score: 0.85, payload: { text: "result2" } },
346
386
  ]);
347
387
 
348
- const results = await manager.search("test-collection", [0.1, 0.2, 0.3], 5);
388
+ const results = await manager.search(
389
+ "test-collection",
390
+ [0.1, 0.2, 0.3],
391
+ 5,
392
+ );
349
393
 
350
394
  expect(results).toEqual([
351
395
  { id: 1, score: 0.95, payload: { text: "result1" } },
@@ -444,7 +488,9 @@ describe("QdrantManager", () => {
444
488
  });
445
489
 
446
490
  it("should handle null payload in results", async () => {
447
- mockClient.search.mockResolvedValue([{ id: 1, score: 0.95, payload: null }]);
491
+ mockClient.search.mockResolvedValue([
492
+ { id: 1, score: 0.95, payload: null },
493
+ ]);
448
494
 
449
495
  const results = await manager.search("test-collection", [0.1, 0.2, 0.3]);
450
496
 
@@ -473,11 +519,19 @@ describe("QdrantManager", () => {
473
519
  },
474
520
  });
475
521
 
476
- mockClient.search.mockResolvedValue([{ id: 1, score: 0.95, payload: { text: "result1" } }]);
522
+ mockClient.search.mockResolvedValue([
523
+ { id: 1, score: 0.95, payload: { text: "result1" } },
524
+ ]);
477
525
 
478
- const results = await manager.search("hybrid-collection", [0.1, 0.2, 0.3], 5);
526
+ const results = await manager.search(
527
+ "hybrid-collection",
528
+ [0.1, 0.2, 0.3],
529
+ 5,
530
+ );
479
531
 
480
- expect(results).toEqual([{ id: 1, score: 0.95, payload: { text: "result1" } }]);
532
+ expect(results).toEqual([
533
+ { id: 1, score: 0.95, payload: { text: "result1" } },
534
+ ]);
481
535
  expect(mockClient.search).toHaveBeenCalledWith("hybrid-collection", {
482
536
  vector: { name: "dense", vector: [0.1, 0.2, 0.3] },
483
537
  limit: 5,
@@ -500,11 +554,19 @@ describe("QdrantManager", () => {
500
554
  },
501
555
  });
502
556
 
503
- mockClient.search.mockResolvedValue([{ id: 1, score: 0.95, payload: { text: "result1" } }]);
557
+ mockClient.search.mockResolvedValue([
558
+ { id: 1, score: 0.95, payload: { text: "result1" } },
559
+ ]);
504
560
 
505
- const results = await manager.search("standard-collection", [0.1, 0.2, 0.3], 5);
561
+ const results = await manager.search(
562
+ "standard-collection",
563
+ [0.1, 0.2, 0.3],
564
+ 5,
565
+ );
506
566
 
507
- expect(results).toEqual([{ id: 1, score: 0.95, payload: { text: "result1" } }]);
567
+ expect(results).toEqual([
568
+ { id: 1, score: 0.95, payload: { text: "result1" } },
569
+ ]);
508
570
  expect(mockClient.search).toHaveBeenCalledWith("standard-collection", {
509
571
  vector: [0.1, 0.2, 0.3],
510
572
  limit: 5,
@@ -515,7 +577,9 @@ describe("QdrantManager", () => {
515
577
 
516
578
  describe("getPoint", () => {
517
579
  it("should retrieve a point by id", async () => {
518
- mockClient.retrieve.mockResolvedValue([{ id: 1, payload: { text: "test" } }]);
580
+ mockClient.retrieve.mockResolvedValue([
581
+ { id: 1, payload: { text: "test" } },
582
+ ]);
519
583
 
520
584
  const point = await manager.getPoint("test-collection", 1);
521
585
 
@@ -586,7 +650,11 @@ describe("QdrantManager", () => {
586
650
  ],
587
651
  });
588
652
 
589
- const results = await manager.hybridSearch("test-collection", denseVector, sparseVector);
653
+ const results = await manager.hybridSearch(
654
+ "test-collection",
655
+ denseVector,
656
+ sparseVector,
657
+ );
590
658
 
591
659
  expect(results).toEqual([
592
660
  { id: 1, score: 0.95, payload: { text: "result1" } },
@@ -622,7 +690,12 @@ describe("QdrantManager", () => {
622
690
 
623
691
  mockClient.query.mockResolvedValue({ points: [] });
624
692
 
625
- await manager.hybridSearch("test-collection", denseVector, sparseVector, 10);
693
+ await manager.hybridSearch(
694
+ "test-collection",
695
+ denseVector,
696
+ sparseVector,
697
+ 10,
698
+ );
626
699
 
627
700
  expect(mockClient.query).toHaveBeenCalledWith(
628
701
  "test-collection",
@@ -631,7 +704,7 @@ describe("QdrantManager", () => {
631
704
  expect.objectContaining({ limit: 40 }), // 10 * 4
632
705
  ]),
633
706
  limit: 10,
634
- })
707
+ }),
635
708
  );
636
709
  });
637
710
 
@@ -642,7 +715,13 @@ describe("QdrantManager", () => {
642
715
 
643
716
  mockClient.query.mockResolvedValue({ points: [] });
644
717
 
645
- await manager.hybridSearch("test-collection", denseVector, sparseVector, 5, filter);
718
+ await manager.hybridSearch(
719
+ "test-collection",
720
+ denseVector,
721
+ sparseVector,
722
+ 5,
723
+ filter,
724
+ );
646
725
 
647
726
  expect(mockClient.query).toHaveBeenCalledWith("test-collection", {
648
727
  prefetch: [
@@ -684,7 +763,13 @@ describe("QdrantManager", () => {
684
763
 
685
764
  mockClient.query.mockResolvedValue({ points: [] });
686
765
 
687
- await manager.hybridSearch("test-collection", denseVector, sparseVector, 5, filter);
766
+ await manager.hybridSearch(
767
+ "test-collection",
768
+ denseVector,
769
+ sparseVector,
770
+ 5,
771
+ filter,
772
+ );
688
773
 
689
774
  const call = mockClient.query.mock.calls[0][1];
690
775
  expect(call.prefetch[0].filter).toEqual(filter);
@@ -694,11 +779,19 @@ describe("QdrantManager", () => {
694
779
  it("should handle Qdrant format filter (should)", async () => {
695
780
  const denseVector = [0.1, 0.2, 0.3];
696
781
  const sparseVector = { indices: [1], values: [0.5] };
697
- const filter = { should: [{ key: "tag", match: { value: "important" } }] };
782
+ const filter = {
783
+ should: [{ key: "tag", match: { value: "important" } }],
784
+ };
698
785
 
699
786
  mockClient.query.mockResolvedValue({ points: [] });
700
787
 
701
- await manager.hybridSearch("test-collection", denseVector, sparseVector, 5, filter);
788
+ await manager.hybridSearch(
789
+ "test-collection",
790
+ denseVector,
791
+ sparseVector,
792
+ 5,
793
+ filter,
794
+ );
702
795
 
703
796
  const call = mockClient.query.mock.calls[0][1];
704
797
  expect(call.prefetch[0].filter).toEqual(filter);
@@ -708,11 +801,19 @@ describe("QdrantManager", () => {
708
801
  it("should handle Qdrant format filter (must_not)", async () => {
709
802
  const denseVector = [0.1, 0.2, 0.3];
710
803
  const sparseVector = { indices: [1], values: [0.5] };
711
- const filter = { must_not: [{ key: "status", match: { value: "deleted" } }] };
804
+ const filter = {
805
+ must_not: [{ key: "status", match: { value: "deleted" } }],
806
+ };
712
807
 
713
808
  mockClient.query.mockResolvedValue({ points: [] });
714
809
 
715
- await manager.hybridSearch("test-collection", denseVector, sparseVector, 5, filter);
810
+ await manager.hybridSearch(
811
+ "test-collection",
812
+ denseVector,
813
+ sparseVector,
814
+ 5,
815
+ filter,
816
+ );
716
817
 
717
818
  const call = mockClient.query.mock.calls[0][1];
718
819
  expect(call.prefetch[0].filter).toEqual(filter);
@@ -725,7 +826,13 @@ describe("QdrantManager", () => {
725
826
 
726
827
  mockClient.query.mockResolvedValue({ points: [] });
727
828
 
728
- await manager.hybridSearch("test-collection", denseVector, sparseVector, 5, {});
829
+ await manager.hybridSearch(
830
+ "test-collection",
831
+ denseVector,
832
+ sparseVector,
833
+ 5,
834
+ {},
835
+ );
729
836
 
730
837
  const call = mockClient.query.mock.calls[0][1];
731
838
  expect(call.prefetch[0].filter).toBeUndefined();
@@ -740,7 +847,11 @@ describe("QdrantManager", () => {
740
847
  points: [{ id: 1, score: 0.95, payload: null }],
741
848
  });
742
849
 
743
- const results = await manager.hybridSearch("test-collection", denseVector, sparseVector);
850
+ const results = await manager.hybridSearch(
851
+ "test-collection",
852
+ denseVector,
853
+ sparseVector,
854
+ );
744
855
 
745
856
  expect(results).toEqual([{ id: 1, score: 0.95, payload: undefined }]);
746
857
  });
@@ -758,9 +869,9 @@ describe("QdrantManager", () => {
758
869
  });
759
870
 
760
871
  await expect(
761
- manager.hybridSearch("test-collection", denseVector, sparseVector)
872
+ manager.hybridSearch("test-collection", denseVector, sparseVector),
762
873
  ).rejects.toThrow(
763
- 'Hybrid search failed on collection "test-collection": Named vector not found'
874
+ 'Hybrid search failed on collection "test-collection": Named vector not found',
764
875
  );
765
876
  });
766
877
 
@@ -771,8 +882,10 @@ describe("QdrantManager", () => {
771
882
  mockClient.query.mockRejectedValue(new Error("Network timeout"));
772
883
 
773
884
  await expect(
774
- manager.hybridSearch("test-collection", denseVector, sparseVector)
775
- ).rejects.toThrow('Hybrid search failed on collection "test-collection": Network timeout');
885
+ manager.hybridSearch("test-collection", denseVector, sparseVector),
886
+ ).rejects.toThrow(
887
+ 'Hybrid search failed on collection "test-collection": Network timeout',
888
+ );
776
889
  });
777
890
 
778
891
  it("should throw error with String(error) fallback", async () => {
@@ -782,8 +895,10 @@ describe("QdrantManager", () => {
782
895
  mockClient.query.mockRejectedValue("Unknown error");
783
896
 
784
897
  await expect(
785
- manager.hybridSearch("test-collection", denseVector, sparseVector)
786
- ).rejects.toThrow('Hybrid search failed on collection "test-collection": Unknown error');
898
+ manager.hybridSearch("test-collection", denseVector, sparseVector),
899
+ ).rejects.toThrow(
900
+ 'Hybrid search failed on collection "test-collection": Unknown error',
901
+ );
787
902
  });
788
903
  });
789
904
 
@@ -874,7 +989,7 @@ describe("QdrantManager", () => {
874
989
  const normalizedId = calls[0][1].points[0].id;
875
990
  // Check that it's a valid UUID format
876
991
  expect(normalizedId).toMatch(
877
- /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i
992
+ /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,
878
993
  );
879
994
  expect(normalizedId).not.toBe("my-doc-id");
880
995
  });
@@ -924,8 +1039,10 @@ describe("QdrantManager", () => {
924
1039
  },
925
1040
  });
926
1041
 
927
- await expect(manager.addPointsWithSparse("test-collection", points)).rejects.toThrow(
928
- 'Failed to add points with sparse vectors to collection "test-collection": Sparse vector not configured'
1042
+ await expect(
1043
+ manager.addPointsWithSparse("test-collection", points),
1044
+ ).rejects.toThrow(
1045
+ 'Failed to add points with sparse vectors to collection "test-collection": Sparse vector not configured',
929
1046
  );
930
1047
  });
931
1048
 
@@ -940,8 +1057,10 @@ describe("QdrantManager", () => {
940
1057
 
941
1058
  mockClient.upsert.mockRejectedValue(new Error("Connection refused"));
942
1059
 
943
- await expect(manager.addPointsWithSparse("test-collection", points)).rejects.toThrow(
944
- 'Failed to add points with sparse vectors to collection "test-collection": Connection refused'
1060
+ await expect(
1061
+ manager.addPointsWithSparse("test-collection", points),
1062
+ ).rejects.toThrow(
1063
+ 'Failed to add points with sparse vectors to collection "test-collection": Connection refused',
945
1064
  );
946
1065
  });
947
1066
 
@@ -956,8 +1075,10 @@ describe("QdrantManager", () => {
956
1075
 
957
1076
  mockClient.upsert.mockRejectedValue("Unexpected error");
958
1077
 
959
- await expect(manager.addPointsWithSparse("test-collection", points)).rejects.toThrow(
960
- 'Failed to add points with sparse vectors to collection "test-collection": Unexpected error'
1078
+ await expect(
1079
+ manager.addPointsWithSparse("test-collection", points),
1080
+ ).rejects.toThrow(
1081
+ 'Failed to add points with sparse vectors to collection "test-collection": Unexpected error',
961
1082
  );
962
1083
  });
963
1084
  });
@@ -37,7 +37,8 @@ export class QdrantManager {
37
37
  }
38
38
 
39
39
  // Check if already a valid UUID (8-4-4-4-12 format)
40
- const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
40
+ const uuidRegex =
41
+ /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
41
42
  if (uuidRegex.test(id)) {
42
43
  return id;
43
44
  }
@@ -51,7 +52,7 @@ export class QdrantManager {
51
52
  name: string,
52
53
  vectorSize: number,
53
54
  distance: "Cosine" | "Euclid" | "Dot" = "Cosine",
54
- enableSparse: boolean = false
55
+ enableSparse: boolean = false,
55
56
  ): Promise<void> {
56
57
  const config: any = {};
57
58
 
@@ -139,7 +140,7 @@ export class QdrantManager {
139
140
  id: string | number;
140
141
  vector: number[];
141
142
  payload?: Record<string, any>;
142
- }>
143
+ }>,
143
144
  ): Promise<void> {
144
145
  try {
145
146
  // Normalize all IDs to ensure string IDs are in UUID format
@@ -153,8 +154,11 @@ export class QdrantManager {
153
154
  points: normalizedPoints,
154
155
  });
155
156
  } catch (error: any) {
156
- const errorMessage = error?.data?.status?.error || error?.message || String(error);
157
- throw new Error(`Failed to add points to collection "${collectionName}": ${errorMessage}`);
157
+ const errorMessage =
158
+ error?.data?.status?.error || error?.message || String(error);
159
+ throw new Error(
160
+ `Failed to add points to collection "${collectionName}": ${errorMessage}`,
161
+ );
158
162
  }
159
163
  }
160
164
 
@@ -162,7 +166,7 @@ export class QdrantManager {
162
166
  collectionName: string,
163
167
  vector: number[],
164
168
  limit: number = 5,
165
- filter?: Record<string, any>
169
+ filter?: Record<string, any>,
166
170
  ): Promise<SearchResult[]> {
167
171
  // Convert simple key-value filter to Qdrant filter format
168
172
  // Accepts either:
@@ -202,7 +206,7 @@ export class QdrantManager {
202
206
 
203
207
  async getPoint(
204
208
  collectionName: string,
205
- id: string | number
209
+ id: string | number,
206
210
  ): Promise<{ id: string | number; payload?: Record<string, any> } | null> {
207
211
  try {
208
212
  const normalizedId = this.normalizeId(id);
@@ -223,7 +227,10 @@ export class QdrantManager {
223
227
  }
224
228
  }
225
229
 
226
- async deletePoints(collectionName: string, ids: (string | number)[]): Promise<void> {
230
+ async deletePoints(
231
+ collectionName: string,
232
+ ids: (string | number)[],
233
+ ): Promise<void> {
227
234
  // Normalize IDs to ensure string IDs are in UUID format
228
235
  const normalizedIds = ids.map((id) => this.normalizeId(id));
229
236
 
@@ -243,7 +250,7 @@ export class QdrantManager {
243
250
  sparseVector: SparseVector,
244
251
  limit: number = 5,
245
252
  filter?: Record<string, any>,
246
- _semanticWeight: number = 0.7
253
+ _semanticWeight: number = 0.7,
247
254
  ): Promise<SearchResult[]> {
248
255
  // Convert simple key-value filter to Qdrant filter format
249
256
  let qdrantFilter;
@@ -293,8 +300,11 @@ export class QdrantManager {
293
300
  payload: result.payload || undefined,
294
301
  }));
295
302
  } catch (error: any) {
296
- const errorMessage = error?.data?.status?.error || error?.message || String(error);
297
- throw new Error(`Hybrid search failed on collection "${collectionName}": ${errorMessage}`);
303
+ const errorMessage =
304
+ error?.data?.status?.error || error?.message || String(error);
305
+ throw new Error(
306
+ `Hybrid search failed on collection "${collectionName}": ${errorMessage}`,
307
+ );
298
308
  }
299
309
  }
300
310
 
@@ -308,7 +318,7 @@ export class QdrantManager {
308
318
  vector: number[];
309
319
  sparseVector: SparseVector;
310
320
  payload?: Record<string, any>;
311
- }>
321
+ }>,
312
322
  ): Promise<void> {
313
323
  try {
314
324
  // Normalize all IDs to ensure string IDs are in UUID format
@@ -326,9 +336,10 @@ export class QdrantManager {
326
336
  points: normalizedPoints,
327
337
  });
328
338
  } catch (error: any) {
329
- const errorMessage = error?.data?.status?.error || error?.message || String(error);
339
+ const errorMessage =
340
+ error?.data?.status?.error || error?.message || String(error);
330
341
  throw new Error(
331
- `Failed to add points with sparse vectors to collection "${collectionName}": ${errorMessage}`
342
+ `Failed to add points with sparse vectors to collection "${collectionName}": ${errorMessage}`,
332
343
  );
333
344
  }
334
345
  }
package/tsconfig.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "compilerOptions": {
3
- "target": "ES2022",
4
- "module": "Node16",
5
- "moduleResolution": "Node16",
3
+ "target": "ES2023",
4
+ "module": "NodeNext",
5
+ "moduleResolution": "NodeNext",
6
6
  "outDir": "./build",
7
7
  "rootDir": "./src",
8
8
  "strict": true,
@@ -12,7 +12,8 @@
12
12
  "resolveJsonModule": true,
13
13
  "declaration": true,
14
14
  "declarationMap": true,
15
- "sourceMap": true
15
+ "sourceMap": true,
16
+ "noImplicitOverride": true
16
17
  },
17
18
  "include": ["src/**/*"],
18
19
  "exclude": ["node_modules", "build"]
package/vitest.config.ts CHANGED
@@ -4,6 +4,7 @@ export default defineConfig({
4
4
  test: {
5
5
  globals: true,
6
6
  environment: "node",
7
+ exclude: ["**/node_modules/**", "**/build/**", "**/dist/**"],
7
8
  coverage: {
8
9
  provider: "v8",
9
10
  reporter: ["text", "json", "html"],
@@ -1,22 +0,0 @@
1
- # No version field needed for Docker Compose v1.27.0+
2
- services:
3
- qdrant:
4
- image: qdrant/qdrant:latest
5
- container_name: qdrant-mcp
6
- ports:
7
- - "6333:6333"
8
- - "6334:6334"
9
- volumes:
10
- - ./qdrant_storage:/qdrant/storage
11
- environment:
12
- - QDRANT__SERVICE__GRPC_PORT=6334
13
- restart: unless-stopped
14
-
15
- ollama:
16
- image: ollama/ollama:latest
17
- container_name: ollama
18
- ports:
19
- - "11434:11434"
20
- volumes:
21
- - ./ollama_storage:/root/.ollama
22
- restart: unless-stopped