@mnemoverse/mcp-memory-server 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +131 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +172 -0
- package/dist/index.js.map +1 -0
- package/llms.txt +52 -0
- package/package.json +44 -0
- package/src/index.ts +251 -0
- package/tsconfig.json +15 -0
package/README.md
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# @mnemoverse/mcp-memory-server
|
|
2
|
+
|
|
3
|
+
Persistent AI memory for Claude Code, Cursor, VS Code, and any MCP client.
|
|
4
|
+
|
|
5
|
+
Your agent remembers everything — across sessions, projects, and tools. One memory, everywhere.
|
|
6
|
+
|
|
7
|
+
## Quick Start
|
|
8
|
+
|
|
9
|
+
### 1. Get a free API key
|
|
10
|
+
|
|
11
|
+
Sign up at [console.mnemoverse.com](https://console.mnemoverse.com) — takes 30 seconds, no credit card.
|
|
12
|
+
|
|
13
|
+
### 2. Connect to your AI tool
|
|
14
|
+
|
|
15
|
+
**Claude Code:**
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
claude mcp add mnemoverse -e MNEMOVERSE_API_KEY=mk_live_YOUR_KEY -- npx @mnemoverse/mcp-memory-server
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
**Cursor** — add to `.cursor/mcp.json`:
|
|
22
|
+
|
|
23
|
+
```json
|
|
24
|
+
{
|
|
25
|
+
"mcpServers": {
|
|
26
|
+
"mnemoverse": {
|
|
27
|
+
"command": "npx",
|
|
28
|
+
"args": ["@mnemoverse/mcp-memory-server"],
|
|
29
|
+
"env": {
|
|
30
|
+
"MNEMOVERSE_API_KEY": "mk_live_YOUR_KEY"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
**VS Code** — add to settings.json:
|
|
38
|
+
|
|
39
|
+
```json
|
|
40
|
+
{
|
|
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
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
**Windsurf** — add to `~/.codeium/windsurf/mcp_config.json`:
|
|
56
|
+
|
|
57
|
+
```json
|
|
58
|
+
{
|
|
59
|
+
"mcpServers": {
|
|
60
|
+
"mnemoverse": {
|
|
61
|
+
"command": "npx",
|
|
62
|
+
"args": ["@mnemoverse/mcp-memory-server"],
|
|
63
|
+
"env": {
|
|
64
|
+
"MNEMOVERSE_API_KEY": "mk_live_YOUR_KEY"
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### 3. Done
|
|
72
|
+
|
|
73
|
+
Your AI now has persistent memory. Try:
|
|
74
|
+
|
|
75
|
+
> "Remember that I prefer Railway for deployments"
|
|
76
|
+
|
|
77
|
+
Then in a new session:
|
|
78
|
+
|
|
79
|
+
> "Where should I deploy this?"
|
|
80
|
+
|
|
81
|
+
It remembers.
|
|
82
|
+
|
|
83
|
+
## Tools
|
|
84
|
+
|
|
85
|
+
| Tool | What it does |
|
|
86
|
+
|------|-------------|
|
|
87
|
+
| `memory_write` | Store a memory — insight, preference, lesson learned |
|
|
88
|
+
| `memory_read` | Search memories by natural language query |
|
|
89
|
+
| `memory_feedback` | Rate memories as helpful or not (improves future recall) |
|
|
90
|
+
| `memory_stats` | Check how many memories stored, which domains exist |
|
|
91
|
+
|
|
92
|
+
## Ideas: What to Remember
|
|
93
|
+
|
|
94
|
+
- **User preferences**: "I use dark mode", "I prefer Tailwind over CSS modules"
|
|
95
|
+
- **Project context**: "This project uses PostgreSQL + Prisma", "Deploy to Railway"
|
|
96
|
+
- **Lessons learned**: "Always run tests before push on this repo"
|
|
97
|
+
- **Decisions made**: "We chose REST over GraphQL because of caching simplicity"
|
|
98
|
+
- **People & roles**: "Alice is the designer, Bob owns the API"
|
|
99
|
+
- **Past mistakes**: "Don't deploy on Fridays — learned this the hard way"
|
|
100
|
+
|
|
101
|
+
## Universal Memory
|
|
102
|
+
|
|
103
|
+
The same API key works across all tools. Write a memory in Claude Code — read it in Cursor. Learn something in VS Code — your GPT Custom Action knows it too.
|
|
104
|
+
|
|
105
|
+
```
|
|
106
|
+
┌── Claude Code (this MCP server)
|
|
107
|
+
├── Cursor (this MCP server)
|
|
108
|
+
Mnemoverse API ──├── VS Code (this MCP server)
|
|
109
|
+
(one memory) ├── GPT (Custom Actions)
|
|
110
|
+
├── Python SDK (pip install mnemoverse)
|
|
111
|
+
└── REST API (curl)
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Configuration
|
|
115
|
+
|
|
116
|
+
| Env Variable | Required | Default |
|
|
117
|
+
|-------------|----------|---------|
|
|
118
|
+
| `MNEMOVERSE_API_KEY` | Yes | — |
|
|
119
|
+
| `MNEMOVERSE_API_URL` | No | `https://core.mnemoverse.com/api/v1` |
|
|
120
|
+
|
|
121
|
+
## Links
|
|
122
|
+
|
|
123
|
+
- [Documentation](https://mnemoverse.com/docs/api/mcp-server)
|
|
124
|
+
- [Python SDK](https://mnemoverse.com/docs/api/python-sdk)
|
|
125
|
+
- [API Reference](https://mnemoverse.com/docs/api/reference)
|
|
126
|
+
- [Console (get API key)](https://console.mnemoverse.com)
|
|
127
|
+
- [GitHub](https://github.com/mnemoverse/mcp-memory-server)
|
|
128
|
+
|
|
129
|
+
## License
|
|
130
|
+
|
|
131
|
+
MIT
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
const API_URL = process.env.MNEMOVERSE_API_URL || "https://core.mnemoverse.com/api/v1";
|
|
6
|
+
const API_KEY = process.env.MNEMOVERSE_API_KEY || "";
|
|
7
|
+
if (!API_KEY) {
|
|
8
|
+
console.error("Error: MNEMOVERSE_API_KEY environment variable is required.\n" +
|
|
9
|
+
"Get your free key at https://console.mnemoverse.com");
|
|
10
|
+
process.exit(1);
|
|
11
|
+
}
|
|
12
|
+
async function apiFetch(path, options = {}) {
|
|
13
|
+
const res = await fetch(`${API_URL}${path}`, {
|
|
14
|
+
...options,
|
|
15
|
+
headers: {
|
|
16
|
+
"Content-Type": "application/json",
|
|
17
|
+
"X-Api-Key": API_KEY,
|
|
18
|
+
...(options.headers || {}),
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
if (!res.ok) {
|
|
22
|
+
const text = await res.text();
|
|
23
|
+
throw new Error(`Mnemoverse API error ${res.status}: ${text}`);
|
|
24
|
+
}
|
|
25
|
+
return res.json();
|
|
26
|
+
}
|
|
27
|
+
// --- Server setup ---
|
|
28
|
+
const server = new McpServer({
|
|
29
|
+
name: "mnemoverse-memory",
|
|
30
|
+
version: "0.1.0",
|
|
31
|
+
});
|
|
32
|
+
// --- Tool: memory_write ---
|
|
33
|
+
server.tool("memory_write", "Store a memory — insight, pattern, preference, or fact. Persists across sessions. Use this when the user teaches you something worth remembering, or when you learn a lesson from a task.", {
|
|
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')"),
|
|
47
|
+
}, async ({ content, concepts, domain }) => {
|
|
48
|
+
const result = await apiFetch("/memory/write", {
|
|
49
|
+
method: "POST",
|
|
50
|
+
body: JSON.stringify({
|
|
51
|
+
content,
|
|
52
|
+
concepts: concepts || [],
|
|
53
|
+
domain: domain || "general",
|
|
54
|
+
}),
|
|
55
|
+
});
|
|
56
|
+
const r = result;
|
|
57
|
+
if (r.stored) {
|
|
58
|
+
return {
|
|
59
|
+
content: [
|
|
60
|
+
{
|
|
61
|
+
type: "text",
|
|
62
|
+
text: `Stored (importance: ${r.importance.toFixed(2)}). ID: ${r.atom_id}`,
|
|
63
|
+
},
|
|
64
|
+
],
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
return {
|
|
68
|
+
content: [
|
|
69
|
+
{
|
|
70
|
+
type: "text",
|
|
71
|
+
text: `Filtered — ${r.reason} (importance: ${r.importance.toFixed(2)})`,
|
|
72
|
+
},
|
|
73
|
+
],
|
|
74
|
+
};
|
|
75
|
+
});
|
|
76
|
+
// --- Tool: memory_read ---
|
|
77
|
+
server.tool("memory_read", "Search memories by natural language query. Returns the most relevant stored memories. Use this before starting a task to check if you already know something about it.", {
|
|
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"),
|
|
94
|
+
}, async ({ query, top_k, domain }) => {
|
|
95
|
+
const result = await apiFetch("/memory/read", {
|
|
96
|
+
method: "POST",
|
|
97
|
+
body: JSON.stringify({
|
|
98
|
+
query,
|
|
99
|
+
top_k: top_k || 5,
|
|
100
|
+
domain: domain || undefined,
|
|
101
|
+
include_associations: true,
|
|
102
|
+
}),
|
|
103
|
+
});
|
|
104
|
+
const r = result;
|
|
105
|
+
if (r.items.length === 0) {
|
|
106
|
+
return {
|
|
107
|
+
content: [
|
|
108
|
+
{ type: "text", text: "No memories found for this query." },
|
|
109
|
+
],
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
const lines = r.items.map((item, i) => `${i + 1}. [${(item.relevance * 100).toFixed(0)}%] ${item.content}` +
|
|
113
|
+
(item.concepts.length > 0
|
|
114
|
+
? ` (${item.concepts.join(", ")})`
|
|
115
|
+
: ""));
|
|
116
|
+
return {
|
|
117
|
+
content: [
|
|
118
|
+
{
|
|
119
|
+
type: "text",
|
|
120
|
+
text: lines.join("\n\n") + `\n\n(${r.search_time_ms.toFixed(0)}ms)`,
|
|
121
|
+
},
|
|
122
|
+
],
|
|
123
|
+
};
|
|
124
|
+
});
|
|
125
|
+
// --- 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"),
|
|
136
|
+
}, async ({ atom_ids, outcome }) => {
|
|
137
|
+
const result = await apiFetch("/memory/feedback", {
|
|
138
|
+
method: "POST",
|
|
139
|
+
body: JSON.stringify({ atom_ids, outcome }),
|
|
140
|
+
});
|
|
141
|
+
const r = result;
|
|
142
|
+
return {
|
|
143
|
+
content: [
|
|
144
|
+
{
|
|
145
|
+
type: "text",
|
|
146
|
+
text: `Feedback recorded for ${r.updated_count} memor${r.updated_count === 1 ? "y" : "ies"}.`,
|
|
147
|
+
},
|
|
148
|
+
],
|
|
149
|
+
};
|
|
150
|
+
});
|
|
151
|
+
// --- 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 () => {
|
|
153
|
+
const result = await apiFetch("/memory/stats");
|
|
154
|
+
const r = result;
|
|
155
|
+
const text = [
|
|
156
|
+
`Memories: ${r.total_atoms} (${r.episodes} episodes, ${r.prototypes} prototypes)`,
|
|
157
|
+
`Associations: ${r.hebbian_edges} Hebbian edges`,
|
|
158
|
+
`Domains: ${r.domains.length > 0 ? r.domains.join(", ") : "general"}`,
|
|
159
|
+
`Avg quality: valence ${r.avg_valence.toFixed(2)}, importance ${r.avg_importance.toFixed(2)}`,
|
|
160
|
+
].join("\n");
|
|
161
|
+
return { content: [{ type: "text", text }] };
|
|
162
|
+
});
|
|
163
|
+
// --- Start ---
|
|
164
|
+
async function main() {
|
|
165
|
+
const transport = new StdioServerTransport();
|
|
166
|
+
await server.connect(transport);
|
|
167
|
+
}
|
|
168
|
+
main().catch((err) => {
|
|
169
|
+
console.error("MCP server error:", err);
|
|
170
|
+
process.exit(1);
|
|
171
|
+
});
|
|
172
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/llms.txt
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Mnemoverse MCP Memory Server
|
|
2
|
+
|
|
3
|
+
> Persistent AI memory via Model Context Protocol. Store and recall memories across sessions.
|
|
4
|
+
|
|
5
|
+
## Tools
|
|
6
|
+
|
|
7
|
+
### memory_write
|
|
8
|
+
Store a memory — insight, pattern, preference, or fact. Persists across sessions.
|
|
9
|
+
|
|
10
|
+
Parameters:
|
|
11
|
+
- content (string, required): The memory to store — what happened, what was learned. 1-10000 chars.
|
|
12
|
+
- concepts (string[], optional): Key concepts for linking related memories. Example: ["deploy", "friday", "staging"]
|
|
13
|
+
- domain (string, optional): Namespace to organize memories. Example: "engineering", "user:alice"
|
|
14
|
+
|
|
15
|
+
Returns: {stored: boolean, atom_id: string|null, importance: number, reason: string}
|
|
16
|
+
|
|
17
|
+
### memory_read
|
|
18
|
+
Search memories by natural language query. Returns most relevant stored memories ranked by relevance.
|
|
19
|
+
|
|
20
|
+
Parameters:
|
|
21
|
+
- query (string, required): Natural language query — what are you looking for? 1-5000 chars.
|
|
22
|
+
- top_k (integer, optional, default 5): Max results to return. Range: 1-50.
|
|
23
|
+
- domain (string, optional): Filter by domain namespace.
|
|
24
|
+
|
|
25
|
+
Returns: List of memories with relevance scores, concepts, and domain.
|
|
26
|
+
|
|
27
|
+
### memory_feedback
|
|
28
|
+
Report whether a retrieved memory was helpful. Positive feedback strengthens recall. Negative lets memories fade.
|
|
29
|
+
|
|
30
|
+
Parameters:
|
|
31
|
+
- atom_ids (string[], required): IDs of memories to give feedback on.
|
|
32
|
+
- outcome (number, required): How helpful? Range: -1.0 (harmful) to 1.0 (very helpful).
|
|
33
|
+
|
|
34
|
+
Returns: {updated_count: number}
|
|
35
|
+
|
|
36
|
+
### memory_stats
|
|
37
|
+
Get memory statistics — count, domains, quality scores.
|
|
38
|
+
|
|
39
|
+
Parameters: none
|
|
40
|
+
|
|
41
|
+
Returns: {total_atoms, episodes, prototypes, hebbian_edges, domains, avg_valence, avg_importance}
|
|
42
|
+
|
|
43
|
+
## Setup
|
|
44
|
+
Environment: MNEMOVERSE_API_KEY (required), MNEMOVERSE_API_URL (optional, default https://core.mnemoverse.com/api/v1)
|
|
45
|
+
Transport: stdio
|
|
46
|
+
Command: npx @mnemoverse/mcp-memory-server
|
|
47
|
+
|
|
48
|
+
## Links
|
|
49
|
+
- Docs: https://mnemoverse.com/docs/api/mcp-server
|
|
50
|
+
- API Reference: https://mnemoverse.com/docs/api/reference
|
|
51
|
+
- Console: https://console.mnemoverse.com
|
|
52
|
+
- Source: https://github.com/mnemoverse/mcp-memory-server
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@mnemoverse/mcp-memory-server",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "MCP server for Mnemoverse Memory API — persistent AI memory across Claude Code, Cursor, VS Code, and any MCP client",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"mcp-memory-server": "./dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"main": "./dist/index.js",
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "tsc",
|
|
13
|
+
"dev": "tsc --watch",
|
|
14
|
+
"start": "node dist/index.js",
|
|
15
|
+
"prepublishOnly": "npm run build"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"mcp",
|
|
19
|
+
"memory",
|
|
20
|
+
"ai",
|
|
21
|
+
"claude",
|
|
22
|
+
"cursor",
|
|
23
|
+
"mnemoverse",
|
|
24
|
+
"persistent-memory",
|
|
25
|
+
"model-context-protocol"
|
|
26
|
+
],
|
|
27
|
+
"author": "Mnemoverse <hello@mnemoverse.com>",
|
|
28
|
+
"license": "MIT",
|
|
29
|
+
"repository": {
|
|
30
|
+
"type": "git",
|
|
31
|
+
"url": "https://github.com/mnemoverse/mcp-memory-server"
|
|
32
|
+
},
|
|
33
|
+
"homepage": "https://mnemoverse.com/docs/api/mcp-server",
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"@modelcontextprotocol/sdk": "^1.12.1"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"typescript": "^5.8.3",
|
|
39
|
+
"@types/node": "^22.15.3"
|
|
40
|
+
},
|
|
41
|
+
"engines": {
|
|
42
|
+
"node": ">=18"
|
|
43
|
+
}
|
|
44
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
4
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
|
|
7
|
+
const API_URL =
|
|
8
|
+
process.env.MNEMOVERSE_API_URL || "https://core.mnemoverse.com/api/v1";
|
|
9
|
+
const API_KEY = process.env.MNEMOVERSE_API_KEY || "";
|
|
10
|
+
|
|
11
|
+
if (!API_KEY) {
|
|
12
|
+
console.error(
|
|
13
|
+
"Error: MNEMOVERSE_API_KEY environment variable is required.\n" +
|
|
14
|
+
"Get your free key at https://console.mnemoverse.com"
|
|
15
|
+
);
|
|
16
|
+
process.exit(1);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
async function apiFetch(
|
|
20
|
+
path: string,
|
|
21
|
+
options: RequestInit = {}
|
|
22
|
+
): Promise<unknown> {
|
|
23
|
+
const res = await fetch(`${API_URL}${path}`, {
|
|
24
|
+
...options,
|
|
25
|
+
headers: {
|
|
26
|
+
"Content-Type": "application/json",
|
|
27
|
+
"X-Api-Key": API_KEY,
|
|
28
|
+
...((options.headers as Record<string, string>) || {}),
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
if (!res.ok) {
|
|
33
|
+
const text = await res.text();
|
|
34
|
+
throw new Error(`Mnemoverse API error ${res.status}: ${text}`);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return res.json();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// --- Server setup ---
|
|
41
|
+
|
|
42
|
+
const server = new McpServer({
|
|
43
|
+
name: "mnemoverse-memory",
|
|
44
|
+
version: "0.1.0",
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
// --- Tool: memory_write ---
|
|
48
|
+
|
|
49
|
+
server.tool(
|
|
50
|
+
"memory_write",
|
|
51
|
+
"Store a memory — insight, pattern, preference, or fact. Persists across sessions. Use this when the user teaches you something worth remembering, or when you learn a lesson from a task.",
|
|
52
|
+
{
|
|
53
|
+
content: z
|
|
54
|
+
.string()
|
|
55
|
+
.min(1)
|
|
56
|
+
.max(10000)
|
|
57
|
+
.describe("The memory to store — what happened, what was learned"),
|
|
58
|
+
concepts: z
|
|
59
|
+
.array(z.string())
|
|
60
|
+
.optional()
|
|
61
|
+
.describe("Key concepts for linking related memories (e.g. ['deploy', 'friday', 'staging'])"),
|
|
62
|
+
domain: z
|
|
63
|
+
.string()
|
|
64
|
+
.optional()
|
|
65
|
+
.describe("Namespace to organize memories (e.g. 'engineering', 'user:alice', 'project:acme')"),
|
|
66
|
+
},
|
|
67
|
+
async ({ content, concepts, domain }) => {
|
|
68
|
+
const result = await apiFetch("/memory/write", {
|
|
69
|
+
method: "POST",
|
|
70
|
+
body: JSON.stringify({
|
|
71
|
+
content,
|
|
72
|
+
concepts: concepts || [],
|
|
73
|
+
domain: domain || "general",
|
|
74
|
+
}),
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
const r = result as {
|
|
78
|
+
stored: boolean;
|
|
79
|
+
atom_id: string | null;
|
|
80
|
+
importance: number;
|
|
81
|
+
reason: string;
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
if (r.stored) {
|
|
85
|
+
return {
|
|
86
|
+
content: [
|
|
87
|
+
{
|
|
88
|
+
type: "text" as const,
|
|
89
|
+
text: `Stored (importance: ${r.importance.toFixed(2)}). ID: ${r.atom_id}`,
|
|
90
|
+
},
|
|
91
|
+
],
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
return {
|
|
95
|
+
content: [
|
|
96
|
+
{
|
|
97
|
+
type: "text" as const,
|
|
98
|
+
text: `Filtered — ${r.reason} (importance: ${r.importance.toFixed(2)})`,
|
|
99
|
+
},
|
|
100
|
+
],
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
// --- Tool: memory_read ---
|
|
106
|
+
|
|
107
|
+
server.tool(
|
|
108
|
+
"memory_read",
|
|
109
|
+
"Search memories by natural language query. Returns the most relevant stored memories. Use this before starting a task to check if you already know something about it.",
|
|
110
|
+
{
|
|
111
|
+
query: z
|
|
112
|
+
.string()
|
|
113
|
+
.min(1)
|
|
114
|
+
.max(5000)
|
|
115
|
+
.describe("Natural language query — what are you looking for?"),
|
|
116
|
+
top_k: z
|
|
117
|
+
.number()
|
|
118
|
+
.int()
|
|
119
|
+
.min(1)
|
|
120
|
+
.max(50)
|
|
121
|
+
.optional()
|
|
122
|
+
.describe("Max results to return (default: 5)"),
|
|
123
|
+
domain: z
|
|
124
|
+
.string()
|
|
125
|
+
.optional()
|
|
126
|
+
.describe("Filter by domain namespace"),
|
|
127
|
+
},
|
|
128
|
+
async ({ query, top_k, domain }) => {
|
|
129
|
+
const result = await apiFetch("/memory/read", {
|
|
130
|
+
method: "POST",
|
|
131
|
+
body: JSON.stringify({
|
|
132
|
+
query,
|
|
133
|
+
top_k: top_k || 5,
|
|
134
|
+
domain: domain || undefined,
|
|
135
|
+
include_associations: true,
|
|
136
|
+
}),
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
const r = result as {
|
|
140
|
+
items: Array<{
|
|
141
|
+
content: string;
|
|
142
|
+
relevance: number;
|
|
143
|
+
concepts: string[];
|
|
144
|
+
domain: string;
|
|
145
|
+
}>;
|
|
146
|
+
search_time_ms: number;
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
if (r.items.length === 0) {
|
|
150
|
+
return {
|
|
151
|
+
content: [
|
|
152
|
+
{ type: "text" as const, text: "No memories found for this query." },
|
|
153
|
+
],
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const lines = r.items.map(
|
|
158
|
+
(item, i) =>
|
|
159
|
+
`${i + 1}. [${(item.relevance * 100).toFixed(0)}%] ${item.content}` +
|
|
160
|
+
(item.concepts.length > 0
|
|
161
|
+
? ` (${item.concepts.join(", ")})`
|
|
162
|
+
: "")
|
|
163
|
+
);
|
|
164
|
+
|
|
165
|
+
return {
|
|
166
|
+
content: [
|
|
167
|
+
{
|
|
168
|
+
type: "text" as const,
|
|
169
|
+
text: lines.join("\n\n") + `\n\n(${r.search_time_ms.toFixed(0)}ms)`,
|
|
170
|
+
},
|
|
171
|
+
],
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
);
|
|
175
|
+
|
|
176
|
+
// --- Tool: memory_feedback ---
|
|
177
|
+
|
|
178
|
+
server.tool(
|
|
179
|
+
"memory_feedback",
|
|
180
|
+
"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.",
|
|
181
|
+
{
|
|
182
|
+
atom_ids: z
|
|
183
|
+
.array(z.string())
|
|
184
|
+
.min(1)
|
|
185
|
+
.describe("IDs of memories to give feedback on (from memory_read results)"),
|
|
186
|
+
outcome: z
|
|
187
|
+
.number()
|
|
188
|
+
.min(-1)
|
|
189
|
+
.max(1)
|
|
190
|
+
.describe("How helpful was this? 1.0 = very helpful, 0 = neutral, -1.0 = harmful/wrong"),
|
|
191
|
+
},
|
|
192
|
+
async ({ atom_ids, outcome }) => {
|
|
193
|
+
const result = await apiFetch("/memory/feedback", {
|
|
194
|
+
method: "POST",
|
|
195
|
+
body: JSON.stringify({ atom_ids, outcome }),
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
const r = result as { updated_count: number };
|
|
199
|
+
|
|
200
|
+
return {
|
|
201
|
+
content: [
|
|
202
|
+
{
|
|
203
|
+
type: "text" as const,
|
|
204
|
+
text: `Feedback recorded for ${r.updated_count} memor${r.updated_count === 1 ? "y" : "ies"}.`,
|
|
205
|
+
},
|
|
206
|
+
],
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
);
|
|
210
|
+
|
|
211
|
+
// --- Tool: memory_stats ---
|
|
212
|
+
|
|
213
|
+
server.tool(
|
|
214
|
+
"memory_stats",
|
|
215
|
+
"Get memory statistics — how many memories are stored, which domains exist, average quality scores. Useful for understanding the current state of memory.",
|
|
216
|
+
{},
|
|
217
|
+
async () => {
|
|
218
|
+
const result = await apiFetch("/memory/stats");
|
|
219
|
+
|
|
220
|
+
const r = result as {
|
|
221
|
+
total_atoms: number;
|
|
222
|
+
episodes: number;
|
|
223
|
+
prototypes: number;
|
|
224
|
+
hebbian_edges: number;
|
|
225
|
+
domains: string[];
|
|
226
|
+
avg_valence: number;
|
|
227
|
+
avg_importance: number;
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
const text = [
|
|
231
|
+
`Memories: ${r.total_atoms} (${r.episodes} episodes, ${r.prototypes} prototypes)`,
|
|
232
|
+
`Associations: ${r.hebbian_edges} Hebbian edges`,
|
|
233
|
+
`Domains: ${r.domains.length > 0 ? r.domains.join(", ") : "general"}`,
|
|
234
|
+
`Avg quality: valence ${r.avg_valence.toFixed(2)}, importance ${r.avg_importance.toFixed(2)}`,
|
|
235
|
+
].join("\n");
|
|
236
|
+
|
|
237
|
+
return { content: [{ type: "text" as const, text }] };
|
|
238
|
+
}
|
|
239
|
+
);
|
|
240
|
+
|
|
241
|
+
// --- Start ---
|
|
242
|
+
|
|
243
|
+
async function main() {
|
|
244
|
+
const transport = new StdioServerTransport();
|
|
245
|
+
await server.connect(transport);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
main().catch((err) => {
|
|
249
|
+
console.error("MCP server error:", err);
|
|
250
|
+
process.exit(1);
|
|
251
|
+
});
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "Node16",
|
|
5
|
+
"moduleResolution": "Node16",
|
|
6
|
+
"outDir": "./dist",
|
|
7
|
+
"rootDir": "./src",
|
|
8
|
+
"strict": true,
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"skipLibCheck": true,
|
|
11
|
+
"declaration": true,
|
|
12
|
+
"sourceMap": true
|
|
13
|
+
},
|
|
14
|
+
"include": ["src/**/*"]
|
|
15
|
+
}
|