@danielsimonjr/memory-mcp 11.1.1 → 12.2.3

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.
@@ -2,7 +2,7 @@
2
2
  * MCP Tool Definitions
3
3
  *
4
4
  * Extracted from MCPServer.ts to reduce file size and improve maintainability.
5
- * Contains all 59 tool schemas for the Knowledge Graph MCP Server.
5
+ * Contains all 106 tool schemas for the Knowledge Graph MCP Server.
6
6
  *
7
7
  * @module server/toolDefinitions
8
8
  */
@@ -14,7 +14,7 @@ export const toolDefinitions = [
14
14
  // ==================== ENTITY TOOLS ====================
15
15
  {
16
16
  name: 'create_entities',
17
- description: 'Create multiple new entities in the knowledge graph',
17
+ description: 'Create multiple new entities in the knowledge graph. Supports v1.6 freshness (ttl/confidence), v1.8 project scoping, and η.4.4 bitemporal validity (validFrom/validUntil/observationMeta).',
18
18
  inputSchema: {
19
19
  type: 'object',
20
20
  properties: {
@@ -30,6 +30,58 @@ export const toolDefinitions = [
30
30
  items: { type: 'string' },
31
31
  description: 'An array of observation contents associated with the entity',
32
32
  },
33
+ tags: {
34
+ type: 'array',
35
+ items: { type: 'string' },
36
+ description: 'Optional lowercase tags for categorization',
37
+ },
38
+ importance: {
39
+ type: 'number',
40
+ minimum: 0,
41
+ maximum: 10,
42
+ description: 'Optional importance score (0-10) for prioritization',
43
+ },
44
+ parentId: {
45
+ type: 'string',
46
+ description: 'Optional parent entity name for hierarchical nesting',
47
+ },
48
+ ttl: {
49
+ type: 'number',
50
+ description: 'v1.6 freshness — seconds until entity is considered stale',
51
+ },
52
+ confidence: {
53
+ type: 'number',
54
+ minimum: 0,
55
+ maximum: 1,
56
+ description: 'v1.6 freshness — belief strength [0, 1]',
57
+ },
58
+ projectId: {
59
+ type: 'string',
60
+ description: 'v1.8 project scope identifier',
61
+ },
62
+ validFrom: {
63
+ type: 'string',
64
+ description: 'η.4.4 ISO 8601 — entity is valid from this instant. Absent ⇒ always valid since creation.',
65
+ },
66
+ validUntil: {
67
+ type: 'string',
68
+ description: 'η.4.4 ISO 8601 — entity is valid until this instant. Absent ⇒ still valid.',
69
+ },
70
+ observationMeta: {
71
+ type: 'array',
72
+ description: 'η.4.4 per-observation temporal metadata; indexed parallel to observations[] by content match',
73
+ items: {
74
+ type: 'object',
75
+ properties: {
76
+ content: { type: 'string', description: 'Matches an entry in observations[] by exact content' },
77
+ validFrom: { type: 'string' },
78
+ validUntil: { type: 'string' },
79
+ recordedAt: { type: 'string', description: 'Bitemporal axis — when the fact was recorded' },
80
+ },
81
+ required: ['content'],
82
+ additionalProperties: false,
83
+ },
84
+ },
33
85
  },
34
86
  required: ['name', 'entityType', 'observations'],
35
87
  additionalProperties: false,
@@ -81,6 +133,41 @@ export const toolDefinitions = [
81
133
  additionalProperties: false,
82
134
  },
83
135
  },
136
+ // Phase 13: Project scoping + memory versioning tools
137
+ {
138
+ name: 'list_projects',
139
+ description: 'List all distinct project IDs in the knowledge graph. Returns sorted array of projectId values, excluding global/unscoped entities.',
140
+ inputSchema: {
141
+ type: 'object',
142
+ properties: {},
143
+ required: [],
144
+ additionalProperties: false,
145
+ },
146
+ },
147
+ {
148
+ name: 'get_entity_versions',
149
+ description: 'Get the latest version of an entity. If the entity has been superseded by newer versions (via contradiction detection), returns the most recent one.',
150
+ inputSchema: {
151
+ type: 'object',
152
+ properties: {
153
+ entityName: { type: 'string', description: 'Name of any entity in the version chain' },
154
+ },
155
+ required: ['entityName'],
156
+ additionalProperties: false,
157
+ },
158
+ },
159
+ {
160
+ name: 'get_version_chain',
161
+ description: 'Get all versions of an entity in its version chain. Returns versions sorted by version number ascending. Works from any entity in the chain (resolves to root automatically).',
162
+ inputSchema: {
163
+ type: 'object',
164
+ properties: {
165
+ entityName: { type: 'string', description: 'Name of any entity in the version chain' },
166
+ },
167
+ required: ['entityName'],
168
+ additionalProperties: false,
169
+ },
170
+ },
84
171
  // ==================== RELATION TOOLS ====================
85
172
  {
86
173
  name: 'create_relations',
@@ -133,6 +220,49 @@ export const toolDefinitions = [
133
220
  additionalProperties: false,
134
221
  },
135
222
  },
223
+ // Phase 13: Temporal knowledge graph tools
224
+ {
225
+ name: 'invalidate_relation',
226
+ description: 'Mark a relation as no longer valid. Sets the validUntil timestamp on the matching active relation. Use for temporal facts that have ended (e.g., "Kai no longer works on Orion").',
227
+ inputSchema: {
228
+ type: 'object',
229
+ properties: {
230
+ from: { type: 'string', description: 'Source entity name' },
231
+ relationType: { type: 'string', description: 'Relation type (e.g., works_on, assigned_to)' },
232
+ to: { type: 'string', description: 'Target entity name' },
233
+ ended: { type: 'string', description: 'ISO 8601 date when the relation ended. Defaults to now.' },
234
+ },
235
+ required: ['from', 'relationType', 'to'],
236
+ additionalProperties: false,
237
+ },
238
+ },
239
+ {
240
+ name: 'query_as_of',
241
+ description: 'Query relations valid at a specific point in time. Returns only relations where validFrom <= date AND (validUntil is undefined OR validUntil >= date). Time-travel query for temporal knowledge graphs.',
242
+ inputSchema: {
243
+ type: 'object',
244
+ properties: {
245
+ entityName: { type: 'string', description: 'Entity to query relations for' },
246
+ asOf: { type: 'string', description: 'ISO 8601 date to query at (e.g., "2026-01-15")' },
247
+ direction: { type: 'string', enum: ['outgoing', 'incoming', 'both'], description: 'Relation direction filter. Default: both.' },
248
+ },
249
+ required: ['entityName', 'asOf'],
250
+ additionalProperties: false,
251
+ },
252
+ },
253
+ {
254
+ name: 'timeline',
255
+ description: 'Get chronological relation history for an entity. Returns ALL relations (current and expired) sorted by validFrom ascending. Shows the full story of an entity over time.',
256
+ inputSchema: {
257
+ type: 'object',
258
+ properties: {
259
+ entityName: { type: 'string', description: 'Entity to get timeline for' },
260
+ direction: { type: 'string', enum: ['outgoing', 'incoming', 'both'], description: 'Relation direction filter. Default: both.' },
261
+ },
262
+ required: ['entityName'],
263
+ additionalProperties: false,
264
+ },
265
+ },
136
266
  // ==================== OBSERVATION TOOLS ====================
137
267
  {
138
268
  name: 'add_observations',
@@ -327,6 +457,22 @@ export const toolDefinitions = [
327
457
  additionalProperties: false,
328
458
  },
329
459
  },
460
+ // Phase 13: Semantic forget
461
+ {
462
+ name: 'forget_memory',
463
+ description: 'Forget (delete) observations matching the given content. Tries exact match first; falls back to semantic search at 0.85 similarity threshold if available. Supports dryRun to preview what would be deleted.',
464
+ inputSchema: {
465
+ type: 'object',
466
+ properties: {
467
+ content: { type: 'string', description: 'The content to forget (observation text)' },
468
+ threshold: { type: 'number', description: 'Semantic similarity threshold for fallback (default: 0.85)' },
469
+ projectId: { type: 'string', description: 'Optional project scope filter' },
470
+ dryRun: { type: 'boolean', description: 'If true, return what would be deleted without actually deleting' },
471
+ },
472
+ required: ['content'],
473
+ additionalProperties: false,
474
+ },
475
+ },
330
476
  // Phase 11 Sprint 2: Hybrid Search
331
477
  {
332
478
  name: 'hybrid_search',
@@ -454,7 +600,6 @@ export const toolDefinitions = [
454
600
  tags: { type: 'array', items: { type: 'string' }, description: 'Optional tags filter' },
455
601
  minImportance: { type: 'number', description: 'Optional minimum importance' },
456
602
  maxImportance: { type: 'number', description: 'Optional maximum importance' },
457
- searchType: { type: 'string', description: 'Type of search (basic, boolean, fuzzy, ranked)' },
458
603
  description: { type: 'string', description: 'Optional description of the search' },
459
604
  },
460
605
  required: ['name', 'query'],
@@ -936,14 +1081,19 @@ export const toolDefinitions = [
936
1081
  },
937
1082
  {
938
1083
  name: 'export_graph',
939
- description: 'Export knowledge graph in various formats with optional brotli compression and streaming for large graphs',
1084
+ description: 'Export knowledge graph in various formats with optional brotli compression and streaming for large graphs. Supports W3C Linked Data formats (turtle, rdf-xml, json-ld) added in η.5.4.',
940
1085
  inputSchema: {
941
1086
  type: 'object',
942
1087
  properties: {
943
1088
  format: {
944
1089
  type: 'string',
945
- enum: ['json', 'csv', 'graphml', 'gexf', 'dot', 'markdown', 'mermaid'],
946
- description: 'Export format',
1090
+ enum: ['json', 'csv', 'graphml', 'gexf', 'dot', 'markdown', 'mermaid', 'turtle', 'rdf-xml', 'json-ld'],
1091
+ description: 'Export format. W3C Linked Data: turtle (RDF 1.1 Turtle), rdf-xml (RDF 1.1 XML with Statement reification for non-NCName predicates), json-ld (JSON-LD 1.1 with @context mapping to RDFS + DCTerms).',
1092
+ },
1093
+ redactPii: {
1094
+ type: 'boolean',
1095
+ default: false,
1096
+ description: 'When true, scrub PII (email/SSN/credit-card/phone/IPv4) from observations before export. Uses η.6.3 PiiRedactor with default pattern bank.',
947
1097
  },
948
1098
  filter: {
949
1099
  type: 'object',
@@ -981,6 +1131,36 @@ export const toolDefinitions = [
981
1131
  additionalProperties: false,
982
1132
  },
983
1133
  },
1134
+ // Phase 13: Conversation ingestion tool
1135
+ {
1136
+ name: 'ingest',
1137
+ description: 'Ingest pre-normalized conversation data into the knowledge graph. Chunks messages by exchange pairs (user+assistant), creates entities with verbatim observations. Format-agnostic: normalize chat exports before calling.',
1138
+ inputSchema: {
1139
+ type: 'object',
1140
+ properties: {
1141
+ messages: {
1142
+ type: 'array',
1143
+ items: {
1144
+ type: 'object',
1145
+ properties: {
1146
+ role: { type: 'string', enum: ['user', 'assistant', 'system'] },
1147
+ content: { type: 'string' },
1148
+ timestamp: { type: 'string', description: 'Optional ISO 8601 timestamp' },
1149
+ },
1150
+ required: ['role', 'content'],
1151
+ },
1152
+ description: 'Array of conversation messages to ingest',
1153
+ },
1154
+ source: { type: 'string', description: 'Source identifier (e.g., filename, session ID)' },
1155
+ projectId: { type: 'string', description: 'Project to scope ingested entities to' },
1156
+ tags: { type: 'array', items: { type: 'string' }, description: 'Tags to apply to all created entities' },
1157
+ chunkBy: { type: 'string', enum: ['exchange', 'paragraph', 'fixed'], description: 'Chunking strategy. Default: exchange (user+assistant pairs).' },
1158
+ dryRun: { type: 'boolean', description: 'Preview without creating entities' },
1159
+ },
1160
+ required: ['messages'],
1161
+ additionalProperties: false,
1162
+ },
1163
+ },
984
1164
  // ==================== SEMANTIC SEARCH TOOLS (Phase 4 Sprint 12) ====================
985
1165
  {
986
1166
  name: 'semantic_search',
@@ -1030,6 +1210,1401 @@ export const toolDefinitions = [
1030
1210
  additionalProperties: false,
1031
1211
  },
1032
1212
  },
1213
+ // ==================== REF INDEX ====================
1214
+ {
1215
+ name: 'register_ref',
1216
+ description: 'Register a stable alias (ref) pointing to an entity name in the RefIndex for O(1) lookups',
1217
+ inputSchema: {
1218
+ type: 'object',
1219
+ properties: {
1220
+ ref: { type: 'string', description: 'Stable alias string to register' },
1221
+ entityName: { type: 'string', description: 'Entity name this ref resolves to' },
1222
+ description: { type: 'string', description: 'Optional human-readable description of this ref' },
1223
+ },
1224
+ required: ['ref', 'entityName'],
1225
+ additionalProperties: false,
1226
+ },
1227
+ },
1228
+ {
1229
+ name: 'resolve_ref',
1230
+ description: 'Resolve a stable alias (ref) to its entity name via the RefIndex',
1231
+ inputSchema: {
1232
+ type: 'object',
1233
+ properties: {
1234
+ ref: { type: 'string', description: 'Alias string to resolve' },
1235
+ },
1236
+ required: ['ref'],
1237
+ additionalProperties: false,
1238
+ },
1239
+ },
1240
+ {
1241
+ name: 'deregister_ref',
1242
+ description: 'Remove a stable alias (ref) from the RefIndex',
1243
+ inputSchema: {
1244
+ type: 'object',
1245
+ properties: {
1246
+ ref: { type: 'string', description: 'Alias string to deregister' },
1247
+ },
1248
+ required: ['ref'],
1249
+ additionalProperties: false,
1250
+ },
1251
+ },
1252
+ {
1253
+ name: 'list_refs',
1254
+ description: 'List all registered refs in the RefIndex, optionally filtered by entity name',
1255
+ inputSchema: {
1256
+ type: 'object',
1257
+ properties: {
1258
+ entityName: { type: 'string', description: 'Optional: filter refs by entity name' },
1259
+ },
1260
+ additionalProperties: false,
1261
+ },
1262
+ },
1263
+ // ==================== ARTIFACT ====================
1264
+ {
1265
+ name: 'create_artifact',
1266
+ description: 'Create an artifact entity (tool output, code snippet, API response, etc.) with a stable auto-generated ref',
1267
+ inputSchema: {
1268
+ type: 'object',
1269
+ properties: {
1270
+ content: { type: 'string', description: 'Artifact content stored as an entity observation' },
1271
+ toolName: { type: 'string', description: 'Name of the tool or source that produced this artifact' },
1272
+ artifactType: {
1273
+ type: 'string',
1274
+ enum: ['tool_output', 'code_snippet', 'api_response', 'search_result', 'file_content', 'user_input'],
1275
+ description: 'Category of artifact for structured filtering',
1276
+ },
1277
+ description: { type: 'string', description: 'Optional human-readable description' },
1278
+ sessionId: { type: 'string', description: 'Optional session context for grouping related artifacts' },
1279
+ },
1280
+ required: ['content', 'toolName', 'artifactType'],
1281
+ additionalProperties: false,
1282
+ },
1283
+ },
1284
+ {
1285
+ name: 'get_artifact',
1286
+ description: 'Retrieve an artifact entity by its stable ref or entity name',
1287
+ inputSchema: {
1288
+ type: 'object',
1289
+ properties: {
1290
+ ref: { type: 'string', description: 'Stable ref or entity name (e.g. "bash-2026-03-24-a3f2")' },
1291
+ },
1292
+ required: ['ref'],
1293
+ additionalProperties: false,
1294
+ },
1295
+ },
1296
+ {
1297
+ name: 'list_artifacts',
1298
+ description: 'List all artifact entities, with optional filtering by tool name, type, or date',
1299
+ inputSchema: {
1300
+ type: 'object',
1301
+ properties: {
1302
+ toolName: { type: 'string', description: 'Filter by originating tool name' },
1303
+ artifactType: {
1304
+ type: 'string',
1305
+ enum: ['tool_output', 'code_snippet', 'api_response', 'search_result', 'file_content', 'user_input'],
1306
+ description: 'Filter by artifact category',
1307
+ },
1308
+ since: { type: 'string', description: 'Only return artifacts created at or after this ISO 8601 date' },
1309
+ },
1310
+ additionalProperties: false,
1311
+ },
1312
+ },
1313
+ // ==================== TEMPORAL SEARCH ====================
1314
+ {
1315
+ name: 'search_by_time',
1316
+ description: 'Search entities using a natural language time expression (e.g. "last week", "yesterday", "in January")',
1317
+ inputSchema: {
1318
+ type: 'object',
1319
+ properties: {
1320
+ query: { type: 'string', description: 'Natural language time expression to parse and search' },
1321
+ field: {
1322
+ type: 'string',
1323
+ enum: ['createdAt', 'lastModified', 'any'],
1324
+ description: 'Which timestamp field to filter on (default: any)',
1325
+ },
1326
+ includeUndated: {
1327
+ type: 'boolean',
1328
+ description: 'If true, treat entities with no timestamps as matching (default: false)',
1329
+ },
1330
+ },
1331
+ required: ['query'],
1332
+ additionalProperties: false,
1333
+ },
1334
+ },
1335
+ // ==================== DISTILLATION ====================
1336
+ {
1337
+ name: 'configure_distillation',
1338
+ description: 'Configure the distillation pipeline policy (default, noop, or none) that filters memories before context formatting',
1339
+ inputSchema: {
1340
+ type: 'object',
1341
+ properties: {
1342
+ policy: {
1343
+ type: 'string',
1344
+ enum: ['default', 'noop', 'none'],
1345
+ description: 'Policy to apply: default (relevance+freshness+dedup), noop (pass-through), none (clear pipeline)',
1346
+ },
1347
+ },
1348
+ required: ['policy'],
1349
+ additionalProperties: false,
1350
+ },
1351
+ },
1352
+ // ==================== FRESHNESS ====================
1353
+ {
1354
+ name: 'check_freshness',
1355
+ description: 'Calculate the freshness score (0–1) for a specific entity based on its TTL and confidence',
1356
+ inputSchema: {
1357
+ type: 'object',
1358
+ properties: {
1359
+ entityName: { type: 'string', description: 'Name of the entity to check freshness for' },
1360
+ },
1361
+ required: ['entityName'],
1362
+ additionalProperties: false,
1363
+ },
1364
+ },
1365
+ {
1366
+ name: 'get_stale_entities',
1367
+ description: 'Return all entities whose freshness score is below a threshold',
1368
+ inputSchema: {
1369
+ type: 'object',
1370
+ properties: {
1371
+ threshold: {
1372
+ type: 'number',
1373
+ description: 'Freshness threshold (0–1). Entities below this score are considered stale (default: 0.5)',
1374
+ },
1375
+ },
1376
+ additionalProperties: false,
1377
+ },
1378
+ },
1379
+ {
1380
+ name: 'get_expired_entities',
1381
+ description: 'Return all entities that have passed their TTL expiry',
1382
+ inputSchema: {
1383
+ type: 'object',
1384
+ properties: {},
1385
+ additionalProperties: false,
1386
+ },
1387
+ },
1388
+ {
1389
+ name: 'refresh_entity',
1390
+ description: 'Reset freshness for an entity by updating its creation timestamp to now and resetting confidence to 1.0',
1391
+ inputSchema: {
1392
+ type: 'object',
1393
+ properties: {
1394
+ entityName: { type: 'string', description: 'Name of the entity to refresh' },
1395
+ },
1396
+ required: ['entityName'],
1397
+ additionalProperties: false,
1398
+ },
1399
+ },
1400
+ {
1401
+ name: 'freshness_report',
1402
+ description: 'Generate a freshness report across all entities showing fresh, stale, and expired counts',
1403
+ inputSchema: {
1404
+ type: 'object',
1405
+ properties: {
1406
+ threshold: {
1407
+ type: 'number',
1408
+ description: 'Freshness threshold for fresh/stale categorisation (default: 0.5)',
1409
+ },
1410
+ },
1411
+ additionalProperties: false,
1412
+ },
1413
+ },
1414
+ // ==================== LLM QUERY PLANNER ====================
1415
+ {
1416
+ name: 'query_natural_language',
1417
+ description: 'Decompose a natural language query into a structured search plan and return matching entities',
1418
+ inputSchema: {
1419
+ type: 'object',
1420
+ properties: {
1421
+ query: { type: 'string', description: 'Natural language query to plan and execute' },
1422
+ },
1423
+ required: ['query'],
1424
+ additionalProperties: false,
1425
+ },
1426
+ },
1427
+ // ==================== GOVERNANCE ====================
1428
+ {
1429
+ name: 'set_governance_policy',
1430
+ description: 'Set the active governance policy controlling which write operations (create, update, delete) are permitted for future requests',
1431
+ inputSchema: {
1432
+ type: 'object',
1433
+ properties: {
1434
+ canCreate: { type: 'boolean', description: 'Whether entity creation is allowed (default: true)' },
1435
+ canUpdate: { type: 'boolean', description: 'Whether entity updates are allowed (default: true)' },
1436
+ canDelete: { type: 'boolean', description: 'Whether entity deletion is allowed (default: true)' },
1437
+ },
1438
+ additionalProperties: false,
1439
+ },
1440
+ },
1441
+ {
1442
+ name: 'audit_query',
1443
+ description: 'Query the audit log for operations matching filter criteria (operation type, agent ID, entity name, date range)',
1444
+ inputSchema: {
1445
+ type: 'object',
1446
+ properties: {
1447
+ operation: {
1448
+ type: 'string',
1449
+ enum: ['create', 'update', 'delete', 'merge', 'archive'],
1450
+ description: 'Filter by operation type',
1451
+ },
1452
+ agentId: { type: 'string', description: 'Filter by agent identifier' },
1453
+ entityName: { type: 'string', description: 'Filter by entity name' },
1454
+ since: { type: 'string', description: 'Only entries at or after this ISO 8601 timestamp' },
1455
+ until: { type: 'string', description: 'Only entries at or before this ISO 8601 timestamp' },
1456
+ limit: { type: 'number', description: 'Maximum number of results to return (default: 50)' },
1457
+ },
1458
+ additionalProperties: false,
1459
+ },
1460
+ },
1461
+ {
1462
+ name: 'audit_history',
1463
+ description: 'Get the full audit history for a specific entity in chronological order',
1464
+ inputSchema: {
1465
+ type: 'object',
1466
+ properties: {
1467
+ entityName: { type: 'string', description: 'Name of the entity to retrieve audit history for' },
1468
+ },
1469
+ required: ['entityName'],
1470
+ additionalProperties: false,
1471
+ },
1472
+ },
1473
+ {
1474
+ name: 'rollback_operation',
1475
+ description: 'Reverse a specific committed operation using its audit entry ID (restores entity to before-snapshot)',
1476
+ inputSchema: {
1477
+ type: 'object',
1478
+ properties: {
1479
+ auditEntryId: { type: 'string', description: 'ID of the audit entry to reverse' },
1480
+ },
1481
+ required: ['auditEntryId'],
1482
+ additionalProperties: false,
1483
+ },
1484
+ },
1485
+ // ==================== ROLE PROFILES ====================
1486
+ {
1487
+ name: 'set_agent_role',
1488
+ description: 'Apply a built-in role profile (researcher, planner, executor, reviewer, coordinator) to adjust salience weights and context budgets',
1489
+ inputSchema: {
1490
+ type: 'object',
1491
+ properties: {
1492
+ role: {
1493
+ type: 'string',
1494
+ enum: ['researcher', 'planner', 'executor', 'reviewer', 'default'],
1495
+ description: 'Role to apply to the agent memory system',
1496
+ },
1497
+ },
1498
+ required: ['role'],
1499
+ additionalProperties: false,
1500
+ },
1501
+ },
1502
+ {
1503
+ name: 'list_role_profiles',
1504
+ description: 'List all built-in role profiles with their salience weight and context budget configurations',
1505
+ inputSchema: {
1506
+ type: 'object',
1507
+ properties: {},
1508
+ additionalProperties: false,
1509
+ },
1510
+ },
1511
+ // ==================== ENTROPY FILTER ====================
1512
+ {
1513
+ name: 'enable_entropy_filter',
1514
+ description: 'Enable or disable the Shannon entropy gate that drops low-information memories during consolidation',
1515
+ inputSchema: {
1516
+ type: 'object',
1517
+ properties: {
1518
+ enabled: { type: 'boolean', description: 'Whether to enable the entropy filter' },
1519
+ minEntropy: {
1520
+ type: 'number',
1521
+ description: 'Minimum entropy threshold in bits (default: 1.5). Higher = stricter filtering.',
1522
+ },
1523
+ minLength: {
1524
+ type: 'number',
1525
+ description: 'Minimum text length before entropy is evaluated (default: 10)',
1526
+ },
1527
+ },
1528
+ required: ['enabled'],
1529
+ additionalProperties: false,
1530
+ },
1531
+ },
1532
+ {
1533
+ name: 'compute_entropy',
1534
+ description: 'Compute the Shannon entropy of a text string (in bits per character)',
1535
+ inputSchema: {
1536
+ type: 'object',
1537
+ properties: {
1538
+ text: { type: 'string', description: 'Text to compute entropy for' },
1539
+ minEntropy: {
1540
+ type: 'number',
1541
+ description: 'Optional: check if text passes this minimum entropy threshold',
1542
+ },
1543
+ },
1544
+ required: ['text'],
1545
+ additionalProperties: false,
1546
+ },
1547
+ },
1548
+ // ==================== CONSOLIDATION ====================
1549
+ {
1550
+ name: 'start_consolidation',
1551
+ description: 'Start the background consolidation scheduler that periodically deduplicates and merges memories',
1552
+ inputSchema: {
1553
+ type: 'object',
1554
+ properties: {
1555
+ intervalMs: {
1556
+ type: 'number',
1557
+ description: 'Interval between consolidation runs in milliseconds (default: 3600000 = 1 hour)',
1558
+ },
1559
+ autoMergeDuplicates: {
1560
+ type: 'boolean',
1561
+ description: 'Enable duplicate detection and merge after each consolidation (default: false)',
1562
+ },
1563
+ },
1564
+ additionalProperties: false,
1565
+ },
1566
+ },
1567
+ {
1568
+ name: 'stop_consolidation',
1569
+ description: 'Stop the background consolidation scheduler',
1570
+ inputSchema: {
1571
+ type: 'object',
1572
+ properties: {},
1573
+ additionalProperties: false,
1574
+ },
1575
+ },
1576
+ {
1577
+ name: 'run_consolidation_now',
1578
+ description: 'Run a consolidation cycle on demand, independently of the scheduled interval',
1579
+ inputSchema: {
1580
+ type: 'object',
1581
+ properties: {},
1582
+ additionalProperties: false,
1583
+ },
1584
+ },
1585
+ // ==================== MEMORY FORMATTER ====================
1586
+ {
1587
+ name: 'format_with_salience_budget',
1588
+ description: 'Format memories for LLM prompt consumption with proportional token allocation based on salience scores',
1589
+ inputSchema: {
1590
+ type: 'object',
1591
+ properties: {
1592
+ entityNames: {
1593
+ type: 'array',
1594
+ items: { type: 'string' },
1595
+ description: 'Names of entities (memories) to format',
1596
+ },
1597
+ salienceScores: {
1598
+ type: 'object',
1599
+ additionalProperties: { type: 'number' },
1600
+ description: 'Map of entityName → salience score (0–1) for proportional allocation',
1601
+ },
1602
+ totalTokenBudget: {
1603
+ type: 'number',
1604
+ description: 'Maximum total token budget for the formatted output',
1605
+ },
1606
+ header: { type: 'string', description: 'Optional header text to prepend' },
1607
+ separator: { type: 'string', description: 'Optional separator between memories (default: newline)' },
1608
+ },
1609
+ required: ['entityNames', 'salienceScores', 'totalTokenBudget'],
1610
+ additionalProperties: false,
1611
+ },
1612
+ },
1613
+ // ==================== COLLABORATIVE SYNTHESIS ====================
1614
+ {
1615
+ name: 'synthesize_collaborative_context',
1616
+ description: 'Synthesize context by traversing the graph neighbourhood from a seed entity and merging high-salience neighbors across agents',
1617
+ inputSchema: {
1618
+ type: 'object',
1619
+ properties: {
1620
+ seedEntityName: { type: 'string', description: 'Name of the entity to start traversal from' },
1621
+ maxDepth: { type: 'number', description: 'Maximum BFS depth to traverse from seed (default: 2)' },
1622
+ minNeighborSalience: {
1623
+ type: 'number',
1624
+ description: 'Minimum salience score for a neighbor to be included (default: 0.3)',
1625
+ },
1626
+ maxNeighbors: { type: 'number', description: 'Maximum number of neighbor entities to include (default: 20)' },
1627
+ queryText: { type: 'string', description: 'Optional query text for salience context scoring' },
1628
+ currentTask: { type: 'string', description: 'Optional current task identifier for salience context' },
1629
+ },
1630
+ required: ['seedEntityName'],
1631
+ additionalProperties: false,
1632
+ },
1633
+ },
1634
+ // ==================== FAILURE DISTILLATION ====================
1635
+ {
1636
+ name: 'distill_failure',
1637
+ description: 'Distill lessons from a failed session by tracing the causal chain and extracting actionable insights',
1638
+ inputSchema: {
1639
+ type: 'object',
1640
+ properties: {
1641
+ sessionId: { type: 'string', description: 'ID of the failed session to analyze' },
1642
+ minLessonConfidence: {
1643
+ type: 'number',
1644
+ description: 'Minimum confidence required for a lesson to be persisted (default: 0.6)',
1645
+ },
1646
+ maxCauseChainLength: {
1647
+ type: 'number',
1648
+ description: 'Maximum depth to follow causal chains (default: 5)',
1649
+ },
1650
+ },
1651
+ required: ['sessionId'],
1652
+ additionalProperties: false,
1653
+ },
1654
+ },
1655
+ {
1656
+ name: 'end_session',
1657
+ description: 'End a session and trigger failure distillation if the session outcome was a failure',
1658
+ inputSchema: {
1659
+ type: 'object',
1660
+ properties: {
1661
+ sessionId: { type: 'string', description: 'ID of the session to end' },
1662
+ outcome: {
1663
+ type: 'string',
1664
+ enum: ['success', 'failure', 'partial'],
1665
+ description: 'Outcome of the session',
1666
+ },
1667
+ distillFailures: {
1668
+ type: 'boolean',
1669
+ description: 'Whether to automatically distill lessons on failure outcome (default: true)',
1670
+ },
1671
+ },
1672
+ required: ['sessionId', 'outcome'],
1673
+ additionalProperties: false,
1674
+ },
1675
+ },
1676
+ // Phase 13: User profile + agent diary tools
1677
+ {
1678
+ name: 'get_profile',
1679
+ description: 'Get the user profile. Returns static facts (long-lived preferences) and dynamic facts (recent session context). Profiles are scoped by projectId.',
1680
+ inputSchema: {
1681
+ type: 'object',
1682
+ properties: {
1683
+ projectId: { type: 'string', description: 'Optional project scope. Omit for global profile.' },
1684
+ },
1685
+ required: [],
1686
+ additionalProperties: false,
1687
+ },
1688
+ },
1689
+ {
1690
+ name: 'update_profile',
1691
+ description: 'Add a fact to the user profile. Static facts are long-lived (preferences, role, tools). Dynamic facts are recent (current project, active work).',
1692
+ inputSchema: {
1693
+ type: 'object',
1694
+ properties: {
1695
+ content: { type: 'string', description: 'The fact to add' },
1696
+ type: { type: 'string', enum: ['static', 'dynamic'], description: 'Fact type: static (long-lived) or dynamic (recent)' },
1697
+ projectId: { type: 'string', description: 'Optional project scope' },
1698
+ },
1699
+ required: ['content', 'type'],
1700
+ additionalProperties: false,
1701
+ },
1702
+ },
1703
+ {
1704
+ name: 'diary_write',
1705
+ description: 'Write a timestamped diary entry for a specialist agent. Each agent gets its own persistent diary (entity: diary-{agentId}). Use for code review findings, architecture decisions, ops incidents, etc.',
1706
+ inputSchema: {
1707
+ type: 'object',
1708
+ properties: {
1709
+ agentId: { type: 'string', description: 'Agent identifier (e.g., reviewer, architect, ops). Alphanumeric + hyphens/underscores only.' },
1710
+ entry: { type: 'string', description: 'The diary entry content' },
1711
+ topic: { type: 'string', description: 'Optional topic tag for filtering (e.g., security, performance)' },
1712
+ },
1713
+ required: ['agentId', 'entry'],
1714
+ additionalProperties: false,
1715
+ },
1716
+ },
1717
+ {
1718
+ name: 'diary_read',
1719
+ description: 'Read recent diary entries for a specialist agent. Returns entries in reverse chronological order. Optionally filter by topic.',
1720
+ inputSchema: {
1721
+ type: 'object',
1722
+ properties: {
1723
+ agentId: { type: 'string', description: 'Agent identifier' },
1724
+ lastN: { type: 'number', description: 'Number of recent entries to return. Default: 10.' },
1725
+ topic: { type: 'string', description: 'Optional topic filter' },
1726
+ },
1727
+ required: ['agentId'],
1728
+ additionalProperties: false,
1729
+ },
1730
+ },
1731
+ // ==================== COGNITIVE LOAD ====================
1732
+ {
1733
+ name: 'analyze_cognitive_load',
1734
+ description: 'Analyze the cognitive load of a set of entities: token density, redundancy ratio, diversity score, and composite load score',
1735
+ inputSchema: {
1736
+ type: 'object',
1737
+ properties: {
1738
+ entityNames: {
1739
+ type: 'array',
1740
+ items: { type: 'string' },
1741
+ description: 'Names of entities to analyze',
1742
+ },
1743
+ loadThreshold: {
1744
+ type: 'number',
1745
+ description: 'Load score threshold above which context is considered overloaded (default: 0.7)',
1746
+ },
1747
+ },
1748
+ required: ['entityNames'],
1749
+ additionalProperties: false,
1750
+ },
1751
+ },
1752
+ {
1753
+ name: 'adaptive_reduce_memories',
1754
+ description: 'Adaptively reduce a set of memories until their cognitive load falls below the configured threshold by removing low-salience redundant memories',
1755
+ inputSchema: {
1756
+ type: 'object',
1757
+ properties: {
1758
+ entityNames: {
1759
+ type: 'array',
1760
+ items: { type: 'string' },
1761
+ description: 'Names of entities to reduce',
1762
+ },
1763
+ salienceScores: {
1764
+ type: 'object',
1765
+ additionalProperties: { type: 'number' },
1766
+ description: 'Map of entityName → salience score (0–1) for prioritizing removal',
1767
+ },
1768
+ loadThreshold: {
1769
+ type: 'number',
1770
+ description: 'Target load threshold to reduce below (default: 0.7)',
1771
+ },
1772
+ },
1773
+ required: ['entityNames', 'salienceScores'],
1774
+ additionalProperties: false,
1775
+ },
1776
+ },
1777
+ // ==================== DREAM ENGINE TOOLS ====================
1778
+ {
1779
+ name: 'dream_start',
1780
+ description: 'Start the DreamEngine background memory maintenance. Runs 8 phases (temporal anchoring, freshness sweep, entropy pruning, consolidation, compression, entity enrichment, pattern promotion, graph hygiene) on a configurable interval.',
1781
+ inputSchema: {
1782
+ type: 'object',
1783
+ properties: {
1784
+ intervalMs: {
1785
+ type: 'number',
1786
+ description: 'Interval between dream cycles in milliseconds (default: 14400000 = 4 hours)',
1787
+ },
1788
+ runOnSessionEnd: {
1789
+ type: 'boolean',
1790
+ description: 'Run a dream cycle automatically when endSession() is called (default: true)',
1791
+ },
1792
+ maxDurationMs: {
1793
+ type: 'number',
1794
+ description: 'Hard limit on total cycle wall-clock time in milliseconds (default: 60000 = 60s)',
1795
+ },
1796
+ phases: {
1797
+ type: 'object',
1798
+ description: 'Per-phase enable/disable flags',
1799
+ properties: {
1800
+ temporalAnchoring: { type: 'boolean', description: 'Phase 1: Resolve relative date references to absolute ISO timestamps' },
1801
+ freshnessSweep: { type: 'boolean', description: 'Phase 2: Flag stale entities, decay confidence, expire TTL records' },
1802
+ entropyPruning: { type: 'boolean', description: 'Phase 3: Remove observations whose Shannon entropy is below threshold' },
1803
+ consolidation: { type: 'boolean', description: 'Phase 4: Merge working-memory items into long-term storage' },
1804
+ compression: { type: 'boolean', description: 'Phase 5: Deduplicate near-identical entities above similarity threshold' },
1805
+ entityEnrichment: { type: 'boolean', description: 'Phase 6: Auto-generate summary observations for entity enrichment' },
1806
+ patternPromotion: { type: 'boolean', description: 'Phase 7: Detect recurring observation themes and promote to semantic memory' },
1807
+ graphHygiene: { type: 'boolean', description: 'Phase 8: Orphan detection and dangling-relation cleanup' },
1808
+ },
1809
+ additionalProperties: false,
1810
+ },
1811
+ },
1812
+ additionalProperties: false,
1813
+ },
1814
+ },
1815
+ {
1816
+ name: 'dream_stop',
1817
+ description: 'Stop the DreamEngine background process.',
1818
+ inputSchema: {
1819
+ type: 'object',
1820
+ properties: {},
1821
+ additionalProperties: false,
1822
+ },
1823
+ },
1824
+ {
1825
+ name: 'dream_run_now',
1826
+ description: 'Run a single dream cycle immediately. Returns detailed per-phase results.',
1827
+ inputSchema: {
1828
+ type: 'object',
1829
+ properties: {
1830
+ phases: {
1831
+ type: 'object',
1832
+ description: 'Per-phase enable/disable flags for this cycle',
1833
+ properties: {
1834
+ temporalAnchoring: { type: 'boolean', description: 'Phase 1: Resolve relative date references to absolute ISO timestamps' },
1835
+ freshnessSweep: { type: 'boolean', description: 'Phase 2: Flag stale entities, decay confidence, expire TTL records' },
1836
+ entropyPruning: { type: 'boolean', description: 'Phase 3: Remove observations whose Shannon entropy is below threshold' },
1837
+ consolidation: { type: 'boolean', description: 'Phase 4: Merge working-memory items into long-term storage' },
1838
+ compression: { type: 'boolean', description: 'Phase 5: Deduplicate near-identical entities above similarity threshold' },
1839
+ entityEnrichment: { type: 'boolean', description: 'Phase 6: Auto-generate summary observations for entity enrichment' },
1840
+ patternPromotion: { type: 'boolean', description: 'Phase 7: Detect recurring observation themes and promote to semantic memory' },
1841
+ graphHygiene: { type: 'boolean', description: 'Phase 8: Orphan detection and dangling-relation cleanup' },
1842
+ },
1843
+ additionalProperties: false,
1844
+ },
1845
+ },
1846
+ additionalProperties: false,
1847
+ },
1848
+ },
1849
+ // Phase 13: Config tool
1850
+ // TODO: set_project_scope requires server state management (activeProjectId on MCPServer)
1851
+ // Skipped in this pass — implement when MCPServer exposes mutable server state to handlers.
1852
+ // ==================== SESSION & WORKING MEMORY TOOLS ====================
1853
+ {
1854
+ name: 'session_start',
1855
+ description: 'Start a new agent session via AgentMemoryManager. Tracks session lifecycle, enables working memory, and supports session chaining. Returns a SessionEntity with id and timestamps.',
1856
+ inputSchema: {
1857
+ type: 'object',
1858
+ properties: {
1859
+ taskDescription: { type: 'string', description: 'Description of the task for this session' },
1860
+ parentSessionId: { type: 'string', description: 'ID of a parent session to chain from' },
1861
+ metadata: { type: 'object', description: 'Arbitrary metadata to attach to the session' },
1862
+ },
1863
+ additionalProperties: false,
1864
+ },
1865
+ },
1866
+ {
1867
+ name: 'session_end',
1868
+ description: 'End an agent session via AgentMemoryManager with summary generation and working memory promotion. Unlike end_session (which handles failure distillation on graph entities), this manages the full agent session lifecycle.',
1869
+ inputSchema: {
1870
+ type: 'object',
1871
+ properties: {
1872
+ sessionId: { type: 'string', description: 'The session ID to end' },
1873
+ status: { type: 'string', enum: ['completed', 'abandoned'], description: 'Session completion status (default: completed)' },
1874
+ },
1875
+ required: ['sessionId'],
1876
+ additionalProperties: false,
1877
+ },
1878
+ },
1879
+ {
1880
+ name: 'session_checkpoint',
1881
+ description: 'Create a checkpoint snapshot of the current session state for later restore',
1882
+ inputSchema: {
1883
+ type: 'object',
1884
+ properties: {
1885
+ sessionId: { type: 'string', description: 'The session ID to checkpoint' },
1886
+ name: { type: 'string', description: 'Optional human-readable name for the checkpoint' },
1887
+ },
1888
+ required: ['sessionId'],
1889
+ additionalProperties: false,
1890
+ },
1891
+ },
1892
+ {
1893
+ name: 'session_restore',
1894
+ description: 'Restore a session from a previously created checkpoint',
1895
+ inputSchema: {
1896
+ type: 'object',
1897
+ properties: {
1898
+ checkpointId: { type: 'string', description: 'The checkpoint ID to restore from' },
1899
+ },
1900
+ required: ['checkpointId'],
1901
+ additionalProperties: false,
1902
+ },
1903
+ },
1904
+ {
1905
+ name: 'add_working_memory',
1906
+ description: 'Create a TTL-based short-term working memory entry scoped to a session. Working memories auto-expire and can be promoted to long-term storage.',
1907
+ inputSchema: {
1908
+ type: 'object',
1909
+ properties: {
1910
+ sessionId: { type: 'string', description: 'Session ID this memory belongs to' },
1911
+ content: { type: 'string', description: 'The memory content' },
1912
+ taskId: { type: 'string', description: 'Optional task ID for task-scoped memory' },
1913
+ importance: { type: 'number', description: 'Importance score (0-10)' },
1914
+ ttlHours: { type: 'number', description: 'Time-to-live in hours (default: 24)' },
1915
+ },
1916
+ required: ['sessionId', 'content'],
1917
+ additionalProperties: false,
1918
+ },
1919
+ },
1920
+ {
1921
+ name: 'promote_working_memory',
1922
+ description: 'Promote a working memory entry to long-term episodic or semantic storage',
1923
+ inputSchema: {
1924
+ type: 'object',
1925
+ properties: {
1926
+ memoryName: { type: 'string', description: 'Name of the working memory entity to promote' },
1927
+ targetType: { type: 'string', enum: ['episodic', 'semantic'], description: 'Target memory type (default: episodic)' },
1928
+ },
1929
+ required: ['memoryName'],
1930
+ additionalProperties: false,
1931
+ },
1932
+ },
1933
+ {
1934
+ name: 'confirm_memory',
1935
+ description: 'Boost a memory\'s confidence score without resetting its timestamp. Unlike refresh_entity (which resets to 1.0), this incrementally increases confidence.',
1936
+ inputSchema: {
1937
+ type: 'object',
1938
+ properties: {
1939
+ memoryName: { type: 'string', description: 'Name of the memory entity to confirm' },
1940
+ confidenceBoost: { type: 'number', description: 'Amount to boost confidence by (default: 0.1)' },
1941
+ },
1942
+ required: ['memoryName'],
1943
+ additionalProperties: false,
1944
+ },
1945
+ },
1946
+ {
1947
+ name: 'clear_expired_memories',
1948
+ description: 'Remove all working memories that have exceeded their TTL. Complements get_expired_entities (which lists but does not delete).',
1949
+ inputSchema: {
1950
+ type: 'object',
1951
+ properties: {},
1952
+ additionalProperties: false,
1953
+ },
1954
+ },
1955
+ {
1956
+ name: 'wake_up',
1957
+ description: 'Initialize a 4-layer memory stack context (~600 tokens). L0 loads profile identity, L1 loads top entities by importance. Returns a compact boot context for LLM consumption.',
1958
+ inputSchema: {
1959
+ type: 'object',
1960
+ properties: {
1961
+ compress: { type: 'boolean', description: 'Apply n-gram compression to reduce token count (default: false)' },
1962
+ },
1963
+ additionalProperties: false,
1964
+ },
1965
+ },
1966
+ // ==================== AUTO-ENHANCEMENT TOOLS ====================
1967
+ {
1968
+ name: 'auto_link_observations',
1969
+ description: 'Detect entity mentions in observation text and suggest cross-reference relations. Unlike normalize_observations (which resolves pronouns/dates), this finds entity name mentions.',
1970
+ inputSchema: {
1971
+ type: 'object',
1972
+ properties: {
1973
+ text: { type: 'string', description: 'Observation text to scan for entity mentions' },
1974
+ },
1975
+ required: ['text'],
1976
+ additionalProperties: false,
1977
+ },
1978
+ },
1979
+ {
1980
+ name: 'extract_facts',
1981
+ description: 'Extract structured facts from observation text using rule-based extraction',
1982
+ inputSchema: {
1983
+ type: 'object',
1984
+ properties: {
1985
+ text: { type: 'string', description: 'Text to extract facts from' },
1986
+ },
1987
+ required: ['text'],
1988
+ additionalProperties: false,
1989
+ },
1990
+ },
1991
+ {
1992
+ name: 'detect_contradictions',
1993
+ description: 'Find conflicting observations within an entity using semantic similarity',
1994
+ inputSchema: {
1995
+ type: 'object',
1996
+ properties: {
1997
+ entityName: { type: 'string', description: 'Entity to check for contradictions' },
1998
+ threshold: { type: 'number', description: 'Similarity threshold for contradiction detection (0-1, default: 0.85)', minimum: 0, maximum: 1 },
1999
+ },
2000
+ required: ['entityName'],
2001
+ additionalProperties: false,
2002
+ },
2003
+ },
2004
+ {
2005
+ name: 'consolidate_session',
2006
+ description: 'Run the full ConsolidationPipeline on a session: promote working memory, merge duplicates, summarize, and extract patterns. Unlike run_consolidation_now (which runs the dedup scheduler), this is a comprehensive session-scoped pipeline.',
2007
+ inputSchema: {
2008
+ type: 'object',
2009
+ properties: {
2010
+ sessionId: { type: 'string', description: 'Session ID to consolidate' },
2011
+ },
2012
+ required: ['sessionId'],
2013
+ additionalProperties: false,
2014
+ },
2015
+ },
2016
+ {
2017
+ name: 'detect_patterns',
2018
+ description: 'Detect recurring token-based patterns across observations of a given entity type',
2019
+ inputSchema: {
2020
+ type: 'object',
2021
+ properties: {
2022
+ entityType: { type: 'string', description: 'Entity type to analyze for patterns' },
2023
+ minOccurrences: { type: 'number', description: 'Minimum occurrences to qualify as a pattern (default: 3)' },
2024
+ },
2025
+ required: ['entityType'],
2026
+ additionalProperties: false,
2027
+ },
2028
+ },
2029
+ {
2030
+ name: 'summarize_entity',
2031
+ description: 'Auto-summarize redundant observations within a single entity. Unlike compress_graph (which merges similar entities), this condenses observations within one entity.',
2032
+ inputSchema: {
2033
+ type: 'object',
2034
+ properties: {
2035
+ entityName: { type: 'string', description: 'Entity whose observations to summarize' },
2036
+ threshold: { type: 'number', description: 'Similarity threshold for merging observations (0-1)', minimum: 0, maximum: 1 },
2037
+ },
2038
+ required: ['entityName'],
2039
+ additionalProperties: false,
2040
+ },
2041
+ },
2042
+ {
2043
+ name: 'priority_dedup',
2044
+ description: 'Smart priority-based deduplication that keeps the highest-scored entity per duplicate group (importance > recency > observation count > tags)',
2045
+ inputSchema: {
2046
+ type: 'object',
2047
+ properties: {
2048
+ dryRun: { type: 'boolean', description: 'If true, report what would be deduplicated without making changes' },
2049
+ },
2050
+ additionalProperties: false,
2051
+ },
2052
+ },
2053
+ // ==================== CONTEXT COMPRESSION TOOLS ====================
2054
+ {
2055
+ name: 'compress_context',
2056
+ description: 'Compress text using n-gram abbreviation with a legend for token-efficient context loading. Unlike format_with_salience_budget (which allocates token budget), this does text-level compression.',
2057
+ inputSchema: {
2058
+ type: 'object',
2059
+ properties: {
2060
+ text: { type: 'string', description: 'Text to compress' },
2061
+ level: { type: 'string', enum: ['light', 'medium', 'aggressive'], description: 'Compression level (default: medium)' },
2062
+ },
2063
+ required: ['text'],
2064
+ additionalProperties: false,
2065
+ },
2066
+ },
2067
+ // ==================== DECAY & SALIENCE TOOLS ====================
2068
+ {
2069
+ name: 'run_decay_cycle',
2070
+ description: 'Run a single pass of time-based importance decay across all agent memories. Returns count of decayed and forgotten memories.',
2071
+ inputSchema: {
2072
+ type: 'object',
2073
+ properties: {},
2074
+ additionalProperties: false,
2075
+ },
2076
+ },
2077
+ {
2078
+ name: 'get_decayed_memories',
2079
+ description: 'List memories whose importance has fallen below a threshold due to time-based decay. Unlike get_stale_entities (which uses freshness timestamps), this uses decay engine importance calculations.',
2080
+ inputSchema: {
2081
+ type: 'object',
2082
+ properties: {
2083
+ threshold: { type: 'number', description: 'Importance threshold (default: 0.1)' },
2084
+ },
2085
+ additionalProperties: false,
2086
+ },
2087
+ },
2088
+ {
2089
+ name: 'forget_weak_memories',
2090
+ description: 'Bulk-delete memories that fell below a decay threshold. Unlike forget_memory (content match) or archive_entities (criteria-based move), this uses decay-based importance scoring.',
2091
+ inputSchema: {
2092
+ type: 'object',
2093
+ properties: {
2094
+ threshold: { type: 'number', description: 'Importance threshold below which to forget' },
2095
+ maxCount: { type: 'number', description: 'Maximum number of memories to forget' },
2096
+ dryRun: { type: 'boolean', description: 'If true, report what would be forgotten without deleting' },
2097
+ },
2098
+ additionalProperties: false,
2099
+ },
2100
+ },
2101
+ {
2102
+ name: 'reinforce_memory',
2103
+ description: 'Boost a memory\'s decay resistance by increasing confirmation count and/or confidence. Unlike refresh_entity (timestamp reset) or set_importance (static score), this modulates the decay model.',
2104
+ inputSchema: {
2105
+ type: 'object',
2106
+ properties: {
2107
+ memoryName: { type: 'string', description: 'Name of the memory to reinforce' },
2108
+ confirmationBoost: { type: 'number', description: 'Amount to boost confirmation count' },
2109
+ confidenceBoost: { type: 'number', description: 'Amount to boost confidence score' },
2110
+ },
2111
+ required: ['memoryName'],
2112
+ additionalProperties: false,
2113
+ },
2114
+ },
2115
+ {
2116
+ name: 'score_salience',
2117
+ description: 'Calculate 5-component relevance score for an entity: baseImportance, recencyBoost, frequencyBoost, contextRelevance, noveltyBoost. Use with format_with_salience_budget to score then format.',
2118
+ inputSchema: {
2119
+ type: 'object',
2120
+ properties: {
2121
+ entityName: { type: 'string', description: 'Entity to score' },
2122
+ queryText: { type: 'string', description: 'Optional query text for context relevance' },
2123
+ taskDescription: { type: 'string', description: 'Optional task description for task relevance' },
2124
+ sessionId: { type: 'string', description: 'Optional session ID for session relevance' },
2125
+ },
2126
+ required: ['entityName'],
2127
+ additionalProperties: false,
2128
+ },
2129
+ },
2130
+ // ==================== MULTI-AGENT TOOLS ====================
2131
+ {
2132
+ name: 'register_agent',
2133
+ description: 'Register an agent for multi-agent operations with identity metadata. Unlike set_agent_role (which applies a role profile), this registers agent identity with type, trust level, and capabilities.',
2134
+ inputSchema: {
2135
+ type: 'object',
2136
+ properties: {
2137
+ agentId: { type: 'string', description: 'Unique agent identifier' },
2138
+ type: { type: 'string', description: 'Agent type (e.g., assistant, specialist, coordinator)' },
2139
+ trustLevel: { type: 'number', description: 'Trust level (0-1)', minimum: 0, maximum: 1 },
2140
+ capabilities: { type: 'array', items: { type: 'string' }, description: 'List of agent capabilities' },
2141
+ },
2142
+ required: ['agentId'],
2143
+ additionalProperties: false,
2144
+ },
2145
+ },
2146
+ {
2147
+ name: 'search_cross_agent',
2148
+ description: 'Search across agent memories with trust-weighted scoring and visibility filtering',
2149
+ inputSchema: {
2150
+ type: 'object',
2151
+ properties: {
2152
+ requestingAgentId: { type: 'string', description: 'Agent ID making the request' },
2153
+ query: { type: 'string', description: 'Search query' },
2154
+ agentIds: { type: 'array', items: { type: 'string' }, description: 'Optional list of agent IDs to search across' },
2155
+ },
2156
+ required: ['requestingAgentId', 'query'],
2157
+ additionalProperties: false,
2158
+ },
2159
+ },
2160
+ {
2161
+ name: 'set_memory_visibility',
2162
+ description: 'Set the visibility of a memory entity for multi-agent access control. Auto-promotes plain entities to AgentEntity (stamps agentId/memoryType/etc.) instead of failing silently. Supports η.5.5.b extensions: allowedRoles (role gate), visibleFrom/visibleUntil (time-window gate).',
2163
+ inputSchema: {
2164
+ type: 'object',
2165
+ properties: {
2166
+ memoryName: { type: 'string', description: 'Name of the memory entity' },
2167
+ agentId: { type: 'string', description: 'Agent ID that owns the memory' },
2168
+ visibility: { type: 'string', enum: ['private', 'team', 'org', 'shared', 'public'], description: 'Visibility level' },
2169
+ allowedRoles: {
2170
+ type: 'array',
2171
+ items: { type: 'string' },
2172
+ description: 'η.5.5.b — Optional role gate. When set, requesting agents whose AgentMetadata.role is NOT in this list are denied even if the visibility level would grant. AND-combined with the level check.',
2173
+ },
2174
+ visibleFrom: {
2175
+ type: 'string',
2176
+ description: 'η.5.5.b — ISO 8601. Memory becomes visible at this instant. Absent ⇒ visible since creation. Denies even the owner before this time.',
2177
+ },
2178
+ visibleUntil: {
2179
+ type: 'string',
2180
+ description: 'η.5.5.b — ISO 8601. Memory stops being visible at this instant. Useful for shared drafts that expire on a known handoff date.',
2181
+ },
2182
+ },
2183
+ required: ['memoryName', 'agentId', 'visibility'],
2184
+ additionalProperties: false,
2185
+ },
2186
+ },
2187
+ {
2188
+ name: 'get_visible_memories',
2189
+ description: 'Get all memories visible to a specific agent based on visibility rules and trust levels',
2190
+ inputSchema: {
2191
+ type: 'object',
2192
+ properties: {
2193
+ agentId: { type: 'string', description: 'Agent ID to check visibility for' },
2194
+ },
2195
+ required: ['agentId'],
2196
+ additionalProperties: false,
2197
+ },
2198
+ },
2199
+ {
2200
+ name: 'resolve_agent_conflict',
2201
+ description: 'Resolve a conflict between two agent memories using a specified strategy',
2202
+ inputSchema: {
2203
+ type: 'object',
2204
+ properties: {
2205
+ primaryMemory: { type: 'string', description: 'Name of the first conflicting memory' },
2206
+ conflictingMemory: { type: 'string', description: 'Name of the second conflicting memory' },
2207
+ strategy: { type: 'string', enum: ['most_recent', 'highest_confidence', 'most_confirmations', 'trusted_agent'], description: 'Conflict resolution strategy (default: most_recent)' },
2208
+ },
2209
+ required: ['primaryMemory', 'conflictingMemory'],
2210
+ additionalProperties: false,
2211
+ },
2212
+ },
2213
+ // ==================== OBSERVABILITY TOOLS ====================
2214
+ {
2215
+ name: 'visualize_graph',
2216
+ description: 'Generate a self-contained interactive HTML page with a D3.js force-directed graph visualization. Nodes are colored by type and sized by importance.',
2217
+ inputSchema: {
2218
+ type: 'object',
2219
+ properties: {
2220
+ maxEntities: { type: 'number', description: 'Maximum entities to include (default: 100)' },
2221
+ title: { type: 'string', description: 'Title for the graph visualization' },
2222
+ },
2223
+ additionalProperties: false,
2224
+ },
2225
+ },
2226
+ {
2227
+ name: 'split_transcript',
2228
+ description: 'Split concatenated multi-session transcripts into per-session chunks via delimiter detection. Preprocessing step before ingest.',
2229
+ inputSchema: {
2230
+ type: 'object',
2231
+ properties: {
2232
+ text: { type: 'string', description: 'Raw transcript text to split' },
2233
+ },
2234
+ required: ['text'],
2235
+ additionalProperties: false,
2236
+ },
2237
+ },
2238
+ {
2239
+ name: 'estimate_query_cost',
2240
+ description: 'Estimate execution cost (time, tokens) for all available search methods on a given query. Unlike analyze_query (which extracts entities/complexity), this predicts per-method performance.',
2241
+ inputSchema: {
2242
+ type: 'object',
2243
+ properties: {
2244
+ query: { type: 'string', description: 'Search query to estimate cost for' },
2245
+ },
2246
+ required: ['query'],
2247
+ additionalProperties: false,
2248
+ },
2249
+ },
2250
+ {
2251
+ name: 'get_context_profile',
2252
+ description: 'Get a ContextWindowManager profile configuration (salience weights, retrieval strategy). Unlike get_profile (user profile facts), this returns context-aware retrieval settings.',
2253
+ inputSchema: {
2254
+ type: 'object',
2255
+ properties: {
2256
+ name: { type: 'string', description: 'Profile name to retrieve' },
2257
+ },
2258
+ required: ['name'],
2259
+ additionalProperties: false,
2260
+ },
2261
+ },
2262
+ // ==================== η.4.4 BITEMPORAL ENTITY TOOLS ====================
2263
+ {
2264
+ name: 'invalidate_entity',
2265
+ description: 'η.4.4 — Mark an entity as no longer valid by setting validUntil. Idempotent. Does not delete the entity — entity_as_of still returns it for past asOf timestamps. Orthogonal to v1.8 supersession.',
2266
+ inputSchema: {
2267
+ type: 'object',
2268
+ properties: {
2269
+ name: { type: 'string', description: 'Entity name' },
2270
+ ended: { type: 'string', description: 'ISO 8601 timestamp; defaults to current time' },
2271
+ },
2272
+ required: ['name'],
2273
+ additionalProperties: false,
2274
+ },
2275
+ },
2276
+ {
2277
+ name: 'entity_as_of',
2278
+ description: 'η.4.4 — Time-travel query for an entity. Returns the entity at a given point in time, or null if it was already invalidated then. An entity is valid at asOf when validFrom <= asOf AND (validUntil is undefined OR validUntil >= asOf).',
2279
+ inputSchema: {
2280
+ type: 'object',
2281
+ properties: {
2282
+ name: { type: 'string', description: 'Entity name' },
2283
+ asOf: { type: 'string', description: 'ISO 8601 date string to query at' },
2284
+ },
2285
+ required: ['name', 'asOf'],
2286
+ additionalProperties: false,
2287
+ },
2288
+ },
2289
+ {
2290
+ name: 'entity_timeline',
2291
+ description: 'η.4.4 — Get all temporal versions of an entity in chronological order (by validFrom asc, with unbounded entities last). Returns the v1.8 supersession chain when one exists.',
2292
+ inputSchema: {
2293
+ type: 'object',
2294
+ properties: {
2295
+ name: { type: 'string', description: 'Entity name (any version in the chain)' },
2296
+ },
2297
+ required: ['name'],
2298
+ additionalProperties: false,
2299
+ },
2300
+ },
2301
+ {
2302
+ name: 'invalidate_observation',
2303
+ description: 'η.4.4 — Mark a specific observation on an entity as no longer valid. Creates a parallel observationMeta[] entry if absent. Throws if observation not found on entity.',
2304
+ inputSchema: {
2305
+ type: 'object',
2306
+ properties: {
2307
+ entityName: { type: 'string', description: 'Entity name' },
2308
+ content: { type: 'string', description: 'Exact observation content to invalidate' },
2309
+ ended: { type: 'string', description: 'ISO 8601 timestamp; defaults to current time' },
2310
+ },
2311
+ required: ['entityName', 'content'],
2312
+ additionalProperties: false,
2313
+ },
2314
+ },
2315
+ {
2316
+ name: 'observations_as_of',
2317
+ description: 'η.4.4 — Get observations valid at a given point in time. Observations with no observationMeta entry are treated as unbounded (always-valid).',
2318
+ inputSchema: {
2319
+ type: 'object',
2320
+ properties: {
2321
+ entityName: { type: 'string', description: 'Entity name' },
2322
+ asOf: { type: 'string', description: 'ISO 8601 date string' },
2323
+ },
2324
+ required: ['entityName', 'asOf'],
2325
+ additionalProperties: false,
2326
+ },
2327
+ },
2328
+ // ==================== η.5.5 OCC + ATTRIBUTION TOOLS ====================
2329
+ {
2330
+ name: 'update_entity',
2331
+ description: 'η.5.5.c — Update an entity with optional optimistic concurrency control. Pass expectedVersion to assert the live entity is at that version; throws VersionConflictError on mismatch. Omit for legacy last-write-wins. OCC-guarded writes auto-increment version.',
2332
+ inputSchema: {
2333
+ type: 'object',
2334
+ properties: {
2335
+ name: { type: 'string', description: 'Entity name to update' },
2336
+ updates: {
2337
+ type: 'object',
2338
+ description: 'Partial entity object — fields to change',
2339
+ additionalProperties: true,
2340
+ },
2341
+ expectedVersion: {
2342
+ type: 'number',
2343
+ description: 'OCC: assert the live entity is at this version. Throws VersionConflictError on mismatch.',
2344
+ },
2345
+ },
2346
+ required: ['name', 'updates'],
2347
+ additionalProperties: false,
2348
+ },
2349
+ },
2350
+ // ==================== η.6.1 RBAC TOOLS ====================
2351
+ {
2352
+ name: 'rbac_assign_role',
2353
+ description: 'η.6.1 — Grant a role to an agent. Roles: reader (read), writer (read+write), admin (read+write+delete), owner (all four). Optional resourceType narrows to one type; optional scope narrows to a name prefix; optional validUntil expires the grant.',
2354
+ inputSchema: {
2355
+ type: 'object',
2356
+ properties: {
2357
+ agentId: { type: 'string', description: 'Agent identifier' },
2358
+ role: { type: 'string', description: 'Role name (reader, writer, admin, owner, or custom)' },
2359
+ resourceType: { type: 'string', enum: ['entity', 'relation', 'observation', 'session', 'artifact'], description: 'Optional resource-type narrow' },
2360
+ scope: { type: 'string', description: 'Optional name prefix (e.g. "project-x:")' },
2361
+ validFrom: { type: 'string', description: 'ISO 8601 — assignment becomes active' },
2362
+ validUntil: { type: 'string', description: 'ISO 8601 — assignment expires' },
2363
+ notes: { type: 'string', description: 'Free-form notes (e.g. ticket reference)' },
2364
+ },
2365
+ required: ['agentId', 'role'],
2366
+ additionalProperties: false,
2367
+ },
2368
+ },
2369
+ {
2370
+ name: 'rbac_revoke_role',
2371
+ description: 'η.6.1 — Remove a specific role assignment. Matching is by agentId + role + resourceType (exact, including undefined).',
2372
+ inputSchema: {
2373
+ type: 'object',
2374
+ properties: {
2375
+ agentId: { type: 'string' },
2376
+ role: { type: 'string' },
2377
+ resourceType: { type: 'string', enum: ['entity', 'relation', 'observation', 'session', 'artifact'] },
2378
+ },
2379
+ required: ['agentId', 'role'],
2380
+ additionalProperties: false,
2381
+ },
2382
+ },
2383
+ {
2384
+ name: 'rbac_check_permission',
2385
+ description: 'η.6.1 — Check whether an agent can perform an action on a resource type. Falls back to defaultRole=reader for agents with no assignments.',
2386
+ inputSchema: {
2387
+ type: 'object',
2388
+ properties: {
2389
+ agentId: { type: 'string' },
2390
+ action: { type: 'string', enum: ['read', 'write', 'delete', 'manage'] },
2391
+ resourceType: { type: 'string', enum: ['entity', 'relation', 'observation', 'session', 'artifact'] },
2392
+ resourceName: { type: 'string', description: 'Optional resource name for scope-prefix matching' },
2393
+ now: { type: 'string', description: 'Optional time override for hypothetical-time queries' },
2394
+ },
2395
+ required: ['agentId', 'action', 'resourceType'],
2396
+ additionalProperties: false,
2397
+ },
2398
+ },
2399
+ {
2400
+ name: 'rbac_list_assignments',
2401
+ description: 'η.6.1 — List role assignments for an agent (active or all).',
2402
+ inputSchema: {
2403
+ type: 'object',
2404
+ properties: {
2405
+ agentId: { type: 'string' },
2406
+ activeOnly: { type: 'boolean', default: false, description: 'If true, filter by current time' },
2407
+ now: { type: 'string', description: 'Optional time override (only meaningful when activeOnly=true)' },
2408
+ },
2409
+ required: ['agentId'],
2410
+ additionalProperties: false,
2411
+ },
2412
+ },
2413
+ // ==================== 3B.4 PROCEDURAL MEMORY TOOLS ====================
2414
+ {
2415
+ name: 'add_procedure',
2416
+ description: '3B.4 — Persist a new procedural memory (executable how-to sequence). Steps are ordered (1-indexed) with optional fallback chains. Auto-generates id when omitted. Distinct from semantic facts and episodic events.',
2417
+ inputSchema: {
2418
+ type: 'object',
2419
+ properties: {
2420
+ id: { type: 'string', description: 'Optional stable id; auto-generated if omitted' },
2421
+ name: { type: 'string', description: 'Human-readable name' },
2422
+ description: { type: 'string' },
2423
+ steps: {
2424
+ type: 'array',
2425
+ description: 'Ordered step list',
2426
+ items: {
2427
+ type: 'object',
2428
+ properties: {
2429
+ order: { type: 'number', description: '1-indexed step order' },
2430
+ action: { type: 'string', description: 'Caller-meaningful action identifier' },
2431
+ parameters: { type: 'object', description: 'Parameter map (string → string)', additionalProperties: { type: 'string' } },
2432
+ fallback: { type: 'object', description: 'Optional fallback step on failure' },
2433
+ timeout: { type: 'number', description: 'Caller-enforced max duration in ms' },
2434
+ },
2435
+ required: ['order', 'action', 'parameters'],
2436
+ },
2437
+ },
2438
+ triggers: { type: 'array', items: { type: 'string' }, description: 'Free-form trigger phrases for matching' },
2439
+ },
2440
+ required: ['steps'],
2441
+ additionalProperties: false,
2442
+ },
2443
+ },
2444
+ {
2445
+ name: 'get_procedure',
2446
+ description: '3B.4 — Load a procedure by id.',
2447
+ inputSchema: {
2448
+ type: 'object',
2449
+ properties: { id: { type: 'string' } },
2450
+ required: ['id'],
2451
+ additionalProperties: false,
2452
+ },
2453
+ },
2454
+ {
2455
+ name: 'match_procedure',
2456
+ description: '3B.4 — Token-overlap match a context description against stored procedures. Returns ranked matches with Jaccard-like scores.',
2457
+ inputSchema: {
2458
+ type: 'object',
2459
+ properties: {
2460
+ context: { type: 'string', description: 'Context description to match against' },
2461
+ threshold: { type: 'number', minimum: 0, maximum: 1, default: 0, description: 'Minimum match score' },
2462
+ candidateIds: { type: 'array', items: { type: 'string' }, description: 'Optional procedure ids to match against (default: all)' },
2463
+ },
2464
+ required: ['context'],
2465
+ additionalProperties: false,
2466
+ },
2467
+ },
2468
+ {
2469
+ name: 'refine_procedure',
2470
+ description: '3B.4 — Apply caller feedback after a procedure execution. Increments executionCount and updates successRate via EWMA (α=0.2).',
2471
+ inputSchema: {
2472
+ type: 'object',
2473
+ properties: {
2474
+ id: { type: 'string' },
2475
+ succeeded: { type: 'boolean' },
2476
+ notes: { type: 'string' },
2477
+ recordedAt: { type: 'string' },
2478
+ },
2479
+ required: ['id', 'succeeded'],
2480
+ additionalProperties: false,
2481
+ },
2482
+ },
2483
+ {
2484
+ name: 'get_procedure_step',
2485
+ description: '3B.4 — Load a specific step from a procedure by 1-indexed order, OR get the next step relative to currentOrder.',
2486
+ inputSchema: {
2487
+ type: 'object',
2488
+ properties: {
2489
+ id: { type: 'string' },
2490
+ order: { type: 'number', description: '1-indexed step to fetch' },
2491
+ next: { type: 'boolean', description: 'If true, returns the step after `order` instead of step `order` itself' },
2492
+ },
2493
+ required: ['id', 'order'],
2494
+ additionalProperties: false,
2495
+ },
2496
+ },
2497
+ // ==================== 3B.5 ACTIVE RETRIEVAL TOOL ====================
2498
+ {
2499
+ name: 'adaptive_retrieve',
2500
+ description: '3B.5 — Run iterative query-rewriting retrieval. Up to maxRounds of (search → score coverage → rewrite). Stops early when coverage ≥ minCoverage or no expansion tokens. Pure symbolic — no LLM provider required.',
2501
+ inputSchema: {
2502
+ type: 'object',
2503
+ properties: {
2504
+ query: { type: 'string' },
2505
+ budgetTokens: { type: 'number', description: 'Optional token budget; rejects retrieval if cost exceeds budget' },
2506
+ maxRounds: { type: 'number', default: 3 },
2507
+ minCoverage: { type: 'number', minimum: 0, maximum: 1, default: 0.6 },
2508
+ resultsPerRound: { type: 'number', default: 10 },
2509
+ },
2510
+ required: ['query'],
2511
+ additionalProperties: false,
2512
+ },
2513
+ },
2514
+ // ==================== 3B.6 CAUSAL REASONING TOOLS ====================
2515
+ {
2516
+ name: 'find_causes',
2517
+ description: '3B.6 — Find causal chains ending at the named effect. Searches paths from candidate causes via causal relation types (causes/enables/prevents/precedes/correlates). Sorted by score = product of per-edge causalStrength.',
2518
+ inputSchema: {
2519
+ type: 'object',
2520
+ properties: {
2521
+ effect: { type: 'string', description: 'Target entity name (effect)' },
2522
+ candidates: { type: 'array', items: { type: 'string' }, description: 'Candidate cause entity names' },
2523
+ maxDepth: { type: 'number', default: 6 },
2524
+ },
2525
+ required: ['effect', 'candidates'],
2526
+ additionalProperties: false,
2527
+ },
2528
+ },
2529
+ {
2530
+ name: 'find_effects',
2531
+ description: '3B.6 — Find causal chains starting at the named cause and reaching any candidate effect. Symmetric counterpart to find_causes.',
2532
+ inputSchema: {
2533
+ type: 'object',
2534
+ properties: {
2535
+ cause: { type: 'string' },
2536
+ candidates: { type: 'array', items: { type: 'string' } },
2537
+ maxDepth: { type: 'number', default: 6 },
2538
+ },
2539
+ required: ['cause', 'candidates'],
2540
+ additionalProperties: false,
2541
+ },
2542
+ },
2543
+ {
2544
+ name: 'counterfactual_query',
2545
+ description: '3B.6 — "What if we remove edge (removeFrom → removeTo)? Is predict still reachable from seed?" Returns chains from seed to predict that DO NOT use the removed edge. Pure: does not mutate the graph.',
2546
+ inputSchema: {
2547
+ type: 'object',
2548
+ properties: {
2549
+ seed: { type: 'string' },
2550
+ removeFrom: { type: 'string' },
2551
+ removeTo: { type: 'string' },
2552
+ predict: { type: 'string' },
2553
+ maxDepth: { type: 'number', default: 6 },
2554
+ },
2555
+ required: ['seed', 'removeFrom', 'removeTo', 'predict'],
2556
+ additionalProperties: false,
2557
+ },
2558
+ },
2559
+ {
2560
+ name: 'detect_causal_cycles',
2561
+ description: '3B.6 — Detect cycles in the causal subgraph rooted at seed. CAVEAT: treats prevents as a directed edge, not as logical negation — prevents+enables triangles ARE flagged.',
2562
+ inputSchema: {
2563
+ type: 'object',
2564
+ properties: {
2565
+ seed: { type: 'string' },
2566
+ maxDepth: { type: 'number', default: 6 },
2567
+ },
2568
+ required: ['seed'],
2569
+ additionalProperties: false,
2570
+ },
2571
+ },
2572
+ // ==================== 3B.7 WORLD MODEL TOOLS ====================
2573
+ {
2574
+ name: 'get_world_state',
2575
+ description: '3B.7 — Capture a fresh snapshot of the live graph: entitiesByName + takenAt timestamp + size. Capped at maxSnapshotSize (default 1000); over-cap prefers high-importance entities.',
2576
+ inputSchema: {
2577
+ type: 'object',
2578
+ properties: {},
2579
+ additionalProperties: false,
2580
+ },
2581
+ },
2582
+ {
2583
+ name: 'validate_fact_against_world',
2584
+ description: '3B.7 — Validate a candidate observation against a target entity. Delegates to MemoryValidator.validateConsistency. Returns null if no validator is wired.',
2585
+ inputSchema: {
2586
+ type: 'object',
2587
+ properties: {
2588
+ observation: { type: 'string' },
2589
+ entityName: { type: 'string' },
2590
+ },
2591
+ required: ['observation', 'entityName'],
2592
+ additionalProperties: false,
2593
+ },
2594
+ },
2595
+ {
2596
+ name: 'predict_outcome',
2597
+ description: '3B.7 — Predict downstream effects of an action by walking the causal subgraph. Delegates to CausalReasoner.findEffects.',
2598
+ inputSchema: {
2599
+ type: 'object',
2600
+ properties: {
2601
+ action: { type: 'string', description: 'Action entity name' },
2602
+ candidates: { type: 'array', items: { type: 'string' }, description: 'Candidate effect entity names' },
2603
+ },
2604
+ required: ['action', 'candidates'],
2605
+ additionalProperties: false,
2606
+ },
2607
+ },
1033
2608
  ];
1034
2609
  // Tool categories are documented in CLAUDE.md for reference:
1035
2610
  // - Entity Operations: create_entities, delete_entities, read_graph, open_nodes