@mnemoverse/mcp-memory-server 0.3.0 → 0.3.1

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.
@@ -0,0 +1,55 @@
1
+ name: verify-configs
2
+
3
+ # Mechanical drift detection for the single-source-of-truth distribution
4
+ # config pipeline. See CONTRIBUTING.md for the design.
5
+ #
6
+ # This workflow MUST pass before any PR can merge into main. It runs the
7
+ # generator in --check mode, which:
8
+ # 1. Re-emits all 14 generated artifacts from src/configs/source.json
9
+ # 2. Re-rewrites the README.md install block from the same source
10
+ # 3. Compares each result to what is committed
11
+ # 4. Exits 1 if anything differs
12
+ #
13
+ # If you see this job fail in your PR, run `npm run generate:configs` locally
14
+ # and commit the regenerated files. Do NOT bypass — the whole point is that
15
+ # bypassing leaves the README/snippets/marketplace listings drifting from
16
+ # the actual npm package.
17
+
18
+ on:
19
+ pull_request:
20
+ paths:
21
+ - "src/configs/source.json"
22
+ - "scripts/generate-configs.mjs"
23
+ - "package.json"
24
+ - "README.md"
25
+ - "docs/configs/**"
26
+ - "docs/snippets/**"
27
+ - "smithery.yaml"
28
+ - "server.json"
29
+ - ".github/workflows/verify-configs.yml"
30
+ push:
31
+ branches: [main]
32
+ paths:
33
+ - "src/configs/source.json"
34
+ - "scripts/generate-configs.mjs"
35
+ - "package.json"
36
+ - "README.md"
37
+ - "docs/configs/**"
38
+ - "docs/snippets/**"
39
+ - "smithery.yaml"
40
+ - "server.json"
41
+ - ".github/workflows/verify-configs.yml"
42
+
43
+ jobs:
44
+ verify:
45
+ runs-on: ubuntu-latest
46
+ steps:
47
+ - uses: actions/checkout@v4
48
+
49
+ - name: Setup Node
50
+ uses: actions/setup-node@v4
51
+ with:
52
+ node-version: "20"
53
+
54
+ - name: Verify all 15 distribution artifacts are in sync with source.json
55
+ run: node scripts/generate-configs.mjs --check
@@ -0,0 +1,159 @@
1
+ # Contributing to mcp-memory-server
2
+
3
+ This package is the public face of Mnemoverse across every AI tool marketplace. A single typo in an install snippet breaks every Cursor / VS Code / Claude Desktop / Smithery / Official MCP Registry / GitHub README copy of it. To make that impossible, we use a **single source of truth** with mechanical drift detection.
4
+
5
+ > **Read this before editing any install snippet, config, or README install section.** The rules are short, but ignoring them produces silent breakage that we only notice when a user reports it.
6
+
7
+ ---
8
+
9
+ ## The one rule
10
+
11
+ **`src/configs/source.json` is the only file you may edit by hand for distribution metadata.** Everything else is generated and any manual edit will be overwritten — or, worse, will silently drift until CI catches it.
12
+
13
+ Files that are **generated** (never edit by hand):
14
+
15
+ | File | What it powers |
16
+ | ---- | -------------- |
17
+ | `docs/configs/cursor.json` | Cursor `.cursor/mcp.json` snippet |
18
+ | `docs/configs/claude-desktop.json` | Claude Desktop `claude_desktop_config.json` snippet |
19
+ | `docs/configs/windsurf.json` | Windsurf `mcp_config.json` snippet |
20
+ | `docs/configs/vscode.json` | VS Code `.vscode/mcp.json` snippet (uses `servers`, not `mcpServers`) |
21
+ | `docs/configs/cursor-deep-link.txt` | Base64-encoded `cursor://...` install URL |
22
+ | `docs/configs/vscode-deep-link.txt` | URL-encoded `vscode:mcp/install?...` URL |
23
+ | `docs/configs/claude-code-cli.sh` | `claude mcp add ...` shell command |
24
+ | `smithery.yaml` | Smithery.ai `configSchema` + `commandFunction` |
25
+ | `server.json` | Official MCP Registry manifest |
26
+ | `docs/snippets/claude-code.md` | Markdown partial — Claude Code install (consumed by README + docs site) |
27
+ | `docs/snippets/cursor.md` | Markdown partial — Cursor install |
28
+ | `docs/snippets/claude-desktop.md` | Markdown partial — Claude Desktop install |
29
+ | `docs/snippets/vscode.md` | Markdown partial — VS Code install |
30
+ | `docs/snippets/windsurf.md` | Markdown partial — Windsurf install |
31
+ | `README.md` (only the section between `<!-- INSTALL_SNIPPETS_START -->` and `<!-- INSTALL_SNIPPETS_END -->`) | Top-level install section, in-place rewritten by the generator |
32
+
33
+ If your editor pops up a diff in any of these files and you didn't change `src/configs/source.json`, the diff is wrong. Discard it.
34
+
35
+ ## How to change a distribution config
36
+
37
+ ```bash
38
+ # 1. Edit the source
39
+ $EDITOR src/configs/source.json
40
+
41
+ # 2. Regenerate everything
42
+ npm run generate:configs
43
+
44
+ # 3. Verify nothing else drifted
45
+ npm run verify:configs
46
+
47
+ # 4. Commit BOTH the source change AND every regenerated file
48
+ git add src/configs/source.json docs/ smithery.yaml server.json README.md
49
+ git commit -m "..."
50
+ ```
51
+
52
+ If you forget step 2 and push only the source change, **CI will fail on the drift check** before the PR can merge. This is intentional — mechanical enforcement is the whole point.
53
+
54
+ ## CI and the optional pre-push hook
55
+
56
+ There are two layers of drift detection — they catch the same problem at different points and you should not skip either.
57
+
58
+ ### Layer 1: GitHub Actions (mandatory)
59
+
60
+ Every PR runs [`.github/workflows/verify-configs.yml`](.github/workflows/verify-configs.yml), which executes `node scripts/generate-configs.mjs --check`. The job fails the build if any of the 15 generated artifacts (or the README install block) does not match what would be re-emitted from `src/configs/source.json`. **The job is required for merge into `main`.** This is the authoritative gate — it works for forks, blocks PRs, can't be bypassed by `--no-verify`, and protects you from your own typos.
61
+
62
+ ### Layer 2: Local pre-push hook (recommended, opt-in)
63
+
64
+ Faster feedback (~50 ms vs ~30-60 s for CI). Catches the drift before the commit even hits GitHub. Install once per clone:
65
+
66
+ ```bash
67
+ npm run install-hooks
68
+ ```
69
+
70
+ This writes `.git/hooks/pre-push` (per-clone, not committed) that runs `npm run verify:configs` before every push. If it fails, your push is aborted and you get the same `✗ Drift detected: ...` message you would have seen in CI — just locally and 1000× faster.
71
+
72
+ If you ever need to bypass it for a one-off (e.g., pushing a temporary branch you don't care about), use `git push --no-verify`. **Do not bypass for branches that target `main`** — CI will reject them anyway.
73
+
74
+ We deliberately avoid `husky` and `pre-commit` — those would add a dependency and force the hook on everyone, including casual contributors who just want to fix a typo. The opt-in script is one command and zero deps.
75
+
76
+ ## How `npm run generate:configs` works
77
+
78
+ `scripts/generate-configs.mjs` reads `src/configs/source.json` and emits 15 artifacts:
79
+
80
+ 1. **9 distribution configs** in `docs/configs/`, plus `smithery.yaml` and `server.json` at the repo root.
81
+ 2. **5 Markdown partials** in `docs/snippets/` — these are the same install snippets, formatted for inclusion in any Markdown context (README, mnemoverse-docs site pages, llms.txt, etc.).
82
+ 3. **1 in-place rewrite** of the install section in `README.md`, between the `<!-- INSTALL_SNIPPETS_START -->` and `<!-- INSTALL_SNIPPETS_END -->` HTML comment markers. The rest of the README is human-prose and is left untouched.
83
+
84
+ The generator is **idempotent**: running it twice in a row produces zero changes the second time. CI relies on this property — it runs the generator with `--check`, which verifies every output matches what is committed and fails the build otherwise.
85
+
86
+ ## How to add a new distribution channel
87
+
88
+ 1. Add a new generator function in `scripts/generate-configs.mjs` that produces the channel's config from the data already in `source.json` (do NOT introduce a parallel data source — extend `source.json` instead if you need new fields).
89
+ 2. Add the new artifact to the `OUTPUTS` array.
90
+ 3. If the channel needs a Markdown install snippet, also add a `snippet*()` helper and a `docs/snippets/{channel}.md` entry. If the snippet should also appear in README, append it to `readmeInstallBlock()`.
91
+ 4. Update this `CONTRIBUTING.md` table above with the new file.
92
+ 5. Run `npm run generate:configs && npm run verify:configs`. Both must succeed.
93
+ 6. Commit everything together — the source change, the new generator function, the new generated files, and the updated `CONTRIBUTING.md`.
94
+
95
+ ## Things you must not do
96
+
97
+ - ❌ **Edit a generated file directly.** Even a one-character fix will be reverted on the next `generate:configs` and CI will fail in the meantime.
98
+ - ❌ **Bypass the drift check.** Do not pass `--no-verify` or skip CI. The check exists because we got bitten by 8 copies of the same install snippet drifting in different directions.
99
+ - ❌ **Hard-code distribution metadata in `src/index.ts`.** The MCP server source code only knows about tools, transport, and the API URL. Channel-specific stuff lives in `source.json`.
100
+ - ❌ **Create a parallel "config" file alongside `source.json`.** If `source.json` is missing a field you need, add it to `source.json` and update the generator. One source.
101
+
102
+ ## Versioning and releases
103
+
104
+ `package.json#version` → `src/index.ts#version` (server name reported to MCP clients) → `server.json#version` (Official MCP Registry).
105
+
106
+ Today these are bumped manually and kept in sync by hand. If they drift, the generator's drift check on `server.json` will catch it (because `server.json` is generated from `package.json#version`).
107
+
108
+ When releasing:
109
+
110
+ ```bash
111
+ # 1. Bump version in package.json
112
+ $EDITOR package.json
113
+
114
+ # 2. Match it in src/index.ts (search for version: "...")
115
+ $EDITOR src/index.ts
116
+
117
+ # 3. Regenerate (this updates server.json to match)
118
+ npm run generate:configs
119
+
120
+ # 4. Build and run e2e
121
+ npm run build
122
+ # ... live e2e against production ...
123
+
124
+ # 5. Commit, tag, push, publish
125
+ git add -A && git commit -m "chore: release vX.Y.Z"
126
+ git tag -a vX.Y.Z -m "..."
127
+ git push origin main vX.Y.Z
128
+ npm publish
129
+ gh release create vX.Y.Z --notes "..."
130
+ ```
131
+
132
+ A future PR will templatize `src/index.ts#version` so `package.json` is the only place to edit it.
133
+
134
+ ## Testing changes locally
135
+
136
+ The fastest feedback loop is:
137
+
138
+ ```bash
139
+ # Build
140
+ npm run build
141
+
142
+ # Pack into an installable tarball
143
+ npm pack
144
+
145
+ # Smoke test in an isolated dir
146
+ mkdir /tmp/mcp-smoke && cd /tmp/mcp-smoke
147
+ npm init -y >/dev/null
148
+ npm install /path/to/mcp-memory-server/mnemoverse-mcp-memory-server-X.Y.Z.tgz
149
+ MNEMOVERSE_API_KEY=mk_test_fake ./node_modules/.bin/mcp-memory-server
150
+ # → should print "Error: MNEMOVERSE_API_KEY environment variable is required" if unset, or start a stdio MCP server if set
151
+ ```
152
+
153
+ For end-to-end testing against the live API, set a real `mk_live_*` key and pipe a few JSON-RPC messages on stdin (`initialize`, `notifications/initialized`, `tools/call`).
154
+
155
+ ## Who to ask
156
+
157
+ - For the design rationale behind single-source-of-truth: see [PR #6](https://github.com/mnemoverse/mcp-memory-server/pull/6).
158
+ - For the README rewriter design: see [PR #11](https://github.com/mnemoverse/mcp-memory-server/pull/11).
159
+ - For everything else, open an issue.
package/README.md CHANGED
@@ -1,8 +1,13 @@
1
1
  # @mnemoverse/mcp-memory-server
2
2
 
3
- Persistent AI memory for Claude Code, Cursor, VS Code, and any MCP client.
3
+ [![npm version](https://img.shields.io/npm/v/@mnemoverse/mcp-memory-server.svg?color=cb3837&label=npm)](https://www.npmjs.com/package/@mnemoverse/mcp-memory-server)
4
+ [![npm downloads](https://img.shields.io/npm/dm/@mnemoverse/mcp-memory-server.svg?color=blue&label=downloads)](https://www.npmjs.com/package/@mnemoverse/mcp-memory-server)
5
+ [![MCP Registry](https://img.shields.io/badge/MCP_Registry-listed-0ea5e9)](https://registry.modelcontextprotocol.io/v0.1/servers?search=mnemoverse)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT)
4
7
 
5
- Your agent remembers everything across sessions, projects, and tools. One memory, everywhere.
8
+ Shared AI memory across Claude, Cursor, VS Code, ChatGPT, and any MCP client. Write once, recall anywhere.
9
+
10
+ Your agent remembers everything — across sessions, projects, and tools. One API key, one memory, everywhere.
6
11
 
7
12
  ## Quick Start
8
13
 
@@ -12,10 +17,14 @@ Sign up at [console.mnemoverse.com](https://console.mnemoverse.com) — takes 30
12
17
 
13
18
  ### 2. Connect to your AI tool
14
19
 
15
- **Claude Code:**
20
+ <!-- INSTALL_SNIPPETS_START — generated from src/configs/source.json. Run `npm run generate:configs` to refresh. Do not edit by hand. -->
21
+
22
+ **Claude Code** — add via CLI:
16
23
 
17
24
  ```bash
18
- claude mcp add mnemoverse -e MNEMOVERSE_API_KEY=mk_live_YOUR_KEY -- npx @mnemoverse/mcp-memory-server
25
+ claude mcp add mnemoverse \
26
+ -e MNEMOVERSE_API_KEY=mk_live_YOUR_KEY \
27
+ -- npx -y @mnemoverse/mcp-memory-server@latest
19
28
  ```
20
29
 
21
30
  **Cursor** — add to `.cursor/mcp.json`:
@@ -25,7 +34,10 @@ claude mcp add mnemoverse -e MNEMOVERSE_API_KEY=mk_live_YOUR_KEY -- npx @mnemove
25
34
  "mcpServers": {
26
35
  "mnemoverse": {
27
36
  "command": "npx",
28
- "args": ["@mnemoverse/mcp-memory-server"],
37
+ "args": [
38
+ "-y",
39
+ "@mnemoverse/mcp-memory-server@latest"
40
+ ],
29
41
  "env": {
30
42
  "MNEMOVERSE_API_KEY": "mk_live_YOUR_KEY"
31
43
  }
@@ -34,18 +46,20 @@ claude mcp add mnemoverse -e MNEMOVERSE_API_KEY=mk_live_YOUR_KEY -- npx @mnemove
34
46
  }
35
47
  ```
36
48
 
37
- **VS Code** — add to settings.json:
49
+ **VS Code** — add to `.vscode/mcp.json` (note: VS Code uses `servers`, not `mcpServers`):
38
50
 
39
51
  ```json
40
52
  {
41
- "mcp": {
42
- "servers": {
43
- "mnemoverse": {
44
- "command": "npx",
45
- "args": ["@mnemoverse/mcp-memory-server"],
46
- "env": {
47
- "MNEMOVERSE_API_KEY": "mk_live_YOUR_KEY"
48
- }
53
+ "servers": {
54
+ "mnemoverse": {
55
+ "type": "stdio",
56
+ "command": "npx",
57
+ "args": [
58
+ "-y",
59
+ "@mnemoverse/mcp-memory-server@latest"
60
+ ],
61
+ "env": {
62
+ "MNEMOVERSE_API_KEY": "mk_live_YOUR_KEY"
49
63
  }
50
64
  }
51
65
  }
@@ -59,7 +73,10 @@ claude mcp add mnemoverse -e MNEMOVERSE_API_KEY=mk_live_YOUR_KEY -- npx @mnemove
59
73
  "mcpServers": {
60
74
  "mnemoverse": {
61
75
  "command": "npx",
62
- "args": ["@mnemoverse/mcp-memory-server"],
76
+ "args": [
77
+ "-y",
78
+ "@mnemoverse/mcp-memory-server@latest"
79
+ ],
63
80
  "env": {
64
81
  "MNEMOVERSE_API_KEY": "mk_live_YOUR_KEY"
65
82
  }
@@ -68,17 +85,27 @@ claude mcp add mnemoverse -e MNEMOVERSE_API_KEY=mk_live_YOUR_KEY -- npx @mnemove
68
85
  }
69
86
  ```
70
87
 
71
- ### 3. Done
88
+ > Why `@latest`? Bare `npx @mnemoverse/mcp-memory-server` is cached indefinitely by npm and stops re-checking the registry. The `@latest` suffix forces a metadata lookup on every Claude Code / Cursor / VS Code session start (~100-300ms), so you always pick up new releases.
89
+
90
+ <!-- INSTALL_SNIPPETS_END -->
91
+
92
+ > ⚠️ **Restart your AI client** after editing the config. MCP servers are only picked up on client startup.
93
+
94
+ ### 3. Try it — 30 seconds to verify it works
95
+
96
+ Paste this in your AI chat:
97
+
98
+ > **"Remember that my favourite TypeScript framework is Hono, and please call `memory_write` to save it."**
72
99
 
73
- Your AI now has persistent memory. Try:
100
+ Your agent should call `memory_write` and confirm the memory was stored.
74
101
 
75
- > "Remember that I prefer Railway for deployments"
102
+ Then open a **new chat / new session** (this is the whole point — memory survives restarts), and ask:
76
103
 
77
- Then in a new session:
104
+ > **"What's my favourite TypeScript framework?"**
78
105
 
79
- > "Where should I deploy this?"
106
+ Your agent should call `memory_read`, find the entry, and answer "Hono". If it does — you're wired up. Write whatever you want next.
80
107
 
81
- It remembers.
108
+ If it doesn't remember: check that the client was fully restarted and the config has your real `mk_live_...` key, not the placeholder.
82
109
 
83
110
  ## Tools
84
111
 
@@ -88,6 +115,8 @@ It remembers.
88
115
  | `memory_read` | Search memories by natural language query |
89
116
  | `memory_feedback` | Rate memories as helpful or not (improves future recall) |
90
117
  | `memory_stats` | Check how many memories stored, which domains exist |
118
+ | `memory_delete` | Permanently delete a single memory by `atom_id` |
119
+ | `memory_delete_domain` | Wipe an entire domain (requires `confirm: true` safety interlock) |
91
120
 
92
121
  ## Ideas: What to Remember
93
122
 
package/dist/index.js CHANGED
@@ -42,7 +42,7 @@ function capResult(text) {
42
42
  // --- Server setup ---
43
43
  const server = new McpServer({
44
44
  name: "mnemoverse-memory",
45
- version: "0.3.0",
45
+ version: "0.3.1",
46
46
  });
47
47
  // --- Tool: memory_write ---
48
48
  server.registerTool("memory_write", {
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env bash
2
2
  claude mcp add mnemoverse \
3
3
  -e MNEMOVERSE_API_KEY=mk_live_YOUR_KEY \
4
- -- npx -y @mnemoverse/mcp-memory-server
4
+ -- npx -y @mnemoverse/mcp-memory-server@latest
@@ -4,7 +4,7 @@
4
4
  "command": "npx",
5
5
  "args": [
6
6
  "-y",
7
- "@mnemoverse/mcp-memory-server"
7
+ "@mnemoverse/mcp-memory-server@latest"
8
8
  ],
9
9
  "env": {
10
10
  "MNEMOVERSE_API_KEY": "mk_live_YOUR_KEY"
@@ -1 +1 @@
1
- cursor://anysphere.cursor-deeplink/mcp/install?name=mnemoverse&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBtbmVtb3ZlcnNlL21jcC1tZW1vcnktc2VydmVyIl0sImVudiI6eyJNTkVNT1ZFUlNFX0FQSV9LRVkiOiJta19saXZlX1lPVVJfS0VZIn19
1
+ cursor://anysphere.cursor-deeplink/mcp/install?name=mnemoverse&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBtbmVtb3ZlcnNlL21jcC1tZW1vcnktc2VydmVyQGxhdGVzdCJdLCJlbnYiOnsiTU5FTU9WRVJTRV9BUElfS0VZIjoibWtfbGl2ZV9ZT1VSX0tFWSJ9fQ==
@@ -4,7 +4,7 @@
4
4
  "command": "npx",
5
5
  "args": [
6
6
  "-y",
7
- "@mnemoverse/mcp-memory-server"
7
+ "@mnemoverse/mcp-memory-server@latest"
8
8
  ],
9
9
  "env": {
10
10
  "MNEMOVERSE_API_KEY": "mk_live_YOUR_KEY"
@@ -1 +1 @@
1
- vscode:mcp/install?%7B%22name%22%3A%22mnemoverse%22%2C%22type%22%3A%22stdio%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40mnemoverse%2Fmcp-memory-server%22%5D%2C%22env%22%3A%7B%22MNEMOVERSE_API_KEY%22%3A%22mk_live_YOUR_KEY%22%7D%7D
1
+ vscode:mcp/install?%7B%22name%22%3A%22mnemoverse%22%2C%22type%22%3A%22stdio%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40mnemoverse%2Fmcp-memory-server%40latest%22%5D%2C%22env%22%3A%7B%22MNEMOVERSE_API_KEY%22%3A%22mk_live_YOUR_KEY%22%7D%7D
@@ -5,7 +5,7 @@
5
5
  "command": "npx",
6
6
  "args": [
7
7
  "-y",
8
- "@mnemoverse/mcp-memory-server"
8
+ "@mnemoverse/mcp-memory-server@latest"
9
9
  ],
10
10
  "env": {
11
11
  "MNEMOVERSE_API_KEY": "mk_live_YOUR_KEY"
@@ -4,7 +4,7 @@
4
4
  "command": "npx",
5
5
  "args": [
6
6
  "-y",
7
- "@mnemoverse/mcp-memory-server"
7
+ "@mnemoverse/mcp-memory-server@latest"
8
8
  ],
9
9
  "env": {
10
10
  "MNEMOVERSE_API_KEY": "mk_live_YOUR_KEY"
@@ -0,0 +1,9 @@
1
+ <!-- AUTO-GENERATED from src/configs/source.json. Run `npm run generate:configs`. Do not edit by hand. -->
2
+
3
+ **Claude Code** — add via CLI:
4
+
5
+ ```bash
6
+ claude mcp add mnemoverse \
7
+ -e MNEMOVERSE_API_KEY=mk_live_YOUR_KEY \
8
+ -- npx -y @mnemoverse/mcp-memory-server@latest
9
+ ```
@@ -0,0 +1,20 @@
1
+ <!-- AUTO-GENERATED from src/configs/source.json. Run `npm run generate:configs`. Do not edit by hand. -->
2
+
3
+ **Claude Desktop** — add to `claude_desktop_config.json`:
4
+
5
+ ```json
6
+ {
7
+ "mcpServers": {
8
+ "mnemoverse": {
9
+ "command": "npx",
10
+ "args": [
11
+ "-y",
12
+ "@mnemoverse/mcp-memory-server@latest"
13
+ ],
14
+ "env": {
15
+ "MNEMOVERSE_API_KEY": "mk_live_YOUR_KEY"
16
+ }
17
+ }
18
+ }
19
+ }
20
+ ```
@@ -0,0 +1,20 @@
1
+ <!-- AUTO-GENERATED from src/configs/source.json. Run `npm run generate:configs`. Do not edit by hand. -->
2
+
3
+ **Cursor** — add to `.cursor/mcp.json`:
4
+
5
+ ```json
6
+ {
7
+ "mcpServers": {
8
+ "mnemoverse": {
9
+ "command": "npx",
10
+ "args": [
11
+ "-y",
12
+ "@mnemoverse/mcp-memory-server@latest"
13
+ ],
14
+ "env": {
15
+ "MNEMOVERSE_API_KEY": "mk_live_YOUR_KEY"
16
+ }
17
+ }
18
+ }
19
+ }
20
+ ```
@@ -0,0 +1,21 @@
1
+ <!-- AUTO-GENERATED from src/configs/source.json. Run `npm run generate:configs`. Do not edit by hand. -->
2
+
3
+ **VS Code** — add to `.vscode/mcp.json` (note: VS Code uses `servers`, not `mcpServers`):
4
+
5
+ ```json
6
+ {
7
+ "servers": {
8
+ "mnemoverse": {
9
+ "type": "stdio",
10
+ "command": "npx",
11
+ "args": [
12
+ "-y",
13
+ "@mnemoverse/mcp-memory-server@latest"
14
+ ],
15
+ "env": {
16
+ "MNEMOVERSE_API_KEY": "mk_live_YOUR_KEY"
17
+ }
18
+ }
19
+ }
20
+ }
21
+ ```
@@ -0,0 +1,20 @@
1
+ <!-- AUTO-GENERATED from src/configs/source.json. Run `npm run generate:configs`. Do not edit by hand. -->
2
+
3
+ **Windsurf** — add to `~/.codeium/windsurf/mcp_config.json`:
4
+
5
+ ```json
6
+ {
7
+ "mcpServers": {
8
+ "mnemoverse": {
9
+ "command": "npx",
10
+ "args": [
11
+ "-y",
12
+ "@mnemoverse/mcp-memory-server@latest"
13
+ ],
14
+ "env": {
15
+ "MNEMOVERSE_API_KEY": "mk_live_YOUR_KEY"
16
+ }
17
+ }
18
+ }
19
+ }
20
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mnemoverse/mcp-memory-server",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "MCP server for Mnemoverse Memory API — persistent AI memory across Claude Code, Cursor, VS Code, and any MCP client",
5
5
  "type": "module",
6
6
  "bin": {
@@ -14,6 +14,7 @@
14
14
  "start": "node dist/index.js",
15
15
  "generate:configs": "node scripts/generate-configs.mjs",
16
16
  "verify:configs": "node scripts/generate-configs.mjs --check",
17
+ "install-hooks": "node scripts/install-hooks.mjs",
17
18
  "prebuild": "npm run generate:configs",
18
19
  "prepublishOnly": "npm run build"
19
20
  },
@@ -191,16 +191,128 @@ ${envAssignments}
191
191
  return yaml;
192
192
  }
193
193
 
194
+ // ─── Markdown partials ────────────────────────────────────────────────────────
195
+ //
196
+ // These are the SAME install snippets that ship to:
197
+ // - mcp-memory-server/README.md (assembled into the INSTALL_SNIPPETS block)
198
+ // - mnemoverse-docs (synced via cross-repo workflow → docs/.snippets/)
199
+ //
200
+ // One channel = one partial = one place to edit (source.json). The README's
201
+ // install block is rebuilt from these partials in-place — never edit it by hand.
202
+
203
+ const PARTIAL_HEADER =
204
+ "<!-- AUTO-GENERATED from src/configs/source.json. Run `npm run generate:configs`. Do not edit by hand. -->\n\n";
205
+
206
+ function snippetClaudeCodeCli() {
207
+ // shell command, multiline with backslash continuations
208
+ return (
209
+ "**Claude Code** — add via CLI:\n\n" +
210
+ "```bash\n" +
211
+ genClaudeCodeCli().trim() +
212
+ "\n```\n"
213
+ );
214
+ }
215
+
216
+ function snippetMcpServersJson(label, configPath) {
217
+ // Cursor / Claude Desktop / Windsurf — shared mcpServers shape
218
+ const json = JSON.stringify(genMcpServersFormat(), null, 2);
219
+ return (
220
+ `**${label}** — add to \`${configPath}\`:\n\n` +
221
+ "```json\n" +
222
+ json +
223
+ "\n```\n"
224
+ );
225
+ }
226
+
227
+ function snippetVscode() {
228
+ // VS Code uses `servers` (not `mcpServers`) and requires `type: "stdio"`
229
+ const json = JSON.stringify(genVscodeFormat(), null, 2);
230
+ return (
231
+ "**VS Code** — add to `.vscode/mcp.json` (note: VS Code uses `servers`, not `mcpServers`):\n\n" +
232
+ "```json\n" +
233
+ json +
234
+ "\n```\n"
235
+ );
236
+ }
237
+
238
+ const WHY_LATEST_NOTE =
239
+ "> Why `@latest`? Bare `npx @mnemoverse/mcp-memory-server` is cached indefinitely by npm and stops re-checking the registry. The `@latest` suffix forces a metadata lookup on every Claude Code / Cursor / VS Code session start (~100-300ms), so you always pick up new releases.";
240
+
241
+ /**
242
+ * Build the README install block contents (without the START/END markers).
243
+ * The order here matches the README — change here, README rewrites itself.
244
+ */
245
+ function readmeInstallBlock() {
246
+ return [
247
+ snippetClaudeCodeCli(),
248
+ snippetMcpServersJson("Cursor", ".cursor/mcp.json"),
249
+ snippetVscode(),
250
+ snippetMcpServersJson("Windsurf", "~/.codeium/windsurf/mcp_config.json"),
251
+ WHY_LATEST_NOTE,
252
+ ].join("\n");
253
+ }
254
+
255
+ // ─── README in-place rewriter ─────────────────────────────────────────────────
256
+
257
+ const README_START =
258
+ "<!-- INSTALL_SNIPPETS_START — generated from src/configs/source.json. Run `npm run generate:configs` to refresh. Do not edit by hand. -->";
259
+ const README_END = "<!-- INSTALL_SNIPPETS_END -->";
260
+
261
+ /**
262
+ * Take current README content + the freshly assembled install block and return
263
+ * the rewritten README content. Idempotent.
264
+ *
265
+ * Throws if the markers are missing — that means a contributor stripped them
266
+ * out and we don't know where to inject the snippets, so we fail loudly
267
+ * instead of silently doing the wrong thing.
268
+ */
269
+ function rewriteReadme(currentReadme, freshBlock) {
270
+ const startIdx = currentReadme.indexOf("<!-- INSTALL_SNIPPETS_START");
271
+ const endIdx = currentReadme.indexOf("<!-- INSTALL_SNIPPETS_END -->");
272
+
273
+ if (startIdx === -1 || endIdx === -1) {
274
+ throw new Error(
275
+ "README.md is missing the INSTALL_SNIPPETS_START / INSTALL_SNIPPETS_END markers.\n" +
276
+ "These markers tell the generator where to inject the install snippets.\n" +
277
+ "Restore them around the install section and re-run `npm run generate:configs`.",
278
+ );
279
+ }
280
+ if (startIdx >= endIdx) {
281
+ throw new Error(
282
+ "README.md INSTALL_SNIPPETS_END marker appears before INSTALL_SNIPPETS_START.",
283
+ );
284
+ }
285
+
286
+ const before = currentReadme.slice(0, startIdx);
287
+ const after = currentReadme.slice(endIdx + README_END.length);
288
+
289
+ return `${before}${README_START}\n\n${freshBlock}\n\n${README_END}${after}`;
290
+ }
291
+
194
292
  /**
195
293
  * Official MCP Registry server.json.
196
294
  *
197
295
  * https://registry.modelcontextprotocol.io/
198
- * Schema: https://static.modelcontextprotocol.io/schemas/2025-09-29/server.schema.json
296
+ * Schema: https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json
297
+ *
298
+ * The canonical shape was verified empirically by running `mcp-publisher init`
299
+ * in a sandbox and matching its output. Key differences vs the older
300
+ * 2025-09-29 schema: registryName → registryType, packages[0].name →
301
+ * packages[0].identifier, new required `transport` object, dropped
302
+ * runtimeArguments (the registry runtime builds its own launch command
303
+ * from identifier + version), and environmentVariables entries gained a
304
+ * `format` field.
305
+ *
306
+ * The `@latest` pin we use in docs/configs/* does NOT belong here — that
307
+ * is for direct JSON-snippet installs where users stay on the bleeding
308
+ * edge. Registry-installed clients get the exact pinned version from
309
+ * server.json.version and we re-publish on each npm release to advance
310
+ * them.
199
311
  */
200
312
  function genServerJson() {
201
313
  return {
202
314
  $schema:
203
- "https://static.modelcontextprotocol.io/schemas/2025-09-29/server.schema.json",
315
+ "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
204
316
  name: "io.github.mnemoverse/mcp-memory-server",
205
317
  description: source.description,
206
318
  repository: {
@@ -210,14 +322,17 @@ function genServerJson() {
210
322
  version: PACKAGE_VERSION,
211
323
  packages: [
212
324
  {
213
- registryName: source.package.registry,
214
- name: source.package.name,
325
+ registryType: source.package.registry,
326
+ identifier: source.package.name,
215
327
  version: PACKAGE_VERSION,
216
- runtimeArguments: source.args.slice(1), // skip "-y"
328
+ transport: {
329
+ type: "stdio",
330
+ },
217
331
  environmentVariables: Object.entries(source.env).map(([key, meta]) => ({
218
332
  name: key,
219
333
  description: meta.description,
220
334
  isRequired: meta.required ?? false,
335
+ format: "string",
221
336
  isSecret: meta.secret ?? false,
222
337
  })),
223
338
  },
@@ -264,6 +379,35 @@ const OUTPUTS = [
264
379
  path: "server.json",
265
380
  content: JSON.stringify(genServerJson(), null, 2) + "\n",
266
381
  },
382
+ // ─── Markdown partials (consumed by README + mnemoverse-docs) ──────────────
383
+ {
384
+ path: "docs/snippets/claude-code.md",
385
+ content: PARTIAL_HEADER + snippetClaudeCodeCli(),
386
+ },
387
+ {
388
+ path: "docs/snippets/cursor.md",
389
+ content:
390
+ PARTIAL_HEADER + snippetMcpServersJson("Cursor", ".cursor/mcp.json"),
391
+ },
392
+ {
393
+ path: "docs/snippets/claude-desktop.md",
394
+ content:
395
+ PARTIAL_HEADER +
396
+ snippetMcpServersJson("Claude Desktop", "claude_desktop_config.json"),
397
+ },
398
+ {
399
+ path: "docs/snippets/vscode.md",
400
+ content: PARTIAL_HEADER + snippetVscode(),
401
+ },
402
+ {
403
+ path: "docs/snippets/windsurf.md",
404
+ content:
405
+ PARTIAL_HEADER +
406
+ snippetMcpServersJson(
407
+ "Windsurf",
408
+ "~/.codeium/windsurf/mcp_config.json",
409
+ ),
410
+ },
267
411
  ];
268
412
 
269
413
  // ─── Write files ─────────────────────────────────────────────────────────────
@@ -297,10 +441,55 @@ for (const { path, content } of OUTPUTS) {
297
441
  written++;
298
442
  }
299
443
 
444
+ // ─── README install block (in-place rewrite) ────────────────────────────────
445
+ //
446
+ // Special-cased because README is read-modify-write — we can only update the
447
+ // region between the INSTALL_SNIPPETS markers, the rest of the file is human-
448
+ // authored prose.
449
+
450
+ const README_PATH = resolve(ROOT, "README.md");
451
+
452
+ if (!existsSync(README_PATH)) {
453
+ console.error(`✗ README.md not found at ${README_PATH}`);
454
+ process.exit(1);
455
+ }
456
+
457
+ const currentReadme = readFileSync(README_PATH, "utf8");
458
+ let freshReadme;
459
+ try {
460
+ freshReadme = rewriteReadme(currentReadme, readmeInstallBlock());
461
+ } catch (err) {
462
+ console.error("✗ Cannot rewrite README.md install block:");
463
+ console.error(" " + (err.message || err).split("\n").join("\n "));
464
+ process.exit(1);
465
+ }
466
+
467
+ if (currentReadme === freshReadme) {
468
+ unchanged++;
469
+ } else if (checkMode) {
470
+ console.error("✗ Drift detected: README.md install block is stale");
471
+ console.error(
472
+ " The INSTALL_SNIPPETS_START/END region in README.md does not match",
473
+ );
474
+ console.error(
475
+ " what the generator would emit from src/configs/source.json.",
476
+ );
477
+ console.error(" Run `npm run generate:configs` and commit the result.");
478
+ process.exit(1);
479
+ } else {
480
+ writeFileSync(README_PATH, freshReadme, "utf8");
481
+ console.log("✓ Generated README.md (install block)");
482
+ written++;
483
+ }
484
+
485
+ const totalArtifacts = OUTPUTS.length + 1; // +1 for README
486
+
300
487
  if (checkMode) {
301
- console.log(`✓ All ${OUTPUTS.length} configs in sync with source.json`);
488
+ console.log(
489
+ `✓ All ${totalArtifacts} artifacts in sync with source.json`,
490
+ );
302
491
  } else {
303
492
  console.log(
304
- `\nDone: ${written} written, ${unchanged} unchanged (${OUTPUTS.length} total)`,
493
+ `\nDone: ${written} written, ${unchanged} unchanged (${totalArtifacts} total)`,
305
494
  );
306
495
  }
@@ -0,0 +1,76 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * install-hooks.mjs
4
+ *
5
+ * Installs the optional pre-push hook for local drift detection. The hook
6
+ * runs `npm run verify:configs` before every push and aborts if any of the
7
+ * 15 generated artifacts is out of sync with src/configs/source.json.
8
+ *
9
+ * The hook is per-clone (.git/hooks/ is not committed) and opt-in. CI is
10
+ * the authoritative gate — see .github/workflows/verify-configs.yml.
11
+ *
12
+ * Usage: npm run install-hooks
13
+ */
14
+
15
+ import {
16
+ writeFileSync,
17
+ chmodSync,
18
+ existsSync,
19
+ mkdirSync,
20
+ } from "node:fs";
21
+ import { resolve, dirname } from "node:path";
22
+ import { fileURLToPath } from "node:url";
23
+
24
+ const __dirname = dirname(fileURLToPath(import.meta.url));
25
+ const ROOT = resolve(__dirname, "..");
26
+ const HOOKS_DIR = resolve(ROOT, ".git/hooks");
27
+ const HOOK_PATH = resolve(HOOKS_DIR, "pre-push");
28
+
29
+ if (!existsSync(resolve(ROOT, ".git"))) {
30
+ console.error(
31
+ "✗ Not a git repo (no .git directory found at " + ROOT + ").",
32
+ );
33
+ console.error(" Cannot install pre-push hook.");
34
+ process.exit(1);
35
+ }
36
+
37
+ mkdirSync(HOOKS_DIR, { recursive: true });
38
+
39
+ const HOOK_BODY = `#!/usr/bin/env bash
40
+ # Auto-generated by scripts/install-hooks.mjs.
41
+ # Aborts the push if any of the 15 distribution artifacts has drifted from
42
+ # src/configs/source.json. Re-run install-hooks after pulling generator changes.
43
+ #
44
+ # To bypass for a one-off (NOT recommended for branches targeting main):
45
+ # git push --no-verify
46
+
47
+ set -e
48
+
49
+ # Find repo root so the hook works regardless of where 'git push' was invoked.
50
+ REPO_ROOT="$(git rev-parse --show-toplevel)"
51
+ cd "$REPO_ROOT"
52
+
53
+ if ! command -v node >/dev/null 2>&1; then
54
+ echo "pre-push: node not found in PATH; skipping drift check"
55
+ exit 0
56
+ fi
57
+
58
+ echo "pre-push: verifying distribution config drift..."
59
+ if ! node scripts/generate-configs.mjs --check; then
60
+ echo ""
61
+ echo "✗ Push aborted: distribution configs are out of sync with src/configs/source.json"
62
+ echo " Run \\\`npm run generate:configs\\\` to fix, commit the result, then push again."
63
+ echo " See CONTRIBUTING.md for details."
64
+ exit 1
65
+ fi
66
+ `;
67
+
68
+ writeFileSync(HOOK_PATH, HOOK_BODY, "utf8");
69
+ chmodSync(HOOK_PATH, 0o755);
70
+
71
+ console.log("✓ Installed pre-push hook at " + HOOK_PATH);
72
+ console.log(" It will run `node scripts/generate-configs.mjs --check`");
73
+ console.log(" before every push and abort on drift.");
74
+ console.log("");
75
+ console.log(" To remove: rm " + HOOK_PATH);
76
+ console.log(" To bypass once: git push --no-verify");
package/server.json CHANGED
@@ -1,25 +1,26 @@
1
1
  {
2
- "$schema": "https://static.modelcontextprotocol.io/schemas/2025-09-29/server.schema.json",
2
+ "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
3
3
  "name": "io.github.mnemoverse/mcp-memory-server",
4
- "description": "Persistent memory for AI agents write once, recall anywhere across all your AI tools",
4
+ "description": "Shared AI memory across Claude, Cursor, VS Code, ChatGPT. Write once, recall anywhere.",
5
5
  "repository": {
6
6
  "url": "https://github.com/mnemoverse/mcp-memory-server",
7
7
  "source": "github"
8
8
  },
9
- "version": "0.3.0",
9
+ "version": "0.3.1",
10
10
  "packages": [
11
11
  {
12
- "registryName": "npm",
13
- "name": "@mnemoverse/mcp-memory-server",
14
- "version": "0.3.0",
15
- "runtimeArguments": [
16
- "@mnemoverse/mcp-memory-server"
17
- ],
12
+ "registryType": "npm",
13
+ "identifier": "@mnemoverse/mcp-memory-server",
14
+ "version": "0.3.1",
15
+ "transport": {
16
+ "type": "stdio"
17
+ },
18
18
  "environmentVariables": [
19
19
  {
20
20
  "name": "MNEMOVERSE_API_KEY",
21
21
  "description": "Your Mnemoverse API key (starts with mk_live_). Get one free at https://console.mnemoverse.com",
22
22
  "isRequired": true,
23
+ "format": "string",
23
24
  "isSecret": true
24
25
  }
25
26
  ]
package/smithery.yaml CHANGED
@@ -17,7 +17,7 @@ startCommand:
17
17
  |-
18
18
  (config) => ({
19
19
  command: 'npx',
20
- args: ["-y","@mnemoverse/mcp-memory-server"],
20
+ args: ["-y","@mnemoverse/mcp-memory-server@latest"],
21
21
  env: {
22
22
  MNEMOVERSE_API_KEY: config.mnemoverseApiKey,
23
23
  }
@@ -2,10 +2,10 @@
2
2
  "$comment": "SINGLE SOURCE OF TRUTH for all distribution channel configs. Edit this file → run `npm run generate:configs` → all 9+ artifacts regenerate. CI verifies committed artifacts match source.",
3
3
  "name": "mnemoverse",
4
4
  "displayName": "Mnemoverse Memory",
5
- "description": "Persistent memory for AI agents write once, recall anywhere across all your AI tools",
5
+ "description": "Shared AI memory across Claude, Cursor, VS Code, ChatGPT. Write once, recall anywhere.",
6
6
  "type": "stdio",
7
7
  "command": "npx",
8
- "args": ["-y", "@mnemoverse/mcp-memory-server"],
8
+ "args": ["-y", "@mnemoverse/mcp-memory-server@latest"],
9
9
  "env": {
10
10
  "MNEMOVERSE_API_KEY": {
11
11
  "value": "mk_live_YOUR_KEY",
package/src/index.ts CHANGED
@@ -59,7 +59,7 @@ function capResult(text: string): string {
59
59
 
60
60
  const server = new McpServer({
61
61
  name: "mnemoverse-memory",
62
- version: "0.3.0",
62
+ version: "0.3.1",
63
63
  });
64
64
 
65
65
  // --- Tool: memory_write ---