kibi-mcp 0.19.0 → 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/runtime/mcp-runtime.js +43 -0
- package/dist/server/docs.js +4 -4
- package/dist/server/json-schema-to-zod.js +73 -2
- package/dist/server/session.js +33 -15
- package/dist/server/tool-registration.js +35 -62
- 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.js +13 -106
- 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.js +5 -50
- package/dist/tools/relationship-validation.js +9 -116
- package/dist/tools/search.js +4 -37
- package/dist/tools/semantic-advisor.js +2 -40
- package/dist/tools/skills.js +17 -57
- 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 -816
- package/dist/tools/validate-upsert.js +12 -48
- package/dist/tools-config.js +75 -802
- package/package.json +4 -3
- package/dist/semantic-advisor/analyze-prose.js +0 -1392
- package/dist/semantic-advisor/prose-coverage-evaluator.js +0 -66
- package/dist/semantic-advisor/types.js +0 -1
|
@@ -1,42 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
function normalizeText(value) {
|
|
3
|
-
const text = typeof value === "string" ? value.trim() : "";
|
|
4
|
-
if (!text) {
|
|
5
|
-
throw new Error("Semantic advisor failed: text must be a non-empty string");
|
|
6
|
-
}
|
|
7
|
-
return text;
|
|
8
|
-
}
|
|
9
|
-
function optionalString(value) {
|
|
10
|
-
const text = typeof value === "string" ? value.trim() : "";
|
|
11
|
-
return text.length > 0 ? text : undefined;
|
|
12
|
-
}
|
|
1
|
+
import { executeSemanticAdvisor } from "kibi-cli/operations";
|
|
13
2
|
export async function handleKbSemanticAdvisor(args) {
|
|
14
|
-
|
|
15
|
-
const id = optionalString(args.id) ?? "REQ-SEMANTIC-ADVISOR-PREVIEW";
|
|
16
|
-
const title = optionalString(args.title) ?? text.split(/[.!?]/, 1)[0] ?? text;
|
|
17
|
-
const source = optionalString(args.source) ?? "mcp://kibi/semantic-advisor";
|
|
18
|
-
const result = analyzeSemanticAdvisorInput({
|
|
19
|
-
payload: {
|
|
20
|
-
type: optionalString(args.type) ?? "req",
|
|
21
|
-
id,
|
|
22
|
-
properties: {
|
|
23
|
-
title,
|
|
24
|
-
status: optionalString(args.status) ?? "open",
|
|
25
|
-
source,
|
|
26
|
-
text_ref: text,
|
|
27
|
-
},
|
|
28
|
-
},
|
|
29
|
-
});
|
|
30
|
-
return {
|
|
31
|
-
content: [
|
|
32
|
-
{
|
|
33
|
-
type: "text",
|
|
34
|
-
text: `kb_semantic_advisor: ${result.receipt.summary} Suggestions: ${result.receipt.suggestions.map((suggestion) => suggestion.kind).join(", ") || "none"}.`,
|
|
35
|
-
},
|
|
36
|
-
],
|
|
37
|
-
structuredContent: {
|
|
38
|
-
receipt: result.receipt,
|
|
39
|
-
warnings: result.warnings,
|
|
40
|
-
},
|
|
41
|
-
};
|
|
3
|
+
return executeSemanticAdvisor(args);
|
|
42
4
|
}
|
package/dist/tools/skills.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { skillsListSpec, skillsLoadSpec, skillsReadSpec, } from "kibi-cli/operations";
|
|
2
|
+
import { loadBundledSkill } from "kibi-cli/skills";
|
|
3
|
+
function runtimeContext() {
|
|
4
|
+
return {
|
|
5
|
+
workspaceRoot: process.cwd(),
|
|
6
|
+
signal: new AbortController().signal,
|
|
7
|
+
clock: () => new Date(),
|
|
8
|
+
};
|
|
9
|
+
}
|
|
3
10
|
// implements REQ-001
|
|
4
11
|
export async function handleKbSkillsList(_args) {
|
|
5
12
|
try {
|
|
6
|
-
|
|
7
|
-
const ids = skills.map((skill) => skill.id).join(", ") || "none";
|
|
8
|
-
return {
|
|
9
|
-
content: [
|
|
10
|
-
{ type: "text", text: `Found ${skills.length} bundled skills: ${ids}` },
|
|
11
|
-
],
|
|
12
|
-
structuredContent: { skills },
|
|
13
|
-
};
|
|
13
|
+
return await skillsListSpec.execute({}, runtimeContext());
|
|
14
14
|
}
|
|
15
15
|
catch (error) {
|
|
16
16
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -20,27 +20,7 @@ export async function handleKbSkillsList(_args) {
|
|
|
20
20
|
// implements REQ-001
|
|
21
21
|
export async function handleKbSkillsLoad(args) {
|
|
22
22
|
try {
|
|
23
|
-
|
|
24
|
-
const bundle = loadBundledSkill(args.id);
|
|
25
|
-
const resources = bundle.manifest.resources ?? [];
|
|
26
|
-
const payload = {
|
|
27
|
-
metadata: bundle.manifest,
|
|
28
|
-
body: bundle.body,
|
|
29
|
-
resources,
|
|
30
|
-
contentHash: createHash("sha256")
|
|
31
|
-
.update(bundle.body, "utf8")
|
|
32
|
-
.digest("hex"),
|
|
33
|
-
sourceType: "bundled",
|
|
34
|
-
};
|
|
35
|
-
return {
|
|
36
|
-
content: [
|
|
37
|
-
{
|
|
38
|
-
type: "text",
|
|
39
|
-
text: `Loaded bundled skill ${bundle.manifest.id} with ${resources.length} resources: ${formatResourceList(resources)}`,
|
|
40
|
-
},
|
|
41
|
-
],
|
|
42
|
-
structuredContent: payload,
|
|
43
|
-
};
|
|
23
|
+
return await skillsLoadSpec.execute(args, runtimeContext());
|
|
44
24
|
}
|
|
45
25
|
catch (error) {
|
|
46
26
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -50,44 +30,24 @@ export async function handleKbSkillsLoad(args) {
|
|
|
50
30
|
// implements REQ-001
|
|
51
31
|
export async function handleKbSkillsRead(args) {
|
|
52
32
|
try {
|
|
53
|
-
|
|
54
|
-
assertNonEmptyString(args.resource, "resource");
|
|
55
|
-
const resourceContent = readBundledSkillResource(args.id, args.resource);
|
|
56
|
-
return {
|
|
57
|
-
content: [
|
|
58
|
-
{
|
|
59
|
-
type: "text",
|
|
60
|
-
text: `Read bundled skill resource ${args.id}/${args.resource}`,
|
|
61
|
-
},
|
|
62
|
-
],
|
|
63
|
-
structuredContent: { content: resourceContent },
|
|
64
|
-
};
|
|
33
|
+
return await skillsReadSpec.execute(args, runtimeContext());
|
|
65
34
|
}
|
|
66
35
|
catch (error) {
|
|
67
36
|
const message = error instanceof Error ? error.message : String(error);
|
|
68
37
|
throw new Error(`Skills read failed: ${message}${resourceListHint(args.id)}`);
|
|
69
38
|
}
|
|
70
39
|
}
|
|
71
|
-
function formatResourceList(resources) {
|
|
72
|
-
return resources.length === 0 ? "none" : resources.join(", ");
|
|
73
|
-
}
|
|
74
40
|
function resourceListHint(id) {
|
|
75
41
|
if (typeof id !== "string" || id.trim() === "") {
|
|
76
42
|
return "";
|
|
77
43
|
}
|
|
78
44
|
try {
|
|
79
45
|
const bundle = loadBundledSkill(id);
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
if (error instanceof Error) {
|
|
84
|
-
return "";
|
|
85
|
-
}
|
|
86
|
-
throw error;
|
|
46
|
+
const resources = bundle.manifest.resources ?? [];
|
|
47
|
+
const resourceList = resources.length === 0 ? "none" : resources.join(", ");
|
|
48
|
+
return `. Declared resources: ${resourceList}`;
|
|
87
49
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
if (typeof value !== "string" || value.trim() === "") {
|
|
91
|
-
throw new Error(`${field} must be a non-empty string`);
|
|
50
|
+
catch {
|
|
51
|
+
return "";
|
|
92
52
|
}
|
|
93
53
|
}
|
package/dist/tools/sparql.js
CHANGED
|
@@ -1,96 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
// implements REQ-002, REQ-013
|
|
3
|
-
export async function handleSparql(
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const payload = await runJsonModuleQuery(prolog, "sparql_client.pl", `kibi_sparql_client:remote_sparql_select_json(${toPrologAtom(args.endpoint)}, ${toPrologAtom(args.query)}, ${toSparqlOptions(args)}, JsonString)`, "SPARQL remote query");
|
|
7
|
-
const rows = payload?.rows ?? [];
|
|
8
|
-
return {
|
|
9
|
-
content: [
|
|
10
|
-
{
|
|
11
|
-
type: "text",
|
|
12
|
-
text: `Remote SPARQL query returned ${rows.length} row${rows.length === 1 ? "" : "s"}.`,
|
|
13
|
-
},
|
|
14
|
-
],
|
|
15
|
-
...(payload !== undefined ? { structuredContent: payload } : {}),
|
|
16
|
-
};
|
|
17
|
-
}
|
|
18
|
-
catch (error) {
|
|
19
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
20
|
-
throw new Error(`SPARQL remote query failed: ${message}`);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
function validateSparqlArgs(args) {
|
|
24
|
-
if (!args.endpoint || args.endpoint.trim().length === 0) {
|
|
1
|
+
import { sparqlRemoteSpec } from "kibi-cli/operations";
|
|
2
|
+
// implements REQ-002, REQ-013, REQ-kibi-operation-interface-parity
|
|
3
|
+
export async function handleSparql(prologOrArgs, legacyArgs) {
|
|
4
|
+
const args = legacyArgs ?? ("endpoint" in prologOrArgs ? prologOrArgs : undefined);
|
|
5
|
+
if (args === undefined) {
|
|
25
6
|
throw new Error("SPARQL endpoint is required");
|
|
26
7
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
throw new Error("SPARQL query must be a SELECT query");
|
|
35
|
-
}
|
|
36
|
-
if (!isPublicRemoteEndpoint(args.endpoint)) {
|
|
37
|
-
throw new Error("SPARQL endpoint must target a public remote host");
|
|
38
|
-
}
|
|
39
|
-
if (args.timeoutMs !== undefined &&
|
|
40
|
-
(!Number.isFinite(args.timeoutMs) || args.timeoutMs <= 0)) {
|
|
41
|
-
throw new Error("SPARQL timeoutMs must be a positive number when provided");
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
function isRemoteHttpEndpoint(endpoint) {
|
|
45
|
-
try {
|
|
46
|
-
const url = new URL(endpoint);
|
|
47
|
-
return url.protocol === "http:" || url.protocol === "https:";
|
|
48
|
-
}
|
|
49
|
-
catch {
|
|
50
|
-
return false;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
function isSelectQuery(query) {
|
|
54
|
-
return /^\s*select\b/i.test(query);
|
|
55
|
-
}
|
|
56
|
-
function isPublicRemoteEndpoint(endpoint) {
|
|
57
|
-
const url = new URL(endpoint);
|
|
58
|
-
const host = normalizeHostname(url.hostname);
|
|
59
|
-
return !isLocalOrPrivateHost(host);
|
|
60
|
-
}
|
|
61
|
-
function normalizeHostname(hostname) {
|
|
62
|
-
return hostname
|
|
63
|
-
.toLowerCase()
|
|
64
|
-
.replace(/^\[/, "")
|
|
65
|
-
.replace(/\]$/, "")
|
|
66
|
-
.replace(/\.$/, "");
|
|
67
|
-
}
|
|
68
|
-
function isLocalOrPrivateHost(host) {
|
|
69
|
-
if (host === "localhost" ||
|
|
70
|
-
host.endsWith(".localhost") ||
|
|
71
|
-
host === "0.0.0.0" ||
|
|
72
|
-
host === "::1" ||
|
|
73
|
-
(host.includes(":") &&
|
|
74
|
-
(host.startsWith("fe80:") ||
|
|
75
|
-
host.startsWith("fc") ||
|
|
76
|
-
host.startsWith("fd")))) {
|
|
77
|
-
return true;
|
|
78
|
-
}
|
|
79
|
-
const octets = host.split(".").map((part) => Number(part));
|
|
80
|
-
if (octets.length !== 4 || octets.some((octet) => !Number.isInteger(octet))) {
|
|
81
|
-
return false;
|
|
82
|
-
}
|
|
83
|
-
const [first = -1, second = -1] = octets;
|
|
84
|
-
return (first === 10 ||
|
|
85
|
-
first === 127 ||
|
|
86
|
-
(first === 169 && second === 254) ||
|
|
87
|
-
(first === 172 && second >= 16 && second <= 31) ||
|
|
88
|
-
(first === 192 && second === 168));
|
|
89
|
-
}
|
|
90
|
-
function toSparqlOptions(args) {
|
|
91
|
-
if (args.timeoutMs === undefined) {
|
|
92
|
-
return "[]";
|
|
93
|
-
}
|
|
94
|
-
const timeoutSeconds = Math.max(1, Math.ceil(args.timeoutMs / 1000));
|
|
95
|
-
return `[timeout(${timeoutSeconds})]`;
|
|
8
|
+
const context = {
|
|
9
|
+
workspaceRoot: process.cwd(),
|
|
10
|
+
signal: new AbortController().signal,
|
|
11
|
+
clock: () => new Date(),
|
|
12
|
+
net: { fetch: (input, init) => globalThis.fetch(input, init) },
|
|
13
|
+
};
|
|
14
|
+
return sparqlRemoteSpec.execute(args, context);
|
|
96
15
|
}
|
package/dist/tools/status.js
CHANGED
|
@@ -1,20 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
export async function handleKbStatus(prolog,
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
return {
|
|
7
|
-
content: [
|
|
8
|
-
{
|
|
9
|
-
type: "text",
|
|
10
|
-
text: `Branch ${payload.branch} is ${payload.syncState} (snapshot ${payload.snapshotId}, dirty=${payload.dirty})`,
|
|
11
|
-
},
|
|
12
|
-
],
|
|
13
|
-
structuredContent: payload,
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
|
-
catch (error) {
|
|
17
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
18
|
-
throw new Error(`Status execution failed: ${message}`);
|
|
19
|
-
}
|
|
1
|
+
import { statusSpec } from "kibi-cli/operations";
|
|
2
|
+
import { createDiscoveryContext } from "./discovery-adapter.js";
|
|
3
|
+
export async function handleKbStatus(prolog, args) {
|
|
4
|
+
// implements REQ-kibi-operation-interface-parity
|
|
5
|
+
return statusSpec.execute(args, createDiscoveryContext(prolog));
|
|
20
6
|
}
|