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.
Files changed (43) hide show
  1. package/bin/kibi-mcp +1 -1
  2. package/dist/diagnostics-helpers.js +22 -0
  3. package/dist/diagnostics.js +113 -4
  4. package/dist/runtime/mcp-runtime.js +43 -0
  5. package/dist/server/docs.js +11 -10
  6. package/dist/server/json-schema-to-zod.js +73 -2
  7. package/dist/server/session.js +33 -15
  8. package/dist/server/tool-registration.js +35 -59
  9. package/dist/server/tools-runtime.js +52 -2
  10. package/dist/server/tools.js +19 -5
  11. package/dist/server/transport.js +9 -5
  12. package/dist/tools/autopilot-generate.js +37 -646
  13. package/dist/tools/autopilot-test-compat.js +88 -0
  14. package/dist/tools/autopilot-test-parsers.js +120 -0
  15. package/dist/tools/check-config.js +67 -0
  16. package/dist/tools/check-format.js +92 -0
  17. package/dist/tools/check-impact.js +45 -0
  18. package/dist/tools/check-prolog.js +51 -0
  19. package/dist/tools/check.js +13 -190
  20. package/dist/tools/coverage.js +11 -25
  21. package/dist/tools/delete.js +5 -112
  22. package/dist/tools/discovery-adapter.js +23 -0
  23. package/dist/tools/entity-query.js +1 -111
  24. package/dist/tools/find-gaps.js +11 -26
  25. package/dist/tools/graph.js +11 -24
  26. package/dist/tools/model-requirement.js +8 -347
  27. package/dist/tools/mutation-context.js +28 -0
  28. package/dist/tools/query-plan-safety.js +58 -0
  29. package/dist/tools/query.js +5 -50
  30. package/dist/tools/relationship-validation.js +11 -0
  31. package/dist/tools/search.js +4 -37
  32. package/dist/tools/semantic-advisor.js +2 -40
  33. package/dist/tools/skills.js +25 -47
  34. package/dist/tools/sparql.js +12 -93
  35. package/dist/tools/status.js +5 -19
  36. package/dist/tools/suggest-predicates.js +11 -2448
  37. package/dist/tools/upsert.js +21 -794
  38. package/dist/tools/validate-upsert.js +16 -40
  39. package/dist/tools-config.js +75 -764
  40. package/package.json +4 -3
  41. package/dist/semantic-advisor/analyze-prose.js +0 -1367
  42. package/dist/semantic-advisor/prose-coverage-evaluator.js +0 -66
  43. /package/dist/{semantic-advisor/types.js → tools/check-types.js} +0 -0
@@ -1,16 +1,16 @@
1
- import { createHash } from "node:crypto";
2
- import { listBundledSkills, loadBundledSkill, readBundledSkillResource, } from "kibi-cli/skills";
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
- const skills = listBundledSkills();
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
- assertNonEmptyString(args.id, "id");
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`,
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,26 +30,24 @@ export async function handleKbSkillsLoad(args) {
50
30
  // implements REQ-001
51
31
  export async function handleKbSkillsRead(args) {
52
32
  try {
53
- assertNonEmptyString(args.id, "id");
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
- throw new Error(`Skills read failed: ${message}`);
37
+ throw new Error(`Skills read failed: ${message}${resourceListHint(args.id)}`);
69
38
  }
70
39
  }
71
- function assertNonEmptyString(value, field) {
72
- if (typeof value !== "string" || value.trim() === "") {
73
- throw new Error(`${field} must be a non-empty string`);
40
+ function resourceListHint(id) {
41
+ if (typeof id !== "string" || id.trim() === "") {
42
+ return "";
43
+ }
44
+ try {
45
+ const bundle = loadBundledSkill(id);
46
+ const resources = bundle.manifest.resources ?? [];
47
+ const resourceList = resources.length === 0 ? "none" : resources.join(", ");
48
+ return `. Declared resources: ${resourceList}`;
49
+ }
50
+ catch {
51
+ return "";
74
52
  }
75
53
  }
@@ -1,96 +1,15 @@
1
- import { runJsonModuleQuery, toPrologAtom } from "./core-module.js";
2
- // implements REQ-002, REQ-013
3
- export async function handleSparql(prolog, args) {
4
- validateSparqlArgs(args);
5
- try {
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
- if (!args.query || args.query.trim().length === 0) {
28
- throw new Error("SPARQL query is required");
29
- }
30
- if (!isRemoteHttpEndpoint(args.endpoint)) {
31
- throw new Error("SPARQL endpoint must be an http:// or https:// URL");
32
- }
33
- if (!isSelectQuery(args.query)) {
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
  }
@@ -1,20 +1,6 @@
1
- import { runJsonModuleQuery } from "./core-module.js";
2
- // implements REQ-002, REQ-013
3
- export async function handleKbStatus(prolog, _args) {
4
- try {
5
- const payload = await runJsonModuleQuery(prolog, "status.pl", "status:kb_status_json(JsonString)", "Status execution");
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
  }