@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.
@@ -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
@@ -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
- client = await weaviate.connectToWeaviateCloud(config.weaviate.url, {
455
- authCredentials: config.weaviate.apiKey ? new weaviate.ApiKey(config.weaviate.apiKey) : void 0,
456
- headers: config.openai.apiKey ? { "X-OpenAI-Api-Key": config.openai.apiKey } : void 0
457
- });
458
- console.log("[Weaviate] Client initialized");
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.1.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: "OPENAI_APIKEY", value: config.openai.apiKey },
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
- client = await weaviate.connectToWeaviateCloud(config.weaviate.url, {
457
- authCredentials: config.weaviate.apiKey ? new weaviate.ApiKey(config.weaviate.apiKey) : void 0,
458
- headers: config.openai.apiKey ? { "X-OpenAI-Api-Key": config.openai.apiKey } : void 0
459
- });
460
- console.log("[Weaviate] Client initialized");
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prmichaelsen/remember-mcp",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "Multi-tenant memory system MCP server with vector search and relationships",
5
5
  "main": "dist/server.js",
6
6
  "type": "module",
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: 'OPENAI_APIKEY', value: config.openai.apiKey },
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
  ];
@@ -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.1.0',
129
+ version: options.version || '0.2.0',
83
130
  },
84
131
  {
85
132
  capabilities: {
@@ -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
- // Weaviate v3 client initialization
15
- client = await weaviate.connectToWeaviateCloud(config.weaviate.url, {
16
- authCredentials: config.weaviate.apiKey
17
- ? new weaviate.ApiKey(config.weaviate.apiKey)
18
- : undefined,
19
- headers: config.openai.apiKey
20
- ? { 'X-OpenAI-Api-Key': config.openai.apiKey }
21
- : undefined,
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