kibi-mcp 0.17.5 → 0.19.2
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/bin/kibi-mcp +1 -1
- package/dist/diagnostics-helpers.js +22 -0
- package/dist/diagnostics.js +113 -4
- package/dist/runtime/mcp-runtime.js +43 -0
- package/dist/server/docs.js +11 -10
- package/dist/server/json-schema-to-zod.js +73 -2
- package/dist/server/session.js +33 -15
- package/dist/server/tool-registration.js +35 -59
- package/dist/server/tools-runtime.js +52 -2
- package/dist/server/tools.js +19 -5
- package/dist/server/transport.js +9 -5
- package/dist/tools/autopilot-generate.js +37 -646
- package/dist/tools/autopilot-test-compat.js +88 -0
- package/dist/tools/autopilot-test-parsers.js +120 -0
- package/dist/tools/check-config.js +67 -0
- package/dist/tools/check-format.js +92 -0
- package/dist/tools/check-impact.js +45 -0
- package/dist/tools/check-prolog.js +51 -0
- package/dist/tools/check.js +13 -190
- package/dist/tools/coverage.js +11 -25
- package/dist/tools/delete.js +5 -112
- package/dist/tools/discovery-adapter.js +23 -0
- package/dist/tools/entity-query.js +1 -111
- package/dist/tools/find-gaps.js +11 -26
- package/dist/tools/graph.js +11 -24
- package/dist/tools/model-requirement.js +8 -347
- package/dist/tools/mutation-context.js +28 -0
- package/dist/tools/query-plan-safety.js +58 -0
- package/dist/tools/query.js +5 -50
- package/dist/tools/relationship-validation.js +11 -0
- package/dist/tools/search.js +4 -37
- package/dist/tools/semantic-advisor.js +2 -40
- package/dist/tools/skills.js +25 -47
- package/dist/tools/sparql.js +12 -93
- package/dist/tools/status.js +5 -19
- package/dist/tools/suggest-predicates.js +11 -2448
- package/dist/tools/upsert.js +21 -794
- package/dist/tools/validate-upsert.js +16 -40
- package/dist/tools-config.js +75 -764
- package/package.json +4 -3
- package/dist/semantic-advisor/analyze-prose.js +0 -1367
- package/dist/semantic-advisor/prose-coverage-evaluator.js +0 -66
- /package/dist/{semantic-advisor/types.js → tools/check-types.js} +0 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getSpec } from "kibi-cli/operations";
|
|
1
2
|
// implements REQ-002, REQ-013
|
|
2
3
|
export function registerConfiguredTools(server, runtime, registerTool) {
|
|
3
4
|
const toolDef = (name) => {
|
|
@@ -6,9 +7,23 @@ export function registerConfiguredTools(server, runtime, registerTool) {
|
|
|
6
7
|
throw new Error(`Unknown tool: ${name}`);
|
|
7
8
|
return t;
|
|
8
9
|
};
|
|
9
|
-
const
|
|
10
|
+
const prologFor = (context) => {
|
|
11
|
+
const prolog = runtime.operationRuntime.sessionProlog(context);
|
|
12
|
+
if (!prolog) {
|
|
13
|
+
throw new Error("Operation requires a session Prolog process");
|
|
14
|
+
}
|
|
15
|
+
return prolog;
|
|
16
|
+
};
|
|
17
|
+
const register = ({ name, execute }) => {
|
|
10
18
|
const definition = toolDef(name);
|
|
11
|
-
|
|
19
|
+
const publicSpec = getSpec(name);
|
|
20
|
+
const spec = {
|
|
21
|
+
name,
|
|
22
|
+
effects: publicSpec.effects,
|
|
23
|
+
requiresProlog: publicSpec.requiresProlog,
|
|
24
|
+
execute: (args, context) => execute(context, args),
|
|
25
|
+
};
|
|
26
|
+
registerTool(server, name, definition.description, definition.inputSchema, async () => undefined, runtime, spec, definition.annotations);
|
|
12
27
|
};
|
|
13
28
|
// INTENTIONAL ARGUMENT CASTS: The `args as (unknown as)? XyzArgs` casts below
|
|
14
29
|
// bridge the generic ToolHandler (which receives Record<string, unknown>) to the
|
|
@@ -16,113 +31,74 @@ export function registerConfiguredTools(server, runtime, registerTool) {
|
|
|
16
31
|
// (via jsonSchemaToZod) before the handler is invoked, so the casts are safe at runtime.
|
|
17
32
|
register({
|
|
18
33
|
name: "kb_query",
|
|
19
|
-
|
|
20
|
-
const prolog = await runtime.ensureProlog();
|
|
21
|
-
return runtime.handleKbQuery(prolog, args);
|
|
22
|
-
},
|
|
34
|
+
execute: async (context, args) => runtime.handleKbQuery(prologFor(context), args),
|
|
23
35
|
});
|
|
24
36
|
register({
|
|
25
37
|
name: "kb_search",
|
|
26
|
-
|
|
27
|
-
const prolog = await runtime.ensureProlog();
|
|
28
|
-
return runtime.handleKbSearch(prolog, args);
|
|
29
|
-
},
|
|
38
|
+
execute: async (context, args) => runtime.handleKbSearch(prologFor(context), args),
|
|
30
39
|
});
|
|
31
40
|
register({
|
|
32
41
|
name: "kb_status",
|
|
33
|
-
|
|
34
|
-
const prolog = await runtime.ensureProlog();
|
|
35
|
-
return runtime.handleKbStatus(prolog, args);
|
|
36
|
-
},
|
|
42
|
+
execute: async (context, args) => runtime.handleKbStatus(prologFor(context), args),
|
|
37
43
|
});
|
|
38
44
|
register({
|
|
39
45
|
name: "kb_skills_list",
|
|
40
|
-
|
|
46
|
+
execute: async (_context, args) => runtime.handleKbSkillsList(args),
|
|
41
47
|
});
|
|
42
48
|
register({
|
|
43
49
|
name: "kb_skills_load",
|
|
44
|
-
|
|
50
|
+
execute: async (_context, args) => runtime.handleKbSkillsLoad(args),
|
|
45
51
|
});
|
|
46
52
|
register({
|
|
47
53
|
name: "kb_skills_read",
|
|
48
|
-
|
|
54
|
+
execute: async (_context, args) => runtime.handleKbSkillsRead(args),
|
|
49
55
|
});
|
|
50
56
|
register({
|
|
51
57
|
name: "kb_find_gaps",
|
|
52
|
-
|
|
53
|
-
const prolog = await runtime.ensureProlog();
|
|
54
|
-
return runtime.handleKbFindGaps(prolog, args);
|
|
55
|
-
},
|
|
58
|
+
execute: async (context, args) => runtime.handleKbFindGaps(prologFor(context), args),
|
|
56
59
|
});
|
|
57
60
|
register({
|
|
58
61
|
name: "kb_coverage",
|
|
59
|
-
|
|
60
|
-
const prolog = await runtime.ensureProlog();
|
|
61
|
-
return runtime.handleKbCoverage(prolog, args);
|
|
62
|
-
},
|
|
62
|
+
execute: async (context, args) => runtime.handleKbCoverage(prologFor(context), args),
|
|
63
63
|
});
|
|
64
64
|
register({
|
|
65
65
|
name: "kb_graph",
|
|
66
|
-
|
|
67
|
-
const prolog = await runtime.ensureProlog();
|
|
68
|
-
return runtime.handleKbGraph(prolog, args);
|
|
69
|
-
},
|
|
66
|
+
execute: async (context, args) => runtime.handleKbGraph(prologFor(context), args),
|
|
70
67
|
});
|
|
71
68
|
register({
|
|
72
69
|
name: "kb_sparql_remote",
|
|
73
|
-
|
|
74
|
-
const prolog = await runtime.ensureProlog();
|
|
75
|
-
return runtime.handleSparql(prolog, args);
|
|
76
|
-
},
|
|
70
|
+
execute: async (context, args) => runtime.handleSparql(args, context),
|
|
77
71
|
});
|
|
78
72
|
register({
|
|
79
73
|
name: "kb_semantic_advisor",
|
|
80
|
-
|
|
74
|
+
execute: async (_context, args) => runtime.handleKbSemanticAdvisor(args),
|
|
81
75
|
});
|
|
82
76
|
register({
|
|
83
77
|
name: "kb_upsert",
|
|
84
|
-
|
|
85
|
-
const prolog = await runtime.ensureProlog();
|
|
86
|
-
return runtime.handleKbUpsert(prolog, args);
|
|
87
|
-
},
|
|
78
|
+
execute: async (context, args) => runtime.handleKbUpsert(prologFor(context), args),
|
|
88
79
|
});
|
|
89
80
|
register({
|
|
90
81
|
name: "kb_validate_upsert",
|
|
91
|
-
|
|
82
|
+
execute: async (context, args) => runtime.handleKbValidateUpsert(prologFor(context), args),
|
|
92
83
|
});
|
|
93
84
|
register({
|
|
94
85
|
name: "kb_delete",
|
|
95
|
-
|
|
96
|
-
const prolog = await runtime.ensureProlog();
|
|
97
|
-
return runtime.handleKbDelete(prolog, args);
|
|
98
|
-
},
|
|
86
|
+
execute: async (context, args) => runtime.handleKbDelete(prologFor(context), args),
|
|
99
87
|
});
|
|
100
88
|
register({
|
|
101
89
|
name: "kb_check",
|
|
102
|
-
|
|
103
|
-
const prolog = await runtime.ensureProlog();
|
|
104
|
-
return runtime.handleKbCheck(prolog, args);
|
|
105
|
-
},
|
|
90
|
+
execute: async (context, args) => runtime.handleKbCheck(prologFor(context), args),
|
|
106
91
|
});
|
|
107
92
|
register({
|
|
108
93
|
name: "kb_model_requirement",
|
|
109
|
-
|
|
110
|
-
const prolog = await runtime.ensureProlog();
|
|
111
|
-
return runtime.handleKbModelRequirement(prolog, args);
|
|
112
|
-
},
|
|
94
|
+
execute: async (context, args) => runtime.handleKbModelRequirement(prologFor(context), args),
|
|
113
95
|
});
|
|
114
96
|
register({
|
|
115
97
|
name: "kb_suggest_predicates",
|
|
116
|
-
|
|
117
|
-
const prolog = await runtime.ensureProlog();
|
|
118
|
-
return runtime.handleKbSuggestPredicates(prolog, args);
|
|
119
|
-
},
|
|
98
|
+
execute: async (context, args) => runtime.handleKbSuggestPredicates(prologFor(context), args),
|
|
120
99
|
});
|
|
121
100
|
register({
|
|
122
101
|
name: "kb_autopilot_generate",
|
|
123
|
-
|
|
124
|
-
const prolog = await runtime.ensureProlog();
|
|
125
|
-
return runtime.handleKbAutopilotGenerate(prolog, args);
|
|
126
|
-
},
|
|
102
|
+
execute: async (context, args) => runtime.handleKbAutopilotGenerate(args, context),
|
|
127
103
|
});
|
|
128
104
|
}
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
+
import { getSpec } from "kibi-cli/operations";
|
|
1
2
|
import { DIAGNOSTIC_MODE_ENABLED, appendUsageLogLine, classifyDiagnosticError, deriveDiagnosticFields, extractToolCallPayload, } from "../diagnostics.js";
|
|
3
|
+
import { isMcpDebugEnabled } from "../env.js";
|
|
4
|
+
import { createMcpRuntime } from "../runtime/mcp-runtime.js";
|
|
2
5
|
import { TOOLS } from "../tools-config.js";
|
|
3
6
|
import { handleKbAutopilotGenerate } from "../tools/autopilot-generate.js";
|
|
4
7
|
import { handleKbCheck } from "../tools/check.js";
|
|
@@ -11,15 +14,17 @@ import { handleKbQuery } from "../tools/query.js";
|
|
|
11
14
|
import { handleKbSearch } from "../tools/search.js";
|
|
12
15
|
import { handleKbSemanticAdvisor } from "../tools/semantic-advisor.js";
|
|
13
16
|
import { handleKbSkillsList, handleKbSkillsLoad, handleKbSkillsRead, } from "../tools/skills.js";
|
|
14
|
-
import { handleSparql } from "../tools/sparql.js";
|
|
15
17
|
import { handleKbStatus } from "../tools/status.js";
|
|
16
18
|
import { handleKbSuggestPredicates } from "../tools/suggest-predicates.js";
|
|
17
19
|
import { handleKbUpsert } from "../tools/upsert.js";
|
|
18
20
|
import { handleKbValidateUpsert } from "../tools/validate-upsert.js";
|
|
21
|
+
import { resolveWorkspaceRoot } from "../workspace.js";
|
|
22
|
+
import { readBranchKbStamp } from "./kb-freshness.js";
|
|
19
23
|
const defaultToolsServerDeps = {
|
|
20
24
|
getSessionModule: () => import("./session.js"),
|
|
21
25
|
};
|
|
22
26
|
let sessionModulePromise = null;
|
|
27
|
+
const prologPorts = new WeakMap();
|
|
23
28
|
// implements REQ-008
|
|
24
29
|
export function _setToolsServerDepsForTests(deps, resetPromise = false) {
|
|
25
30
|
defaultToolsServerDeps.getSessionModule =
|
|
@@ -39,6 +44,50 @@ async function getSessionModule() {
|
|
|
39
44
|
sessionModulePromise ??= defaultToolsServerDeps.getSessionModule();
|
|
40
45
|
return sessionModulePromise;
|
|
41
46
|
}
|
|
47
|
+
function adaptProlog(prolog) {
|
|
48
|
+
const existing = prologPorts.get(prolog);
|
|
49
|
+
if (existing) {
|
|
50
|
+
return existing;
|
|
51
|
+
}
|
|
52
|
+
let lastResult = null;
|
|
53
|
+
const port = {
|
|
54
|
+
query: async (goal) => {
|
|
55
|
+
lastResult = await prolog.query(goal);
|
|
56
|
+
return lastResult;
|
|
57
|
+
},
|
|
58
|
+
nextSolution: async () => {
|
|
59
|
+
const result = lastResult;
|
|
60
|
+
lastResult = null;
|
|
61
|
+
return result;
|
|
62
|
+
},
|
|
63
|
+
save: () => prolog.query("kb_save"),
|
|
64
|
+
};
|
|
65
|
+
prologPorts.set(prolog, port);
|
|
66
|
+
return port;
|
|
67
|
+
}
|
|
68
|
+
const operationRuntime = createMcpRuntime({
|
|
69
|
+
workspaceRoot: resolveWorkspaceRoot(),
|
|
70
|
+
activeBranchName: async () => (await getSessionModule()).activeBranchName,
|
|
71
|
+
attachedBranchKbPath: async () => (await getSessionModule()).attachedBranchKbPath,
|
|
72
|
+
ensureProlog: async () => (await getSessionModule()).ensureProlog(),
|
|
73
|
+
adaptProlog,
|
|
74
|
+
net: { fetch: (input, init) => globalThis.fetch(input, init) },
|
|
75
|
+
refreshAttachedBranchStamp: async () => {
|
|
76
|
+
const session = await getSessionModule();
|
|
77
|
+
const kbPath = session.attachedBranchKbPath;
|
|
78
|
+
if (kbPath) {
|
|
79
|
+
try {
|
|
80
|
+
session.updateAttachedBranchStamp(await readBranchKbStamp(kbPath));
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
84
|
+
if (isMcpDebugEnabled()) {
|
|
85
|
+
console.warn("[KIBI-MCP] Attached branch stamp refresh failed:", message);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
});
|
|
42
91
|
export const DEFAULT_TOOLS_RUNTIME = {
|
|
43
92
|
diagnosticModeEnabled: () => DIAGNOSTIC_MODE_ENABLED,
|
|
44
93
|
appendUsageLogLine,
|
|
@@ -55,12 +104,13 @@ export const DEFAULT_TOOLS_RUNTIME = {
|
|
|
55
104
|
inFlightRequests: async () => (await getSessionModule()).inFlightRequests,
|
|
56
105
|
isShuttingDown: async () => (await getSessionModule()).isShuttingDown,
|
|
57
106
|
prologProcess: async () => (await getSessionModule()).prologProcess,
|
|
107
|
+
operationRuntime,
|
|
58
108
|
handleKbCheck,
|
|
59
109
|
handleKbCoverage,
|
|
60
110
|
handleKbDelete,
|
|
61
111
|
handleKbFindGaps,
|
|
62
112
|
handleKbGraph,
|
|
63
|
-
handleSparql,
|
|
113
|
+
handleSparql: (args, context) => getSpec("kb_sparql_remote").execute(args, context),
|
|
64
114
|
handleKbQuery,
|
|
65
115
|
handleKbSearch,
|
|
66
116
|
handleKbStatus,
|
package/dist/server/tools.js
CHANGED
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
17
|
*/
|
|
18
18
|
import process from "node:process";
|
|
19
|
+
import { executeOperation, } from "kibi-cli/operations/runtime-types";
|
|
19
20
|
import { isMcpDebugEnabled } from "../env.js";
|
|
20
21
|
import { appendDiagnosticErrorUsage, appendDiagnosticSuccessUsage, } from "./diagnostic-usage.js";
|
|
21
22
|
import { jsonSchemaToZod } from "./json-schema-to-zod.js";
|
|
@@ -73,7 +74,7 @@ export function addTool(server, name, description, inputSchema, handler,
|
|
|
73
74
|
// INTENTIONAL: DEFAULT_TOOLS_RUNTIME is typed as ToolsRuntime<PrologProcess>; the
|
|
74
75
|
// generic TProlog parameter exists so tests can inject a mock type. The cast is safe
|
|
75
76
|
// because the runtime object satisfies the full ToolsRuntime contract at runtime.
|
|
76
|
-
runtime = DEFAULT_TOOLS_RUNTIME) {
|
|
77
|
+
runtime = DEFAULT_TOOLS_RUNTIME, spec, annotations) {
|
|
77
78
|
const wrappedHandler = async (args) => {
|
|
78
79
|
const startedAt = new Date();
|
|
79
80
|
const diagnosticModeEnabled = runtime.diagnosticModeEnabled();
|
|
@@ -100,21 +101,30 @@ runtime = DEFAULT_TOOLS_RUNTIME) {
|
|
|
100
101
|
}
|
|
101
102
|
// Track the handler promise in inFlightRequests Map
|
|
102
103
|
const trackedRequests = await runtime.inFlightRequests();
|
|
103
|
-
const
|
|
104
|
+
const controller = new AbortController();
|
|
105
|
+
const operationSpec = spec ?? {
|
|
106
|
+
name,
|
|
107
|
+
effects: ["local-read"],
|
|
108
|
+
requiresProlog: false,
|
|
109
|
+
execute: async (input, _context) => handler(input),
|
|
110
|
+
};
|
|
111
|
+
const handlerPromise = executeOperation(runtime.operationRuntime, operationSpec, businessArgs, { signal: controller.signal });
|
|
104
112
|
trackedRequests.set(requestId, handlerPromise);
|
|
105
113
|
let resetAttempted = false;
|
|
106
114
|
let resetSucceeded = false;
|
|
107
115
|
let resetError = null;
|
|
108
116
|
try {
|
|
109
117
|
// Execute handler
|
|
110
|
-
const result = await withToolTimeout(name, handlerPromise, async () => {
|
|
118
|
+
const result = await withToolTimeout(name, handlerPromise, async (error) => {
|
|
111
119
|
resetAttempted = true;
|
|
120
|
+
controller.abort(error);
|
|
112
121
|
try {
|
|
113
122
|
await runtime.resetProlog(`tool timeout: ${name}`);
|
|
114
123
|
resetSucceeded = true;
|
|
115
124
|
}
|
|
116
125
|
catch (error) {
|
|
117
|
-
resetError =
|
|
126
|
+
resetError =
|
|
127
|
+
error instanceof Error ? error.message : String(error);
|
|
118
128
|
}
|
|
119
129
|
});
|
|
120
130
|
// Log usage in diagnostic mode
|
|
@@ -163,7 +173,11 @@ runtime = DEFAULT_TOOLS_RUNTIME) {
|
|
|
163
173
|
throw new Error(`Tool ${name} failed: ${err.message}`, { cause: err });
|
|
164
174
|
}
|
|
165
175
|
};
|
|
166
|
-
server.registerTool(name, {
|
|
176
|
+
server.registerTool(name, {
|
|
177
|
+
description,
|
|
178
|
+
inputSchema: jsonSchemaToZod(inputSchema),
|
|
179
|
+
...(annotations ? { annotations } : {}),
|
|
180
|
+
}, wrappedHandler);
|
|
167
181
|
}
|
|
168
182
|
// implements REQ-002, REQ-013
|
|
169
183
|
export function registerAllTools(server,
|
package/dist/server/transport.js
CHANGED
|
@@ -23,7 +23,7 @@ function debugLog(...args) {
|
|
|
23
23
|
console.error(...args);
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
|
-
export function setupTransportHandlers(
|
|
26
|
+
export function setupTransportHandlers(_server, transport) {
|
|
27
27
|
transport.onerror = (error) => {
|
|
28
28
|
// Stdio transport surfaces JSON parse / schema validation failures via onerror.
|
|
29
29
|
// Those errors should not crash the server: emit a JSON-RPC error (id omitted)
|
|
@@ -62,11 +62,15 @@ export function setupTransportHandlers(server, transport) {
|
|
|
62
62
|
debugLog("[KIBI-MCP] Transport closed");
|
|
63
63
|
initiateGracefulShutdown(0);
|
|
64
64
|
};
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
65
|
+
for (const signal of ["SIGINT", "SIGTERM"]) {
|
|
66
|
+
process.on(signal, () => {
|
|
67
|
+
debugLog(`[KIBI-MCP] Received ${signal}, initiating graceful shutdown`);
|
|
68
|
+
void initiateGracefulShutdown(0);
|
|
69
|
+
});
|
|
70
|
+
}
|
|
69
71
|
}
|
|
72
|
+
// implements REQ-002
|
|
73
|
+
// covered_by TEST-mcp-kb-freshness
|
|
70
74
|
export async function connectTransport(server, transport) {
|
|
71
75
|
await server.connect(transport);
|
|
72
76
|
}
|