@dungle-scrubs/hippo 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.
Files changed (95) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +439 -0
  3. package/dist/cli.d.ts +3 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +559 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/db.d.ts +45 -0
  8. package/dist/db.d.ts.map +1 -0
  9. package/dist/db.js +80 -0
  10. package/dist/db.js.map +1 -0
  11. package/dist/extractor.d.ts +23 -0
  12. package/dist/extractor.d.ts.map +1 -0
  13. package/dist/extractor.js +121 -0
  14. package/dist/extractor.js.map +1 -0
  15. package/dist/hash.d.ts +11 -0
  16. package/dist/hash.d.ts.map +1 -0
  17. package/dist/hash.js +14 -0
  18. package/dist/hash.js.map +1 -0
  19. package/dist/index.d.ts +19 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +40 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/providers/embedding.d.ts +27 -0
  24. package/dist/providers/embedding.d.ts.map +1 -0
  25. package/dist/providers/embedding.js +41 -0
  26. package/dist/providers/embedding.js.map +1 -0
  27. package/dist/providers/llm.d.ts +29 -0
  28. package/dist/providers/llm.d.ts.map +1 -0
  29. package/dist/providers/llm.js +74 -0
  30. package/dist/providers/llm.js.map +1 -0
  31. package/dist/schema.d.ts +20 -0
  32. package/dist/schema.d.ts.map +1 -0
  33. package/dist/schema.js +78 -0
  34. package/dist/schema.js.map +1 -0
  35. package/dist/server/config.d.ts +38 -0
  36. package/dist/server/config.d.ts.map +1 -0
  37. package/dist/server/config.js +71 -0
  38. package/dist/server/config.js.map +1 -0
  39. package/dist/server/index.d.ts +13 -0
  40. package/dist/server/index.d.ts.map +1 -0
  41. package/dist/server/index.js +372 -0
  42. package/dist/server/index.js.map +1 -0
  43. package/dist/similarity.d.ts +41 -0
  44. package/dist/similarity.d.ts.map +1 -0
  45. package/dist/similarity.js +70 -0
  46. package/dist/similarity.js.map +1 -0
  47. package/dist/strength.d.ts +59 -0
  48. package/dist/strength.d.ts.map +1 -0
  49. package/dist/strength.js +76 -0
  50. package/dist/strength.js.map +1 -0
  51. package/dist/tools/append-memory-block.d.ts +22 -0
  52. package/dist/tools/append-memory-block.d.ts.map +1 -0
  53. package/dist/tools/append-memory-block.js +45 -0
  54. package/dist/tools/append-memory-block.js.map +1 -0
  55. package/dist/tools/forget-memory.d.ts +31 -0
  56. package/dist/tools/forget-memory.d.ts.map +1 -0
  57. package/dist/tools/forget-memory.js +77 -0
  58. package/dist/tools/forget-memory.js.map +1 -0
  59. package/dist/tools/index.d.ts +9 -0
  60. package/dist/tools/index.d.ts.map +1 -0
  61. package/dist/tools/index.js +9 -0
  62. package/dist/tools/index.js.map +1 -0
  63. package/dist/tools/recall-conversation.d.ts +21 -0
  64. package/dist/tools/recall-conversation.d.ts.map +1 -0
  65. package/dist/tools/recall-conversation.js +93 -0
  66. package/dist/tools/recall-conversation.js.map +1 -0
  67. package/dist/tools/recall-memories.d.ts +29 -0
  68. package/dist/tools/recall-memories.d.ts.map +1 -0
  69. package/dist/tools/recall-memories.js +106 -0
  70. package/dist/tools/recall-memories.js.map +1 -0
  71. package/dist/tools/recall-memory-block.d.ts +21 -0
  72. package/dist/tools/recall-memory-block.d.ts.map +1 -0
  73. package/dist/tools/recall-memory-block.js +36 -0
  74. package/dist/tools/recall-memory-block.js.map +1 -0
  75. package/dist/tools/remember-facts.d.ts +30 -0
  76. package/dist/tools/remember-facts.d.ts.map +1 -0
  77. package/dist/tools/remember-facts.js +235 -0
  78. package/dist/tools/remember-facts.js.map +1 -0
  79. package/dist/tools/replace-memory-block.d.ts +25 -0
  80. package/dist/tools/replace-memory-block.d.ts.map +1 -0
  81. package/dist/tools/replace-memory-block.js +69 -0
  82. package/dist/tools/replace-memory-block.js.map +1 -0
  83. package/dist/tools/store-memory.d.ts +27 -0
  84. package/dist/tools/store-memory.d.ts.map +1 -0
  85. package/dist/tools/store-memory.js +129 -0
  86. package/dist/tools/store-memory.js.map +1 -0
  87. package/dist/types.d.ts +86 -0
  88. package/dist/types.d.ts.map +1 -0
  89. package/dist/types.js +2 -0
  90. package/dist/types.js.map +1 -0
  91. package/dist/ulid.d.ts +13 -0
  92. package/dist/ulid.d.ts.map +1 -0
  93. package/dist/ulid.js +39 -0
  94. package/dist/ulid.js.map +1 -0
  95. package/package.json +70 -0
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Server configuration — resolved from environment variables.
3
+ *
4
+ * All config comes from env vars. No config files. The server
5
+ * needs: a database path, embedding API credentials, and LLM
6
+ * API credentials.
7
+ */
8
+ import type { EmbeddingProviderConfig } from "../providers/embedding.js";
9
+ import type { LlmProviderConfig } from "../providers/llm.js";
10
+ /** Fully resolved server configuration. */
11
+ export interface ServerConfig {
12
+ readonly db: string;
13
+ readonly embedding: EmbeddingProviderConfig;
14
+ readonly llm: LlmProviderConfig;
15
+ readonly port: number;
16
+ readonly transport: "http" | "stdio";
17
+ }
18
+ /**
19
+ * Resolve server configuration from environment variables.
20
+ *
21
+ * Required:
22
+ * HIPPO_DB — SQLite database path
23
+ * HIPPO_EMBED_KEY — Embedding API key
24
+ * HIPPO_LLM_KEY — LLM API key
25
+ *
26
+ * Optional:
27
+ * HIPPO_TRANSPORT — "http" (default) or "stdio"
28
+ * HIPPO_PORT — HTTP port (default: 3100)
29
+ * HIPPO_EMBED_URL — Embedding base URL (default: https://api.openai.com/v1)
30
+ * HIPPO_EMBED_MODEL — Embedding model (default: text-embedding-3-small)
31
+ * HIPPO_EMBED_DIMENSIONS — Embedding dimensions (optional)
32
+ * HIPPO_LLM_URL — LLM base URL (default: https://openrouter.ai/api/v1)
33
+ * HIPPO_LLM_MODEL — LLM model (default: google/gemini-flash-2.0)
34
+ *
35
+ * @returns Resolved ServerConfig
36
+ */
37
+ export declare function resolveConfig(): ServerConfig;
38
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/server/config.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACzE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAE7D,2CAA2C;AAC3C,MAAM,WAAW,YAAY;IAC5B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,SAAS,EAAE,uBAAuB,CAAC;IAC5C,QAAQ,CAAC,GAAG,EAAE,iBAAiB,CAAC;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;CACrC;AA4BD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,aAAa,IAAI,YAAY,CAoB5C"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Server configuration — resolved from environment variables.
3
+ *
4
+ * All config comes from env vars. No config files. The server
5
+ * needs: a database path, embedding API credentials, and LLM
6
+ * API credentials.
7
+ */
8
+ /**
9
+ * Read a required environment variable, throwing if missing.
10
+ *
11
+ * @param key - Environment variable name
12
+ * @returns The value
13
+ * @throws Error if the variable is not set
14
+ */
15
+ function required(key) {
16
+ const value = process.env[key];
17
+ if (!value) {
18
+ throw new Error(`Missing required environment variable: ${key}`);
19
+ }
20
+ return value;
21
+ }
22
+ /**
23
+ * Read an optional environment variable with a default.
24
+ *
25
+ * @param key - Environment variable name
26
+ * @param fallback - Default value if not set
27
+ * @returns The value or default
28
+ */
29
+ function optional(key, fallback) {
30
+ return process.env[key] ?? fallback;
31
+ }
32
+ /**
33
+ * Resolve server configuration from environment variables.
34
+ *
35
+ * Required:
36
+ * HIPPO_DB — SQLite database path
37
+ * HIPPO_EMBED_KEY — Embedding API key
38
+ * HIPPO_LLM_KEY — LLM API key
39
+ *
40
+ * Optional:
41
+ * HIPPO_TRANSPORT — "http" (default) or "stdio"
42
+ * HIPPO_PORT — HTTP port (default: 3100)
43
+ * HIPPO_EMBED_URL — Embedding base URL (default: https://api.openai.com/v1)
44
+ * HIPPO_EMBED_MODEL — Embedding model (default: text-embedding-3-small)
45
+ * HIPPO_EMBED_DIMENSIONS — Embedding dimensions (optional)
46
+ * HIPPO_LLM_URL — LLM base URL (default: https://openrouter.ai/api/v1)
47
+ * HIPPO_LLM_MODEL — LLM model (default: google/gemini-flash-2.0)
48
+ *
49
+ * @returns Resolved ServerConfig
50
+ */
51
+ export function resolveConfig() {
52
+ const transport = optional("HIPPO_TRANSPORT", "http");
53
+ const dimensionsStr = process.env.HIPPO_EMBED_DIMENSIONS;
54
+ return {
55
+ db: required("HIPPO_DB"),
56
+ embedding: {
57
+ apiKey: required("HIPPO_EMBED_KEY"),
58
+ baseUrl: optional("HIPPO_EMBED_URL", "https://api.openai.com/v1"),
59
+ dimensions: dimensionsStr ? Number.parseInt(dimensionsStr, 10) : undefined,
60
+ model: optional("HIPPO_EMBED_MODEL", "text-embedding-3-small"),
61
+ },
62
+ llm: {
63
+ apiKey: required("HIPPO_LLM_KEY"),
64
+ baseUrl: optional("HIPPO_LLM_URL", "https://openrouter.ai/api/v1"),
65
+ model: optional("HIPPO_LLM_MODEL", "google/gemini-flash-2.0"),
66
+ },
67
+ port: Number.parseInt(optional("HIPPO_PORT", "3100"), 10),
68
+ transport,
69
+ };
70
+ }
71
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/server/config.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAcH;;;;;;GAMG;AACH,SAAS,QAAQ,CAAC,GAAW;IAC5B,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC/B,IAAI,CAAC,KAAK,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,0CAA0C,GAAG,EAAE,CAAC,CAAC;IAClE,CAAC;IACD,OAAO,KAAK,CAAC;AACd,CAAC;AAED;;;;;;GAMG;AACH,SAAS,QAAQ,CAAC,GAAW,EAAE,QAAgB;IAC9C,OAAO,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,QAAQ,CAAC;AACrC,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,aAAa;IAC5B,MAAM,SAAS,GAAG,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAqB,CAAC;IAC1E,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC;IAEzD,OAAO;QACN,EAAE,EAAE,QAAQ,CAAC,UAAU,CAAC;QACxB,SAAS,EAAE;YACV,MAAM,EAAE,QAAQ,CAAC,iBAAiB,CAAC;YACnC,OAAO,EAAE,QAAQ,CAAC,iBAAiB,EAAE,2BAA2B,CAAC;YACjE,UAAU,EAAE,aAAa,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS;YAC1E,KAAK,EAAE,QAAQ,CAAC,mBAAmB,EAAE,wBAAwB,CAAC;SAC9D;QACD,GAAG,EAAE;YACJ,MAAM,EAAE,QAAQ,CAAC,eAAe,CAAC;YACjC,OAAO,EAAE,QAAQ,CAAC,eAAe,EAAE,8BAA8B,CAAC;YAClE,KAAK,EAAE,QAAQ,CAAC,iBAAiB,EAAE,yBAAyB,CAAC;SAC7D;QACD,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC;QACzD,SAAS;KACT,CAAC;AACH,CAAC"}
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Hippo MCP server — exposes memory tools over MCP protocol.
4
+ *
5
+ * Supports HTTP/SSE (multi-client) and STDIO (single-client) transports.
6
+ * Embedding and LLM are configured via environment variables — consumers
7
+ * send text, hippo handles vectorization and extraction.
8
+ *
9
+ * Every tool call includes an `agent_id` parameter for multi-agent
10
+ * support on a shared database.
11
+ */
12
+ export {};
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":";AACA;;;;;;;;;GASG"}
@@ -0,0 +1,372 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Hippo MCP server — exposes memory tools over MCP protocol.
4
+ *
5
+ * Supports HTTP/SSE (multi-client) and STDIO (single-client) transports.
6
+ * Embedding and LLM are configured via environment variables — consumers
7
+ * send text, hippo handles vectorization and extraction.
8
+ *
9
+ * Every tool call includes an `agent_id` parameter for multi-agent
10
+ * support on a shared database.
11
+ */
12
+ import { createServer } from "node:http";
13
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
14
+ import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
15
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
16
+ import Database from "better-sqlite3";
17
+ import { z } from "zod";
18
+ import { prepareStatements } from "../db.js";
19
+ import { classifyConflict, extractFacts } from "../extractor.js";
20
+ import { contentHash } from "../hash.js";
21
+ import { createEmbeddingProvider } from "../providers/embedding.js";
22
+ import { createLlmProvider } from "../providers/llm.js";
23
+ import { initSchema, verifyEmbeddingModel } from "../schema.js";
24
+ import { chunkEmbedding, cosineSimilarity, embeddingToBuffer } from "../similarity.js";
25
+ import { effectiveStrength, recencyScore, retrievalBoost, STRENGTH_FLOOR, searchScore, } from "../strength.js";
26
+ import { ulid } from "../ulid.js";
27
+ import { resolveConfig } from "./config.js";
28
+ // ── Setup ────────────────────────────────────────────────────────────
29
+ const config = resolveConfig();
30
+ const db = new Database(config.db);
31
+ initSchema(db);
32
+ verifyEmbeddingModel(db, config.embedding.model);
33
+ const stmts = prepareStatements(db);
34
+ const embed = createEmbeddingProvider(config.embedding);
35
+ const llm = createLlmProvider(config.llm);
36
+ const mcp = new McpServer({
37
+ name: "hippo",
38
+ version: "0.1.0", // x-release-please-version
39
+ });
40
+ // ── Tool: remember_facts ─────────────────────────────────────────────
41
+ mcp.tool("remember_facts", "Extract and store facts from text. Handles conflict resolution: duplicates strengthen, superseding facts replace old ones.", {
42
+ agent_id: z.string().describe("Agent namespace for memory isolation"),
43
+ text: z.string().max(10_000).describe("Text containing facts to extract and remember"),
44
+ }, async ({ agent_id, text }) => {
45
+ const facts = await extractFacts(text, llm);
46
+ if (facts.length === 0) {
47
+ return { content: [{ type: "text", text: "No facts extracted." }] };
48
+ }
49
+ const results = [];
50
+ for (const { fact, intensity } of facts) {
51
+ const embedding = await embed(fact);
52
+ const embeddingBuf = embeddingToBuffer(embedding);
53
+ const now = new Date().toISOString();
54
+ // Find similar existing facts
55
+ const existing = stmts.getActiveChunksByAgent.all(agent_id, "fact", 200);
56
+ let bestSim = 0;
57
+ let bestChunk = null;
58
+ for (const chunk of existing) {
59
+ const sim = cosineSimilarity(embedding, chunkEmbedding(chunk));
60
+ if (sim > bestSim) {
61
+ bestSim = sim;
62
+ bestChunk = chunk;
63
+ }
64
+ }
65
+ if (bestSim > 0.93 && bestChunk) {
66
+ // Auto-DUPLICATE
67
+ const newIntensity = (bestChunk.running_intensity * bestChunk.encounter_count + intensity) /
68
+ (bestChunk.encounter_count + 1);
69
+ stmts.reinforceChunk.run({
70
+ id: bestChunk.id,
71
+ last_accessed_at: now,
72
+ running_intensity: newIntensity,
73
+ });
74
+ results.push(`reinforced: "${fact}"`);
75
+ }
76
+ else if (bestSim >= 0.78 && bestChunk) {
77
+ // LLM tiebreaker
78
+ const classification = await classifyConflict(fact, bestChunk.content, llm);
79
+ if (classification === "DUPLICATE") {
80
+ const newIntensity = (bestChunk.running_intensity * bestChunk.encounter_count + intensity) /
81
+ (bestChunk.encounter_count + 1);
82
+ stmts.reinforceChunk.run({
83
+ id: bestChunk.id,
84
+ last_accessed_at: now,
85
+ running_intensity: newIntensity,
86
+ });
87
+ results.push(`reinforced: "${fact}"`);
88
+ }
89
+ else if (classification === "SUPERSEDES") {
90
+ const newId = ulid();
91
+ db.transaction(() => {
92
+ stmts.insertChunk.run({
93
+ access_count: 0,
94
+ agent_id,
95
+ content: fact,
96
+ content_hash: null,
97
+ created_at: now,
98
+ embedding: embeddingBuf,
99
+ encounter_count: 1,
100
+ id: newId,
101
+ kind: "fact",
102
+ last_accessed_at: now,
103
+ metadata: null,
104
+ running_intensity: intensity,
105
+ superseded_by: null,
106
+ });
107
+ stmts.supersedeChunk.run(newId, bestChunk.id);
108
+ })();
109
+ results.push(`superseded: "${fact}" (replaced "${bestChunk.content}")`);
110
+ }
111
+ else {
112
+ // DISTINCT
113
+ stmts.insertChunk.run({
114
+ access_count: 0,
115
+ agent_id,
116
+ content: fact,
117
+ content_hash: null,
118
+ created_at: now,
119
+ embedding: embeddingBuf,
120
+ encounter_count: 1,
121
+ id: ulid(),
122
+ kind: "fact",
123
+ last_accessed_at: now,
124
+ metadata: null,
125
+ running_intensity: intensity,
126
+ superseded_by: null,
127
+ });
128
+ results.push(`new: "${fact}"`);
129
+ }
130
+ }
131
+ else {
132
+ // NEW
133
+ stmts.insertChunk.run({
134
+ access_count: 0,
135
+ agent_id,
136
+ content: fact,
137
+ content_hash: null,
138
+ created_at: now,
139
+ embedding: embeddingBuf,
140
+ encounter_count: 1,
141
+ id: ulid(),
142
+ kind: "fact",
143
+ last_accessed_at: now,
144
+ metadata: null,
145
+ running_intensity: intensity,
146
+ superseded_by: null,
147
+ });
148
+ results.push(`new: "${fact}"`);
149
+ }
150
+ }
151
+ return { content: [{ type: "text", text: results.join("\n") }] };
152
+ });
153
+ // ── Tool: store_memory ───────────────────────────────────────────────
154
+ mcp.tool("store_memory", "Store raw content as a memory chunk. Deduplicates by content hash — storing the same text twice strengthens the existing memory instead of creating a duplicate.", {
155
+ agent_id: z.string().describe("Agent namespace for memory isolation"),
156
+ content: z.string().max(50_000).describe("Content to store as a memory"),
157
+ metadata: z.string().optional().describe("Optional JSON metadata"),
158
+ }, async ({ agent_id, content, metadata }) => {
159
+ const hash = contentHash(content);
160
+ const now = new Date().toISOString();
161
+ // Check for duplicate
162
+ const existing = stmts.getMemoryByHash.get(agent_id, hash);
163
+ if (existing) {
164
+ const boosted = retrievalBoost(existing.running_intensity);
165
+ stmts.reinforceChunk.run({
166
+ id: existing.id,
167
+ last_accessed_at: now,
168
+ running_intensity: boosted,
169
+ });
170
+ return {
171
+ content: [{ type: "text", text: `Memory already exists (strengthened): ${existing.id}` }],
172
+ };
173
+ }
174
+ const embedding = await embed(content);
175
+ const id = ulid();
176
+ stmts.insertChunk.run({
177
+ access_count: 0,
178
+ agent_id,
179
+ content,
180
+ content_hash: hash,
181
+ created_at: now,
182
+ embedding: embeddingToBuffer(embedding),
183
+ encounter_count: 1,
184
+ id,
185
+ kind: "memory",
186
+ last_accessed_at: now,
187
+ metadata: metadata ?? null,
188
+ running_intensity: 0.5,
189
+ superseded_by: null,
190
+ });
191
+ return { content: [{ type: "text", text: `Stored memory: ${id}` }] };
192
+ });
193
+ // ── Tool: recall_memories ────────────────────────────────────────────
194
+ mcp.tool("recall_memories", "Semantic search over stored facts and memories. Returns results ranked by relevance, strength, and recency.", {
195
+ agent_id: z.string().describe("Agent namespace for memory isolation"),
196
+ limit: z.number().min(1).max(50).default(10).describe("Max results to return"),
197
+ query: z.string().describe("What to search for in memory"),
198
+ }, async ({ agent_id, limit, query }) => {
199
+ const queryEmbedding = await embed(query);
200
+ const now = new Date();
201
+ const allChunks = stmts.getAllActiveChunksByAgent.all(agent_id, 10_000);
202
+ const scored = [];
203
+ for (const chunk of allChunks) {
204
+ const similarity = cosineSimilarity(queryEmbedding, chunkEmbedding(chunk));
205
+ if (similarity < 0.1)
206
+ continue;
207
+ const hoursSince = (now.getTime() - new Date(chunk.last_accessed_at).getTime()) / (1000 * 60 * 60);
208
+ const strength = effectiveStrength(chunk.running_intensity, chunk.access_count, hoursSince);
209
+ if (strength < STRENGTH_FLOOR)
210
+ continue;
211
+ const daysSince = (now.getTime() - new Date(chunk.created_at).getTime()) / (1000 * 60 * 60 * 24);
212
+ const recency = recencyScore(daysSince);
213
+ scored.push({ chunk, score: searchScore(similarity, strength, recency) });
214
+ }
215
+ scored.sort((a, b) => b.score - a.score);
216
+ const top = scored.slice(0, limit);
217
+ // Retrieval boost
218
+ for (const { chunk } of top) {
219
+ try {
220
+ stmts.touchChunk.run({
221
+ id: chunk.id,
222
+ last_accessed_at: now.toISOString(),
223
+ running_intensity: retrievalBoost(chunk.running_intensity),
224
+ });
225
+ }
226
+ catch {
227
+ // Non-fatal
228
+ }
229
+ }
230
+ if (top.length === 0) {
231
+ return { content: [{ type: "text", text: "No memories found." }] };
232
+ }
233
+ const lines = top.map((r, i) => `${i + 1}. [${r.chunk.kind}] (score: ${r.score.toFixed(3)}) ${r.chunk.content}`);
234
+ return { content: [{ type: "text", text: lines.join("\n") }] };
235
+ });
236
+ // ── Tool: forget_memory ──────────────────────────────────────────────
237
+ mcp.tool("forget_memory", "Forget memories matching a description. Embeds the description, finds semantically similar chunks, and hard-deletes them.", {
238
+ agent_id: z.string().describe("Agent namespace for memory isolation"),
239
+ description: z.string().describe("Description of what to forget"),
240
+ threshold: z.number().min(0).max(1).default(0.7).describe("Minimum similarity to delete"),
241
+ }, async ({ agent_id, description, threshold }) => {
242
+ const queryEmbedding = await embed(description);
243
+ const allChunks = stmts.getAllActiveChunksByAgent.all(agent_id, 10_000);
244
+ const toDelete = [];
245
+ for (const chunk of allChunks) {
246
+ const sim = cosineSimilarity(queryEmbedding, chunkEmbedding(chunk));
247
+ if (sim >= threshold) {
248
+ toDelete.push(chunk);
249
+ }
250
+ }
251
+ if (toDelete.length === 0) {
252
+ return { content: [{ type: "text", text: "No matching memories found to forget." }] };
253
+ }
254
+ db.transaction(() => {
255
+ for (const chunk of toDelete) {
256
+ stmts.clearSupersededBy.run(chunk.id, agent_id);
257
+ stmts.deleteChunk.run(chunk.id);
258
+ }
259
+ })();
260
+ const lines = toDelete.map((c) => `- [${c.kind}] ${c.content}`);
261
+ return {
262
+ content: [
263
+ { type: "text", text: `Forgot ${toDelete.length} memory(s):\n${lines.join("\n")}` },
264
+ ],
265
+ };
266
+ });
267
+ // ── Tool: recall_memory_block ────────────────────────────────────────
268
+ mcp.tool("recall_memory_block", "Read the contents of a named memory block (key-value text buffer like persona, objectives, etc.).", {
269
+ agent_id: z.string().describe("Agent namespace"),
270
+ key: z.string().describe("Block key (e.g. persona, objectives)"),
271
+ }, async ({ agent_id, key }) => {
272
+ const row = stmts.getBlockByKey.get(agent_id, key);
273
+ if (!row) {
274
+ return { content: [{ type: "text", text: `Block "${key}" not found.` }] };
275
+ }
276
+ return { content: [{ type: "text", text: row.value }] };
277
+ });
278
+ // ── Tool: replace_memory_block ───────────────────────────────────────
279
+ mcp.tool("replace_memory_block", "Find and replace text within a named memory block. Returns error if block doesn't exist or text not found.", {
280
+ agent_id: z.string().describe("Agent namespace"),
281
+ key: z.string().describe("Block key"),
282
+ new_text: z.string().describe("Replacement text"),
283
+ old_text: z.string().min(1).describe("Text to find"),
284
+ }, async ({ agent_id, key, new_text, old_text }) => {
285
+ const row = stmts.getBlockByKey.get(agent_id, key);
286
+ if (!row) {
287
+ return {
288
+ content: [{ type: "text", text: `Block "${key}" not found.` }],
289
+ isError: true,
290
+ };
291
+ }
292
+ if (!row.value.includes(old_text)) {
293
+ return {
294
+ content: [{ type: "text", text: `Text not found in block "${key}".` }],
295
+ isError: true,
296
+ };
297
+ }
298
+ const updated = row.value.replace(old_text, new_text);
299
+ stmts.upsertBlock.run({ agent_id, key, updated_at: new Date().toISOString(), value: updated });
300
+ return { content: [{ type: "text", text: `Updated block "${key}".` }] };
301
+ });
302
+ // ── Tool: append_memory_block ────────────────────────────────────────
303
+ mcp.tool("append_memory_block", "Append text to a named memory block. Creates the block if it doesn't exist.", {
304
+ agent_id: z.string().describe("Agent namespace"),
305
+ content: z.string().describe("Text to append"),
306
+ key: z.string().describe("Block key"),
307
+ }, async ({ agent_id, content, key }) => {
308
+ const row = stmts.getBlockByKey.get(agent_id, key);
309
+ const newValue = row ? row.value + content : content;
310
+ stmts.upsertBlock.run({
311
+ agent_id,
312
+ key,
313
+ updated_at: new Date().toISOString(),
314
+ value: newValue,
315
+ });
316
+ const sizeBytes = new TextEncoder().encode(newValue).byteLength;
317
+ let msg = `Appended to block "${key}" (${sizeBytes} bytes).`;
318
+ if (sizeBytes > 100_000) {
319
+ msg += " Warning: block exceeds 100KB.";
320
+ }
321
+ return { content: [{ type: "text", text: msg }] };
322
+ });
323
+ // ── Transport ────────────────────────────────────────────────────────
324
+ if (config.transport === "stdio") {
325
+ const transport = new StdioServerTransport();
326
+ await mcp.connect(transport);
327
+ console.error("Hippo MCP server running on stdio");
328
+ }
329
+ else {
330
+ const transports = new Map();
331
+ const httpServer = createServer(async (req, res) => {
332
+ const url = new URL(req.url ?? "/", `http://${req.headers.host}`);
333
+ // Health check
334
+ if (url.pathname === "/health") {
335
+ res.writeHead(200, { "Content-Type": "application/json" });
336
+ res.end(JSON.stringify({ status: "ok" }));
337
+ return;
338
+ }
339
+ // SSE endpoint — new connections
340
+ if (url.pathname === "/sse" && req.method === "GET") {
341
+ const transport = new SSEServerTransport("/messages", res);
342
+ transports.set(transport.sessionId, transport);
343
+ transport.onclose = () => {
344
+ transports.delete(transport.sessionId);
345
+ };
346
+ await mcp.connect(transport);
347
+ return;
348
+ }
349
+ // Message endpoint — client POSTs to this
350
+ if (url.pathname === "/messages" && req.method === "POST") {
351
+ const sessionId = url.searchParams.get("sessionId");
352
+ if (!sessionId || !transports.has(sessionId)) {
353
+ res.writeHead(400, { "Content-Type": "application/json" });
354
+ res.end(JSON.stringify({ error: "Invalid or missing sessionId" }));
355
+ return;
356
+ }
357
+ // biome-ignore lint/style/noNonNullAssertion: checked in the guard above
358
+ const transport = transports.get(sessionId);
359
+ await transport.handlePostMessage(req, res);
360
+ return;
361
+ }
362
+ res.writeHead(404);
363
+ res.end("Not found");
364
+ });
365
+ httpServer.listen(config.port, () => {
366
+ console.error(`Hippo MCP server listening on http://localhost:${config.port}`);
367
+ console.error(` SSE endpoint: GET /sse`);
368
+ console.error(` Messages: POST /messages?sessionId=<id>`);
369
+ console.error(` Health: GET /health`);
370
+ });
371
+ }
372
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Compute cosine similarity between two Float32Array embeddings.
3
+ *
4
+ * @param a - First embedding vector
5
+ * @param b - Second embedding vector
6
+ * @returns Cosine similarity in range [-1, 1]
7
+ * @throws If vectors have different lengths or are zero-length
8
+ */
9
+ export declare function cosineSimilarity(a: Float32Array, b: Float32Array): number;
10
+ /**
11
+ * Deserialize embedding BLOB from SQLite into Float32Array.
12
+ *
13
+ * Copies through Uint8Array to guarantee 4-byte alignment.
14
+ * better-sqlite3 typically returns offset-0 Buffers, but the spec
15
+ * doesn't guarantee it and Float32Array requires aligned access.
16
+ *
17
+ * @param buf - Buffer containing raw float32 bytes
18
+ * @returns Float32Array embedding
19
+ */
20
+ export declare function bufferToEmbedding(buf: Buffer): Float32Array;
21
+ /**
22
+ * Serialize Float32Array to Buffer for SQLite BLOB storage.
23
+ *
24
+ * Creates a copy so the returned Buffer is independent of the source array.
25
+ *
26
+ * @param embedding - Float32Array embedding
27
+ * @returns Buffer for BLOB column
28
+ */
29
+ export declare function embeddingToBuffer(embedding: Float32Array): Buffer;
30
+ /**
31
+ * Extract and deserialize a chunk's embedding BLOB into Float32Array.
32
+ *
33
+ * Centralizes the Buffer cast from better-sqlite3's runtime type.
34
+ *
35
+ * @param chunk - A chunk row from SQLite
36
+ * @returns Float32Array embedding
37
+ */
38
+ export declare function chunkEmbedding(chunk: {
39
+ readonly embedding: Buffer;
40
+ }): Float32Array;
41
+ //# sourceMappingURL=similarity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"similarity.d.ts","sourceRoot":"","sources":["../src/similarity.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,YAAY,GAAG,MAAM,CA4BzE;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,CAK3D;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,YAAY,GAAG,MAAM,CAEjE;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE;IAAE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAAG,YAAY,CAElF"}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Compute cosine similarity between two Float32Array embeddings.
3
+ *
4
+ * @param a - First embedding vector
5
+ * @param b - Second embedding vector
6
+ * @returns Cosine similarity in range [-1, 1]
7
+ * @throws If vectors have different lengths or are zero-length
8
+ */
9
+ export function cosineSimilarity(a, b) {
10
+ if (a.length !== b.length) {
11
+ throw new Error(`Vector length mismatch: ${a.length} vs ${b.length}`);
12
+ }
13
+ if (a.length === 0) {
14
+ throw new Error("Cannot compute cosine similarity of zero-length vectors");
15
+ }
16
+ let dot = 0;
17
+ let normA = 0;
18
+ let normB = 0;
19
+ for (let i = 0; i < a.length; i++) {
20
+ // biome-ignore lint/style/noNonNullAssertion: loop bounded by length
21
+ const ai = a[i];
22
+ // biome-ignore lint/style/noNonNullAssertion: loop bounded by length
23
+ const bi = b[i];
24
+ dot += ai * bi;
25
+ normA += ai * ai;
26
+ normB += bi * bi;
27
+ }
28
+ const denom = Math.sqrt(normA) * Math.sqrt(normB);
29
+ if (denom === 0) {
30
+ return 0;
31
+ }
32
+ return dot / denom;
33
+ }
34
+ /**
35
+ * Deserialize embedding BLOB from SQLite into Float32Array.
36
+ *
37
+ * Copies through Uint8Array to guarantee 4-byte alignment.
38
+ * better-sqlite3 typically returns offset-0 Buffers, but the spec
39
+ * doesn't guarantee it and Float32Array requires aligned access.
40
+ *
41
+ * @param buf - Buffer containing raw float32 bytes
42
+ * @returns Float32Array embedding
43
+ */
44
+ export function bufferToEmbedding(buf) {
45
+ const bytes = new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);
46
+ return new Float32Array(bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength));
47
+ }
48
+ /**
49
+ * Serialize Float32Array to Buffer for SQLite BLOB storage.
50
+ *
51
+ * Creates a copy so the returned Buffer is independent of the source array.
52
+ *
53
+ * @param embedding - Float32Array embedding
54
+ * @returns Buffer for BLOB column
55
+ */
56
+ export function embeddingToBuffer(embedding) {
57
+ return Buffer.copyBytesFrom(embedding);
58
+ }
59
+ /**
60
+ * Extract and deserialize a chunk's embedding BLOB into Float32Array.
61
+ *
62
+ * Centralizes the Buffer cast from better-sqlite3's runtime type.
63
+ *
64
+ * @param chunk - A chunk row from SQLite
65
+ * @returns Float32Array embedding
66
+ */
67
+ export function chunkEmbedding(chunk) {
68
+ return bufferToEmbedding(chunk.embedding);
69
+ }
70
+ //# sourceMappingURL=similarity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"similarity.js","sourceRoot":"","sources":["../src/similarity.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,UAAU,gBAAgB,CAAC,CAAe,EAAE,CAAe;IAChE,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC,MAAM,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;IACvE,CAAC;IACD,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC,CAAC;IAC5E,CAAC;IAED,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,KAAK,GAAG,CAAC,CAAC;IAEd,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACnC,qEAAqE;QACrE,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,CAAE,CAAC;QACjB,qEAAqE;QACrE,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,CAAE,CAAC;QACjB,GAAG,IAAI,EAAE,GAAG,EAAE,CAAC;QACf,KAAK,IAAI,EAAE,GAAG,EAAE,CAAC;QACjB,KAAK,IAAI,EAAE,GAAG,EAAE,CAAC;IAClB,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClD,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;QACjB,OAAO,CAAC,CAAC;IACV,CAAC;IAED,OAAO,GAAG,GAAG,KAAK,CAAC;AACpB,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAW;IAC5C,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,UAAU,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC;IACzE,OAAO,IAAI,YAAY,CACtB,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,UAAU,GAAG,KAAK,CAAC,UAAU,CAAC,CACzE,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB,CAAC,SAAuB;IACxD,OAAO,MAAM,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;AACxC,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAAC,KAAqC;IACnE,OAAO,iBAAiB,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;AAC3C,CAAC"}