@aaronsb/kg-cli 0.9.4 → 0.10.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 +4 -0
- package/dist/api/client.d.ts.map +1 -1
- package/dist/api/client.js +10 -0
- package/dist/api/client.js.map +1 -1
- package/dist/cli/ai-config/embedding.d.ts +2 -2
- package/dist/cli/ai-config/embedding.d.ts.map +1 -1
- package/dist/cli/ai-config/embedding.js +262 -129
- package/dist/cli/ai-config/embedding.js.map +1 -1
- package/dist/cli/program.d.ts.map +1 -1
- package/dist/cli/program.js +7 -1
- package/dist/cli/program.js.map +1 -1
- package/dist/lib/config.d.ts +18 -0
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +24 -0
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/table.d.ts.map +1 -1
- package/dist/lib/table.js +1 -0
- package/dist/lib/table.js.map +1 -1
- package/dist/mcp/formatters/concept.d.ts.map +1 -1
- package/dist/mcp/formatters/concept.js +6 -1
- package/dist/mcp/formatters/concept.js.map +1 -1
- package/dist/mcp/formatters/index.d.ts +1 -0
- package/dist/mcp/formatters/index.d.ts.map +1 -1
- package/dist/mcp/formatters/index.js +5 -1
- package/dist/mcp/formatters/index.js.map +1 -1
- package/dist/mcp/formatters/job.js +5 -5
- package/dist/mcp/formatters/job.js.map +1 -1
- package/dist/mcp/formatters/session.d.ts +19 -0
- package/dist/mcp/formatters/session.d.ts.map +1 -0
- package/dist/mcp/formatters/session.js +39 -0
- package/dist/mcp/formatters/session.js.map +1 -0
- package/dist/mcp/graph-operations.d.ts.map +1 -1
- package/dist/mcp/graph-operations.js +15 -7
- package/dist/mcp/graph-operations.js.map +1 -1
- package/dist/mcp-server.js +203 -16
- package/dist/mcp-server.js.map +1 -1
- package/dist/types/index.d.ts +1 -1
- 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-server.js
CHANGED
|
@@ -47,6 +47,7 @@ const index_js_1 = require("@modelcontextprotocol/sdk/server/index.js");
|
|
|
47
47
|
const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
48
48
|
const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
|
|
49
49
|
const client_js_1 = require("./api/client.js");
|
|
50
|
+
const config_js_1 = require("./lib/config.js");
|
|
50
51
|
const auth_client_js_1 = require("./lib/auth/auth-client.js");
|
|
51
52
|
const mcp_allowlist_js_1 = require("./lib/mcp-allowlist.js");
|
|
52
53
|
const index_js_2 = require("./mcp/formatters/index.js");
|
|
@@ -220,6 +221,62 @@ function createAuthenticatedClient() {
|
|
|
220
221
|
}
|
|
221
222
|
// Client instance - will be initialized in main() before server starts
|
|
222
223
|
let client;
|
|
224
|
+
/**
|
|
225
|
+
* Fetch recent concepts from the graph for session context.
|
|
226
|
+
* Returns a compact summary and structured data. Fails gracefully if API is unreachable.
|
|
227
|
+
*/
|
|
228
|
+
async function fetchRecentConcepts(limit, ontology) {
|
|
229
|
+
try {
|
|
230
|
+
let query = 'MATCH (c:Concept) WHERE c.created_at_epoch IS NOT NULL';
|
|
231
|
+
if (ontology) {
|
|
232
|
+
// Whitelist validation — ontology names are slugified strings
|
|
233
|
+
if (!/^[a-zA-Z0-9_\-. ()]+$/.test(ontology)) {
|
|
234
|
+
return { summary: `Invalid ontology name: ${ontology}`, concepts: [] };
|
|
235
|
+
}
|
|
236
|
+
query += ` AND c.ontology = '${ontology}'`;
|
|
237
|
+
}
|
|
238
|
+
query += ' RETURN c ORDER BY c.created_at_epoch DESC';
|
|
239
|
+
const result = await client.executeProgram({
|
|
240
|
+
program: {
|
|
241
|
+
version: 1,
|
|
242
|
+
statements: [{
|
|
243
|
+
op: '+',
|
|
244
|
+
operation: { type: 'cypher', query, limit },
|
|
245
|
+
label: 'recent_concepts',
|
|
246
|
+
}],
|
|
247
|
+
},
|
|
248
|
+
});
|
|
249
|
+
const nodes = result.result.nodes || [];
|
|
250
|
+
const concepts = nodes.map((n) => ({
|
|
251
|
+
label: n.label,
|
|
252
|
+
concept_id: n.concept_id,
|
|
253
|
+
ontology: n.ontology ?? null,
|
|
254
|
+
created_at_epoch: n.properties?.created_at_epoch ?? 0,
|
|
255
|
+
}));
|
|
256
|
+
if (concepts.length === 0) {
|
|
257
|
+
return { summary: 'No concepts in the knowledge graph yet.', concepts: [] };
|
|
258
|
+
}
|
|
259
|
+
const labels = concepts.map((c) => c.label).join(' | ');
|
|
260
|
+
return { summary: `Recent concepts (${concepts.length}): ${labels}`, concepts };
|
|
261
|
+
}
|
|
262
|
+
catch {
|
|
263
|
+
return { summary: 'Knowledge graph unavailable — API server may not be running.', concepts: [] };
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Resolve the ontology name for session ingest.
|
|
268
|
+
* Priority: config oauth_client_name > env KG_OAUTH_CLIENT_ID > 'sessions'
|
|
269
|
+
*/
|
|
270
|
+
function getSessionOntology() {
|
|
271
|
+
const config = (0, config_js_1.getConfig)();
|
|
272
|
+
const clientName = config.get('auth.oauth_client_name');
|
|
273
|
+
if (clientName)
|
|
274
|
+
return clientName;
|
|
275
|
+
const envClientId = process.env.KG_OAUTH_CLIENT_ID;
|
|
276
|
+
if (envClientId)
|
|
277
|
+
return envClientId;
|
|
278
|
+
return 'sessions';
|
|
279
|
+
}
|
|
223
280
|
/**
|
|
224
281
|
* Tool Definitions
|
|
225
282
|
*
|
|
@@ -227,6 +284,28 @@ let client;
|
|
|
227
284
|
*/
|
|
228
285
|
// List available tools
|
|
229
286
|
server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => {
|
|
287
|
+
// Build dynamic session context
|
|
288
|
+
const config = (0, config_js_1.getConfig)();
|
|
289
|
+
let sessionContextDescription;
|
|
290
|
+
if (config.getSessionContextEnabled()) {
|
|
291
|
+
const { summary } = await fetchRecentConcepts(config.getSessionContextLimit(), config.getSessionContextOntology());
|
|
292
|
+
sessionContextDescription = `Recent knowledge graph activity. This tool provides active, unsolicited state information about the knowledge graph — what concepts were most recently created or encountered.
|
|
293
|
+
|
|
294
|
+
${summary}
|
|
295
|
+
|
|
296
|
+
Call this tool to refresh context, adjust the limit, or filter by ontology. Results include concept labels, IDs, ontology, and creation epoch.`;
|
|
297
|
+
}
|
|
298
|
+
else {
|
|
299
|
+
sessionContextDescription = 'Read recent knowledge graph activity. Session context is currently disabled in config (~/.config/kg/config.json session.context_enabled).';
|
|
300
|
+
}
|
|
301
|
+
const sessionOntology = getSessionOntology();
|
|
302
|
+
const sessionIngestDescription = `Save a session summary to the knowledge graph for cross-session memory.
|
|
303
|
+
|
|
304
|
+
**IMPORTANT: Before your session ends or context compacts, call this tool with a summary of key topics, decisions, and insights from this session.**
|
|
305
|
+
|
|
306
|
+
Text is ingested into the "${sessionOntology}" ontology, creating concepts that will appear in session_context on your next connection. The ingest job is auto-approved.
|
|
307
|
+
|
|
308
|
+
Input: text (required) — your session summary. Optional: filename for source tracking.`;
|
|
230
309
|
return {
|
|
231
310
|
tools: [
|
|
232
311
|
{
|
|
@@ -257,6 +336,10 @@ RECOMMENDED WORKFLOW: After search, use concept (action: "connect") to find HOW
|
|
|
257
336
|
|
|
258
337
|
For multi-step exploration, compose searches into a GraphProgram (program tool) instead of making individual calls. One program can seed from search, expand relationships, and filter — all server-side in a single round-trip. Use program (action: "list") to find reusable stored programs, or read the program/syntax resource for composition examples.
|
|
259
338
|
|
|
339
|
+
ESCALATION: For analytical questions or exploring more than 2 concepts, go directly to the program tool — one composed query replaces many individual calls.
|
|
340
|
+
|
|
341
|
+
To verify a result, use source to retrieve the original text behind any evidence, or concept (action: "details") to see all evidence and relationships for a concept.
|
|
342
|
+
|
|
260
343
|
Use 2-3 word phrases (e.g., "linear thinking patterns").`,
|
|
261
344
|
inputSchema: {
|
|
262
345
|
type: 'object',
|
|
@@ -298,9 +381,11 @@ Use 2-3 word phrases (e.g., "linear thinking patterns").`,
|
|
|
298
381
|
name: 'concept',
|
|
299
382
|
description: `Work with concepts: get details (ALL evidence + relationships), find related concepts (neighborhood exploration), or discover connections (paths between concepts).
|
|
300
383
|
|
|
301
|
-
For "connect" action, defaults (threshold=0.5, max_hops=5) match the CLI and work well for most queries. Use higher thresholds (0.75+) only if you need to narrow results for precision.
|
|
384
|
+
For "connect" action, defaults (threshold=0.5, max_hops=5) match the CLI and work well for most queries. Use higher thresholds (0.75+) only if you need to narrow results for precision. Note: connect traverses semantic edges only (IMPLIES, SUPPORTS, CONTRADICTS, etc.) — manually-created edges with no traversal history may not appear in paths. Use program/Cypher for comprehensive traversal.
|
|
385
|
+
|
|
386
|
+
If connect returns no paths or you need to combine multiple lookups, escalate to the program tool — one composed query replaces many individual calls. Do not repeat connect hoping for different results.
|
|
302
387
|
|
|
303
|
-
For multi-step workflows (search → connect → expand → filter), compose these into a GraphProgram instead of making individual calls. See the program tool and program/syntax resource.`,
|
|
388
|
+
For multi-step workflows (search → connect → expand → filter), compose these into a GraphProgram instead of making individual calls. For example, seed from a search then expand via Cypher using $W_IDS to reference accumulated concept IDs. See the program tool and program/syntax resource for this and other composition patterns.`,
|
|
304
389
|
inputSchema: {
|
|
305
390
|
type: 'object',
|
|
306
391
|
properties: {
|
|
@@ -343,7 +428,7 @@ For multi-step workflows (search → connect → expand → filter), compose the
|
|
|
343
428
|
relationship_types: {
|
|
344
429
|
type: 'array',
|
|
345
430
|
items: { type: 'string' },
|
|
346
|
-
description: 'Filter relationships (e.g., ["SUPPORTS", "CONTRADICTS"])',
|
|
431
|
+
description: 'Filter relationships (e.g., ["SUPPORTS", "CONTRADICTS"]). Constrains traversal, not just results — if the first hop is structural, filtering to semantic types may return empty. Omit for broadest results, then narrow.',
|
|
347
432
|
},
|
|
348
433
|
// ADR-065: Epistemic status filtering (for related and connect)
|
|
349
434
|
include_epistemic_status: {
|
|
@@ -626,7 +711,9 @@ Use when you need to:
|
|
|
626
711
|
- Verify extracted concepts against original source
|
|
627
712
|
- Get the full context of a text passage
|
|
628
713
|
- Retrieve images for visual analysis
|
|
629
|
-
- Check character offsets for highlighting
|
|
714
|
+
- Check character offsets for highlighting
|
|
715
|
+
|
|
716
|
+
Source IDs appear in search results and concept details evidence. Use concept (action: "details") to see all evidence for a concept, or search (type: "sources") to find passages directly.`,
|
|
630
717
|
inputSchema: {
|
|
631
718
|
type: 'object',
|
|
632
719
|
properties: {
|
|
@@ -655,7 +742,9 @@ EPISTEMIC STATUS CLASSIFICATIONS:
|
|
|
655
742
|
- INSUFFICIENT_DATA: <3 successful measurements
|
|
656
743
|
- UNCLASSIFIED: Doesn't fit known patterns
|
|
657
744
|
|
|
658
|
-
Use for filtering relationships by epistemic reliability, identifying contested knowledge areas, and curating high-confidence vs exploratory subgraphs
|
|
745
|
+
Use for filtering relationships by epistemic reliability, identifying contested knowledge areas, and curating high-confidence vs exploratory subgraphs.
|
|
746
|
+
|
|
747
|
+
Concept (action: "related") and connect accept include_epistemic_status/exclude_epistemic_status filters to narrow traversals by reliability. Use search to find concepts in contested areas, then epistemic_status to understand why.`,
|
|
659
748
|
inputSchema: {
|
|
660
749
|
type: 'object',
|
|
661
750
|
properties: {
|
|
@@ -711,7 +800,9 @@ Use Cases:
|
|
|
711
800
|
- Explore conceptual spectrums and gradients
|
|
712
801
|
- Identify position-grounding correlation patterns
|
|
713
802
|
- Discover concepts balanced between opposing ideas
|
|
714
|
-
- Map semantic dimensions in the knowledge graph
|
|
803
|
+
- Map semantic dimensions in the knowledge graph
|
|
804
|
+
|
|
805
|
+
Requires concept IDs for poles — use search to find opposing concepts first. Use concept (action: "details") to inspect pole concepts before analysis.`,
|
|
715
806
|
inputSchema: {
|
|
716
807
|
type: 'object',
|
|
717
808
|
properties: {
|
|
@@ -811,7 +902,7 @@ Three actions available:
|
|
|
811
902
|
- "concepts": Get all concepts extracted from a document
|
|
812
903
|
|
|
813
904
|
Documents are aggregated from source chunks and stored in Garage (S3-compatible storage).
|
|
814
|
-
Use search tool with type="documents" to find documents semantically.`,
|
|
905
|
+
Use search tool with type="documents" to find documents semantically. Use document (action: "concepts") to see what was extracted, then concept (action: "details") or source to drill into specifics.`,
|
|
815
906
|
inputSchema: {
|
|
816
907
|
type: 'object',
|
|
817
908
|
properties: {
|
|
@@ -875,7 +966,8 @@ Use for manual curation, agent-driven knowledge building, and precise graph mani
|
|
|
875
966
|
|
|
876
967
|
**Semantic Resolution:**
|
|
877
968
|
- Use \`from_label\`/\`to_label\` to reference concepts by name instead of ID
|
|
878
|
-
- Resolution uses vector similarity (
|
|
969
|
+
- Resolution uses vector similarity (75% threshold) to find matching concepts
|
|
970
|
+
- Near-misses (60-75%) return "Did you mean?" suggestions with concept IDs
|
|
879
971
|
|
|
880
972
|
**Examples:**
|
|
881
973
|
- Create concept: \`{action: "create", entity: "concept", label: "CAP Theorem", ontology: "distributed-systems"}\`
|
|
@@ -894,7 +986,7 @@ Use for manual curation, agent-driven knowledge building, and precise graph mani
|
|
|
894
986
|
]
|
|
895
987
|
}
|
|
896
988
|
\`\`\`
|
|
897
|
-
Queue executes sequentially,
|
|
989
|
+
Queue executes sequentially, continues past errors by default (set continue_on_error=false to stop on first error). Max 20 operations.`,
|
|
898
990
|
inputSchema: {
|
|
899
991
|
type: 'object',
|
|
900
992
|
properties: {
|
|
@@ -939,8 +1031,8 @@ Queue executes sequentially, stops on first error (unless continue_on_error=true
|
|
|
939
1031
|
},
|
|
940
1032
|
continue_on_error: {
|
|
941
1033
|
type: 'boolean',
|
|
942
|
-
description: 'For queue: continue executing after errors (default: false
|
|
943
|
-
default:
|
|
1034
|
+
description: 'For queue: continue executing after errors (default: true). Set false to stop on first error.',
|
|
1035
|
+
default: true,
|
|
944
1036
|
},
|
|
945
1037
|
// Concept fields
|
|
946
1038
|
label: {
|
|
@@ -1042,6 +1134,8 @@ Queue executes sequentially, stops on first error (unless continue_on_error=true
|
|
|
1042
1134
|
name: 'program',
|
|
1043
1135
|
description: `Compose and execute GraphProgram queries against the knowledge graph (ADR-500).
|
|
1044
1136
|
|
|
1137
|
+
Use search/connect/related for quick lookups (one concept, one path). Use program when you need the neighborhood of more than 2 concepts, want to combine search with traversal, or are asking an analytical question about graph structure. If you've made 3+ individual tool calls without converging, you should already be here.
|
|
1138
|
+
|
|
1045
1139
|
Programs are JSON ASTs that compose Cypher queries and API calls using set-algebra operators.
|
|
1046
1140
|
Each statement applies an operator to merge/filter results into a mutable Working Graph (W).
|
|
1047
1141
|
|
|
@@ -1067,6 +1161,11 @@ Each statement applies an operator to merge/filter results into a mutable Workin
|
|
|
1067
1161
|
{ type: "cypher", query: "MATCH (c:Concept)-[r]->(t:Concept) RETURN c, r, t", limit?: 20 }
|
|
1068
1162
|
Queries must be read-only (no CREATE/SET/DELETE/MERGE). RETURN nodes and relationships.
|
|
1069
1163
|
|
|
1164
|
+
**AGE Cypher gotchas** (Apache AGE openCypher differs from Neo4j):
|
|
1165
|
+
- Filter relationship types with WHERE, not inline: \`WHERE type(r) IN ['SUPPORTS', 'CONTRADICTS']\` (NOT \`[r:SUPPORTS|CONTRADICTS]\`)
|
|
1166
|
+
- Reference working graph concepts: \`WHERE c.concept_id IN $W_IDS\`
|
|
1167
|
+
- Always RETURN both nodes and relationships for full path data
|
|
1168
|
+
|
|
1070
1169
|
**ApiOp** — call internal service functions (no HTTP):
|
|
1071
1170
|
{ type: "api", endpoint: "/search/concepts", params: { query: "...", limit: 10 } }
|
|
1072
1171
|
|
|
@@ -1074,7 +1173,7 @@ Each statement applies an operator to merge/filter results into a mutable Workin
|
|
|
1074
1173
|
/search/concepts — params: query (required), min_similarity?, limit?
|
|
1075
1174
|
/search/sources — params: query (required), min_similarity?, limit?
|
|
1076
1175
|
/concepts/details — params: concept_id (required)
|
|
1077
|
-
/concepts/related — params: concept_id (required), max_depth?, relationship_types?
|
|
1176
|
+
/concepts/related — params: concept_id (required), max_depth?, relationship_types? [returns nodes + edges in programs]
|
|
1078
1177
|
/concepts/batch — params: concept_ids (required, list)
|
|
1079
1178
|
/vocabulary/status — params: relationship_type?, status_filter?
|
|
1080
1179
|
|
|
@@ -1087,6 +1186,9 @@ Each statement applies an operator to merge/filter results into a mutable Workin
|
|
|
1087
1186
|
label: "expand relationships" }
|
|
1088
1187
|
]}
|
|
1089
1188
|
|
|
1189
|
+
**Alternative** — API-only composition (no Cypher needed):
|
|
1190
|
+
Use /concepts/related to expand from a known concept ID. Inside programs, related returns both nodes and edges (topology), making it suitable for graph exploration without writing Cypher.
|
|
1191
|
+
|
|
1090
1192
|
Read the program/syntax resource for the complete language reference with more examples.`,
|
|
1091
1193
|
inputSchema: {
|
|
1092
1194
|
type: 'object',
|
|
@@ -1136,6 +1238,43 @@ Read the program/syntax resource for the complete language reference with more e
|
|
|
1136
1238
|
required: ['action'],
|
|
1137
1239
|
},
|
|
1138
1240
|
},
|
|
1241
|
+
{
|
|
1242
|
+
name: 'session_context',
|
|
1243
|
+
description: sessionContextDescription,
|
|
1244
|
+
inputSchema: {
|
|
1245
|
+
type: 'object',
|
|
1246
|
+
properties: {
|
|
1247
|
+
limit: {
|
|
1248
|
+
type: 'number',
|
|
1249
|
+
description: 'Maximum concepts to return (default: 10, max: 50)',
|
|
1250
|
+
default: 10,
|
|
1251
|
+
},
|
|
1252
|
+
ontology: {
|
|
1253
|
+
type: 'string',
|
|
1254
|
+
description: 'Filter by ontology name (default: all ontologies)',
|
|
1255
|
+
},
|
|
1256
|
+
},
|
|
1257
|
+
required: [],
|
|
1258
|
+
},
|
|
1259
|
+
},
|
|
1260
|
+
{
|
|
1261
|
+
name: 'session_ingest',
|
|
1262
|
+
description: sessionIngestDescription,
|
|
1263
|
+
inputSchema: {
|
|
1264
|
+
type: 'object',
|
|
1265
|
+
properties: {
|
|
1266
|
+
text: {
|
|
1267
|
+
type: 'string',
|
|
1268
|
+
description: 'Session summary text to ingest into the knowledge graph',
|
|
1269
|
+
},
|
|
1270
|
+
filename: {
|
|
1271
|
+
type: 'string',
|
|
1272
|
+
description: 'Optional filename for source tracking (e.g., "session-2025-01-15.md")',
|
|
1273
|
+
},
|
|
1274
|
+
},
|
|
1275
|
+
required: ['text'],
|
|
1276
|
+
},
|
|
1277
|
+
},
|
|
1139
1278
|
],
|
|
1140
1279
|
};
|
|
1141
1280
|
});
|
|
@@ -2347,7 +2486,7 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
2347
2486
|
}
|
|
2348
2487
|
case 'queue': {
|
|
2349
2488
|
const operations = toolArgs.operations;
|
|
2350
|
-
const continueOnError = toolArgs.continue_on_error
|
|
2489
|
+
const continueOnError = toolArgs.continue_on_error !== false;
|
|
2351
2490
|
if (!operations || !Array.isArray(operations)) {
|
|
2352
2491
|
throw new Error('operations array is required for queue action');
|
|
2353
2492
|
}
|
|
@@ -2483,6 +2622,11 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
2483
2622
|
});
|
|
2484
2623
|
const lines = [];
|
|
2485
2624
|
const totalMs = result.log.reduce((sum, e) => sum + e.duration_ms, 0);
|
|
2625
|
+
// Build id → label map for readable link output
|
|
2626
|
+
const nodeLabels = new Map();
|
|
2627
|
+
for (const node of result.result.nodes) {
|
|
2628
|
+
nodeLabels.set(node.concept_id, node.label);
|
|
2629
|
+
}
|
|
2486
2630
|
if (result.aborted) {
|
|
2487
2631
|
lines.push(`✗ Aborted at statement ${result.aborted.statement}: ${result.aborted.reason}`);
|
|
2488
2632
|
}
|
|
@@ -2516,7 +2660,9 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
2516
2660
|
if (result.result.links.length > 0) {
|
|
2517
2661
|
lines.push('\nLinks:');
|
|
2518
2662
|
for (const link of result.result.links.slice(0, 30)) {
|
|
2519
|
-
|
|
2663
|
+
const from = nodeLabels.get(link.from_id) || link.from_id;
|
|
2664
|
+
const to = nodeLabels.get(link.to_id) || link.to_id;
|
|
2665
|
+
lines.push(` ${from} → ${link.relationship_type} → ${to}`);
|
|
2520
2666
|
}
|
|
2521
2667
|
if (result.result.links.length > 30) {
|
|
2522
2668
|
lines.push(` ... and ${result.result.links.length - 30} more`);
|
|
@@ -2579,6 +2725,11 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
2579
2725
|
try {
|
|
2580
2726
|
const result = await client.chainPrograms(toolArgs.deck);
|
|
2581
2727
|
const lines = [];
|
|
2728
|
+
// Build id → label map for readable link output
|
|
2729
|
+
const nodeLabels = new Map();
|
|
2730
|
+
for (const node of result.result.nodes) {
|
|
2731
|
+
nodeLabels.set(node.concept_id, node.label);
|
|
2732
|
+
}
|
|
2582
2733
|
if (result.aborted) {
|
|
2583
2734
|
lines.push(`✗ Chain aborted at statement ${result.aborted.statement}: ${result.aborted.reason}`);
|
|
2584
2735
|
}
|
|
@@ -2609,7 +2760,9 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
2609
2760
|
if (result.result.links.length > 0) {
|
|
2610
2761
|
lines.push('\nLinks:');
|
|
2611
2762
|
for (const link of result.result.links.slice(0, 30)) {
|
|
2612
|
-
|
|
2763
|
+
const from = nodeLabels.get(link.from_id) || link.from_id;
|
|
2764
|
+
const to = nodeLabels.get(link.to_id) || link.to_id;
|
|
2765
|
+
lines.push(` ${from} → ${link.relationship_type} → ${to}`);
|
|
2613
2766
|
}
|
|
2614
2767
|
if (result.result.links.length > 30) {
|
|
2615
2768
|
lines.push(` ... and ${result.result.links.length - 30} more`);
|
|
@@ -2634,6 +2787,39 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
2634
2787
|
throw new Error(`Unknown program action: ${action}. Use: validate, create, get, list, execute, or chain`);
|
|
2635
2788
|
}
|
|
2636
2789
|
}
|
|
2790
|
+
case 'session_context': {
|
|
2791
|
+
const limit = Math.min(toolArgs.limit || 10, 50);
|
|
2792
|
+
const ontology = toolArgs.ontology || null;
|
|
2793
|
+
const { summary, concepts } = await fetchRecentConcepts(limit, ontology);
|
|
2794
|
+
return {
|
|
2795
|
+
content: [{
|
|
2796
|
+
type: 'text',
|
|
2797
|
+
text: (0, index_js_2.formatSessionContext)(concepts, summary),
|
|
2798
|
+
}],
|
|
2799
|
+
};
|
|
2800
|
+
}
|
|
2801
|
+
case 'session_ingest': {
|
|
2802
|
+
const text = toolArgs.text;
|
|
2803
|
+
if (!text) {
|
|
2804
|
+
throw new Error('text is required');
|
|
2805
|
+
}
|
|
2806
|
+
const ontology = getSessionOntology();
|
|
2807
|
+
const result = await client.ingestText(text, {
|
|
2808
|
+
ontology,
|
|
2809
|
+
filename: toolArgs.filename || undefined,
|
|
2810
|
+
auto_approve: true,
|
|
2811
|
+
force: false,
|
|
2812
|
+
processing_mode: 'serial',
|
|
2813
|
+
options: {
|
|
2814
|
+
target_words: 1000,
|
|
2815
|
+
overlap_words: 200,
|
|
2816
|
+
},
|
|
2817
|
+
source_type: 'mcp',
|
|
2818
|
+
});
|
|
2819
|
+
return {
|
|
2820
|
+
content: [{ type: 'text', text: (0, index_js_2.formatSessionIngest)(result) }],
|
|
2821
|
+
};
|
|
2822
|
+
}
|
|
2637
2823
|
default:
|
|
2638
2824
|
throw new Error(`Unknown tool: ${name}`);
|
|
2639
2825
|
}
|
|
@@ -2850,7 +3036,8 @@ Allowed endpoints and their parameters:
|
|
|
2850
3036
|
/concepts/related
|
|
2851
3037
|
Required: concept_id (string)
|
|
2852
3038
|
Optional: max_depth (integer, default 2), relationship_types (string array)
|
|
2853
|
-
Returns: neighborhood concept nodes
|
|
3039
|
+
Returns: neighborhood concept nodes + edges between them (full topology).
|
|
3040
|
+
Note: relationship_types constrains traversal — omit for broadest results.
|
|
2854
3041
|
|
|
2855
3042
|
/concepts/batch
|
|
2856
3043
|
Required: concept_ids (string array)
|