@aaronsb/kg-cli 0.6.6 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/dist/api/client.d.ts +168 -1
  2. package/dist/api/client.d.ts.map +1 -1
  3. package/dist/api/client.js +266 -0
  4. package/dist/api/client.js.map +1 -1
  5. package/dist/cli/batch.d.ts +8 -0
  6. package/dist/cli/batch.d.ts.map +1 -0
  7. package/dist/cli/batch.js +225 -0
  8. package/dist/cli/batch.js.map +1 -0
  9. package/dist/cli/commands.d.ts.map +1 -1
  10. package/dist/cli/commands.js +8 -0
  11. package/dist/cli/commands.js.map +1 -1
  12. package/dist/cli/concept.d.ts +9 -0
  13. package/dist/cli/concept.d.ts.map +1 -0
  14. package/dist/cli/concept.js +336 -0
  15. package/dist/cli/concept.js.map +1 -0
  16. package/dist/cli/edge.d.ts +9 -0
  17. package/dist/cli/edge.d.ts.map +1 -0
  18. package/dist/cli/edge.js +364 -0
  19. package/dist/cli/edge.js.map +1 -0
  20. package/dist/cli/jobs.js +111 -3
  21. package/dist/cli/jobs.js.map +1 -1
  22. package/dist/cli/ontology.d.ts.map +1 -1
  23. package/dist/cli/ontology.js +534 -1
  24. package/dist/cli/ontology.js.map +1 -1
  25. package/dist/cli/storage.d.ts +10 -0
  26. package/dist/cli/storage.d.ts.map +1 -0
  27. package/dist/cli/storage.js +260 -0
  28. package/dist/cli/storage.js.map +1 -0
  29. package/dist/cli/vocabulary/index.d.ts.map +1 -1
  30. package/dist/cli/vocabulary/index.js +1 -0
  31. package/dist/cli/vocabulary/index.js.map +1 -1
  32. package/dist/cli/vocabulary/similarity.d.ts +1 -0
  33. package/dist/cli/vocabulary/similarity.d.ts.map +1 -1
  34. package/dist/cli/vocabulary/similarity.js +60 -9
  35. package/dist/cli/vocabulary/similarity.js.map +1 -1
  36. package/dist/lib/interactive.d.ts +84 -0
  37. package/dist/lib/interactive.d.ts.map +1 -0
  38. package/dist/lib/interactive.js +296 -0
  39. package/dist/lib/interactive.js.map +1 -0
  40. package/dist/lib/validation.d.ts +106 -0
  41. package/dist/lib/validation.d.ts.map +1 -0
  42. package/dist/lib/validation.js +354 -0
  43. package/dist/lib/validation.js.map +1 -0
  44. package/dist/mcp/formatters/concept.d.ts +24 -0
  45. package/dist/mcp/formatters/concept.d.ts.map +1 -0
  46. package/dist/mcp/formatters/concept.js +243 -0
  47. package/dist/mcp/formatters/concept.js.map +1 -0
  48. package/dist/mcp/formatters/document.d.ts +25 -0
  49. package/dist/mcp/formatters/document.d.ts.map +1 -0
  50. package/dist/mcp/formatters/document.js +178 -0
  51. package/dist/mcp/formatters/document.js.map +1 -0
  52. package/dist/mcp/formatters/epistemic.d.ts +16 -0
  53. package/dist/mcp/formatters/epistemic.d.ts.map +1 -0
  54. package/dist/mcp/formatters/epistemic.js +269 -0
  55. package/dist/mcp/formatters/epistemic.js.map +1 -0
  56. package/dist/mcp/formatters/graph.d.ts +63 -0
  57. package/dist/mcp/formatters/graph.d.ts.map +1 -0
  58. package/dist/mcp/formatters/graph.js +220 -0
  59. package/dist/mcp/formatters/graph.js.map +1 -0
  60. package/dist/mcp/formatters/index.d.ts +19 -0
  61. package/dist/mcp/formatters/index.d.ts.map +1 -0
  62. package/dist/mcp/formatters/index.js +73 -0
  63. package/dist/mcp/formatters/index.js.map +1 -0
  64. package/dist/mcp/formatters/ingest.d.ts +16 -0
  65. package/dist/mcp/formatters/ingest.d.ts.map +1 -0
  66. package/dist/mcp/formatters/ingest.js +169 -0
  67. package/dist/mcp/formatters/ingest.js.map +1 -0
  68. package/dist/mcp/formatters/job.d.ts +13 -0
  69. package/dist/mcp/formatters/job.d.ts.map +1 -0
  70. package/dist/mcp/formatters/job.js +204 -0
  71. package/dist/mcp/formatters/job.js.map +1 -0
  72. package/dist/mcp/formatters/ontology.d.ts +93 -0
  73. package/dist/mcp/formatters/ontology.d.ts.map +1 -0
  74. package/dist/mcp/formatters/ontology.js +328 -0
  75. package/dist/mcp/formatters/ontology.js.map +1 -0
  76. package/dist/mcp/formatters/source.d.ts +19 -0
  77. package/dist/mcp/formatters/source.d.ts.map +1 -0
  78. package/dist/mcp/formatters/source.js +182 -0
  79. package/dist/mcp/formatters/source.js.map +1 -0
  80. package/dist/mcp/formatters/system.d.ts +10 -0
  81. package/dist/mcp/formatters/system.d.ts.map +1 -0
  82. package/dist/mcp/formatters/system.js +152 -0
  83. package/dist/mcp/formatters/system.js.map +1 -0
  84. package/dist/mcp/formatters/utils.d.ts +17 -0
  85. package/dist/mcp/formatters/utils.d.ts.map +1 -0
  86. package/dist/mcp/formatters/utils.js +55 -0
  87. package/dist/mcp/formatters/utils.js.map +1 -0
  88. package/dist/mcp/graph-operations.d.ts +242 -0
  89. package/dist/mcp/graph-operations.d.ts.map +1 -0
  90. package/dist/mcp/graph-operations.js +532 -0
  91. package/dist/mcp/graph-operations.js.map +1 -0
  92. package/dist/mcp-server.js +625 -37
  93. package/dist/mcp-server.js.map +1 -1
  94. package/dist/types/index.d.ts +289 -0
  95. package/dist/types/index.d.ts.map +1 -1
  96. package/dist/version.d.ts +3 -3
  97. package/dist/version.js +3 -3
  98. package/dist/version.js.map +1 -1
  99. package/package.json +1 -1
  100. package/dist/mcp/formatters.d.ts +0 -100
  101. package/dist/mcp/formatters.d.ts.map +0 -1
  102. package/dist/mcp/formatters.js +0 -1411
  103. package/dist/mcp/formatters.js.map +0 -1
@@ -49,7 +49,8 @@ const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
49
49
  const client_js_1 = require("./api/client.js");
50
50
  const auth_client_js_1 = require("./lib/auth/auth-client.js");
51
51
  const mcp_allowlist_js_1 = require("./lib/mcp-allowlist.js");
52
- const formatters_js_1 = require("./mcp/formatters.js");
52
+ const index_js_2 = require("./mcp/formatters/index.js");
53
+ const graph_operations_js_1 = require("./mcp/graph-operations.js");
53
54
  const fs = __importStar(require("fs"));
54
55
  const path = __importStar(require("path"));
55
56
  const package_json_1 = __importDefault(require("../package.json"));
@@ -389,46 +390,135 @@ PERFORMANCE CRITICAL: For "connect" action, use threshold >= 0.75 to avoid datab
389
390
  properties: {
390
391
  action: {
391
392
  type: 'string',
392
- enum: ['list', 'info', 'files', 'delete'],
393
- description: 'Operation: "list" (all ontologies), "info" (details), "files" (source files), "delete" (remove)',
393
+ enum: ['list', 'info', 'files', 'create', 'rename', 'delete', 'lifecycle', 'scores', 'score', 'score_all', 'candidates', 'affinity', 'edges', 'reassign', 'dissolve', 'proposals', 'proposal_review', 'annealing_cycle'],
394
+ description: 'Operation: "list" (all ontologies), "info" (details), "files" (source files), "create" (new ontology), "rename" (change name), "delete" (remove), "lifecycle" (set state), "scores" (cached scores), "score" (recompute one), "score_all" (recompute all), "candidates" (top concepts), "affinity" (cross-ontology overlap), "edges" (ontology-to-ontology edges), "reassign" (move sources), "dissolve" (non-destructive demotion), "proposals" (list annealing proposals), "proposal_review" (approve/reject proposal), "annealing_cycle" (trigger annealing cycle)',
394
395
  },
395
396
  ontology_name: {
396
397
  type: 'string',
397
- description: 'Ontology name (required for info, files, delete)',
398
+ description: 'Ontology name (required for info, files, create, rename, delete)',
399
+ },
400
+ description: {
401
+ type: 'string',
402
+ description: 'What this knowledge domain covers (for create action)',
403
+ },
404
+ new_name: {
405
+ type: 'string',
406
+ description: 'New ontology name (required for rename action)',
407
+ },
408
+ lifecycle_state: {
409
+ type: 'string',
410
+ enum: ['active', 'pinned', 'frozen'],
411
+ description: 'Target lifecycle state (required for lifecycle action)',
398
412
  },
399
413
  force: {
400
414
  type: 'boolean',
401
415
  description: 'Confirm deletion (required for delete)',
402
416
  default: false,
403
417
  },
418
+ target_ontology: {
419
+ type: 'string',
420
+ description: 'Target ontology for reassign/dissolve actions',
421
+ },
422
+ source_ids: {
423
+ type: 'array',
424
+ items: { type: 'string' },
425
+ description: 'Source IDs to move (for reassign action)',
426
+ },
427
+ limit: {
428
+ type: 'number',
429
+ description: 'Max results for candidates/affinity (default: 20/10)',
430
+ },
431
+ proposal_id: {
432
+ type: 'number',
433
+ description: 'Proposal ID (for proposal_review action)',
434
+ },
435
+ status: {
436
+ type: 'string',
437
+ enum: ['pending', 'approved', 'rejected', 'executing', 'executed', 'failed'],
438
+ description: 'Filter proposals by status, or review status (approved/rejected)',
439
+ },
440
+ proposal_type: {
441
+ type: 'string',
442
+ enum: ['promotion', 'demotion'],
443
+ description: 'Filter proposals by type',
444
+ },
445
+ notes: {
446
+ type: 'string',
447
+ description: 'Review notes (for proposal_review action)',
448
+ },
449
+ dry_run: {
450
+ type: 'boolean',
451
+ description: 'Preview candidates without proposals (for annealing_cycle)',
452
+ default: false,
453
+ },
454
+ demotion_threshold: {
455
+ type: 'number',
456
+ description: 'Protection score below which to consider demotion (default: 0.15)',
457
+ },
458
+ promotion_min_degree: {
459
+ type: 'number',
460
+ description: 'Minimum concept degree for promotion candidacy (default: 10)',
461
+ },
462
+ max_proposals: {
463
+ type: 'number',
464
+ description: 'Maximum proposals per annealing cycle (default: 5)',
465
+ },
404
466
  },
405
467
  required: ['action'],
406
468
  },
407
469
  },
408
470
  {
409
471
  name: 'job',
410
- description: 'Manage ingestion jobs: get status, list jobs, approve, or cancel. Use action parameter to specify operation.',
472
+ description: 'Manage ingestion jobs: get status, list jobs, approve, cancel, delete, or cleanup. Use action parameter to specify operation.',
411
473
  inputSchema: {
412
474
  type: 'object',
413
475
  properties: {
414
476
  action: {
415
477
  type: 'string',
416
- enum: ['status', 'list', 'approve', 'cancel'],
417
- description: 'Operation: "status" (get job status), "list" (list jobs), "approve" (approve job), "cancel" (cancel job)',
478
+ enum: ['status', 'list', 'approve', 'cancel', 'delete', 'cleanup'],
479
+ description: 'Operation: "status" (get job status), "list" (list jobs), "approve" (approve job), "cancel" (cancel job), "delete" (permanently delete single job), "cleanup" (delete jobs matching filters)',
418
480
  },
419
481
  job_id: {
420
482
  type: 'string',
421
- description: 'Job ID (required for status, approve, cancel)',
483
+ description: 'Job ID (required for status, approve, cancel, delete)',
422
484
  },
423
485
  status: {
424
486
  type: 'string',
425
- description: 'Filter by status for list (pending, awaiting_approval, running, completed, failed)',
487
+ description: 'Filter by status for list/cleanup (pending, awaiting_approval, running, completed, failed)',
426
488
  },
427
489
  limit: {
428
490
  type: 'number',
429
491
  description: 'Max jobs to return for list (default: 50)',
430
492
  default: 50,
431
493
  },
494
+ force: {
495
+ type: 'boolean',
496
+ description: 'Force delete even if job is processing (for delete action)',
497
+ default: false,
498
+ },
499
+ system_only: {
500
+ type: 'boolean',
501
+ description: 'Only delete system/scheduled jobs (for cleanup action)',
502
+ default: false,
503
+ },
504
+ older_than: {
505
+ type: 'string',
506
+ description: 'Delete jobs older than duration: 1h, 24h, 7d, 30d (for cleanup action)',
507
+ },
508
+ job_type: {
509
+ type: 'string',
510
+ description: 'Filter by job type for cleanup (ingestion, epistemic_remeasurement, projection, etc)',
511
+ },
512
+ dry_run: {
513
+ type: 'boolean',
514
+ description: 'Preview what would be deleted without deleting (for cleanup, default: true)',
515
+ default: true,
516
+ },
517
+ confirm: {
518
+ type: 'boolean',
519
+ description: 'Confirm deletion - set to true to actually delete (for cleanup action)',
520
+ default: false,
521
+ },
432
522
  },
433
523
  required: ['action'],
434
524
  },
@@ -749,6 +839,193 @@ Use search tool with type="documents" to find documents semantically.`,
749
839
  required: ['action'],
750
840
  },
751
841
  },
842
+ // ADR-089 Phase 3a: Graph CRUD Tool
843
+ {
844
+ name: 'graph',
845
+ description: `Create, edit, delete, and list concepts and edges in the knowledge graph (ADR-089).
846
+
847
+ This tool provides deterministic graph editing without going through the LLM ingest pipeline.
848
+ Use for manual curation, agent-driven knowledge building, and precise graph manipulation.
849
+
850
+ **Actions:**
851
+ - "create": Create a new concept or edge
852
+ - "edit": Update an existing concept or edge
853
+ - "delete": Delete a concept or edge
854
+ - "list": List concepts or edges with filters
855
+
856
+ **Entity Types:**
857
+ - "concept": Knowledge graph concepts (nodes)
858
+ - "edge": Relationships between concepts
859
+
860
+ **Matching Modes (for create):**
861
+ - "auto": Link to existing if match found, create if not (default)
862
+ - "force_create": Always create new, even if similar exists
863
+ - "match_only": Only link to existing, error if no match
864
+
865
+ **Semantic Resolution:**
866
+ - Use \`from_label\`/\`to_label\` to reference concepts by name instead of ID
867
+ - Resolution uses vector similarity (85% threshold) to find matching concepts
868
+
869
+ **Examples:**
870
+ - Create concept: \`{action: "create", entity: "concept", label: "CAP Theorem", ontology: "distributed-systems"}\`
871
+ - Create edge: \`{action: "create", entity: "edge", from_label: "CAP Theorem", to_label: "Partition Tolerance", relationship_type: "REQUIRES"}\`
872
+ - List concepts: \`{action: "list", entity: "concept", ontology: "distributed-systems"}\`
873
+ - Delete concept: \`{action: "delete", entity: "concept", concept_id: "c_abc123"}\`
874
+
875
+ **Queue Mode** (batch multiple operations in one call):
876
+ \`\`\`json
877
+ {
878
+ "action": "queue",
879
+ "operations": [
880
+ {"op": "create", "entity": "concept", "label": "A", "ontology": "test"},
881
+ {"op": "create", "entity": "concept", "label": "B", "ontology": "test"},
882
+ {"op": "create", "entity": "edge", "from_label": "A", "to_label": "B", "relationship_type": "IMPLIES"}
883
+ ]
884
+ }
885
+ \`\`\`
886
+ Queue executes sequentially, stops on first error (unless continue_on_error=true). Max 20 operations.`,
887
+ inputSchema: {
888
+ type: 'object',
889
+ properties: {
890
+ action: {
891
+ type: 'string',
892
+ enum: ['create', 'edit', 'delete', 'list', 'queue'],
893
+ description: 'Operation to perform. Use "queue" to batch multiple operations.',
894
+ },
895
+ entity: {
896
+ type: 'string',
897
+ enum: ['concept', 'edge'],
898
+ description: 'Entity type (required for create/edit/delete/list, not for queue)',
899
+ },
900
+ // Queue fields
901
+ operations: {
902
+ type: 'array',
903
+ items: {
904
+ type: 'object',
905
+ properties: {
906
+ op: { type: 'string', enum: ['create', 'edit', 'delete', 'list'], description: 'Operation' },
907
+ entity: { type: 'string', enum: ['concept', 'edge'] },
908
+ label: { type: 'string' },
909
+ ontology: { type: 'string' },
910
+ description: { type: 'string' },
911
+ search_terms: { type: 'array', items: { type: 'string' } },
912
+ matching_mode: { type: 'string', enum: ['auto', 'force_create', 'match_only'] },
913
+ concept_id: { type: 'string' },
914
+ from_concept_id: { type: 'string' },
915
+ to_concept_id: { type: 'string' },
916
+ from_label: { type: 'string' },
917
+ to_label: { type: 'string' },
918
+ relationship_type: { type: 'string' },
919
+ category: { type: 'string' },
920
+ confidence: { type: 'number' },
921
+ limit: { type: 'number' },
922
+ offset: { type: 'number' },
923
+ cascade: { type: 'boolean' },
924
+ },
925
+ required: ['op', 'entity'],
926
+ },
927
+ description: 'Array of operations for queue action (max 20). Each has op, entity, and action-specific fields.',
928
+ },
929
+ continue_on_error: {
930
+ type: 'boolean',
931
+ description: 'For queue: continue executing after errors (default: false, stop on first error)',
932
+ default: false,
933
+ },
934
+ // Concept fields
935
+ label: {
936
+ type: 'string',
937
+ description: 'Concept label (required for create concept)',
938
+ },
939
+ ontology: {
940
+ type: 'string',
941
+ description: 'Ontology/namespace (required for create concept, optional filter for list)',
942
+ },
943
+ description: {
944
+ type: 'string',
945
+ description: 'Concept description (optional)',
946
+ },
947
+ search_terms: {
948
+ type: 'array',
949
+ items: { type: 'string' },
950
+ description: 'Alternative search terms for the concept',
951
+ },
952
+ matching_mode: {
953
+ type: 'string',
954
+ enum: ['auto', 'force_create', 'match_only'],
955
+ description: 'How to handle similar existing concepts (default: auto)',
956
+ default: 'auto',
957
+ },
958
+ // Edge fields
959
+ from_concept_id: {
960
+ type: 'string',
961
+ description: 'Source concept ID (for edge create/delete)',
962
+ },
963
+ to_concept_id: {
964
+ type: 'string',
965
+ description: 'Target concept ID (for edge create/delete)',
966
+ },
967
+ from_label: {
968
+ type: 'string',
969
+ description: 'Source concept by label (semantic resolution)',
970
+ },
971
+ to_label: {
972
+ type: 'string',
973
+ description: 'Target concept by label (semantic resolution)',
974
+ },
975
+ relationship_type: {
976
+ type: 'string',
977
+ description: 'Edge relationship type (e.g., IMPLIES, SUPPORTS, CONTRADICTS)',
978
+ },
979
+ category: {
980
+ type: 'string',
981
+ enum: ['logical_truth', 'causal', 'structural', 'temporal', 'comparative', 'functional', 'definitional'],
982
+ description: 'Semantic category of the relationship (default: structural)',
983
+ default: 'structural',
984
+ },
985
+ confidence: {
986
+ type: 'number',
987
+ description: 'Edge confidence 0.0-1.0 (default: 1.0)',
988
+ default: 1.0,
989
+ },
990
+ // Identifiers for edit/delete
991
+ concept_id: {
992
+ type: 'string',
993
+ description: 'Concept ID (for edit/delete concept)',
994
+ },
995
+ // List filters
996
+ label_contains: {
997
+ type: 'string',
998
+ description: 'Filter concepts by label substring (for list)',
999
+ },
1000
+ creation_method: {
1001
+ type: 'string',
1002
+ description: 'Filter by creation method (for list)',
1003
+ },
1004
+ source: {
1005
+ type: 'string',
1006
+ description: 'Filter edges by source (for list)',
1007
+ },
1008
+ // Pagination
1009
+ limit: {
1010
+ type: 'number',
1011
+ description: 'Max results to return (default: 20)',
1012
+ default: 20,
1013
+ },
1014
+ offset: {
1015
+ type: 'number',
1016
+ description: 'Number to skip for pagination (default: 0)',
1017
+ default: 0,
1018
+ },
1019
+ // Delete option
1020
+ cascade: {
1021
+ type: 'boolean',
1022
+ description: 'For concept delete: also delete orphaned synthetic sources (default: false)',
1023
+ default: false,
1024
+ },
1025
+ },
1026
+ required: ['action'],
1027
+ },
1028
+ },
752
1029
  ],
753
1030
  };
754
1031
  });
@@ -806,7 +1083,7 @@ server.setRequestHandler(types_js_1.ReadResourceRequestSchema, async (request) =
806
1083
  contents: [{
807
1084
  uri,
808
1085
  mimeType: 'text/plain',
809
- text: (0, formatters_js_1.formatDatabaseStats)(result)
1086
+ text: (0, index_js_2.formatDatabaseStats)(result)
810
1087
  }]
811
1088
  };
812
1089
  }
@@ -816,7 +1093,7 @@ server.setRequestHandler(types_js_1.ReadResourceRequestSchema, async (request) =
816
1093
  contents: [{
817
1094
  uri,
818
1095
  mimeType: 'text/plain',
819
- text: (0, formatters_js_1.formatDatabaseInfo)(result)
1096
+ text: (0, index_js_2.formatDatabaseInfo)(result)
820
1097
  }]
821
1098
  };
822
1099
  }
@@ -826,7 +1103,7 @@ server.setRequestHandler(types_js_1.ReadResourceRequestSchema, async (request) =
826
1103
  contents: [{
827
1104
  uri,
828
1105
  mimeType: 'text/plain',
829
- text: (0, formatters_js_1.formatDatabaseHealth)(result)
1106
+ text: (0, index_js_2.formatDatabaseHealth)(result)
830
1107
  }]
831
1108
  };
832
1109
  }
@@ -836,7 +1113,7 @@ server.setRequestHandler(types_js_1.ReadResourceRequestSchema, async (request) =
836
1113
  contents: [{
837
1114
  uri,
838
1115
  mimeType: 'text/plain',
839
- text: (0, formatters_js_1.formatSystemStatus)(result)
1116
+ text: (0, index_js_2.formatSystemStatus)(result)
840
1117
  }]
841
1118
  };
842
1119
  }
@@ -846,7 +1123,7 @@ server.setRequestHandler(types_js_1.ReadResourceRequestSchema, async (request) =
846
1123
  contents: [{
847
1124
  uri,
848
1125
  mimeType: 'text/plain',
849
- text: (0, formatters_js_1.formatApiHealth)(result)
1126
+ text: (0, index_js_2.formatApiHealth)(result)
850
1127
  }]
851
1128
  };
852
1129
  }
@@ -858,7 +1135,7 @@ server.setRequestHandler(types_js_1.ReadResourceRequestSchema, async (request) =
858
1135
  contents: [{
859
1136
  uri,
860
1137
  mimeType: 'text/plain',
861
- text: (0, formatters_js_1.formatMcpAllowedPaths)({
1138
+ text: (0, index_js_2.formatMcpAllowedPaths)({
862
1139
  configured: false,
863
1140
  message: 'Allowlist not initialized. Run: kg mcp-config init-allowlist',
864
1141
  hint: 'Initialize with default safe patterns for .md, .txt, .pdf, .png, .jpg files'
@@ -870,7 +1147,7 @@ server.setRequestHandler(types_js_1.ReadResourceRequestSchema, async (request) =
870
1147
  contents: [{
871
1148
  uri,
872
1149
  mimeType: 'text/plain',
873
- text: (0, formatters_js_1.formatMcpAllowedPaths)({
1150
+ text: (0, index_js_2.formatMcpAllowedPaths)({
874
1151
  configured: true,
875
1152
  version: config.version,
876
1153
  allowed_directories: config.allowed_directories,
@@ -948,7 +1225,7 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
948
1225
  include_concepts: true,
949
1226
  include_full_text: true,
950
1227
  });
951
- const formattedText = (0, formatters_js_1.formatSourceSearchResults)(result);
1228
+ const formattedText = (0, index_js_2.formatSourceSearchResults)(result);
952
1229
  return {
953
1230
  content: [{ type: 'text', text: formattedText }],
954
1231
  };
@@ -963,7 +1240,7 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
963
1240
  });
964
1241
  // Add query to result for formatting
965
1242
  const resultWithQuery = { ...result, query };
966
- const formattedText = (0, formatters_js_1.formatDocumentSearchResults)(resultWithQuery);
1243
+ const formattedText = (0, index_js_2.formatDocumentSearchResults)(resultWithQuery);
967
1244
  return {
968
1245
  content: [{ type: 'text', text: formattedText }],
969
1246
  };
@@ -980,7 +1257,7 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
980
1257
  include_diversity: true,
981
1258
  diversity_max_hops: 2,
982
1259
  });
983
- const formattedText = (0, formatters_js_1.formatSearchResults)(result);
1260
+ const formattedText = (0, index_js_2.formatSearchResults)(result);
984
1261
  return {
985
1262
  content: [{ type: 'text', text: formattedText }],
986
1263
  };
@@ -995,7 +1272,7 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
995
1272
  const diversityMaxHops = toolArgs.diversity_max_hops || 2;
996
1273
  const truncateEvidence = toolArgs.truncate_evidence !== false; // Default true
997
1274
  const result = await client.getConceptDetails(toolArgs.concept_id, includeGrounding, includeDiversity, diversityMaxHops);
998
- const formattedText = (0, formatters_js_1.formatConceptDetails)(result, truncateEvidence);
1275
+ const formattedText = (0, index_js_2.formatConceptDetails)(result, truncateEvidence);
999
1276
  return {
1000
1277
  content: [{ type: 'text', text: formattedText }],
1001
1278
  };
@@ -1009,7 +1286,7 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
1009
1286
  include_epistemic_status: toolArgs.include_epistemic_status,
1010
1287
  exclude_epistemic_status: toolArgs.exclude_epistemic_status,
1011
1288
  });
1012
- const formattedText = (0, formatters_js_1.formatRelatedConcepts)(result);
1289
+ const formattedText = (0, index_js_2.formatRelatedConcepts)(result);
1013
1290
  return {
1014
1291
  content: [{ type: 'text', text: formattedText }],
1015
1292
  };
@@ -1045,7 +1322,7 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
1045
1322
  include_epistemic_status: toolArgs.include_epistemic_status,
1046
1323
  exclude_epistemic_status: toolArgs.exclude_epistemic_status,
1047
1324
  });
1048
- const formattedText = (0, formatters_js_1.formatConnectionPaths)(result);
1325
+ const formattedText = (0, index_js_2.formatConnectionPaths)(result);
1049
1326
  return {
1050
1327
  content: [{ type: 'text', text: formattedText }],
1051
1328
  };
@@ -1061,13 +1338,13 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
1061
1338
  case 'list': {
1062
1339
  const result = await client.listOntologies();
1063
1340
  return {
1064
- content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
1341
+ content: [{ type: 'text', text: (0, index_js_2.formatOntologyList)(result) }],
1065
1342
  };
1066
1343
  }
1067
1344
  case 'info': {
1068
1345
  const result = await client.getOntologyInfo(toolArgs.ontology_name);
1069
1346
  return {
1070
- content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
1347
+ content: [{ type: 'text', text: (0, index_js_2.formatOntologyInfo)(result) }],
1071
1348
  };
1072
1349
  }
1073
1350
  case 'files': {
@@ -1076,12 +1353,111 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
1076
1353
  content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
1077
1354
  };
1078
1355
  }
1356
+ case 'create': {
1357
+ const result = await client.createOntology(toolArgs.ontology_name, toolArgs.description || '');
1358
+ return {
1359
+ content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
1360
+ };
1361
+ }
1362
+ case 'rename': {
1363
+ const result = await client.renameOntology(toolArgs.ontology_name, toolArgs.new_name);
1364
+ return {
1365
+ content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
1366
+ };
1367
+ }
1368
+ case 'lifecycle': {
1369
+ const result = await client.updateOntologyLifecycle(toolArgs.ontology_name, toolArgs.lifecycle_state);
1370
+ return {
1371
+ content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
1372
+ };
1373
+ }
1079
1374
  case 'delete': {
1080
1375
  const result = await client.deleteOntology(toolArgs.ontology_name, toolArgs.force || false);
1081
1376
  return {
1082
1377
  content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
1083
1378
  };
1084
1379
  }
1380
+ // ADR-200 Phase 3a: Scoring & Annealing Control Surface
1381
+ case 'scores': {
1382
+ const result = await client.getOntologyScores(toolArgs.ontology_name);
1383
+ return {
1384
+ content: [{ type: 'text', text: (0, index_js_2.formatOntologyScores)(result) }],
1385
+ };
1386
+ }
1387
+ case 'score': {
1388
+ const result = await client.computeOntologyScores(toolArgs.ontology_name);
1389
+ return {
1390
+ content: [{ type: 'text', text: (0, index_js_2.formatOntologyScores)(result) }],
1391
+ };
1392
+ }
1393
+ case 'score_all': {
1394
+ const result = await client.computeAllOntologyScores();
1395
+ return {
1396
+ content: [{ type: 'text', text: (0, index_js_2.formatOntologyScores)(result) }],
1397
+ };
1398
+ }
1399
+ case 'candidates': {
1400
+ const result = await client.getOntologyCandidates(toolArgs.ontology_name, toolArgs.limit || 20);
1401
+ return {
1402
+ content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
1403
+ };
1404
+ }
1405
+ case 'affinity': {
1406
+ const result = await client.getOntologyAffinity(toolArgs.ontology_name, toolArgs.limit || 10);
1407
+ return {
1408
+ content: [{ type: 'text', text: (0, index_js_2.formatOntologyAffinity)(result) }],
1409
+ };
1410
+ }
1411
+ case 'edges': {
1412
+ const result = await client.getOntologyEdges(toolArgs.ontology_name);
1413
+ return {
1414
+ content: [{ type: 'text', text: (0, index_js_2.formatOntologyEdges)(result) }],
1415
+ };
1416
+ }
1417
+ case 'reassign': {
1418
+ const result = await client.reassignSources(toolArgs.ontology_name, toolArgs.target_ontology, toolArgs.source_ids);
1419
+ return {
1420
+ content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
1421
+ };
1422
+ }
1423
+ case 'dissolve': {
1424
+ const result = await client.dissolveOntology(toolArgs.ontology_name, toolArgs.target_ontology);
1425
+ return {
1426
+ content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
1427
+ };
1428
+ }
1429
+ case 'proposals': {
1430
+ const result = await client.listProposals({
1431
+ status: toolArgs.status,
1432
+ proposal_type: toolArgs.proposal_type,
1433
+ ontology: toolArgs.ontology_name,
1434
+ limit: toolArgs.limit,
1435
+ });
1436
+ return {
1437
+ content: [{ type: 'text', text: (0, index_js_2.formatProposalList)(result) }],
1438
+ };
1439
+ }
1440
+ case 'proposal_review': {
1441
+ const reviewStatus = toolArgs.status;
1442
+ if (!reviewStatus || !['approved', 'rejected'].includes(reviewStatus)) {
1443
+ throw new Error('proposal_review requires status: "approved" or "rejected"');
1444
+ }
1445
+ const result = await client.reviewProposal(toolArgs.proposal_id, reviewStatus, toolArgs.notes);
1446
+ return {
1447
+ content: [{ type: 'text', text: (0, index_js_2.formatProposalDetail)(result) }],
1448
+ };
1449
+ }
1450
+ case 'annealing_cycle': {
1451
+ const result = await client.triggerAnnealingCycle({
1452
+ dry_run: toolArgs.dry_run,
1453
+ demotion_threshold: toolArgs.demotion_threshold,
1454
+ promotion_min_degree: toolArgs.promotion_min_degree,
1455
+ max_proposals: toolArgs.max_proposals,
1456
+ });
1457
+ return {
1458
+ content: [{ type: 'text', text: (0, index_js_2.formatAnnealingCycleResult)(result) }],
1459
+ };
1460
+ }
1085
1461
  default:
1086
1462
  throw new Error(`Unknown ontology action: ${action}`);
1087
1463
  }
@@ -1091,14 +1467,14 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
1091
1467
  switch (action) {
1092
1468
  case 'status': {
1093
1469
  const result = await client.getJobStatus(toolArgs.job_id);
1094
- const formattedText = (0, formatters_js_1.formatJobStatus)(result);
1470
+ const formattedText = (0, index_js_2.formatJobStatus)(result);
1095
1471
  return {
1096
1472
  content: [{ type: 'text', text: formattedText }],
1097
1473
  };
1098
1474
  }
1099
1475
  case 'list': {
1100
1476
  const result = await client.listJobs(toolArgs.status, undefined, toolArgs.limit || 50);
1101
- const formattedText = (0, formatters_js_1.formatJobList)(result);
1477
+ const formattedText = (0, index_js_2.formatJobList)(result);
1102
1478
  return {
1103
1479
  content: [{ type: 'text', text: formattedText }],
1104
1480
  };
@@ -1115,6 +1491,49 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
1115
1491
  content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
1116
1492
  };
1117
1493
  }
1494
+ case 'delete': {
1495
+ const result = await client.deleteJob(toolArgs.job_id, {
1496
+ purge: true,
1497
+ force: toolArgs.force || false
1498
+ });
1499
+ return {
1500
+ content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
1501
+ };
1502
+ }
1503
+ case 'cleanup': {
1504
+ const result = await client.deleteJobs({
1505
+ dryRun: toolArgs.dry_run !== false && !toolArgs.confirm,
1506
+ confirm: toolArgs.confirm || false,
1507
+ status: toolArgs.status,
1508
+ system: toolArgs.system_only || false,
1509
+ olderThan: toolArgs.older_than,
1510
+ jobType: toolArgs.job_type
1511
+ });
1512
+ let output = '';
1513
+ if (result.dry_run) {
1514
+ output = `## Cleanup Preview (dry run)\n\n`;
1515
+ output += `Jobs matching filters: ${result.jobs_to_delete}\n\n`;
1516
+ if (result.jobs && result.jobs.length > 0) {
1517
+ output += `| Job ID | Type | Status | Created |\n`;
1518
+ output += `|--------|------|--------|--------|\n`;
1519
+ for (const job of result.jobs.slice(0, 20)) {
1520
+ output += `| ${job.job_id.substring(0, 16)} | ${job.job_type} | ${job.status} | ${job.created_at} |\n`;
1521
+ }
1522
+ if (result.jobs.length > 20) {
1523
+ output += `\n... and ${result.jobs.length - 20} more\n`;
1524
+ }
1525
+ }
1526
+ output += `\nTo delete, use confirm: true`;
1527
+ }
1528
+ else {
1529
+ output = `## Cleanup Complete\n\n`;
1530
+ output += `Jobs deleted: ${result.jobs_deleted}\n`;
1531
+ output += `\n${result.message}`;
1532
+ }
1533
+ return {
1534
+ content: [{ type: 'text', text: output }],
1535
+ };
1536
+ }
1118
1537
  default:
1119
1538
  throw new Error(`Unknown job action: ${action}`);
1120
1539
  }
@@ -1201,7 +1620,7 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
1201
1620
  content: [
1202
1621
  {
1203
1622
  type: 'text',
1204
- text: (0, formatters_js_1.formatInspectFileResult)(result),
1623
+ text: (0, index_js_2.formatInspectFileResult)(result),
1205
1624
  },
1206
1625
  ],
1207
1626
  };
@@ -1297,7 +1716,7 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
1297
1716
  content: [
1298
1717
  {
1299
1718
  type: 'text',
1300
- text: (0, formatters_js_1.formatIngestFileResult)(result),
1719
+ text: (0, index_js_2.formatIngestFileResult)(result),
1301
1720
  },
1302
1721
  ],
1303
1722
  };
@@ -1380,7 +1799,7 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
1380
1799
  content: [
1381
1800
  {
1382
1801
  type: 'text',
1383
- text: (0, formatters_js_1.formatIngestDirectoryResult)(result),
1802
+ text: (0, index_js_2.formatIngestDirectoryResult)(result),
1384
1803
  },
1385
1804
  ],
1386
1805
  };
@@ -1449,7 +1868,7 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
1449
1868
  case 'list': {
1450
1869
  const statusFilter = toolArgs.status_filter;
1451
1870
  const result = await client.listEpistemicStatus(statusFilter);
1452
- const output = (0, formatters_js_1.formatEpistemicStatusList)(result);
1871
+ const output = (0, index_js_2.formatEpistemicStatusList)(result);
1453
1872
  return {
1454
1873
  content: [{ type: 'text', text: output }],
1455
1874
  };
@@ -1460,7 +1879,7 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
1460
1879
  throw new Error('relationship_type is required for show action');
1461
1880
  }
1462
1881
  const result = await client.getEpistemicStatus(relationshipType);
1463
- const output = (0, formatters_js_1.formatEpistemicStatusDetails)(result);
1882
+ const output = (0, index_js_2.formatEpistemicStatusDetails)(result);
1464
1883
  return {
1465
1884
  content: [{ type: 'text', text: output }],
1466
1885
  };
@@ -1474,7 +1893,7 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
1474
1893
  store: store,
1475
1894
  verbose: verbose,
1476
1895
  });
1477
- const output = (0, formatters_js_1.formatEpistemicStatusMeasurement)(result);
1896
+ const output = (0, index_js_2.formatEpistemicStatusMeasurement)(result);
1478
1897
  return {
1479
1898
  content: [{ type: 'text', text: output }],
1480
1899
  };
@@ -1492,7 +1911,7 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
1492
1911
  max_candidates: toolArgs.max_candidates || 20,
1493
1912
  max_hops: toolArgs.max_hops || 2,
1494
1913
  });
1495
- const formattedText = (0, formatters_js_1.formatPolarityAxisResults)(result);
1914
+ const formattedText = (0, index_js_2.formatPolarityAxisResults)(result);
1496
1915
  return {
1497
1916
  content: [{ type: 'text', text: formattedText }],
1498
1917
  };
@@ -1596,7 +2015,7 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
1596
2015
  limit: toolArgs.limit || 50,
1597
2016
  offset: toolArgs.offset || 0,
1598
2017
  });
1599
- const formattedText = (0, formatters_js_1.formatDocumentList)(result);
2018
+ const formattedText = (0, index_js_2.formatDocumentList)(result);
1600
2019
  return {
1601
2020
  content: [{ type: 'text', text: formattedText }],
1602
2021
  };
@@ -1607,7 +2026,7 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
1607
2026
  throw new Error('document_id is required for show action');
1608
2027
  }
1609
2028
  const result = await client.getDocumentContent(documentId);
1610
- const formattedText = (0, formatters_js_1.formatDocumentContent)(result);
2029
+ const formattedText = (0, index_js_2.formatDocumentContent)(result);
1611
2030
  return {
1612
2031
  content: [{ type: 'text', text: formattedText }],
1613
2032
  };
@@ -1636,13 +2055,13 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
1636
2055
  });
1637
2056
  }
1638
2057
  }
1639
- const formattedText = (0, formatters_js_1.formatDocumentConceptsDetailed)(result, conceptDetails);
2058
+ const formattedText = (0, index_js_2.formatDocumentConceptsDetailed)(result, conceptDetails);
1640
2059
  return {
1641
2060
  content: [{ type: 'text', text: formattedText }],
1642
2061
  };
1643
2062
  }
1644
2063
  else {
1645
- const formattedText = (0, formatters_js_1.formatDocumentConcepts)(result);
2064
+ const formattedText = (0, index_js_2.formatDocumentConcepts)(result);
1646
2065
  return {
1647
2066
  content: [{ type: 'text', text: formattedText }],
1648
2067
  };
@@ -1652,6 +2071,175 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
1652
2071
  throw new Error(`Unknown document action: ${action}`);
1653
2072
  }
1654
2073
  }
2074
+ // ADR-089 Phase 3a: Graph CRUD Tool Handler (Refactored)
2075
+ case 'graph': {
2076
+ const action = toolArgs.action;
2077
+ const entity = toolArgs.entity;
2078
+ // Entity required for all actions except queue
2079
+ if (action !== 'queue' && !entity) {
2080
+ throw new Error('entity is required (concept or edge)');
2081
+ }
2082
+ // Create executor instance for this request
2083
+ const executor = new graph_operations_js_1.GraphOperationExecutor(client);
2084
+ switch (action) {
2085
+ case 'create': {
2086
+ if (entity === 'concept') {
2087
+ const result = await executor.createConcept({
2088
+ label: toolArgs.label,
2089
+ ontology: toolArgs.ontology,
2090
+ description: toolArgs.description,
2091
+ search_terms: toolArgs.search_terms,
2092
+ matching_mode: toolArgs.matching_mode,
2093
+ });
2094
+ if (!result.success)
2095
+ throw new Error(result.error);
2096
+ return {
2097
+ content: [{ type: 'text', text: (0, index_js_2.formatGraphConceptResult)(result.data, 'create') }],
2098
+ };
2099
+ }
2100
+ else if (entity === 'edge') {
2101
+ const result = await executor.createEdge({
2102
+ from_concept_id: toolArgs.from_concept_id,
2103
+ from_label: toolArgs.from_label,
2104
+ to_concept_id: toolArgs.to_concept_id,
2105
+ to_label: toolArgs.to_label,
2106
+ relationship_type: toolArgs.relationship_type,
2107
+ category: toolArgs.category,
2108
+ confidence: toolArgs.confidence,
2109
+ });
2110
+ if (!result.success)
2111
+ throw new Error(result.error);
2112
+ return {
2113
+ content: [{ type: 'text', text: (0, index_js_2.formatGraphEdgeResult)(result.data, 'create') }],
2114
+ };
2115
+ }
2116
+ else {
2117
+ throw new Error(`Unknown entity type: ${entity}`);
2118
+ }
2119
+ }
2120
+ case 'list': {
2121
+ if (entity === 'concept') {
2122
+ const result = await executor.listConcepts({
2123
+ ontology: toolArgs.ontology,
2124
+ label_contains: toolArgs.label_contains,
2125
+ creation_method: toolArgs.creation_method,
2126
+ offset: toolArgs.offset,
2127
+ limit: toolArgs.limit,
2128
+ });
2129
+ if (!result.success)
2130
+ throw new Error(result.error);
2131
+ return {
2132
+ content: [{ type: 'text', text: (0, index_js_2.formatGraphConceptList)(result.data) }],
2133
+ };
2134
+ }
2135
+ else if (entity === 'edge') {
2136
+ const result = await executor.listEdges({
2137
+ from_concept_id: toolArgs.from_concept_id,
2138
+ from_label: toolArgs.from_label,
2139
+ to_concept_id: toolArgs.to_concept_id,
2140
+ to_label: toolArgs.to_label,
2141
+ relationship_type: toolArgs.relationship_type,
2142
+ category: toolArgs.category,
2143
+ source: toolArgs.source,
2144
+ offset: toolArgs.offset,
2145
+ limit: toolArgs.limit,
2146
+ });
2147
+ if (!result.success)
2148
+ throw new Error(result.error);
2149
+ return {
2150
+ content: [{ type: 'text', text: (0, index_js_2.formatGraphEdgeList)(result.data) }],
2151
+ };
2152
+ }
2153
+ else {
2154
+ throw new Error(`Unknown entity type: ${entity}`);
2155
+ }
2156
+ }
2157
+ case 'edit': {
2158
+ if (entity === 'concept') {
2159
+ const result = await executor.editConcept({
2160
+ concept_id: toolArgs.concept_id,
2161
+ label: toolArgs.label,
2162
+ description: toolArgs.description,
2163
+ search_terms: toolArgs.search_terms,
2164
+ });
2165
+ if (!result.success)
2166
+ throw new Error(result.error);
2167
+ return {
2168
+ content: [{ type: 'text', text: (0, index_js_2.formatGraphConceptResult)(result.data, 'edit') }],
2169
+ };
2170
+ }
2171
+ else if (entity === 'edge') {
2172
+ const result = await executor.editEdge({
2173
+ from_concept_id: toolArgs.from_concept_id,
2174
+ from_label: toolArgs.from_label,
2175
+ to_concept_id: toolArgs.to_concept_id,
2176
+ to_label: toolArgs.to_label,
2177
+ relationship_type: toolArgs.relationship_type,
2178
+ confidence: toolArgs.confidence,
2179
+ category: toolArgs.category,
2180
+ });
2181
+ if (!result.success)
2182
+ throw new Error(result.error);
2183
+ return {
2184
+ content: [{ type: 'text', text: (0, index_js_2.formatGraphEdgeResult)(result.data, 'edit') }],
2185
+ };
2186
+ }
2187
+ else {
2188
+ throw new Error(`Unknown entity type: ${entity}`);
2189
+ }
2190
+ }
2191
+ case 'delete': {
2192
+ if (entity === 'concept') {
2193
+ const result = await executor.deleteConcept({
2194
+ concept_id: toolArgs.concept_id,
2195
+ cascade: toolArgs.cascade,
2196
+ });
2197
+ if (!result.success)
2198
+ throw new Error(result.error);
2199
+ return {
2200
+ content: [{ type: 'text', text: (0, index_js_2.formatGraphConceptResult)(result.data, 'delete') }],
2201
+ };
2202
+ }
2203
+ else if (entity === 'edge') {
2204
+ const result = await executor.deleteEdge({
2205
+ from_concept_id: toolArgs.from_concept_id,
2206
+ from_label: toolArgs.from_label,
2207
+ to_concept_id: toolArgs.to_concept_id,
2208
+ to_label: toolArgs.to_label,
2209
+ relationship_type: toolArgs.relationship_type,
2210
+ });
2211
+ if (!result.success)
2212
+ throw new Error(result.error);
2213
+ return {
2214
+ content: [{ type: 'text', text: (0, index_js_2.formatGraphEdgeResult)(result.data, 'delete') }],
2215
+ };
2216
+ }
2217
+ else {
2218
+ throw new Error(`Unknown entity type: ${entity}`);
2219
+ }
2220
+ }
2221
+ case 'queue': {
2222
+ const operations = toolArgs.operations;
2223
+ const continueOnError = toolArgs.continue_on_error === true;
2224
+ if (!operations || !Array.isArray(operations)) {
2225
+ throw new Error('operations array is required for queue action');
2226
+ }
2227
+ if (operations.length === 0) {
2228
+ throw new Error('operations array cannot be empty');
2229
+ }
2230
+ if (operations.length > 20) {
2231
+ throw new Error(`Queue too large: ${operations.length} operations (max 20)`);
2232
+ }
2233
+ const queueResult = await executor.executeQueue(operations, continueOnError);
2234
+ const formattedOutput = (0, index_js_2.formatGraphQueueResult)(queueResult, operations.length);
2235
+ return {
2236
+ content: [{ type: 'text', text: formattedOutput }],
2237
+ };
2238
+ }
2239
+ default:
2240
+ throw new Error(`Unknown graph action: ${action}. Use: create, edit, delete, list, or queue`);
2241
+ }
2242
+ }
1655
2243
  default:
1656
2244
  throw new Error(`Unknown tool: ${name}`);
1657
2245
  }