@luisarg/memory-mcp 0.1.1 → 0.1.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.
package/cordis.patch.yml CHANGED
@@ -10,8 +10,10 @@
10
10
  config:
11
11
  serverName: memory
12
12
  transport: stdio
13
- command: uv
14
- args: [run, --directory, !!js process.env.DSH_MEMORY_SERVER_DIR ?? dshHomePath('memory-vault-server'), python, server.py]
13
+ # launcher.mjs (bundled with the server): `uv run` when uv is on PATH,
14
+ # else a pip-managed .venv (python3 -m venv + pip install -r requirements.txt)
15
+ command: !!js process.execPath
16
+ args: [!!js "(process.env.DSH_MEMORY_SERVER_DIR ?? dshHomePath('memory-vault-server')) + '/launcher.mjs'"]
15
17
  env:
16
18
  MEMORY_PATH: !!js process.env.DSH_MEMORY_PATH ?? dshHomePath('memory-vault')
17
19
  UV_CACHE_DIR: /tmp/uv-cache
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.ts"],"sourcesContent":[],"mappings":";;;;cAOa,IAAA;UAEI,MAAA;EAFJ,UAAI,EAAA,MAAA;EAEA,SAAM,EAAA,MAAA;AAKvB;AA6BgB,cA7BH,MA6Bc,EA7BN,MA6BuB,CA7BhB,MA6BsB,CAAA;iBAAlC,KAAA,MAAW,iBAAiB"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.ts"],"sourcesContent":[],"mappings":";;;;cAOa,IAAA;UAEI,MAAA;EAFJ,UAAI,EAAA,MAAA;EAEA,SAAM,EAAA,MAAA;AAKvB;AAwCgB,cAxCH,MAwCc,EAxCN,MAwCuB,CAxChB,MAwCsB,CAAA;iBAAlC,KAAA,MAAW,iBAAiB"}
package/dist/index.js CHANGED
@@ -30,11 +30,23 @@ function ensure(target, bundled, key) {
30
30
  cpSync(bundled, target, { recursive: true });
31
31
  return true;
32
32
  }
33
+ /** Copy one bundled file into `target` when missing (upgrades add files 0.1.1 → 0.1.2). */
34
+ function ensureFile(target, bundled, file) {
35
+ const dest = join(target, file);
36
+ if (existsSync(dest)) return false;
37
+ const src = join(bundled, file);
38
+ if (!existsSync(src)) return false;
39
+ mkdirSync(target, { recursive: true });
40
+ cpSync(src, dest);
41
+ return true;
42
+ }
33
43
  function apply(ctx, config) {
34
44
  const serverDir = resolveUnderHome(config.serverDir, "memory-vault-server");
35
45
  const memoryPath = resolveUnderHome(config.memoryPath, "memory-vault");
36
46
  if (ensure(serverDir, join(packageRoot, "server"), "server.py")) console.log(`[memory-mcp] installed memory-vault-server -> ${serverDir}`);
37
47
  if (ensure(memoryPath, join(packageRoot, "vault"), "type-registry.yaml")) console.log(`[memory-mcp] installed vault starter -> ${memoryPath}`);
48
+ const bundled = join(packageRoot, "server");
49
+ for (const file of ["launcher.mjs", "requirements.txt"]) if (ensureFile(serverDir, bundled, file)) console.log(`[memory-mcp] installed ${file} -> ${serverDir}`);
38
50
  if (!existsSync(join(serverDir, "server.py"))) console.warn(`[memory-mcp] memory-vault-server not found at ${serverDir} and not bundled — set DSH_MEMORY_SERVER_DIR (or run \`node scripts/bundle-assets.mjs\` in a checkout)`);
39
51
  }
40
52
 
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["Config: Schema<Config>"],"sources":["../src/index.ts"],"sourcesContent":["import { cpSync, existsSync, mkdirSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { dirname, isAbsolute, join } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport type { Context } from '@deepseek-ai/cordis'\nimport Schema from '@deepseek-ai/schemastery'\n\nexport const name = 'memory-mcp'\n\nexport interface Config {\n memoryPath: string\n serverDir: string\n}\n\nexport const Config: Schema<Config> = Schema.object({\n memoryPath: Schema.string().default(process.env.DSH_MEMORY_PATH ?? ''),\n serverDir: Schema.string().default(process.env.DSH_MEMORY_SERVER_DIR ?? ''),\n})\n\nconst packageRoot = dirname(dirname(fileURLToPath(import.meta.url)))\n\n/** Harness home, resolved like the harness itself ($DSH_HOME, or ~/.dsh). */\nfunction dshHome(): string {\n const env = process.env.DSH_HOME?.trim()\n return env && env.length > 0 ? env : join(homedir(), '.dsh')\n}\n\n/** Absolute paths stay; empty/relative values resolve under the harness home. */\nfunction resolveUnderHome(value: string, segment: string): string {\n const v = value.trim()\n if (v.length === 0) return join(dshHome(), segment)\n return isAbsolute(v) ? v : join(dshHome(), v)\n}\n\n/** Copy the bundled dir into `target` when `key` is missing there. */\nfunction ensure(target: string, bundled: string, key: string): boolean {\n if (existsSync(join(target, key))) return false\n if (!existsSync(bundled)) return false\n mkdirSync(target, { recursive: true })\n cpSync(bundled, target, { recursive: true })\n return true\n}\n\nexport function apply(ctx: Context, config: Config) {\n const serverDir = resolveUnderHome(config.serverDir, 'memory-vault-server')\n const memoryPath = resolveUnderHome(config.memoryPath, 'memory-vault')\n\n // Self-contained install: first boot copies the bundled server and vault\n // starter under the harness home when they are missing. Env-overridden\n // paths are respected (never overwritten, never copied over).\n if (ensure(serverDir, join(packageRoot, 'server'), 'server.py')) {\n console.log(`[memory-mcp] installed memory-vault-server -> ${serverDir}`)\n }\n if (ensure(memoryPath, join(packageRoot, 'vault'), 'type-registry.yaml')) {\n console.log(`[memory-mcp] installed vault starter -> ${memoryPath}`)\n }\n if (!existsSync(join(serverDir, 'server.py'))) {\n console.warn(\n `[memory-mcp] memory-vault-server not found at ${serverDir} and not bundled — ` +\n 'set DSH_MEMORY_SERVER_DIR (or run `node scripts/bundle-assets.mjs` in a checkout)',\n )\n }\n}\n"],"mappings":";;;;;;;AAOA,MAAa,OAAO;AAOpB,MAAaA,SAAyB,OAAO,OAAO;CAClD,YAAY,OAAO,QAAQ,CAAC,QAAQ,QAAQ,IAAI,mBAAmB,GAAG;CACtE,WAAW,OAAO,QAAQ,CAAC,QAAQ,QAAQ,IAAI,yBAAyB,GAAG;CAC5E,CAAC;AAEF,MAAM,cAAc,QAAQ,QAAQ,cAAc,OAAO,KAAK,IAAI,CAAC,CAAC;;AAGpE,SAAS,UAAkB;CACzB,MAAM,MAAM,QAAQ,IAAI,UAAU,MAAM;AACxC,QAAO,OAAO,IAAI,SAAS,IAAI,MAAM,KAAK,SAAS,EAAE,OAAO;;;AAI9D,SAAS,iBAAiB,OAAe,SAAyB;CAChE,MAAM,IAAI,MAAM,MAAM;AACtB,KAAI,EAAE,WAAW,EAAG,QAAO,KAAK,SAAS,EAAE,QAAQ;AACnD,QAAO,WAAW,EAAE,GAAG,IAAI,KAAK,SAAS,EAAE,EAAE;;;AAI/C,SAAS,OAAO,QAAgB,SAAiB,KAAsB;AACrE,KAAI,WAAW,KAAK,QAAQ,IAAI,CAAC,CAAE,QAAO;AAC1C,KAAI,CAAC,WAAW,QAAQ,CAAE,QAAO;AACjC,WAAU,QAAQ,EAAE,WAAW,MAAM,CAAC;AACtC,QAAO,SAAS,QAAQ,EAAE,WAAW,MAAM,CAAC;AAC5C,QAAO;;AAGT,SAAgB,MAAM,KAAc,QAAgB;CAClD,MAAM,YAAY,iBAAiB,OAAO,WAAW,sBAAsB;CAC3E,MAAM,aAAa,iBAAiB,OAAO,YAAY,eAAe;AAKtE,KAAI,OAAO,WAAW,KAAK,aAAa,SAAS,EAAE,YAAY,CAC7D,SAAQ,IAAI,iDAAiD,YAAY;AAE3E,KAAI,OAAO,YAAY,KAAK,aAAa,QAAQ,EAAE,qBAAqB,CACtE,SAAQ,IAAI,2CAA2C,aAAa;AAEtE,KAAI,CAAC,WAAW,KAAK,WAAW,YAAY,CAAC,CAC3C,SAAQ,KACN,iDAAiD,UAAU,wGAE5D"}
1
+ {"version":3,"file":"index.js","names":["Config: Schema<Config>"],"sources":["../src/index.ts"],"sourcesContent":["import { cpSync, existsSync, mkdirSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { dirname, isAbsolute, join } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport type { Context } from '@deepseek-ai/cordis'\nimport Schema from '@deepseek-ai/schemastery'\n\nexport const name = 'memory-mcp'\n\nexport interface Config {\n memoryPath: string\n serverDir: string\n}\n\nexport const Config: Schema<Config> = Schema.object({\n memoryPath: Schema.string().default(process.env.DSH_MEMORY_PATH ?? ''),\n serverDir: Schema.string().default(process.env.DSH_MEMORY_SERVER_DIR ?? ''),\n})\n\nconst packageRoot = dirname(dirname(fileURLToPath(import.meta.url)))\n\n/** Harness home, resolved like the harness itself ($DSH_HOME, or ~/.dsh). */\nfunction dshHome(): string {\n const env = process.env.DSH_HOME?.trim()\n return env && env.length > 0 ? env : join(homedir(), '.dsh')\n}\n\n/** Absolute paths stay; empty/relative values resolve under the harness home. */\nfunction resolveUnderHome(value: string, segment: string): string {\n const v = value.trim()\n if (v.length === 0) return join(dshHome(), segment)\n return isAbsolute(v) ? v : join(dshHome(), v)\n}\n\n/** Copy the bundled dir into `target` when `key` is missing there. */\nfunction ensure(target: string, bundled: string, key: string): boolean {\n if (existsSync(join(target, key))) return false\n if (!existsSync(bundled)) return false\n mkdirSync(target, { recursive: true })\n cpSync(bundled, target, { recursive: true })\n return true\n}\n\n/** Copy one bundled file into `target` when missing (upgrades add files 0.1.1 → 0.1.2). */\nfunction ensureFile(target: string, bundled: string, file: string): boolean {\n const dest = join(target, file)\n if (existsSync(dest)) return false\n const src = join(bundled, file)\n if (!existsSync(src)) return false\n mkdirSync(target, { recursive: true })\n cpSync(src, dest)\n return true\n}\n\nexport function apply(ctx: Context, config: Config) {\n const serverDir = resolveUnderHome(config.serverDir, 'memory-vault-server')\n const memoryPath = resolveUnderHome(config.memoryPath, 'memory-vault')\n\n // Self-contained install: first boot copies the bundled server and vault\n // starter under the harness home when they are missing. Env-overridden\n // paths are respected (never overwritten, never copied over).\n if (ensure(serverDir, join(packageRoot, 'server'), 'server.py')) {\n console.log(`[memory-mcp] installed memory-vault-server -> ${serverDir}`)\n }\n if (ensure(memoryPath, join(packageRoot, 'vault'), 'type-registry.yaml')) {\n console.log(`[memory-mcp] installed vault starter -> ${memoryPath}`)\n }\n // launcher.mjs runs the server via uv or the pip-venv fallback; upgrades of\n // existing installs (server.py already present) still need the new files.\n const bundled = join(packageRoot, 'server')\n for (const file of ['launcher.mjs', 'requirements.txt']) {\n if (ensureFile(serverDir, bundled, file)) {\n console.log(`[memory-mcp] installed ${file} -> ${serverDir}`)\n }\n }\n if (!existsSync(join(serverDir, 'server.py'))) {\n console.warn(\n `[memory-mcp] memory-vault-server not found at ${serverDir} and not bundled — ` +\n 'set DSH_MEMORY_SERVER_DIR (or run `node scripts/bundle-assets.mjs` in a checkout)',\n )\n }\n}\n"],"mappings":";;;;;;;AAOA,MAAa,OAAO;AAOpB,MAAaA,SAAyB,OAAO,OAAO;CAClD,YAAY,OAAO,QAAQ,CAAC,QAAQ,QAAQ,IAAI,mBAAmB,GAAG;CACtE,WAAW,OAAO,QAAQ,CAAC,QAAQ,QAAQ,IAAI,yBAAyB,GAAG;CAC5E,CAAC;AAEF,MAAM,cAAc,QAAQ,QAAQ,cAAc,OAAO,KAAK,IAAI,CAAC,CAAC;;AAGpE,SAAS,UAAkB;CACzB,MAAM,MAAM,QAAQ,IAAI,UAAU,MAAM;AACxC,QAAO,OAAO,IAAI,SAAS,IAAI,MAAM,KAAK,SAAS,EAAE,OAAO;;;AAI9D,SAAS,iBAAiB,OAAe,SAAyB;CAChE,MAAM,IAAI,MAAM,MAAM;AACtB,KAAI,EAAE,WAAW,EAAG,QAAO,KAAK,SAAS,EAAE,QAAQ;AACnD,QAAO,WAAW,EAAE,GAAG,IAAI,KAAK,SAAS,EAAE,EAAE;;;AAI/C,SAAS,OAAO,QAAgB,SAAiB,KAAsB;AACrE,KAAI,WAAW,KAAK,QAAQ,IAAI,CAAC,CAAE,QAAO;AAC1C,KAAI,CAAC,WAAW,QAAQ,CAAE,QAAO;AACjC,WAAU,QAAQ,EAAE,WAAW,MAAM,CAAC;AACtC,QAAO,SAAS,QAAQ,EAAE,WAAW,MAAM,CAAC;AAC5C,QAAO;;;AAIT,SAAS,WAAW,QAAgB,SAAiB,MAAuB;CAC1E,MAAM,OAAO,KAAK,QAAQ,KAAK;AAC/B,KAAI,WAAW,KAAK,CAAE,QAAO;CAC7B,MAAM,MAAM,KAAK,SAAS,KAAK;AAC/B,KAAI,CAAC,WAAW,IAAI,CAAE,QAAO;AAC7B,WAAU,QAAQ,EAAE,WAAW,MAAM,CAAC;AACtC,QAAO,KAAK,KAAK;AACjB,QAAO;;AAGT,SAAgB,MAAM,KAAc,QAAgB;CAClD,MAAM,YAAY,iBAAiB,OAAO,WAAW,sBAAsB;CAC3E,MAAM,aAAa,iBAAiB,OAAO,YAAY,eAAe;AAKtE,KAAI,OAAO,WAAW,KAAK,aAAa,SAAS,EAAE,YAAY,CAC7D,SAAQ,IAAI,iDAAiD,YAAY;AAE3E,KAAI,OAAO,YAAY,KAAK,aAAa,QAAQ,EAAE,qBAAqB,CACtE,SAAQ,IAAI,2CAA2C,aAAa;CAItE,MAAM,UAAU,KAAK,aAAa,SAAS;AAC3C,MAAK,MAAM,QAAQ,CAAC,gBAAgB,mBAAmB,CACrD,KAAI,WAAW,WAAW,SAAS,KAAK,CACtC,SAAQ,IAAI,0BAA0B,KAAK,MAAM,YAAY;AAGjE,KAAI,CAAC,WAAW,KAAK,WAAW,YAAY,CAAC,CAC3C,SAAQ,KACN,iDAAiD,UAAU,wGAE5D"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@luisarg/memory-mcp",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "type": "module",
5
5
  "description": "DSH MCP client for the memory vault",
6
6
  "repository": {
@@ -0,0 +1,69 @@
1
+ // memory-vault-server launcher — run `server.py` with uv when uv is on PATH,
2
+ // otherwise bootstrap a pip venv (.venv + requirements.txt) and run with that
3
+ // python. Used by both DSH launch points (memory-mcp cordis patch, memory-auto
4
+ // digest) so the fallback decision lives in exactly one place.
5
+ //
6
+ // stdout is the MCP channel of the spawned server — never print to it here.
7
+ // All progress/errors go to stderr.
8
+ //
9
+ // ponytail: fallback triggers only when the `uv` binary is absent, not when
10
+ // `uv run` fails (e.g. offline with an empty cache). If that ever matters,
11
+ // upgrade path: on uv run exit != 0, retry through the pip branch below.
12
+
13
+ import { spawn, spawnSync } from 'node:child_process'
14
+ import { existsSync } from 'node:fs'
15
+ import { dirname, join } from 'node:path'
16
+ import { fileURLToPath, pathToFileURL } from 'node:url'
17
+
18
+ const DIR = dirname(fileURLToPath(import.meta.url))
19
+
20
+ /** Pure decision: which command runs the server, given uv presence. */
21
+ export function resolveRunner(hasUv, dir = DIR, platform = process.platform) {
22
+ if (hasUv) return { command: 'uv', args: ['run', '--directory', dir, 'python', 'server.py'] }
23
+ const pyBin = join(dir, platform === 'win32' ? '.venv/Scripts/python.exe' : '.venv/bin/python')
24
+ return { command: pyBin, args: ['server.py'] }
25
+ }
26
+
27
+ export function hasUv() {
28
+ return spawnSync('uv', ['--version'], { stdio: 'ignore' }).status === 0
29
+ }
30
+
31
+ /** Ensure a runnable venv with the server's deps installed (pip branch only). */
32
+ export function ensurePipEnv(dir = DIR, platform = process.platform) {
33
+ const pyBin = join(dir, platform === 'win32' ? '.venv/Scripts/python.exe' : '.venv/bin/python')
34
+ const venvCmd = platform === 'win32' ? 'py' : 'python3'
35
+ if (!existsSync(pyBin)) {
36
+ console.error('[memory-vault-server] uv not found — creating fallback venv with ' + venvCmd)
37
+ // stdout is the MCP channel: keep install output off it.
38
+ const created = spawnSync(venvCmd, ['-m', 'venv', join(dir, '.venv')], { stdio: ['ignore', 'ignore', 'inherit'] })
39
+ if (created.status !== 0) {
40
+ console.error(`[memory-vault-server] venv creation failed (exit ${created.status}) — install uv or fix ${venvCmd}`)
41
+ process.exit(created.status ?? 1)
42
+ }
43
+ }
44
+ const depsOk = spawnSync(pyBin, ['-c', 'import mcp, yaml'], { stdio: 'ignore' }).status === 0
45
+ if (!depsOk) {
46
+ console.error('[memory-vault-server] fallback venv missing deps — pip install -r requirements.txt')
47
+ const pip = spawnSync(pyBin, ['-m', 'pip', 'install', '--quiet', '-r', join(dir, 'requirements.txt')], { stdio: ['ignore', 'ignore', 'inherit'] })
48
+ if (pip.status !== 0) {
49
+ console.error(`[memory-vault-server] pip install failed (exit ${pip.status}) — install uv, fix the network, or run the pip install manually`)
50
+ process.exit(pip.status ?? 1)
51
+ }
52
+ }
53
+ return pyBin
54
+ }
55
+
56
+ function main() {
57
+ const withUv = hasUv()
58
+ const { command, args } = resolveRunner(withUv)
59
+ if (!withUv) ensurePipEnv()
60
+ const child = spawn(command, args, { cwd: DIR, env: process.env, stdio: 'inherit' })
61
+ for (const sig of ['SIGTERM', 'SIGINT']) process.on(sig, () => child.kill(sig))
62
+ child.on('error', (err) => {
63
+ console.error(`[memory-vault-server] spawn failed (${command}): ${err.message}`)
64
+ process.exit(1)
65
+ })
66
+ child.on('exit', (code, signal) => process.exit(code ?? (signal ? 1 : 0)))
67
+ }
68
+
69
+ if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) main()
@@ -0,0 +1,4 @@
1
+ # Mirror of the dependencies in pyproject.toml — keep in sync by hand.
2
+ # Used only by launcher.mjs' pip fallback on hosts without uv.
3
+ mcp>=1.2.0
4
+ PyYAML>=6.0