airweave-mcp-search 0.6.50 → 0.6.52
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/build/api/airweave-client.d.ts +0 -1
- package/build/api/airweave-client.d.ts.map +1 -1
- package/build/api/airweave-client.js +12 -33
- package/build/api/airweave-client.js.map +1 -1
- package/build/index-http.d.ts +15 -0
- package/build/index-http.d.ts.map +1 -1
- package/build/index-http.js +364 -77
- package/build/index-http.js.map +1 -1
- package/build/session/redis-session-manager.d.ts +97 -0
- package/build/session/redis-session-manager.d.ts.map +1 -0
- package/build/session/redis-session-manager.js +254 -0
- package/build/session/redis-session-manager.js.map +1 -0
- package/package.json +8 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"airweave-client.d.ts","sourceRoot":"","sources":["../../src/api/airweave-client.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE5D,qBAAa,cAAc;IAGX,OAAO,CAAC,MAAM;IAF1B,OAAO,CAAC,MAAM,CAAoB;gBAEd,MAAM,EAAE,cAAc;IAOpC,MAAM,CAAC,aAAa,EAAE,GAAG,GAAG,OAAO,CAAC,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"airweave-client.d.ts","sourceRoot":"","sources":["../../src/api/airweave-client.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE5D,qBAAa,cAAc;IAGX,OAAO,CAAC,MAAM;IAF1B,OAAO,CAAC,MAAM,CAAoB;gBAEd,MAAM,EAAE,cAAc;IAOpC,MAAM,CAAC,aAAa,EAAE,GAAG,GAAG,OAAO,CAAC,cAAc,CAAC;IA2BzD,OAAO,CAAC,eAAe;CA8C1B"}
|
|
@@ -11,54 +11,36 @@ export class AirweaveClient {
|
|
|
11
11
|
});
|
|
12
12
|
}
|
|
13
13
|
async search(searchRequest) {
|
|
14
|
+
console.log(`[${new Date().toISOString()}] AirweaveClient.search called with:`, JSON.stringify(searchRequest, null, 2));
|
|
14
15
|
// Mock mode for testing
|
|
15
16
|
if (this.config.apiKey === 'test-key' && this.config.baseUrl.includes('localhost')) {
|
|
16
17
|
return this.getMockResponse(searchRequest);
|
|
17
18
|
}
|
|
18
19
|
try {
|
|
19
|
-
//
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
26
|
-
else {
|
|
27
|
-
// Use the official SDK for basic search
|
|
28
|
-
const { query, response_type, limit, offset, recency_bias } = searchRequest;
|
|
29
|
-
const response = await this.client.collections.search(this.config.collection, {
|
|
30
|
-
query,
|
|
31
|
-
response_type,
|
|
32
|
-
limit,
|
|
33
|
-
offset,
|
|
34
|
-
recency_bias
|
|
35
|
-
});
|
|
36
|
-
return response;
|
|
37
|
-
}
|
|
20
|
+
// Use the SDK's search method - it handles both basic and advanced parameters
|
|
21
|
+
// The SDK will automatically use GET for basic params and POST for advanced
|
|
22
|
+
console.log(`[${new Date().toISOString()}] Calling SDK search with all params`);
|
|
23
|
+
const response = await this.client.collections.search(this.config.collection, searchRequest);
|
|
24
|
+
console.log(`[${new Date().toISOString()}] Search successful, got ${response.results?.length || 0} results`);
|
|
25
|
+
return response;
|
|
38
26
|
}
|
|
39
27
|
catch (error) {
|
|
40
28
|
// Handle SDK errors and convert to our error format
|
|
29
|
+
console.error(`[${new Date().toISOString()}] Search error:`, error);
|
|
41
30
|
if (error.statusCode) {
|
|
42
|
-
|
|
31
|
+
const errorBody = typeof error.body === 'string' ? error.body : JSON.stringify(error.body);
|
|
32
|
+
throw new Error(`Airweave API error (${error.statusCode}): ${error.message}\nStatus code: ${error.statusCode}\nBody: ${errorBody}`);
|
|
43
33
|
}
|
|
44
34
|
else {
|
|
45
|
-
throw new Error(`Airweave API error: ${error.message}`);
|
|
35
|
+
throw new Error(`Airweave API error: ${error.message || 'Unknown error'}`);
|
|
46
36
|
}
|
|
47
37
|
}
|
|
48
38
|
}
|
|
49
|
-
hasAdvancedParameters(params) {
|
|
50
|
-
return !!(params.score_threshold !== undefined ||
|
|
51
|
-
params.search_method !== undefined ||
|
|
52
|
-
params.expansion_strategy !== undefined ||
|
|
53
|
-
params.enable_reranking !== undefined ||
|
|
54
|
-
params.enable_query_interpretation !== undefined);
|
|
55
|
-
}
|
|
56
39
|
getMockResponse(request) {
|
|
57
40
|
const { query, response_type, limit, offset, recency_bias, score_threshold, search_method, expansion_strategy, enable_reranking, enable_query_interpretation } = request;
|
|
58
41
|
// Generate mock results based on the query
|
|
59
42
|
const mockResults = [];
|
|
60
43
|
const resultCount = Math.min(limit || 100, 5); // Limit to 5 for testing
|
|
61
|
-
const hasAdvancedParams = this.hasAdvancedParameters(request);
|
|
62
44
|
for (let i = 0; i < resultCount; i++) {
|
|
63
45
|
const score = 0.95 - (i * 0.1);
|
|
64
46
|
// Apply score threshold if specified
|
|
@@ -83,16 +65,13 @@ export class AirweaveClient {
|
|
|
83
65
|
search_method: search_method,
|
|
84
66
|
expansion_strategy: expansion_strategy,
|
|
85
67
|
enable_reranking: enable_reranking,
|
|
86
|
-
enable_query_interpretation: enable_query_interpretation
|
|
87
|
-
used_advanced_search: hasAdvancedParams
|
|
68
|
+
enable_query_interpretation: enable_query_interpretation
|
|
88
69
|
}
|
|
89
70
|
}
|
|
90
71
|
});
|
|
91
72
|
}
|
|
92
73
|
return {
|
|
93
74
|
results: mockResults,
|
|
94
|
-
response_type: response_type || "raw",
|
|
95
|
-
status: "success",
|
|
96
75
|
completion: response_type === "completion"
|
|
97
76
|
? `Based on the search results for "${query}", here's a comprehensive summary of the findings...`
|
|
98
77
|
: undefined
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"airweave-client.js","sourceRoot":"","sources":["../../src/api/airweave-client.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAE7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAGlD,MAAM,OAAO,cAAc;IAGH;IAFZ,MAAM,CAAoB;IAElC,YAAoB,MAAsB;QAAtB,WAAM,GAAN,MAAM,CAAgB;QACtC,IAAI,CAAC,MAAM,GAAG,IAAI,iBAAiB,CAAC;YAChC,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,OAAO,EAAE,MAAM,CAAC,OAAO;SAC1B,CAAC,CAAC;IACP,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,aAAkB;QAC3B,wBAAwB;QACxB,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,UAAU,IAAI,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;YACjF,OAAO,IAAI,CAAC,eAAe,CAAC,aAAa,CAAC,CAAC;QAC/C,CAAC;QAED,IAAI,CAAC;YACD,
|
|
1
|
+
{"version":3,"file":"airweave-client.js","sourceRoot":"","sources":["../../src/api/airweave-client.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAE7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAGlD,MAAM,OAAO,cAAc;IAGH;IAFZ,MAAM,CAAoB;IAElC,YAAoB,MAAsB;QAAtB,WAAM,GAAN,MAAM,CAAgB;QACtC,IAAI,CAAC,MAAM,GAAG,IAAI,iBAAiB,CAAC;YAChC,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,OAAO,EAAE,MAAM,CAAC,OAAO;SAC1B,CAAC,CAAC;IACP,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,aAAkB;QAC3B,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,sCAAsC,EAAE,IAAI,CAAC,SAAS,CAAC,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAExH,wBAAwB;QACxB,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,UAAU,IAAI,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;YACjF,OAAO,IAAI,CAAC,eAAe,CAAC,aAAa,CAAC,CAAC;QAC/C,CAAC;QAED,IAAI,CAAC;YACD,8EAA8E;YAC9E,4EAA4E;YAC5E,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,sCAAsC,CAAC,CAAC;YAChF,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;YAC7F,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,4BAA4B,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC,UAAU,CAAC,CAAC;YAC7G,OAAO,QAAQ,CAAC;QACpB,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YAClB,oDAAoD;YACpD,OAAO,CAAC,KAAK,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,iBAAiB,EAAE,KAAK,CAAC,CAAC;YACpE,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC;gBACnB,MAAM,SAAS,GAAG,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBAC3F,MAAM,IAAI,KAAK,CAAC,uBAAuB,KAAK,CAAC,UAAU,MAAM,KAAK,CAAC,OAAO,kBAAkB,KAAK,CAAC,UAAU,WAAW,SAAS,EAAE,CAAC,CAAC;YACxI,CAAC;iBAAM,CAAC;gBACJ,MAAM,IAAI,KAAK,CAAC,uBAAuB,KAAK,CAAC,OAAO,IAAI,eAAe,EAAE,CAAC,CAAC;YAC/E,CAAC;QACL,CAAC;IACL,CAAC;IAEO,eAAe,CAAC,OAAY;QAChC,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,eAAe,EAAE,aAAa,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,2BAA2B,EAAE,GAAG,OAAO,CAAC;QAEzK,2CAA2C;QAC3C,MAAM,WAAW,GAAG,EAAE,CAAC;QACvB,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,yBAAyB;QAExE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,EAAE,CAAC,EAAE,EAAE,CAAC;YACnC,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC;YAE/B,qCAAqC;YACrC,IAAI,eAAe,KAAK,SAAS,IAAI,KAAK,GAAG,eAAe,EAAE,CAAC;gBAC3D,SAAS;YACb,CAAC;YAED,WAAW,CAAC,IAAI,CAAC;gBACb,KAAK,EAAE,KAAK;gBACZ,OAAO,EAAE;oBACL,WAAW,EAAE,eAAe,CAAC,GAAG,CAAC,EAAE;oBACnC,SAAS,EAAE,QAAQ,CAAC,GAAG,CAAC,EAAE;oBAC1B,KAAK,EAAE,iBAAiB,CAAC,GAAG,CAAC,WAAW,KAAK,GAAG;oBAChD,UAAU,EAAE,0CAA0C,KAAK,wDAAwD,KAAK,mEAAmE;oBAC3L,UAAU,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,WAAW,EAAE,EAAE,kBAAkB;oBAC9F,QAAQ,EAAE;wBACN,IAAI,EAAE,IAAI;wBACV,KAAK,EAAE,KAAK;wBACZ,KAAK,EAAE,KAAK;wBACZ,MAAM,EAAE,MAAM;wBACd,YAAY,EAAE,YAAY;wBAC1B,eAAe,EAAE,eAAe;wBAChC,aAAa,EAAE,aAAa;wBAC5B,kBAAkB,EAAE,kBAAkB;wBACtC,gBAAgB,EAAE,gBAAgB;wBAClC,2BAA2B,EAAE,2BAA2B;qBAC3D;iBACJ;aACJ,CAAC,CAAC;QACP,CAAC;QAED,OAAO;YACH,OAAO,EAAE,WAAW;YACpB,UAAU,EAAE,aAAa,KAAK,YAAY;gBACtC,CAAC,CAAC,oCAAoC,KAAK,sDAAsD;gBACjG,CAAC,CAAC,SAAS;SAClB,CAAC;IACN,CAAC;CACJ"}
|
package/build/index-http.d.ts
CHANGED
|
@@ -1,3 +1,18 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Airweave MCP Server - HTTP/Streamable Transport with Redis Session Management
|
|
4
|
+
*
|
|
5
|
+
* This is the production HTTP server for cloud-based AI platforms like OpenAI Agent Builder.
|
|
6
|
+
* Uses the modern Streamable HTTP transport (MCP 2025-03-26) instead of deprecated SSE.
|
|
7
|
+
*
|
|
8
|
+
* Session Management:
|
|
9
|
+
* - Redis stores session metadata (API key, collection, timestamps)
|
|
10
|
+
* - Each pod maintains an in-memory cache of McpServer/Transport instances
|
|
11
|
+
* - Sessions can be served by any pod (stateless, horizontally scalable)
|
|
12
|
+
*
|
|
13
|
+
* Endpoint: https://mcp.airweave.ai/mcp
|
|
14
|
+
* Protocol: MCP 2025-03-26 (Streamable HTTP)
|
|
15
|
+
* Authentication: Bearer token, X-API-Key, or query parameter
|
|
16
|
+
*/
|
|
2
17
|
export {};
|
|
3
18
|
//# sourceMappingURL=index-http.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-http.d.ts","sourceRoot":"","sources":["../src/index-http.ts"],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"index-http.d.ts","sourceRoot":"","sources":["../src/index-http.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;;;;GAcG"}
|
package/build/index-http.js
CHANGED
|
@@ -1,35 +1,87 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
2
|
+
/**
|
|
3
|
+
* Airweave MCP Server - HTTP/Streamable Transport with Redis Session Management
|
|
4
|
+
*
|
|
5
|
+
* This is the production HTTP server for cloud-based AI platforms like OpenAI Agent Builder.
|
|
6
|
+
* Uses the modern Streamable HTTP transport (MCP 2025-03-26) instead of deprecated SSE.
|
|
7
|
+
*
|
|
8
|
+
* Session Management:
|
|
9
|
+
* - Redis stores session metadata (API key, collection, timestamps)
|
|
10
|
+
* - Each pod maintains an in-memory cache of McpServer/Transport instances
|
|
11
|
+
* - Sessions can be served by any pod (stateless, horizontally scalable)
|
|
12
|
+
*
|
|
13
|
+
* Endpoint: https://mcp.airweave.ai/mcp
|
|
14
|
+
* Protocol: MCP 2025-03-26 (Streamable HTTP)
|
|
15
|
+
* Authentication: Bearer token, X-API-Key, or query parameter
|
|
16
|
+
*/
|
|
17
|
+
import express from 'express';
|
|
18
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
19
|
+
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
|
20
|
+
import { AirweaveClient } from './api/airweave-client.js';
|
|
21
|
+
import { createSearchTool } from './tools/search-tool.js';
|
|
22
|
+
import { createConfigTool } from './tools/config-tool.js';
|
|
23
|
+
import { RedisSessionManager } from './session/redis-session-manager.js';
|
|
13
24
|
const app = express();
|
|
25
|
+
app.use(express.json({ limit: '10mb' }));
|
|
26
|
+
// Initialize Redis session manager
|
|
27
|
+
const sessionManager = new RedisSessionManager();
|
|
28
|
+
// Create MCP server instance with tools
|
|
29
|
+
const createMcpServer = (apiKey) => {
|
|
30
|
+
const collection = process.env.AIRWEAVE_COLLECTION || 'default';
|
|
31
|
+
const baseUrl = process.env.AIRWEAVE_BASE_URL || 'https://api.airweave.ai';
|
|
32
|
+
const config = {
|
|
33
|
+
collection,
|
|
34
|
+
baseUrl,
|
|
35
|
+
apiKey // Use the provided API key from the request
|
|
36
|
+
};
|
|
37
|
+
const server = new McpServer({
|
|
38
|
+
name: 'airweave-search',
|
|
39
|
+
version: '2.1.0',
|
|
40
|
+
}, {
|
|
41
|
+
capabilities: {
|
|
42
|
+
tools: {},
|
|
43
|
+
logging: {}
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
// Create dynamic tool name based on collection
|
|
47
|
+
const toolName = `search-${collection}`;
|
|
48
|
+
// Initialize Airweave client with the request's API key
|
|
49
|
+
const airweaveClient = new AirweaveClient(config);
|
|
50
|
+
// Create tools using shared tool creation functions
|
|
51
|
+
const searchTool = createSearchTool(toolName, collection, airweaveClient);
|
|
52
|
+
const configTool = createConfigTool(toolName, collection, baseUrl, apiKey);
|
|
53
|
+
// Register tools
|
|
54
|
+
server.tool(searchTool.name, searchTool.description, searchTool.schema, searchTool.handler);
|
|
55
|
+
server.tool(configTool.name, configTool.description, configTool.schema, configTool.handler);
|
|
56
|
+
return server;
|
|
57
|
+
};
|
|
14
58
|
// Health check endpoint
|
|
15
|
-
app.get(
|
|
59
|
+
app.get('/health', async (req, res) => {
|
|
60
|
+
const redisConnected = sessionManager.isConnected();
|
|
16
61
|
res.json({
|
|
17
|
-
status:
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
62
|
+
status: redisConnected ? 'healthy' : 'degraded',
|
|
63
|
+
transport: 'streamable-http',
|
|
64
|
+
protocol: 'MCP 2025-03-26',
|
|
65
|
+
collection: process.env.AIRWEAVE_COLLECTION || 'unknown',
|
|
66
|
+
redis: {
|
|
67
|
+
connected: redisConnected
|
|
68
|
+
},
|
|
69
|
+
timestamp: new Date().toISOString()
|
|
21
70
|
});
|
|
22
71
|
});
|
|
23
72
|
// Root endpoint with server info
|
|
24
|
-
app.get(
|
|
73
|
+
app.get('/', (req, res) => {
|
|
74
|
+
const collection = process.env.AIRWEAVE_COLLECTION || 'default';
|
|
75
|
+
const baseUrl = process.env.AIRWEAVE_BASE_URL || 'https://api.airweave.ai';
|
|
25
76
|
res.json({
|
|
26
77
|
name: "Airweave MCP Search Server",
|
|
27
78
|
version: "2.1.0",
|
|
28
|
-
|
|
29
|
-
|
|
79
|
+
transport: "Streamable HTTP",
|
|
80
|
+
protocol: "MCP 2025-03-26",
|
|
81
|
+
collection: collection,
|
|
30
82
|
endpoints: {
|
|
31
83
|
health: "/health",
|
|
32
|
-
|
|
84
|
+
mcp: "/mcp"
|
|
33
85
|
},
|
|
34
86
|
authentication: {
|
|
35
87
|
required: true,
|
|
@@ -40,74 +92,309 @@ app.get("/", (_req, res) => {
|
|
|
40
92
|
"Query parameter: ?api_key=your-key"
|
|
41
93
|
],
|
|
42
94
|
openai_agent_builder: {
|
|
43
|
-
url: "https://mcp.
|
|
95
|
+
url: "https://mcp.airweave.ai/mcp",
|
|
44
96
|
headers: {
|
|
45
97
|
Authorization: "Bearer <your-airweave-api-key>"
|
|
46
98
|
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
},
|
|
99
|
+
}
|
|
100
|
+
}
|
|
50
101
|
});
|
|
51
102
|
});
|
|
52
|
-
//
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
103
|
+
// Local cache: Map session IDs to { server, transport, data }
|
|
104
|
+
// This cache is per-pod and reconstructed from Redis as needed
|
|
105
|
+
const localSessionCache = new Map();
|
|
106
|
+
/**
|
|
107
|
+
* Helper function to create or recreate session objects (server + transport)
|
|
108
|
+
* Note: apiKey parameter is the PLAINTEXT key needed for API calls
|
|
109
|
+
*/
|
|
110
|
+
async function createSessionObjects(sessionData, apiKey) {
|
|
111
|
+
const { sessionId, collection, baseUrl } = sessionData;
|
|
112
|
+
// Create a new server with the API key
|
|
113
|
+
const server = createMcpServer(apiKey);
|
|
114
|
+
// Create a new transport for this session
|
|
115
|
+
const transport = new StreamableHTTPServerTransport({
|
|
116
|
+
sessionIdGenerator: () => sessionId
|
|
117
|
+
});
|
|
118
|
+
// Set up session management callbacks
|
|
119
|
+
transport.onsessioninitialized = (sid) => {
|
|
120
|
+
console.log(`[${new Date().toISOString()}] Session initialized: ${sid}`);
|
|
121
|
+
};
|
|
122
|
+
// Set up cleanup on close
|
|
123
|
+
transport.onclose = async () => {
|
|
124
|
+
console.log(`[${new Date().toISOString()}] Session closed: ${sessionId}`);
|
|
125
|
+
localSessionCache.delete(sessionId);
|
|
126
|
+
await sessionManager.deleteSession(sessionId);
|
|
127
|
+
};
|
|
128
|
+
// Connect the transport to the server
|
|
129
|
+
await server.connect(transport);
|
|
130
|
+
return { server, transport, data: sessionData };
|
|
131
|
+
}
|
|
132
|
+
// Main MCP endpoint (Streamable HTTP) with Redis session management
|
|
133
|
+
app.post('/mcp', async (req, res) => {
|
|
134
|
+
try {
|
|
135
|
+
// Extract API key from request headers or query parameters
|
|
136
|
+
const apiKey = req.headers['x-api-key'] ||
|
|
137
|
+
req.headers['authorization']?.replace('Bearer ', '') ||
|
|
138
|
+
req.query.apiKey ||
|
|
139
|
+
req.query.api_key;
|
|
140
|
+
if (!apiKey) {
|
|
141
|
+
res.status(401).json({
|
|
142
|
+
jsonrpc: '2.0',
|
|
143
|
+
error: {
|
|
144
|
+
code: -32001,
|
|
145
|
+
message: 'Authentication required',
|
|
146
|
+
data: 'Please provide an API key via X-API-Key header, Authorization header, or apiKey query parameter'
|
|
147
|
+
},
|
|
148
|
+
id: req.body.id || null
|
|
149
|
+
});
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
// Get or create session ID from MCP-Session-ID header
|
|
153
|
+
const sessionId = req.headers['mcp-session-id'] ||
|
|
154
|
+
`session_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
155
|
+
const collection = process.env.AIRWEAVE_COLLECTION || 'default';
|
|
156
|
+
const baseUrl = process.env.AIRWEAVE_BASE_URL || 'https://api.airweave.ai';
|
|
157
|
+
// Security: Extract client metadata for session binding
|
|
158
|
+
const clientIP = req.headers['x-forwarded-for']?.split(',')[0] ||
|
|
159
|
+
req.headers['x-real-ip'] ||
|
|
160
|
+
req.socket.remoteAddress ||
|
|
161
|
+
'unknown';
|
|
162
|
+
const userAgent = req.headers['user-agent'] || 'unknown';
|
|
163
|
+
let session;
|
|
164
|
+
// Step 1: Check local cache (fastest path - same pod, same session)
|
|
165
|
+
session = localSessionCache.get(sessionId);
|
|
166
|
+
if (session) {
|
|
167
|
+
// Security: Validate API key hasn't changed
|
|
168
|
+
const apiKeyMatches = RedisSessionManager.validateApiKey(apiKey, session.data.apiKeyHash);
|
|
169
|
+
if (!apiKeyMatches) {
|
|
170
|
+
console.log(`[${new Date().toISOString()}] API key changed for session ${sessionId}, recreating...`);
|
|
171
|
+
// Close old session
|
|
172
|
+
session.transport.close();
|
|
173
|
+
localSessionCache.delete(sessionId);
|
|
174
|
+
// Create new session data with hash
|
|
175
|
+
const newSessionData = {
|
|
176
|
+
sessionId,
|
|
177
|
+
apiKeyHash: RedisSessionManager.hashApiKey(apiKey),
|
|
178
|
+
collection,
|
|
179
|
+
baseUrl,
|
|
180
|
+
createdAt: Date.now(),
|
|
181
|
+
lastAccessedAt: Date.now(),
|
|
182
|
+
clientIP,
|
|
183
|
+
userAgent
|
|
184
|
+
};
|
|
185
|
+
// Store in Redis
|
|
186
|
+
await sessionManager.setSession(newSessionData, true);
|
|
187
|
+
// Create new session objects
|
|
188
|
+
session = await createSessionObjects(newSessionData, apiKey);
|
|
189
|
+
localSessionCache.set(sessionId, session);
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
// Security: Validate session binding
|
|
193
|
+
if (session.data.clientIP && session.data.clientIP !== clientIP) {
|
|
194
|
+
console.warn(`[${new Date().toISOString()}] Session hijacking attempt detected: IP mismatch for ${sessionId}`);
|
|
195
|
+
res.status(403).json({
|
|
196
|
+
jsonrpc: '2.0',
|
|
197
|
+
error: {
|
|
198
|
+
code: -32003,
|
|
199
|
+
message: 'Session validation failed: Client identity mismatch',
|
|
200
|
+
},
|
|
201
|
+
id: req.body.id || null
|
|
202
|
+
});
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
else {
|
|
208
|
+
// Step 2: Not in local cache - check Redis (different pod or first request)
|
|
209
|
+
const sessionData = await sessionManager.getSession(sessionId);
|
|
210
|
+
if (sessionData) {
|
|
211
|
+
// Session exists in Redis but not in this pod's cache
|
|
212
|
+
console.log(`[${new Date().toISOString()}] Restoring session from Redis: ${sessionId}`);
|
|
213
|
+
// Security: Validate API key matches
|
|
214
|
+
const apiKeyMatches = RedisSessionManager.validateApiKey(apiKey, sessionData.apiKeyHash);
|
|
215
|
+
if (!apiKeyMatches) {
|
|
216
|
+
console.log(`[${new Date().toISOString()}] API key mismatch for session ${sessionId}, recreating...`);
|
|
217
|
+
// Update session data with new API key hash
|
|
218
|
+
sessionData.apiKeyHash = RedisSessionManager.hashApiKey(apiKey);
|
|
219
|
+
sessionData.lastAccessedAt = Date.now();
|
|
220
|
+
sessionData.clientIP = clientIP;
|
|
221
|
+
sessionData.userAgent = userAgent;
|
|
222
|
+
await sessionManager.setSession(sessionData, false);
|
|
223
|
+
}
|
|
224
|
+
// Security: Validate session binding
|
|
225
|
+
if (sessionData.clientIP && sessionData.clientIP !== clientIP) {
|
|
226
|
+
console.warn(`[${new Date().toISOString()}] Session hijacking attempt detected: IP mismatch for ${sessionId}`);
|
|
227
|
+
res.status(403).json({
|
|
228
|
+
jsonrpc: '2.0',
|
|
229
|
+
error: {
|
|
230
|
+
code: -32003,
|
|
231
|
+
message: 'Session validation failed: Client identity mismatch',
|
|
232
|
+
},
|
|
233
|
+
id: req.body.id || null
|
|
234
|
+
});
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
// Recreate server and transport from session data
|
|
238
|
+
session = await createSessionObjects(sessionData, apiKey);
|
|
239
|
+
localSessionCache.set(sessionId, session);
|
|
240
|
+
}
|
|
241
|
+
else {
|
|
242
|
+
// Step 3: New session - check rate limit first
|
|
243
|
+
console.log(`[${new Date().toISOString()}] Creating new session: ${sessionId}`);
|
|
244
|
+
// Security: Check rate limit
|
|
245
|
+
const rateLimit = await sessionManager.checkRateLimit(apiKey);
|
|
246
|
+
if (!rateLimit.allowed) {
|
|
247
|
+
console.warn(`[${new Date().toISOString()}] Rate limit exceeded for API key (${rateLimit.count} sessions/hour)`);
|
|
248
|
+
res.status(429).json({
|
|
249
|
+
jsonrpc: '2.0',
|
|
250
|
+
error: {
|
|
251
|
+
code: -32002,
|
|
252
|
+
message: 'Too many sessions created. Please try again later.',
|
|
253
|
+
data: {
|
|
254
|
+
limit: 100,
|
|
255
|
+
current: rateLimit.count,
|
|
256
|
+
retryAfter: 3600
|
|
257
|
+
}
|
|
258
|
+
},
|
|
259
|
+
id: req.body.id || null
|
|
260
|
+
});
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
const newSessionData = {
|
|
264
|
+
sessionId,
|
|
265
|
+
apiKeyHash: RedisSessionManager.hashApiKey(apiKey),
|
|
266
|
+
collection,
|
|
267
|
+
baseUrl,
|
|
268
|
+
createdAt: Date.now(),
|
|
269
|
+
lastAccessedAt: Date.now(),
|
|
270
|
+
clientIP,
|
|
271
|
+
userAgent
|
|
272
|
+
};
|
|
273
|
+
// Store in Redis
|
|
274
|
+
await sessionManager.setSession(newSessionData, true);
|
|
275
|
+
// Create session objects
|
|
276
|
+
session = await createSessionObjects(newSessionData, apiKey);
|
|
277
|
+
localSessionCache.set(sessionId, session);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
// Handle the request with the session's transport
|
|
281
|
+
await session.transport.handleRequest(req, res, req.body);
|
|
282
|
+
}
|
|
283
|
+
catch (error) {
|
|
284
|
+
console.error(`[${new Date().toISOString()}] Error handling MCP request:`, error);
|
|
285
|
+
if (!res.headersSent) {
|
|
286
|
+
res.status(500).json({
|
|
287
|
+
jsonrpc: '2.0',
|
|
288
|
+
error: {
|
|
289
|
+
code: -32603,
|
|
290
|
+
message: 'Internal server error',
|
|
291
|
+
},
|
|
292
|
+
id: req.body.id || null
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
});
|
|
297
|
+
// DELETE endpoint for session termination
|
|
298
|
+
app.delete('/mcp', async (req, res) => {
|
|
299
|
+
const sessionId = req.headers['mcp-session-id'];
|
|
300
|
+
if (!sessionId) {
|
|
301
|
+
res.status(400).json({
|
|
302
|
+
jsonrpc: '2.0',
|
|
303
|
+
error: {
|
|
304
|
+
code: -32000,
|
|
305
|
+
message: 'Bad Request: No session ID provided',
|
|
306
|
+
},
|
|
307
|
+
id: null
|
|
65
308
|
});
|
|
66
309
|
return;
|
|
67
310
|
}
|
|
68
|
-
//
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
//
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
311
|
+
// Close the session if it exists locally
|
|
312
|
+
const session = localSessionCache.get(sessionId);
|
|
313
|
+
if (session) {
|
|
314
|
+
console.log(`[${new Date().toISOString()}] Terminating session: ${sessionId}`);
|
|
315
|
+
session.transport.close();
|
|
316
|
+
localSessionCache.delete(sessionId);
|
|
317
|
+
}
|
|
318
|
+
// Delete from Redis (works across all pods)
|
|
319
|
+
await sessionManager.deleteSession(sessionId);
|
|
320
|
+
res.status(200).json({
|
|
321
|
+
jsonrpc: '2.0',
|
|
322
|
+
result: {
|
|
323
|
+
message: 'Session terminated successfully'
|
|
324
|
+
},
|
|
325
|
+
id: null
|
|
83
326
|
});
|
|
84
327
|
});
|
|
85
|
-
// POST endpoint for client messages (required by SSE transport)
|
|
86
|
-
app.post("/message", express.json(), async (req, res) => {
|
|
87
|
-
// The SSE transport handles this internally
|
|
88
|
-
// This endpoint is registered but the actual handling is done by the transport
|
|
89
|
-
res.status(200).send();
|
|
90
|
-
});
|
|
91
328
|
// Error handling middleware
|
|
92
|
-
app.use((
|
|
93
|
-
console.error(
|
|
94
|
-
res.
|
|
329
|
+
app.use((error, req, res, next) => {
|
|
330
|
+
console.error(`[${new Date().toISOString()}] Unhandled error:`, error);
|
|
331
|
+
if (!res.headersSent) {
|
|
332
|
+
res.status(500).json({
|
|
333
|
+
jsonrpc: '2.0',
|
|
334
|
+
error: {
|
|
335
|
+
code: -32603,
|
|
336
|
+
message: 'Internal server error',
|
|
337
|
+
},
|
|
338
|
+
id: null
|
|
339
|
+
});
|
|
340
|
+
}
|
|
95
341
|
});
|
|
342
|
+
// Initialize and start server
|
|
343
|
+
async function startServer() {
|
|
344
|
+
const PORT = process.env.PORT || 8080;
|
|
345
|
+
const collection = process.env.AIRWEAVE_COLLECTION || 'default';
|
|
346
|
+
const baseUrl = process.env.AIRWEAVE_BASE_URL || 'https://api.airweave.ai';
|
|
347
|
+
try {
|
|
348
|
+
// Connect to Redis
|
|
349
|
+
console.log('🔌 Connecting to Redis...');
|
|
350
|
+
await sessionManager.connect();
|
|
351
|
+
console.log('✅ Redis connected');
|
|
352
|
+
// Start HTTP server
|
|
353
|
+
const server = app.listen(PORT, () => {
|
|
354
|
+
console.log(`\n🚀 Airweave MCP Search Server (Streamable HTTP) started`);
|
|
355
|
+
console.log(`📡 Protocol: MCP 2025-03-26`);
|
|
356
|
+
console.log(`🔗 Endpoint: http://localhost:${PORT}/mcp`);
|
|
357
|
+
console.log(`🏥 Health: http://localhost:${PORT}/health`);
|
|
358
|
+
console.log(`📋 Info: http://localhost:${PORT}/`);
|
|
359
|
+
console.log(`📚 Collection: ${collection}`);
|
|
360
|
+
console.log(`🌐 Base URL: ${baseUrl}`);
|
|
361
|
+
console.log(`💾 Session Storage: Redis (stateless, horizontally scalable)`);
|
|
362
|
+
console.log(`\n🔑 Authentication required: Provide your Airweave API key via:`);
|
|
363
|
+
console.log(` - Authorization: Bearer <your-api-key>`);
|
|
364
|
+
console.log(` - X-API-Key: <your-api-key>`);
|
|
365
|
+
console.log(` - Query parameter: ?apiKey=your-key`);
|
|
366
|
+
});
|
|
367
|
+
// Graceful shutdown
|
|
368
|
+
const shutdown = async (signal) => {
|
|
369
|
+
console.log(`\n${signal} received. Shutting down gracefully...`);
|
|
370
|
+
// Close HTTP server
|
|
371
|
+
server.close(() => {
|
|
372
|
+
console.log('HTTP server closed');
|
|
373
|
+
});
|
|
374
|
+
// Close all local sessions
|
|
375
|
+
console.log(`Closing ${localSessionCache.size} local sessions...`);
|
|
376
|
+
for (const [sessionId, session] of localSessionCache.entries()) {
|
|
377
|
+
try {
|
|
378
|
+
session.transport.close();
|
|
379
|
+
}
|
|
380
|
+
catch (err) {
|
|
381
|
+
console.error(`Error closing session ${sessionId}:`, err);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
localSessionCache.clear();
|
|
385
|
+
// Disconnect from Redis
|
|
386
|
+
await sessionManager.disconnect();
|
|
387
|
+
console.log('Redis disconnected');
|
|
388
|
+
process.exit(0);
|
|
389
|
+
};
|
|
390
|
+
process.on('SIGTERM', () => shutdown('SIGTERM'));
|
|
391
|
+
process.on('SIGINT', () => shutdown('SIGINT'));
|
|
392
|
+
}
|
|
393
|
+
catch (error) {
|
|
394
|
+
console.error('Failed to start server:', error);
|
|
395
|
+
process.exit(1);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
96
398
|
// Start the server
|
|
97
|
-
|
|
98
|
-
console.error(`Airweave MCP Search Server (HTTP/SSE) started`);
|
|
99
|
-
console.error(`Collection: ${config.collection}`);
|
|
100
|
-
console.error(`Base URL: ${config.baseUrl}`);
|
|
101
|
-
console.error(`Listening on port: ${PORT}`);
|
|
102
|
-
console.error(`SSE endpoint: http://localhost:${PORT}/sse`);
|
|
103
|
-
});
|
|
104
|
-
// Handle graceful shutdown
|
|
105
|
-
process.on("SIGINT", () => {
|
|
106
|
-
console.error("Shutting down Airweave MCP HTTP server...");
|
|
107
|
-
process.exit(0);
|
|
108
|
-
});
|
|
109
|
-
process.on("SIGTERM", () => {
|
|
110
|
-
console.error("Shutting down Airweave MCP HTTP server...");
|
|
111
|
-
process.exit(0);
|
|
112
|
-
});
|
|
399
|
+
startServer().catch(console.error);
|
|
113
400
|
//# sourceMappingURL=index-http.js.map
|
package/build/index-http.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-http.js","sourceRoot":"","sources":["../src/index-http.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index-http.js","sourceRoot":"","sources":["../src/index-http.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,6BAA6B,EAAE,MAAM,oDAAoD,CAAC;AACnG,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAsD,MAAM,oCAAoC,CAAC;AAE7H,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;AACtB,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;AAEzC,mCAAmC;AACnC,MAAM,cAAc,GAAG,IAAI,mBAAmB,EAAE,CAAC;AAEjD,wCAAwC;AACxC,MAAM,eAAe,GAAG,CAAC,MAAc,EAAE,EAAE;IACvC,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,SAAS,CAAC;IAChE,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,yBAAyB,CAAC;IAE3E,MAAM,MAAM,GAAG;QACX,UAAU;QACV,OAAO;QACP,MAAM,CAAC,4CAA4C;KACtD,CAAC;IAEF,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;QACzB,IAAI,EAAE,iBAAiB;QACvB,OAAO,EAAE,OAAO;KACnB,EAAE;QACC,YAAY,EAAE;YACV,KAAK,EAAE,EAAE;YACT,OAAO,EAAE,EAAE;SACd;KACJ,CAAC,CAAC;IAEH,+CAA+C;IAC/C,MAAM,QAAQ,GAAG,UAAU,UAAU,EAAE,CAAC;IAExC,wDAAwD;IACxD,MAAM,cAAc,GAAG,IAAI,cAAc,CAAC,MAAM,CAAC,CAAC;IAElD,oDAAoD;IACpD,MAAM,UAAU,GAAG,gBAAgB,CAAC,QAAQ,EAAE,UAAU,EAAE,cAAc,CAAC,CAAC;IAC1E,MAAM,UAAU,GAAG,gBAAgB,CAAC,QAAQ,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IAE3E,iBAAiB;IACjB,MAAM,CAAC,IAAI,CACP,UAAU,CAAC,IAAI,EACf,UAAU,CAAC,WAAW,EACtB,UAAU,CAAC,MAAM,EACjB,UAAU,CAAC,OAAO,CACrB,CAAC;IAEF,MAAM,CAAC,IAAI,CACP,UAAU,CAAC,IAAI,EACf,UAAU,CAAC,WAAW,EACtB,UAAU,CAAC,MAAM,EACjB,UAAU,CAAC,OAAO,CACrB,CAAC;IAEF,OAAO,MAAM,CAAC;AAClB,CAAC,CAAC;AAEF,wBAAwB;AACxB,GAAG,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;IAClC,MAAM,cAAc,GAAG,cAAc,CAAC,WAAW,EAAE,CAAC;IAEpD,GAAG,CAAC,IAAI,CAAC;QACL,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU;QAC/C,SAAS,EAAE,iBAAiB;QAC5B,QAAQ,EAAE,gBAAgB;QAC1B,UAAU,EAAE,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,SAAS;QACxD,KAAK,EAAE;YACH,SAAS,EAAE,cAAc;SAC5B;QACD,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACtC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC;AAEH,iCAAiC;AACjC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;IACtB,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,SAAS,CAAC;IAChE,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,yBAAyB,CAAC;IAE3E,GAAG,CAAC,IAAI,CAAC;QACL,IAAI,EAAE,4BAA4B;QAClC,OAAO,EAAE,OAAO;QAChB,SAAS,EAAE,iBAAiB;QAC5B,QAAQ,EAAE,gBAAgB;QAC1B,UAAU,EAAE,UAAU;QACtB,SAAS,EAAE;YACP,MAAM,EAAE,SAAS;YACjB,GAAG,EAAE,MAAM;SACd;QACD,cAAc,EAAE;YACZ,QAAQ,EAAE,IAAI;YACd,OAAO,EAAE;gBACL,6EAA6E;gBAC7E,2BAA2B;gBAC3B,mCAAmC;gBACnC,oCAAoC;aACvC;YACD,oBAAoB,EAAE;gBAClB,GAAG,EAAE,6BAA6B;gBAClC,OAAO,EAAE;oBACL,aAAa,EAAE,gCAAgC;iBAClD;aACJ;SACJ;KACJ,CAAC,CAAC;AACP,CAAC,CAAC,CAAC;AAEH,8DAA8D;AAC9D,+DAA+D;AAC/D,MAAM,iBAAiB,GAAG,IAAI,GAAG,EAAgC,CAAC;AAElE;;;GAGG;AACH,KAAK,UAAU,oBAAoB,CAAC,WAAwB,EAAE,MAAc;IACxE,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,OAAO,EAAE,GAAG,WAAW,CAAC;IAEvD,uCAAuC;IACvC,MAAM,MAAM,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;IAEvC,0CAA0C;IAC1C,MAAM,SAAS,GAAG,IAAI,6BAA6B,CAAC;QAChD,kBAAkB,EAAE,GAAG,EAAE,CAAC,SAAS;KACtC,CAAC,CAAC;IAEH,sCAAsC;IACrC,SAAiB,CAAC,oBAAoB,GAAG,CAAC,GAAW,EAAE,EAAE;QACtD,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,0BAA0B,GAAG,EAAE,CAAC,CAAC;IAC7E,CAAC,CAAC;IAEF,0BAA0B;IAC1B,SAAS,CAAC,OAAO,GAAG,KAAK,IAAI,EAAE;QAC3B,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,qBAAqB,SAAS,EAAE,CAAC,CAAC;QAC1E,iBAAiB,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QACpC,MAAM,cAAc,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;IAClD,CAAC,CAAC;IAEF,sCAAsC;IACtC,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAEhC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;AACpD,CAAC;AAED,oEAAoE;AACpE,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;IAChC,IAAI,CAAC;QACD,2DAA2D;QAC3D,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC;YACnC,GAAG,CAAC,OAAO,CAAC,eAAe,CAAC,EAAE,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC;YACpD,GAAG,CAAC,KAAK,CAAC,MAAM;YAChB,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC;QAEtB,IAAI,CAAC,MAAM,EAAE,CAAC;YACV,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;gBACjB,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE;oBACH,IAAI,EAAE,CAAC,KAAK;oBACZ,OAAO,EAAE,yBAAyB;oBAClC,IAAI,EAAE,iGAAiG;iBAC1G;gBACD,EAAE,EAAE,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,IAAI;aAC1B,CAAC,CAAC;YACH,OAAO;QACX,CAAC;QAED,sDAAsD;QACtD,MAAM,SAAS,GAAG,GAAG,CAAC,OAAO,CAAC,gBAAgB,CAAW;YACrD,WAAW,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;QAEvE,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,SAAS,CAAC;QAChE,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,yBAAyB,CAAC;QAE3E,wDAAwD;QACxD,MAAM,QAAQ,GAAI,GAAG,CAAC,OAAO,CAAC,iBAAiB,CAAY,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YACrE,GAAG,CAAC,OAAO,CAAC,WAAW,CAAY;YACpC,GAAG,CAAC,MAAM,CAAC,aAAa;YACxB,SAAS,CAAC;QACd,MAAM,SAAS,GAAG,GAAG,CAAC,OAAO,CAAC,YAAY,CAAC,IAAI,SAAS,CAAC;QAEzD,IAAI,OAAyC,CAAC;QAE9C,oEAAoE;QACpE,OAAO,GAAG,iBAAiB,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAE3C,IAAI,OAAO,EAAE,CAAC;YACV,4CAA4C;YAC5C,MAAM,aAAa,GAAG,mBAAmB,CAAC,cAAc,CACpD,MAAgB,EAChB,OAAO,CAAC,IAAI,CAAC,UAAU,CAC1B,CAAC;YAEF,IAAI,CAAC,aAAa,EAAE,CAAC;gBACjB,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,iCAAiC,SAAS,iBAAiB,CAAC,CAAC;gBAErG,oBAAoB;gBACpB,OAAO,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;gBAC1B,iBAAiB,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;gBAEpC,oCAAoC;gBACpC,MAAM,cAAc,GAAgB;oBAChC,SAAS;oBACT,UAAU,EAAE,mBAAmB,CAAC,UAAU,CAAC,MAAgB,CAAC;oBAC5D,UAAU;oBACV,OAAO;oBACP,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;oBACrB,cAAc,EAAE,IAAI,CAAC,GAAG,EAAE;oBAC1B,QAAQ;oBACR,SAAS;iBACZ,CAAC;gBAEF,iBAAiB;gBACjB,MAAM,cAAc,CAAC,UAAU,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC;gBAEtD,6BAA6B;gBAC7B,OAAO,GAAG,MAAM,oBAAoB,CAAC,cAAc,EAAE,MAAgB,CAAC,CAAC;gBACvE,iBAAiB,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;YAC9C,CAAC;iBAAM,CAAC;gBACJ,qCAAqC;gBACrC,IAAI,OAAO,CAAC,IAAI,CAAC,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;oBAC9D,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,yDAAyD,SAAS,EAAE,CAAC,CAAC;oBAC/G,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;wBACjB,OAAO,EAAE,KAAK;wBACd,KAAK,EAAE;4BACH,IAAI,EAAE,CAAC,KAAK;4BACZ,OAAO,EAAE,qDAAqD;yBACjE;wBACD,EAAE,EAAE,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,IAAI;qBAC1B,CAAC,CAAC;oBACH,OAAO;gBACX,CAAC;YACL,CAAC;QACL,CAAC;aAAM,CAAC;YACJ,4EAA4E;YAC5E,MAAM,WAAW,GAAG,MAAM,cAAc,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;YAE/D,IAAI,WAAW,EAAE,CAAC;gBACd,sDAAsD;gBACtD,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,mCAAmC,SAAS,EAAE,CAAC,CAAC;gBAExF,qCAAqC;gBACrC,MAAM,aAAa,GAAG,mBAAmB,CAAC,cAAc,CACpD,MAAgB,EAChB,WAAW,CAAC,UAAU,CACzB,CAAC;gBAEF,IAAI,CAAC,aAAa,EAAE,CAAC;oBACjB,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,kCAAkC,SAAS,iBAAiB,CAAC,CAAC;oBAEtG,4CAA4C;oBAC5C,WAAW,CAAC,UAAU,GAAG,mBAAmB,CAAC,UAAU,CAAC,MAAgB,CAAC,CAAC;oBAC1E,WAAW,CAAC,cAAc,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;oBACxC,WAAW,CAAC,QAAQ,GAAG,QAAQ,CAAC;oBAChC,WAAW,CAAC,SAAS,GAAG,SAAS,CAAC;oBAClC,MAAM,cAAc,CAAC,UAAU,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;gBACxD,CAAC;gBAED,qCAAqC;gBACrC,IAAI,WAAW,CAAC,QAAQ,IAAI,WAAW,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;oBAC5D,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,yDAAyD,SAAS,EAAE,CAAC,CAAC;oBAC/G,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;wBACjB,OAAO,EAAE,KAAK;wBACd,KAAK,EAAE;4BACH,IAAI,EAAE,CAAC,KAAK;4BACZ,OAAO,EAAE,qDAAqD;yBACjE;wBACD,EAAE,EAAE,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,IAAI;qBAC1B,CAAC,CAAC;oBACH,OAAO;gBACX,CAAC;gBAED,kDAAkD;gBAClD,OAAO,GAAG,MAAM,oBAAoB,CAAC,WAAW,EAAE,MAAgB,CAAC,CAAC;gBACpE,iBAAiB,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;YAC9C,CAAC;iBAAM,CAAC;gBACJ,+CAA+C;gBAC/C,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,2BAA2B,SAAS,EAAE,CAAC,CAAC;gBAEhF,6BAA6B;gBAC7B,MAAM,SAAS,GAAG,MAAM,cAAc,CAAC,cAAc,CAAC,MAAgB,CAAC,CAAC;gBACxE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC;oBACrB,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,sCAAsC,SAAS,CAAC,KAAK,iBAAiB,CAAC,CAAC;oBACjH,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;wBACjB,OAAO,EAAE,KAAK;wBACd,KAAK,EAAE;4BACH,IAAI,EAAE,CAAC,KAAK;4BACZ,OAAO,EAAE,oDAAoD;4BAC7D,IAAI,EAAE;gCACF,KAAK,EAAE,GAAG;gCACV,OAAO,EAAE,SAAS,CAAC,KAAK;gCACxB,UAAU,EAAE,IAAI;6BACnB;yBACJ;wBACD,EAAE,EAAE,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,IAAI;qBAC1B,CAAC,CAAC;oBACH,OAAO;gBACX,CAAC;gBAED,MAAM,cAAc,GAAgB;oBAChC,SAAS;oBACT,UAAU,EAAE,mBAAmB,CAAC,UAAU,CAAC,MAAgB,CAAC;oBAC5D,UAAU;oBACV,OAAO;oBACP,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;oBACrB,cAAc,EAAE,IAAI,CAAC,GAAG,EAAE;oBAC1B,QAAQ;oBACR,SAAS;iBACZ,CAAC;gBAEF,iBAAiB;gBACjB,MAAM,cAAc,CAAC,UAAU,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC;gBAEtD,yBAAyB;gBACzB,OAAO,GAAG,MAAM,oBAAoB,CAAC,cAAc,EAAE,MAAgB,CAAC,CAAC;gBACvE,iBAAiB,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;YAC9C,CAAC;QACL,CAAC;QAED,kDAAkD;QAClD,MAAM,OAAO,CAAC,SAAS,CAAC,aAAa,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;IAE9D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,+BAA+B,EAAE,KAAK,CAAC,CAAC;QAClF,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;YACnB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;gBACjB,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE;oBACH,IAAI,EAAE,CAAC,KAAK;oBACZ,OAAO,EAAE,uBAAuB;iBACnC;gBACD,EAAE,EAAE,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,IAAI;aAC1B,CAAC,CAAC;QACP,CAAC;IACL,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,0CAA0C;AAC1C,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;IAClC,MAAM,SAAS,GAAG,GAAG,CAAC,OAAO,CAAC,gBAAgB,CAAW,CAAC;IAE1D,IAAI,CAAC,SAAS,EAAE,CAAC;QACb,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;YACjB,OAAO,EAAE,KAAK;YACd,KAAK,EAAE;gBACH,IAAI,EAAE,CAAC,KAAK;gBACZ,OAAO,EAAE,qCAAqC;aACjD;YACD,EAAE,EAAE,IAAI;SACX,CAAC,CAAC;QACH,OAAO;IACX,CAAC;IAED,yCAAyC;IACzC,MAAM,OAAO,GAAG,iBAAiB,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IACjD,IAAI,OAAO,EAAE,CAAC;QACV,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,0BAA0B,SAAS,EAAE,CAAC,CAAC;QAC/E,OAAO,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;QAC1B,iBAAiB,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACxC,CAAC;IAED,4CAA4C;IAC5C,MAAM,cAAc,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;IAE9C,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;QACjB,OAAO,EAAE,KAAK;QACd,MAAM,EAAE;YACJ,OAAO,EAAE,iCAAiC;SAC7C;QACD,EAAE,EAAE,IAAI;KACX,CAAC,CAAC;AACP,CAAC,CAAC,CAAC;AAEH,4BAA4B;AAC5B,GAAG,CAAC,GAAG,CAAC,CAAC,KAAY,EAAE,GAAoB,EAAE,GAAqB,EAAE,IAA0B,EAAE,EAAE;IAC9F,OAAO,CAAC,KAAK,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,oBAAoB,EAAE,KAAK,CAAC,CAAC;IACvE,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;QACnB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;YACjB,OAAO,EAAE,KAAK;YACd,KAAK,EAAE;gBACH,IAAI,EAAE,CAAC,KAAK;gBACZ,OAAO,EAAE,uBAAuB;aACnC;YACD,EAAE,EAAE,IAAI;SACX,CAAC,CAAC;IACP,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,8BAA8B;AAC9B,KAAK,UAAU,WAAW;IACtB,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,CAAC;IACtC,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,SAAS,CAAC;IAChE,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,yBAAyB,CAAC;IAE3E,IAAI,CAAC;QACD,mBAAmB;QACnB,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;QACzC,MAAM,cAAc,CAAC,OAAO,EAAE,CAAC;QAC/B,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;QAEjC,oBAAoB;QACpB,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE;YACjC,OAAO,CAAC,GAAG,CAAC,2DAA2D,CAAC,CAAC;YACzE,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAC;YAC3C,OAAO,CAAC,GAAG,CAAC,iCAAiC,IAAI,MAAM,CAAC,CAAC;YACzD,OAAO,CAAC,GAAG,CAAC,+BAA+B,IAAI,SAAS,CAAC,CAAC;YAC1D,OAAO,CAAC,GAAG,CAAC,6BAA6B,IAAI,GAAG,CAAC,CAAC;YAClD,OAAO,CAAC,GAAG,CAAC,kBAAkB,UAAU,EAAE,CAAC,CAAC;YAC5C,OAAO,CAAC,GAAG,CAAC,gBAAgB,OAAO,EAAE,CAAC,CAAC;YACvC,OAAO,CAAC,GAAG,CAAC,8DAA8D,CAAC,CAAC;YAC5E,OAAO,CAAC,GAAG,CAAC,kEAAkE,CAAC,CAAC;YAChF,OAAO,CAAC,GAAG,CAAC,2CAA2C,CAAC,CAAC;YACzD,OAAO,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAC;YAC9C,OAAO,CAAC,GAAG,CAAC,wCAAwC,CAAC,CAAC;QAC1D,CAAC,CAAC,CAAC;QAEH,oBAAoB;QACpB,MAAM,QAAQ,GAAG,KAAK,EAAE,MAAc,EAAE,EAAE;YACtC,OAAO,CAAC,GAAG,CAAC,KAAK,MAAM,wCAAwC,CAAC,CAAC;YAEjE,oBAAoB;YACpB,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE;gBACd,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;YACtC,CAAC,CAAC,CAAC;YAEH,2BAA2B;YAC3B,OAAO,CAAC,GAAG,CAAC,WAAW,iBAAiB,CAAC,IAAI,oBAAoB,CAAC,CAAC;YACnE,KAAK,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,IAAI,iBAAiB,CAAC,OAAO,EAAE,EAAE,CAAC;gBAC7D,IAAI,CAAC;oBACD,OAAO,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;gBAC9B,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACX,OAAO,CAAC,KAAK,CAAC,yBAAyB,SAAS,GAAG,EAAE,GAAG,CAAC,CAAC;gBAC9D,CAAC;YACL,CAAC;YACD,iBAAiB,CAAC,KAAK,EAAE,CAAC;YAE1B,wBAAwB;YACxB,MAAM,cAAc,CAAC,UAAU,EAAE,CAAC;YAClC,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;YAElC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,CAAC,CAAC;QAEF,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;QACjD,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;IAEnD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,yBAAyB,EAAE,KAAK,CAAC,CAAC;QAChD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;AACL,CAAC;AAED,mBAAmB;AACnB,WAAW,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Redis-based session manager for MCP server
|
|
3
|
+
*
|
|
4
|
+
* Stores session metadata in Redis to enable stateless, horizontally-scalable deployments.
|
|
5
|
+
* Session state includes: API key hash, collections metadata, last access timestamp.
|
|
6
|
+
*
|
|
7
|
+
* Security measures:
|
|
8
|
+
* - API keys are hashed (SHA-256) before storage for defense-in-depth
|
|
9
|
+
* - Session TTL limits exposure window
|
|
10
|
+
* - Client binding (IP/User-Agent) prevents session hijacking
|
|
11
|
+
* - Comprehensive audit logging for security monitoring
|
|
12
|
+
*
|
|
13
|
+
* Note: We still need plaintext API keys at runtime to call Airweave API,
|
|
14
|
+
* but Redis compromise won't expose them.
|
|
15
|
+
*/
|
|
16
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
17
|
+
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
|
18
|
+
export interface SessionData {
|
|
19
|
+
sessionId: string;
|
|
20
|
+
apiKeyHash: string;
|
|
21
|
+
collection: string;
|
|
22
|
+
baseUrl: string;
|
|
23
|
+
createdAt: number;
|
|
24
|
+
lastAccessedAt: number;
|
|
25
|
+
clientIP?: string;
|
|
26
|
+
userAgent?: string;
|
|
27
|
+
}
|
|
28
|
+
export interface SessionMetadata {
|
|
29
|
+
clientIP?: string;
|
|
30
|
+
userAgent?: string;
|
|
31
|
+
}
|
|
32
|
+
export interface SessionWithTransport {
|
|
33
|
+
server: McpServer;
|
|
34
|
+
transport: StreamableHTTPServerTransport;
|
|
35
|
+
data: SessionData;
|
|
36
|
+
}
|
|
37
|
+
export declare class RedisSessionManager {
|
|
38
|
+
private redis;
|
|
39
|
+
private connected;
|
|
40
|
+
private readonly SESSION_PREFIX;
|
|
41
|
+
private readonly RATE_LIMIT_PREFIX;
|
|
42
|
+
private readonly DEFAULT_TTL;
|
|
43
|
+
private readonly RATE_LIMIT_WINDOW;
|
|
44
|
+
private readonly MAX_SESSIONS_PER_HOUR;
|
|
45
|
+
constructor(redisUrl?: string);
|
|
46
|
+
connect(): Promise<void>;
|
|
47
|
+
disconnect(): Promise<void>;
|
|
48
|
+
isConnected(): boolean;
|
|
49
|
+
private getKey;
|
|
50
|
+
private getRateLimitKey;
|
|
51
|
+
/**
|
|
52
|
+
* Hash an API key using SHA-256 for secure storage
|
|
53
|
+
* Note: This is defense-in-depth. We still need the plaintext key at runtime.
|
|
54
|
+
*/
|
|
55
|
+
static hashApiKey(apiKey: string): string;
|
|
56
|
+
/**
|
|
57
|
+
* Validate that an API key matches the stored hash
|
|
58
|
+
*/
|
|
59
|
+
static validateApiKey(apiKey: string, apiKeyHash: string): boolean;
|
|
60
|
+
/**
|
|
61
|
+
* Audit log for security monitoring
|
|
62
|
+
*/
|
|
63
|
+
private auditLog;
|
|
64
|
+
/**
|
|
65
|
+
* Check rate limit for session creation
|
|
66
|
+
*/
|
|
67
|
+
checkRateLimit(apiKey: string): Promise<{
|
|
68
|
+
allowed: boolean;
|
|
69
|
+
count: number;
|
|
70
|
+
}>;
|
|
71
|
+
/**
|
|
72
|
+
* Get session data from Redis
|
|
73
|
+
*/
|
|
74
|
+
getSession(sessionId: string): Promise<SessionData | null>;
|
|
75
|
+
/**
|
|
76
|
+
* Create or update session in Redis
|
|
77
|
+
* Includes rate limiting check for new sessions
|
|
78
|
+
*/
|
|
79
|
+
setSession(sessionData: SessionData, isNewSession?: boolean): Promise<void>;
|
|
80
|
+
/**
|
|
81
|
+
* Delete session from Redis
|
|
82
|
+
*/
|
|
83
|
+
deleteSession(sessionId: string): Promise<void>;
|
|
84
|
+
/**
|
|
85
|
+
* Check if a session exists
|
|
86
|
+
*/
|
|
87
|
+
sessionExists(sessionId: string): Promise<boolean>;
|
|
88
|
+
/**
|
|
89
|
+
* Get all session IDs (for debugging/monitoring)
|
|
90
|
+
*/
|
|
91
|
+
getAllSessionIds(): Promise<string[]>;
|
|
92
|
+
/**
|
|
93
|
+
* Clean up expired sessions (manual cleanup, Redis TTL handles this automatically)
|
|
94
|
+
*/
|
|
95
|
+
cleanupExpiredSessions(maxAge?: number): Promise<number>;
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=redis-session-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redis-session-manager.d.ts","sourceRoot":"","sources":["../../src/session/redis-session-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,6BAA6B,EAAE,MAAM,oDAAoD,CAAC;AAGnG,MAAM,WAAW,WAAW;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IAEvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,oBAAoB;IACjC,MAAM,EAAE,SAAS,CAAC;IAClB,SAAS,EAAE,6BAA6B,CAAC;IACzC,IAAI,EAAE,WAAW,CAAC;CACrB;AAED,qBAAa,mBAAmB;IAC5B,OAAO,CAAC,KAAK,CAAkB;IAC/B,OAAO,CAAC,SAAS,CAAkB;IACnC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAkB;IACjD,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAqB;IACvD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAQ;IACpC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAQ;IAC1C,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAO;gBAEjC,QAAQ,CAAC,EAAE,MAAM;IA+BvB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAMxB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAOjC,WAAW,IAAI,OAAO;IAItB,OAAO,CAAC,MAAM;IAId,OAAO,CAAC,eAAe;IAKvB;;;OAGG;IACH,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAIzC;;OAEG;IACH,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO;IAIlE;;OAEG;IACH,OAAO,CAAC,QAAQ;IAShB;;OAEG;IACG,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IA8BlF;;OAEG;IACG,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAgChE;;;OAGG;IACG,UAAU,CAAC,WAAW,EAAE,WAAW,EAAE,YAAY,GAAE,OAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAwBxF;;OAEG;IACG,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgBrD;;OAEG;IACG,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAWxD;;OAEG;IACG,gBAAgB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAW3C;;OAEG;IACG,sBAAsB,CAAC,MAAM,GAAE,MAAgC,GAAG,OAAO,CAAC,MAAM,CAAC;CAwB1F"}
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Redis-based session manager for MCP server
|
|
3
|
+
*
|
|
4
|
+
* Stores session metadata in Redis to enable stateless, horizontally-scalable deployments.
|
|
5
|
+
* Session state includes: API key hash, collections metadata, last access timestamp.
|
|
6
|
+
*
|
|
7
|
+
* Security measures:
|
|
8
|
+
* - API keys are hashed (SHA-256) before storage for defense-in-depth
|
|
9
|
+
* - Session TTL limits exposure window
|
|
10
|
+
* - Client binding (IP/User-Agent) prevents session hijacking
|
|
11
|
+
* - Comprehensive audit logging for security monitoring
|
|
12
|
+
*
|
|
13
|
+
* Note: We still need plaintext API keys at runtime to call Airweave API,
|
|
14
|
+
* but Redis compromise won't expose them.
|
|
15
|
+
*/
|
|
16
|
+
import { createClient } from 'redis';
|
|
17
|
+
import { createHash } from 'crypto';
|
|
18
|
+
export class RedisSessionManager {
|
|
19
|
+
redis;
|
|
20
|
+
connected = false;
|
|
21
|
+
SESSION_PREFIX = 'mcp:session:';
|
|
22
|
+
RATE_LIMIT_PREFIX = 'mcp:rate_limit:';
|
|
23
|
+
DEFAULT_TTL = 1800; // 30 minutes (reduced from 1 hour for security)
|
|
24
|
+
RATE_LIMIT_WINDOW = 3600; // 1 hour
|
|
25
|
+
MAX_SESSIONS_PER_HOUR = 100; // Per API key
|
|
26
|
+
constructor(redisUrl) {
|
|
27
|
+
this.redis = createClient({
|
|
28
|
+
url: redisUrl || process.env.REDIS_URL || 'redis://localhost:6379',
|
|
29
|
+
socket: {
|
|
30
|
+
reconnectStrategy: (retries) => {
|
|
31
|
+
if (retries > 10) {
|
|
32
|
+
console.error('Redis: Max reconnection attempts reached');
|
|
33
|
+
return new Error('Max reconnection attempts reached');
|
|
34
|
+
}
|
|
35
|
+
const delay = Math.min(retries * 100, 3000);
|
|
36
|
+
console.log(`Redis: Reconnecting in ${delay}ms (attempt ${retries})`);
|
|
37
|
+
return delay;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
this.redis.on('error', (err) => {
|
|
42
|
+
console.error('Redis Client Error:', err);
|
|
43
|
+
});
|
|
44
|
+
this.redis.on('connect', () => {
|
|
45
|
+
console.log('Redis: Connected');
|
|
46
|
+
this.connected = true;
|
|
47
|
+
});
|
|
48
|
+
this.redis.on('disconnect', () => {
|
|
49
|
+
console.log('Redis: Disconnected');
|
|
50
|
+
this.connected = false;
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
async connect() {
|
|
54
|
+
if (!this.connected) {
|
|
55
|
+
await this.redis.connect();
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
async disconnect() {
|
|
59
|
+
if (this.connected) {
|
|
60
|
+
await this.redis.quit();
|
|
61
|
+
this.connected = false;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
isConnected() {
|
|
65
|
+
return this.connected;
|
|
66
|
+
}
|
|
67
|
+
getKey(sessionId) {
|
|
68
|
+
return `${this.SESSION_PREFIX}${sessionId}`;
|
|
69
|
+
}
|
|
70
|
+
getRateLimitKey(apiKeyHash) {
|
|
71
|
+
const hour = Math.floor(Date.now() / (1000 * 60 * 60));
|
|
72
|
+
return `${this.RATE_LIMIT_PREFIX}${apiKeyHash}:${hour}`;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Hash an API key using SHA-256 for secure storage
|
|
76
|
+
* Note: This is defense-in-depth. We still need the plaintext key at runtime.
|
|
77
|
+
*/
|
|
78
|
+
static hashApiKey(apiKey) {
|
|
79
|
+
return createHash('sha256').update(apiKey).digest('hex');
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Validate that an API key matches the stored hash
|
|
83
|
+
*/
|
|
84
|
+
static validateApiKey(apiKey, apiKeyHash) {
|
|
85
|
+
return RedisSessionManager.hashApiKey(apiKey) === apiKeyHash;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Audit log for security monitoring
|
|
89
|
+
*/
|
|
90
|
+
auditLog(operation, details) {
|
|
91
|
+
console.log(JSON.stringify({
|
|
92
|
+
timestamp: new Date().toISOString(),
|
|
93
|
+
service: 'mcp-redis-session',
|
|
94
|
+
operation,
|
|
95
|
+
...details
|
|
96
|
+
}));
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Check rate limit for session creation
|
|
100
|
+
*/
|
|
101
|
+
async checkRateLimit(apiKey) {
|
|
102
|
+
try {
|
|
103
|
+
const apiKeyHash = RedisSessionManager.hashApiKey(apiKey);
|
|
104
|
+
const rateLimitKey = this.getRateLimitKey(apiKeyHash);
|
|
105
|
+
const count = await this.redis.incr(rateLimitKey);
|
|
106
|
+
// Set expiration on first increment
|
|
107
|
+
if (count === 1) {
|
|
108
|
+
await this.redis.expire(rateLimitKey, this.RATE_LIMIT_WINDOW);
|
|
109
|
+
}
|
|
110
|
+
const allowed = count <= this.MAX_SESSIONS_PER_HOUR;
|
|
111
|
+
if (!allowed) {
|
|
112
|
+
this.auditLog('rate_limit_exceeded', {
|
|
113
|
+
apiKeyHash: apiKeyHash ? apiKeyHash.substring(0, 16) + '...' : 'N/A',
|
|
114
|
+
count,
|
|
115
|
+
limit: this.MAX_SESSIONS_PER_HOUR
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
return { allowed, count };
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
console.error('Error checking rate limit:', error);
|
|
122
|
+
// Fail open - allow the request if rate limiting fails
|
|
123
|
+
return { allowed: true, count: 0 };
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Get session data from Redis
|
|
128
|
+
*/
|
|
129
|
+
async getSession(sessionId) {
|
|
130
|
+
try {
|
|
131
|
+
const key = this.getKey(sessionId);
|
|
132
|
+
const data = await this.redis.get(key);
|
|
133
|
+
if (!data) {
|
|
134
|
+
this.auditLog('session_miss', { sessionId });
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
const sessionData = JSON.parse(data);
|
|
138
|
+
// Update last accessed time
|
|
139
|
+
sessionData.lastAccessedAt = Date.now();
|
|
140
|
+
await this.redis.set(key, JSON.stringify(sessionData), {
|
|
141
|
+
EX: this.DEFAULT_TTL
|
|
142
|
+
});
|
|
143
|
+
this.auditLog('session_accessed', {
|
|
144
|
+
sessionId,
|
|
145
|
+
apiKeyHash: sessionData.apiKeyHash ? sessionData.apiKeyHash.substring(0, 16) + '...' : 'N/A',
|
|
146
|
+
age: Date.now() - sessionData.createdAt
|
|
147
|
+
});
|
|
148
|
+
return sessionData;
|
|
149
|
+
}
|
|
150
|
+
catch (error) {
|
|
151
|
+
console.error(`Error getting session ${sessionId}:`, error);
|
|
152
|
+
this.auditLog('session_error', { sessionId, error: String(error) });
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Create or update session in Redis
|
|
158
|
+
* Includes rate limiting check for new sessions
|
|
159
|
+
*/
|
|
160
|
+
async setSession(sessionData, isNewSession = false) {
|
|
161
|
+
try {
|
|
162
|
+
const key = this.getKey(sessionData.sessionId);
|
|
163
|
+
await this.redis.set(key, JSON.stringify(sessionData), {
|
|
164
|
+
EX: this.DEFAULT_TTL
|
|
165
|
+
});
|
|
166
|
+
this.auditLog(isNewSession ? 'session_created' : 'session_updated', {
|
|
167
|
+
sessionId: sessionData.sessionId,
|
|
168
|
+
apiKeyHash: sessionData.apiKeyHash ? sessionData.apiKeyHash.substring(0, 16) + '...' : 'N/A',
|
|
169
|
+
clientIP: sessionData.clientIP || 'unknown',
|
|
170
|
+
hasBinding: !!(sessionData.clientIP && sessionData.userAgent)
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
catch (error) {
|
|
174
|
+
console.error(`Error setting session ${sessionData.sessionId}:`, error);
|
|
175
|
+
this.auditLog('session_error', {
|
|
176
|
+
sessionId: sessionData.sessionId,
|
|
177
|
+
error: String(error),
|
|
178
|
+
operation: 'set'
|
|
179
|
+
});
|
|
180
|
+
throw error;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Delete session from Redis
|
|
185
|
+
*/
|
|
186
|
+
async deleteSession(sessionId) {
|
|
187
|
+
try {
|
|
188
|
+
const key = this.getKey(sessionId);
|
|
189
|
+
await this.redis.del(key);
|
|
190
|
+
this.auditLog('session_deleted', { sessionId });
|
|
191
|
+
}
|
|
192
|
+
catch (error) {
|
|
193
|
+
console.error(`Error deleting session ${sessionId}:`, error);
|
|
194
|
+
this.auditLog('session_error', {
|
|
195
|
+
sessionId,
|
|
196
|
+
error: String(error),
|
|
197
|
+
operation: 'delete'
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Check if a session exists
|
|
203
|
+
*/
|
|
204
|
+
async sessionExists(sessionId) {
|
|
205
|
+
try {
|
|
206
|
+
const key = this.getKey(sessionId);
|
|
207
|
+
const exists = await this.redis.exists(key);
|
|
208
|
+
return exists === 1;
|
|
209
|
+
}
|
|
210
|
+
catch (error) {
|
|
211
|
+
console.error(`Error checking session ${sessionId}:`, error);
|
|
212
|
+
return false;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Get all session IDs (for debugging/monitoring)
|
|
217
|
+
*/
|
|
218
|
+
async getAllSessionIds() {
|
|
219
|
+
try {
|
|
220
|
+
const keys = await this.redis.keys(`${this.SESSION_PREFIX}*`);
|
|
221
|
+
return keys.map(key => key.replace(this.SESSION_PREFIX, ''));
|
|
222
|
+
}
|
|
223
|
+
catch (error) {
|
|
224
|
+
console.error('Error getting all session IDs:', error);
|
|
225
|
+
return [];
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Clean up expired sessions (manual cleanup, Redis TTL handles this automatically)
|
|
230
|
+
*/
|
|
231
|
+
async cleanupExpiredSessions(maxAge = this.DEFAULT_TTL * 1000) {
|
|
232
|
+
try {
|
|
233
|
+
const keys = await this.redis.keys(`${this.SESSION_PREFIX}*`);
|
|
234
|
+
let deleted = 0;
|
|
235
|
+
for (const key of keys) {
|
|
236
|
+
const data = await this.redis.get(key);
|
|
237
|
+
if (data) {
|
|
238
|
+
const sessionData = JSON.parse(data);
|
|
239
|
+
const age = Date.now() - sessionData.lastAccessedAt;
|
|
240
|
+
if (age > maxAge) {
|
|
241
|
+
await this.redis.del(key);
|
|
242
|
+
deleted++;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
return deleted;
|
|
247
|
+
}
|
|
248
|
+
catch (error) {
|
|
249
|
+
console.error('Error cleaning up expired sessions:', error);
|
|
250
|
+
return 0;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
//# sourceMappingURL=redis-session-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redis-session-manager.js","sourceRoot":"","sources":["../../src/session/redis-session-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,YAAY,EAAmB,MAAM,OAAO,CAAC;AAGtD,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAyBpC,MAAM,OAAO,mBAAmB;IACpB,KAAK,CAAkB;IACvB,SAAS,GAAY,KAAK,CAAC;IAClB,cAAc,GAAG,cAAc,CAAC;IAChC,iBAAiB,GAAG,iBAAiB,CAAC;IACtC,WAAW,GAAG,IAAI,CAAC,CAAC,gDAAgD;IACpE,iBAAiB,GAAG,IAAI,CAAC,CAAC,SAAS;IACnC,qBAAqB,GAAG,GAAG,CAAC,CAAC,cAAc;IAE5D,YAAY,QAAiB;QACzB,IAAI,CAAC,KAAK,GAAG,YAAY,CAAC;YACtB,GAAG,EAAE,QAAQ,IAAI,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,wBAAwB;YAClE,MAAM,EAAE;gBACJ,iBAAiB,EAAE,CAAC,OAAO,EAAE,EAAE;oBAC3B,IAAI,OAAO,GAAG,EAAE,EAAE,CAAC;wBACf,OAAO,CAAC,KAAK,CAAC,0CAA0C,CAAC,CAAC;wBAC1D,OAAO,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;oBAC1D,CAAC;oBACD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,GAAG,GAAG,EAAE,IAAI,CAAC,CAAC;oBAC5C,OAAO,CAAC,GAAG,CAAC,0BAA0B,KAAK,eAAe,OAAO,GAAG,CAAC,CAAC;oBACtE,OAAO,KAAK,CAAC;gBACjB,CAAC;aACJ;SACJ,CAAC,CAAC;QAEH,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YAC3B,OAAO,CAAC,KAAK,CAAC,qBAAqB,EAAE,GAAG,CAAC,CAAC;QAC9C,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE;YAC1B,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;YAChC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QAC1B,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,EAAE,GAAG,EAAE;YAC7B,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;YACnC,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;QAC3B,CAAC,CAAC,CAAC;IACP,CAAC;IAED,KAAK,CAAC,OAAO;QACT,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YAClB,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;QAC/B,CAAC;IACL,CAAC;IAED,KAAK,CAAC,UAAU;QACZ,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACjB,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;YACxB,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;QAC3B,CAAC;IACL,CAAC;IAED,WAAW;QACP,OAAO,IAAI,CAAC,SAAS,CAAC;IAC1B,CAAC;IAEO,MAAM,CAAC,SAAiB;QAC5B,OAAO,GAAG,IAAI,CAAC,cAAc,GAAG,SAAS,EAAE,CAAC;IAChD,CAAC;IAEO,eAAe,CAAC,UAAkB;QACtC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;QACvD,OAAO,GAAG,IAAI,CAAC,iBAAiB,GAAG,UAAU,IAAI,IAAI,EAAE,CAAC;IAC5D,CAAC;IAED;;;OAGG;IACH,MAAM,CAAC,UAAU,CAAC,MAAc;QAC5B,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC7D,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,cAAc,CAAC,MAAc,EAAE,UAAkB;QACpD,OAAO,mBAAmB,CAAC,UAAU,CAAC,MAAM,CAAC,KAAK,UAAU,CAAC;IACjE,CAAC;IAED;;OAEG;IACK,QAAQ,CAAC,SAAiB,EAAE,OAA4B;QAC5D,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC;YACvB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,OAAO,EAAE,mBAAmB;YAC5B,SAAS;YACT,GAAG,OAAO;SACb,CAAC,CAAC,CAAC;IACR,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,cAAc,CAAC,MAAc;QAC/B,IAAI,CAAC;YACD,MAAM,UAAU,GAAG,mBAAmB,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;YAC1D,MAAM,YAAY,GAAG,IAAI,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC;YAEtD,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YAElD,oCAAoC;YACpC,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;gBACd,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,EAAE,IAAI,CAAC,iBAAiB,CAAC,CAAC;YAClE,CAAC;YAED,MAAM,OAAO,GAAG,KAAK,IAAI,IAAI,CAAC,qBAAqB,CAAC;YAEpD,IAAI,CAAC,OAAO,EAAE,CAAC;gBACX,IAAI,CAAC,QAAQ,CAAC,qBAAqB,EAAE;oBACjC,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,KAAK;oBACpE,KAAK;oBACL,KAAK,EAAE,IAAI,CAAC,qBAAqB;iBACpC,CAAC,CAAC;YACP,CAAC;YAED,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QAC9B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,4BAA4B,EAAE,KAAK,CAAC,CAAC;YACnD,uDAAuD;YACvD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;QACvC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,UAAU,CAAC,SAAiB;QAC9B,IAAI,CAAC;YACD,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;YACnC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAEvC,IAAI,CAAC,IAAI,EAAE,CAAC;gBACR,IAAI,CAAC,QAAQ,CAAC,cAAc,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC;gBAC7C,OAAO,IAAI,CAAC;YAChB,CAAC;YAED,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAgB,CAAC;YAEpD,4BAA4B;YAC5B,WAAW,CAAC,cAAc,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACxC,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,EAAE;gBACnD,EAAE,EAAE,IAAI,CAAC,WAAW;aACvB,CAAC,CAAC;YAEH,IAAI,CAAC,QAAQ,CAAC,kBAAkB,EAAE;gBAC9B,SAAS;gBACT,UAAU,EAAE,WAAW,CAAC,UAAU,CAAC,CAAC,CAAC,WAAW,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,KAAK;gBAC5F,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,WAAW,CAAC,SAAS;aAC1C,CAAC,CAAC;YAEH,OAAO,WAAW,CAAC;QACvB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,yBAAyB,SAAS,GAAG,EAAE,KAAK,CAAC,CAAC;YAC5D,IAAI,CAAC,QAAQ,CAAC,eAAe,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YACpE,OAAO,IAAI,CAAC;QAChB,CAAC;IACL,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,UAAU,CAAC,WAAwB,EAAE,eAAwB,KAAK;QACpE,IAAI,CAAC;YACD,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;YAC/C,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,EAAE;gBACnD,EAAE,EAAE,IAAI,CAAC,WAAW;aACvB,CAAC,CAAC;YAEH,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,iBAAiB,EAAE;gBAChE,SAAS,EAAE,WAAW,CAAC,SAAS;gBAChC,UAAU,EAAE,WAAW,CAAC,UAAU,CAAC,CAAC,CAAC,WAAW,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,KAAK;gBAC5F,QAAQ,EAAE,WAAW,CAAC,QAAQ,IAAI,SAAS;gBAC3C,UAAU,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,QAAQ,IAAI,WAAW,CAAC,SAAS,CAAC;aAChE,CAAC,CAAC;QACP,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,yBAAyB,WAAW,CAAC,SAAS,GAAG,EAAE,KAAK,CAAC,CAAC;YACxE,IAAI,CAAC,QAAQ,CAAC,eAAe,EAAE;gBAC3B,SAAS,EAAE,WAAW,CAAC,SAAS;gBAChC,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC;gBACpB,SAAS,EAAE,KAAK;aACnB,CAAC,CAAC;YACH,MAAM,KAAK,CAAC;QAChB,CAAC;IACL,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,aAAa,CAAC,SAAiB;QACjC,IAAI,CAAC;YACD,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;YACnC,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAE1B,IAAI,CAAC,QAAQ,CAAC,iBAAiB,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC;QACpD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,0BAA0B,SAAS,GAAG,EAAE,KAAK,CAAC,CAAC;YAC7D,IAAI,CAAC,QAAQ,CAAC,eAAe,EAAE;gBAC3B,SAAS;gBACT,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC;gBACpB,SAAS,EAAE,QAAQ;aACtB,CAAC,CAAC;QACP,CAAC;IACL,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,aAAa,CAAC,SAAiB;QACjC,IAAI,CAAC;YACD,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;YACnC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC5C,OAAO,MAAM,KAAK,CAAC,CAAC;QACxB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,0BAA0B,SAAS,GAAG,EAAE,KAAK,CAAC,CAAC;YAC7D,OAAO,KAAK,CAAC;QACjB,CAAC;IACL,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,gBAAgB;QAClB,IAAI,CAAC;YACD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,cAAc,GAAG,CAAC,CAAC;YAC9D,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC,CAAC;QACjE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,gCAAgC,EAAE,KAAK,CAAC,CAAC;YACvD,OAAO,EAAE,CAAC;QACd,CAAC;IACL,CAAC;IAGD;;OAEG;IACH,KAAK,CAAC,sBAAsB,CAAC,SAAiB,IAAI,CAAC,WAAW,GAAG,IAAI;QACjE,IAAI,CAAC;YACD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,cAAc,GAAG,CAAC,CAAC;YAC9D,IAAI,OAAO,GAAG,CAAC,CAAC;YAEhB,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;gBACrB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;gBACvC,IAAI,IAAI,EAAE,CAAC;oBACP,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAgB,CAAC;oBACpD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,WAAW,CAAC,cAAc,CAAC;oBAEpD,IAAI,GAAG,GAAG,MAAM,EAAE,CAAC;wBACf,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;wBAC1B,OAAO,EAAE,CAAC;oBACd,CAAC;gBACL,CAAC;YACL,CAAC;YAED,OAAO,OAAO,CAAC;QACnB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,qCAAqC,EAAE,KAAK,CAAC,CAAC;YAC5D,OAAO,CAAC,CAAC;QACb,CAAC;IACL,CAAC;CACJ"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "airweave-mcp-search",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.52",
|
|
4
4
|
"description": "MCP server for searching Airweave collections",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "build/index.js",
|
|
@@ -16,9 +16,9 @@
|
|
|
16
16
|
"test": "vitest run",
|
|
17
17
|
"test:watch": "vitest",
|
|
18
18
|
"test:coverage": "vitest run --coverage",
|
|
19
|
-
"test:
|
|
20
|
-
"test:
|
|
21
|
-
"test:
|
|
19
|
+
"test:mcp": "vitest run tests/mcp-server.test.ts",
|
|
20
|
+
"test:http": "vitest run tests/http-transport.test.ts",
|
|
21
|
+
"test:all": "npm run test:mcp && npm run test:http",
|
|
22
22
|
"prepublishOnly": "npm run build"
|
|
23
23
|
},
|
|
24
24
|
"keywords": [
|
|
@@ -46,15 +46,18 @@
|
|
|
46
46
|
"node": ">=18.0.0"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@airweave/sdk": "^0.
|
|
49
|
+
"@airweave/sdk": "^0.6.0",
|
|
50
50
|
"@modelcontextprotocol/sdk": "^1.12.0",
|
|
51
51
|
"express": "^4.18.2",
|
|
52
|
+
"redis": "^4.6.13",
|
|
52
53
|
"zod": "^3.23.8"
|
|
53
54
|
},
|
|
54
55
|
"devDependencies": {
|
|
55
56
|
"@types/express": "^4.17.21",
|
|
56
57
|
"@types/node": "^22.10.7",
|
|
58
|
+
"@types/supertest": "^6.0.2",
|
|
57
59
|
"@vitest/coverage-v8": "^2.0.0",
|
|
60
|
+
"supertest": "^7.0.0",
|
|
58
61
|
"typescript": "^5.7.3",
|
|
59
62
|
"vitest": "^2.0.0"
|
|
60
63
|
},
|