@engramlabs/mcp 0.1.3-alpha → 0.1.4-alpha
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/README.md +26 -56
- package/agent-install.js +109 -53
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -1,47 +1,35 @@
|
|
|
1
1
|
# @engramlabs/mcp
|
|
2
2
|
|
|
3
|
-
Local-first
|
|
3
|
+
Local-first **knowledge & memory layer** for AI agents — via MCP.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
SQLite files on your machine. No cloud, no telemetry, no network calls on
|
|
8
|
-
the default path.
|
|
5
|
+
Durable memory, a code graph, beliefs, and governed retrieval in SQLite
|
|
6
|
+
files on your machine. No cloud, no telemetry.
|
|
9
7
|
|
|
10
|
-
##
|
|
8
|
+
## Quick start
|
|
11
9
|
|
|
12
10
|
```bash
|
|
13
11
|
npm install -g @engramlabs/mcp@alpha
|
|
12
|
+
engram-mcp install --agent claude # skills + hooks + red-forman subagent
|
|
14
13
|
```
|
|
15
14
|
|
|
16
|
-
|
|
15
|
+
Hosts: `claude` · `claude-desktop` · `cursor` · `codex` · `pi` · `copilot` · `all`
|
|
17
16
|
|
|
18
|
-
|
|
17
|
+
**Project scope** — install skills, hooks, and agents into the repo
|
|
18
|
+
(committed, shared with the team) instead of your home directory:
|
|
19
19
|
|
|
20
20
|
```bash
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
cd your-repo
|
|
22
|
+
engram-mcp install --agent claude --scope project
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
Lands in `.claude/`, `.agents/skills/` (Codex + Copilot + pi read this
|
|
26
|
+
cross-tool dir), `.codex/hooks.json`, `.github/hooks/`, `.pi/`.
|
|
26
27
|
|
|
27
|
-
|
|
28
|
-
engram-mcp install --client claude # Claude Code
|
|
29
|
-
engram-mcp install --client claude-desktop # Claude Desktop
|
|
30
|
-
engram-mcp install --client cursor # Cursor
|
|
31
|
-
engram-mcp install --client codex # Codex CLI
|
|
32
|
-
engram-mcp install --client pi # pi
|
|
33
|
-
engram-mcp install --client copilot # GitHub Copilot / VS Code
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
Or run directly:
|
|
28
|
+
MCP server only (no skills/hooks): `engram-mcp install --client <host>`
|
|
37
29
|
|
|
38
|
-
|
|
39
|
-
npx @engramlabs/mcp@alpha --storage ~/.engram
|
|
40
|
-
```
|
|
30
|
+
Or run directly: `npx @engramlabs/mcp@alpha --storage ~/.engram`
|
|
41
31
|
|
|
42
|
-
### Manual
|
|
43
|
-
|
|
44
|
-
Add to your `.mcp.json` (or your host's config):
|
|
32
|
+
### Manual config
|
|
45
33
|
|
|
46
34
|
```json
|
|
47
35
|
{
|
|
@@ -58,40 +46,22 @@ Add to your `.mcp.json` (or your host's config):
|
|
|
58
46
|
|
|
59
47
|
| | |
|
|
60
48
|
|---|---|
|
|
61
|
-
| **
|
|
62
|
-
| **
|
|
63
|
-
| **
|
|
64
|
-
| **
|
|
65
|
-
| **
|
|
66
|
-
| **Runbooks** | `procedure_put`, `procedure_list` — replayable with success/fail counters |
|
|
67
|
-
| **Correct** | `forget`, `graph_health` — remove wrong data, monitor health |
|
|
68
|
-
| **Adversarial review** | `red-forman` subagent — severity-tagged findings on any diff before you declare done |
|
|
49
|
+
| **Memory** | remember decisions, gotchas, invariants — recall them automatically |
|
|
50
|
+
| **Code graph** | index a repo → symbols, blast radius, architecture |
|
|
51
|
+
| **Skills** | `engram-index/learn/search/plan/implement` — evidence-labeled workflows |
|
|
52
|
+
| **Auto-recall** | hooks inject relevant memory per prompt; irrelevant stays silent |
|
|
53
|
+
| **Adversarial review** | `red-forman` subagent — severity-tagged findings before you ship |
|
|
69
54
|
|
|
70
55
|
## Platforms
|
|
71
56
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
| Linux | x86-64 | ~49 MB |
|
|
75
|
-
| Linux | ARM64 | ~49 MB |
|
|
76
|
-
| macOS | Apple Silicon | ~49 MB |
|
|
77
|
-
| Windows | x86-64 | ~49 MB |
|
|
78
|
-
|
|
79
|
-
Platform binaries install automatically as optional dependencies — you
|
|
80
|
-
don't need to pick one.
|
|
57
|
+
Linux x64/ARM64 · macOS Apple Silicon · Windows x64 — binaries install
|
|
58
|
+
automatically per machine.
|
|
81
59
|
|
|
82
60
|
## Privacy
|
|
83
61
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
- No cloud calls on the default path
|
|
87
|
-
- Delete the storage directory = everything is gone
|
|
88
|
-
|
|
89
|
-
## Learn more
|
|
90
|
-
|
|
91
|
-
- [GitHub](https://github.com/phanijapps/engram) — source, architecture, docs
|
|
92
|
-
- [HOW-TO](https://github.com/phanijapps/engram/blob/main/mcp/engram-mcp/HOW-TO.md) — full setup guide
|
|
93
|
-
- [RFC-0021](https://github.com/phanijapps/engram/blob/main/docs/rfcs/0021-npm-distribution-rollout.md) — distribution design
|
|
62
|
+
All data in SQLite under `~/.engram`. No telemetry, no cloud. Delete
|
|
63
|
+
the directory = everything is gone.
|
|
94
64
|
|
|
95
|
-
##
|
|
65
|
+
## Links
|
|
96
66
|
|
|
97
|
-
MIT
|
|
67
|
+
[GitHub](https://github.com/phanijapps/engram) · [Setup guide](https://github.com/phanijapps/engram/blob/main/mcp/engram-mcp/HOW-TO.md) · MIT
|
package/agent-install.js
CHANGED
|
@@ -147,16 +147,17 @@ function mergeClaudeHooks(file, entries, remove) {
|
|
|
147
147
|
}
|
|
148
148
|
|
|
149
149
|
const HOSTS = {
|
|
150
|
+
// USER scope installs to the home directory (available everywhere);
|
|
151
|
+
// PROJECT scope installs into the current repo (committed, per-team).
|
|
150
152
|
claude: {
|
|
151
153
|
label: 'Claude Code',
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
const settings = path.join(home, '.claude', 'settings.json');
|
|
154
|
+
install(home, remove, written, cwd, scope) {
|
|
155
|
+
const root = scope === 'project' ? path.join(cwd, '.claude') : path.join(home, '.claude');
|
|
156
|
+
copySkills(path.join(root, 'skills'), written);
|
|
157
|
+
const agentDir = path.join(root, 'agents');
|
|
158
|
+
if (remove) { try { fs.rmSync(path.join(agentDir, 'red-forman.md')); } catch {} }
|
|
159
|
+
else copyAgent(agentDir, 'red-forman.claude.md', 'red-forman.md', written);
|
|
160
|
+
const settings = path.join(root, 'settings.json');
|
|
160
161
|
const recall = hookScript('recall-context.cjs');
|
|
161
162
|
const stale = hookScript('stale-index.cjs');
|
|
162
163
|
mergeClaudeHooks(
|
|
@@ -173,40 +174,70 @@ const HOSTS = {
|
|
|
173
174
|
},
|
|
174
175
|
codex: {
|
|
175
176
|
label: 'Codex',
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
copySkills(
|
|
179
|
-
|
|
180
|
-
|
|
177
|
+
install(home, remove, written, cwd, scope) {
|
|
178
|
+
// Skills: the cross-tool .agents/skills dir (project) or ~/.agents/skills (user).
|
|
179
|
+
copySkills(
|
|
180
|
+
scope === 'project' ? path.join(cwd, '.agents', 'skills') : path.join(home, '.agents', 'skills'),
|
|
181
|
+
written,
|
|
182
|
+
);
|
|
183
|
+
// Agents: Codex discovers agents at user level only (~/.codex/agents,
|
|
184
|
+
// YAML form) — no documented project-agent location.
|
|
181
185
|
const agentDir = path.join(home, '.codex', 'agents');
|
|
182
186
|
if (remove) { try { fs.rmSync(path.join(agentDir, 'red-forman.yaml')); } catch {} }
|
|
183
|
-
else
|
|
187
|
+
else {
|
|
188
|
+
copyAgent(agentDir, 'red-forman.codex.yaml', 'red-forman.yaml', written);
|
|
189
|
+
if (scope === 'project') {
|
|
190
|
+
process.stdout.write(' note: Codex agents are user-scope (no project-agent discovery)\n');
|
|
191
|
+
}
|
|
192
|
+
}
|
|
184
193
|
const recall = hookScript('recall-context.cjs');
|
|
185
194
|
const stale = hookScript('stale-index.cjs');
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
'
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
195
|
+
if (scope === 'project') {
|
|
196
|
+
// Project hooks live in <repo>/.codex/hooks.json (JSON, not TOML).
|
|
197
|
+
const file = path.join(cwd, '.codex', 'hooks.json');
|
|
198
|
+
if (remove) {
|
|
199
|
+
try { fs.rmSync(file); } catch {}
|
|
200
|
+
} else {
|
|
201
|
+
writeJson(file, {
|
|
202
|
+
description: 'engram agent bundle (skills + hooks + subagent)',
|
|
203
|
+
hooks: {
|
|
204
|
+
UserPromptSubmit: [
|
|
205
|
+
{ hooks: [{ type: 'command', command: `node "${recall}"`, async: true, statusMessage: 'engram recall' }] },
|
|
206
|
+
],
|
|
207
|
+
Stop: [{ hooks: [{ type: 'command', command: `node "${stale}"` }] }],
|
|
208
|
+
SessionStart: [
|
|
209
|
+
{ matcher: 'startup|resume', hooks: [{ type: 'command', command: `node "${recall}"`, additionalContextLimit: 2000 }] },
|
|
210
|
+
],
|
|
211
|
+
},
|
|
212
|
+
});
|
|
213
|
+
written.push(file);
|
|
214
|
+
}
|
|
215
|
+
} else {
|
|
216
|
+
const body = remove
|
|
217
|
+
? null
|
|
218
|
+
: [
|
|
219
|
+
'[[hooks.UserPromptSubmit]]',
|
|
220
|
+
' [[hooks.UserPromptSubmit.hooks]]',
|
|
221
|
+
' type = "command"',
|
|
222
|
+
` command = 'node "${recall}"'`,
|
|
223
|
+
' async = true',
|
|
224
|
+
' statusMessage = "engram recall"',
|
|
225
|
+
'',
|
|
226
|
+
'[[hooks.Stop]]',
|
|
227
|
+
' [[hooks.Stop.hooks]]',
|
|
228
|
+
' type = "command"',
|
|
229
|
+
` command = 'node "${stale}"'`,
|
|
230
|
+
'',
|
|
231
|
+
'[[hooks.SessionStart]]',
|
|
232
|
+
' matcher = "startup|resume"',
|
|
233
|
+
' [[hooks.SessionStart.hooks]]',
|
|
234
|
+
' type = "command"',
|
|
235
|
+
` command = 'node "${recall}"'`,
|
|
236
|
+
' additionalContextLimit = 2000',
|
|
237
|
+
].join('\n');
|
|
238
|
+
writeTomlSection(path.join(home, '.codex', 'config.toml'), 'hooks', body);
|
|
239
|
+
written.push(path.join(home, '.codex', 'config.toml'));
|
|
240
|
+
}
|
|
210
241
|
if (!remove) {
|
|
211
242
|
process.stdout.write(' note: run /hooks inside Codex to trust the new hooks\n');
|
|
212
243
|
}
|
|
@@ -214,20 +245,24 @@ const HOSTS = {
|
|
|
214
245
|
},
|
|
215
246
|
copilot: {
|
|
216
247
|
label: 'GitHub Copilot',
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
copySkills(
|
|
220
|
-
|
|
248
|
+
install(home, remove, written, cwd, scope) {
|
|
249
|
+
// Skills: .agents/skills (project, cross-tool) or ~/.agents/skills (user).
|
|
250
|
+
copySkills(
|
|
251
|
+
scope === 'project' ? path.join(cwd, '.agents', 'skills') : path.join(home, '.agents', 'skills'),
|
|
252
|
+
written,
|
|
253
|
+
);
|
|
254
|
+
// Agents: repo-scoped either way (.github/agents/).
|
|
221
255
|
const agentDir = path.join(cwd || process.cwd(), '.github', 'agents');
|
|
222
256
|
if (remove) { try { fs.rmSync(path.join(agentDir, 'red-forman.md')); } catch {} }
|
|
223
257
|
else copyAgent(agentDir, 'red-forman.copilot.md', 'red-forman.md', written);
|
|
224
258
|
// Per-prompt injection is not available to Copilot command hooks
|
|
225
259
|
// (output dropped by design) — sessionStart only. Honest limitation.
|
|
226
|
-
const file =
|
|
260
|
+
const file =
|
|
261
|
+
scope === 'project'
|
|
262
|
+
? path.join(cwd, '.github', 'hooks', 'engram.json')
|
|
263
|
+
: path.join(home, '.copilot', 'hooks', 'engram.json');
|
|
227
264
|
if (remove) {
|
|
228
|
-
try {
|
|
229
|
-
fs.rmSync(file);
|
|
230
|
-
} catch {}
|
|
265
|
+
try { fs.rmSync(file); } catch {}
|
|
231
266
|
} else {
|
|
232
267
|
writeJson(file, {
|
|
233
268
|
version: 1,
|
|
@@ -241,17 +276,31 @@ const HOSTS = {
|
|
|
241
276
|
});
|
|
242
277
|
written.push(file);
|
|
243
278
|
}
|
|
279
|
+
if (scope === 'project' && !remove) {
|
|
280
|
+
process.stdout.write(' note: commit .github/ and .agents/ so the team gets the bundle\n');
|
|
281
|
+
}
|
|
244
282
|
},
|
|
245
283
|
},
|
|
246
284
|
pi: {
|
|
247
285
|
label: 'pi',
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
286
|
+
install(home, remove, written, cwd, scope) {
|
|
287
|
+
// Skills: pi reads the cross-tool .agents/skills at project level
|
|
288
|
+
// (same dir codex/copilot read) or ~/.pi/agent/skills at user level.
|
|
289
|
+
copySkills(
|
|
290
|
+
scope === 'project' ? path.join(cwd, '.agents', 'skills') : path.join(home, '.pi', 'agent', 'skills'),
|
|
291
|
+
written,
|
|
292
|
+
);
|
|
293
|
+
// Agents: .pi/agents/ (project) or ~/.pi/agent/agents/ (user).
|
|
294
|
+
const agentDir =
|
|
295
|
+
scope === 'project' ? path.join(cwd, '.pi', 'agents') : path.join(home, '.pi', 'agent', 'agents');
|
|
252
296
|
if (remove) { try { fs.rmSync(path.join(agentDir, 'red-forman.md')); } catch {} }
|
|
253
297
|
else copyAgent(agentDir, 'red-forman.pi.md', 'red-forman.md', written);
|
|
254
|
-
|
|
298
|
+
// Extensions are pi's hook mechanism: .pi/extensions/ (project)
|
|
299
|
+
// or ~/.pi/agent/extensions/ (user).
|
|
300
|
+
const ext =
|
|
301
|
+
scope === 'project'
|
|
302
|
+
? path.join(cwd, '.pi', 'extensions', 'engram-recall.cjs')
|
|
303
|
+
: path.join(home, '.pi', 'agent', 'extensions', 'engram-recall.cjs');
|
|
255
304
|
if (remove) {
|
|
256
305
|
try {
|
|
257
306
|
fs.rmSync(ext);
|
|
@@ -270,23 +319,30 @@ function agentInstall(args) {
|
|
|
270
319
|
const cwd = process.cwd();
|
|
271
320
|
let target = null;
|
|
272
321
|
let remove = false;
|
|
322
|
+
let scope = 'user';
|
|
273
323
|
let storage = process.env.ENGRAM_STORAGE || path.join(home, '.engram');
|
|
274
324
|
for (let i = 0; i < args.length; i++) {
|
|
275
325
|
if (args[i] === '--agent') target = args[++i];
|
|
276
326
|
else if (args[i] === '--remove') remove = true;
|
|
327
|
+
else if (args[i] === '--scope') scope = args[++i];
|
|
277
328
|
else if (args[i] === '--storage') storage = args[++i];
|
|
278
329
|
}
|
|
330
|
+
if (scope !== 'user' && scope !== 'project') {
|
|
331
|
+
process.stderr.write(`engram-mcp install: --scope must be 'user' or 'project'\n`);
|
|
332
|
+
process.exit(1);
|
|
333
|
+
}
|
|
279
334
|
if (!target || (target !== 'all' && !HOSTS[target])) {
|
|
280
335
|
process.stderr.write(
|
|
281
336
|
`engram-mcp install: ${target ? `unknown agent '${target}'` : 'missing --agent'}\n` +
|
|
282
337
|
`Agents: ${Object.keys(HOSTS).join(', ')}, all\n` +
|
|
283
|
-
`Usage: engram-mcp install --agent <id> [--remove] [--storage <path>]\n`,
|
|
338
|
+
`Usage: engram-mcp install --agent <id> [--scope user|project] [--remove] [--storage <path>]\n`,
|
|
284
339
|
);
|
|
285
340
|
process.exit(1);
|
|
286
341
|
}
|
|
287
342
|
const ids = target === 'all' ? Object.keys(HOSTS) : [target];
|
|
288
343
|
process.stdout.write(
|
|
289
344
|
`${remove ? 'Removing' : 'Installing'} engram agent bundle (skills + hooks + subagents)\n` +
|
|
345
|
+
` scope: ${scope}${scope === 'project' ? ` (${cwd})` : ''}\n` +
|
|
290
346
|
` storage: ${storage}\n\n`,
|
|
291
347
|
);
|
|
292
348
|
for (const id of ids) {
|
|
@@ -294,7 +350,7 @@ function agentInstall(args) {
|
|
|
294
350
|
process.stdout.write(`[${host.label}]\n`);
|
|
295
351
|
const written = [];
|
|
296
352
|
try {
|
|
297
|
-
host.install(home, remove, written, cwd);
|
|
353
|
+
host.install(home, remove, written, cwd, scope);
|
|
298
354
|
for (const w of written) process.stdout.write(` ${remove ? 'cleaned' : 'wrote'}: ${w}\n`);
|
|
299
355
|
if (id === 'copilot' && !remove) {
|
|
300
356
|
process.stdout.write(
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@engramlabs/mcp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4-alpha",
|
|
4
4
|
"description": "Local-first agentic memory: the engram MCP server launcher. Memory + knowledge graph + beliefs + code intelligence for any MCP client.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -32,11 +32,11 @@
|
|
|
32
32
|
"local-first"
|
|
33
33
|
],
|
|
34
34
|
"optionalDependencies": {
|
|
35
|
-
"@engramlabs/mcp-linux-x64-gnu": "0.1.
|
|
36
|
-
"@engramlabs/mcp-linux-arm64-gnu": "0.1.
|
|
37
|
-
"@engramlabs/mcp-darwin-arm64": "0.1.
|
|
38
|
-
"@engramlabs/mcp-darwin-x64": "0.1.
|
|
39
|
-
"@engramlabs/mcp-win32-x64": "0.1.
|
|
35
|
+
"@engramlabs/mcp-linux-x64-gnu": "0.1.4-alpha",
|
|
36
|
+
"@engramlabs/mcp-linux-arm64-gnu": "0.1.4-alpha",
|
|
37
|
+
"@engramlabs/mcp-darwin-arm64": "0.1.4-alpha",
|
|
38
|
+
"@engramlabs/mcp-darwin-x64": "0.1.4-alpha",
|
|
39
|
+
"@engramlabs/mcp-win32-x64": "0.1.4-alpha"
|
|
40
40
|
},
|
|
41
41
|
"scripts": {
|
|
42
42
|
"test": "node --test test/*.test.cjs"
|