@cybermem/mcp 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 ADDED
@@ -0,0 +1,49 @@
1
+ # @cybermem/mcp
2
+
3
+ Official TypeScript MCP Server for CyberMem.
4
+
5
+ ## Configuration
6
+
7
+ ### Option A: Local (Standard)
8
+ If you are running CyberMem locally on your machine, use `npx` to spawn the MCP server. It will bridge the connection to your local Docker instance.
9
+
10
+ **Claude Desktop Config (`~/Library/Application Support/Claude/claude_desktop_config.json`):**
11
+ ```json
12
+ {
13
+ "mcpServers": {
14
+ "cybermem": {
15
+ "command": "npx",
16
+ "args": [
17
+ "-y",
18
+ "@cybermem/mcp"
19
+ ],
20
+ "env": {
21
+ "CYBERMEM_URL": "http://localhost:8080/memory",
22
+ "CYBERMEM_API_KEY": "your-api-key"
23
+ }
24
+ }
25
+ }
26
+ }
27
+ ```
28
+
29
+ ### Option B: Remote (RPi / Cloud)
30
+ If you have deployed CyberMem to a Raspberry Pi or Cloud VPS, **do not use npx**. Instead, connect directly to the remote SSE endpoint.
31
+
32
+ **Claude Desktop Config:**
33
+ ```json
34
+ {
35
+ "mcpServers": {
36
+ "cybermem-remote": {
37
+ "url": "http://<your-rpi-ip>:8080/mcp",
38
+ "transport": "sse",
39
+ "headers": {
40
+ "x-api-key": "your-api-key"
41
+ }
42
+ }
43
+ }
44
+ }
45
+ ```
46
+
47
+ ## Environment Variables
48
+ - `CYBERMEM_URL`: URL to the OpenMemory API (default: `http://localhost:8080/memory`)
49
+ - `CYBERMEM_API_KEY`: Your API Key (found in `~/.cybermem/.env`)
package/dist/index.js ADDED
@@ -0,0 +1,104 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const index_js_1 = require("@modelcontextprotocol/sdk/server/index.js");
7
+ const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
8
+ const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
9
+ const axios_1 = __importDefault(require("axios"));
10
+ const dotenv_1 = __importDefault(require("dotenv"));
11
+ dotenv_1.default.config();
12
+ const API_URL = process.env.CYBERMEM_URL || "http://localhost:8080/memory";
13
+ const API_KEY = process.env.CYBERMEM_API_KEY || "dev-secret-key";
14
+ const server = new index_js_1.Server({
15
+ name: "cybermem-mcp",
16
+ version: "0.1.0",
17
+ }, {
18
+ capabilities: {
19
+ tools: {},
20
+ },
21
+ });
22
+ const tools = [
23
+ {
24
+ name: "add_memory",
25
+ description: "Store a new memory in CyberMem",
26
+ inputSchema: {
27
+ type: "object",
28
+ properties: {
29
+ content: { type: "string" },
30
+ user_id: { type: "string" },
31
+ tags: { type: "array", items: { type: "string" } },
32
+ },
33
+ required: ["content"],
34
+ },
35
+ },
36
+ {
37
+ name: "query_memory",
38
+ description: "Search for relevant memories",
39
+ inputSchema: {
40
+ type: "object",
41
+ properties: {
42
+ query: { type: "string" },
43
+ k: { type: "number", default: 5 },
44
+ },
45
+ required: ["query"],
46
+ },
47
+ },
48
+ {
49
+ name: "list_memories",
50
+ description: "List recent memories",
51
+ inputSchema: {
52
+ type: "object",
53
+ properties: {
54
+ limit: { type: "number", default: 10 },
55
+ },
56
+ },
57
+ }
58
+ ];
59
+ server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({
60
+ tools,
61
+ }));
62
+ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
63
+ const { name, arguments: args } = request.params;
64
+ try {
65
+ switch (name) {
66
+ case "add_memory": {
67
+ const response = await axios_1.default.post(`${API_URL}/add`, args, {
68
+ headers: { "Authorization": `Bearer ${API_KEY}` }
69
+ });
70
+ return { content: [{ type: "text", text: JSON.stringify(response.data) }] };
71
+ }
72
+ case "query_memory": {
73
+ const response = await axios_1.default.post(`${API_URL}/query`, args, {
74
+ headers: { "Authorization": `Bearer ${API_KEY}` }
75
+ });
76
+ return { content: [{ type: "text", text: JSON.stringify(response.data) }] };
77
+ }
78
+ case "list_memories": {
79
+ const limit = args?.limit || 10;
80
+ const response = await axios_1.default.get(`${API_URL}/list?limit=${limit}`, {
81
+ headers: { "Authorization": `Bearer ${API_KEY}` }
82
+ });
83
+ return { content: [{ type: "text", text: JSON.stringify(response.data) }] };
84
+ }
85
+ default:
86
+ throw new Error(`Unknown tool: ${name}`);
87
+ }
88
+ }
89
+ catch (error) {
90
+ return {
91
+ content: [{ type: "text", text: `Error: ${error.message}` }],
92
+ isError: true,
93
+ };
94
+ }
95
+ });
96
+ async function run() {
97
+ const transport = new stdio_js_1.StdioServerTransport();
98
+ await server.connect(transport);
99
+ console.error("CyberMem MCP Server running on stdio");
100
+ }
101
+ run().catch((error) => {
102
+ console.error("Fatal error running server:", error);
103
+ process.exit(1);
104
+ });
package/package.json ADDED
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "@cybermem/mcp",
3
+ "version": "0.1.0",
4
+ "description": "CyberMem MCP Server (TypeScript)",
5
+ "main": "dist/index.js",
6
+ "bin": {
7
+ "cybermem-mcp": "./dist/index.js"
8
+ },
9
+ "scripts": {
10
+ "build": "tsc",
11
+ "start": "node dist/index.js",
12
+ "dev": "ts-node src/index.ts"
13
+ },
14
+ "publishConfig": {
15
+ "access": "public"
16
+ },
17
+ "dependencies": {
18
+ "@modelcontextprotocol/sdk": "^1.0.0",
19
+ "axios": "^1.6.0",
20
+ "dotenv": "^16.0.0"
21
+ },
22
+ "devDependencies": {
23
+ "@types/node": "^18.0.0",
24
+ "ts-node": "^10.9.1",
25
+ "typescript": "^5.0.0"
26
+ }
27
+ }
@@ -0,0 +1,2 @@
1
+ mcp>=0.9.0
2
+ httpx>=0.27.0
package/server.py ADDED
@@ -0,0 +1,347 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ CyberMem MCP Server
4
+
5
+ MCP server that exposes shared memory functionality to several LLM.
6
+ """
7
+
8
+ import asyncio
9
+ import os
10
+ from typing import Any
11
+
12
+ import httpx
13
+ from mcp import types
14
+ from mcp.server import NotificationOptions, Server
15
+ from mcp.server.models import InitializationOptions
16
+ from mcp.server.stdio import stdio_server
17
+
18
+ # CyberMem configuration (OpenMemory backend)
19
+ OPENMEMORY_URL = os.getenv("OPENMEMORY_URL", "http://localhost:80")
20
+ CYBERMEM_API_KEY = os.getenv("CYBERMEM_API_KEY", "dev-secret-key")
21
+
22
+ # Create MCP server instance
23
+ server = Server("cybermem")
24
+
25
+
26
+ @server.list_tools()
27
+ async def handle_list_tools() -> list[types.Tool]:
28
+ """List available memory management tools."""
29
+ return [
30
+ types.Tool(
31
+ name="add_memory",
32
+ description="Store information in long-term memory. Use this to remember important facts, decisions, or context for future conversations.",
33
+ inputSchema={
34
+ "type": "object",
35
+ "properties": {
36
+ "content": {
37
+ "type": "string",
38
+ "description": "The information to remember (text content)",
39
+ },
40
+ "metadata": {
41
+ "type": "object",
42
+ "description": "Optional metadata (tags, category, importance, etc.)",
43
+ "additionalProperties": True,
44
+ },
45
+ },
46
+ "required": ["content"],
47
+ },
48
+ ),
49
+ types.Tool(
50
+ name="search_memory",
51
+ description="Search through stored memories to find relevant information. Use this to recall past conversations, decisions, or facts.",
52
+ inputSchema={
53
+ "type": "object",
54
+ "properties": {
55
+ "query": {
56
+ "type": "string",
57
+ "description": "What to search for (semantic search query)",
58
+ },
59
+ "limit": {
60
+ "type": "number",
61
+ "description": "Maximum number of results (default: 5)",
62
+ "default": 5,
63
+ },
64
+ },
65
+ "required": ["query"],
66
+ },
67
+ ),
68
+ types.Tool(
69
+ name="list_memories",
70
+ description="List recent memories stored in the system. Useful for browsing what has been remembered.",
71
+ inputSchema={
72
+ "type": "object",
73
+ "properties": {
74
+ "limit": {
75
+ "type": "number",
76
+ "description": "Maximum number of memories to retrieve (default: 10)",
77
+ "default": 10,
78
+ }
79
+ },
80
+ },
81
+ ),
82
+ types.Tool(
83
+ name="delete_memory",
84
+ description="Delete a specific memory by its ID. Use this to remove outdated or incorrect information.",
85
+ inputSchema={
86
+ "type": "object",
87
+ "properties": {
88
+ "memory_id": {
89
+ "type": "string",
90
+ "description": "The UUID of the memory to delete",
91
+ }
92
+ },
93
+ "required": ["memory_id"],
94
+ },
95
+ ),
96
+ types.Tool(
97
+ name="update_memory",
98
+ description="Update an existing memory's content, tags, or metadata.",
99
+ inputSchema={
100
+ "type": "object",
101
+ "properties": {
102
+ "memory_id": {
103
+ "type": "string",
104
+ "description": "The UUID of the memory to update",
105
+ },
106
+ "content": {
107
+ "type": "string",
108
+ "description": "New content for the memory (optional)",
109
+ },
110
+ "tags": {
111
+ "type": "array",
112
+ "items": {"type": "string"},
113
+ "description": "New tags for the memory (optional)",
114
+ },
115
+ "metadata": {
116
+ "type": "object",
117
+ "description": "New metadata for the memory (optional)",
118
+ "additionalProperties": True,
119
+ },
120
+ },
121
+ "required": ["memory_id"],
122
+ },
123
+ ),
124
+ ]
125
+
126
+
127
+ @server.call_tool()
128
+ async def handle_call_tool(
129
+ name: str, arguments: dict[str, Any]
130
+ ) -> list[types.TextContent]:
131
+ """Handle tool execution requests."""
132
+
133
+ # Get client info from MCP context
134
+ client_name, client_version = "unknown", "unknown"
135
+ try:
136
+ ctx = server.request_context
137
+ if hasattr(ctx, "session"):
138
+ session = ctx.session
139
+ if hasattr(session, "_client_params"):
140
+ client_params = session._client_params
141
+ if client_params and hasattr(client_params, "clientInfo"):
142
+ client_info = client_params.clientInfo
143
+ client_name = client_info.name or "unknown"
144
+ client_version = client_info.version or "unknown"
145
+ except Exception:
146
+ pass
147
+
148
+ headers = {
149
+ "Authorization": f"Bearer {CYBERMEM_API_KEY}",
150
+ "Content-Type": "application/json",
151
+ "X-Client-Name": client_name,
152
+ "X-Client-Version": client_version,
153
+ }
154
+
155
+ async with httpx.AsyncClient(timeout=30.0) as client:
156
+ try:
157
+ if name == "add_memory":
158
+ # Store memory in OpenMemory
159
+ content = arguments.get("content")
160
+ metadata = arguments.get("metadata", {})
161
+
162
+ response = await client.post(
163
+ f"{OPENMEMORY_URL}/memory/add",
164
+ json={"content": content, "metadata": metadata},
165
+ headers=headers,
166
+ )
167
+ response.raise_for_status()
168
+ result = response.json()
169
+
170
+ return [
171
+ types.TextContent(
172
+ type="text",
173
+ text=f"āœ… Memory stored successfully!\n\nID: {result.get('id')}\nChunks: {result.get('chunks')}\nSectors: {', '.join(result.get('sectors', []))}",
174
+ )
175
+ ]
176
+
177
+ elif name == "search_memory":
178
+ # Search memories in OpenMemory
179
+ query = arguments.get("query")
180
+ limit = arguments.get("limit", 5)
181
+
182
+ response = await client.post(
183
+ f"{OPENMEMORY_URL}/memory/query",
184
+ json={"query": query, "k": limit},
185
+ headers=headers,
186
+ )
187
+ response.raise_for_status()
188
+ data = response.json()
189
+ matches = data.get("matches", [])
190
+
191
+ if not matches:
192
+ return [
193
+ types.TextContent(
194
+ type="text",
195
+ text="šŸ” No memories found matching your query.",
196
+ )
197
+ ]
198
+
199
+ # Format search results
200
+ formatted_results = []
201
+ for i, memory in enumerate(matches, 1):
202
+ content = memory.get("content", "")
203
+ score = memory.get("score", 0)
204
+ sector = memory.get("primary_sector", "")
205
+
206
+ formatted_results.append(
207
+ f"**Result {i}** (score: {score:.2f}, sector: {sector})\n{content}\n"
208
+ )
209
+
210
+ return [
211
+ types.TextContent(
212
+ type="text",
213
+ text=f"šŸ” Found {len(matches)} memories:\n\n"
214
+ + "\n".join(formatted_results),
215
+ )
216
+ ]
217
+
218
+ elif name == "list_memories":
219
+ # List recent memories
220
+ limit = arguments.get("limit", 10)
221
+
222
+ # Note: OpenMemory doesn't have a /list endpoint yet,
223
+ # so we'll do a broad query with generic term
224
+ response = await client.post(
225
+ f"{OPENMEMORY_URL}/memory/query",
226
+ json={"query": "memory context", "k": limit},
227
+ headers=headers,
228
+ )
229
+ response.raise_for_status()
230
+ data = response.json()
231
+ matches = data.get("matches", [])
232
+
233
+ if not matches:
234
+ return [
235
+ types.TextContent(
236
+ type="text", text="šŸ“‹ No memories stored yet."
237
+ )
238
+ ]
239
+
240
+ # Format list
241
+ formatted_list = []
242
+ for i, memory in enumerate(matches, 1):
243
+ content = memory.get("content", "")
244
+ sector = memory.get("primary_sector", "")
245
+ # Truncate long content
246
+ if len(content) > 100:
247
+ content = content[:97] + "..."
248
+ formatted_list.append(f"{i}. [{sector}] {content}")
249
+
250
+ return [
251
+ types.TextContent(
252
+ type="text",
253
+ text=f"šŸ“‹ Recent memories ({len(matches)}):\n\n"
254
+ + "\n".join(formatted_list),
255
+ )
256
+ ]
257
+
258
+ elif name == "delete_memory":
259
+ # Delete memory by ID
260
+ memory_id = arguments.get("memory_id")
261
+
262
+ try:
263
+ response = await client.delete(
264
+ f"{OPENMEMORY_URL}/memory/{memory_id}", headers=headers
265
+ )
266
+ response.raise_for_status()
267
+ result = response.json()
268
+ status = result.get("ok", "deleted")
269
+ except httpx.HTTPStatusError as e:
270
+ # Workaround: OpenMemory returns 500 on successful delete (bug in OpenMemory)
271
+ # We'll treat it as success since the memory is actually deleted
272
+ if e.response.status_code == 500:
273
+ status = "deleted (500 ignored - OpenMemory bug)"
274
+ else:
275
+ raise
276
+
277
+ return [
278
+ types.TextContent(
279
+ type="text",
280
+ text=f"šŸ—‘ļø Memory deleted successfully!\n\nID: {memory_id}\nStatus: {status}",
281
+ )
282
+ ]
283
+
284
+ elif name == "update_memory":
285
+ # Update memory by ID
286
+ memory_id = arguments.get("memory_id")
287
+ content = arguments.get("content")
288
+ tags = arguments.get("tags")
289
+ metadata = arguments.get("metadata")
290
+
291
+ payload = {}
292
+ if content:
293
+ payload["content"] = content
294
+ if tags:
295
+ payload["tags"] = tags
296
+ if metadata:
297
+ payload["metadata"] = metadata
298
+
299
+ response = await client.patch(
300
+ f"{OPENMEMORY_URL}/memory/{memory_id}",
301
+ json=payload,
302
+ headers=headers,
303
+ )
304
+ response.raise_for_status()
305
+ result = response.json()
306
+
307
+ return [
308
+ types.TextContent(
309
+ type="text",
310
+ text=f"āœļø Memory updated successfully!\n\nID: {result.get('id', memory_id)}",
311
+ )
312
+ ]
313
+
314
+ else:
315
+ raise ValueError(f"Unknown tool: {name}")
316
+
317
+ except httpx.HTTPStatusError as e:
318
+ return [
319
+ types.TextContent(
320
+ type="text",
321
+ text=f"āŒ API Error: {e.response.status_code}\n{e.response.text}",
322
+ )
323
+ ]
324
+ except Exception as e:
325
+ return [types.TextContent(type="text", text=f"āŒ Error: {str(e)}")]
326
+
327
+
328
+ async def main():
329
+ """Run the MCP server."""
330
+
331
+ async with stdio_server() as (read_stream, write_stream):
332
+ await server.run(
333
+ read_stream,
334
+ write_stream,
335
+ InitializationOptions(
336
+ server_name="cybermem",
337
+ server_version="0.1.0",
338
+ capabilities=server.get_capabilities(
339
+ notification_options=NotificationOptions(),
340
+ experimental_capabilities={},
341
+ ),
342
+ ),
343
+ )
344
+
345
+
346
+ if __name__ == "__main__":
347
+ asyncio.run(main())
package/src/index.ts ADDED
@@ -0,0 +1,114 @@
1
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
2
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ import {
4
+ CallToolRequestSchema,
5
+ ListToolsRequestSchema,
6
+ Tool
7
+ } from "@modelcontextprotocol/sdk/types.js";
8
+ import axios from "axios";
9
+ import dotenv from "dotenv";
10
+
11
+ dotenv.config();
12
+
13
+ const API_URL = process.env.CYBERMEM_URL || "http://localhost:8080/memory";
14
+ const API_KEY = process.env.CYBERMEM_API_KEY || "dev-secret-key";
15
+
16
+ const server = new Server(
17
+ {
18
+ name: "cybermem-mcp",
19
+ version: "0.1.0",
20
+ },
21
+ {
22
+ capabilities: {
23
+ tools: {},
24
+ },
25
+ }
26
+ );
27
+
28
+ const tools: Tool[] = [
29
+ {
30
+ name: "add_memory",
31
+ description: "Store a new memory in CyberMem",
32
+ inputSchema: {
33
+ type: "object",
34
+ properties: {
35
+ content: { type: "string" },
36
+ user_id: { type: "string" },
37
+ tags: { type: "array", items: { type: "string" } },
38
+ },
39
+ required: ["content"],
40
+ },
41
+ },
42
+ {
43
+ name: "query_memory",
44
+ description: "Search for relevant memories",
45
+ inputSchema: {
46
+ type: "object",
47
+ properties: {
48
+ query: { type: "string" },
49
+ k: { type: "number", default: 5 },
50
+ },
51
+ required: ["query"],
52
+ },
53
+ },
54
+ {
55
+ name: "list_memories",
56
+ description: "List recent memories",
57
+ inputSchema: {
58
+ type: "object",
59
+ properties: {
60
+ limit: { type: "number", default: 10 },
61
+ },
62
+ },
63
+ }
64
+ ];
65
+
66
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({
67
+ tools,
68
+ }));
69
+
70
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
71
+ const { name, arguments: args } = request.params;
72
+
73
+ try {
74
+ switch (name) {
75
+ case "add_memory": {
76
+ const response = await axios.post(`${API_URL}/add`, args, {
77
+ headers: { "Authorization": `Bearer ${API_KEY}` }
78
+ });
79
+ return { content: [{ type: "text", text: JSON.stringify(response.data) }] };
80
+ }
81
+ case "query_memory": {
82
+ const response = await axios.post(`${API_URL}/query`, args, {
83
+ headers: { "Authorization": `Bearer ${API_KEY}` }
84
+ });
85
+ return { content: [{ type: "text", text: JSON.stringify(response.data) }] };
86
+ }
87
+ case "list_memories": {
88
+ const limit = args?.limit || 10;
89
+ const response = await axios.get(`${API_URL}/list?limit=${limit}`, {
90
+ headers: { "Authorization": `Bearer ${API_KEY}` }
91
+ });
92
+ return { content: [{ type: "text", text: JSON.stringify(response.data) }] };
93
+ }
94
+ default:
95
+ throw new Error(`Unknown tool: ${name}`);
96
+ }
97
+ } catch (error: any) {
98
+ return {
99
+ content: [{ type: "text", text: `Error: ${error.message}` }],
100
+ isError: true,
101
+ };
102
+ }
103
+ });
104
+
105
+ async function run() {
106
+ const transport = new StdioServerTransport();
107
+ await server.connect(transport);
108
+ console.error("CyberMem MCP Server running on stdio");
109
+ }
110
+
111
+ run().catch((error) => {
112
+ console.error("Fatal error running server:", error);
113
+ process.exit(1);
114
+ });
package/test_mcp.py ADDED
@@ -0,0 +1,111 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Test script for OpenMemory MCP Server
4
+
5
+ Demonstrates MCP server functionality by simulating tool calls.
6
+ """
7
+
8
+ import asyncio
9
+ import httpx
10
+ import json
11
+
12
+
13
+ OPENMEMORY_URL = "http://localhost/memory"
14
+ OPENMEMORY_API_KEY = "dev-secret-key"
15
+
16
+
17
+ async def test_add_memory():
18
+ """Test adding a memory."""
19
+ print("\n🧪 Test 1: Adding memory...")
20
+
21
+ headers = {
22
+ "Authorization": f"Bearer {OPENMEMORY_API_KEY}",
23
+ "Content-Type": "application/json"
24
+ }
25
+
26
+ async with httpx.AsyncClient(timeout=30.0) as client:
27
+ response = await client.post(
28
+ f"{OPENMEMORY_URL}/add",
29
+ json={
30
+ "content": "MCP server test: Claude Code can now remember conversations and context",
31
+ "metadata": {
32
+ "source": "mcp_test",
33
+ "category": "integration_test",
34
+ "timestamp": "2025-11-30"
35
+ }
36
+ },
37
+ headers=headers
38
+ )
39
+
40
+ if response.status_code == 200:
41
+ result = response.json()
42
+ print(f"āœ… Memory added successfully!")
43
+ print(f" ID: {result.get('id')}")
44
+ print(f" Chunks: {result.get('chunks')}")
45
+ print(f" Sectors: {', '.join(result.get('sectors', []))}")
46
+ return result.get('id')
47
+ else:
48
+ print(f"āŒ Failed: {response.status_code} - {response.text}")
49
+ return None
50
+
51
+
52
+ async def test_search_memory():
53
+ """Test searching memories."""
54
+ print("\n🧪 Test 2: Searching memory...")
55
+
56
+ headers = {
57
+ "Authorization": f"Bearer {OPENMEMORY_API_KEY}",
58
+ "Content-Type": "application/json"
59
+ }
60
+
61
+ async with httpx.AsyncClient(timeout=30.0) as client:
62
+ response = await client.post(
63
+ f"{OPENMEMORY_URL}/query",
64
+ json={
65
+ "query": "Claude Code remember conversations",
66
+ "k": 3
67
+ },
68
+ headers=headers
69
+ )
70
+
71
+ if response.status_code == 200:
72
+ data = response.json()
73
+ matches = data.get("matches", [])
74
+ print(f"āœ… Found {len(matches)} memories:")
75
+ for i, memory in enumerate(matches, 1):
76
+ content = memory.get("content", "")
77
+ score = memory.get("score", 0)
78
+ sector = memory.get("primary_sector", "")
79
+ print(f"\n Result {i} (score: {score:.2f}, sector: {sector}):")
80
+ print(f" {content[:100]}...")
81
+ else:
82
+ print(f"āŒ Failed: {response.status_code} - {response.text}")
83
+
84
+
85
+ async def test_mcp_integration():
86
+ """Run full MCP integration test."""
87
+ print("=" * 60)
88
+ print("OpenMemory MCP Server - Integration Test")
89
+ print("=" * 60)
90
+
91
+ # Test 1: Add memory
92
+ memory_id = await test_add_memory()
93
+
94
+ # Wait a bit for indexing
95
+ await asyncio.sleep(2)
96
+
97
+ # Test 2: Search memory
98
+ await test_search_memory()
99
+
100
+ print("\n" + "=" * 60)
101
+ print("āœ… Integration test completed!")
102
+ print("=" * 60)
103
+ print("\nNext steps:")
104
+ print("1. Restart Claude Code to load the MCP server")
105
+ print("2. Try asking Claude Code to remember something")
106
+ print("3. Check Grafana dashboard for audit trail")
107
+ print(" → http://localhost:3000/d/cybermem-memory")
108
+
109
+
110
+ if __name__ == "__main__":
111
+ asyncio.run(test_mcp_integration())
package/tsconfig.json ADDED
@@ -0,0 +1,14 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "NodeNext",
5
+ "moduleResolution": "NodeNext",
6
+ "outDir": "./dist",
7
+ "rootDir": "./src",
8
+ "strict": true,
9
+ "esModuleInterop": true,
10
+ "skipLibCheck": true,
11
+ "forceConsistentCasingInFileNames": true
12
+ },
13
+ "include": ["src/**/*"]
14
+ }