@cybermem/mcp 0.6.8 → 0.6.10
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/dist/index.js +77 -19
- package/package.json +1 -1
- package/src/index.ts +103 -31
package/dist/index.js
CHANGED
|
@@ -19,9 +19,9 @@ const getArg = (name) => {
|
|
|
19
19
|
const idx = args.indexOf(name);
|
|
20
20
|
return idx !== -1 && args[idx + 1] ? args[idx + 1] : undefined;
|
|
21
21
|
};
|
|
22
|
-
const cliUrl = getArg(
|
|
23
|
-
const cliApiKey = getArg(
|
|
24
|
-
const cliClientName = getArg(
|
|
22
|
+
const cliUrl = getArg("--url");
|
|
23
|
+
const cliApiKey = getArg("--api-key");
|
|
24
|
+
const cliClientName = getArg("--client-name");
|
|
25
25
|
// Use CLI args first, then env, then defaults
|
|
26
26
|
// Default to local CyberMem backend (via Traefik on port 8626)
|
|
27
27
|
const API_URL = cliUrl || process.env.CYBERMEM_URL || "http://localhost:8626/memory";
|
|
@@ -49,32 +49,67 @@ INTEGRITY RULES:
|
|
|
49
49
|
- Last-write-wins for conflicts
|
|
50
50
|
|
|
51
51
|
For full protocol: https://cybermem.dev/docs/agent-protocol`;
|
|
52
|
+
// Short protocol reminder for tool descriptions (derived from main instructions)
|
|
53
|
+
const PROTOCOL_REMINDER = "CyberMem Protocol: Store FULL content (no summaries), always include tags [topic, year, source:client-name]. Query 'user context profile' on session start.";
|
|
52
54
|
const server = new index_js_1.Server({
|
|
53
55
|
name: "cybermem",
|
|
54
|
-
version: "0.6.
|
|
56
|
+
version: "0.6.8",
|
|
55
57
|
}, {
|
|
56
58
|
capabilities: {
|
|
57
59
|
tools: {},
|
|
60
|
+
resources: {}, // Enable resources for protocol document
|
|
58
61
|
},
|
|
59
62
|
instructions: CYBERMEM_INSTRUCTIONS,
|
|
60
63
|
});
|
|
64
|
+
// Register resources handler for protocol document
|
|
65
|
+
server.setRequestHandler(types_js_1.ListResourcesRequestSchema, async () => ({
|
|
66
|
+
resources: [
|
|
67
|
+
{
|
|
68
|
+
uri: "cybermem://protocol",
|
|
69
|
+
name: "CyberMem Agent Protocol",
|
|
70
|
+
description: "Instructions for AI agents using CyberMem memory system",
|
|
71
|
+
mimeType: "text/plain",
|
|
72
|
+
},
|
|
73
|
+
],
|
|
74
|
+
}));
|
|
75
|
+
server.setRequestHandler(types_js_1.ReadResourceRequestSchema, async (request) => {
|
|
76
|
+
if (request.params.uri === "cybermem://protocol") {
|
|
77
|
+
return {
|
|
78
|
+
contents: [
|
|
79
|
+
{
|
|
80
|
+
uri: "cybermem://protocol",
|
|
81
|
+
mimeType: "text/plain",
|
|
82
|
+
text: CYBERMEM_INSTRUCTIONS,
|
|
83
|
+
},
|
|
84
|
+
],
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
throw new Error(`Unknown resource: ${request.params.uri}`);
|
|
88
|
+
});
|
|
61
89
|
const tools = [
|
|
62
90
|
{
|
|
63
91
|
name: "add_memory",
|
|
64
|
-
description:
|
|
92
|
+
description: `Store a new memory in CyberMem. ${PROTOCOL_REMINDER}`,
|
|
65
93
|
inputSchema: {
|
|
66
94
|
type: "object",
|
|
67
95
|
properties: {
|
|
68
|
-
content: {
|
|
96
|
+
content: {
|
|
97
|
+
type: "string",
|
|
98
|
+
description: "Full content with all details - NO truncation or summarization",
|
|
99
|
+
},
|
|
69
100
|
user_id: { type: "string" },
|
|
70
|
-
tags: {
|
|
101
|
+
tags: {
|
|
102
|
+
type: "array",
|
|
103
|
+
items: { type: "string" },
|
|
104
|
+
description: "Always include [topic, year, source:your-client-name]",
|
|
105
|
+
},
|
|
71
106
|
},
|
|
72
107
|
required: ["content"],
|
|
73
108
|
},
|
|
74
109
|
},
|
|
75
110
|
{
|
|
76
111
|
name: "query_memory",
|
|
77
|
-
description:
|
|
112
|
+
description: `Search for relevant memories. On session start, call query_memory("user context profile") first.`,
|
|
78
113
|
inputSchema: {
|
|
79
114
|
type: "object",
|
|
80
115
|
properties: {
|
|
@@ -118,7 +153,7 @@ const tools = [
|
|
|
118
153
|
},
|
|
119
154
|
required: ["id"],
|
|
120
155
|
},
|
|
121
|
-
}
|
|
156
|
+
},
|
|
122
157
|
];
|
|
123
158
|
server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({
|
|
124
159
|
tools,
|
|
@@ -127,7 +162,7 @@ server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({
|
|
|
127
162
|
const apiClient = axios_1.default.create({
|
|
128
163
|
baseURL: API_URL,
|
|
129
164
|
headers: {
|
|
130
|
-
|
|
165
|
+
Authorization: `Bearer ${API_KEY}`,
|
|
131
166
|
},
|
|
132
167
|
});
|
|
133
168
|
// Helper to get client with context
|
|
@@ -137,11 +172,26 @@ function getClient(customHeaders = {}) {
|
|
|
137
172
|
const clientName = customHeaders["X-Client-Name"] || clientVersion?.name || currentClientName;
|
|
138
173
|
return {
|
|
139
174
|
...apiClient,
|
|
140
|
-
get: (url, config) => apiClient.get(url, {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
175
|
+
get: (url, config) => apiClient.get(url, {
|
|
176
|
+
...config,
|
|
177
|
+
headers: { "X-Client-Name": clientName, ...config?.headers },
|
|
178
|
+
}),
|
|
179
|
+
post: (url, data, config) => apiClient.post(url, data, {
|
|
180
|
+
...config,
|
|
181
|
+
headers: { "X-Client-Name": clientName, ...config?.headers },
|
|
182
|
+
}),
|
|
183
|
+
put: (url, data, config) => apiClient.put(url, data, {
|
|
184
|
+
...config,
|
|
185
|
+
headers: { "X-Client-Name": clientName, ...config?.headers },
|
|
186
|
+
}),
|
|
187
|
+
patch: (url, data, config) => apiClient.patch(url, data, {
|
|
188
|
+
...config,
|
|
189
|
+
headers: { "X-Client-Name": clientName, ...config?.headers },
|
|
190
|
+
}),
|
|
191
|
+
delete: (url, config) => apiClient.delete(url, {
|
|
192
|
+
...config,
|
|
193
|
+
headers: { "X-Client-Name": clientName, ...config?.headers },
|
|
194
|
+
}),
|
|
145
195
|
};
|
|
146
196
|
}
|
|
147
197
|
server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
@@ -150,16 +200,22 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
150
200
|
switch (name) {
|
|
151
201
|
case "add_memory": {
|
|
152
202
|
const response = await getClient().post("/add", args);
|
|
153
|
-
return {
|
|
203
|
+
return {
|
|
204
|
+
content: [{ type: "text", text: JSON.stringify(response.data) }],
|
|
205
|
+
};
|
|
154
206
|
}
|
|
155
207
|
case "query_memory": {
|
|
156
208
|
const response = await getClient().post("/query", args);
|
|
157
|
-
return {
|
|
209
|
+
return {
|
|
210
|
+
content: [{ type: "text", text: JSON.stringify(response.data) }],
|
|
211
|
+
};
|
|
158
212
|
}
|
|
159
213
|
case "list_memories": {
|
|
160
214
|
const limit = args?.limit || 10;
|
|
161
215
|
const response = await getClient().get(`/all?l=${limit}`);
|
|
162
|
-
return {
|
|
216
|
+
return {
|
|
217
|
+
content: [{ type: "text", text: JSON.stringify(response.data) }],
|
|
218
|
+
};
|
|
163
219
|
}
|
|
164
220
|
case "delete_memory": {
|
|
165
221
|
const { id } = args;
|
|
@@ -169,7 +225,9 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
169
225
|
case "update_memory": {
|
|
170
226
|
const { id, ...updates } = args;
|
|
171
227
|
const response = await getClient().patch(`/${id}`, updates);
|
|
172
|
-
return {
|
|
228
|
+
return {
|
|
229
|
+
content: [{ type: "text", text: JSON.stringify(response.data) }],
|
|
230
|
+
};
|
|
173
231
|
}
|
|
174
232
|
default:
|
|
175
233
|
throw new Error(`Unknown tool: ${name}`);
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -4,8 +4,10 @@ import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
|
|
|
4
4
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
5
5
|
import {
|
|
6
6
|
CallToolRequestSchema,
|
|
7
|
+
ListResourcesRequestSchema,
|
|
7
8
|
ListToolsRequestSchema,
|
|
8
|
-
|
|
9
|
+
ReadResourceRequestSchema,
|
|
10
|
+
Tool,
|
|
9
11
|
} from "@modelcontextprotocol/sdk/types.js";
|
|
10
12
|
import axios from "axios";
|
|
11
13
|
import cors from "cors";
|
|
@@ -21,18 +23,18 @@ const getArg = (name: string): string | undefined => {
|
|
|
21
23
|
return idx !== -1 && args[idx + 1] ? args[idx + 1] : undefined;
|
|
22
24
|
};
|
|
23
25
|
|
|
24
|
-
const cliUrl = getArg(
|
|
25
|
-
const cliApiKey = getArg(
|
|
26
|
-
const cliClientName = getArg(
|
|
26
|
+
const cliUrl = getArg("--url");
|
|
27
|
+
const cliApiKey = getArg("--api-key");
|
|
28
|
+
const cliClientName = getArg("--client-name");
|
|
27
29
|
|
|
28
30
|
// Use CLI args first, then env, then defaults
|
|
29
31
|
// Default to local CyberMem backend (via Traefik on port 8626)
|
|
30
|
-
const API_URL =
|
|
32
|
+
const API_URL =
|
|
33
|
+
cliUrl || process.env.CYBERMEM_URL || "http://localhost:8626/memory";
|
|
31
34
|
const API_KEY = cliApiKey || process.env.OM_API_KEY || "";
|
|
32
35
|
|
|
33
36
|
// Track client name per session
|
|
34
37
|
let currentClientName = cliClientName || "cybermem-mcp";
|
|
35
|
-
|
|
36
38
|
// CyberMem Agent Protocol - instructions sent to clients on handshake
|
|
37
39
|
const CYBERMEM_INSTRUCTIONS = `CyberMem is a persistent context daemon for AI agents.
|
|
38
40
|
|
|
@@ -55,36 +57,76 @@ INTEGRITY RULES:
|
|
|
55
57
|
|
|
56
58
|
For full protocol: https://cybermem.dev/docs/agent-protocol`;
|
|
57
59
|
|
|
60
|
+
// Short protocol reminder for tool descriptions (derived from main instructions)
|
|
61
|
+
const PROTOCOL_REMINDER =
|
|
62
|
+
"CyberMem Protocol: Store FULL content (no summaries), always include tags [topic, year, source:client-name]. Query 'user context profile' on session start.";
|
|
63
|
+
|
|
58
64
|
const server = new Server(
|
|
59
65
|
{
|
|
60
66
|
name: "cybermem",
|
|
61
|
-
version: "0.6.
|
|
67
|
+
version: "0.6.8",
|
|
62
68
|
},
|
|
63
69
|
{
|
|
64
70
|
capabilities: {
|
|
65
71
|
tools: {},
|
|
72
|
+
resources: {}, // Enable resources for protocol document
|
|
66
73
|
},
|
|
67
74
|
instructions: CYBERMEM_INSTRUCTIONS,
|
|
68
|
-
}
|
|
75
|
+
},
|
|
69
76
|
);
|
|
70
77
|
|
|
78
|
+
// Register resources handler for protocol document
|
|
79
|
+
server.setRequestHandler(ListResourcesRequestSchema, async () => ({
|
|
80
|
+
resources: [
|
|
81
|
+
{
|
|
82
|
+
uri: "cybermem://protocol",
|
|
83
|
+
name: "CyberMem Agent Protocol",
|
|
84
|
+
description: "Instructions for AI agents using CyberMem memory system",
|
|
85
|
+
mimeType: "text/plain",
|
|
86
|
+
},
|
|
87
|
+
],
|
|
88
|
+
}));
|
|
89
|
+
|
|
90
|
+
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
91
|
+
if (request.params.uri === "cybermem://protocol") {
|
|
92
|
+
return {
|
|
93
|
+
contents: [
|
|
94
|
+
{
|
|
95
|
+
uri: "cybermem://protocol",
|
|
96
|
+
mimeType: "text/plain",
|
|
97
|
+
text: CYBERMEM_INSTRUCTIONS,
|
|
98
|
+
},
|
|
99
|
+
],
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
throw new Error(`Unknown resource: ${request.params.uri}`);
|
|
103
|
+
});
|
|
104
|
+
|
|
71
105
|
const tools: Tool[] = [
|
|
72
106
|
{
|
|
73
107
|
name: "add_memory",
|
|
74
|
-
description:
|
|
108
|
+
description: `Store a new memory in CyberMem. ${PROTOCOL_REMINDER}`,
|
|
75
109
|
inputSchema: {
|
|
76
110
|
type: "object",
|
|
77
111
|
properties: {
|
|
78
|
-
content: {
|
|
112
|
+
content: {
|
|
113
|
+
type: "string",
|
|
114
|
+
description:
|
|
115
|
+
"Full content with all details - NO truncation or summarization",
|
|
116
|
+
},
|
|
79
117
|
user_id: { type: "string" },
|
|
80
|
-
tags: {
|
|
118
|
+
tags: {
|
|
119
|
+
type: "array",
|
|
120
|
+
items: { type: "string" },
|
|
121
|
+
description: "Always include [topic, year, source:your-client-name]",
|
|
122
|
+
},
|
|
81
123
|
},
|
|
82
124
|
required: ["content"],
|
|
83
125
|
},
|
|
84
126
|
},
|
|
85
127
|
{
|
|
86
128
|
name: "query_memory",
|
|
87
|
-
description:
|
|
129
|
+
description: `Search for relevant memories. On session start, call query_memory("user context profile") first.`,
|
|
88
130
|
inputSchema: {
|
|
89
131
|
type: "object",
|
|
90
132
|
properties: {
|
|
@@ -128,7 +170,7 @@ const tools: Tool[] = [
|
|
|
128
170
|
},
|
|
129
171
|
required: ["id"],
|
|
130
172
|
},
|
|
131
|
-
}
|
|
173
|
+
},
|
|
132
174
|
];
|
|
133
175
|
|
|
134
176
|
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
@@ -139,24 +181,45 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
139
181
|
const apiClient = axios.create({
|
|
140
182
|
baseURL: API_URL,
|
|
141
183
|
headers: {
|
|
142
|
-
|
|
184
|
+
Authorization: `Bearer ${API_KEY}`,
|
|
143
185
|
},
|
|
144
186
|
});
|
|
145
187
|
|
|
146
188
|
// Helper to get client with context
|
|
147
189
|
function getClient(customHeaders: Record<string, string> = {}) {
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
190
|
+
// Get client name from MCP protocol (sent during initialize) or fallback to CLI arg
|
|
191
|
+
const clientVersion = server.getClientVersion();
|
|
192
|
+
const clientName =
|
|
193
|
+
customHeaders["X-Client-Name"] || clientVersion?.name || currentClientName;
|
|
151
194
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
195
|
+
return {
|
|
196
|
+
...apiClient,
|
|
197
|
+
get: (url: string, config?: any) =>
|
|
198
|
+
apiClient.get(url, {
|
|
199
|
+
...config,
|
|
200
|
+
headers: { "X-Client-Name": clientName, ...config?.headers },
|
|
201
|
+
}),
|
|
202
|
+
post: (url: string, data?: any, config?: any) =>
|
|
203
|
+
apiClient.post(url, data, {
|
|
204
|
+
...config,
|
|
205
|
+
headers: { "X-Client-Name": clientName, ...config?.headers },
|
|
206
|
+
}),
|
|
207
|
+
put: (url: string, data?: any, config?: any) =>
|
|
208
|
+
apiClient.put(url, data, {
|
|
209
|
+
...config,
|
|
210
|
+
headers: { "X-Client-Name": clientName, ...config?.headers },
|
|
211
|
+
}),
|
|
212
|
+
patch: (url: string, data?: any, config?: any) =>
|
|
213
|
+
apiClient.patch(url, data, {
|
|
214
|
+
...config,
|
|
215
|
+
headers: { "X-Client-Name": clientName, ...config?.headers },
|
|
216
|
+
}),
|
|
217
|
+
delete: (url: string, config?: any) =>
|
|
218
|
+
apiClient.delete(url, {
|
|
219
|
+
...config,
|
|
220
|
+
headers: { "X-Client-Name": clientName, ...config?.headers },
|
|
221
|
+
}),
|
|
222
|
+
};
|
|
160
223
|
}
|
|
161
224
|
|
|
162
225
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
@@ -166,16 +229,22 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
166
229
|
switch (name) {
|
|
167
230
|
case "add_memory": {
|
|
168
231
|
const response = await getClient().post("/add", args);
|
|
169
|
-
return {
|
|
232
|
+
return {
|
|
233
|
+
content: [{ type: "text", text: JSON.stringify(response.data) }],
|
|
234
|
+
};
|
|
170
235
|
}
|
|
171
236
|
case "query_memory": {
|
|
172
237
|
const response = await getClient().post("/query", args);
|
|
173
|
-
return {
|
|
238
|
+
return {
|
|
239
|
+
content: [{ type: "text", text: JSON.stringify(response.data) }],
|
|
240
|
+
};
|
|
174
241
|
}
|
|
175
242
|
case "list_memories": {
|
|
176
243
|
const limit = args?.limit || 10;
|
|
177
244
|
const response = await getClient().get(`/all?l=${limit}`);
|
|
178
|
-
return {
|
|
245
|
+
return {
|
|
246
|
+
content: [{ type: "text", text: JSON.stringify(response.data) }],
|
|
247
|
+
};
|
|
179
248
|
}
|
|
180
249
|
case "delete_memory": {
|
|
181
250
|
const { id } = args as { id: string };
|
|
@@ -185,7 +254,9 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
185
254
|
case "update_memory": {
|
|
186
255
|
const { id, ...updates } = args as { id: string; [key: string]: any };
|
|
187
256
|
const response = await getClient().patch(`/${id}`, updates);
|
|
188
|
-
return {
|
|
257
|
+
return {
|
|
258
|
+
content: [{ type: "text", text: JSON.stringify(response.data) }],
|
|
259
|
+
};
|
|
189
260
|
}
|
|
190
261
|
default:
|
|
191
262
|
throw new Error(`Unknown tool: ${name}`);
|
|
@@ -234,11 +305,12 @@ async function run() {
|
|
|
234
305
|
});
|
|
235
306
|
|
|
236
307
|
app.listen(port, () => {
|
|
237
|
-
console.error(
|
|
308
|
+
console.error(
|
|
309
|
+
`CyberMem MCP Server running on SSE at http://localhost:${port}`,
|
|
310
|
+
);
|
|
238
311
|
console.error(` - SSE endpoint: http://localhost:${port}/sse`);
|
|
239
312
|
console.error(` - Message endpoint: http://localhost:${port}/messages`);
|
|
240
313
|
});
|
|
241
|
-
|
|
242
314
|
} else {
|
|
243
315
|
const transport = new StdioServerTransport();
|
|
244
316
|
await server.connect(transport);
|