@ekkos/mcp-server 2.0.2 → 2.0.4

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/index.d.ts CHANGED
@@ -2,8 +2,11 @@
2
2
  /**
3
3
  * @ekkos/mcp-server
4
4
  *
5
- * Simple stdio proxy to ekkOS cloud MCP gateway.
6
- * This creates a local MCP server that forwards all requests to https://mcp.ekkos.dev
5
+ * Local-first MCP server for ekkOS cloud memory.
6
+ * - Caches patterns + directives locally for <5ms search
7
+ * - Falls back to cloud gateway for full results
8
+ * - Queues writes when offline, flushes on reconnect
9
+ * - Auto-discovers API key from ~/.ekkos/config.json
7
10
  */
8
11
  export {};
9
12
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;GAKG"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;;;;GAQG"}
package/dist/index.js CHANGED
@@ -2,8 +2,11 @@
2
2
  /**
3
3
  * @ekkos/mcp-server
4
4
  *
5
- * Simple stdio proxy to ekkOS cloud MCP gateway.
6
- * This creates a local MCP server that forwards all requests to https://mcp.ekkos.dev
5
+ * Local-first MCP server for ekkOS cloud memory.
6
+ * - Caches patterns + directives locally for <5ms search
7
+ * - Falls back to cloud gateway for full results
8
+ * - Queues writes when offline, flushes on reconnect
9
+ * - Auto-discovers API key from ~/.ekkos/config.json
7
10
  */
8
11
  // Sentry must be imported and initialized before other imports
9
12
  import * as Sentry from '@sentry/node';
@@ -19,18 +22,173 @@ if (process.env.SENTRY_DSN) {
19
22
  import { Server } from '@modelcontextprotocol/sdk/server/index.js';
20
23
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
21
24
  import { ListToolsRequestSchema, CallToolRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema } from '@modelcontextprotocol/sdk/types.js';
22
- // Configuration
23
- const EKKOS_API_KEY = process.env.EKKOS_API_KEY || '';
25
+ import { readFileSync, existsSync, writeFileSync, mkdirSync } from 'fs';
26
+ import { join } from 'path';
27
+ import { homedir } from 'os';
28
+ import { loadCacheFromDisk, warmCache, searchLocal, getDirectives, invalidateCache, isCacheStale, startPeriodicRefresh, getCacheStats, } from './local-cache.js';
29
+ import { isWriteTool, queueWrite, flushQueue, getPendingCount, } from './offline-queue.js';
30
+ // ═══════════════════════════════════════════════════════════════════════════
31
+ // CONFIGURATION — resolve API key from env, then ~/.ekkos/config.json
32
+ // ═══════════════════════════════════════════════════════════════════════════
33
+ function resolveApiKey() {
34
+ // Priority 1: Environment variable
35
+ if (process.env.EKKOS_API_KEY) {
36
+ return process.env.EKKOS_API_KEY;
37
+ }
38
+ // Priority 2: ~/.ekkos/config.json (from prior `ekkos init`)
39
+ try {
40
+ const configPath = join(homedir(), '.ekkos', 'config.json');
41
+ if (existsSync(configPath)) {
42
+ const config = JSON.parse(readFileSync(configPath, 'utf-8'));
43
+ if (config.apiKey) {
44
+ console.error('[ekkOS] Using API key from ~/.ekkos/config.json');
45
+ return config.apiKey;
46
+ }
47
+ }
48
+ }
49
+ catch {
50
+ // Config unreadable — fall through to degraded mode
51
+ }
52
+ // No key found — caller will enable degraded mode
53
+ return null;
54
+ }
55
+ const EKKOS_API_KEY = resolveApiKey();
56
+ /**
57
+ * Degraded mode: no API key available.
58
+ * Search returns local cache only. Writes are queued to offline queue.
59
+ * All tools still register normally so Claude sees no missing tools.
60
+ */
61
+ const degradedMode = EKKOS_API_KEY === null;
24
62
  const EKKOS_USER_ID = process.env.EKKOS_USER_ID || '';
25
- const EKKOS_MCP_URL = process.env.EKKOS_MCP_URL || 'https://api.ekkos.dev/api/v1/mcp';
63
+ const EKKOS_MCP_URL = process.env.EKKOS_MCP_URL || 'https://mcp.ekkos.dev/api/v1/mcp';
26
64
  const DEBUG = process.env.EKKOS_DEBUG === 'true';
27
- if (!EKKOS_API_KEY) {
28
- console.error('[ekkOS] ERROR: EKKOS_API_KEY environment variable is required');
29
- console.error('[ekkOS] Get your API key at https://platform.ekkos.dev/dashboard/settings/api-keys');
30
- process.exit(1);
65
+ // ═══════════════════════════════════════════════════════════════════════════
66
+ // SESSION METRICS written to ~/.ekkos/session-metrics.json after each tool call
67
+ // ═══════════════════════════════════════════════════════════════════════════
68
+ const METRICS_DIR = join(homedir(), '.ekkos');
69
+ const METRICS_FILE = join(METRICS_DIR, 'session-metrics.json');
70
+ // In-process counters — reset each MCP server process lifetime (= one Claude session)
71
+ const sessionMetrics = {
72
+ session_id: `mcp-${Date.now()}`,
73
+ session_name: '',
74
+ turn: 0,
75
+ started_at: new Date().toISOString(),
76
+ updated_at: new Date().toISOString(),
77
+ tool_calls: 0,
78
+ patterns_recalled: 0,
79
+ patterns_forged: 0,
80
+ directives_active: 0,
81
+ cache_backend: 'json',
82
+ cache_patterns: 0,
83
+ tokens_in: 0,
84
+ tokens_out: 0,
85
+ };
86
+ /** Fire-and-forget write of metrics to disk. Never throws. */
87
+ function writeMetrics() {
88
+ try {
89
+ mkdirSync(METRICS_DIR, { recursive: true });
90
+ const stats = getCacheStats();
91
+ sessionMetrics.updated_at = new Date().toISOString();
92
+ sessionMetrics.cache_backend = stats.backend;
93
+ sessionMetrics.cache_patterns = stats.patterns;
94
+ sessionMetrics.directives_active = stats.directives;
95
+ writeFileSync(METRICS_FILE, JSON.stringify(sessionMetrics, null, 2), 'utf-8');
96
+ }
97
+ catch {
98
+ // best-effort — never block the tool response
99
+ }
100
+ }
101
+ // ═══════════════════════════════════════════════════════════════════════════
102
+ // CIRCUIT BREAKER — fast-fail when cloud is unreachable
103
+ // ═══════════════════════════════════════════════════════════════════════════
104
+ let circuitFailures = 0;
105
+ let circuitOpenUntil = 0;
106
+ const CIRCUIT_THRESHOLD = 3; // failures before opening
107
+ const CIRCUIT_RESET_MS = 60_000; // 60s before half-open retry
108
+ const GATEWAY_TIMEOUT_MS = 8_000; // 8s request timeout
109
+ function isCircuitOpen() {
110
+ if (circuitFailures < CIRCUIT_THRESHOLD)
111
+ return false;
112
+ if (Date.now() > circuitOpenUntil) {
113
+ // Half-open: allow one request through
114
+ return false;
115
+ }
116
+ return true;
117
+ }
118
+ function recordSuccess() {
119
+ circuitFailures = 0;
120
+ circuitOpenUntil = 0;
31
121
  }
32
- // Simple HTTP client for MCP gateway
122
+ function recordFailure() {
123
+ circuitFailures++;
124
+ if (circuitFailures >= CIRCUIT_THRESHOLD) {
125
+ circuitOpenUntil = Date.now() + CIRCUIT_RESET_MS;
126
+ console.error(`[ekkOS:circuit] OPEN — ${circuitFailures} failures, retrying in ${CIRCUIT_RESET_MS / 1000}s`);
127
+ }
128
+ }
129
+ // ═══════════════════════════════════════════════════════════════════════════
130
+ // RESULT SLIMMING — strip verbose _ekkos_* metadata from gateway responses
131
+ // These fields (_ekkos_stream_message, _ekkos_context, _ekkos_pattern_contract,
132
+ // _ekkos_acknowledgment_*) are designed for Cursor's sidebar UI. When returned
133
+ // via MCP stdio to CLI clients (Gemini, Claude Code) the model sees them as
134
+ // raw tool output and parrots them back, producing noisy verbose responses.
135
+ // ═══════════════════════════════════════════════════════════════════════════
136
+ const VERBOSE_EKKOS_KEYS = new Set([
137
+ '_ekkos_stream_message',
138
+ '_ekkos_context',
139
+ '_ekkos_pattern_contract',
140
+ '_ekkos_acknowledgment_required',
141
+ '_ekkos_acknowledgment_instruction',
142
+ '_ekkos_enforcement',
143
+ '_ekkos_session_summary',
144
+ ]);
145
+ /**
146
+ * Strip verbose _ekkos_* fields from a gateway result.
147
+ * Keeps compact fields like _ekkos_patterns and _ekkos_auto_retrieved.
148
+ */
149
+ function slimGatewayResult(data) {
150
+ if (!data || typeof data !== 'object')
151
+ return data;
152
+ // If result has content[].text with JSON, parse → strip → re-serialize
153
+ if (data.result && typeof data.result === 'object') {
154
+ for (const key of VERBOSE_EKKOS_KEYS) {
155
+ delete data.result[key];
156
+ }
157
+ }
158
+ // Also strip from top-level content array (MCP format)
159
+ if (data.content && Array.isArray(data.content)) {
160
+ for (const part of data.content) {
161
+ if (part.type === 'text' && typeof part.text === 'string') {
162
+ try {
163
+ const parsed = JSON.parse(part.text);
164
+ if (parsed && typeof parsed === 'object') {
165
+ let changed = false;
166
+ for (const key of VERBOSE_EKKOS_KEYS) {
167
+ if (key in parsed) {
168
+ delete parsed[key];
169
+ changed = true;
170
+ }
171
+ }
172
+ if (changed) {
173
+ part.text = JSON.stringify(parsed);
174
+ }
175
+ }
176
+ }
177
+ catch {
178
+ // Not JSON — leave as-is
179
+ }
180
+ }
181
+ }
182
+ }
183
+ return data;
184
+ }
185
+ // ═══════════════════════════════════════════════════════════════════════════
186
+ // GATEWAY CLIENT — HTTP calls to cloud MCP gateway
187
+ // ═══════════════════════════════════════════════════════════════════════════
33
188
  async function callGateway(endpoint, method, params) {
189
+ if (degradedMode) {
190
+ throw new Error('ekkOS running in cache-only mode — no API key');
191
+ }
34
192
  const url = `${EKKOS_MCP_URL}/${endpoint}`;
35
193
  const headers = {
36
194
  'Content-Type': 'application/json',
@@ -42,24 +200,155 @@ async function callGateway(endpoint, method, params) {
42
200
  if (DEBUG) {
43
201
  console.error(`[ekkOS] → ${method} ${endpoint}`);
44
202
  }
45
- const response = await fetch(url, {
46
- method: 'POST',
47
- headers,
48
- body: JSON.stringify({ method, params: params || {} }),
49
- });
50
- if (!response.ok) {
51
- throw new Error(`HTTP ${response.status}: ${response.statusText}`);
203
+ const controller = new AbortController();
204
+ const timeout = setTimeout(() => controller.abort(), GATEWAY_TIMEOUT_MS);
205
+ try {
206
+ const response = await fetch(url, {
207
+ method: 'POST',
208
+ headers,
209
+ body: JSON.stringify({ method, params: params || {} }),
210
+ signal: controller.signal,
211
+ });
212
+ if (!response.ok) {
213
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
214
+ }
215
+ const data = await response.json();
216
+ if (DEBUG) {
217
+ console.error(`[ekkOS] ← ${method} OK`);
218
+ }
219
+ recordSuccess();
220
+ return slimGatewayResult(data);
52
221
  }
53
- const data = await response.json();
54
- if (DEBUG) {
55
- console.error(`[ekkOS] ← ${method} OK`);
222
+ catch (err) {
223
+ recordFailure();
224
+ throw err;
225
+ }
226
+ finally {
227
+ clearTimeout(timeout);
56
228
  }
57
- return data;
58
229
  }
59
- // Create MCP server
230
+ /**
231
+ * Call gateway with offline fallback.
232
+ * For write tools: queues when offline.
233
+ * For read tools: returns null when offline (caller handles fallback).
234
+ */
235
+ async function callGatewayWithFallback(endpoint, method, params, toolName) {
236
+ // If circuit is open, don't even try
237
+ if (isCircuitOpen()) {
238
+ if (toolName && isWriteTool(toolName)) {
239
+ queueWrite(toolName, params?.arguments || {});
240
+ return {
241
+ content: [{ type: 'text', text: JSON.stringify({ _offline: true, _queued: true, message: 'Queued for sync when connection restores' }) }],
242
+ };
243
+ }
244
+ return null; // Caller handles fallback
245
+ }
246
+ try {
247
+ const result = await callGateway(endpoint, method, params);
248
+ // Connectivity restored — flush any pending writes in background
249
+ const pendingCount = getPendingCount();
250
+ if (pendingCount > 0) {
251
+ flushQueue(callGateway).catch(() => { });
252
+ }
253
+ return result;
254
+ }
255
+ catch {
256
+ if (toolName && isWriteTool(toolName)) {
257
+ queueWrite(toolName, params?.arguments || {});
258
+ return {
259
+ content: [{ type: 'text', text: JSON.stringify({ _offline: true, _queued: true, message: 'Queued for sync when connection restores' }) }],
260
+ };
261
+ }
262
+ return null; // Caller handles fallback
263
+ }
264
+ }
265
+ // ═══════════════════════════════════════════════════════════════════════════
266
+ // LOCAL-FIRST SEARCH — check cache before cloud
267
+ // ═══════════════════════════════════════════════════════════════════════════
268
+ /**
269
+ * Handle ekkOS_Search with local-first strategy:
270
+ * 1. Search local cache (<5ms)
271
+ * 2. If cache has results, return them immediately
272
+ * 3. Background: also query cloud for freshness
273
+ * 4. If cache miss or stale, fall through to cloud
274
+ */
275
+ async function handleSearchLocally(args) {
276
+ const query = args.query || '';
277
+ const limit = args.limit || 5;
278
+ const start = Date.now();
279
+ // Try local cache first
280
+ const localPatterns = searchLocal(query, limit);
281
+ const localDirectives = getDirectives();
282
+ const localLatency = Date.now() - start;
283
+ if (localPatterns.length > 0 || localDirectives.length > 0) {
284
+ // Build a response that matches the cloud format
285
+ const localResult = {
286
+ content: [{
287
+ type: 'text',
288
+ text: JSON.stringify({
289
+ patterns: localPatterns.map(p => ({
290
+ id: p.id,
291
+ title: p.title,
292
+ similarity: 0.75, // Approximate — local search doesn't compute embeddings
293
+ success_rate: p.success_rate,
294
+ applied_count: p.applied_count,
295
+ tags: p.tags?.slice(0, 3),
296
+ })),
297
+ directives: localDirectives,
298
+ total: localPatterns.length + localDirectives.length,
299
+ _cache: 'local',
300
+ _cache_latency_ms: localLatency,
301
+ }),
302
+ }],
303
+ _ekkos_status: `[ekkOS_RETRIEVE] ⚡ Local: ${localPatterns.length} patterns, ${localDirectives.length} directives (${localLatency}ms)`,
304
+ };
305
+ // If cache is stale, trigger background refresh (don't block)
306
+ if (isCacheStale()) {
307
+ warmCache(callGateway, EKKOS_USER_ID).catch(() => { });
308
+ }
309
+ // Also query cloud in background to update cache (don't await)
310
+ callGatewayWithFallback('tools/call', 'tools/call', {
311
+ name: 'ekkOS_Search',
312
+ arguments: args,
313
+ }).then(cloudResult => {
314
+ if (cloudResult) {
315
+ // Update cache with fresh cloud results
316
+ warmCache(callGateway, EKKOS_USER_ID).catch(() => { });
317
+ }
318
+ }).catch(() => { });
319
+ return localResult;
320
+ }
321
+ // No local results — fall through to cloud
322
+ const cloudResult = await callGatewayWithFallback('tools/call', 'tools/call', {
323
+ name: 'ekkOS_Search',
324
+ arguments: args,
325
+ }, 'ekkOS_Search');
326
+ if (cloudResult) {
327
+ // Trigger cache update with fresh data
328
+ warmCache(callGateway, EKKOS_USER_ID).catch(() => { });
329
+ return cloudResult;
330
+ }
331
+ // Both local and cloud failed
332
+ return {
333
+ content: [{
334
+ type: 'text',
335
+ text: JSON.stringify({
336
+ patterns: [],
337
+ directives: [],
338
+ total: 0,
339
+ _cache: 'miss',
340
+ _offline: true,
341
+ message: 'No cached patterns and cloud unreachable',
342
+ }),
343
+ }],
344
+ };
345
+ }
346
+ // ═══════════════════════════════════════════════════════════════════════════
347
+ // MCP SERVER
348
+ // ═══════════════════════════════════════════════════════════════════════════
60
349
  const server = new Server({
61
350
  name: 'ekkos-memory',
62
- version: '1.0.0',
351
+ version: '1.1.0',
63
352
  }, {
64
353
  capabilities: {
65
354
  tools: {},
@@ -67,26 +356,107 @@ const server = new Server({
67
356
  prompts: {},
68
357
  },
69
358
  });
70
- // List tools - proxy to gateway
359
+ // Cache-invalidating tools after these succeed, refresh local cache
360
+ const CACHE_INVALIDATING_TOOLS = new Set([
361
+ 'ekkOS_Forge',
362
+ 'ekkOS_Directive',
363
+ 'ekkOS_UpdateDirective',
364
+ 'ekkOS_DeleteDirective',
365
+ ]);
366
+ // List tools - proxy to gateway (or return cached list in degraded mode)
71
367
  server.setRequestHandler(ListToolsRequestSchema, async () => {
368
+ if (degradedMode) {
369
+ // In cache-only mode we have no cloud connection to fetch the full tool
370
+ // definition list. Return a minimal stub so Claude can still call tools
371
+ // (handlers below respond gracefully); the real list is fetched once the
372
+ // user runs `ekkos init` and restarts the server.
373
+ return { tools: [] };
374
+ }
72
375
  const result = await callGateway('tools/list', 'tools/list');
73
376
  return result;
74
377
  });
75
- // Call tool - proxy to gateway
378
+ // Call tool - local-first for search, gateway for everything else
76
379
  server.setRequestHandler(CallToolRequestSchema, async (request) => {
77
- const result = await callGateway('tools/call', 'tools/call', {
78
- name: request.params.name,
79
- arguments: request.params.arguments,
80
- });
81
- return result;
380
+ const toolName = request.params.name;
381
+ const toolArgs = request.params.arguments || {};
382
+ // ── Increment global tool-call counter ──────────────────────────────────
383
+ sessionMetrics.tool_calls++;
384
+ // Extract session_name from ekkOS_Search / ekkOS_Forge args if present
385
+ const argsAny = toolArgs;
386
+ if (argsAny.session_name && typeof argsAny.session_name === 'string' && !sessionMetrics.session_name) {
387
+ sessionMetrics.session_name = argsAny.session_name;
388
+ }
389
+ // LOCAL-FIRST: ekkOS_Search uses local cache
390
+ if (toolName === 'ekkOS_Search') {
391
+ const result = await handleSearchLocally(argsAny);
392
+ // Count patterns returned as "recalled" — parse result text if available
393
+ try {
394
+ const text = result?.content?.[0]?.text;
395
+ if (text) {
396
+ const parsed = JSON.parse(text);
397
+ sessionMetrics.patterns_recalled += (parsed.patterns?.length ?? 0);
398
+ // Infer turn from total search calls (each search ≈ one turn)
399
+ sessionMetrics.turn = sessionMetrics.patterns_recalled > 0
400
+ ? Math.max(sessionMetrics.turn, Math.ceil(sessionMetrics.tool_calls / 2))
401
+ : sessionMetrics.turn;
402
+ }
403
+ }
404
+ catch { /* ignore parse errors */ }
405
+ writeMetrics();
406
+ return result;
407
+ }
408
+ // WRITE TOOLS: use fallback with offline queue
409
+ if (isWriteTool(toolName)) {
410
+ const result = await callGatewayWithFallback('tools/call', 'tools/call', {
411
+ name: toolName,
412
+ arguments: toolArgs,
413
+ }, toolName);
414
+ // Invalidate cache after successful writes
415
+ if (result && CACHE_INVALIDATING_TOOLS.has(toolName)) {
416
+ invalidateCache();
417
+ warmCache(callGateway, EKKOS_USER_ID).catch(() => { });
418
+ }
419
+ // Track forged patterns
420
+ if (toolName === 'ekkOS_Forge' && result && !result.content?.[0]?.text?.includes('_offline')) {
421
+ sessionMetrics.patterns_forged++;
422
+ }
423
+ writeMetrics();
424
+ return result || {
425
+ content: [{ type: 'text', text: JSON.stringify({ _offline: true, _queued: true }) }],
426
+ };
427
+ }
428
+ // ALL OTHER TOOLS: proxy to cloud with graceful fallback
429
+ const result = await callGatewayWithFallback('tools/call', 'tools/call', {
430
+ name: toolName,
431
+ arguments: toolArgs,
432
+ }, toolName);
433
+ writeMetrics();
434
+ if (result)
435
+ return result;
436
+ // Offline fallback for read tools
437
+ return {
438
+ content: [{
439
+ type: 'text',
440
+ text: JSON.stringify({
441
+ _offline: true,
442
+ message: `Cloud unreachable — ${toolName} requires connectivity`,
443
+ cache_stats: getCacheStats(),
444
+ }),
445
+ }],
446
+ };
82
447
  });
83
448
  // List resources - proxy to gateway
84
449
  server.setRequestHandler(ListResourcesRequestSchema, async () => {
450
+ if (degradedMode)
451
+ return { resources: [] };
85
452
  const result = await callGateway('resources/list', 'resources/list');
86
453
  return result;
87
454
  });
88
455
  // Read resource - proxy to gateway
89
456
  server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
457
+ if (degradedMode) {
458
+ return { contents: [{ uri: request.params.uri, text: 'ekkOS running in cache-only mode. Run `ekkos init` to connect.' }] };
459
+ }
90
460
  const result = await callGateway('resources/read', 'resources/read', {
91
461
  uri: request.params.uri,
92
462
  });
@@ -94,11 +464,16 @@ server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
94
464
  });
95
465
  // List prompts - proxy to gateway
96
466
  server.setRequestHandler(ListPromptsRequestSchema, async () => {
467
+ if (degradedMode)
468
+ return { prompts: [] };
97
469
  const result = await callGateway('prompts/list', 'prompts/list');
98
470
  return result;
99
471
  });
100
472
  // Get prompt - proxy to gateway
101
473
  server.setRequestHandler(GetPromptRequestSchema, async (request) => {
474
+ if (degradedMode) {
475
+ return { description: 'ekkOS cache-only mode', messages: [] };
476
+ }
102
477
  const result = await callGateway('prompts/get', 'prompts/get', {
103
478
  name: request.params.name,
104
479
  arguments: request.params.arguments,
@@ -117,17 +492,42 @@ process.on('SIGINT', async () => {
117
492
  await server.close();
118
493
  process.exit(0);
119
494
  });
120
- // Start server
495
+ // ═══════════════════════════════════════════════════════════════════════════
496
+ // STARTUP
497
+ // ═══════════════════════════════════════════════════════════════════════════
121
498
  async function main() {
499
+ // Step 1: Load cache from disk (instant, <1ms)
500
+ const diskCache = loadCacheFromDisk();
501
+ if (diskCache.patterns > 0 || diskCache.directives > 0) {
502
+ console.error(`[ekkOS] Cache loaded: ${diskCache.patterns} patterns, ${diskCache.directives} directives`);
503
+ }
504
+ // Degraded mode: no API key — run cache-only, skip all cloud steps
505
+ if (degradedMode) {
506
+ console.error('[ekkOS] WARNING: ekkOS running in cache-only mode. Run `ekkos init` to connect.');
507
+ const transport = new StdioServerTransport();
508
+ await server.connect(transport);
509
+ return;
510
+ }
511
+ // Step 2: Flush any pending offline writes (background)
512
+ const pendingCount = getPendingCount();
513
+ if (pendingCount > 0) {
514
+ console.error(`[ekkOS] Flushing ${pendingCount} pending offline writes...`);
515
+ flushQueue(callGateway).catch(() => { });
516
+ }
517
+ // Step 3: Start MCP transport
122
518
  if (DEBUG) {
123
- console.error('[ekkOS] Starting MCP proxy to ekkOS Memory...');
519
+ console.error('[ekkOS] Starting ekkOS Memory MCP Server...');
124
520
  console.error(`[ekkOS] Gateway: ${EKKOS_MCP_URL}`);
125
521
  console.error(`[ekkOS] User ID: ${EKKOS_USER_ID || '(not set)'}`);
126
522
  }
127
523
  const transport = new StdioServerTransport();
128
524
  await server.connect(transport);
525
+ // Step 4: Warm cache from cloud (non-blocking background task)
526
+ warmCache(callGateway, EKKOS_USER_ID).catch(() => { });
527
+ // Step 5: Start periodic cache refresh (every 5 min)
528
+ startPeriodicRefresh(callGateway, EKKOS_USER_ID);
129
529
  if (DEBUG) {
130
- console.error('[ekkOS] ✓ Ready! Your AI can now access ekkOS memory.');
530
+ console.error('[ekkOS] ✓ Ready! Local-first memory with cloud sync.');
131
531
  }
132
532
  }
133
533
  main().catch((error) => {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}