@199-bio/engram 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.
@@ -0,0 +1,218 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Interactive test for Engram MCP server
4
+ * Sends multiple requests and captures responses
5
+ */
6
+
7
+ import { spawn } from "child_process";
8
+ import { createInterface } from "readline";
9
+ import path from "path";
10
+ import { fileURLToPath } from "url";
11
+
12
+ const __filename = fileURLToPath(import.meta.url);
13
+ const __dirname = path.dirname(__filename);
14
+
15
+ const requests = [
16
+ // 1. Stats (empty)
17
+ {
18
+ name: "Stats (empty)",
19
+ request: { method: "tools/call", params: { name: "stats", arguments: {} } },
20
+ },
21
+ // 2. Remember Sarah
22
+ {
23
+ name: "Remember Sarah background",
24
+ request: {
25
+ method: "tools/call",
26
+ params: {
27
+ name: "remember",
28
+ arguments: {
29
+ content: "Sarah Chen is the VP of Engineering at Acme Corp. She's allergic to shellfish, prefers window seats on flights, and is leading the Q1 product launch.",
30
+ importance: 0.9,
31
+ },
32
+ },
33
+ },
34
+ },
35
+ // 3. Remember Sarah preferences
36
+ {
37
+ name: "Remember Sarah preferences",
38
+ request: {
39
+ method: "tools/call",
40
+ params: {
41
+ name: "remember",
42
+ arguments: {
43
+ content: "Sarah prefers async communication over meetings. She's most productive in the mornings and usually blocks her calendar before 10am for deep work.",
44
+ importance: 0.8,
45
+ },
46
+ },
47
+ },
48
+ },
49
+ // 4. Remember John
50
+ {
51
+ name: "Remember John",
52
+ request: {
53
+ method: "tools/call",
54
+ params: {
55
+ name: "remember",
56
+ arguments: {
57
+ content: "John Martinez is a senior developer who reports to Sarah. He's an expert in backend systems and recently led the API redesign project.",
58
+ },
59
+ },
60
+ },
61
+ },
62
+ // 5. Create relationship
63
+ {
64
+ name: "Relate Sarah and John",
65
+ request: {
66
+ method: "tools/call",
67
+ params: {
68
+ name: "relate",
69
+ arguments: { from: "John Martinez", to: "Sarah Chen", relation: "reports_to" },
70
+ },
71
+ },
72
+ },
73
+ // 6. Add observation
74
+ {
75
+ name: "Observe Sarah allergy",
76
+ request: {
77
+ method: "tools/call",
78
+ params: {
79
+ name: "observe",
80
+ arguments: {
81
+ entity: "Sarah Chen",
82
+ observation: "Has severe shellfish allergy - avoid all seafood restaurants for team events",
83
+ },
84
+ },
85
+ },
86
+ },
87
+ // 7. Query entity
88
+ {
89
+ name: "Query Sarah entity",
90
+ request: {
91
+ method: "tools/call",
92
+ params: { name: "query_entity", arguments: { entity: "Sarah Chen" } },
93
+ },
94
+ },
95
+ // 8. Recall semantic
96
+ {
97
+ name: "Recall: Sarah's work preferences",
98
+ request: {
99
+ method: "tools/call",
100
+ params: {
101
+ name: "recall",
102
+ arguments: { query: "How does Sarah prefer to work and communicate?" },
103
+ },
104
+ },
105
+ },
106
+ // 9. Recall by context
107
+ {
108
+ name: "Recall: Team lunch planning",
109
+ request: {
110
+ method: "tools/call",
111
+ params: {
112
+ name: "recall",
113
+ arguments: { query: "What should I know when planning a team lunch?" },
114
+ },
115
+ },
116
+ },
117
+ // 10. List entities
118
+ {
119
+ name: "List person entities",
120
+ request: {
121
+ method: "tools/call",
122
+ params: { name: "list_entities", arguments: { type: "person" } },
123
+ },
124
+ },
125
+ // 11. Final stats
126
+ {
127
+ name: "Final stats",
128
+ request: { method: "tools/call", params: { name: "stats", arguments: {} } },
129
+ },
130
+ ];
131
+
132
+ async function main() {
133
+ console.log("=== Engram MCP Test Suite ===\n");
134
+
135
+ // Start the MCP server
136
+ const serverPath = path.join(__dirname, "..", "dist", "index.js");
137
+ const server = spawn("node", [serverPath], {
138
+ stdio: ["pipe", "pipe", "pipe"],
139
+ });
140
+
141
+ // Capture stderr for logging
142
+ server.stderr.on("data", (data) => {
143
+ const msg = data.toString().trim();
144
+ if (msg) console.log(`[Server] ${msg}`);
145
+ });
146
+
147
+ const rl = createInterface({
148
+ input: server.stdout,
149
+ crlfDelay: Infinity,
150
+ });
151
+
152
+ let responseResolve;
153
+ let responsePromise;
154
+
155
+ rl.on("line", (line) => {
156
+ try {
157
+ const response = JSON.parse(line);
158
+ if (responseResolve) {
159
+ responseResolve(response);
160
+ }
161
+ } catch (e) {
162
+ // Ignore non-JSON lines
163
+ }
164
+ });
165
+
166
+ // Wait for server to be ready
167
+ await new Promise((resolve) => setTimeout(resolve, 3000));
168
+
169
+ // Run each test
170
+ let id = 1;
171
+ for (const test of requests) {
172
+ console.log(`\n--- Test ${id}: ${test.name} ---`);
173
+
174
+ responsePromise = new Promise((resolve) => {
175
+ responseResolve = resolve;
176
+ });
177
+
178
+ const request = {
179
+ jsonrpc: "2.0",
180
+ id: id++,
181
+ ...test.request,
182
+ };
183
+
184
+ server.stdin.write(JSON.stringify(request) + "\n");
185
+
186
+ try {
187
+ const response = await Promise.race([
188
+ responsePromise,
189
+ new Promise((_, reject) =>
190
+ setTimeout(() => reject(new Error("Timeout")), 10000)
191
+ ),
192
+ ]);
193
+
194
+ if (response.error) {
195
+ console.log(`Error: ${JSON.stringify(response.error)}`);
196
+ } else if (response.result?.content?.[0]?.text) {
197
+ const text = response.result.content[0].text;
198
+ try {
199
+ const parsed = JSON.parse(text);
200
+ console.log(`Result: ${JSON.stringify(parsed, null, 2)}`);
201
+ } catch {
202
+ console.log(`Result: ${text}`);
203
+ }
204
+ } else {
205
+ console.log(`Response: ${JSON.stringify(response, null, 2)}`);
206
+ }
207
+ } catch (e) {
208
+ console.log(`Error: ${e.message}`);
209
+ }
210
+ }
211
+
212
+ // Cleanup
213
+ console.log("\n=== Tests Complete ===");
214
+ server.kill();
215
+ process.exit(0);
216
+ }
217
+
218
+ main().catch(console.error);
@@ -0,0 +1,81 @@
1
+ #!/bin/bash
2
+ # Test Engram MCP server with fictional examples
3
+
4
+ cd "$(dirname "$0")/.."
5
+
6
+ echo "=== Testing Engram MCP Server ==="
7
+ echo ""
8
+
9
+ # Function to send JSON-RPC request
10
+ send_request() {
11
+ local request="$1"
12
+ echo "$request" | node dist/index.js 2>/dev/null | grep -v '^\[' | head -1
13
+ }
14
+
15
+ # Test 1: Stats (empty)
16
+ echo "1. Testing stats (empty database)..."
17
+ STATS=$(send_request '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"stats","arguments":{}}}')
18
+ echo "Response: $STATS"
19
+ echo ""
20
+
21
+ # Test 2: Remember a memory about Sarah
22
+ echo "2. Testing remember (Sarah memory)..."
23
+ REMEMBER1=$(send_request '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"remember","arguments":{"content":"Sarah Chen is the VP of Engineering at Acme Corp. She is allergic to shellfish and prefers window seats on flights.","importance":0.9}}}')
24
+ echo "Response: $REMEMBER1"
25
+ echo ""
26
+
27
+ # Test 3: Remember another memory
28
+ echo "3. Testing remember (Sarah work preferences)..."
29
+ REMEMBER2=$(send_request '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"remember","arguments":{"content":"Sarah prefers async communication over meetings. She blocks her calendar before 10am for deep work.","importance":0.8}}}')
30
+ echo "Response: $REMEMBER2"
31
+ echo ""
32
+
33
+ # Test 4: Remember about John
34
+ echo "4. Testing remember (John memory)..."
35
+ REMEMBER3=$(send_request '{"jsonrpc":"2.0","id":4,"method":"tools/call","params":{"name":"remember","arguments":{"content":"John Martinez is a senior developer who reports to Sarah. He is an expert in backend systems."}}}')
36
+ echo "Response: $REMEMBER3"
37
+ echo ""
38
+
39
+ # Test 5: Create explicit relationship
40
+ echo "5. Testing relate (John and Sarah)..."
41
+ RELATE=$(send_request '{"jsonrpc":"2.0","id":5,"method":"tools/call","params":{"name":"relate","arguments":{"from":"John Martinez","to":"Sarah Chen","relation":"reports_to"}}}')
42
+ echo "Response: $RELATE"
43
+ echo ""
44
+
45
+ # Test 6: Add observation
46
+ echo "6. Testing observe (Sarah allergy)..."
47
+ OBSERVE=$(send_request '{"jsonrpc":"2.0","id":6,"method":"tools/call","params":{"name":"observe","arguments":{"entity":"Sarah Chen","observation":"Has severe shellfish allergy - avoid seafood restaurants"}}}')
48
+ echo "Response: $OBSERVE"
49
+ echo ""
50
+
51
+ # Test 7: Query entity
52
+ echo "7. Testing query_entity (Sarah)..."
53
+ QUERY=$(send_request '{"jsonrpc":"2.0","id":7,"method":"tools/call","params":{"name":"query_entity","arguments":{"entity":"Sarah Chen"}}}')
54
+ echo "Response: $QUERY"
55
+ echo ""
56
+
57
+ # Test 8: Recall - semantic search
58
+ echo "8. Testing recall (Sarah work preferences)..."
59
+ RECALL1=$(send_request '{"jsonrpc":"2.0","id":8,"method":"tools/call","params":{"name":"recall","arguments":{"query":"How does Sarah prefer to work and communicate?"}}}')
60
+ echo "Response: $RECALL1"
61
+ echo ""
62
+
63
+ # Test 9: Recall - context search
64
+ echo "9. Testing recall (team lunch planning)..."
65
+ RECALL2=$(send_request '{"jsonrpc":"2.0","id":9,"method":"tools/call","params":{"name":"recall","arguments":{"query":"What should I know when planning a team lunch?"}}}')
66
+ echo "Response: $RECALL2"
67
+ echo ""
68
+
69
+ # Test 10: List entities
70
+ echo "10. Testing list_entities..."
71
+ LIST=$(send_request '{"jsonrpc":"2.0","id":10,"method":"tools/call","params":{"name":"list_entities","arguments":{"type":"person"}}}')
72
+ echo "Response: $LIST"
73
+ echo ""
74
+
75
+ # Test 11: Final stats
76
+ echo "11. Testing stats (after adding data)..."
77
+ FINAL_STATS=$(send_request '{"jsonrpc":"2.0","id":11,"method":"tools/call","params":{"name":"stats","arguments":{}}}')
78
+ echo "Response: $FINAL_STATS"
79
+ echo ""
80
+
81
+ echo "=== All tests completed ==="
package/tsconfig.json ADDED
@@ -0,0 +1,20 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "NodeNext",
5
+ "moduleResolution": "NodeNext",
6
+ "lib": ["ES2022"],
7
+ "outDir": "./dist",
8
+ "rootDir": "./src",
9
+ "strict": true,
10
+ "esModuleInterop": true,
11
+ "skipLibCheck": true,
12
+ "forceConsistentCasingInFileNames": true,
13
+ "resolveJsonModule": true,
14
+ "declaration": true,
15
+ "declarationMap": true,
16
+ "sourceMap": true
17
+ },
18
+ "include": ["src/**/*"],
19
+ "exclude": ["node_modules", "dist", "tests"]
20
+ }