@mhalder/qdrant-mcp-server 1.2.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/README.md +34 -0
- package/build/index.js +203 -2
- package/build/index.js.map +1 -1
- package/build/transport.test.d.ts +2 -0
- package/build/transport.test.d.ts.map +1 -0
- package/build/transport.test.js +168 -0
- package/build/transport.test.js.map +1 -0
- package/examples/hybrid-search/README.md +37 -0
- package/package.json +3 -1
- package/src/index.ts +232 -2
- package/src/transport.test.ts +202 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,16 @@
|
|
|
1
|
+
## 1.3.0 (2025-10-11)
|
|
2
|
+
|
|
3
|
+
* Merge pull request #25 from mhalder/feature/http-transport ([efc90c3](https://github.com/mhalder/qdrant-mcp-server/commit/efc90c3)), closes [#25](https://github.com/mhalder/qdrant-mcp-server/issues/25)
|
|
4
|
+
* fix: address PR feedback for HTTP transport implementation ([1aec6d5](https://github.com/mhalder/qdrant-mcp-server/commit/1aec6d5))
|
|
5
|
+
* fix: address PR feedback for HTTP transport implementation ([3243d0e](https://github.com/mhalder/qdrant-mcp-server/commit/3243d0e))
|
|
6
|
+
* fix: clear cleanup interval on shutdown and improve error messages ([6aa29f3](https://github.com/mhalder/qdrant-mcp-server/commit/6aa29f3))
|
|
7
|
+
* fix: implement per-IP rate limiting and consolidate port validation ([c3bfc92](https://github.com/mhalder/qdrant-mcp-server/commit/c3bfc92))
|
|
8
|
+
* fix: prevent transport double closure and add rate limiter memory management ([2f92d78](https://github.com/mhalder/qdrant-mcp-server/commit/2f92d78))
|
|
9
|
+
* fix: resolve critical issues in HTTP transport implementation ([7951f2b](https://github.com/mhalder/qdrant-mcp-server/commit/7951f2b))
|
|
10
|
+
* fix: resolve race condition and resource leak in HTTP timeout handler ([6635ccb](https://github.com/mhalder/qdrant-mcp-server/commit/6635ccb))
|
|
11
|
+
* docs: add Try It and Cleanup sections to hybrid-search example ([5e32f16](https://github.com/mhalder/qdrant-mcp-server/commit/5e32f16))
|
|
12
|
+
* feat: add HTTP transport support for remote MCP server deployment ([983a9d6](https://github.com/mhalder/qdrant-mcp-server/commit/983a9d6)), closes [#24](https://github.com/mhalder/qdrant-mcp-server/issues/24)
|
|
13
|
+
|
|
1
14
|
## 1.2.0 (2025-10-11)
|
|
2
15
|
|
|
3
16
|
* Merge pull request #23 from mhalder/feature/hybrid-search ([5925df7](https://github.com/mhalder/qdrant-mcp-server/commit/5925df7)), closes [#23](https://github.com/mhalder/qdrant-mcp-server/issues/23)
|
package/README.md
CHANGED
|
@@ -14,6 +14,7 @@ A Model Context Protocol (MCP) server providing semantic search capabilities usi
|
|
|
14
14
|
- **Semantic Search**: Natural language search with metadata filtering
|
|
15
15
|
- **Rate Limiting**: Intelligent throttling with exponential backoff
|
|
16
16
|
- **Full CRUD**: Create, search, and manage collections and documents
|
|
17
|
+
- **Flexible Deployment**: Run locally (stdio) or as a remote HTTP server
|
|
17
18
|
|
|
18
19
|
## Quick Start
|
|
19
20
|
|
|
@@ -40,6 +41,8 @@ npm run build
|
|
|
40
41
|
|
|
41
42
|
### Configuration
|
|
42
43
|
|
|
44
|
+
#### Local Setup (stdio transport)
|
|
45
|
+
|
|
43
46
|
Add to `~/.claude/claude_code_config.json`:
|
|
44
47
|
|
|
45
48
|
```json
|
|
@@ -57,6 +60,35 @@ Add to `~/.claude/claude_code_config.json`:
|
|
|
57
60
|
}
|
|
58
61
|
```
|
|
59
62
|
|
|
63
|
+
#### Remote Setup (HTTP transport)
|
|
64
|
+
|
|
65
|
+
> **⚠️ Security Warning**: When deploying the HTTP transport in production:
|
|
66
|
+
>
|
|
67
|
+
> - **Always** run behind a reverse proxy (nginx, Caddy) with HTTPS
|
|
68
|
+
> - Implement authentication/authorization at the proxy level
|
|
69
|
+
> - Use firewalls to restrict access to trusted networks
|
|
70
|
+
> - Never expose directly to the public internet without protection
|
|
71
|
+
> - Consider implementing rate limiting at the proxy level
|
|
72
|
+
> - Monitor server logs for suspicious activity
|
|
73
|
+
|
|
74
|
+
**Start the server:**
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
TRANSPORT_MODE=http HTTP_PORT=3000 node build/index.js
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
**Configure client:**
|
|
81
|
+
|
|
82
|
+
```json
|
|
83
|
+
{
|
|
84
|
+
"mcpServers": {
|
|
85
|
+
"qdrant": {
|
|
86
|
+
"url": "http://your-server:3000/mcp"
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
60
92
|
**Using a different provider:**
|
|
61
93
|
|
|
62
94
|
```json
|
|
@@ -111,6 +143,8 @@ See [examples/](examples/) directory for detailed guides:
|
|
|
111
143
|
|
|
112
144
|
| Variable | Description | Default |
|
|
113
145
|
| ----------------------------------- | -------------------------------------- | --------------------- |
|
|
146
|
+
| `TRANSPORT_MODE` | "stdio" or "http" | stdio |
|
|
147
|
+
| `HTTP_PORT` | Port for HTTP transport | 3000 |
|
|
114
148
|
| `EMBEDDING_PROVIDER` | "ollama", "openai", "cohere", "voyage" | ollama |
|
|
115
149
|
| `QDRANT_URL` | Qdrant server URL | http://localhost:6333 |
|
|
116
150
|
| `EMBEDDING_MODEL` | Model name | Provider-specific |
|
package/build/index.js
CHANGED
|
@@ -4,7 +4,10 @@ import { dirname, join } from "node:path";
|
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
5
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
6
6
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
7
|
+
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
7
8
|
import { CallToolRequestSchema, ListResourcesRequestSchema, ListToolsRequestSchema, ReadResourceRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
9
|
+
import Bottleneck from "bottleneck";
|
|
10
|
+
import express from "express";
|
|
8
11
|
import { z } from "zod";
|
|
9
12
|
import { EmbeddingProviderFactory } from "./embeddings/factory.js";
|
|
10
13
|
import { BM25SparseVectorGenerator } from "./embeddings/sparse.js";
|
|
@@ -15,6 +18,15 @@ const pkg = JSON.parse(readFileSync(join(__dirname, "../package.json"), "utf-8")
|
|
|
15
18
|
// Validate environment variables
|
|
16
19
|
const QDRANT_URL = process.env.QDRANT_URL || "http://localhost:6333";
|
|
17
20
|
const EMBEDDING_PROVIDER = (process.env.EMBEDDING_PROVIDER || "ollama").toLowerCase();
|
|
21
|
+
const TRANSPORT_MODE = (process.env.TRANSPORT_MODE || "stdio").toLowerCase();
|
|
22
|
+
const HTTP_PORT = parseInt(process.env.HTTP_PORT || "3000", 10);
|
|
23
|
+
// Validate HTTP_PORT when HTTP mode is selected
|
|
24
|
+
if (TRANSPORT_MODE === "http") {
|
|
25
|
+
if (Number.isNaN(HTTP_PORT) || HTTP_PORT < 1 || HTTP_PORT > 65535) {
|
|
26
|
+
console.error(`Error: Invalid HTTP_PORT "${process.env.HTTP_PORT}". Must be a number between 1 and 65535.`);
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
18
30
|
// Check for required API keys based on provider
|
|
19
31
|
if (EMBEDDING_PROVIDER !== "ollama") {
|
|
20
32
|
let apiKey;
|
|
@@ -620,13 +632,202 @@ server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
|
620
632
|
],
|
|
621
633
|
};
|
|
622
634
|
});
|
|
623
|
-
// Start server
|
|
624
|
-
async function
|
|
635
|
+
// Start server with stdio transport
|
|
636
|
+
async function startStdioServer() {
|
|
625
637
|
await checkOllamaAvailability();
|
|
626
638
|
const transport = new StdioServerTransport();
|
|
627
639
|
await server.connect(transport);
|
|
628
640
|
console.error("Qdrant MCP server running on stdio");
|
|
629
641
|
}
|
|
642
|
+
// Start server with HTTP transport
|
|
643
|
+
async function startHttpServer() {
|
|
644
|
+
await checkOllamaAvailability();
|
|
645
|
+
const app = express();
|
|
646
|
+
app.use(express.json({ limit: "10mb" }));
|
|
647
|
+
// Configure Express to trust proxy for correct IP detection
|
|
648
|
+
app.set("trust proxy", true);
|
|
649
|
+
// Rate limiter group: max 100 requests per 15 minutes per IP, max 10 concurrent per IP
|
|
650
|
+
const rateLimiterGroup = new Bottleneck.Group({
|
|
651
|
+
reservoir: 100, // initial capacity per IP
|
|
652
|
+
reservoirRefreshAmount: 100, // refresh back to 100
|
|
653
|
+
reservoirRefreshInterval: 15 * 60 * 1000, // every 15 minutes
|
|
654
|
+
maxConcurrent: 10, // max concurrent requests per IP
|
|
655
|
+
});
|
|
656
|
+
// Periodic cleanup of inactive rate limiters to prevent memory leaks
|
|
657
|
+
// Track last access time for each IP
|
|
658
|
+
const ipLastAccess = new Map();
|
|
659
|
+
const INACTIVE_TIMEOUT = 60 * 60 * 1000; // 1 hour
|
|
660
|
+
const cleanupIntervalId = setInterval(() => {
|
|
661
|
+
const now = Date.now();
|
|
662
|
+
const keysToDelete = [];
|
|
663
|
+
ipLastAccess.forEach((lastAccess, ip) => {
|
|
664
|
+
if (now - lastAccess > INACTIVE_TIMEOUT) {
|
|
665
|
+
keysToDelete.push(ip);
|
|
666
|
+
}
|
|
667
|
+
});
|
|
668
|
+
keysToDelete.forEach((ip) => {
|
|
669
|
+
rateLimiterGroup.deleteKey(ip);
|
|
670
|
+
ipLastAccess.delete(ip);
|
|
671
|
+
});
|
|
672
|
+
if (keysToDelete.length > 0) {
|
|
673
|
+
console.error(`Cleaned up ${keysToDelete.length} inactive rate limiters`);
|
|
674
|
+
}
|
|
675
|
+
}, INACTIVE_TIMEOUT);
|
|
676
|
+
// Rate limiting middleware
|
|
677
|
+
const rateLimitMiddleware = async (req, res, next) => {
|
|
678
|
+
const clientIp = req.ip || req.socket.remoteAddress || "unknown";
|
|
679
|
+
try {
|
|
680
|
+
// Update last access time for this IP
|
|
681
|
+
ipLastAccess.set(clientIp, Date.now());
|
|
682
|
+
// Get or create a limiter for this specific IP
|
|
683
|
+
const limiter = rateLimiterGroup.key(clientIp);
|
|
684
|
+
await limiter.schedule(() => Promise.resolve());
|
|
685
|
+
next();
|
|
686
|
+
}
|
|
687
|
+
catch (error) {
|
|
688
|
+
// Differentiate between rate limit errors and unexpected errors
|
|
689
|
+
if (error instanceof Bottleneck.BottleneckError) {
|
|
690
|
+
// Rate limit exceeded or Bottleneck operational error
|
|
691
|
+
console.error(`Rate limit exceeded for IP ${clientIp}:`, error.message);
|
|
692
|
+
}
|
|
693
|
+
else {
|
|
694
|
+
// Unexpected error in rate limiting logic
|
|
695
|
+
console.error("Unexpected rate limiting error:", error);
|
|
696
|
+
}
|
|
697
|
+
res.status(429).json({
|
|
698
|
+
jsonrpc: "2.0",
|
|
699
|
+
error: {
|
|
700
|
+
code: -32000,
|
|
701
|
+
message: "Too many requests",
|
|
702
|
+
},
|
|
703
|
+
id: null,
|
|
704
|
+
});
|
|
705
|
+
}
|
|
706
|
+
};
|
|
707
|
+
// Health check endpoint
|
|
708
|
+
app.get("/health", (_req, res) => {
|
|
709
|
+
res.json({
|
|
710
|
+
status: "ok",
|
|
711
|
+
mode: TRANSPORT_MODE,
|
|
712
|
+
version: pkg.version,
|
|
713
|
+
embedding_provider: EMBEDDING_PROVIDER,
|
|
714
|
+
});
|
|
715
|
+
});
|
|
716
|
+
app.post("/mcp", rateLimitMiddleware, async (req, res) => {
|
|
717
|
+
const REQUEST_TIMEOUT = 60000; // 60 seconds
|
|
718
|
+
let timeoutId;
|
|
719
|
+
let isTimedOut = false;
|
|
720
|
+
let transportClosed = false;
|
|
721
|
+
// Create a new transport for each request in stateless mode.
|
|
722
|
+
// This prevents request ID collisions when different clients use the same JSON-RPC request IDs.
|
|
723
|
+
const transport = new StreamableHTTPServerTransport({
|
|
724
|
+
sessionIdGenerator: undefined, // Stateless mode
|
|
725
|
+
enableJsonResponse: true,
|
|
726
|
+
});
|
|
727
|
+
// Helper to safely close transport only once
|
|
728
|
+
const closeTransport = async () => {
|
|
729
|
+
if (!transportClosed) {
|
|
730
|
+
transportClosed = true;
|
|
731
|
+
await transport.close().catch((e) => console.error("Error closing transport:", e));
|
|
732
|
+
}
|
|
733
|
+
};
|
|
734
|
+
try {
|
|
735
|
+
// Set request timeout
|
|
736
|
+
timeoutId = setTimeout(async () => {
|
|
737
|
+
isTimedOut = true;
|
|
738
|
+
// Close transport on timeout to prevent resource leaks
|
|
739
|
+
await closeTransport();
|
|
740
|
+
if (!res.headersSent) {
|
|
741
|
+
res.status(408).json({
|
|
742
|
+
jsonrpc: "2.0",
|
|
743
|
+
error: {
|
|
744
|
+
code: -32000,
|
|
745
|
+
message: "Request timeout",
|
|
746
|
+
},
|
|
747
|
+
id: null,
|
|
748
|
+
});
|
|
749
|
+
}
|
|
750
|
+
}, REQUEST_TIMEOUT);
|
|
751
|
+
// Clean up transport when response closes
|
|
752
|
+
res.on("close", async () => {
|
|
753
|
+
await closeTransport();
|
|
754
|
+
if (timeoutId)
|
|
755
|
+
clearTimeout(timeoutId);
|
|
756
|
+
});
|
|
757
|
+
// Connect the transport to the shared server instance.
|
|
758
|
+
// In stateless mode, each request gets a new transport connection.
|
|
759
|
+
await server.connect(transport);
|
|
760
|
+
await transport.handleRequest(req, res, req.body);
|
|
761
|
+
// Clear timeout immediately on success to prevent race condition
|
|
762
|
+
if (timeoutId) {
|
|
763
|
+
clearTimeout(timeoutId);
|
|
764
|
+
timeoutId = undefined;
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
catch (error) {
|
|
768
|
+
console.error("Error handling MCP request:", error);
|
|
769
|
+
if (!res.headersSent && !isTimedOut) {
|
|
770
|
+
res.status(500).json({
|
|
771
|
+
jsonrpc: "2.0",
|
|
772
|
+
error: {
|
|
773
|
+
code: -32603,
|
|
774
|
+
message: "Internal server error",
|
|
775
|
+
},
|
|
776
|
+
id: null,
|
|
777
|
+
});
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
finally {
|
|
781
|
+
if (timeoutId)
|
|
782
|
+
clearTimeout(timeoutId);
|
|
783
|
+
// Ensure transport is closed even if an error occurs
|
|
784
|
+
await closeTransport();
|
|
785
|
+
}
|
|
786
|
+
});
|
|
787
|
+
const httpServer = app
|
|
788
|
+
.listen(HTTP_PORT, () => {
|
|
789
|
+
console.error(`Qdrant MCP server running on http://localhost:${HTTP_PORT}/mcp`);
|
|
790
|
+
})
|
|
791
|
+
.on("error", (error) => {
|
|
792
|
+
console.error("HTTP server error:", error);
|
|
793
|
+
process.exit(1);
|
|
794
|
+
});
|
|
795
|
+
// Graceful shutdown handling
|
|
796
|
+
let isShuttingDown = false;
|
|
797
|
+
const shutdown = () => {
|
|
798
|
+
if (isShuttingDown)
|
|
799
|
+
return;
|
|
800
|
+
isShuttingDown = true;
|
|
801
|
+
console.error("Shutdown signal received, closing HTTP server gracefully...");
|
|
802
|
+
// Clear the cleanup interval to allow graceful shutdown
|
|
803
|
+
clearInterval(cleanupIntervalId);
|
|
804
|
+
// Force shutdown after 10 seconds
|
|
805
|
+
const forceTimeout = setTimeout(() => {
|
|
806
|
+
console.error("Forcing shutdown after timeout");
|
|
807
|
+
process.exit(1);
|
|
808
|
+
}, 10000);
|
|
809
|
+
httpServer.close(() => {
|
|
810
|
+
clearTimeout(forceTimeout);
|
|
811
|
+
console.error("HTTP server closed");
|
|
812
|
+
process.exit(0);
|
|
813
|
+
});
|
|
814
|
+
};
|
|
815
|
+
process.on("SIGTERM", shutdown);
|
|
816
|
+
process.on("SIGINT", shutdown);
|
|
817
|
+
}
|
|
818
|
+
// Main entry point
|
|
819
|
+
async function main() {
|
|
820
|
+
if (TRANSPORT_MODE === "http") {
|
|
821
|
+
await startHttpServer();
|
|
822
|
+
}
|
|
823
|
+
else if (TRANSPORT_MODE === "stdio") {
|
|
824
|
+
await startStdioServer();
|
|
825
|
+
}
|
|
826
|
+
else {
|
|
827
|
+
console.error(`Error: Invalid TRANSPORT_MODE "${TRANSPORT_MODE}". Supported modes: stdio, http.`);
|
|
828
|
+
process.exit(1);
|
|
829
|
+
}
|
|
830
|
+
}
|
|
630
831
|
main().catch((error) => {
|
|
631
832
|
console.error("Fatal error:", error);
|
|
632
833
|
process.exit(1);
|
package/build/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transport.test.d.ts","sourceRoot":"","sources":["../src/transport.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
+
describe("Transport Configuration", () => {
|
|
3
|
+
let originalEnv;
|
|
4
|
+
beforeEach(() => {
|
|
5
|
+
originalEnv = { ...process.env };
|
|
6
|
+
});
|
|
7
|
+
afterEach(() => {
|
|
8
|
+
process.env = originalEnv;
|
|
9
|
+
});
|
|
10
|
+
describe("HTTP Port Validation", () => {
|
|
11
|
+
it("should accept valid port numbers", () => {
|
|
12
|
+
const validPorts = ["1", "80", "443", "3000", "8080", "65535"];
|
|
13
|
+
validPorts.forEach((port) => {
|
|
14
|
+
const parsed = parseInt(port, 10);
|
|
15
|
+
expect(parsed).toBeGreaterThanOrEqual(1);
|
|
16
|
+
expect(parsed).toBeLessThanOrEqual(65535);
|
|
17
|
+
expect(Number.isNaN(parsed)).toBe(false);
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
it("should reject invalid port numbers", () => {
|
|
21
|
+
const invalidCases = [
|
|
22
|
+
{ port: "0", reason: "port 0 is reserved" },
|
|
23
|
+
{ port: "-1", reason: "negative ports are invalid" },
|
|
24
|
+
{ port: "65536", reason: "exceeds maximum port" },
|
|
25
|
+
{ port: "99999", reason: "exceeds maximum port" },
|
|
26
|
+
{ port: "abc", reason: "non-numeric input" },
|
|
27
|
+
{ port: "", reason: "empty string" },
|
|
28
|
+
];
|
|
29
|
+
invalidCases.forEach(({ port, reason }) => {
|
|
30
|
+
const parsed = parseInt(port, 10);
|
|
31
|
+
const isValid = !Number.isNaN(parsed) && parsed >= 1 && parsed <= 65535;
|
|
32
|
+
expect(isValid, `Failed for ${port}: ${reason}`).toBe(false);
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
it("should use default port 3000 when HTTP_PORT is not set", () => {
|
|
36
|
+
const port = parseInt(process.env.HTTP_PORT || "3000", 10);
|
|
37
|
+
expect(port).toBe(3000);
|
|
38
|
+
});
|
|
39
|
+
it("should parse HTTP_PORT from environment", () => {
|
|
40
|
+
process.env.HTTP_PORT = "8080";
|
|
41
|
+
const port = parseInt(process.env.HTTP_PORT || "3000", 10);
|
|
42
|
+
expect(port).toBe(8080);
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
describe("Transport Mode Validation", () => {
|
|
46
|
+
it("should accept valid transport modes", () => {
|
|
47
|
+
const validModes = ["stdio", "http", "STDIO", "HTTP"];
|
|
48
|
+
validModes.forEach((mode) => {
|
|
49
|
+
const normalized = mode.toLowerCase();
|
|
50
|
+
expect(["stdio", "http"]).toContain(normalized);
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
it("should reject invalid transport modes", () => {
|
|
54
|
+
const invalidModes = ["tcp", "websocket", "grpc", ""];
|
|
55
|
+
invalidModes.forEach((mode) => {
|
|
56
|
+
const normalized = mode.toLowerCase();
|
|
57
|
+
expect(["stdio", "http"]).not.toContain(normalized);
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
it("should default to stdio when TRANSPORT_MODE is not set", () => {
|
|
61
|
+
const mode = (process.env.TRANSPORT_MODE || "stdio").toLowerCase();
|
|
62
|
+
expect(mode).toBe("stdio");
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
describe("Request Size Limits", () => {
|
|
66
|
+
it("should define request size limit for HTTP transport", () => {
|
|
67
|
+
const limit = "10mb";
|
|
68
|
+
expect(limit).toMatch(/^\d+mb$/);
|
|
69
|
+
});
|
|
70
|
+
it("should parse size limit correctly", () => {
|
|
71
|
+
const limit = "10mb";
|
|
72
|
+
const sizeInBytes = parseInt(limit, 10) * 1024 * 1024;
|
|
73
|
+
expect(sizeInBytes).toBe(10485760);
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
describe("HTTP Server Configuration", () => {
|
|
78
|
+
describe("Graceful Shutdown", () => {
|
|
79
|
+
it("should handle shutdown signals", async () => {
|
|
80
|
+
const mockServer = {
|
|
81
|
+
close: vi.fn((callback) => {
|
|
82
|
+
if (callback)
|
|
83
|
+
callback();
|
|
84
|
+
}),
|
|
85
|
+
};
|
|
86
|
+
const shutdown = () => {
|
|
87
|
+
mockServer.close(() => {
|
|
88
|
+
// Shutdown callback
|
|
89
|
+
});
|
|
90
|
+
};
|
|
91
|
+
shutdown();
|
|
92
|
+
expect(mockServer.close).toHaveBeenCalled();
|
|
93
|
+
});
|
|
94
|
+
it("should support timeout for forced shutdown", () => {
|
|
95
|
+
vi.useFakeTimers();
|
|
96
|
+
let forcedShutdown = false;
|
|
97
|
+
const timeout = setTimeout(() => {
|
|
98
|
+
forcedShutdown = true;
|
|
99
|
+
}, 10000);
|
|
100
|
+
vi.advanceTimersByTime(9999);
|
|
101
|
+
expect(forcedShutdown).toBe(false);
|
|
102
|
+
vi.advanceTimersByTime(1);
|
|
103
|
+
expect(forcedShutdown).toBe(true);
|
|
104
|
+
clearTimeout(timeout);
|
|
105
|
+
vi.useRealTimers();
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
describe("Error Handling", () => {
|
|
109
|
+
it("should return JSON-RPC 2.0 error format", () => {
|
|
110
|
+
const error = {
|
|
111
|
+
jsonrpc: "2.0",
|
|
112
|
+
error: {
|
|
113
|
+
code: -32603,
|
|
114
|
+
message: "Internal server error",
|
|
115
|
+
},
|
|
116
|
+
id: null,
|
|
117
|
+
};
|
|
118
|
+
expect(error.jsonrpc).toBe("2.0");
|
|
119
|
+
expect(error.error.code).toBe(-32603);
|
|
120
|
+
expect(error.error.message).toBeTruthy();
|
|
121
|
+
expect(error.id).toBeNull();
|
|
122
|
+
});
|
|
123
|
+
it("should use standard JSON-RPC error codes", () => {
|
|
124
|
+
const errorCodes = {
|
|
125
|
+
parseError: -32700,
|
|
126
|
+
invalidRequest: -32600,
|
|
127
|
+
methodNotFound: -32601,
|
|
128
|
+
invalidParams: -32602,
|
|
129
|
+
internalError: -32603,
|
|
130
|
+
};
|
|
131
|
+
expect(errorCodes.parseError).toBe(-32700);
|
|
132
|
+
expect(errorCodes.invalidRequest).toBe(-32600);
|
|
133
|
+
expect(errorCodes.methodNotFound).toBe(-32601);
|
|
134
|
+
expect(errorCodes.invalidParams).toBe(-32602);
|
|
135
|
+
expect(errorCodes.internalError).toBe(-32603);
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
describe("Transport Lifecycle", () => {
|
|
140
|
+
it("should close transport on response close", () => {
|
|
141
|
+
const mockTransport = {
|
|
142
|
+
close: vi.fn(),
|
|
143
|
+
};
|
|
144
|
+
const mockResponse = {
|
|
145
|
+
on: vi.fn((event, callback) => {
|
|
146
|
+
if (event === "close") {
|
|
147
|
+
callback();
|
|
148
|
+
}
|
|
149
|
+
}),
|
|
150
|
+
};
|
|
151
|
+
mockResponse.on("close", () => {
|
|
152
|
+
mockTransport.close();
|
|
153
|
+
});
|
|
154
|
+
expect(mockTransport.close).toHaveBeenCalled();
|
|
155
|
+
});
|
|
156
|
+
it("should handle transport connection", async () => {
|
|
157
|
+
const mockServer = {
|
|
158
|
+
connect: vi.fn().mockResolvedValue(undefined),
|
|
159
|
+
};
|
|
160
|
+
const mockTransport = {
|
|
161
|
+
handleRequest: vi.fn().mockResolvedValue(undefined),
|
|
162
|
+
close: vi.fn(),
|
|
163
|
+
};
|
|
164
|
+
await mockServer.connect(mockTransport);
|
|
165
|
+
expect(mockServer.connect).toHaveBeenCalledWith(mockTransport);
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
//# sourceMappingURL=transport.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transport.test.js","sourceRoot":"","sources":["../src/transport.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -175,6 +175,28 @@ Benefits:
|
|
|
175
175
|
- **Query time**: Hybrid search performs two searches and fusion
|
|
176
176
|
- **Scalability**: Qdrant optimizes both vector types efficiently
|
|
177
177
|
|
|
178
|
+
## Try It
|
|
179
|
+
|
|
180
|
+
Practice hybrid search with your own example:
|
|
181
|
+
|
|
182
|
+
```
|
|
183
|
+
Create a collection named "my-hybrid-docs" with Cosine distance and enableHybrid set to true
|
|
184
|
+
|
|
185
|
+
Add these documents to my-hybrid-docs:
|
|
186
|
+
- id: "doc1", text: "The calculateTax function computes sales tax based on location and product type", metadata: {"category": "finance", "type": "function"}
|
|
187
|
+
- id: "doc2", text: "Tax calculation involves applying regional rates and exemptions", metadata: {"category": "finance", "type": "concept"}
|
|
188
|
+
- id: "doc3", text: "The generateInvoice method creates PDF invoices with itemized charges", metadata: {"category": "billing", "type": "function"}
|
|
189
|
+
- id: "doc4", text: "Invoice generation includes customer details, line items, and payment terms", metadata: {"category": "billing", "type": "concept"}
|
|
190
|
+
|
|
191
|
+
Search my-hybrid-docs for "calculateTax invoice" with limit 3 using hybrid_search
|
|
192
|
+
|
|
193
|
+
Search my-hybrid-docs for "tax calculation" with limit 2 using semantic_search
|
|
194
|
+
|
|
195
|
+
# Compare the results - notice how hybrid search finds both exact function names and concepts
|
|
196
|
+
|
|
197
|
+
Delete collection "my-hybrid-docs"
|
|
198
|
+
```
|
|
199
|
+
|
|
178
200
|
## Troubleshooting
|
|
179
201
|
|
|
180
202
|
### "Collection does not have hybrid search enabled"
|
|
@@ -197,3 +219,18 @@ Benefits:
|
|
|
197
219
|
1. Reduce prefetch limit (contact support for tuning)
|
|
198
220
|
2. Add filters to narrow search space
|
|
199
221
|
3. Use fewer documents or partition data
|
|
222
|
+
|
|
223
|
+
## Cleanup
|
|
224
|
+
|
|
225
|
+
```
|
|
226
|
+
Delete collection "technical_docs"
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
## Next Steps
|
|
230
|
+
|
|
231
|
+
Continue learning with these examples:
|
|
232
|
+
|
|
233
|
+
- **[Knowledge Base](../knowledge-base/)** - Searchable documentation with metadata
|
|
234
|
+
- **[Advanced Filtering](../filters/)** - Complex search queries
|
|
235
|
+
- **[Rate Limiting](../rate-limiting/)** - Batch processing patterns
|
|
236
|
+
- **[Basic Usage](../basic/)** - Fundamental operations
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mhalder/qdrant-mcp-server",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "MCP server for semantic search using local Qdrant and Ollama (default) with support for OpenAI, Cohere, and Voyage AI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
"@qdrant/js-client-rest": "^1.12.0",
|
|
38
38
|
"bottleneck": "^2.19.5",
|
|
39
39
|
"cohere-ai": "^7.19.0",
|
|
40
|
+
"express": "^5.1.0",
|
|
40
41
|
"openai": "^4.77.3",
|
|
41
42
|
"zod": "^3.24.1"
|
|
42
43
|
},
|
|
@@ -47,6 +48,7 @@
|
|
|
47
48
|
"@semantic-release/git": "^10.0.1",
|
|
48
49
|
"@semantic-release/github": "^11.0.6",
|
|
49
50
|
"@semantic-release/npm": "^12.0.2",
|
|
51
|
+
"@types/express": "^5.0.3",
|
|
50
52
|
"@types/node": "^22.10.5",
|
|
51
53
|
"@vitest/coverage-v8": "^2.1.8",
|
|
52
54
|
"@vitest/ui": "^2.1.8",
|
package/src/index.ts
CHANGED
|
@@ -5,12 +5,15 @@ import { dirname, join } from "node:path";
|
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
7
7
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
8
|
+
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
8
9
|
import {
|
|
9
10
|
CallToolRequestSchema,
|
|
10
11
|
ListResourcesRequestSchema,
|
|
11
12
|
ListToolsRequestSchema,
|
|
12
13
|
ReadResourceRequestSchema,
|
|
13
14
|
} from "@modelcontextprotocol/sdk/types.js";
|
|
15
|
+
import Bottleneck from "bottleneck";
|
|
16
|
+
import express from "express";
|
|
14
17
|
import { z } from "zod";
|
|
15
18
|
import { EmbeddingProviderFactory } from "./embeddings/factory.js";
|
|
16
19
|
import { BM25SparseVectorGenerator } from "./embeddings/sparse.js";
|
|
@@ -23,6 +26,18 @@ const pkg = JSON.parse(readFileSync(join(__dirname, "../package.json"), "utf-8")
|
|
|
23
26
|
// Validate environment variables
|
|
24
27
|
const QDRANT_URL = process.env.QDRANT_URL || "http://localhost:6333";
|
|
25
28
|
const EMBEDDING_PROVIDER = (process.env.EMBEDDING_PROVIDER || "ollama").toLowerCase();
|
|
29
|
+
const TRANSPORT_MODE = (process.env.TRANSPORT_MODE || "stdio").toLowerCase();
|
|
30
|
+
const HTTP_PORT = parseInt(process.env.HTTP_PORT || "3000", 10);
|
|
31
|
+
|
|
32
|
+
// Validate HTTP_PORT when HTTP mode is selected
|
|
33
|
+
if (TRANSPORT_MODE === "http") {
|
|
34
|
+
if (Number.isNaN(HTTP_PORT) || HTTP_PORT < 1 || HTTP_PORT > 65535) {
|
|
35
|
+
console.error(
|
|
36
|
+
`Error: Invalid HTTP_PORT "${process.env.HTTP_PORT}". Must be a number between 1 and 65535.`
|
|
37
|
+
);
|
|
38
|
+
process.exit(1);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
26
41
|
|
|
27
42
|
// Check for required API keys based on provider
|
|
28
43
|
if (EMBEDDING_PROVIDER !== "ollama") {
|
|
@@ -704,14 +719,229 @@ server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
|
704
719
|
};
|
|
705
720
|
});
|
|
706
721
|
|
|
707
|
-
// Start server
|
|
708
|
-
async function
|
|
722
|
+
// Start server with stdio transport
|
|
723
|
+
async function startStdioServer() {
|
|
709
724
|
await checkOllamaAvailability();
|
|
710
725
|
const transport = new StdioServerTransport();
|
|
711
726
|
await server.connect(transport);
|
|
712
727
|
console.error("Qdrant MCP server running on stdio");
|
|
713
728
|
}
|
|
714
729
|
|
|
730
|
+
// Start server with HTTP transport
|
|
731
|
+
async function startHttpServer() {
|
|
732
|
+
await checkOllamaAvailability();
|
|
733
|
+
|
|
734
|
+
const app = express();
|
|
735
|
+
app.use(express.json({ limit: "10mb" }));
|
|
736
|
+
|
|
737
|
+
// Configure Express to trust proxy for correct IP detection
|
|
738
|
+
app.set("trust proxy", true);
|
|
739
|
+
|
|
740
|
+
// Rate limiter group: max 100 requests per 15 minutes per IP, max 10 concurrent per IP
|
|
741
|
+
const rateLimiterGroup = new Bottleneck.Group({
|
|
742
|
+
reservoir: 100, // initial capacity per IP
|
|
743
|
+
reservoirRefreshAmount: 100, // refresh back to 100
|
|
744
|
+
reservoirRefreshInterval: 15 * 60 * 1000, // every 15 minutes
|
|
745
|
+
maxConcurrent: 10, // max concurrent requests per IP
|
|
746
|
+
});
|
|
747
|
+
|
|
748
|
+
// Periodic cleanup of inactive rate limiters to prevent memory leaks
|
|
749
|
+
// Track last access time for each IP
|
|
750
|
+
const ipLastAccess = new Map<string, number>();
|
|
751
|
+
const INACTIVE_TIMEOUT = 60 * 60 * 1000; // 1 hour
|
|
752
|
+
|
|
753
|
+
const cleanupIntervalId = setInterval(() => {
|
|
754
|
+
const now = Date.now();
|
|
755
|
+
const keysToDelete: string[] = [];
|
|
756
|
+
|
|
757
|
+
ipLastAccess.forEach((lastAccess, ip) => {
|
|
758
|
+
if (now - lastAccess > INACTIVE_TIMEOUT) {
|
|
759
|
+
keysToDelete.push(ip);
|
|
760
|
+
}
|
|
761
|
+
});
|
|
762
|
+
|
|
763
|
+
keysToDelete.forEach((ip) => {
|
|
764
|
+
rateLimiterGroup.deleteKey(ip);
|
|
765
|
+
ipLastAccess.delete(ip);
|
|
766
|
+
});
|
|
767
|
+
|
|
768
|
+
if (keysToDelete.length > 0) {
|
|
769
|
+
console.error(`Cleaned up ${keysToDelete.length} inactive rate limiters`);
|
|
770
|
+
}
|
|
771
|
+
}, INACTIVE_TIMEOUT);
|
|
772
|
+
|
|
773
|
+
// Rate limiting middleware
|
|
774
|
+
const rateLimitMiddleware = async (
|
|
775
|
+
req: express.Request,
|
|
776
|
+
res: express.Response,
|
|
777
|
+
next: express.NextFunction
|
|
778
|
+
) => {
|
|
779
|
+
const clientIp = req.ip || req.socket.remoteAddress || "unknown";
|
|
780
|
+
|
|
781
|
+
try {
|
|
782
|
+
// Update last access time for this IP
|
|
783
|
+
ipLastAccess.set(clientIp, Date.now());
|
|
784
|
+
|
|
785
|
+
// Get or create a limiter for this specific IP
|
|
786
|
+
const limiter = rateLimiterGroup.key(clientIp);
|
|
787
|
+
await limiter.schedule(() => Promise.resolve());
|
|
788
|
+
next();
|
|
789
|
+
} catch (error) {
|
|
790
|
+
// Differentiate between rate limit errors and unexpected errors
|
|
791
|
+
if (error instanceof Bottleneck.BottleneckError) {
|
|
792
|
+
// Rate limit exceeded or Bottleneck operational error
|
|
793
|
+
console.error(`Rate limit exceeded for IP ${clientIp}:`, error.message);
|
|
794
|
+
} else {
|
|
795
|
+
// Unexpected error in rate limiting logic
|
|
796
|
+
console.error("Unexpected rate limiting error:", error);
|
|
797
|
+
}
|
|
798
|
+
res.status(429).json({
|
|
799
|
+
jsonrpc: "2.0",
|
|
800
|
+
error: {
|
|
801
|
+
code: -32000,
|
|
802
|
+
message: "Too many requests",
|
|
803
|
+
},
|
|
804
|
+
id: null,
|
|
805
|
+
});
|
|
806
|
+
}
|
|
807
|
+
};
|
|
808
|
+
|
|
809
|
+
// Health check endpoint
|
|
810
|
+
app.get("/health", (_req, res) => {
|
|
811
|
+
res.json({
|
|
812
|
+
status: "ok",
|
|
813
|
+
mode: TRANSPORT_MODE,
|
|
814
|
+
version: pkg.version,
|
|
815
|
+
embedding_provider: EMBEDDING_PROVIDER,
|
|
816
|
+
});
|
|
817
|
+
});
|
|
818
|
+
|
|
819
|
+
app.post("/mcp", rateLimitMiddleware, async (req, res) => {
|
|
820
|
+
const REQUEST_TIMEOUT = 60000; // 60 seconds
|
|
821
|
+
let timeoutId: NodeJS.Timeout | undefined;
|
|
822
|
+
let isTimedOut = false;
|
|
823
|
+
let transportClosed = false;
|
|
824
|
+
|
|
825
|
+
// Create a new transport for each request in stateless mode.
|
|
826
|
+
// This prevents request ID collisions when different clients use the same JSON-RPC request IDs.
|
|
827
|
+
const transport = new StreamableHTTPServerTransport({
|
|
828
|
+
sessionIdGenerator: undefined, // Stateless mode
|
|
829
|
+
enableJsonResponse: true,
|
|
830
|
+
});
|
|
831
|
+
|
|
832
|
+
// Helper to safely close transport only once
|
|
833
|
+
const closeTransport = async () => {
|
|
834
|
+
if (!transportClosed) {
|
|
835
|
+
transportClosed = true;
|
|
836
|
+
await transport.close().catch((e) => console.error("Error closing transport:", e));
|
|
837
|
+
}
|
|
838
|
+
};
|
|
839
|
+
|
|
840
|
+
try {
|
|
841
|
+
// Set request timeout
|
|
842
|
+
timeoutId = setTimeout(async () => {
|
|
843
|
+
isTimedOut = true;
|
|
844
|
+
// Close transport on timeout to prevent resource leaks
|
|
845
|
+
await closeTransport();
|
|
846
|
+
if (!res.headersSent) {
|
|
847
|
+
res.status(408).json({
|
|
848
|
+
jsonrpc: "2.0",
|
|
849
|
+
error: {
|
|
850
|
+
code: -32000,
|
|
851
|
+
message: "Request timeout",
|
|
852
|
+
},
|
|
853
|
+
id: null,
|
|
854
|
+
});
|
|
855
|
+
}
|
|
856
|
+
}, REQUEST_TIMEOUT);
|
|
857
|
+
|
|
858
|
+
// Clean up transport when response closes
|
|
859
|
+
res.on("close", async () => {
|
|
860
|
+
await closeTransport();
|
|
861
|
+
if (timeoutId) clearTimeout(timeoutId);
|
|
862
|
+
});
|
|
863
|
+
|
|
864
|
+
// Connect the transport to the shared server instance.
|
|
865
|
+
// In stateless mode, each request gets a new transport connection.
|
|
866
|
+
await server.connect(transport);
|
|
867
|
+
await transport.handleRequest(req, res, req.body);
|
|
868
|
+
|
|
869
|
+
// Clear timeout immediately on success to prevent race condition
|
|
870
|
+
if (timeoutId) {
|
|
871
|
+
clearTimeout(timeoutId);
|
|
872
|
+
timeoutId = undefined;
|
|
873
|
+
}
|
|
874
|
+
} catch (error) {
|
|
875
|
+
console.error("Error handling MCP request:", error);
|
|
876
|
+
if (!res.headersSent && !isTimedOut) {
|
|
877
|
+
res.status(500).json({
|
|
878
|
+
jsonrpc: "2.0",
|
|
879
|
+
error: {
|
|
880
|
+
code: -32603,
|
|
881
|
+
message: "Internal server error",
|
|
882
|
+
},
|
|
883
|
+
id: null,
|
|
884
|
+
});
|
|
885
|
+
}
|
|
886
|
+
} finally {
|
|
887
|
+
if (timeoutId) clearTimeout(timeoutId);
|
|
888
|
+
// Ensure transport is closed even if an error occurs
|
|
889
|
+
await closeTransport();
|
|
890
|
+
}
|
|
891
|
+
});
|
|
892
|
+
|
|
893
|
+
const httpServer = app
|
|
894
|
+
.listen(HTTP_PORT, () => {
|
|
895
|
+
console.error(`Qdrant MCP server running on http://localhost:${HTTP_PORT}/mcp`);
|
|
896
|
+
})
|
|
897
|
+
.on("error", (error) => {
|
|
898
|
+
console.error("HTTP server error:", error);
|
|
899
|
+
process.exit(1);
|
|
900
|
+
});
|
|
901
|
+
|
|
902
|
+
// Graceful shutdown handling
|
|
903
|
+
let isShuttingDown = false;
|
|
904
|
+
|
|
905
|
+
const shutdown = () => {
|
|
906
|
+
if (isShuttingDown) return;
|
|
907
|
+
isShuttingDown = true;
|
|
908
|
+
|
|
909
|
+
console.error("Shutdown signal received, closing HTTP server gracefully...");
|
|
910
|
+
|
|
911
|
+
// Clear the cleanup interval to allow graceful shutdown
|
|
912
|
+
clearInterval(cleanupIntervalId);
|
|
913
|
+
|
|
914
|
+
// Force shutdown after 10 seconds
|
|
915
|
+
const forceTimeout = setTimeout(() => {
|
|
916
|
+
console.error("Forcing shutdown after timeout");
|
|
917
|
+
process.exit(1);
|
|
918
|
+
}, 10000);
|
|
919
|
+
|
|
920
|
+
httpServer.close(() => {
|
|
921
|
+
clearTimeout(forceTimeout);
|
|
922
|
+
console.error("HTTP server closed");
|
|
923
|
+
process.exit(0);
|
|
924
|
+
});
|
|
925
|
+
};
|
|
926
|
+
|
|
927
|
+
process.on("SIGTERM", shutdown);
|
|
928
|
+
process.on("SIGINT", shutdown);
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
// Main entry point
|
|
932
|
+
async function main() {
|
|
933
|
+
if (TRANSPORT_MODE === "http") {
|
|
934
|
+
await startHttpServer();
|
|
935
|
+
} else if (TRANSPORT_MODE === "stdio") {
|
|
936
|
+
await startStdioServer();
|
|
937
|
+
} else {
|
|
938
|
+
console.error(
|
|
939
|
+
`Error: Invalid TRANSPORT_MODE "${TRANSPORT_MODE}". Supported modes: stdio, http.`
|
|
940
|
+
);
|
|
941
|
+
process.exit(1);
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
|
|
715
945
|
main().catch((error) => {
|
|
716
946
|
console.error("Fatal error:", error);
|
|
717
947
|
process.exit(1);
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import type { Server as HttpServer } from "node:http";
|
|
2
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
3
|
+
|
|
4
|
+
describe("Transport Configuration", () => {
|
|
5
|
+
let originalEnv: NodeJS.ProcessEnv;
|
|
6
|
+
|
|
7
|
+
beforeEach(() => {
|
|
8
|
+
originalEnv = { ...process.env };
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
afterEach(() => {
|
|
12
|
+
process.env = originalEnv;
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
describe("HTTP Port Validation", () => {
|
|
16
|
+
it("should accept valid port numbers", () => {
|
|
17
|
+
const validPorts = ["1", "80", "443", "3000", "8080", "65535"];
|
|
18
|
+
|
|
19
|
+
validPorts.forEach((port) => {
|
|
20
|
+
const parsed = parseInt(port, 10);
|
|
21
|
+
expect(parsed).toBeGreaterThanOrEqual(1);
|
|
22
|
+
expect(parsed).toBeLessThanOrEqual(65535);
|
|
23
|
+
expect(Number.isNaN(parsed)).toBe(false);
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it("should reject invalid port numbers", () => {
|
|
28
|
+
const invalidCases = [
|
|
29
|
+
{ port: "0", reason: "port 0 is reserved" },
|
|
30
|
+
{ port: "-1", reason: "negative ports are invalid" },
|
|
31
|
+
{ port: "65536", reason: "exceeds maximum port" },
|
|
32
|
+
{ port: "99999", reason: "exceeds maximum port" },
|
|
33
|
+
{ port: "abc", reason: "non-numeric input" },
|
|
34
|
+
{ port: "", reason: "empty string" },
|
|
35
|
+
];
|
|
36
|
+
|
|
37
|
+
invalidCases.forEach(({ port, reason }) => {
|
|
38
|
+
const parsed = parseInt(port, 10);
|
|
39
|
+
const isValid = !Number.isNaN(parsed) && parsed >= 1 && parsed <= 65535;
|
|
40
|
+
expect(isValid, `Failed for ${port}: ${reason}`).toBe(false);
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("should use default port 3000 when HTTP_PORT is not set", () => {
|
|
45
|
+
const port = parseInt(process.env.HTTP_PORT || "3000", 10);
|
|
46
|
+
expect(port).toBe(3000);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it("should parse HTTP_PORT from environment", () => {
|
|
50
|
+
process.env.HTTP_PORT = "8080";
|
|
51
|
+
const port = parseInt(process.env.HTTP_PORT || "3000", 10);
|
|
52
|
+
expect(port).toBe(8080);
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
describe("Transport Mode Validation", () => {
|
|
57
|
+
it("should accept valid transport modes", () => {
|
|
58
|
+
const validModes = ["stdio", "http", "STDIO", "HTTP"];
|
|
59
|
+
|
|
60
|
+
validModes.forEach((mode) => {
|
|
61
|
+
const normalized = mode.toLowerCase();
|
|
62
|
+
expect(["stdio", "http"]).toContain(normalized);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it("should reject invalid transport modes", () => {
|
|
67
|
+
const invalidModes = ["tcp", "websocket", "grpc", ""];
|
|
68
|
+
|
|
69
|
+
invalidModes.forEach((mode) => {
|
|
70
|
+
const normalized = mode.toLowerCase();
|
|
71
|
+
expect(["stdio", "http"]).not.toContain(normalized);
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it("should default to stdio when TRANSPORT_MODE is not set", () => {
|
|
76
|
+
const mode = (process.env.TRANSPORT_MODE || "stdio").toLowerCase();
|
|
77
|
+
expect(mode).toBe("stdio");
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
describe("Request Size Limits", () => {
|
|
82
|
+
it("should define request size limit for HTTP transport", () => {
|
|
83
|
+
const limit = "10mb";
|
|
84
|
+
expect(limit).toMatch(/^\d+mb$/);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it("should parse size limit correctly", () => {
|
|
88
|
+
const limit = "10mb";
|
|
89
|
+
const sizeInBytes = parseInt(limit, 10) * 1024 * 1024;
|
|
90
|
+
expect(sizeInBytes).toBe(10485760);
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
describe("HTTP Server Configuration", () => {
|
|
96
|
+
describe("Graceful Shutdown", () => {
|
|
97
|
+
it("should handle shutdown signals", async () => {
|
|
98
|
+
const mockServer = {
|
|
99
|
+
close: vi.fn((callback) => {
|
|
100
|
+
if (callback) callback();
|
|
101
|
+
}),
|
|
102
|
+
} as unknown as HttpServer;
|
|
103
|
+
|
|
104
|
+
const shutdown = () => {
|
|
105
|
+
mockServer.close(() => {
|
|
106
|
+
// Shutdown callback
|
|
107
|
+
});
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
shutdown();
|
|
111
|
+
expect(mockServer.close).toHaveBeenCalled();
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it("should support timeout for forced shutdown", () => {
|
|
115
|
+
vi.useFakeTimers();
|
|
116
|
+
|
|
117
|
+
let forcedShutdown = false;
|
|
118
|
+
const timeout = setTimeout(() => {
|
|
119
|
+
forcedShutdown = true;
|
|
120
|
+
}, 10000);
|
|
121
|
+
|
|
122
|
+
vi.advanceTimersByTime(9999);
|
|
123
|
+
expect(forcedShutdown).toBe(false);
|
|
124
|
+
|
|
125
|
+
vi.advanceTimersByTime(1);
|
|
126
|
+
expect(forcedShutdown).toBe(true);
|
|
127
|
+
|
|
128
|
+
clearTimeout(timeout);
|
|
129
|
+
vi.useRealTimers();
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
describe("Error Handling", () => {
|
|
134
|
+
it("should return JSON-RPC 2.0 error format", () => {
|
|
135
|
+
const error = {
|
|
136
|
+
jsonrpc: "2.0",
|
|
137
|
+
error: {
|
|
138
|
+
code: -32603,
|
|
139
|
+
message: "Internal server error",
|
|
140
|
+
},
|
|
141
|
+
id: null,
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
expect(error.jsonrpc).toBe("2.0");
|
|
145
|
+
expect(error.error.code).toBe(-32603);
|
|
146
|
+
expect(error.error.message).toBeTruthy();
|
|
147
|
+
expect(error.id).toBeNull();
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
it("should use standard JSON-RPC error codes", () => {
|
|
151
|
+
const errorCodes = {
|
|
152
|
+
parseError: -32700,
|
|
153
|
+
invalidRequest: -32600,
|
|
154
|
+
methodNotFound: -32601,
|
|
155
|
+
invalidParams: -32602,
|
|
156
|
+
internalError: -32603,
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
expect(errorCodes.parseError).toBe(-32700);
|
|
160
|
+
expect(errorCodes.invalidRequest).toBe(-32600);
|
|
161
|
+
expect(errorCodes.methodNotFound).toBe(-32601);
|
|
162
|
+
expect(errorCodes.invalidParams).toBe(-32602);
|
|
163
|
+
expect(errorCodes.internalError).toBe(-32603);
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
describe("Transport Lifecycle", () => {
|
|
169
|
+
it("should close transport on response close", () => {
|
|
170
|
+
const mockTransport = {
|
|
171
|
+
close: vi.fn(),
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
const mockResponse = {
|
|
175
|
+
on: vi.fn((event, callback) => {
|
|
176
|
+
if (event === "close") {
|
|
177
|
+
callback();
|
|
178
|
+
}
|
|
179
|
+
}),
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
mockResponse.on("close", () => {
|
|
183
|
+
mockTransport.close();
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
expect(mockTransport.close).toHaveBeenCalled();
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
it("should handle transport connection", async () => {
|
|
190
|
+
const mockServer = {
|
|
191
|
+
connect: vi.fn().mockResolvedValue(undefined),
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
const mockTransport = {
|
|
195
|
+
handleRequest: vi.fn().mockResolvedValue(undefined),
|
|
196
|
+
close: vi.fn(),
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
await mockServer.connect(mockTransport);
|
|
200
|
+
expect(mockServer.connect).toHaveBeenCalledWith(mockTransport);
|
|
201
|
+
});
|
|
202
|
+
});
|