@levalicious/server-memory 0.0.18 → 0.0.20

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/server.js CHANGED
@@ -101,7 +101,7 @@ function sortNeighbors(neighbors, sortBy = "llmrank", sortDir, rankMaps) {
101
101
  return mult * (aVal - bVal);
102
102
  });
103
103
  }
104
- export const MAX_CHARS = 16384;
104
+ export const MAX_CHARS = 4096;
105
105
  function paginateItems(items, cursor = 0, maxChars = MAX_CHARS) {
106
106
  const result = [];
107
107
  let i = cursor;
@@ -953,7 +953,7 @@ export function createServer(memoryFilePath) {
953
953
  sizes: ["any"]
954
954
  }
955
955
  ],
956
- version: "0.0.18",
956
+ version: "0.0.20",
957
957
  }, {
958
958
  capabilities: {
959
959
  tools: {},
@@ -1105,7 +1105,7 @@ export function createServer(memoryFilePath) {
1105
1105
  },
1106
1106
  {
1107
1107
  name: "search_nodes",
1108
- description: "Search for nodes in the knowledge graph using a regex pattern. Results are paginated (max 512 chars).",
1108
+ description: "Search for nodes in the knowledge graph using a regex pattern. Results are paginated (max 4096 chars).",
1109
1109
  inputSchema: {
1110
1110
  type: "object",
1111
1111
  properties: {
@@ -1121,7 +1121,7 @@ export function createServer(memoryFilePath) {
1121
1121
  },
1122
1122
  {
1123
1123
  name: "open_nodes",
1124
- description: "Open specific nodes in the knowledge graph by their names. Results are paginated (max 512 chars).",
1124
+ description: "Open specific nodes in the knowledge graph by their names. Results are paginated (max 4096 chars).",
1125
1125
  inputSchema: {
1126
1126
  type: "object",
1127
1127
  properties: {
@@ -1139,7 +1139,7 @@ export function createServer(memoryFilePath) {
1139
1139
  },
1140
1140
  {
1141
1141
  name: "get_neighbors",
1142
- description: "Get names of neighboring entities connected to a specific entity within a given depth. Returns neighbor names with timestamps for sorting. Use open_nodes to get full entity data. Results are paginated (max 512 chars).",
1142
+ description: "Get names of neighboring entities connected to a specific entity within a given depth. Returns neighbor names with timestamps for sorting. Use open_nodes to get full entity data. Results are paginated (max 4096 chars).",
1143
1143
  inputSchema: {
1144
1144
  type: "object",
1145
1145
  properties: {
@@ -1155,7 +1155,7 @@ export function createServer(memoryFilePath) {
1155
1155
  },
1156
1156
  {
1157
1157
  name: "find_path",
1158
- description: "Find a path between two entities in the knowledge graph. Results are paginated (max 512 chars).",
1158
+ description: "Find a path between two entities in the knowledge graph. Results are paginated (max 4096 chars).",
1159
1159
  inputSchema: {
1160
1160
  type: "object",
1161
1161
  properties: {
@@ -1170,7 +1170,7 @@ export function createServer(memoryFilePath) {
1170
1170
  },
1171
1171
  {
1172
1172
  name: "get_entities_by_type",
1173
- description: "Get all entities of a specific type. Results are paginated (max 512 chars).",
1173
+ description: "Get all entities of a specific type. Results are paginated (max 4096 chars).",
1174
1174
  inputSchema: {
1175
1175
  type: "object",
1176
1176
  properties: {
@@ -1208,7 +1208,7 @@ export function createServer(memoryFilePath) {
1208
1208
  },
1209
1209
  {
1210
1210
  name: "get_orphaned_entities",
1211
- description: "Get entities that have no relations (orphaned entities). In strict mode, returns entities not connected to 'Self' entity. Results are paginated (max 512 chars).",
1211
+ description: "Get entities that have no relations (orphaned entities). In strict mode, returns entities not connected to 'Self' entity. Results are paginated (max 4096 chars).",
1212
1212
  inputSchema: {
1213
1213
  type: "object",
1214
1214
  properties: {
@@ -350,6 +350,9 @@ export function loadDocument(text, title, st, topK = 15) {
350
350
  observations: [idx.phrase],
351
351
  });
352
352
  }
353
+ // Index hub — empty structural node linking Document to index entries
354
+ const indexHubId = `${title}__index`;
355
+ entities.push({ name: indexHubId, entityType: 'DocumentIndex', observations: [] });
353
356
  // ─── Assemble relations ─────────────────────────────────────────
354
357
  // Document → chain endpoints
355
358
  if (chunks.length > 0) {
@@ -365,12 +368,15 @@ export function loadDocument(text, title, st, topK = 15) {
365
368
  relations.push({ from: chunks[i].id, to: chunks[i + 1].id, relationType: 'follows' });
366
369
  relations.push({ from: chunks[i + 1].id, to: chunks[i].id, relationType: 'preceded_by' });
367
370
  }
368
- // Document → index entries
371
+ // Document → index hub
372
+ relations.push({ from: title, to: indexHubId, relationType: 'has_index' });
373
+ relations.push({ from: indexHubId, to: title, relationType: 'indexes' });
374
+ // Index hub → index entries
369
375
  for (const idx of indexEntities) {
370
- relations.push({ from: title, to: idx.id, relationType: 'has_index' });
371
- relations.push({ from: idx.id, to: title, relationType: 'indexes' });
376
+ relations.push({ from: indexHubId, to: idx.id, relationType: 'contains' });
377
+ relations.push({ from: idx.id, to: indexHubId, relationType: 'contained_in' });
372
378
  }
373
- // Index → highlighted chunks
379
+ // Index entries → highlighted chunks
374
380
  for (const idx of indexEntities) {
375
381
  relations.push({ from: idx.id, to: idx.chunk.id, relationType: 'highlights' });
376
382
  relations.push({ from: idx.chunk.id, to: idx.id, relationType: 'highlighted_by' });
@@ -1068,13 +1068,16 @@ describe('MCP Memory Server E2E Tests', () => {
1068
1068
  const docResult = await callTool(client, 'open_nodes', { names: ['test-doc'] });
1069
1069
  expect(docResult.entities.items).toHaveLength(1);
1070
1070
  expect(docResult.entities.items[0].entityType).toBe('Document');
1071
- // Check index entities (one per key phrase)
1071
+ // Check index entities one hub (0 observations) + entries (1 observation each)
1072
1072
  const indexEntities = await callTool(client, 'get_entities_by_type', { entityType: 'DocumentIndex' });
1073
- expect(indexEntities.items.length).toBeGreaterThan(0);
1074
- for (const idx of indexEntities.items) {
1075
- expect(idx.entityType).toBe('DocumentIndex');
1076
- expect(idx.observations.length).toBe(1);
1077
- expect(idx.observations[0].length).toBeLessThanOrEqual(140);
1073
+ expect(indexEntities.items.length).toBeGreaterThan(1);
1074
+ const hub = indexEntities.items.filter(e => e.observations.length === 0);
1075
+ const entries = indexEntities.items.filter(e => e.observations.length > 0);
1076
+ expect(hub).toHaveLength(1);
1077
+ expect(entries.length).toBeGreaterThan(0);
1078
+ for (const entry of entries) {
1079
+ expect(entry.observations.length).toBe(1);
1080
+ expect(entry.observations[0].length).toBeLessThanOrEqual(140);
1078
1081
  }
1079
1082
  // Check TextChunk entities exist via type query
1080
1083
  const chunks = await callTool(client, 'get_entities_by_type', { entityType: 'TextChunk' });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@levalicious/server-memory",
3
- "version": "0.0.18",
3
+ "version": "0.0.20",
4
4
  "description": "MCP server for enabling memory for Claude through a knowledge graph",
5
5
  "license": "MIT",
6
6
  "author": "Levalicious",