@ekkos/mcp-server 2.0.3 → 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 +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +432 -32
- package/dist/index.js.map +1 -1
- package/dist/local-cache.d.ts +90 -0
- package/dist/local-cache.d.ts.map +1 -0
- package/dist/local-cache.js +525 -0
- package/dist/local-cache.js.map +1 -0
- package/dist/offline-queue.d.ts +25 -0
- package/dist/offline-queue.d.ts.map +1 -0
- package/dist/offline-queue.js +118 -0
- package/dist/offline-queue.js.map +1 -0
- package/ekkOS_CONTEXT.md +62 -0
- package/package.json +5 -1
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Offline Write Queue for ekkOS MCP Server
|
|
3
|
+
*
|
|
4
|
+
* When the cloud gateway is unreachable, queues write operations
|
|
5
|
+
* (Forge, Track, Outcome, Directive) to a local JSONL file.
|
|
6
|
+
* Flushes the queue when connectivity is restored.
|
|
7
|
+
*/
|
|
8
|
+
import { appendFileSync, readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';
|
|
9
|
+
import { join } from 'path';
|
|
10
|
+
import { homedir } from 'os';
|
|
11
|
+
const CACHE_DIR = join(homedir(), '.ekkos', 'cache');
|
|
12
|
+
const QUEUE_FILE = join(CACHE_DIR, 'pending-writes.jsonl');
|
|
13
|
+
// Tools that perform writes and should be queued when offline
|
|
14
|
+
const WRITE_TOOLS = new Set([
|
|
15
|
+
'ekkOS_Forge',
|
|
16
|
+
'ekkOS_Track',
|
|
17
|
+
'ekkOS_Outcome',
|
|
18
|
+
'ekkOS_Directive',
|
|
19
|
+
'ekkOS_UpdateDirective',
|
|
20
|
+
'ekkOS_DeleteDirective',
|
|
21
|
+
'ekkOS_Capture',
|
|
22
|
+
'ekkOS_StoreSecret',
|
|
23
|
+
'ekkOS_RotateSecret',
|
|
24
|
+
'ekkOS_DeleteSecret',
|
|
25
|
+
]);
|
|
26
|
+
/**
|
|
27
|
+
* Check if a tool is a write operation that can be queued
|
|
28
|
+
*/
|
|
29
|
+
export function isWriteTool(toolName) {
|
|
30
|
+
return WRITE_TOOLS.has(toolName);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Queue a write operation for later execution
|
|
34
|
+
*/
|
|
35
|
+
export function queueWrite(toolName, args) {
|
|
36
|
+
try {
|
|
37
|
+
if (!existsSync(CACHE_DIR)) {
|
|
38
|
+
mkdirSync(CACHE_DIR, { recursive: true });
|
|
39
|
+
}
|
|
40
|
+
const entry = {
|
|
41
|
+
timestamp: new Date().toISOString(),
|
|
42
|
+
toolName,
|
|
43
|
+
arguments: args,
|
|
44
|
+
};
|
|
45
|
+
appendFileSync(QUEUE_FILE, JSON.stringify(entry) + '\n');
|
|
46
|
+
console.error(`[ekkOS:offline] Queued ${toolName} for later sync`);
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
console.error('[ekkOS:offline] Failed to queue write:', err);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Flush all pending writes to the cloud gateway
|
|
54
|
+
* Returns the number of successfully flushed writes
|
|
55
|
+
*/
|
|
56
|
+
export async function flushQueue(callGateway) {
|
|
57
|
+
if (!existsSync(QUEUE_FILE))
|
|
58
|
+
return 0;
|
|
59
|
+
let lines;
|
|
60
|
+
try {
|
|
61
|
+
const raw = readFileSync(QUEUE_FILE, 'utf-8').trim();
|
|
62
|
+
if (!raw)
|
|
63
|
+
return 0;
|
|
64
|
+
lines = raw.split('\n');
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return 0;
|
|
68
|
+
}
|
|
69
|
+
let flushed = 0;
|
|
70
|
+
const failed = [];
|
|
71
|
+
for (const line of lines) {
|
|
72
|
+
try {
|
|
73
|
+
const entry = JSON.parse(line);
|
|
74
|
+
await callGateway('tools/call', 'tools/call', {
|
|
75
|
+
name: entry.toolName,
|
|
76
|
+
arguments: entry.arguments,
|
|
77
|
+
});
|
|
78
|
+
flushed++;
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
// Keep failed writes for next flush attempt
|
|
82
|
+
failed.push(line);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// Rewrite queue with only failed writes
|
|
86
|
+
try {
|
|
87
|
+
if (failed.length > 0) {
|
|
88
|
+
writeFileSync(QUEUE_FILE, failed.join('\n') + '\n');
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
writeFileSync(QUEUE_FILE, '');
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
// Best effort cleanup
|
|
96
|
+
}
|
|
97
|
+
if (flushed > 0) {
|
|
98
|
+
console.error(`[ekkOS:offline] Flushed ${flushed} queued writes (${failed.length} remaining)`);
|
|
99
|
+
}
|
|
100
|
+
return flushed;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Get count of pending writes
|
|
104
|
+
*/
|
|
105
|
+
export function getPendingCount() {
|
|
106
|
+
try {
|
|
107
|
+
if (!existsSync(QUEUE_FILE))
|
|
108
|
+
return 0;
|
|
109
|
+
const raw = readFileSync(QUEUE_FILE, 'utf-8').trim();
|
|
110
|
+
if (!raw)
|
|
111
|
+
return 0;
|
|
112
|
+
return raw.split('\n').length;
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
return 0;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=offline-queue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"offline-queue.js","sourceRoot":"","sources":["../src/offline-queue.ts"],"names":[],"mappings":"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"}
|
package/ekkOS_CONTEXT.md
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
---
|
|
2
|
+
system_id: packages-ekkos-mcp-server
|
|
3
|
+
domain: packages
|
|
4
|
+
status: active
|
|
5
|
+
last_compiled_at: 2026-03-17T00:54:14.311-04:00
|
|
6
|
+
compiled_timezone: America/Toronto
|
|
7
|
+
activity_status: active
|
|
8
|
+
days_since_last_change: 15
|
|
9
|
+
content_hash: dd7d874972bb04417852038485edca703142b4cb1c8e477abd26d7a8aa69f788
|
|
10
|
+
invalidation_fingerprint: 60d856ec21bd71e6ac9cc693cdbdea5717a152588e2fc22b153f6cad9f6a0f1b
|
|
11
|
+
recompile_reason: "1 local file change"
|
|
12
|
+
source_event_ids: []
|
|
13
|
+
source_event_count: 1
|
|
14
|
+
evidence_window_start: 2026-03-17T00:54:11.658-04:00
|
|
15
|
+
evidence_window_end: 2026-03-17T00:54:11.658-04:00
|
|
16
|
+
confidence: medium
|
|
17
|
+
redactions: 0
|
|
18
|
+
compiled_by: ekkOS Local Compiler
|
|
19
|
+
compiler_model: local-mechanical-v1
|
|
20
|
+
compiler_template_version: local-mechanical-v4
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
<!-- EKKOS_AUTOGENERATED_START dd7d874972bb04417852038485edca703142b4cb1c8e477abd26d7a8aa69f788 -->
|
|
24
|
+
|
|
25
|
+
# packages/ekkos-mcp-server
|
|
26
|
+
|
|
27
|
+
Stdio-to-SSE bridge for [ekkOS](https://ekkos.dev) Memory substrate. Enables AI tools like Claude Code and Cursor to access your persistent memory via the Model Context Protocol (MCP).
|
|
28
|
+
|
|
29
|
+
## Architecture
|
|
30
|
+
- **Runtime**: JSON, TS, MD
|
|
31
|
+
- **Entry points**: `index.ts`
|
|
32
|
+
- **Key dependencies**: `@modelcontextprotocol/sdk`, `@sentry/node`, `@types/better-sqlite3`, `@types/node`, `typescript`
|
|
33
|
+
- **Size**: 7 files across 1 directories (json (3), ts (3), md (1))
|
|
34
|
+
|
|
35
|
+
## Key Modules
|
|
36
|
+
- `src/` — 3 .ts files
|
|
37
|
+
|
|
38
|
+
## Environment Variables
|
|
39
|
+
- `EKKOS_API_KEY`
|
|
40
|
+
- `EKKOS_DEBUG`
|
|
41
|
+
- `EKKOS_MCP_URL`
|
|
42
|
+
- `EKKOS_USER_ID`
|
|
43
|
+
- `NODE_ENV`
|
|
44
|
+
- `SENTRY_DSN`
|
|
45
|
+
|
|
46
|
+
## Change Log
|
|
47
|
+
- **Mar 1**: feat(synk): rebrand Happy Coder fork → ekkOS Synk — files: package-lock.json, package.json, index.ts, local-cache.ts, offline-queue.ts +12 more | - Rename packages: happy-wire → @ekkos/wire, happy-cli → @ekkos/remote, happy-agent → @ekkos/agent, happy-server → @ekko
|
|
48
|
+
|
|
49
|
+
## Active Work
|
|
50
|
+
These 1 file(s) changed since last compile:
|
|
51
|
+
|
|
52
|
+
- `ekkos-mcp-server/package.json`
|
|
53
|
+
|
|
54
|
+
## System Info
|
|
55
|
+
- **Path**: `packages/ekkos-mcp-server` · **ID**: `packages-ekkos-mcp-server` · **Domain**: `packages`
|
|
56
|
+
- **Status**: active (15d since last commit) · **Compiled**: Today, 12:54 AM
|
|
57
|
+
- **Trigger**: 1 local file change
|
|
58
|
+
|
|
59
|
+
<!-- EKKOS_AUTOGENERATED_END -->
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
*Generated directly from the local workspace to keep CLI context aligned with on-disk code.*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ekkos/mcp-server",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.4",
|
|
4
4
|
"description": "ekkOS Memory MCP Server - stdio bridge to cloud memory substrate",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -32,7 +32,11 @@
|
|
|
32
32
|
"@modelcontextprotocol/sdk": "^1.0.4",
|
|
33
33
|
"@sentry/node": "^10.31.0"
|
|
34
34
|
},
|
|
35
|
+
"optionalDependencies": {
|
|
36
|
+
"better-sqlite3": "^9.4.3"
|
|
37
|
+
},
|
|
35
38
|
"devDependencies": {
|
|
39
|
+
"@types/better-sqlite3": "^7.6.8",
|
|
36
40
|
"@types/node": "^20.11.5",
|
|
37
41
|
"typescript": "^5.3.3"
|
|
38
42
|
},
|