@prmichaelsen/remember-mcp 0.2.0 → 0.2.2
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/dist/server-factory.d.ts +2 -0
- package/dist/server-factory.js +59 -8
- package/dist/server.js +27 -8
- package/dist/weaviate/client.d.ts +3 -0
- package/package.json +1 -1
- package/src/config.ts +3 -3
- package/src/server-factory.ts +52 -5
- package/src/weaviate/client.ts +43 -10
package/dist/server-factory.d.ts
CHANGED
|
@@ -13,6 +13,8 @@ export interface ServerOptions {
|
|
|
13
13
|
* This factory function is compatible with mcp-auth wrapping pattern.
|
|
14
14
|
* It creates isolated server instances with no shared state.
|
|
15
15
|
*
|
|
16
|
+
* Note: Databases (Weaviate + Firestore) are initialized once globally on first call.
|
|
17
|
+
*
|
|
16
18
|
* @param accessToken - User's access token (reserved for future external APIs)
|
|
17
19
|
* @param userId - User identifier for scoping operations
|
|
18
20
|
* @param options - Optional server configuration
|
package/dist/server-factory.js
CHANGED
|
@@ -410,9 +410,9 @@ var init_config = __esm({
|
|
|
410
410
|
url: process.env.WEAVIATE_URL || "http://localhost:8080",
|
|
411
411
|
apiKey: process.env.WEAVIATE_API_KEY || ""
|
|
412
412
|
},
|
|
413
|
-
// OpenAI
|
|
413
|
+
// OpenAI (for embeddings)
|
|
414
414
|
openai: {
|
|
415
|
-
apiKey: process.env.OPENAI_APIKEY || ""
|
|
415
|
+
apiKey: process.env.OPENAI_EMBEDDINGS_API_KEY || process.env.OPENAI_APIKEY || ""
|
|
416
416
|
},
|
|
417
417
|
// Firebase (using firebase-admin-sdk-v8)
|
|
418
418
|
firebase: {
|
|
@@ -451,11 +451,30 @@ async function initWeaviateClient() {
|
|
|
451
451
|
if (client) {
|
|
452
452
|
return client;
|
|
453
453
|
}
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
454
|
+
const weaviateUrl = config.weaviate.url;
|
|
455
|
+
const isLocal = weaviateUrl.includes("localhost") || weaviateUrl.includes("127.0.0.1");
|
|
456
|
+
if (isLocal) {
|
|
457
|
+
console.log("[Weaviate] Connecting to local Weaviate:", weaviateUrl);
|
|
458
|
+
const localConfig = {
|
|
459
|
+
host: weaviateUrl.replace(/^https?:\/\//, "").split(":")[0],
|
|
460
|
+
port: weaviateUrl.includes(":") ? parseInt(weaviateUrl.split(":").pop() || "8080") : 8080,
|
|
461
|
+
scheme: weaviateUrl.startsWith("https") ? "https" : "http"
|
|
462
|
+
};
|
|
463
|
+
if (config.weaviate.apiKey) {
|
|
464
|
+
localConfig.authClientSecret = new weaviate.ApiKey(config.weaviate.apiKey);
|
|
465
|
+
}
|
|
466
|
+
if (config.openai.apiKey) {
|
|
467
|
+
localConfig.headers = { "X-OpenAI-Api-Key": config.openai.apiKey };
|
|
468
|
+
}
|
|
469
|
+
client = await weaviate.connectToLocal(localConfig);
|
|
470
|
+
} else {
|
|
471
|
+
console.log("[Weaviate] Connecting to remote Weaviate:", weaviateUrl);
|
|
472
|
+
client = await weaviate.connectToWeaviateCloud(weaviateUrl, {
|
|
473
|
+
authCredentials: config.weaviate.apiKey ? new weaviate.ApiKey(config.weaviate.apiKey) : void 0,
|
|
474
|
+
headers: config.openai.apiKey ? { "X-OpenAI-Api-Key": config.openai.apiKey } : void 0
|
|
475
|
+
});
|
|
476
|
+
}
|
|
477
|
+
console.log("[Weaviate] Client initialized successfully");
|
|
459
478
|
return client;
|
|
460
479
|
}
|
|
461
480
|
function getWeaviateClient() {
|
|
@@ -630,6 +649,10 @@ var logger = {
|
|
|
630
649
|
}
|
|
631
650
|
};
|
|
632
651
|
|
|
652
|
+
// src/server-factory.ts
|
|
653
|
+
init_client();
|
|
654
|
+
init_init();
|
|
655
|
+
|
|
633
656
|
// src/weaviate/schema.ts
|
|
634
657
|
init_client();
|
|
635
658
|
import weaviate2 from "weaviate-client";
|
|
@@ -2657,6 +2680,31 @@ async function handleDeleteRelationship(args, userId) {
|
|
|
2657
2680
|
}
|
|
2658
2681
|
|
|
2659
2682
|
// src/server-factory.ts
|
|
2683
|
+
var databasesInitialized = false;
|
|
2684
|
+
var initializationPromise = null;
|
|
2685
|
+
async function ensureDatabasesInitialized() {
|
|
2686
|
+
if (databasesInitialized) {
|
|
2687
|
+
return;
|
|
2688
|
+
}
|
|
2689
|
+
if (initializationPromise) {
|
|
2690
|
+
return initializationPromise;
|
|
2691
|
+
}
|
|
2692
|
+
initializationPromise = (async () => {
|
|
2693
|
+
try {
|
|
2694
|
+
logger.info("Initializing databases...");
|
|
2695
|
+
await initWeaviateClient();
|
|
2696
|
+
initFirestore();
|
|
2697
|
+
databasesInitialized = true;
|
|
2698
|
+
logger.info("Databases initialized successfully");
|
|
2699
|
+
} catch (error) {
|
|
2700
|
+
logger.error("Database initialization failed:", error);
|
|
2701
|
+
throw error;
|
|
2702
|
+
} finally {
|
|
2703
|
+
initializationPromise = null;
|
|
2704
|
+
}
|
|
2705
|
+
})();
|
|
2706
|
+
return initializationPromise;
|
|
2707
|
+
}
|
|
2660
2708
|
function createServer(accessToken, userId, options = {}) {
|
|
2661
2709
|
if (!accessToken) {
|
|
2662
2710
|
throw new Error("accessToken is required");
|
|
@@ -2665,10 +2713,13 @@ function createServer(accessToken, userId, options = {}) {
|
|
|
2665
2713
|
throw new Error("userId is required");
|
|
2666
2714
|
}
|
|
2667
2715
|
logger.debug("Creating server instance", { userId });
|
|
2716
|
+
ensureDatabasesInitialized().catch((error) => {
|
|
2717
|
+
logger.error("Failed to initialize databases:", error);
|
|
2718
|
+
});
|
|
2668
2719
|
const server = new Server(
|
|
2669
2720
|
{
|
|
2670
2721
|
name: options.name || "remember-mcp",
|
|
2671
|
-
version: options.version || "0.
|
|
2722
|
+
version: options.version || "0.2.0"
|
|
2672
2723
|
},
|
|
2673
2724
|
{
|
|
2674
2725
|
capabilities: {
|
package/dist/server.js
CHANGED
|
@@ -410,9 +410,9 @@ var config = {
|
|
|
410
410
|
url: process.env.WEAVIATE_URL || "http://localhost:8080",
|
|
411
411
|
apiKey: process.env.WEAVIATE_API_KEY || ""
|
|
412
412
|
},
|
|
413
|
-
// OpenAI
|
|
413
|
+
// OpenAI (for embeddings)
|
|
414
414
|
openai: {
|
|
415
|
-
apiKey: process.env.OPENAI_APIKEY || ""
|
|
415
|
+
apiKey: process.env.OPENAI_EMBEDDINGS_API_KEY || process.env.OPENAI_APIKEY || ""
|
|
416
416
|
},
|
|
417
417
|
// Firebase (using firebase-admin-sdk-v8)
|
|
418
418
|
firebase: {
|
|
@@ -433,7 +433,7 @@ var config = {
|
|
|
433
433
|
function validateConfig() {
|
|
434
434
|
const required = [
|
|
435
435
|
{ key: "WEAVIATE_URL", value: config.weaviate.url },
|
|
436
|
-
{ key: "
|
|
436
|
+
{ key: "OPENAI_EMBEDDINGS_API_KEY", value: config.openai.apiKey },
|
|
437
437
|
{ key: "FIREBASE_ADMIN_SERVICE_ACCOUNT_KEY", value: config.firebase.serviceAccount },
|
|
438
438
|
{ key: "FIREBASE_PROJECT_ID", value: config.firebase.projectId }
|
|
439
439
|
];
|
|
@@ -453,11 +453,30 @@ async function initWeaviateClient() {
|
|
|
453
453
|
if (client) {
|
|
454
454
|
return client;
|
|
455
455
|
}
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
456
|
+
const weaviateUrl = config.weaviate.url;
|
|
457
|
+
const isLocal = weaviateUrl.includes("localhost") || weaviateUrl.includes("127.0.0.1");
|
|
458
|
+
if (isLocal) {
|
|
459
|
+
console.log("[Weaviate] Connecting to local Weaviate:", weaviateUrl);
|
|
460
|
+
const localConfig = {
|
|
461
|
+
host: weaviateUrl.replace(/^https?:\/\//, "").split(":")[0],
|
|
462
|
+
port: weaviateUrl.includes(":") ? parseInt(weaviateUrl.split(":").pop() || "8080") : 8080,
|
|
463
|
+
scheme: weaviateUrl.startsWith("https") ? "https" : "http"
|
|
464
|
+
};
|
|
465
|
+
if (config.weaviate.apiKey) {
|
|
466
|
+
localConfig.authClientSecret = new weaviate.ApiKey(config.weaviate.apiKey);
|
|
467
|
+
}
|
|
468
|
+
if (config.openai.apiKey) {
|
|
469
|
+
localConfig.headers = { "X-OpenAI-Api-Key": config.openai.apiKey };
|
|
470
|
+
}
|
|
471
|
+
client = await weaviate.connectToLocal(localConfig);
|
|
472
|
+
} else {
|
|
473
|
+
console.log("[Weaviate] Connecting to remote Weaviate:", weaviateUrl);
|
|
474
|
+
client = await weaviate.connectToWeaviateCloud(weaviateUrl, {
|
|
475
|
+
authCredentials: config.weaviate.apiKey ? new weaviate.ApiKey(config.weaviate.apiKey) : void 0,
|
|
476
|
+
headers: config.openai.apiKey ? { "X-OpenAI-Api-Key": config.openai.apiKey } : void 0
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
console.log("[Weaviate] Client initialized successfully");
|
|
461
480
|
return client;
|
|
462
481
|
}
|
|
463
482
|
function getWeaviateClient() {
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { WeaviateClient } from 'weaviate-client';
|
|
2
2
|
/**
|
|
3
3
|
* Initialize Weaviate client
|
|
4
|
+
*
|
|
5
|
+
* Note: connectToWeaviateCloud() works for ANY remote Weaviate (cloud or self-hosted)
|
|
6
|
+
* Only use connectToLocal() for localhost development
|
|
4
7
|
*/
|
|
5
8
|
export declare function initWeaviateClient(): Promise<WeaviateClient>;
|
|
6
9
|
/**
|
package/package.json
CHANGED
package/src/config.ts
CHANGED
|
@@ -9,9 +9,9 @@ export const config = {
|
|
|
9
9
|
apiKey: process.env.WEAVIATE_API_KEY || '',
|
|
10
10
|
},
|
|
11
11
|
|
|
12
|
-
// OpenAI
|
|
12
|
+
// OpenAI (for embeddings)
|
|
13
13
|
openai: {
|
|
14
|
-
apiKey: process.env.OPENAI_APIKEY || '',
|
|
14
|
+
apiKey: process.env.OPENAI_EMBEDDINGS_API_KEY || process.env.OPENAI_APIKEY || '',
|
|
15
15
|
},
|
|
16
16
|
|
|
17
17
|
// Firebase (using firebase-admin-sdk-v8)
|
|
@@ -39,7 +39,7 @@ export const config = {
|
|
|
39
39
|
export function validateConfig(): void {
|
|
40
40
|
const required = [
|
|
41
41
|
{ key: 'WEAVIATE_URL', value: config.weaviate.url },
|
|
42
|
-
{ key: '
|
|
42
|
+
{ key: 'OPENAI_EMBEDDINGS_API_KEY', value: config.openai.apiKey },
|
|
43
43
|
{ key: 'FIREBASE_ADMIN_SERVICE_ACCOUNT_KEY', value: config.firebase.serviceAccount },
|
|
44
44
|
{ key: 'FIREBASE_PROJECT_ID', value: config.firebase.projectId },
|
|
45
45
|
];
|
package/src/server-factory.ts
CHANGED
|
@@ -11,6 +11,8 @@ import {
|
|
|
11
11
|
McpError,
|
|
12
12
|
} from '@modelcontextprotocol/sdk/types.js';
|
|
13
13
|
import { logger } from './utils/logger.js';
|
|
14
|
+
import { initWeaviateClient } from './weaviate/client.js';
|
|
15
|
+
import { initFirestore } from './firestore/init.js';
|
|
14
16
|
|
|
15
17
|
// Import memory tools
|
|
16
18
|
import { createMemoryTool, handleCreateMemory } from './tools/create-memory.js';
|
|
@@ -31,24 +33,62 @@ export interface ServerOptions {
|
|
|
31
33
|
version?: string;
|
|
32
34
|
}
|
|
33
35
|
|
|
36
|
+
// Global initialization flag to ensure databases are initialized once
|
|
37
|
+
let databasesInitialized = false;
|
|
38
|
+
let initializationPromise: Promise<void> | null = null;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Initialize databases (called once globally)
|
|
42
|
+
*/
|
|
43
|
+
async function ensureDatabasesInitialized(): Promise<void> {
|
|
44
|
+
if (databasesInitialized) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// If initialization is in progress, wait for it
|
|
49
|
+
if (initializationPromise) {
|
|
50
|
+
return initializationPromise;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Start initialization
|
|
54
|
+
initializationPromise = (async () => {
|
|
55
|
+
try {
|
|
56
|
+
logger.info('Initializing databases...');
|
|
57
|
+
await initWeaviateClient();
|
|
58
|
+
initFirestore();
|
|
59
|
+
databasesInitialized = true;
|
|
60
|
+
logger.info('Databases initialized successfully');
|
|
61
|
+
} catch (error) {
|
|
62
|
+
logger.error('Database initialization failed:', error);
|
|
63
|
+
throw error;
|
|
64
|
+
} finally {
|
|
65
|
+
initializationPromise = null;
|
|
66
|
+
}
|
|
67
|
+
})();
|
|
68
|
+
|
|
69
|
+
return initializationPromise;
|
|
70
|
+
}
|
|
71
|
+
|
|
34
72
|
/**
|
|
35
73
|
* Create a server instance for a specific user/tenant
|
|
36
|
-
*
|
|
74
|
+
*
|
|
37
75
|
* This factory function is compatible with mcp-auth wrapping pattern.
|
|
38
76
|
* It creates isolated server instances with no shared state.
|
|
39
|
-
*
|
|
77
|
+
*
|
|
78
|
+
* Note: Databases (Weaviate + Firestore) are initialized once globally on first call.
|
|
79
|
+
*
|
|
40
80
|
* @param accessToken - User's access token (reserved for future external APIs)
|
|
41
81
|
* @param userId - User identifier for scoping operations
|
|
42
82
|
* @param options - Optional server configuration
|
|
43
83
|
* @returns Configured MCP Server instance (not connected to transport)
|
|
44
|
-
*
|
|
84
|
+
*
|
|
45
85
|
* @example
|
|
46
86
|
* ```typescript
|
|
47
87
|
* // Direct usage
|
|
48
88
|
* const server = createServer('token', 'user123');
|
|
49
89
|
* const transport = new StdioServerTransport();
|
|
50
90
|
* await server.connect(transport);
|
|
51
|
-
*
|
|
91
|
+
*
|
|
52
92
|
* // With mcp-auth
|
|
53
93
|
* import { wrapServer } from '@prmichaelsen/mcp-auth';
|
|
54
94
|
* const wrapped = wrapServer({
|
|
@@ -75,11 +115,18 @@ export function createServer(
|
|
|
75
115
|
|
|
76
116
|
logger.debug('Creating server instance', { userId });
|
|
77
117
|
|
|
118
|
+
// Ensure databases are initialized (happens once globally)
|
|
119
|
+
// Note: This is synchronous to match the Server return type
|
|
120
|
+
// The actual initialization happens on first tool call
|
|
121
|
+
ensureDatabasesInitialized().catch(error => {
|
|
122
|
+
logger.error('Failed to initialize databases:', error);
|
|
123
|
+
});
|
|
124
|
+
|
|
78
125
|
// Create MCP server
|
|
79
126
|
const server = new Server(
|
|
80
127
|
{
|
|
81
128
|
name: options.name || 'remember-mcp',
|
|
82
|
-
version: options.version || '0.
|
|
129
|
+
version: options.version || '0.2.0',
|
|
83
130
|
},
|
|
84
131
|
{
|
|
85
132
|
capabilities: {
|
package/src/weaviate/client.ts
CHANGED
|
@@ -5,23 +5,56 @@ let client: WeaviateClient | null = null;
|
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Initialize Weaviate client
|
|
8
|
+
*
|
|
9
|
+
* Note: connectToWeaviateCloud() works for ANY remote Weaviate (cloud or self-hosted)
|
|
10
|
+
* Only use connectToLocal() for localhost development
|
|
8
11
|
*/
|
|
9
12
|
export async function initWeaviateClient(): Promise<WeaviateClient> {
|
|
10
13
|
if (client) {
|
|
11
14
|
return client;
|
|
12
15
|
}
|
|
13
16
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
17
|
+
const weaviateUrl = config.weaviate.url;
|
|
18
|
+
|
|
19
|
+
// Check if this is localhost (use connectToLocal)
|
|
20
|
+
const isLocal = weaviateUrl.includes('localhost') ||
|
|
21
|
+
weaviateUrl.includes('127.0.0.1');
|
|
22
|
+
|
|
23
|
+
// Use appropriate connection method
|
|
24
|
+
if (isLocal) {
|
|
25
|
+
console.log('[Weaviate] Connecting to local Weaviate:', weaviateUrl);
|
|
26
|
+
// connectToLocal() for localhost only
|
|
27
|
+
const localConfig: any = {
|
|
28
|
+
host: weaviateUrl.replace(/^https?:\/\//, '').split(':')[0],
|
|
29
|
+
port: weaviateUrl.includes(':')
|
|
30
|
+
? parseInt(weaviateUrl.split(':').pop() || '8080')
|
|
31
|
+
: 8080,
|
|
32
|
+
scheme: weaviateUrl.startsWith('https') ? 'https' : 'http',
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
if (config.weaviate.apiKey) {
|
|
36
|
+
localConfig.authClientSecret = new weaviate.ApiKey(config.weaviate.apiKey);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (config.openai.apiKey) {
|
|
40
|
+
localConfig.headers = { 'X-OpenAI-Api-Key': config.openai.apiKey };
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
client = await weaviate.connectToLocal(localConfig);
|
|
44
|
+
} else {
|
|
45
|
+
// Use connectToWeaviateCloud() for ALL remote instances (cloud or self-hosted)
|
|
46
|
+
console.log('[Weaviate] Connecting to remote Weaviate:', weaviateUrl);
|
|
47
|
+
client = await weaviate.connectToWeaviateCloud(weaviateUrl, {
|
|
48
|
+
authCredentials: config.weaviate.apiKey
|
|
49
|
+
? new weaviate.ApiKey(config.weaviate.apiKey)
|
|
50
|
+
: undefined,
|
|
51
|
+
headers: config.openai.apiKey
|
|
52
|
+
? { 'X-OpenAI-Api-Key': config.openai.apiKey }
|
|
53
|
+
: undefined,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
23
56
|
|
|
24
|
-
console.log('[Weaviate] Client initialized');
|
|
57
|
+
console.log('[Weaviate] Client initialized successfully');
|
|
25
58
|
return client;
|
|
26
59
|
}
|
|
27
60
|
|