mevoric 2.0.0

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.
Files changed (5) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +86 -0
  3. package/init.mjs +445 -0
  4. package/package.json +38 -0
  5. package/server.mjs +1469 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Lloyd Muzamhindo
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,86 @@
1
+ # Mevoric
2
+
3
+ Unified memory + agent bridge for Claude Code. One MCP server, 12 tools, zero config.
4
+
5
+ ## What It Does
6
+
7
+ - **Semantic memory** — Store and recall conversations across sessions using a remote memory server
8
+ - **Cross-tab messaging** — Send messages between Claude Code tabs in real time
9
+ - **Context sharing** — Share working knowledge between agents, persists after sessions end
10
+ - **Session checkpoints** — Save and restore structured session state automatically
11
+
12
+ ## Install
13
+
14
+ ```bash
15
+ npx mevoric init --server http://your-server:4000
16
+ ```
17
+
18
+ This single command:
19
+ 1. Adds the MCP server to `~/.claude/.mcp.json`
20
+ 2. Updates any project-level `.mcp.json` files with old entries
21
+ 3. Configures hooks in `~/.claude/settings.json`
22
+ 4. Removes legacy packages (`newcode-memory`, `agent-bridge-mcp`) if installed
23
+
24
+ Restart VS Code after running.
25
+
26
+ ## 12 Tools
27
+
28
+ | Group | Tools |
29
+ |-------|-------|
30
+ | **Memory** | `retrieve_memories`, `store_conversation`, `judge_memories` |
31
+ | **Bridge** | `register_agent`, `list_agents`, `send_message`, `read_messages`, `broadcast` |
32
+ | **Context** | `share_context`, `get_context` |
33
+ | **Checkpoints** | `save_checkpoint`, `load_checkpoint` |
34
+
35
+ ## 3 Hooks (auto-configured)
36
+
37
+ | Event | What It Does |
38
+ |-------|-------------|
39
+ | **SessionStart** | Loads shared contexts, pending messages, and checkpoints |
40
+ | **UserPromptSubmit** | Captures prompts + delivers pending agent messages |
41
+ | **Stop** | Pairs prompt+response, POSTs to memory server, saves context + checkpoint |
42
+
43
+ ## Memory Server
44
+
45
+ The memory tools (`retrieve_memories`, `store_conversation`, `judge_memories`) require a backend server that handles semantic search, embedding, and storage. Mevoric is the **client** — it calls your server's `/retrieve`, `/ingest`, and `/feedback` endpoints.
46
+
47
+ Without a memory server configured, the 9 bridge/context/checkpoint tools still work fine. Memory tools will return errors gracefully.
48
+
49
+ Set the server URL during init:
50
+
51
+ ```bash
52
+ npx mevoric init --server http://192.168.2.100:4000
53
+ ```
54
+
55
+ Or set it as an environment variable:
56
+
57
+ ```
58
+ MEVORIC_SERVER_URL=http://192.168.2.100:4000
59
+ ```
60
+
61
+ ## Environment Variables
62
+
63
+ | Variable | Default | Description |
64
+ |----------|---------|-------------|
65
+ | `MEVORIC_SERVER_URL` | *(none)* | Memory server URL (required for memory tools) |
66
+ | `MEVORIC_DATA_DIR` | OS-specific app data | Directory for agent data, messages, contexts |
67
+ | `MEVORIC_AGENT_NAME` | *(auto-generated)* | Human-readable name for this agent |
68
+
69
+ ## How It Works
70
+
71
+ Mevoric runs as a single Node.js MCP server via stdio. Claude Code starts it automatically.
72
+
73
+ **Agent Bridge:** Each Claude Code tab registers as an agent with a name. Agents communicate through file-based messaging in the data directory. A heartbeat file tracks liveness — agents that stop writing heartbeats are cleaned up automatically.
74
+
75
+ **Memory:** On session end, the Stop hook pairs the user's prompt with the assistant's response and POSTs it to your memory server for storage. On the next session, `retrieve_memories` searches for relevant past conversations.
76
+
77
+ **Checkpoints:** Structured snapshots of your working state (task, files touched, decisions made). Auto-saved on session end, auto-loaded on session start. Expire after 24 hours.
78
+
79
+ ## Requirements
80
+
81
+ - Node.js 18+
82
+ - Claude Code CLI
83
+
84
+ ## License
85
+
86
+ MIT
package/init.mjs ADDED
@@ -0,0 +1,445 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * npx mevoric init
5
+ *
6
+ * Sets up Mevoric for Claude Code. Handles everything:
7
+ * 1. Writes global ~/.claude/.mcp.json entry
8
+ * 2. Finds and updates ALL project-level .mcp.json files that have old agent-bridge or newcode-memory entries
9
+ * 3. Updates ~/.claude/settings.json hooks and permissions
10
+ * 4. Removes old pip packages (newcode-memory, agent-bridge-mcp) that auto-register as duplicate MCP servers
11
+ * 5. Migrates existing data (agent-bridge data dir) so nothing is lost
12
+ */
13
+
14
+ import {
15
+ existsSync, readFileSync, writeFileSync, readdirSync,
16
+ mkdirSync, statSync
17
+ } from 'fs';
18
+ import { resolve, dirname } from 'path';
19
+ import { homedir, platform } from 'os';
20
+ import { fileURLToPath } from 'url';
21
+ import { execSync } from 'child_process';
22
+
23
+ const __filename = fileURLToPath(import.meta.url);
24
+ const __dirname = dirname(__filename);
25
+ const SERVER_PATH = resolve(__dirname, 'server.mjs');
26
+
27
+ // ============================================================
28
+ // Paths
29
+ // ============================================================
30
+
31
+ const CLAUDE_DIR = resolve(homedir(), '.claude');
32
+ const GLOBAL_MCP = resolve(CLAUDE_DIR, '.mcp.json');
33
+ const SETTINGS = resolve(CLAUDE_DIR, 'settings.json');
34
+
35
+ function getDefaultDataDir() {
36
+ const p = platform();
37
+ if (p === 'win32') return resolve(process.env.LOCALAPPDATA || resolve(homedir(), 'AppData', 'Local'), 'mevoric');
38
+ if (p === 'darwin') return resolve(homedir(), 'Library', 'Application Support', 'mevoric');
39
+ return resolve(process.env.XDG_DATA_HOME || resolve(homedir(), '.local', 'share'), 'mevoric');
40
+ }
41
+
42
+ function getLegacyDataDir() {
43
+ const p = platform();
44
+ if (p === 'win32') return resolve(process.env.LOCALAPPDATA || resolve(homedir(), 'AppData', 'Local'), 'agent-bridge');
45
+ if (p === 'darwin') return resolve(homedir(), 'Library', 'Application Support', 'agent-bridge');
46
+ return resolve(process.env.XDG_DATA_HOME || resolve(homedir(), '.local', 'share'), 'agent-bridge');
47
+ }
48
+
49
+ // ============================================================
50
+ // Helpers
51
+ // ============================================================
52
+
53
+ function readJSON(path) {
54
+ try {
55
+ return JSON.parse(readFileSync(path, 'utf8'));
56
+ } catch {
57
+ return null;
58
+ }
59
+ }
60
+
61
+ function writeJSON(path, data) {
62
+ mkdirSync(dirname(path), { recursive: true });
63
+ writeFileSync(path, JSON.stringify(data, null, 2) + '\n');
64
+ }
65
+
66
+ function log(msg) {
67
+ console.log(` ${msg}`);
68
+ }
69
+
70
+ function logHeader(msg) {
71
+ console.log(`\n${msg}`);
72
+ }
73
+
74
+ // ============================================================
75
+ // Step 1: Global .mcp.json
76
+ // ============================================================
77
+
78
+ function updateGlobalMcp(serverUrl) {
79
+ logHeader('1. Global MCP config (~/.claude/.mcp.json)');
80
+
81
+ const existing = readJSON(GLOBAL_MCP) || { mcpServers: {} };
82
+ if (!existing.mcpServers) existing.mcpServers = {};
83
+
84
+ // Remove old entries
85
+ let removedOld = false;
86
+ if (existing.mcpServers['agent-bridge']) {
87
+ delete existing.mcpServers['agent-bridge'];
88
+ log('Removed old agent-bridge entry');
89
+ removedOld = true;
90
+ }
91
+ if (existing.mcpServers['newcode-memory']) {
92
+ delete existing.mcpServers['newcode-memory'];
93
+ log('Removed old newcode-memory entry');
94
+ removedOld = true;
95
+ }
96
+
97
+ // Determine data dir — use legacy dir if it exists (preserve existing data)
98
+ const legacyDir = getLegacyDataDir();
99
+ const dataDir = existsSync(legacyDir) ? legacyDir : getDefaultDataDir();
100
+
101
+ // Add mevoric entry
102
+ const env = {};
103
+ if (serverUrl) env.MEVORIC_SERVER_URL = serverUrl;
104
+ if (dataDir !== getDefaultDataDir()) env.MEVORIC_DATA_DIR = dataDir;
105
+
106
+ existing.mcpServers['mevoric'] = {
107
+ type: 'stdio',
108
+ command: 'node',
109
+ args: [SERVER_PATH],
110
+ ...(Object.keys(env).length > 0 ? { env } : {})
111
+ };
112
+
113
+ writeJSON(GLOBAL_MCP, existing);
114
+ log(existing.mcpServers['mevoric'] ? 'Updated mevoric entry' : 'Added mevoric entry');
115
+ if (dataDir !== getDefaultDataDir()) log(`Using legacy data dir: ${dataDir}`);
116
+
117
+ return dataDir;
118
+ }
119
+
120
+ // ============================================================
121
+ // Step 2: Find and update project-level .mcp.json files
122
+ // ============================================================
123
+
124
+ function findProjectMcpFiles() {
125
+ const dirs = [];
126
+
127
+ // Check settings.json for additionalDirectories
128
+ const settings = readJSON(SETTINGS);
129
+ if (settings?.permissions?.additionalDirectories) {
130
+ dirs.push(...settings.permissions.additionalDirectories);
131
+ }
132
+
133
+ // Also check common dev directories
134
+ const devDirs = [
135
+ resolve(homedir(), 'dev'),
136
+ resolve(homedir(), 'projects'),
137
+ resolve(homedir(), 'code'),
138
+ resolve(homedir(), 'src'),
139
+ ];
140
+ // Windows: also check C:\dev
141
+ if (platform() === 'win32') {
142
+ devDirs.push('C:\\dev');
143
+ devDirs.push('D:\\dev');
144
+ }
145
+
146
+ for (const dir of devDirs) {
147
+ if (existsSync(dir)) {
148
+ try {
149
+ const entries = readdirSync(dir);
150
+ for (const entry of entries) {
151
+ const full = resolve(dir, entry);
152
+ try {
153
+ if (statSync(full).isDirectory()) dirs.push(full);
154
+ } catch {}
155
+ }
156
+ } catch {}
157
+ }
158
+ }
159
+
160
+ // Deduplicate
161
+ const seen = new Set();
162
+ const unique = [];
163
+ for (const d of dirs) {
164
+ const norm = d.toLowerCase().replace(/\\/g, '/');
165
+ if (!seen.has(norm)) {
166
+ seen.add(norm);
167
+ unique.push(d);
168
+ }
169
+ }
170
+
171
+ // Check each for .mcp.json with old entries
172
+ const results = [];
173
+ for (const dir of unique) {
174
+ const mcpPath = resolve(dir, '.mcp.json');
175
+ if (!existsSync(mcpPath)) continue;
176
+
177
+ const mcp = readJSON(mcpPath);
178
+ if (!mcp?.mcpServers) continue;
179
+
180
+ const hasOld = mcp.mcpServers['agent-bridge'] || mcp.mcpServers['newcode-memory'];
181
+ if (hasOld) {
182
+ results.push({ path: mcpPath, dir, mcp });
183
+ }
184
+ }
185
+
186
+ return results;
187
+ }
188
+
189
+ function updateProjectMcpFiles(serverUrl, dataDir) {
190
+ logHeader('2. Project-level .mcp.json files');
191
+
192
+ const files = findProjectMcpFiles();
193
+ if (files.length === 0) {
194
+ log('No project-level files with old entries found');
195
+ return;
196
+ }
197
+
198
+ for (const { path, dir, mcp } of files) {
199
+ // Extract agent name from old entry
200
+ const oldBridge = mcp.mcpServers['agent-bridge'];
201
+ const oldMemory = mcp.mcpServers['newcode-memory'];
202
+ const agentName = oldBridge?.env?.AGENT_BRIDGE_NAME
203
+ || oldBridge?.env?.MEVORIC_AGENT_NAME
204
+ || null;
205
+
206
+ // Remove old entries
207
+ delete mcp.mcpServers['agent-bridge'];
208
+ delete mcp.mcpServers['newcode-memory'];
209
+
210
+ // Add mevoric entry
211
+ const env = {};
212
+ if (agentName) env.MEVORIC_AGENT_NAME = agentName;
213
+ if (serverUrl) env.MEVORIC_SERVER_URL = serverUrl;
214
+ if (dataDir && dataDir !== getDefaultDataDir()) env.MEVORIC_DATA_DIR = dataDir;
215
+
216
+ mcp.mcpServers['mevoric'] = {
217
+ type: 'stdio',
218
+ command: 'node',
219
+ args: [SERVER_PATH],
220
+ ...(Object.keys(env).length > 0 ? { env } : {})
221
+ };
222
+
223
+ writeJSON(path, mcp);
224
+ log(`Updated ${path}${agentName ? ` (agent: ${agentName})` : ''}`);
225
+ }
226
+
227
+ log(`${files.length} project file(s) updated`);
228
+ }
229
+
230
+ // ============================================================
231
+ // Step 3: Update settings.json (hooks + permissions)
232
+ // ============================================================
233
+
234
+ function updateSettings() {
235
+ logHeader('3. Settings (~/.claude/settings.json)');
236
+
237
+ const settings = readJSON(SETTINGS) || {};
238
+ if (!settings.permissions) settings.permissions = {};
239
+ if (!settings.permissions.allow) settings.permissions.allow = [];
240
+
241
+ // --- Permissions ---
242
+ const oldPerms = [
243
+ 'mcp__agent-bridge__register_agent',
244
+ 'mcp__agent-bridge__list_agents',
245
+ 'mcp__agent-bridge__send_message',
246
+ 'mcp__agent-bridge__read_messages',
247
+ 'mcp__agent-bridge__broadcast',
248
+ 'mcp__agent-bridge__share_context',
249
+ 'mcp__agent-bridge__get_context',
250
+ 'mcp__agent-bridge__save_checkpoint',
251
+ 'mcp__agent-bridge__load_checkpoint',
252
+ 'mcp__newcode-memory__retrieve_memories',
253
+ 'mcp__newcode-memory__store_conversation',
254
+ 'mcp__newcode-memory__judge_memories',
255
+ ];
256
+
257
+ const newPerms = [
258
+ 'mcp__mevoric__register_agent',
259
+ 'mcp__mevoric__list_agents',
260
+ 'mcp__mevoric__send_message',
261
+ 'mcp__mevoric__read_messages',
262
+ 'mcp__mevoric__broadcast',
263
+ 'mcp__mevoric__share_context',
264
+ 'mcp__mevoric__get_context',
265
+ 'mcp__mevoric__save_checkpoint',
266
+ 'mcp__mevoric__load_checkpoint',
267
+ 'mcp__mevoric__retrieve_memories',
268
+ 'mcp__mevoric__store_conversation',
269
+ 'mcp__mevoric__judge_memories',
270
+ ];
271
+
272
+ // Remove old, add new (avoid duplicates)
273
+ let removedCount = 0;
274
+ settings.permissions.allow = settings.permissions.allow.filter(p => {
275
+ if (oldPerms.includes(p)) { removedCount++; return false; }
276
+ return true;
277
+ });
278
+
279
+ let addedCount = 0;
280
+ for (const perm of newPerms) {
281
+ if (!settings.permissions.allow.includes(perm)) {
282
+ settings.permissions.allow.push(perm);
283
+ addedCount++;
284
+ }
285
+ }
286
+
287
+ if (removedCount > 0) log(`Removed ${removedCount} old permissions`);
288
+ if (addedCount > 0) log(`Added ${addedCount} new permissions`);
289
+
290
+ // --- Hooks ---
291
+ if (!settings.hooks) settings.hooks = {};
292
+
293
+ // Old hook commands to detect and remove
294
+ const oldHookPatterns = [
295
+ 'agent-bridge',
296
+ 'newcode-memory',
297
+ 'capture-prompt.py',
298
+ 'auto-ingest.py',
299
+ 'npx agent-bridge-mcp',
300
+ ];
301
+
302
+ function isOldHook(command) {
303
+ return oldHookPatterns.some(p => command.includes(p));
304
+ }
305
+
306
+ function isMevoricHook(command) {
307
+ return command.includes('Mevoric') || command.includes('mevoric');
308
+ }
309
+
310
+ // SessionStart
311
+ settings.hooks.SessionStart = [{
312
+ hooks: [{
313
+ type: 'command',
314
+ command: `node ${SERVER_PATH} --bootstrap-context`,
315
+ timeout: 10
316
+ }]
317
+ }];
318
+
319
+ // UserPromptSubmit
320
+ settings.hooks.UserPromptSubmit = [{
321
+ hooks: [
322
+ {
323
+ type: 'command',
324
+ command: `node ${SERVER_PATH} --capture-prompt`,
325
+ timeout: 5
326
+ },
327
+ {
328
+ type: 'command',
329
+ command: `node ${SERVER_PATH} --check-messages`,
330
+ timeout: 5
331
+ }
332
+ ]
333
+ }];
334
+
335
+ // Stop
336
+ settings.hooks.Stop = [{
337
+ hooks: [{
338
+ type: 'command',
339
+ command: `node ${SERVER_PATH} --ingest`,
340
+ timeout: 30
341
+ }]
342
+ }];
343
+
344
+ log('Hooks updated (SessionStart, UserPromptSubmit, Stop)');
345
+
346
+ writeJSON(SETTINGS, settings);
347
+ log('Settings saved');
348
+ }
349
+
350
+ // ============================================================
351
+ // Step 4: Remove legacy pip packages
352
+ // ============================================================
353
+
354
+ function removeLegacyPipPackages() {
355
+ logHeader('4. Legacy pip packages');
356
+
357
+ const packagesToRemove = ['newcode-memory', 'agent-bridge-mcp'];
358
+ let removed = 0;
359
+
360
+ for (const pkg of packagesToRemove) {
361
+ // Check if installed
362
+ try {
363
+ const result = execSync(`pip show ${pkg} 2>&1`, { encoding: 'utf8', timeout: 10000 });
364
+ if (result.includes('Name:')) {
365
+ // It's installed — remove it
366
+ try {
367
+ execSync(`pip uninstall ${pkg} -y 2>&1`, { encoding: 'utf8', timeout: 30000 });
368
+ log(`Removed ${pkg} pip package (was auto-registering as duplicate MCP server)`);
369
+ removed++;
370
+ } catch (err) {
371
+ log(`Warning: failed to remove ${pkg}: ${err.message}`);
372
+ }
373
+ }
374
+ } catch {
375
+ // Not installed or pip not available — skip
376
+ }
377
+ }
378
+
379
+ // Also try pip3 in case pip points to a different Python
380
+ for (const pkg of packagesToRemove) {
381
+ try {
382
+ const result = execSync(`pip3 show ${pkg} 2>&1`, { encoding: 'utf8', timeout: 10000 });
383
+ if (result.includes('Name:')) {
384
+ try {
385
+ execSync(`pip3 uninstall ${pkg} -y 2>&1`, { encoding: 'utf8', timeout: 30000 });
386
+ log(`Removed ${pkg} via pip3`);
387
+ removed++;
388
+ } catch {}
389
+ }
390
+ } catch {}
391
+ }
392
+
393
+ if (removed === 0) {
394
+ log('No legacy pip packages found');
395
+ }
396
+ }
397
+
398
+ // ============================================================
399
+ // Main
400
+ // ============================================================
401
+
402
+ function main() {
403
+ console.log('Mevoric — init\n');
404
+
405
+ // Parse args
406
+ const args = process.argv.slice(2).filter(a => a !== 'init');
407
+ let serverUrl = '';
408
+
409
+ for (let i = 0; i < args.length; i++) {
410
+ if (args[i] === '--server' && args[i + 1]) {
411
+ serverUrl = args[i + 1];
412
+ i++;
413
+ }
414
+ }
415
+
416
+ // Step 1: Global config
417
+ const dataDir = updateGlobalMcp(serverUrl);
418
+
419
+ // Step 2: Project-level configs
420
+ updateProjectMcpFiles(serverUrl, dataDir);
421
+
422
+ // Step 3: Settings (hooks + permissions)
423
+ updateSettings();
424
+
425
+ // Step 4: Remove old pip packages that auto-register as MCP servers
426
+ removeLegacyPipPackages();
427
+
428
+ // Done
429
+ logHeader('Done!');
430
+ log('Restart VS Code (or close/reopen Claude Code) for changes to take effect.');
431
+ log('');
432
+ log('Tools available (12):');
433
+ log(' Memory: retrieve_memories, store_conversation, judge_memories');
434
+ log(' Bridge: register_agent, list_agents, send_message, read_messages, broadcast');
435
+ log(' Context: share_context, get_context');
436
+ log(' Checkpoints: save_checkpoint, load_checkpoint');
437
+ if (serverUrl) {
438
+ log(`\nMemory server: ${serverUrl}`);
439
+ } else {
440
+ log('\nNo memory server configured. Memory tools will return errors.');
441
+ log('Run: npx mevoric init --server http://your-server:4000');
442
+ }
443
+ }
444
+
445
+ main();
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "mevoric",
3
+ "version": "2.0.0",
4
+ "description": "Unified memory + agent bridge for Claude Code. Semantic recall, cross-tab messaging, session checkpoints — one MCP server.",
5
+ "type": "module",
6
+ "main": "server.mjs",
7
+ "bin": {
8
+ "mevoric": "init.mjs"
9
+ },
10
+ "keywords": [
11
+ "mcp",
12
+ "model-context-protocol",
13
+ "claude",
14
+ "claude-code",
15
+ "agent",
16
+ "multi-agent",
17
+ "memory",
18
+ "bridge",
19
+ "checkpoints"
20
+ ],
21
+ "license": "MIT",
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "https://github.com/Lloydm15/mevoric.git"
25
+ },
26
+ "engines": {
27
+ "node": ">=18.0.0"
28
+ },
29
+ "files": [
30
+ "server.mjs",
31
+ "init.mjs",
32
+ "README.md",
33
+ "LICENSE"
34
+ ],
35
+ "dependencies": {
36
+ "@modelcontextprotocol/sdk": "^1.0.0"
37
+ }
38
+ }