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.
Files changed (2) hide show
  1. package/package.json +2 -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.1",
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
- server.setRequestHandler(ListToolsRequestSchema, async () => ({
37
- tools: [
38
- {
39
- name: "remember",
40
- description: "Save something to permanent memory. Use for important facts, decisions, code snippets, or anything that should persist across sessions.",
41
- inputSchema: {
42
- type: "object",
43
- properties: {
44
- key: {
45
- type: "string",
46
- description: "Memory key e.g. 'architecture', 'decision-db', 'bug-fix-auth'"
47
- },
48
- value: {
49
- type: "string",
50
- description: "What to remember"
51
- },
52
- project: {
53
- type: "string",
54
- description: "Project name (optional, defaults to default)"
55
- }
56
- },
57
- required: ["key", "value"]
58
- }
59
- },
60
- {
61
- name: "recall",
62
- description: "Retrieve something from permanent memory by key.",
63
- inputSchema: {
64
- type: "object",
65
- properties: {
66
- key: { type: "string", description: "Memory key to retrieve" },
67
- project: { type: "string", description: "Project name (optional)" }
68
- },
69
- required: ["key"]
70
- }
71
- },
72
- {
73
- name: "list_memories",
74
- description: "List all memory keys for a project.",
75
- inputSchema: {
76
- type: "object",
77
- properties: {
78
- project: { type: "string", description: "Project name (optional)" }
79
- }
80
- }
81
- },
82
- {
83
- name: "forget",
84
- description: "Delete something from memory.",
85
- inputSchema: {
86
- type: "object",
87
- properties: {
88
- key: { type: "string" },
89
- project: { type: "string" }
90
- },
91
- required: ["key"]
92
- }
93
- },
94
- {
95
- name: "load_context",
96
- description: "Load full project context including architecture, decisions, and recent conversation history. Call this at the start of every session.",
97
- inputSchema: {
98
- type: "object",
99
- properties: {
100
- project: { type: "string", description: "Project name" },
101
- days: { type: "number", description: "Days of history to load (default 2)" }
102
- }
103
- }
104
- },
105
- {
106
- name: "save_context",
107
- description: "Save project context document (architecture, conventions, current status).",
108
- inputSchema: {
109
- type: "object",
110
- properties: {
111
- project: { type: "string" },
112
- content: { type: "string", description: "Full context document in markdown" }
113
- },
114
- required: ["content"]
115
- }
116
- },
117
- {
118
- name: "save_session",
119
- description: "Save current conversation messages to history. Call at end of session.",
120
- inputSchema: {
121
- type: "object",
122
- properties: {
123
- project: { type: "string" },
124
- messages: {
125
- type: "array",
126
- description: "Array of {role, content} message objects"
127
- }
128
- },
129
- required: ["messages"]
130
- }
131
- },
132
- {
133
- name: "status",
134
- description: "Check himem connection status and plan details.",
135
- inputSchema: {
136
- type: "object",
137
- properties: {}
138
- }
139
- }
140
- ]
141
- }));
142
-
143
- server.setRequestHandler(CallToolRequestSchema, async (request) => {
144
- const { name, arguments: args } = request.params;
145
- const project = args.project || PROJECT;
146
-
147
- try {
148
- if (name === "remember") {
149
- const result = await himem("/write", "POST", {
150
- key: args.key,
151
- value: args.value,
152
- project
153
- });
154
- return {
155
- content: [{
156
- type: "text",
157
- text: result.success
158
- ? `✓ Remembered: ${args.key}`
159
- : `✗ Failed: ${result.error}`
160
- }]
161
- };
162
- }
163
-
164
- if (name === "recall") {
165
- const result = await himem(
166
- `/read?key=${encodeURIComponent(args.key)}&project=${encodeURIComponent(project)}`
167
- );
168
- return {
169
- content: [{
170
- type: "text",
171
- text: result.found
172
- ? result.value
173
- : `No memory found for key: ${args.key}`
174
- }]
175
- };
176
- }
177
-
178
- if (name === "list_memories") {
179
- const result = await himem(
180
- `/list?project=${encodeURIComponent(project)}`
181
- );
182
- return {
183
- content: [{
184
- type: "text",
185
- text: result.keys?.length
186
- ? `Memory keys in ${project}:\n${result.keys.map(k => `• ${k}`).join('\n')}`
187
- : `No memories found in project: ${project}`
188
- }]
189
- };
190
- }
191
-
192
- if (name === "forget") {
193
- const result = await himem(
194
- `/delete?key=${encodeURIComponent(args.key)}&project=${encodeURIComponent(project)}`,
195
- "DELETE"
196
- );
197
- return {
198
- content: [{
199
- type: "text",
200
- text: result.success
201
- ? `✓ Forgotten: ${args.key}`
202
- : `✗ Failed: ${result.error}`
203
- }]
204
- };
205
- }
206
-
207
- if (name === "load_context") {
208
- const result = await himem(
209
- `/context/load?project=${encodeURIComponent(project)}&days=${args.days || 2}`
210
- );
211
-
212
- let output = "";
213
- if (result.context) {
214
- output += `PROJECT CONTEXT:\n${result.context}\n\n`;
215
- }
216
- if (result.history?.length > 0) {
217
- output += `RECENT HISTORY (${result.history.length} messages):\n`;
218
- output += result.history
219
- .slice(-20)
220
- .map(m => `${m.role.toUpperCase()}: ${m.content.substring(0, 200)}`)
221
- .join('\n');
222
- }
223
- if (!output) {
224
- output = `No context found for project: ${project}. Start by saving context with save_context.`;
225
- }
226
- return { content: [{ type: "text", text: output }] };
227
- }
228
-
229
- if (name === "save_context") {
230
- const result = await himem("/context/save", "POST", {
231
- project,
232
- content: args.content
233
- });
234
- return {
235
- content: [{
236
- type: "text",
237
- text: result.success
238
- ? `✓ Context saved for project: ${project}`
239
- : `✗ Failed: ${result.error}`
240
- }]
241
- };
242
- }
243
-
244
- if (name === "save_session") {
245
- const result = await himem("/session/save", "POST", {
246
- project,
247
- messages: args.messages
248
- });
249
- return {
250
- content: [{
251
- type: "text",
252
- text: result.success
253
- ? `✓ Session saved: ${result.messages_saved} messages (${result.total} total today)`
254
- : `✗ Failed: ${result.error}`
255
- }]
256
- };
257
- }
258
-
259
- if (name === "status") {
260
- const result = await himem("/status");
261
- return {
262
- content: [{
263
- type: "text",
264
- text: `HIMEM STATUS\n─────────────\nPlan: ${result.plan}\nEmail: ${result.email}\nVersion: ${result.himem_version}\nDocs: ${result.docs}`
265
- }]
266
- };
267
- }
268
-
269
- } catch (err) {
270
- return {
271
- content: [{
272
- type: "text",
273
- text: `HIMEM ERROR: ${err.message}`
274
- }]
275
- };
276
- }
277
- });
278
-
279
- const transport = new StdioServerTransport();
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);