@mnemoverse/mcp-memory-server 0.1.1 → 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
@@ -4,6 +4,10 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
4
4
  import { z } from "zod";
5
5
  const API_URL = process.env.MNEMOVERSE_API_URL || "https://core.mnemoverse.com/api/v1";
6
6
  const API_KEY = process.env.MNEMOVERSE_API_KEY || "";
7
+ // Hard cap on tool result size — required by Claude Connectors Directory
8
+ // (https://support.claude.com/en/articles/12922490-remote-mcp-server-submission-guide).
9
+ // Approximate token count = chars / 4. Cap at 24,000 tokens to leave headroom under the 25K limit.
10
+ const MAX_RESULT_CHARS = 24_000 * 4;
7
11
  if (!API_KEY) {
8
12
  console.error("Error: MNEMOVERSE_API_KEY environment variable is required.\n" +
9
13
  "Get your free key at https://console.mnemoverse.com");
@@ -24,26 +28,47 @@ async function apiFetch(path, options = {}) {
24
28
  }
25
29
  return res.json();
26
30
  }
31
+ /**
32
+ * Truncate a result string to MAX_RESULT_CHARS, appending a notice if truncated.
33
+ * Required by Claude Connectors Directory submission policy.
34
+ */
35
+ function capResult(text) {
36
+ if (text.length <= MAX_RESULT_CHARS)
37
+ return text;
38
+ const truncated = text.slice(0, MAX_RESULT_CHARS - 200);
39
+ return (truncated +
40
+ `\n\n[…truncated to fit 25K token limit. Use a more specific query or smaller top_k to see all results.]`);
41
+ }
27
42
  // --- Server setup ---
28
43
  const server = new McpServer({
29
44
  name: "mnemoverse-memory",
30
- version: "0.1.0",
45
+ version: "0.3.1",
31
46
  });
32
47
  // --- Tool: memory_write ---
33
- server.tool("memory_write", "Store a memory that should persist across sessions — preferences, decisions, lessons learned, project facts, people and roles. Call this PROACTIVELY whenever the user states a preference, makes a decision, or you learn something important. Don't wait to be asked — if it's worth remembering, store it now.", {
34
- content: z
35
- .string()
36
- .min(1)
37
- .max(10000)
38
- .describe("The memory to store — what happened, what was learned"),
39
- concepts: z
40
- .array(z.string())
41
- .optional()
42
- .describe("Key concepts for linking related memories (e.g. ['deploy', 'friday', 'staging'])"),
43
- domain: z
44
- .string()
45
- .optional()
46
- .describe("Namespace to organize memories (e.g. 'engineering', 'user:alice', 'project:acme')"),
48
+ server.registerTool("memory_write", {
49
+ description: "Store a memory that should persist across sessions — preferences, decisions, lessons learned, project facts, people and roles. Memories you store are also accessible from Claude, ChatGPT, Cursor, VS Code, and any other AI tool the user connects to Mnemoverse — write once, recall everywhere. Call this PROACTIVELY whenever the user states a preference, makes a decision, or you learn something important. Don't wait to be asked — if it's worth remembering, store it now.",
50
+ inputSchema: {
51
+ content: z
52
+ .string()
53
+ .min(1)
54
+ .max(10000)
55
+ .describe("The memory to store — what happened, what was learned"),
56
+ concepts: z
57
+ .array(z.string())
58
+ .optional()
59
+ .describe("Key concepts for linking related memories (e.g. ['deploy', 'friday', 'staging'])"),
60
+ domain: z
61
+ .string()
62
+ .optional()
63
+ .describe("Namespace to organize memories (e.g. 'engineering', 'user:alice', 'project:acme')"),
64
+ },
65
+ annotations: {
66
+ title: "Store Memory",
67
+ readOnlyHint: false,
68
+ destructiveHint: false,
69
+ idempotentHint: false,
70
+ openWorldHint: true,
71
+ },
47
72
  }, async ({ content, concepts, domain }) => {
48
73
  const result = await apiFetch("/memory/write", {
49
74
  method: "POST",
@@ -74,23 +99,33 @@ server.tool("memory_write", "Store a memory that should persist across sessions
74
99
  };
75
100
  });
76
101
  // --- Tool: memory_read ---
77
- server.tool("memory_read", "ALWAYS call this tool first when the user asks a question about preferences, past decisions, project setup, people, or anything that might have been discussed before. This is your long-term memory — it persists across sessions and tools. Search by natural language query. If you have any doubt whether you know something — check memory first.", {
78
- query: z
79
- .string()
80
- .min(1)
81
- .max(5000)
82
- .describe("Natural language query — what are you looking for?"),
83
- top_k: z
84
- .number()
85
- .int()
86
- .min(1)
87
- .max(50)
88
- .optional()
89
- .describe("Max results to return (default: 5)"),
90
- domain: z
91
- .string()
92
- .optional()
93
- .describe("Filter by domain namespace"),
102
+ server.registerTool("memory_read", {
103
+ description: "ALWAYS call this tool first when the user asks a question about preferences, past decisions, project setup, people, or anything that might have been discussed before. This is your long-term memory — it persists across sessions and tools (Claude, ChatGPT, Cursor, VS Code, and any other AI tool the user connects). Search by natural language query. If you have any doubt whether you know something — check memory first.",
104
+ inputSchema: {
105
+ query: z
106
+ .string()
107
+ .min(1)
108
+ .max(5000)
109
+ .describe("Natural language query — what are you looking for?"),
110
+ top_k: z
111
+ .number()
112
+ .int()
113
+ .min(1)
114
+ .max(50)
115
+ .optional()
116
+ .describe("Max results to return (default: 5)"),
117
+ domain: z
118
+ .string()
119
+ .optional()
120
+ .describe("Filter by domain namespace"),
121
+ },
122
+ annotations: {
123
+ title: "Search Memories",
124
+ readOnlyHint: true,
125
+ destructiveHint: false,
126
+ idempotentHint: true,
127
+ openWorldHint: true,
128
+ },
94
129
  }, async ({ query, top_k, domain }) => {
95
130
  const result = await apiFetch("/memory/read", {
96
131
  method: "POST",
@@ -113,26 +148,37 @@ server.tool("memory_read", "ALWAYS call this tool first when the user asks a que
113
148
  (item.concepts.length > 0
114
149
  ? ` (${item.concepts.join(", ")})`
115
150
  : ""));
151
+ const text = lines.join("\n\n") + `\n\n(${r.search_time_ms.toFixed(0)}ms)`;
116
152
  return {
117
153
  content: [
118
154
  {
119
155
  type: "text",
120
- text: lines.join("\n\n") + `\n\n(${r.search_time_ms.toFixed(0)}ms)`,
156
+ text: capResult(text),
121
157
  },
122
158
  ],
123
159
  };
124
160
  });
125
161
  // --- Tool: memory_feedback ---
126
- server.tool("memory_feedback", "Report whether a retrieved memory was helpful. Positive feedback makes memories easier to find next time. Negative feedback lets them fade. Call this after using memories from memory_read.", {
127
- atom_ids: z
128
- .array(z.string())
129
- .min(1)
130
- .describe("IDs of memories to give feedback on (from memory_read results)"),
131
- outcome: z
132
- .number()
133
- .min(-1)
134
- .max(1)
135
- .describe("How helpful was this? 1.0 = very helpful, 0 = neutral, -1.0 = harmful/wrong"),
162
+ server.registerTool("memory_feedback", {
163
+ description: "Report whether a retrieved memory was helpful. Positive feedback makes memories easier to find next time across all tools. Negative feedback lets them fade. Call this after using memories from memory_read.",
164
+ inputSchema: {
165
+ atom_ids: z
166
+ .array(z.string())
167
+ .min(1)
168
+ .describe("IDs of memories to give feedback on (from memory_read results)"),
169
+ outcome: z
170
+ .number()
171
+ .min(-1)
172
+ .max(1)
173
+ .describe("How helpful was this? 1.0 = very helpful, 0 = neutral, -1.0 = harmful/wrong"),
174
+ },
175
+ annotations: {
176
+ title: "Rate Memory Helpfulness",
177
+ readOnlyHint: false,
178
+ destructiveHint: false,
179
+ idempotentHint: false,
180
+ openWorldHint: true,
181
+ },
136
182
  }, async ({ atom_ids, outcome }) => {
137
183
  const result = await apiFetch("/memory/feedback", {
138
184
  method: "POST",
@@ -149,7 +195,17 @@ server.tool("memory_feedback", "Report whether a retrieved memory was helpful. P
149
195
  };
150
196
  });
151
197
  // --- Tool: memory_stats ---
152
- server.tool("memory_stats", "Get memory statistics — how many memories are stored, which domains exist, average quality scores. Useful for understanding the current state of memory.", {}, async () => {
198
+ server.registerTool("memory_stats", {
199
+ description: "Get memory statistics — how many memories are stored, which domains exist, average quality scores. These memories are shared with all AI tools the user has connected to Mnemoverse. Useful for understanding the current state of memory.",
200
+ inputSchema: {},
201
+ annotations: {
202
+ title: "Memory Statistics",
203
+ readOnlyHint: true,
204
+ destructiveHint: false,
205
+ idempotentHint: true,
206
+ openWorldHint: true,
207
+ },
208
+ }, async () => {
153
209
  const result = await apiFetch("/memory/stats");
154
210
  const r = result;
155
211
  const text = [
@@ -160,6 +216,85 @@ server.tool("memory_stats", "Get memory statistics — how many memories are sto
160
216
  ].join("\n");
161
217
  return { content: [{ type: "text", text }] };
162
218
  });
219
+ // --- Tool: memory_delete ---
220
+ server.registerTool("memory_delete", {
221
+ description: "Permanently delete a single memory by its atom_id. Use when the user explicitly asks to forget something specific, or when you stored a wrong fact that needs correcting. The deletion is irreversible — the memory is gone for good. For broad cleanup of an entire topic, prefer memory_delete_domain.",
222
+ inputSchema: {
223
+ atom_id: z
224
+ .string()
225
+ .min(1)
226
+ .describe("The atom_id of the memory to delete (from memory_read results — each item has an id)"),
227
+ },
228
+ annotations: {
229
+ title: "Delete a Memory",
230
+ readOnlyHint: false,
231
+ destructiveHint: true,
232
+ idempotentHint: true,
233
+ openWorldHint: true,
234
+ },
235
+ }, async ({ atom_id }) => {
236
+ const result = await apiFetch(`/memory/atoms/${encodeURIComponent(atom_id)}`, {
237
+ method: "DELETE",
238
+ });
239
+ // Core API returns { deleted: <count>, atom_id }. count == 0 means
240
+ // the atom didn't exist (or was already removed). count >= 1 means it was deleted.
241
+ const r = result;
242
+ if (!r.deleted) {
243
+ return {
244
+ content: [
245
+ {
246
+ type: "text",
247
+ text: `No memory found with id ${atom_id}.`,
248
+ },
249
+ ],
250
+ };
251
+ }
252
+ return {
253
+ content: [
254
+ {
255
+ type: "text",
256
+ text: `Deleted memory ${atom_id}.`,
257
+ },
258
+ ],
259
+ };
260
+ });
261
+ // --- Tool: memory_delete_domain ---
262
+ server.registerTool("memory_delete_domain", {
263
+ description: "Permanently delete ALL memories in a given domain. Use when the user wants to clean up an entire topic — e.g., 'forget everything about project X' or 'wipe my benchmark experiments'. The deletion is irreversible. List domains first with memory_stats to confirm the exact name. Refuse to call this without an explicit user request — it is much more destructive than memory_delete.",
264
+ inputSchema: {
265
+ domain: z
266
+ .string()
267
+ .min(1)
268
+ .max(200)
269
+ .describe("The domain namespace to wipe (e.g., 'project:old', 'experiments-2025'). Must match exactly."),
270
+ confirm: z
271
+ .literal(true)
272
+ .describe("Must be exactly true to proceed. Acts as a safety interlock against accidental invocation."),
273
+ },
274
+ annotations: {
275
+ title: "Delete an Entire Memory Domain",
276
+ readOnlyHint: false,
277
+ destructiveHint: true,
278
+ idempotentHint: true,
279
+ openWorldHint: true,
280
+ },
281
+ }, async ({ domain, confirm }) => {
282
+ if (confirm !== true) {
283
+ throw new Error("memory_delete_domain requires confirm=true as a safety interlock.");
284
+ }
285
+ const result = await apiFetch(`/memory/domain/${encodeURIComponent(domain)}`, {
286
+ method: "DELETE",
287
+ });
288
+ const r = result;
289
+ return {
290
+ content: [
291
+ {
292
+ type: "text",
293
+ text: `Deleted ${r.deleted} ${r.deleted === 1 ? "memory" : "memories"} from domain "${r.domain}".`,
294
+ },
295
+ ],
296
+ };
297
+ });
163
298
  // --- Start ---
164
299
  async function main() {
165
300
  const transport = new StdioServerTransport();
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}