@neruva/mcp 0.16.3 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/server.js CHANGED
@@ -394,363 +394,17 @@ const TOOLS = [
394
394
  },
395
395
  },
396
396
  // ==================================================================
397
- // Memory index (legacy vector layer) -- migration on-ramp; records_* preferred.
397
+ // ===== REMOVED in MCP 0.18.0 =====
398
+ // memory_* (vector-index legacy surface) -- REST still serves them at
399
+ // /v1/indexes/* for back-compat; not surfaced via MCP because records_*
400
+ // is strictly better (typed kinds + tags + semantic query in one call).
401
+ //
402
+ // agent_plan_cache_save/lookup + agent_postmortem -- dead Computer/Code
403
+ // agent wedge per pivot 23373 (2026-05-18).
404
+ //
405
+ // hd_kg_add_fact -- strictly dominated by hd_kg_add_facts (batch). Use
406
+ // the batch version for both single + multi-fact writes.
398
407
  // ==================================================================
399
- {
400
- name: "memory_embed",
401
- description: "Encode one or more texts to L2-normalized D=1024 float vectors " +
402
- "using the server-side static-MRL encoder. Use this for memory_upsert " +
403
- "and memory_query when you don't have a local encoder. ~7000 texts/sec " +
404
- "on the hosted instance; first call adds ~5s for model load.",
405
- inputSchema: {
406
- type: "object",
407
- properties: {
408
- texts: {
409
- type: "array",
410
- items: { type: "string" },
411
- description: "Texts to embed (any length; truncated at ~512 tokens internally)",
412
- },
413
- },
414
- required: ["texts"],
415
- },
416
- },
417
- {
418
- name: "memory_upsert_text",
419
- description: "Embed and upsert text in a single call -- the all-in-one for new " +
420
- "users. Server runs static-MRL D=1024 internally; you don't need " +
421
- "an embedder. Each item: {id, text, metadata?}. The original text " +
422
- "is auto-stored into metadata.text for round-trip.",
423
- inputSchema: {
424
- type: "object",
425
- properties: {
426
- index: { type: "string" },
427
- namespace: { type: "string", default: "" },
428
- items: {
429
- type: "array",
430
- items: {
431
- type: "object",
432
- properties: {
433
- id: { type: "string" },
434
- text: { type: "string" },
435
- metadata: { type: "object" },
436
- },
437
- required: ["id", "text"],
438
- },
439
- },
440
- },
441
- required: ["index", "items"],
442
- },
443
- },
444
- {
445
- name: "memory_query_text",
446
- description: "Embed a text query and search the namespace in a single call. " +
447
- "Returns top-K matches by cosine; metadata included by default so " +
448
- "you can read the stored text back. Pass `tags: ['foo','bar']` for a " +
449
- "convenient AND-filter on metadata.tags.",
450
- inputSchema: {
451
- type: "object",
452
- properties: {
453
- index: { type: "string" },
454
- namespace: { type: "string", default: "" },
455
- text: { type: "string" },
456
- topK: { type: "integer", default: 10 },
457
- includeMetadata: { type: "boolean", default: true },
458
- includeValues: { type: "boolean", default: false },
459
- filter: { type: "object", description: "Metadata filter ({field: value} or {field: {$eq|$gte|$lte|$in: ...}})" },
460
- tags: {
461
- type: "array", items: { type: "string" },
462
- description: "Convenience: AND-match on metadata.tags (every tag must be present)",
463
- },
464
- tagsAny: {
465
- type: "array", items: { type: "string" },
466
- description: "Convenience: ANY-match on metadata.tags (record matches if any one tag is present)",
467
- },
468
- },
469
- required: ["index", "text"],
470
- },
471
- },
472
- {
473
- name: "memory_replace_text",
474
- description: "Re-encode a new text and overwrite the existing vector + " +
475
- "metadata.text in one call. Surgical: bipolar prefilter row, " +
476
- "float rerank vector, and metadata all updated atomically. Use " +
477
- "for refactor tracking, deploy state edits, or any existing " +
478
- "memory whose content changed.",
479
- inputSchema: {
480
- type: "object",
481
- properties: {
482
- index: { type: "string" },
483
- namespace: { type: "string", default: "" },
484
- id: { type: "string" },
485
- newText: { type: "string" },
486
- },
487
- required: ["index", "id", "newText"],
488
- },
489
- },
490
- {
491
- name: "memory_forget_where",
492
- description: "Bulk-delete vectors whose metadata matches a filter. " +
493
- "Filter: {field: value} or {field: {$eq|$gte|$lte|$in: ...}}. " +
494
- "GDPR Article 17 in one call -- forget every vector tagged " +
495
- "{user_id: 'alice'} for example.",
496
- inputSchema: {
497
- type: "object",
498
- properties: {
499
- index: { type: "string" },
500
- namespace: { type: "string", default: "" },
501
- filter: { type: "object", description: "Metadata filter ({field: value} or operator-syntax)" },
502
- },
503
- required: ["index", "filter"],
504
- },
505
- },
506
- {
507
- name: "memory_bind_role",
508
- description: "Bind a named role atom onto a stored vector's bipolar prefilter " +
509
- "row. Lets you narrow future queries by compound roles like " +
510
- "[\"user\", \"from_alice\"] without a secondary index. Mutates the " +
511
- "row's prefilter; the float rerank is unchanged.",
512
- inputSchema: {
513
- type: "object",
514
- properties: {
515
- index: { type: "string" },
516
- namespace: { type: "string", default: "" },
517
- id: { type: "string", description: "Vector id to bind" },
518
- role: { type: "string", description: "Role atom name (e.g. 'user')" },
519
- },
520
- required: ["index", "id", "role"],
521
- },
522
- },
523
- {
524
- name: "memory_read_roles",
525
- description: "Approximate-unbind introspection: given a stored vector's id and " +
526
- "its original encoder vector, recover which role atoms it was " +
527
- "bound under. Pass a role_dict mapping axis names to candidate " +
528
- "role names; returns axis -> [best_role, score]. If the row was " +
529
- "bound under multiple atoms, peel known ones via the `known` arg.",
530
- inputSchema: {
531
- type: "object",
532
- properties: {
533
- index: { type: "string" },
534
- namespace: { type: "string", default: "" },
535
- id: { type: "string" },
536
- queryVector: { type: "array", items: { type: "number" } },
537
- roleDict: {
538
- type: "object",
539
- description: "Map axis_name -> list of candidate role names.",
540
- },
541
- known: {
542
- type: "array",
543
- items: { type: "string" },
544
- description: "Already-known bound roles to peel off first",
545
- },
546
- },
547
- required: ["index", "id", "queryVector", "roleDict"],
548
- },
549
- },
550
- {
551
- name: "memory_create_index",
552
- description: "Create a vector index. Required once before " +
553
- "memory_upsert / memory_query / memory_delete can be used. Idempotent " +
554
- "on existing indexes (returns the existing description).",
555
- inputSchema: {
556
- type: "object",
557
- properties: {
558
- name: { type: "string", description: "Index name" },
559
- dimension: {
560
- type: "integer",
561
- description: "Vector dimension (matches your encoder, e.g. 1024 for static-MRL)",
562
- },
563
- metric: {
564
- type: "string",
565
- enum: ["cosine", "dotproduct", "euclidean"],
566
- default: "cosine",
567
- },
568
- },
569
- required: ["name", "dimension"],
570
- },
571
- },
572
- {
573
- name: "memory_list_indexes",
574
- description: "List all indexes for your account.",
575
- inputSchema: { type: "object", properties: {}, required: [] },
576
- },
577
- {
578
- name: "memory_describe_index",
579
- description: "Describe one index (dimension, metric, host, status).",
580
- inputSchema: {
581
- type: "object",
582
- properties: { name: { type: "string" } },
583
- required: ["name"],
584
- },
585
- },
586
- {
587
- name: "memory_stats",
588
- description: "Per-namespace vector counts and total vector count for an index.",
589
- inputSchema: {
590
- type: "object",
591
- properties: { name: { type: "string" } },
592
- required: ["name"],
593
- },
594
- },
595
- {
596
- name: "memory_fetch",
597
- description: "Fetch one or more vectors by id from a namespace.",
598
- inputSchema: {
599
- type: "object",
600
- properties: {
601
- index: { type: "string" },
602
- ids: { type: "array", items: { type: "string" } },
603
- namespace: { type: "string", default: "" },
604
- },
605
- required: ["index", "ids"],
606
- },
607
- },
608
- {
609
- name: "memory_update",
610
- description: "Update one vector in a namespace -- replace its values and/or " +
611
- "metadata without re-upserting. ID must already exist.",
612
- inputSchema: {
613
- type: "object",
614
- properties: {
615
- index: { type: "string" },
616
- id: { type: "string" },
617
- values: { type: "array", items: { type: "number" } },
618
- metadata: { type: "object" },
619
- namespace: { type: "string", default: "" },
620
- },
621
- required: ["index", "id"],
622
- },
623
- },
624
- {
625
- name: "memory_export",
626
- description: "Export an index (or one namespace) to the portable .nmm format. " +
627
- "Returns base64-encoded bytes. Take your memory with you between " +
628
- "providers, environments, agents.",
629
- inputSchema: {
630
- type: "object",
631
- properties: {
632
- index: { type: "string" },
633
- namespace: {
634
- type: "string",
635
- description: "Optional namespace; omit to export the whole index.",
636
- },
637
- },
638
- required: ["index"],
639
- },
640
- },
641
- {
642
- name: "memory_import",
643
- description: "Import a previously-exported .nmm blob into an index. " +
644
- "Index must already exist with matching dimension. Pass base64-encoded " +
645
- "bytes via the `nmm_base64` field.",
646
- inputSchema: {
647
- type: "object",
648
- properties: {
649
- index: { type: "string" },
650
- nmm_base64: { type: "string" },
651
- },
652
- required: ["index", "nmm_base64"],
653
- },
654
- },
655
- {
656
- name: "memory_upsert",
657
- description: "Insert or update vectors in a Neruva Memory namespace. The index " +
658
- "must exist (create it once with memory_create_index).",
659
- inputSchema: {
660
- type: "object",
661
- properties: {
662
- index: { type: "string", description: "Index name" },
663
- namespace: {
664
- type: "string",
665
- description: "Namespace (one per agent or context); defaults to ''",
666
- default: "",
667
- },
668
- vectors: {
669
- type: "array",
670
- description: "Vectors: {id, values, metadata?}",
671
- items: {
672
- type: "object",
673
- properties: {
674
- id: { type: "string" },
675
- values: { type: "array", items: { type: "number" } },
676
- metadata: { type: "object" },
677
- },
678
- required: ["id", "values"],
679
- },
680
- },
681
- },
682
- required: ["index", "vectors"],
683
- },
684
- },
685
- {
686
- name: "memory_query",
687
- description: "Cosine-search a namespace by vector. Returns top-K matches with " +
688
- "metadata. The index must exist. Pass `tags: ['foo','bar']` for a " +
689
- "convenient AND-filter on metadata.tags (combines with `filter` if " +
690
- "both given).",
691
- inputSchema: {
692
- type: "object",
693
- properties: {
694
- index: { type: "string" },
695
- namespace: { type: "string", default: "" },
696
- vector: { type: "array", items: { type: "number" } },
697
- topK: { type: "integer", default: 10 },
698
- includeMetadata: { type: "boolean", default: true },
699
- includeValues: { type: "boolean", default: false },
700
- filter: { type: "object", description: "Metadata filter ({field: value} or {field: {$eq|$gte|$lte|$in: ...}})" },
701
- tags: {
702
- type: "array", items: { type: "string" },
703
- description: "Convenience: AND-match on metadata.tags (every tag must be present)",
704
- },
705
- tagsAny: {
706
- type: "array", items: { type: "string" },
707
- description: "Convenience: ANY-match on metadata.tags (record matches if any one tag is present)",
708
- },
709
- },
710
- required: ["index", "vector"],
711
- },
712
- },
713
- {
714
- name: "memory_delete",
715
- description: "Delete vectors by id from a namespace. The index must exist.",
716
- inputSchema: {
717
- type: "object",
718
- properties: {
719
- index: { type: "string" },
720
- namespace: { type: "string", default: "" },
721
- ids: { type: "array", items: { type: "string" } },
722
- },
723
- required: ["index", "ids"],
724
- },
725
- },
726
- {
727
- name: "hd_kg_add_fact",
728
- description: "Add a (subject, relation, object) fact to a knowledge graph. The KG " +
729
- "is auto-created on first add. Persists across restarts.\n\n" +
730
- "engine (FRESH KGs only; ignored if KG exists):\n" +
731
- " hadamard -- default; <10k facts, latency-critical.\n" +
732
- " opb -- recommended for >10k facts; 250k facts in single " +
733
- "matrix at 100% recall; supports hd_kg_derive_relation matrix-power.\n" +
734
- " multishard -- 250k-1M+ facts; auto-routes via stable hash.\n" +
735
- " quorum -- 3-shard redundant write; adversarial-resistant.\n" +
736
- " feature_bundle -- bundled-feature atoms; zero-shot generalization " +
737
- "to unseen concepts (84% on UNSEEN, requires hd_kg_assign_features).",
738
- inputSchema: {
739
- type: "object",
740
- properties: {
741
- kg: { type: "string", description: "Knowledge-graph name" },
742
- subject: { type: "string" },
743
- relation: { type: "string" },
744
- object: { type: "string" },
745
- engine: {
746
- type: "string",
747
- enum: ["hadamard", "opb", "multishard", "quorum", "feature_bundle"],
748
- description: "Fresh-KG engine selector (see tool description).",
749
- },
750
- },
751
- required: ["kg", "subject", "relation", "object"],
752
- },
753
- },
754
408
  {
755
409
  name: "hd_kg_extraction_prompt",
756
410
  description: "Return the canonical system prompt agents should run with their " +
@@ -900,36 +554,6 @@ const TOOLS = [
900
554
  required: ["namespace", "id", "tag"],
901
555
  },
902
556
  },
903
- {
904
- name: "memory_timeline",
905
- description: "Chronological scan of a vector index namespace by metadata.ts " +
906
- "(descending). Records without a ts in metadata are skipped " +
907
- "(use the Records substrate for universal timeline). Page back " +
908
- "in time by passing until=<nextCursor> from the previous response.",
909
- inputSchema: {
910
- type: "object",
911
- properties: {
912
- index: { type: "string" },
913
- namespace: { type: "string", default: "" },
914
- since: { type: "integer", description: "ts lower bound (inclusive)" },
915
- until: { type: "integer", description: "ts upper bound (exclusive); pass nextCursor to page back" },
916
- limit: { type: "integer", default: 50, minimum: 1, maximum: 500 },
917
- includeValues: { type: "boolean", default: false },
918
- },
919
- required: ["index"],
920
- },
921
- },
922
- {
923
- name: "memory_delete_index",
924
- description: "Delete a vector index AND all its namespaces. Hard delete -- " +
925
- "blobs are removed from GCS, in-memory cache evicted. Use this to " +
926
- "clean up zombie indexes from old tests / probes / abandoned namespaces.",
927
- inputSchema: {
928
- type: "object",
929
- properties: { name: { type: "string" } },
930
- required: ["name"],
931
- },
932
- },
933
557
  {
934
558
  name: "hd_kg_context",
935
559
  description: "Return a customizable context block ready to drop into an LLM prompt. " +
@@ -1423,52 +1047,6 @@ const TOOLS = [
1423
1047
  required: ["snapshot_id", "target_namespace"],
1424
1048
  },
1425
1049
  },
1426
- {
1427
- name: "agent_postmortem",
1428
- description: "Distill a failed agent run into a structured lesson + corrected " +
1429
- "plan via Magistral reasoning. Returns " +
1430
- "{failure_class, lesson, corrected_plan}. Pair with agent_remember " +
1431
- "to store the lesson back into substrate so future similar tasks " +
1432
- "see it as `LEARNED:` context. The recursive-intelligence loop: " +
1433
- "agent fails -> postmortem distills -> remember stores -> " +
1434
- "recall surfaces it on the next run, no human in the loop. " +
1435
- "failure_class is one of: tool_arg_missing | primitive_mismatch | " +
1436
- "context_drift | wrong_target | timeout | captcha_blocked | unknown.",
1437
- inputSchema: {
1438
- type: "object",
1439
- properties: {
1440
- agent: {
1441
- type: "string",
1442
- enum: ["computer", "code"],
1443
- description: "Which agent failed (computer | code).",
1444
- },
1445
- task_text: { type: "string", description: "Original task." },
1446
- plan: {
1447
- type: "array",
1448
- items: { type: "string" },
1449
- description: "Plan steps that were attempted (string repr).",
1450
- },
1451
- history: {
1452
- type: "array",
1453
- items: { type: "object" },
1454
- description: "Execution trace: [{step, result}, ...].",
1455
- },
1456
- error: {
1457
- type: "string",
1458
- description: "Final error message, if any.",
1459
- },
1460
- task_class: {
1461
- type: "string",
1462
- description: "Optional tag: web_search | calc | file_edit | ...",
1463
- },
1464
- app: {
1465
- type: "string",
1466
- description: "Optional tag: chrome | notepad | calculator | ...",
1467
- },
1468
- },
1469
- required: ["agent", "task_text"],
1470
- },
1471
- },
1472
1050
  {
1473
1051
  name: "agent_check_consistency",
1474
1052
  description: "Anomaly detection on Quorum KGs. Scans every (subject, relation) " +
@@ -1532,6 +1110,263 @@ const TOOLS = [
1532
1110
  },
1533
1111
  },
1534
1112
  },
1113
+ // ==================================================================
1114
+ // Cognitive primitives (substrate v0.4.0): counterfactual rollouts,
1115
+ // theory-of-mind, schema lifting, EFE planning, continual K-gram,
1116
+ // hierarchical chunking, few-shot rule induction + persistence.
1117
+ // ==================================================================
1118
+ {
1119
+ name: "agent_counterfactual_rollout",
1120
+ description: "Replay an action sequence with one action substituted at step_k. " +
1121
+ "Returns the predicted final factored state. Stateless. " +
1122
+ "Use when you need 'what if at step k the agent had taken action " +
1123
+ "a' instead?'.",
1124
+ inputSchema: {
1125
+ type: "object",
1126
+ properties: {
1127
+ initial_state: { type: "array", items: { type: "integer" } },
1128
+ action_seq: { type: "array", items: { type: "integer" } },
1129
+ step_k: { type: "integer", description: "Index in action_seq to substitute." },
1130
+ alternate_action: { type: "integer" },
1131
+ n_axes: { type: "integer", default: 3, minimum: 1, maximum: 16 },
1132
+ n_values: { type: "integer", default: 8, minimum: 2, maximum: 32 },
1133
+ seed: { type: "integer", default: 2047 },
1134
+ },
1135
+ required: ["initial_state", "action_seq", "step_k", "alternate_action"],
1136
+ },
1137
+ },
1138
+ {
1139
+ name: "agent_model_belief_add",
1140
+ description: "Store a nested belief in the namespace's Theory-of-Mind store. " +
1141
+ "`chain` is outer-to-inner person indices: [0,1,2] means person 0 " +
1142
+ "believes person 1 believes person 2 believes prop=val. " +
1143
+ "Per-tenant stateful (keyed by tenant_id+namespace).",
1144
+ inputSchema: {
1145
+ type: "object",
1146
+ properties: {
1147
+ tenant_id: { type: "string", default: "default" },
1148
+ namespace: { type: "string", default: "tom" },
1149
+ chain: { type: "array", items: { type: "integer" } },
1150
+ prop: { type: "integer" },
1151
+ val: { type: "integer" },
1152
+ n_people: { type: "integer", default: 10 },
1153
+ n_props: { type: "integer", default: 50 },
1154
+ n_vals: { type: "integer", default: 20 },
1155
+ max_depth: { type: "integer", default: 4 },
1156
+ seed: { type: "integer", default: 2048 },
1157
+ },
1158
+ required: ["chain", "prop", "val"],
1159
+ },
1160
+ },
1161
+ {
1162
+ name: "agent_model_belief",
1163
+ description: "Recall what the nested `chain` believes about prop. Returns " +
1164
+ "{val, confidence}. 404 if no beliefs stored in this namespace yet.",
1165
+ inputSchema: {
1166
+ type: "object",
1167
+ properties: {
1168
+ tenant_id: { type: "string", default: "default" },
1169
+ namespace: { type: "string", default: "tom" },
1170
+ chain: { type: "array", items: { type: "integer" } },
1171
+ prop: { type: "integer" },
1172
+ },
1173
+ required: ["chain", "prop"],
1174
+ },
1175
+ },
1176
+ {
1177
+ name: "agent_extract_schema",
1178
+ description: "Given (role_idx, filler_idx) pairs for one instance, return the " +
1179
+ "per-role signature score vector and the inferred role indices " +
1180
+ "above the noise threshold. Use for analogical pattern matching: " +
1181
+ "'which roles are bound in this instance?'. Per-tenant stateful.",
1182
+ inputSchema: {
1183
+ type: "object",
1184
+ properties: {
1185
+ tenant_id: { type: "string", default: "default" },
1186
+ namespace: { type: "string", default: "schema" },
1187
+ role_filler_pairs: {
1188
+ type: "array",
1189
+ items: { type: "array", items: { type: "integer" }, minItems: 2, maxItems: 2 },
1190
+ },
1191
+ n_roles: { type: "integer", default: 10 },
1192
+ n_fillers_per_role: { type: "integer", default: 100 },
1193
+ seed: { type: "integer", default: 2049 },
1194
+ },
1195
+ required: ["role_filler_pairs"],
1196
+ },
1197
+ },
1198
+ {
1199
+ name: "agent_register_action",
1200
+ description: "Register an action's add/del effects with the planner. " +
1201
+ "add_effects/del_effects are {attr_idx: probability_in_[0,1]}. " +
1202
+ "Call once per available action before agent_plan_efe. " +
1203
+ "Per-tenant stateful.",
1204
+ inputSchema: {
1205
+ type: "object",
1206
+ properties: {
1207
+ tenant_id: { type: "string", default: "default" },
1208
+ namespace: { type: "string", default: "planner" },
1209
+ action_id: { type: "integer" },
1210
+ add_effects: { type: "object", additionalProperties: { type: "number" } },
1211
+ del_effects: { type: "object", additionalProperties: { type: "number" } },
1212
+ n_attrs: { type: "integer", default: 100 },
1213
+ seed: { type: "integer", default: 6001 },
1214
+ },
1215
+ required: ["action_id"],
1216
+ },
1217
+ },
1218
+ {
1219
+ name: "agent_plan_efe",
1220
+ description: "Score candidate action sequences against goal attribute marginals " +
1221
+ "and return the one minimising KL(predicted || goal). Returns " +
1222
+ "{best_plan_index, best_kl, all_kls}. Register actions first via " +
1223
+ "agent_register_action. 400 if no actions registered.",
1224
+ inputSchema: {
1225
+ type: "object",
1226
+ properties: {
1227
+ tenant_id: { type: "string", default: "default" },
1228
+ namespace: { type: "string", default: "planner" },
1229
+ state: { type: "array", items: { type: "integer" } },
1230
+ candidate_plans: {
1231
+ type: "array",
1232
+ items: { type: "array", items: { type: "integer" } },
1233
+ },
1234
+ want_on: { type: "array", items: { type: "integer" } },
1235
+ want_off: { type: "array", items: { type: "integer" } },
1236
+ p_on: { type: "number", default: 0.95 },
1237
+ p_off: { type: "number", default: 0.05 },
1238
+ },
1239
+ required: ["state", "candidate_plans"],
1240
+ },
1241
+ },
1242
+ {
1243
+ name: "agent_continual_train",
1244
+ description: "Train a sharded K-gram next-token predictor on a token stream. " +
1245
+ "Repeated calls accumulate without forgetting earlier patterns. " +
1246
+ "Per-tenant stateful.",
1247
+ inputSchema: {
1248
+ type: "object",
1249
+ properties: {
1250
+ tenant_id: { type: "string", default: "default" },
1251
+ namespace: { type: "string", default: "continual" },
1252
+ token_stream: { type: "array", items: { type: "integer" } },
1253
+ vocab_size: { type: "integer", default: 200 },
1254
+ k: { type: "integer", default: 2, description: "K-gram order." },
1255
+ seed: { type: "integer", default: 7000 },
1256
+ },
1257
+ required: ["token_stream"],
1258
+ },
1259
+ },
1260
+ {
1261
+ name: "agent_continual_predict",
1262
+ description: "Predict the next-token sequence from a primed context using the " +
1263
+ "previously trained K-gram. Returns N-K predicted tokens. 404 if " +
1264
+ "the namespace has not been trained yet.",
1265
+ inputSchema: {
1266
+ type: "object",
1267
+ properties: {
1268
+ tenant_id: { type: "string", default: "default" },
1269
+ namespace: { type: "string", default: "continual" },
1270
+ token_stream: { type: "array", items: { type: "integer" } },
1271
+ },
1272
+ required: ["token_stream"],
1273
+ },
1274
+ },
1275
+ {
1276
+ name: "agent_hierarchical_add",
1277
+ description: "Encode a tree of L^K leaf ids under top_id (must supply exactly " +
1278
+ "L^K leaf_ids in row-major order). Lets a single top-level id " +
1279
+ "resolve to any leaf via a K-position path. Per-tenant stateful.",
1280
+ inputSchema: {
1281
+ type: "object",
1282
+ properties: {
1283
+ tenant_id: { type: "string", default: "default" },
1284
+ namespace: { type: "string", default: "hier" },
1285
+ top_id: { type: "string" },
1286
+ leaf_ids: { type: "array", items: { type: "integer" } },
1287
+ L: { type: "integer", default: 4, description: "Branching factor." },
1288
+ K: { type: "integer", default: 5, description: "Tree depth." },
1289
+ n_leaf_vocab: { type: "integer", default: 1000 },
1290
+ seed: { type: "integer", default: 2050 },
1291
+ },
1292
+ required: ["top_id", "leaf_ids"],
1293
+ },
1294
+ },
1295
+ {
1296
+ name: "agent_hierarchical_decode",
1297
+ description: "Walk a path of K position indices (outer-to-inner, each in " +
1298
+ "[0, L)) from top_id and return the leaf_id at that path. 404 " +
1299
+ "if no tree stored.",
1300
+ inputSchema: {
1301
+ type: "object",
1302
+ properties: {
1303
+ tenant_id: { type: "string", default: "default" },
1304
+ namespace: { type: "string", default: "hier" },
1305
+ top_id: { type: "string" },
1306
+ path: { type: "array", items: { type: "integer" } },
1307
+ },
1308
+ required: ["top_id", "path"],
1309
+ },
1310
+ },
1311
+ {
1312
+ name: "agent_induce_rule",
1313
+ description: "Given matched (xs, ys) demo grids, infer which named " +
1314
+ "transformation rule applies (e.g. rot90, color_invert, mirror_h). " +
1315
+ "Returns {rule_name, confidence}. Stateless. xs and ys must be " +
1316
+ "same length.",
1317
+ inputSchema: {
1318
+ type: "object",
1319
+ properties: {
1320
+ xs: {
1321
+ type: "array",
1322
+ items: { type: "array", items: { type: "array", items: { type: "integer" } } },
1323
+ },
1324
+ ys: {
1325
+ type: "array",
1326
+ items: { type: "array", items: { type: "array", items: { type: "integer" } } },
1327
+ },
1328
+ },
1329
+ required: ["xs", "ys"],
1330
+ },
1331
+ },
1332
+ {
1333
+ name: "agent_persist_rule",
1334
+ description: "Induce a rule from (xs, ys) demos AND store it under rule_id for " +
1335
+ "later recall. Returns {rule_name, confidence, n_rules_stored}. " +
1336
+ "Per-tenant stateful.",
1337
+ inputSchema: {
1338
+ type: "object",
1339
+ properties: {
1340
+ tenant_id: { type: "string", default: "default" },
1341
+ namespace: { type: "string", default: "rules" },
1342
+ rule_id: { type: "string" },
1343
+ xs: {
1344
+ type: "array",
1345
+ items: { type: "array", items: { type: "array", items: { type: "integer" } } },
1346
+ },
1347
+ ys: {
1348
+ type: "array",
1349
+ items: { type: "array", items: { type: "array", items: { type: "integer" } } },
1350
+ },
1351
+ },
1352
+ required: ["rule_id", "xs", "ys"],
1353
+ },
1354
+ },
1355
+ {
1356
+ name: "agent_recall_rule",
1357
+ description: "Recall a previously persisted rule by rule_id. Returns " +
1358
+ "{rule_name, confidence}. 404 if no rules stored in this " +
1359
+ "namespace yet.",
1360
+ inputSchema: {
1361
+ type: "object",
1362
+ properties: {
1363
+ tenant_id: { type: "string", default: "default" },
1364
+ namespace: { type: "string", default: "rules" },
1365
+ rule_id: { type: "string" },
1366
+ },
1367
+ required: ["rule_id"],
1368
+ },
1369
+ },
1535
1370
  ];
1536
1371
  const HANDLERS = {
1537
1372
  // ----- Records -----
@@ -1618,113 +1453,7 @@ const HANDLERS = {
1618
1453
  return text;
1619
1454
  }
1620
1455
  },
1621
- // ----- Memory index (legacy vector layer) -----
1622
- memory_embed: (a) => call("POST", "/v1/memory/embed", { texts: a.texts }),
1623
- memory_list_indexes: () => call("GET", "/v1/indexes"),
1624
- memory_describe_index: (a) => call("GET", `/v1/indexes/${enc(a.name)}`),
1625
- memory_stats: (a) => call("GET", `/v1/indexes/${enc(a.name)}/describe_index_stats`),
1626
- memory_fetch: (a) => {
1627
- const ids = a.ids.map(enc).join("&ids=");
1628
- const ns = a.namespace ? `&namespace=${enc(a.namespace)}` : "";
1629
- return call("GET", `/v1/indexes/${enc(a.index)}/vectors/fetch?ids=${ids}${ns}`);
1630
- },
1631
- memory_update: (a) => {
1632
- const body = { id: a.id, namespace: a.namespace ?? "" };
1633
- if (a.values !== undefined)
1634
- body.values = a.values;
1635
- // Server expects setMetadata; sending metadata is a silent no-op.
1636
- if (a.metadata !== undefined)
1637
- body.setMetadata = a.metadata;
1638
- return call("POST", `/v1/indexes/${enc(a.index)}/vectors/update`, body);
1639
- },
1640
- memory_export: async (a) => {
1641
- const ns = a.namespace !== undefined ? `?namespace=${enc(a.namespace)}` : "";
1642
- const r = await fetch(BASE_URL + `/v1/indexes/${enc(a.index)}/export${ns}`, {
1643
- method: "GET",
1644
- headers: { "Api-Key": API_KEY },
1645
- });
1646
- if (!r.ok) {
1647
- throw new Error(`GET /v1/indexes/.../export -> ${r.status}: ${await r.text()}`);
1648
- }
1649
- const buf = new Uint8Array(await r.arrayBuffer());
1650
- let bin = "";
1651
- for (let i = 0; i < buf.length; i++)
1652
- bin += String.fromCharCode(buf[i]);
1653
- return { nmm_base64: btoa(bin), bytes: buf.length };
1654
- },
1655
- memory_import: async (a) => {
1656
- const bin = atob(a.nmm_base64);
1657
- const buf = new Uint8Array(bin.length);
1658
- for (let i = 0; i < bin.length; i++)
1659
- buf[i] = bin.charCodeAt(i);
1660
- const r = await fetch(BASE_URL + `/v1/indexes/${enc(a.index)}/import`, {
1661
- method: "POST",
1662
- headers: { "Api-Key": API_KEY, "Content-Type": "application/octet-stream" },
1663
- body: buf,
1664
- });
1665
- if (!r.ok) {
1666
- throw new Error(`POST /v1/indexes/.../import -> ${r.status}: ${await r.text()}`);
1667
- }
1668
- const text = await r.text();
1669
- try {
1670
- return JSON.parse(text);
1671
- }
1672
- catch {
1673
- return text;
1674
- }
1675
- },
1676
- memory_upsert_text: (a) => call("POST", `/v1/indexes/${enc(a.index)}/text/upsert`, {
1677
- items: a.items, namespace: a.namespace ?? "",
1678
- }),
1679
- memory_query_text: (a) => call("POST", `/v1/indexes/${enc(a.index)}/text/query`, {
1680
- text: a.text,
1681
- namespace: a.namespace ?? "",
1682
- topK: a.topK ?? 10,
1683
- includeMetadata: a.includeMetadata ?? true,
1684
- includeValues: a.includeValues ?? false,
1685
- filter: _foldTags(a.filter, a.tags, a.tagsAny),
1686
- }),
1687
- memory_replace_text: (a) => call("POST", `/v1/indexes/${enc(a.index)}/text/replace`, {
1688
- id: a.id, newText: a.newText, namespace: a.namespace ?? "",
1689
- }),
1690
- memory_forget_where: (a) => call("POST", `/v1/indexes/${enc(a.index)}/vectors/delete`, {
1691
- filter: a.filter, namespace: a.namespace ?? "",
1692
- }),
1693
- memory_bind_role: (a) => call("POST", `/v1/indexes/${enc(a.index)}/roles/bind`, {
1694
- id: a.id, role: a.role, namespace: a.namespace ?? "",
1695
- }),
1696
- memory_read_roles: (a) => call("POST", `/v1/indexes/${enc(a.index)}/roles/read`, {
1697
- id: a.id,
1698
- queryVector: a.queryVector,
1699
- roleDict: a.roleDict,
1700
- known: a.known,
1701
- namespace: a.namespace ?? "",
1702
- }),
1703
- memory_create_index: (a) => call("POST", "/v1/indexes", {
1704
- name: a.name,
1705
- dimension: a.dimension,
1706
- metric: a.metric ?? "cosine",
1707
- }),
1708
- memory_upsert: (a) => call("POST", `/v1/indexes/${enc(a.index)}/vectors/upsert`, {
1709
- vectors: a.vectors,
1710
- namespace: a.namespace ?? "",
1711
- }),
1712
- memory_query: (a) => call("POST", `/v1/indexes/${enc(a.index)}/query`, {
1713
- vector: a.vector,
1714
- namespace: a.namespace ?? "",
1715
- topK: a.topK ?? 10,
1716
- includeMetadata: a.includeMetadata ?? true,
1717
- includeValues: a.includeValues ?? false,
1718
- filter: _foldTags(a.filter, a.tags, a.tagsAny),
1719
- }),
1720
- memory_delete: (a) => call("POST", `/v1/indexes/${enc(a.index)}/vectors/delete`, {
1721
- ids: a.ids,
1722
- namespace: a.namespace ?? "",
1723
- }),
1724
- hd_kg_add_fact: (a) => call("POST", `/v1/hd/kg/${enc(a.kg)}/facts`, {
1725
- facts: [{ subject: a.subject, relation: a.relation, object: a.object }],
1726
- engine: a.engine,
1727
- }),
1456
+ // ----- Memory index (legacy vector layer) -- handlers removed in 0.18.0 -----
1728
1457
  hd_kg_extraction_prompt: () => call("GET", "/v1/hd/kg/extraction_prompt"),
1729
1458
  hd_kg_add_facts: (a) => call("POST", `/v1/hd/kg/${enc(a.kg)}/facts`, {
1730
1459
  facts: a.facts, engine: a.engine,
@@ -1738,7 +1467,6 @@ const HANDLERS = {
1738
1467
  hd_scm_describe: (a) => call("GET", `/v1/hd/causal/${enc(a.scm)}/describe`),
1739
1468
  hd_cbr_list: () => call("GET", "/v1/hd/cbr"),
1740
1469
  hd_cbr_describe: (a) => call("GET", `/v1/hd/cbr/${enc(a.cbr)}/describe`),
1741
- memory_delete_index: (a) => call("DELETE", `/v1/indexes/${enc(a.name)}`),
1742
1470
  records_update: (a) => call("POST", `/v1/records/${enc(a.namespace ?? "")}/${enc(a.id)}/update`, {
1743
1471
  text: a.text,
1744
1472
  setTags: a.setTags,
@@ -1752,21 +1480,6 @@ const HANDLERS = {
1752
1480
  records_bind_tag: (a) => call("POST", `/v1/records/${enc(a.namespace ?? "")}/${enc(a.id)}/bind_tag`, {
1753
1481
  tag: a.tag,
1754
1482
  }),
1755
- memory_timeline: (a) => {
1756
- const params = new URLSearchParams();
1757
- if (a.namespace != null)
1758
- params.set("namespace", String(a.namespace));
1759
- if (a.since != null)
1760
- params.set("since", String(a.since));
1761
- if (a.until != null)
1762
- params.set("until", String(a.until));
1763
- if (a.limit != null)
1764
- params.set("limit", String(a.limit));
1765
- if (a.includeValues)
1766
- params.set("includeValues", "true");
1767
- const qs = params.toString();
1768
- return call("GET", `/v1/indexes/${enc(a.index)}/timeline${qs ? `?${qs}` : ""}`);
1769
- },
1770
1483
  hd_kg_context: (a) => call("POST", `/v1/hd/kg/${enc(a.kg)}/context`, {
1771
1484
  question: a.question,
1772
1485
  top_k: a.top_k ?? 10,
@@ -1933,15 +1646,6 @@ const HANDLERS = {
1933
1646
  snapshot_id: a.snapshot_id,
1934
1647
  target_namespace: a.target_namespace,
1935
1648
  }),
1936
- agent_postmortem: (a) => call("POST", "/v1/agent/postmortem", {
1937
- agent: a.agent,
1938
- task_text: a.task_text,
1939
- plan: a.plan ?? [],
1940
- history: a.history ?? [],
1941
- error: a.error,
1942
- task_class: a.task_class,
1943
- app: a.app,
1944
- }),
1945
1649
  agent_check_consistency: (a) => call("POST", "/v1/agent/check_consistency", {
1946
1650
  kg: a.kg,
1947
1651
  max_anomalies: a.max_anomalies ?? 100,
@@ -1951,8 +1655,108 @@ const HANDLERS = {
1951
1655
  neruva_op_stats: (a) => call("GET", `/v1/me/usage?window=${encodeURIComponent(a?.window ?? "30d")}`),
1952
1656
  neruva_keys_list: () => call("GET", "/v1/me/keys"),
1953
1657
  neruva_op_log: (a) => call("GET", `/v1/me/op_log?limit=${encodeURIComponent(String(a?.limit ?? 50))}`),
1658
+ // ----- Cognitive primitives (substrate v0.4.0) -----
1659
+ agent_counterfactual_rollout: (a) => call("POST", "/v1/agent/counterfactual_rollout", {
1660
+ initial_state: a.initial_state,
1661
+ action_seq: a.action_seq,
1662
+ step_k: a.step_k,
1663
+ alternate_action: a.alternate_action,
1664
+ n_axes: a.n_axes ?? 3,
1665
+ n_values: a.n_values ?? 8,
1666
+ seed: a.seed ?? 2047,
1667
+ }),
1668
+ agent_model_belief_add: (a) => call("POST", "/v1/agent/model_belief_add", {
1669
+ tenant_id: a.tenant_id ?? "default",
1670
+ namespace: a.namespace ?? "tom",
1671
+ chain: a.chain,
1672
+ prop: a.prop,
1673
+ val: a.val,
1674
+ n_people: a.n_people ?? 10,
1675
+ n_props: a.n_props ?? 50,
1676
+ n_vals: a.n_vals ?? 20,
1677
+ max_depth: a.max_depth ?? 4,
1678
+ seed: a.seed ?? 2048,
1679
+ }),
1680
+ agent_model_belief: (a) => call("POST", "/v1/agent/model_belief", {
1681
+ tenant_id: a.tenant_id ?? "default",
1682
+ namespace: a.namespace ?? "tom",
1683
+ chain: a.chain,
1684
+ prop: a.prop,
1685
+ }),
1686
+ agent_extract_schema: (a) => call("POST", "/v1/agent/extract_schema", {
1687
+ tenant_id: a.tenant_id ?? "default",
1688
+ namespace: a.namespace ?? "schema",
1689
+ role_filler_pairs: a.role_filler_pairs,
1690
+ n_roles: a.n_roles ?? 10,
1691
+ n_fillers_per_role: a.n_fillers_per_role ?? 100,
1692
+ seed: a.seed ?? 2049,
1693
+ }),
1694
+ agent_register_action: (a) => call("POST", "/v1/agent/register_action", {
1695
+ tenant_id: a.tenant_id ?? "default",
1696
+ namespace: a.namespace ?? "planner",
1697
+ action_id: a.action_id,
1698
+ add_effects: a.add_effects ?? {},
1699
+ del_effects: a.del_effects ?? {},
1700
+ n_attrs: a.n_attrs ?? 100,
1701
+ seed: a.seed ?? 6001,
1702
+ }),
1703
+ agent_plan_efe: (a) => call("POST", "/v1/agent/plan_efe", {
1704
+ tenant_id: a.tenant_id ?? "default",
1705
+ namespace: a.namespace ?? "planner",
1706
+ state: a.state,
1707
+ candidate_plans: a.candidate_plans,
1708
+ want_on: a.want_on ?? [],
1709
+ want_off: a.want_off ?? [],
1710
+ p_on: a.p_on ?? 0.95,
1711
+ p_off: a.p_off ?? 0.05,
1712
+ }),
1713
+ agent_continual_train: (a) => call("POST", "/v1/agent/continual_train", {
1714
+ tenant_id: a.tenant_id ?? "default",
1715
+ namespace: a.namespace ?? "continual",
1716
+ token_stream: a.token_stream,
1717
+ vocab_size: a.vocab_size ?? 200,
1718
+ k: a.k ?? 2,
1719
+ seed: a.seed ?? 7000,
1720
+ }),
1721
+ agent_continual_predict: (a) => call("POST", "/v1/agent/continual_predict", {
1722
+ tenant_id: a.tenant_id ?? "default",
1723
+ namespace: a.namespace ?? "continual",
1724
+ token_stream: a.token_stream,
1725
+ }),
1726
+ agent_hierarchical_add: (a) => call("POST", "/v1/agent/hierarchical_add", {
1727
+ tenant_id: a.tenant_id ?? "default",
1728
+ namespace: a.namespace ?? "hier",
1729
+ top_id: a.top_id,
1730
+ leaf_ids: a.leaf_ids,
1731
+ L: a.L ?? 4,
1732
+ K: a.K ?? 5,
1733
+ n_leaf_vocab: a.n_leaf_vocab ?? 1000,
1734
+ seed: a.seed ?? 2050,
1735
+ }),
1736
+ agent_hierarchical_decode: (a) => call("POST", "/v1/agent/hierarchical_decode", {
1737
+ tenant_id: a.tenant_id ?? "default",
1738
+ namespace: a.namespace ?? "hier",
1739
+ top_id: a.top_id,
1740
+ path: a.path,
1741
+ }),
1742
+ agent_induce_rule: (a) => call("POST", "/v1/agent/induce_rule", {
1743
+ xs: a.xs,
1744
+ ys: a.ys,
1745
+ }),
1746
+ agent_persist_rule: (a) => call("POST", "/v1/agent/persist_rule", {
1747
+ tenant_id: a.tenant_id ?? "default",
1748
+ namespace: a.namespace ?? "rules",
1749
+ rule_id: a.rule_id,
1750
+ xs: a.xs,
1751
+ ys: a.ys,
1752
+ }),
1753
+ agent_recall_rule: (a) => call("POST", "/v1/agent/recall_rule", {
1754
+ tenant_id: a.tenant_id ?? "default",
1755
+ namespace: a.namespace ?? "rules",
1756
+ rule_id: a.rule_id,
1757
+ }),
1954
1758
  };
1955
- const server = new Server({ name: "neruva", version: "0.16.1" }, { capabilities: { tools: {} } });
1759
+ const server = new Server({ name: "neruva", version: "0.18.0" }, { capabilities: { tools: {} } });
1956
1760
  server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: TOOLS }));
1957
1761
  server.setRequestHandler(CallToolRequestSchema, async (req) => {
1958
1762
  const name = req.params.name;