himem-mcp 1.0.1 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/src/index.js +272 -274
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "himem-mcp",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Persistent memory for any AI — Claude, GPT, Gemini, Cursor. Never forget a codebase, decision, or conversation.",
|
|
6
6
|
"main": "src/index.js",
|
|
7
7
|
"bin": {
|
|
8
|
-
"himem-mcp": "src/index.js"
|
|
8
|
+
"himem-mcp": "./src/index.js"
|
|
9
9
|
},
|
|
10
10
|
"keywords": [
|
|
11
11
|
"mcp",
|
package/src/index.js
CHANGED
|
@@ -1,280 +1,278 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
3
3
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
-
import { ListToolsRequestSchema, CallToolRequestSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
5
|
-
|
|
6
|
-
const HIMEM_API = process.env.HIMEM_API || "https://api.himem.ai";
|
|
7
|
-
const HIMEM_KEY = process.env.HIMEM_KEY;
|
|
8
|
-
const PROJECT = process.env.HIMEM_PROJECT || "default";
|
|
9
|
-
|
|
10
|
-
if (!HIMEM_KEY) {
|
|
11
|
-
console.error("HIMEM_KEY required. Get yours at https://himem.ai");
|
|
12
|
-
process.exit(1);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
async function himem(path, method = "GET", body = null) {
|
|
16
|
-
const res = await fetch(`${HIMEM_API}${path}`, {
|
|
17
|
-
method,
|
|
18
|
-
headers: {
|
|
19
|
-
"Authorization": `Bearer ${HIMEM_KEY}`,
|
|
20
|
-
"Content-Type": "application/json"
|
|
21
|
-
},
|
|
22
|
-
body: body ? JSON.stringify(body) : null
|
|
23
|
-
});
|
|
24
|
-
return res.json();
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const server = new Server({
|
|
28
|
-
name: "himem",
|
|
29
|
-
version: "1.0.0"
|
|
30
|
-
}, {
|
|
31
|
-
capabilities: { tools: {} }
|
|
32
|
-
});
|
|
33
|
-
|
|
34
4
|
import { ListToolsRequestSchema, CallToolRequestSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
35
5
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
);
|
|
182
|
-
return {
|
|
183
|
-
content: [{
|
|
184
|
-
type: "text",
|
|
185
|
-
text: result.
|
|
186
|
-
?
|
|
187
|
-
:
|
|
188
|
-
}]
|
|
189
|
-
};
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
if (name === "
|
|
193
|
-
const result = await himem(
|
|
194
|
-
`/
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
6
|
+
const HIMEM_API = process.env.HIMEM_API || "https://api.himem.ai";
|
|
7
|
+
const HIMEM_KEY = process.env.HIMEM_KEY;
|
|
8
|
+
const PROJECT = process.env.HIMEM_PROJECT || "default";
|
|
9
|
+
|
|
10
|
+
if (!HIMEM_KEY) {
|
|
11
|
+
console.error("HIMEM_KEY required. Get yours at https://himem.ai");
|
|
12
|
+
process.exit(1);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async function himem(path, method = "GET", body = null) {
|
|
16
|
+
const res = await fetch(`${HIMEM_API}${path}`, {
|
|
17
|
+
method,
|
|
18
|
+
headers: {
|
|
19
|
+
"Authorization": `Bearer ${HIMEM_KEY}`,
|
|
20
|
+
"Content-Type": "application/json"
|
|
21
|
+
},
|
|
22
|
+
body: body ? JSON.stringify(body) : null
|
|
23
|
+
});
|
|
24
|
+
return res.json();
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const server = new Server({
|
|
28
|
+
name: "himem",
|
|
29
|
+
version: "1.0.0"
|
|
30
|
+
}, {
|
|
31
|
+
capabilities: { tools: {} }
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
35
|
+
tools: [
|
|
36
|
+
{
|
|
37
|
+
name: "remember",
|
|
38
|
+
description: "Save something to permanent memory. Use for important facts, decisions, code snippets, or anything that should persist across sessions.",
|
|
39
|
+
inputSchema: {
|
|
40
|
+
type: "object",
|
|
41
|
+
properties: {
|
|
42
|
+
key: {
|
|
43
|
+
type: "string",
|
|
44
|
+
description: "Memory key e.g. 'architecture', 'decision-db', 'bug-fix-auth'"
|
|
45
|
+
},
|
|
46
|
+
value: {
|
|
47
|
+
type: "string",
|
|
48
|
+
description: "What to remember"
|
|
49
|
+
},
|
|
50
|
+
project: {
|
|
51
|
+
type: "string",
|
|
52
|
+
description: "Project name (optional, defaults to default)"
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
required: ["key", "value"]
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
name: "recall",
|
|
60
|
+
description: "Retrieve something from permanent memory by key.",
|
|
61
|
+
inputSchema: {
|
|
62
|
+
type: "object",
|
|
63
|
+
properties: {
|
|
64
|
+
key: { type: "string", description: "Memory key to retrieve" },
|
|
65
|
+
project: { type: "string", description: "Project name (optional)" }
|
|
66
|
+
},
|
|
67
|
+
required: ["key"]
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
name: "list_memories",
|
|
72
|
+
description: "List all memory keys for a project.",
|
|
73
|
+
inputSchema: {
|
|
74
|
+
type: "object",
|
|
75
|
+
properties: {
|
|
76
|
+
project: { type: "string", description: "Project name (optional)" }
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
name: "forget",
|
|
82
|
+
description: "Delete something from memory.",
|
|
83
|
+
inputSchema: {
|
|
84
|
+
type: "object",
|
|
85
|
+
properties: {
|
|
86
|
+
key: { type: "string" },
|
|
87
|
+
project: { type: "string" }
|
|
88
|
+
},
|
|
89
|
+
required: ["key"]
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
name: "load_context",
|
|
94
|
+
description: "Load full project context including architecture, decisions, and recent conversation history. Call this at the start of every session.",
|
|
95
|
+
inputSchema: {
|
|
96
|
+
type: "object",
|
|
97
|
+
properties: {
|
|
98
|
+
project: { type: "string", description: "Project name" },
|
|
99
|
+
days: { type: "number", description: "Days of history to load (default 2)" }
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
name: "save_context",
|
|
105
|
+
description: "Save project context document (architecture, conventions, current status).",
|
|
106
|
+
inputSchema: {
|
|
107
|
+
type: "object",
|
|
108
|
+
properties: {
|
|
109
|
+
project: { type: "string" },
|
|
110
|
+
content: { type: "string", description: "Full context document in markdown" }
|
|
111
|
+
},
|
|
112
|
+
required: ["content"]
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
name: "save_session",
|
|
117
|
+
description: "Save current conversation messages to history. Call at end of session.",
|
|
118
|
+
inputSchema: {
|
|
119
|
+
type: "object",
|
|
120
|
+
properties: {
|
|
121
|
+
project: { type: "string" },
|
|
122
|
+
messages: {
|
|
123
|
+
type: "array",
|
|
124
|
+
description: "Array of {role, content} message objects"
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
required: ["messages"]
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
name: "status",
|
|
132
|
+
description: "Check himem connection status and plan details.",
|
|
133
|
+
inputSchema: {
|
|
134
|
+
type: "object",
|
|
135
|
+
properties: {}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
]
|
|
139
|
+
}));
|
|
140
|
+
|
|
141
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
142
|
+
const { name, arguments: args } = request.params;
|
|
143
|
+
const project = args.project || PROJECT;
|
|
144
|
+
|
|
145
|
+
try {
|
|
146
|
+
if (name === "remember") {
|
|
147
|
+
const result = await himem("/write", "POST", {
|
|
148
|
+
key: args.key,
|
|
149
|
+
value: args.value,
|
|
150
|
+
project
|
|
151
|
+
});
|
|
152
|
+
return {
|
|
153
|
+
content: [{
|
|
154
|
+
type: "text",
|
|
155
|
+
text: result.success
|
|
156
|
+
? `✓ Remembered: ${args.key}`
|
|
157
|
+
: `✗ Failed: ${result.error}`
|
|
158
|
+
}]
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (name === "recall") {
|
|
163
|
+
const result = await himem(
|
|
164
|
+
`/read?key=${encodeURIComponent(args.key)}&project=${encodeURIComponent(project)}`
|
|
165
|
+
);
|
|
166
|
+
return {
|
|
167
|
+
content: [{
|
|
168
|
+
type: "text",
|
|
169
|
+
text: result.found
|
|
170
|
+
? result.value
|
|
171
|
+
: `No memory found for key: ${args.key}`
|
|
172
|
+
}]
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (name === "list_memories") {
|
|
177
|
+
const result = await himem(
|
|
178
|
+
`/list?project=${encodeURIComponent(project)}`
|
|
179
|
+
);
|
|
180
|
+
return {
|
|
181
|
+
content: [{
|
|
182
|
+
type: "text",
|
|
183
|
+
text: result.keys?.length
|
|
184
|
+
? `Memory keys in ${project}:\n${result.keys.map(k => `• ${k}`).join('\n')}`
|
|
185
|
+
: `No memories found in project: ${project}`
|
|
186
|
+
}]
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
if (name === "forget") {
|
|
191
|
+
const result = await himem(
|
|
192
|
+
`/delete?key=${encodeURIComponent(args.key)}&project=${encodeURIComponent(project)}`,
|
|
193
|
+
"DELETE"
|
|
194
|
+
);
|
|
195
|
+
return {
|
|
196
|
+
content: [{
|
|
197
|
+
type: "text",
|
|
198
|
+
text: result.success
|
|
199
|
+
? `✓ Forgotten: ${args.key}`
|
|
200
|
+
: `✗ Failed: ${result.error}`
|
|
201
|
+
}]
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
if (name === "load_context") {
|
|
206
|
+
const result = await himem(
|
|
207
|
+
`/context/load?project=${encodeURIComponent(project)}&days=${args.days || 2}`
|
|
208
|
+
);
|
|
209
|
+
|
|
210
|
+
let output = "";
|
|
211
|
+
if (result.context) {
|
|
212
|
+
output += `PROJECT CONTEXT:\n${result.context}\n\n`;
|
|
213
|
+
}
|
|
214
|
+
if (result.history?.length > 0) {
|
|
215
|
+
output += `RECENT HISTORY (${result.history.length} messages):\n`;
|
|
216
|
+
output += result.history
|
|
217
|
+
.slice(-20)
|
|
218
|
+
.map(m => `${m.role.toUpperCase()}: ${m.content.substring(0, 200)}`)
|
|
219
|
+
.join('\n');
|
|
220
|
+
}
|
|
221
|
+
if (!output) {
|
|
222
|
+
output = `No context found for project: ${project}. Start by saving context with save_context.`;
|
|
223
|
+
}
|
|
224
|
+
return { content: [{ type: "text", text: output }] };
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
if (name === "save_context") {
|
|
228
|
+
const result = await himem("/context/save", "POST", {
|
|
229
|
+
project,
|
|
230
|
+
content: args.content
|
|
231
|
+
});
|
|
232
|
+
return {
|
|
233
|
+
content: [{
|
|
234
|
+
type: "text",
|
|
235
|
+
text: result.success
|
|
236
|
+
? `✓ Context saved for project: ${project}`
|
|
237
|
+
: `✗ Failed: ${result.error}`
|
|
238
|
+
}]
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
if (name === "save_session") {
|
|
243
|
+
const result = await himem("/session/save", "POST", {
|
|
244
|
+
project,
|
|
245
|
+
messages: args.messages
|
|
246
|
+
});
|
|
247
|
+
return {
|
|
248
|
+
content: [{
|
|
249
|
+
type: "text",
|
|
250
|
+
text: result.success
|
|
251
|
+
? `✓ Session saved: ${result.messages_saved} messages (${result.total} total today)`
|
|
252
|
+
: `✗ Failed: ${result.error}`
|
|
253
|
+
}]
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
if (name === "status") {
|
|
258
|
+
const result = await himem("/status");
|
|
259
|
+
return {
|
|
260
|
+
content: [{
|
|
261
|
+
type: "text",
|
|
262
|
+
text: `HIMEM STATUS\n─────────────\nPlan: ${result.plan}\nEmail: ${result.email}\nVersion: ${result.himem_version}\nDocs: ${result.docs}`
|
|
263
|
+
}]
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
} catch (err) {
|
|
268
|
+
return {
|
|
269
|
+
content: [{
|
|
270
|
+
type: "text",
|
|
271
|
+
text: `HIMEM ERROR: ${err.message}`
|
|
272
|
+
}]
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
const transport = new StdioServerTransport();
|
|
280
278
|
await server.connect(transport);
|