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