@aaronsb/kg-cli 0.6.5 → 0.7.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/api/client.d.ts +127 -1
- package/dist/api/client.d.ts.map +1 -1
- package/dist/api/client.js +147 -0
- package/dist/api/client.js.map +1 -1
- package/dist/cli/batch.d.ts +8 -0
- package/dist/cli/batch.d.ts.map +1 -0
- package/dist/cli/batch.js +225 -0
- package/dist/cli/batch.js.map +1 -0
- package/dist/cli/commands.d.ts.map +1 -1
- package/dist/cli/commands.js +10 -1
- package/dist/cli/commands.js.map +1 -1
- package/dist/cli/concept.d.ts +9 -0
- package/dist/cli/concept.d.ts.map +1 -0
- package/dist/cli/concept.js +336 -0
- package/dist/cli/concept.js.map +1 -0
- package/dist/cli/edge.d.ts +9 -0
- package/dist/cli/edge.d.ts.map +1 -0
- package/dist/cli/edge.js +364 -0
- package/dist/cli/edge.js.map +1 -0
- package/dist/cli/jobs.js +111 -3
- package/dist/cli/jobs.js.map +1 -1
- package/dist/cli/storage.d.ts +10 -0
- package/dist/cli/storage.d.ts.map +1 -0
- package/dist/cli/storage.js +260 -0
- package/dist/cli/storage.js.map +1 -0
- package/dist/cli/vocabulary/index.d.ts.map +1 -1
- package/dist/cli/vocabulary/index.js +1 -0
- package/dist/cli/vocabulary/index.js.map +1 -1
- package/dist/cli/vocabulary/similarity.d.ts +1 -0
- package/dist/cli/vocabulary/similarity.d.ts.map +1 -1
- package/dist/cli/vocabulary/similarity.js +60 -9
- package/dist/cli/vocabulary/similarity.js.map +1 -1
- package/dist/lib/interactive.d.ts +84 -0
- package/dist/lib/interactive.d.ts.map +1 -0
- package/dist/lib/interactive.js +296 -0
- package/dist/lib/interactive.js.map +1 -0
- package/dist/lib/validation.d.ts +106 -0
- package/dist/lib/validation.d.ts.map +1 -0
- package/dist/lib/validation.js +354 -0
- package/dist/lib/validation.js.map +1 -0
- package/dist/mcp/formatters/concept.d.ts +24 -0
- package/dist/mcp/formatters/concept.d.ts.map +1 -0
- package/dist/mcp/formatters/concept.js +243 -0
- package/dist/mcp/formatters/concept.js.map +1 -0
- package/dist/mcp/formatters/document.d.ts +25 -0
- package/dist/mcp/formatters/document.d.ts.map +1 -0
- package/dist/mcp/formatters/document.js +178 -0
- package/dist/mcp/formatters/document.js.map +1 -0
- package/dist/mcp/formatters/epistemic.d.ts +16 -0
- package/dist/mcp/formatters/epistemic.d.ts.map +1 -0
- package/dist/mcp/formatters/epistemic.js +269 -0
- package/dist/mcp/formatters/epistemic.js.map +1 -0
- package/dist/mcp/formatters/graph.d.ts +63 -0
- package/dist/mcp/formatters/graph.d.ts.map +1 -0
- package/dist/mcp/formatters/graph.js +220 -0
- package/dist/mcp/formatters/graph.js.map +1 -0
- package/dist/mcp/formatters/index.d.ts +18 -0
- package/dist/mcp/formatters/index.d.ts.map +1 -0
- package/dist/mcp/formatters/index.js +63 -0
- package/dist/mcp/formatters/index.js.map +1 -0
- package/dist/mcp/formatters/ingest.d.ts +16 -0
- package/dist/mcp/formatters/ingest.d.ts.map +1 -0
- package/dist/mcp/formatters/ingest.js +169 -0
- package/dist/mcp/formatters/ingest.js.map +1 -0
- package/dist/mcp/formatters/job.d.ts +13 -0
- package/dist/mcp/formatters/job.d.ts.map +1 -0
- package/dist/mcp/formatters/job.js +204 -0
- package/dist/mcp/formatters/job.js.map +1 -0
- package/dist/mcp/formatters/source.d.ts +19 -0
- package/dist/mcp/formatters/source.d.ts.map +1 -0
- package/dist/mcp/formatters/source.js +182 -0
- package/dist/mcp/formatters/source.js.map +1 -0
- package/dist/mcp/formatters/system.d.ts +10 -0
- package/dist/mcp/formatters/system.d.ts.map +1 -0
- package/dist/mcp/formatters/system.js +152 -0
- package/dist/mcp/formatters/system.js.map +1 -0
- package/dist/mcp/formatters/utils.d.ts +17 -0
- package/dist/mcp/formatters/utils.d.ts.map +1 -0
- package/dist/mcp/formatters/utils.js +55 -0
- package/dist/mcp/formatters/utils.js.map +1 -0
- package/dist/mcp/graph-operations.d.ts +242 -0
- package/dist/mcp/graph-operations.d.ts.map +1 -0
- package/dist/mcp/graph-operations.js +532 -0
- package/dist/mcp/graph-operations.js.map +1 -0
- package/dist/mcp-server.js +465 -33
- package/dist/mcp-server.js.map +1 -1
- package/dist/types/index.d.ts +153 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/version.d.ts +3 -3
- package/dist/version.js +3 -3
- package/dist/version.js.map +1 -1
- package/package.json +1 -1
- package/dist/mcp/formatters.d.ts +0 -100
- package/dist/mcp/formatters.d.ts.map +0 -1
- package/dist/mcp/formatters.js +0 -1411
- package/dist/mcp/formatters.js.map +0 -1
package/dist/mcp-server.js
CHANGED
|
@@ -39,6 +39,9 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
39
39
|
return result;
|
|
40
40
|
};
|
|
41
41
|
})();
|
|
42
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
43
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
44
|
+
};
|
|
42
45
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
43
46
|
const index_js_1 = require("@modelcontextprotocol/sdk/server/index.js");
|
|
44
47
|
const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
@@ -46,9 +49,11 @@ const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
|
|
|
46
49
|
const client_js_1 = require("./api/client.js");
|
|
47
50
|
const auth_client_js_1 = require("./lib/auth/auth-client.js");
|
|
48
51
|
const mcp_allowlist_js_1 = require("./lib/mcp-allowlist.js");
|
|
49
|
-
const
|
|
52
|
+
const index_js_2 = require("./mcp/formatters/index.js");
|
|
53
|
+
const graph_operations_js_1 = require("./mcp/graph-operations.js");
|
|
50
54
|
const fs = __importStar(require("fs"));
|
|
51
55
|
const path = __importStar(require("path"));
|
|
56
|
+
const package_json_1 = __importDefault(require("../package.json"));
|
|
52
57
|
/**
|
|
53
58
|
* Default parameters for graph queries (ADR-048 Query Safety)
|
|
54
59
|
*
|
|
@@ -64,7 +69,7 @@ const DEFAULT_MAX_DEPTH = 2; // Related concepts neighborhood depth
|
|
|
64
69
|
// Create server instance
|
|
65
70
|
const server = new index_js_1.Server({
|
|
66
71
|
name: 'knowledge-graph-server',
|
|
67
|
-
version:
|
|
72
|
+
version: package_json_1.default.version,
|
|
68
73
|
}, {
|
|
69
74
|
capabilities: {
|
|
70
75
|
tools: {},
|
|
@@ -403,28 +408,56 @@ PERFORMANCE CRITICAL: For "connect" action, use threshold >= 0.75 to avoid datab
|
|
|
403
408
|
},
|
|
404
409
|
{
|
|
405
410
|
name: 'job',
|
|
406
|
-
description: 'Manage ingestion jobs: get status, list jobs, approve, or
|
|
411
|
+
description: 'Manage ingestion jobs: get status, list jobs, approve, cancel, delete, or cleanup. Use action parameter to specify operation.',
|
|
407
412
|
inputSchema: {
|
|
408
413
|
type: 'object',
|
|
409
414
|
properties: {
|
|
410
415
|
action: {
|
|
411
416
|
type: 'string',
|
|
412
|
-
enum: ['status', 'list', 'approve', 'cancel'],
|
|
413
|
-
description: 'Operation: "status" (get job status), "list" (list jobs), "approve" (approve job), "cancel" (cancel job)',
|
|
417
|
+
enum: ['status', 'list', 'approve', 'cancel', 'delete', 'cleanup'],
|
|
418
|
+
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)',
|
|
414
419
|
},
|
|
415
420
|
job_id: {
|
|
416
421
|
type: 'string',
|
|
417
|
-
description: 'Job ID (required for status, approve, cancel)',
|
|
422
|
+
description: 'Job ID (required for status, approve, cancel, delete)',
|
|
418
423
|
},
|
|
419
424
|
status: {
|
|
420
425
|
type: 'string',
|
|
421
|
-
description: 'Filter by status for list (pending, awaiting_approval, running, completed, failed)',
|
|
426
|
+
description: 'Filter by status for list/cleanup (pending, awaiting_approval, running, completed, failed)',
|
|
422
427
|
},
|
|
423
428
|
limit: {
|
|
424
429
|
type: 'number',
|
|
425
430
|
description: 'Max jobs to return for list (default: 50)',
|
|
426
431
|
default: 50,
|
|
427
432
|
},
|
|
433
|
+
force: {
|
|
434
|
+
type: 'boolean',
|
|
435
|
+
description: 'Force delete even if job is processing (for delete action)',
|
|
436
|
+
default: false,
|
|
437
|
+
},
|
|
438
|
+
system_only: {
|
|
439
|
+
type: 'boolean',
|
|
440
|
+
description: 'Only delete system/scheduled jobs (for cleanup action)',
|
|
441
|
+
default: false,
|
|
442
|
+
},
|
|
443
|
+
older_than: {
|
|
444
|
+
type: 'string',
|
|
445
|
+
description: 'Delete jobs older than duration: 1h, 24h, 7d, 30d (for cleanup action)',
|
|
446
|
+
},
|
|
447
|
+
job_type: {
|
|
448
|
+
type: 'string',
|
|
449
|
+
description: 'Filter by job type for cleanup (ingestion, epistemic_remeasurement, projection, etc)',
|
|
450
|
+
},
|
|
451
|
+
dry_run: {
|
|
452
|
+
type: 'boolean',
|
|
453
|
+
description: 'Preview what would be deleted without deleting (for cleanup, default: true)',
|
|
454
|
+
default: true,
|
|
455
|
+
},
|
|
456
|
+
confirm: {
|
|
457
|
+
type: 'boolean',
|
|
458
|
+
description: 'Confirm deletion - set to true to actually delete (for cleanup action)',
|
|
459
|
+
default: false,
|
|
460
|
+
},
|
|
428
461
|
},
|
|
429
462
|
required: ['action'],
|
|
430
463
|
},
|
|
@@ -745,6 +778,193 @@ Use search tool with type="documents" to find documents semantically.`,
|
|
|
745
778
|
required: ['action'],
|
|
746
779
|
},
|
|
747
780
|
},
|
|
781
|
+
// ADR-089 Phase 3a: Graph CRUD Tool
|
|
782
|
+
{
|
|
783
|
+
name: 'graph',
|
|
784
|
+
description: `Create, edit, delete, and list concepts and edges in the knowledge graph (ADR-089).
|
|
785
|
+
|
|
786
|
+
This tool provides deterministic graph editing without going through the LLM ingest pipeline.
|
|
787
|
+
Use for manual curation, agent-driven knowledge building, and precise graph manipulation.
|
|
788
|
+
|
|
789
|
+
**Actions:**
|
|
790
|
+
- "create": Create a new concept or edge
|
|
791
|
+
- "edit": Update an existing concept or edge
|
|
792
|
+
- "delete": Delete a concept or edge
|
|
793
|
+
- "list": List concepts or edges with filters
|
|
794
|
+
|
|
795
|
+
**Entity Types:**
|
|
796
|
+
- "concept": Knowledge graph concepts (nodes)
|
|
797
|
+
- "edge": Relationships between concepts
|
|
798
|
+
|
|
799
|
+
**Matching Modes (for create):**
|
|
800
|
+
- "auto": Link to existing if match found, create if not (default)
|
|
801
|
+
- "force_create": Always create new, even if similar exists
|
|
802
|
+
- "match_only": Only link to existing, error if no match
|
|
803
|
+
|
|
804
|
+
**Semantic Resolution:**
|
|
805
|
+
- Use \`from_label\`/\`to_label\` to reference concepts by name instead of ID
|
|
806
|
+
- Resolution uses vector similarity (85% threshold) to find matching concepts
|
|
807
|
+
|
|
808
|
+
**Examples:**
|
|
809
|
+
- Create concept: \`{action: "create", entity: "concept", label: "CAP Theorem", ontology: "distributed-systems"}\`
|
|
810
|
+
- Create edge: \`{action: "create", entity: "edge", from_label: "CAP Theorem", to_label: "Partition Tolerance", relationship_type: "REQUIRES"}\`
|
|
811
|
+
- List concepts: \`{action: "list", entity: "concept", ontology: "distributed-systems"}\`
|
|
812
|
+
- Delete concept: \`{action: "delete", entity: "concept", concept_id: "c_abc123"}\`
|
|
813
|
+
|
|
814
|
+
**Queue Mode** (batch multiple operations in one call):
|
|
815
|
+
\`\`\`json
|
|
816
|
+
{
|
|
817
|
+
"action": "queue",
|
|
818
|
+
"operations": [
|
|
819
|
+
{"op": "create", "entity": "concept", "label": "A", "ontology": "test"},
|
|
820
|
+
{"op": "create", "entity": "concept", "label": "B", "ontology": "test"},
|
|
821
|
+
{"op": "create", "entity": "edge", "from_label": "A", "to_label": "B", "relationship_type": "IMPLIES"}
|
|
822
|
+
]
|
|
823
|
+
}
|
|
824
|
+
\`\`\`
|
|
825
|
+
Queue executes sequentially, stops on first error (unless continue_on_error=true). Max 20 operations.`,
|
|
826
|
+
inputSchema: {
|
|
827
|
+
type: 'object',
|
|
828
|
+
properties: {
|
|
829
|
+
action: {
|
|
830
|
+
type: 'string',
|
|
831
|
+
enum: ['create', 'edit', 'delete', 'list', 'queue'],
|
|
832
|
+
description: 'Operation to perform. Use "queue" to batch multiple operations.',
|
|
833
|
+
},
|
|
834
|
+
entity: {
|
|
835
|
+
type: 'string',
|
|
836
|
+
enum: ['concept', 'edge'],
|
|
837
|
+
description: 'Entity type (required for create/edit/delete/list, not for queue)',
|
|
838
|
+
},
|
|
839
|
+
// Queue fields
|
|
840
|
+
operations: {
|
|
841
|
+
type: 'array',
|
|
842
|
+
items: {
|
|
843
|
+
type: 'object',
|
|
844
|
+
properties: {
|
|
845
|
+
op: { type: 'string', enum: ['create', 'edit', 'delete', 'list'], description: 'Operation' },
|
|
846
|
+
entity: { type: 'string', enum: ['concept', 'edge'] },
|
|
847
|
+
label: { type: 'string' },
|
|
848
|
+
ontology: { type: 'string' },
|
|
849
|
+
description: { type: 'string' },
|
|
850
|
+
search_terms: { type: 'array', items: { type: 'string' } },
|
|
851
|
+
matching_mode: { type: 'string', enum: ['auto', 'force_create', 'match_only'] },
|
|
852
|
+
concept_id: { type: 'string' },
|
|
853
|
+
from_concept_id: { type: 'string' },
|
|
854
|
+
to_concept_id: { type: 'string' },
|
|
855
|
+
from_label: { type: 'string' },
|
|
856
|
+
to_label: { type: 'string' },
|
|
857
|
+
relationship_type: { type: 'string' },
|
|
858
|
+
category: { type: 'string' },
|
|
859
|
+
confidence: { type: 'number' },
|
|
860
|
+
limit: { type: 'number' },
|
|
861
|
+
offset: { type: 'number' },
|
|
862
|
+
cascade: { type: 'boolean' },
|
|
863
|
+
},
|
|
864
|
+
required: ['op', 'entity'],
|
|
865
|
+
},
|
|
866
|
+
description: 'Array of operations for queue action (max 20). Each has op, entity, and action-specific fields.',
|
|
867
|
+
},
|
|
868
|
+
continue_on_error: {
|
|
869
|
+
type: 'boolean',
|
|
870
|
+
description: 'For queue: continue executing after errors (default: false, stop on first error)',
|
|
871
|
+
default: false,
|
|
872
|
+
},
|
|
873
|
+
// Concept fields
|
|
874
|
+
label: {
|
|
875
|
+
type: 'string',
|
|
876
|
+
description: 'Concept label (required for create concept)',
|
|
877
|
+
},
|
|
878
|
+
ontology: {
|
|
879
|
+
type: 'string',
|
|
880
|
+
description: 'Ontology/namespace (required for create concept, optional filter for list)',
|
|
881
|
+
},
|
|
882
|
+
description: {
|
|
883
|
+
type: 'string',
|
|
884
|
+
description: 'Concept description (optional)',
|
|
885
|
+
},
|
|
886
|
+
search_terms: {
|
|
887
|
+
type: 'array',
|
|
888
|
+
items: { type: 'string' },
|
|
889
|
+
description: 'Alternative search terms for the concept',
|
|
890
|
+
},
|
|
891
|
+
matching_mode: {
|
|
892
|
+
type: 'string',
|
|
893
|
+
enum: ['auto', 'force_create', 'match_only'],
|
|
894
|
+
description: 'How to handle similar existing concepts (default: auto)',
|
|
895
|
+
default: 'auto',
|
|
896
|
+
},
|
|
897
|
+
// Edge fields
|
|
898
|
+
from_concept_id: {
|
|
899
|
+
type: 'string',
|
|
900
|
+
description: 'Source concept ID (for edge create/delete)',
|
|
901
|
+
},
|
|
902
|
+
to_concept_id: {
|
|
903
|
+
type: 'string',
|
|
904
|
+
description: 'Target concept ID (for edge create/delete)',
|
|
905
|
+
},
|
|
906
|
+
from_label: {
|
|
907
|
+
type: 'string',
|
|
908
|
+
description: 'Source concept by label (semantic resolution)',
|
|
909
|
+
},
|
|
910
|
+
to_label: {
|
|
911
|
+
type: 'string',
|
|
912
|
+
description: 'Target concept by label (semantic resolution)',
|
|
913
|
+
},
|
|
914
|
+
relationship_type: {
|
|
915
|
+
type: 'string',
|
|
916
|
+
description: 'Edge relationship type (e.g., IMPLIES, SUPPORTS, CONTRADICTS)',
|
|
917
|
+
},
|
|
918
|
+
category: {
|
|
919
|
+
type: 'string',
|
|
920
|
+
enum: ['logical_truth', 'empirical_claim', 'value_judgment', 'conceptual', 'temporal_sequence', 'causal', 'other'],
|
|
921
|
+
description: 'Semantic category of the relationship (default: logical_truth)',
|
|
922
|
+
default: 'logical_truth',
|
|
923
|
+
},
|
|
924
|
+
confidence: {
|
|
925
|
+
type: 'number',
|
|
926
|
+
description: 'Edge confidence 0.0-1.0 (default: 1.0)',
|
|
927
|
+
default: 1.0,
|
|
928
|
+
},
|
|
929
|
+
// Identifiers for edit/delete
|
|
930
|
+
concept_id: {
|
|
931
|
+
type: 'string',
|
|
932
|
+
description: 'Concept ID (for edit/delete concept)',
|
|
933
|
+
},
|
|
934
|
+
// List filters
|
|
935
|
+
label_contains: {
|
|
936
|
+
type: 'string',
|
|
937
|
+
description: 'Filter concepts by label substring (for list)',
|
|
938
|
+
},
|
|
939
|
+
creation_method: {
|
|
940
|
+
type: 'string',
|
|
941
|
+
description: 'Filter by creation method (for list)',
|
|
942
|
+
},
|
|
943
|
+
source: {
|
|
944
|
+
type: 'string',
|
|
945
|
+
description: 'Filter edges by source (for list)',
|
|
946
|
+
},
|
|
947
|
+
// Pagination
|
|
948
|
+
limit: {
|
|
949
|
+
type: 'number',
|
|
950
|
+
description: 'Max results to return (default: 20)',
|
|
951
|
+
default: 20,
|
|
952
|
+
},
|
|
953
|
+
offset: {
|
|
954
|
+
type: 'number',
|
|
955
|
+
description: 'Number to skip for pagination (default: 0)',
|
|
956
|
+
default: 0,
|
|
957
|
+
},
|
|
958
|
+
// Delete option
|
|
959
|
+
cascade: {
|
|
960
|
+
type: 'boolean',
|
|
961
|
+
description: 'For concept delete: also delete orphaned synthetic sources (default: false)',
|
|
962
|
+
default: false,
|
|
963
|
+
},
|
|
964
|
+
},
|
|
965
|
+
required: ['action'],
|
|
966
|
+
},
|
|
967
|
+
},
|
|
748
968
|
],
|
|
749
969
|
};
|
|
750
970
|
});
|
|
@@ -802,7 +1022,7 @@ server.setRequestHandler(types_js_1.ReadResourceRequestSchema, async (request) =
|
|
|
802
1022
|
contents: [{
|
|
803
1023
|
uri,
|
|
804
1024
|
mimeType: 'text/plain',
|
|
805
|
-
text: (0,
|
|
1025
|
+
text: (0, index_js_2.formatDatabaseStats)(result)
|
|
806
1026
|
}]
|
|
807
1027
|
};
|
|
808
1028
|
}
|
|
@@ -812,7 +1032,7 @@ server.setRequestHandler(types_js_1.ReadResourceRequestSchema, async (request) =
|
|
|
812
1032
|
contents: [{
|
|
813
1033
|
uri,
|
|
814
1034
|
mimeType: 'text/plain',
|
|
815
|
-
text: (0,
|
|
1035
|
+
text: (0, index_js_2.formatDatabaseInfo)(result)
|
|
816
1036
|
}]
|
|
817
1037
|
};
|
|
818
1038
|
}
|
|
@@ -822,7 +1042,7 @@ server.setRequestHandler(types_js_1.ReadResourceRequestSchema, async (request) =
|
|
|
822
1042
|
contents: [{
|
|
823
1043
|
uri,
|
|
824
1044
|
mimeType: 'text/plain',
|
|
825
|
-
text: (0,
|
|
1045
|
+
text: (0, index_js_2.formatDatabaseHealth)(result)
|
|
826
1046
|
}]
|
|
827
1047
|
};
|
|
828
1048
|
}
|
|
@@ -832,7 +1052,7 @@ server.setRequestHandler(types_js_1.ReadResourceRequestSchema, async (request) =
|
|
|
832
1052
|
contents: [{
|
|
833
1053
|
uri,
|
|
834
1054
|
mimeType: 'text/plain',
|
|
835
|
-
text: (0,
|
|
1055
|
+
text: (0, index_js_2.formatSystemStatus)(result)
|
|
836
1056
|
}]
|
|
837
1057
|
};
|
|
838
1058
|
}
|
|
@@ -842,7 +1062,7 @@ server.setRequestHandler(types_js_1.ReadResourceRequestSchema, async (request) =
|
|
|
842
1062
|
contents: [{
|
|
843
1063
|
uri,
|
|
844
1064
|
mimeType: 'text/plain',
|
|
845
|
-
text: (0,
|
|
1065
|
+
text: (0, index_js_2.formatApiHealth)(result)
|
|
846
1066
|
}]
|
|
847
1067
|
};
|
|
848
1068
|
}
|
|
@@ -854,7 +1074,7 @@ server.setRequestHandler(types_js_1.ReadResourceRequestSchema, async (request) =
|
|
|
854
1074
|
contents: [{
|
|
855
1075
|
uri,
|
|
856
1076
|
mimeType: 'text/plain',
|
|
857
|
-
text: (0,
|
|
1077
|
+
text: (0, index_js_2.formatMcpAllowedPaths)({
|
|
858
1078
|
configured: false,
|
|
859
1079
|
message: 'Allowlist not initialized. Run: kg mcp-config init-allowlist',
|
|
860
1080
|
hint: 'Initialize with default safe patterns for .md, .txt, .pdf, .png, .jpg files'
|
|
@@ -866,7 +1086,7 @@ server.setRequestHandler(types_js_1.ReadResourceRequestSchema, async (request) =
|
|
|
866
1086
|
contents: [{
|
|
867
1087
|
uri,
|
|
868
1088
|
mimeType: 'text/plain',
|
|
869
|
-
text: (0,
|
|
1089
|
+
text: (0, index_js_2.formatMcpAllowedPaths)({
|
|
870
1090
|
configured: true,
|
|
871
1091
|
version: config.version,
|
|
872
1092
|
allowed_directories: config.allowed_directories,
|
|
@@ -944,7 +1164,7 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
944
1164
|
include_concepts: true,
|
|
945
1165
|
include_full_text: true,
|
|
946
1166
|
});
|
|
947
|
-
const formattedText = (0,
|
|
1167
|
+
const formattedText = (0, index_js_2.formatSourceSearchResults)(result);
|
|
948
1168
|
return {
|
|
949
1169
|
content: [{ type: 'text', text: formattedText }],
|
|
950
1170
|
};
|
|
@@ -959,7 +1179,7 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
959
1179
|
});
|
|
960
1180
|
// Add query to result for formatting
|
|
961
1181
|
const resultWithQuery = { ...result, query };
|
|
962
|
-
const formattedText = (0,
|
|
1182
|
+
const formattedText = (0, index_js_2.formatDocumentSearchResults)(resultWithQuery);
|
|
963
1183
|
return {
|
|
964
1184
|
content: [{ type: 'text', text: formattedText }],
|
|
965
1185
|
};
|
|
@@ -976,7 +1196,7 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
976
1196
|
include_diversity: true,
|
|
977
1197
|
diversity_max_hops: 2,
|
|
978
1198
|
});
|
|
979
|
-
const formattedText = (0,
|
|
1199
|
+
const formattedText = (0, index_js_2.formatSearchResults)(result);
|
|
980
1200
|
return {
|
|
981
1201
|
content: [{ type: 'text', text: formattedText }],
|
|
982
1202
|
};
|
|
@@ -991,7 +1211,7 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
991
1211
|
const diversityMaxHops = toolArgs.diversity_max_hops || 2;
|
|
992
1212
|
const truncateEvidence = toolArgs.truncate_evidence !== false; // Default true
|
|
993
1213
|
const result = await client.getConceptDetails(toolArgs.concept_id, includeGrounding, includeDiversity, diversityMaxHops);
|
|
994
|
-
const formattedText = (0,
|
|
1214
|
+
const formattedText = (0, index_js_2.formatConceptDetails)(result, truncateEvidence);
|
|
995
1215
|
return {
|
|
996
1216
|
content: [{ type: 'text', text: formattedText }],
|
|
997
1217
|
};
|
|
@@ -1005,7 +1225,7 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
1005
1225
|
include_epistemic_status: toolArgs.include_epistemic_status,
|
|
1006
1226
|
exclude_epistemic_status: toolArgs.exclude_epistemic_status,
|
|
1007
1227
|
});
|
|
1008
|
-
const formattedText = (0,
|
|
1228
|
+
const formattedText = (0, index_js_2.formatRelatedConcepts)(result);
|
|
1009
1229
|
return {
|
|
1010
1230
|
content: [{ type: 'text', text: formattedText }],
|
|
1011
1231
|
};
|
|
@@ -1041,7 +1261,7 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
1041
1261
|
include_epistemic_status: toolArgs.include_epistemic_status,
|
|
1042
1262
|
exclude_epistemic_status: toolArgs.exclude_epistemic_status,
|
|
1043
1263
|
});
|
|
1044
|
-
const formattedText = (0,
|
|
1264
|
+
const formattedText = (0, index_js_2.formatConnectionPaths)(result);
|
|
1045
1265
|
return {
|
|
1046
1266
|
content: [{ type: 'text', text: formattedText }],
|
|
1047
1267
|
};
|
|
@@ -1087,14 +1307,14 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
1087
1307
|
switch (action) {
|
|
1088
1308
|
case 'status': {
|
|
1089
1309
|
const result = await client.getJobStatus(toolArgs.job_id);
|
|
1090
|
-
const formattedText = (0,
|
|
1310
|
+
const formattedText = (0, index_js_2.formatJobStatus)(result);
|
|
1091
1311
|
return {
|
|
1092
1312
|
content: [{ type: 'text', text: formattedText }],
|
|
1093
1313
|
};
|
|
1094
1314
|
}
|
|
1095
1315
|
case 'list': {
|
|
1096
1316
|
const result = await client.listJobs(toolArgs.status, undefined, toolArgs.limit || 50);
|
|
1097
|
-
const formattedText = (0,
|
|
1317
|
+
const formattedText = (0, index_js_2.formatJobList)(result);
|
|
1098
1318
|
return {
|
|
1099
1319
|
content: [{ type: 'text', text: formattedText }],
|
|
1100
1320
|
};
|
|
@@ -1111,6 +1331,49 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
1111
1331
|
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
|
|
1112
1332
|
};
|
|
1113
1333
|
}
|
|
1334
|
+
case 'delete': {
|
|
1335
|
+
const result = await client.deleteJob(toolArgs.job_id, {
|
|
1336
|
+
purge: true,
|
|
1337
|
+
force: toolArgs.force || false
|
|
1338
|
+
});
|
|
1339
|
+
return {
|
|
1340
|
+
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
|
|
1341
|
+
};
|
|
1342
|
+
}
|
|
1343
|
+
case 'cleanup': {
|
|
1344
|
+
const result = await client.deleteJobs({
|
|
1345
|
+
dryRun: toolArgs.dry_run !== false && !toolArgs.confirm,
|
|
1346
|
+
confirm: toolArgs.confirm || false,
|
|
1347
|
+
status: toolArgs.status,
|
|
1348
|
+
system: toolArgs.system_only || false,
|
|
1349
|
+
olderThan: toolArgs.older_than,
|
|
1350
|
+
jobType: toolArgs.job_type
|
|
1351
|
+
});
|
|
1352
|
+
let output = '';
|
|
1353
|
+
if (result.dry_run) {
|
|
1354
|
+
output = `## Cleanup Preview (dry run)\n\n`;
|
|
1355
|
+
output += `Jobs matching filters: ${result.jobs_to_delete}\n\n`;
|
|
1356
|
+
if (result.jobs && result.jobs.length > 0) {
|
|
1357
|
+
output += `| Job ID | Type | Status | Created |\n`;
|
|
1358
|
+
output += `|--------|------|--------|--------|\n`;
|
|
1359
|
+
for (const job of result.jobs.slice(0, 20)) {
|
|
1360
|
+
output += `| ${job.job_id.substring(0, 16)} | ${job.job_type} | ${job.status} | ${job.created_at} |\n`;
|
|
1361
|
+
}
|
|
1362
|
+
if (result.jobs.length > 20) {
|
|
1363
|
+
output += `\n... and ${result.jobs.length - 20} more\n`;
|
|
1364
|
+
}
|
|
1365
|
+
}
|
|
1366
|
+
output += `\nTo delete, use confirm: true`;
|
|
1367
|
+
}
|
|
1368
|
+
else {
|
|
1369
|
+
output = `## Cleanup Complete\n\n`;
|
|
1370
|
+
output += `Jobs deleted: ${result.jobs_deleted}\n`;
|
|
1371
|
+
output += `\n${result.message}`;
|
|
1372
|
+
}
|
|
1373
|
+
return {
|
|
1374
|
+
content: [{ type: 'text', text: output }],
|
|
1375
|
+
};
|
|
1376
|
+
}
|
|
1114
1377
|
default:
|
|
1115
1378
|
throw new Error(`Unknown job action: ${action}`);
|
|
1116
1379
|
}
|
|
@@ -1197,7 +1460,7 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
1197
1460
|
content: [
|
|
1198
1461
|
{
|
|
1199
1462
|
type: 'text',
|
|
1200
|
-
text: (0,
|
|
1463
|
+
text: (0, index_js_2.formatInspectFileResult)(result),
|
|
1201
1464
|
},
|
|
1202
1465
|
],
|
|
1203
1466
|
};
|
|
@@ -1293,7 +1556,7 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
1293
1556
|
content: [
|
|
1294
1557
|
{
|
|
1295
1558
|
type: 'text',
|
|
1296
|
-
text: (0,
|
|
1559
|
+
text: (0, index_js_2.formatIngestFileResult)(result),
|
|
1297
1560
|
},
|
|
1298
1561
|
],
|
|
1299
1562
|
};
|
|
@@ -1376,7 +1639,7 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
1376
1639
|
content: [
|
|
1377
1640
|
{
|
|
1378
1641
|
type: 'text',
|
|
1379
|
-
text: (0,
|
|
1642
|
+
text: (0, index_js_2.formatIngestDirectoryResult)(result),
|
|
1380
1643
|
},
|
|
1381
1644
|
],
|
|
1382
1645
|
};
|
|
@@ -1445,7 +1708,7 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
1445
1708
|
case 'list': {
|
|
1446
1709
|
const statusFilter = toolArgs.status_filter;
|
|
1447
1710
|
const result = await client.listEpistemicStatus(statusFilter);
|
|
1448
|
-
const output = (0,
|
|
1711
|
+
const output = (0, index_js_2.formatEpistemicStatusList)(result);
|
|
1449
1712
|
return {
|
|
1450
1713
|
content: [{ type: 'text', text: output }],
|
|
1451
1714
|
};
|
|
@@ -1456,7 +1719,7 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
1456
1719
|
throw new Error('relationship_type is required for show action');
|
|
1457
1720
|
}
|
|
1458
1721
|
const result = await client.getEpistemicStatus(relationshipType);
|
|
1459
|
-
const output = (0,
|
|
1722
|
+
const output = (0, index_js_2.formatEpistemicStatusDetails)(result);
|
|
1460
1723
|
return {
|
|
1461
1724
|
content: [{ type: 'text', text: output }],
|
|
1462
1725
|
};
|
|
@@ -1470,7 +1733,7 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
1470
1733
|
store: store,
|
|
1471
1734
|
verbose: verbose,
|
|
1472
1735
|
});
|
|
1473
|
-
const output = (0,
|
|
1736
|
+
const output = (0, index_js_2.formatEpistemicStatusMeasurement)(result);
|
|
1474
1737
|
return {
|
|
1475
1738
|
content: [{ type: 'text', text: output }],
|
|
1476
1739
|
};
|
|
@@ -1488,7 +1751,7 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
1488
1751
|
max_candidates: toolArgs.max_candidates || 20,
|
|
1489
1752
|
max_hops: toolArgs.max_hops || 2,
|
|
1490
1753
|
});
|
|
1491
|
-
const formattedText = (0,
|
|
1754
|
+
const formattedText = (0, index_js_2.formatPolarityAxisResults)(result);
|
|
1492
1755
|
return {
|
|
1493
1756
|
content: [{ type: 'text', text: formattedText }],
|
|
1494
1757
|
};
|
|
@@ -1592,7 +1855,7 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
1592
1855
|
limit: toolArgs.limit || 50,
|
|
1593
1856
|
offset: toolArgs.offset || 0,
|
|
1594
1857
|
});
|
|
1595
|
-
const formattedText = (0,
|
|
1858
|
+
const formattedText = (0, index_js_2.formatDocumentList)(result);
|
|
1596
1859
|
return {
|
|
1597
1860
|
content: [{ type: 'text', text: formattedText }],
|
|
1598
1861
|
};
|
|
@@ -1603,7 +1866,7 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
1603
1866
|
throw new Error('document_id is required for show action');
|
|
1604
1867
|
}
|
|
1605
1868
|
const result = await client.getDocumentContent(documentId);
|
|
1606
|
-
const formattedText = (0,
|
|
1869
|
+
const formattedText = (0, index_js_2.formatDocumentContent)(result);
|
|
1607
1870
|
return {
|
|
1608
1871
|
content: [{ type: 'text', text: formattedText }],
|
|
1609
1872
|
};
|
|
@@ -1632,13 +1895,13 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
1632
1895
|
});
|
|
1633
1896
|
}
|
|
1634
1897
|
}
|
|
1635
|
-
const formattedText = (0,
|
|
1898
|
+
const formattedText = (0, index_js_2.formatDocumentConceptsDetailed)(result, conceptDetails);
|
|
1636
1899
|
return {
|
|
1637
1900
|
content: [{ type: 'text', text: formattedText }],
|
|
1638
1901
|
};
|
|
1639
1902
|
}
|
|
1640
1903
|
else {
|
|
1641
|
-
const formattedText = (0,
|
|
1904
|
+
const formattedText = (0, index_js_2.formatDocumentConcepts)(result);
|
|
1642
1905
|
return {
|
|
1643
1906
|
content: [{ type: 'text', text: formattedText }],
|
|
1644
1907
|
};
|
|
@@ -1648,6 +1911,175 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
1648
1911
|
throw new Error(`Unknown document action: ${action}`);
|
|
1649
1912
|
}
|
|
1650
1913
|
}
|
|
1914
|
+
// ADR-089 Phase 3a: Graph CRUD Tool Handler (Refactored)
|
|
1915
|
+
case 'graph': {
|
|
1916
|
+
const action = toolArgs.action;
|
|
1917
|
+
const entity = toolArgs.entity;
|
|
1918
|
+
// Entity required for all actions except queue
|
|
1919
|
+
if (action !== 'queue' && !entity) {
|
|
1920
|
+
throw new Error('entity is required (concept or edge)');
|
|
1921
|
+
}
|
|
1922
|
+
// Create executor instance for this request
|
|
1923
|
+
const executor = new graph_operations_js_1.GraphOperationExecutor(client);
|
|
1924
|
+
switch (action) {
|
|
1925
|
+
case 'create': {
|
|
1926
|
+
if (entity === 'concept') {
|
|
1927
|
+
const result = await executor.createConcept({
|
|
1928
|
+
label: toolArgs.label,
|
|
1929
|
+
ontology: toolArgs.ontology,
|
|
1930
|
+
description: toolArgs.description,
|
|
1931
|
+
search_terms: toolArgs.search_terms,
|
|
1932
|
+
matching_mode: toolArgs.matching_mode,
|
|
1933
|
+
});
|
|
1934
|
+
if (!result.success)
|
|
1935
|
+
throw new Error(result.error);
|
|
1936
|
+
return {
|
|
1937
|
+
content: [{ type: 'text', text: (0, index_js_2.formatGraphConceptResult)(result.data, 'create') }],
|
|
1938
|
+
};
|
|
1939
|
+
}
|
|
1940
|
+
else if (entity === 'edge') {
|
|
1941
|
+
const result = await executor.createEdge({
|
|
1942
|
+
from_concept_id: toolArgs.from_concept_id,
|
|
1943
|
+
from_label: toolArgs.from_label,
|
|
1944
|
+
to_concept_id: toolArgs.to_concept_id,
|
|
1945
|
+
to_label: toolArgs.to_label,
|
|
1946
|
+
relationship_type: toolArgs.relationship_type,
|
|
1947
|
+
category: toolArgs.category,
|
|
1948
|
+
confidence: toolArgs.confidence,
|
|
1949
|
+
});
|
|
1950
|
+
if (!result.success)
|
|
1951
|
+
throw new Error(result.error);
|
|
1952
|
+
return {
|
|
1953
|
+
content: [{ type: 'text', text: (0, index_js_2.formatGraphEdgeResult)(result.data, 'create') }],
|
|
1954
|
+
};
|
|
1955
|
+
}
|
|
1956
|
+
else {
|
|
1957
|
+
throw new Error(`Unknown entity type: ${entity}`);
|
|
1958
|
+
}
|
|
1959
|
+
}
|
|
1960
|
+
case 'list': {
|
|
1961
|
+
if (entity === 'concept') {
|
|
1962
|
+
const result = await executor.listConcepts({
|
|
1963
|
+
ontology: toolArgs.ontology,
|
|
1964
|
+
label_contains: toolArgs.label_contains,
|
|
1965
|
+
creation_method: toolArgs.creation_method,
|
|
1966
|
+
offset: toolArgs.offset,
|
|
1967
|
+
limit: toolArgs.limit,
|
|
1968
|
+
});
|
|
1969
|
+
if (!result.success)
|
|
1970
|
+
throw new Error(result.error);
|
|
1971
|
+
return {
|
|
1972
|
+
content: [{ type: 'text', text: (0, index_js_2.formatGraphConceptList)(result.data) }],
|
|
1973
|
+
};
|
|
1974
|
+
}
|
|
1975
|
+
else if (entity === 'edge') {
|
|
1976
|
+
const result = await executor.listEdges({
|
|
1977
|
+
from_concept_id: toolArgs.from_concept_id,
|
|
1978
|
+
from_label: toolArgs.from_label,
|
|
1979
|
+
to_concept_id: toolArgs.to_concept_id,
|
|
1980
|
+
to_label: toolArgs.to_label,
|
|
1981
|
+
relationship_type: toolArgs.relationship_type,
|
|
1982
|
+
category: toolArgs.category,
|
|
1983
|
+
source: toolArgs.source,
|
|
1984
|
+
offset: toolArgs.offset,
|
|
1985
|
+
limit: toolArgs.limit,
|
|
1986
|
+
});
|
|
1987
|
+
if (!result.success)
|
|
1988
|
+
throw new Error(result.error);
|
|
1989
|
+
return {
|
|
1990
|
+
content: [{ type: 'text', text: (0, index_js_2.formatGraphEdgeList)(result.data) }],
|
|
1991
|
+
};
|
|
1992
|
+
}
|
|
1993
|
+
else {
|
|
1994
|
+
throw new Error(`Unknown entity type: ${entity}`);
|
|
1995
|
+
}
|
|
1996
|
+
}
|
|
1997
|
+
case 'edit': {
|
|
1998
|
+
if (entity === 'concept') {
|
|
1999
|
+
const result = await executor.editConcept({
|
|
2000
|
+
concept_id: toolArgs.concept_id,
|
|
2001
|
+
label: toolArgs.label,
|
|
2002
|
+
description: toolArgs.description,
|
|
2003
|
+
search_terms: toolArgs.search_terms,
|
|
2004
|
+
});
|
|
2005
|
+
if (!result.success)
|
|
2006
|
+
throw new Error(result.error);
|
|
2007
|
+
return {
|
|
2008
|
+
content: [{ type: 'text', text: (0, index_js_2.formatGraphConceptResult)(result.data, 'edit') }],
|
|
2009
|
+
};
|
|
2010
|
+
}
|
|
2011
|
+
else if (entity === 'edge') {
|
|
2012
|
+
const result = await executor.editEdge({
|
|
2013
|
+
from_concept_id: toolArgs.from_concept_id,
|
|
2014
|
+
from_label: toolArgs.from_label,
|
|
2015
|
+
to_concept_id: toolArgs.to_concept_id,
|
|
2016
|
+
to_label: toolArgs.to_label,
|
|
2017
|
+
relationship_type: toolArgs.relationship_type,
|
|
2018
|
+
confidence: toolArgs.confidence,
|
|
2019
|
+
category: toolArgs.category,
|
|
2020
|
+
});
|
|
2021
|
+
if (!result.success)
|
|
2022
|
+
throw new Error(result.error);
|
|
2023
|
+
return {
|
|
2024
|
+
content: [{ type: 'text', text: (0, index_js_2.formatGraphEdgeResult)(result.data, 'edit') }],
|
|
2025
|
+
};
|
|
2026
|
+
}
|
|
2027
|
+
else {
|
|
2028
|
+
throw new Error(`Unknown entity type: ${entity}`);
|
|
2029
|
+
}
|
|
2030
|
+
}
|
|
2031
|
+
case 'delete': {
|
|
2032
|
+
if (entity === 'concept') {
|
|
2033
|
+
const result = await executor.deleteConcept({
|
|
2034
|
+
concept_id: toolArgs.concept_id,
|
|
2035
|
+
cascade: toolArgs.cascade,
|
|
2036
|
+
});
|
|
2037
|
+
if (!result.success)
|
|
2038
|
+
throw new Error(result.error);
|
|
2039
|
+
return {
|
|
2040
|
+
content: [{ type: 'text', text: (0, index_js_2.formatGraphConceptResult)(result.data, 'delete') }],
|
|
2041
|
+
};
|
|
2042
|
+
}
|
|
2043
|
+
else if (entity === 'edge') {
|
|
2044
|
+
const result = await executor.deleteEdge({
|
|
2045
|
+
from_concept_id: toolArgs.from_concept_id,
|
|
2046
|
+
from_label: toolArgs.from_label,
|
|
2047
|
+
to_concept_id: toolArgs.to_concept_id,
|
|
2048
|
+
to_label: toolArgs.to_label,
|
|
2049
|
+
relationship_type: toolArgs.relationship_type,
|
|
2050
|
+
});
|
|
2051
|
+
if (!result.success)
|
|
2052
|
+
throw new Error(result.error);
|
|
2053
|
+
return {
|
|
2054
|
+
content: [{ type: 'text', text: (0, index_js_2.formatGraphEdgeResult)(result.data, 'delete') }],
|
|
2055
|
+
};
|
|
2056
|
+
}
|
|
2057
|
+
else {
|
|
2058
|
+
throw new Error(`Unknown entity type: ${entity}`);
|
|
2059
|
+
}
|
|
2060
|
+
}
|
|
2061
|
+
case 'queue': {
|
|
2062
|
+
const operations = toolArgs.operations;
|
|
2063
|
+
const continueOnError = toolArgs.continue_on_error === true;
|
|
2064
|
+
if (!operations || !Array.isArray(operations)) {
|
|
2065
|
+
throw new Error('operations array is required for queue action');
|
|
2066
|
+
}
|
|
2067
|
+
if (operations.length === 0) {
|
|
2068
|
+
throw new Error('operations array cannot be empty');
|
|
2069
|
+
}
|
|
2070
|
+
if (operations.length > 20) {
|
|
2071
|
+
throw new Error(`Queue too large: ${operations.length} operations (max 20)`);
|
|
2072
|
+
}
|
|
2073
|
+
const queueResult = await executor.executeQueue(operations, continueOnError);
|
|
2074
|
+
const formattedOutput = (0, index_js_2.formatGraphQueueResult)(queueResult, operations.length);
|
|
2075
|
+
return {
|
|
2076
|
+
content: [{ type: 'text', text: formattedOutput }],
|
|
2077
|
+
};
|
|
2078
|
+
}
|
|
2079
|
+
default:
|
|
2080
|
+
throw new Error(`Unknown graph action: ${action}. Use: create, edit, delete, list, or queue`);
|
|
2081
|
+
}
|
|
2082
|
+
}
|
|
1651
2083
|
default:
|
|
1652
2084
|
throw new Error(`Unknown tool: ${name}`);
|
|
1653
2085
|
}
|