kibi-mcp 0.20.1 → 0.22.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.
@@ -7,6 +7,7 @@
7
7
  * the Free Software Foundation, either version 3 of the License, or
8
8
  * (at your option) any later version.
9
9
  */
10
+ import { createHash } from "node:crypto";
10
11
  import fs from "node:fs";
11
12
  import path from "node:path";
12
13
  import { resolveWorkspaceRoot } from "./workspace.js";
@@ -63,6 +64,14 @@ export const DIAGNOSTIC_TELEMETRY_SCHEMA = {
63
64
  type: "string",
64
65
  description: "If you had to split your task into multiple steps because this tool lacks a specific filtering or querying capability, describe what parameter is missing. Otherwise, leave empty.",
65
66
  },
67
+ session_id: {
68
+ type: "string",
69
+ description: "Optional opaque workflow-session identifier used to correlate advisor, preflight, mutation, coverage, and verification evidence. Do not put personal data in this field.",
70
+ },
71
+ actor_id: {
72
+ type: "string",
73
+ description: "Optional opaque actor identifier used to prevent evidence from a different actor being correlated with this call. Do not put personal data in this field.",
74
+ },
66
75
  },
67
76
  };
68
77
  function isRecord(value) {
@@ -103,6 +112,69 @@ function appendSemanticAdvisorFields(fields, receipt) {
103
112
  fields.semantic_suggestion_kinds = suggestionKinds;
104
113
  fields.semantic_suggestion_count = suggestionKinds.length;
105
114
  fields.semantic_next_tools = stringArray(receipt.suggested_next_tools);
115
+ const inventoryContract = receipt.inventory_contract;
116
+ if (isRecord(inventoryContract) &&
117
+ typeof inventoryContract.source_hash === "string") {
118
+ fields.semantic_source_hash = inventoryContract.source_hash;
119
+ }
120
+ }
121
+ function canonicalDiagnosticValue(value) {
122
+ if (Array.isArray(value))
123
+ return value.map(canonicalDiagnosticValue);
124
+ if (!isRecord(value))
125
+ return value;
126
+ return Object.fromEntries(Object.entries(value)
127
+ .filter(([key]) => key !== "_diagnostic_telemetry")
128
+ .sort(([left], [right]) => left.localeCompare(right))
129
+ .map(([key, child]) => [key, canonicalDiagnosticValue(child)]));
130
+ }
131
+ function mutationFingerprint(args) {
132
+ return createHash("sha256")
133
+ .update(JSON.stringify(canonicalDiagnosticValue(args)))
134
+ .digest("hex");
135
+ }
136
+ function appendMutationFields(fields, args) {
137
+ fields.mutation_fingerprint = mutationFingerprint(args);
138
+ const type = typeof args.type === "string" ? args.type : "unknown";
139
+ const id = typeof args.id === "string" ? args.id : "unknown";
140
+ fields.mutation_target = `${type}:${id}`;
141
+ }
142
+ const RECEIPT_GAP_CODES = new Set([
143
+ "missing_verification_receipt",
144
+ "stale_verification_receipt",
145
+ "failed_verification_receipt",
146
+ "invalid_verification_receipt",
147
+ "verification_snapshot_unavailable",
148
+ ]);
149
+ function appendCoverageFields(fields, args, structuredContent) {
150
+ const rows = Array.isArray(structuredContent.rows)
151
+ ? structuredContent.rows.filter(isRecord)
152
+ : [];
153
+ const summary = isRecord(structuredContent.summary)
154
+ ? structuredContent.summary
155
+ : {};
156
+ const gapCodes = rows.flatMap((row) => stringArray(row.proofGaps));
157
+ const uniqueGapCodes = [...new Set(gapCodes)].sort();
158
+ const repairPlan = isRecord(structuredContent.repairPlan)
159
+ ? structuredContent.repairPlan
160
+ : undefined;
161
+ const scope = isRecord(repairPlan?.scope) ? repairPlan.scope : undefined;
162
+ fields.coverage_by = typeof args.by === "string" ? args.by : "req";
163
+ fields.coverage_requirement_count = Number(summary.total ?? rows.length);
164
+ fields.coverage_proven_count = Number(summary.proofProven ?? 0);
165
+ fields.coverage_proof_missing_count = Number(summary.proofMissing ?? 0);
166
+ fields.coverage_proof_gap_count = gapCodes.length;
167
+ fields.coverage_gap_codes = uniqueGapCodes;
168
+ fields.coverage_receipt_gap_count = gapCodes.filter((gap) => RECEIPT_GAP_CODES.has(gap)).length;
169
+ if (typeof scope?.complete === "boolean") {
170
+ fields.coverage_scope_complete = scope.complete;
171
+ }
172
+ const metadata = isRecord(structuredContent.meta)
173
+ ? structuredContent.meta
174
+ : undefined;
175
+ if (typeof metadata?.verificationSnapshot === "string") {
176
+ fields.coverage_verification_snapshot = metadata.verificationSnapshot;
177
+ }
106
178
  }
107
179
  function appendPredicateSuggestionFields(fields, structuredContent) {
108
180
  const candidates = Array.isArray(structuredContent.candidates)
@@ -155,6 +227,12 @@ export function deriveDiagnosticFields(toolName, args, telemetry, result) {
155
227
  fields.telemetry_is_autonomous = telemetry.is_autonomous ?? null;
156
228
  fields.telemetry_confidence_score = telemetry.confidence_score ?? null;
157
229
  fields.telemetry_attempt_number = telemetry.attempt_number ?? null;
230
+ if (typeof telemetry.session_id === "string") {
231
+ fields.session_id = telemetry.session_id;
232
+ }
233
+ if (typeof telemetry.actor_id === "string") {
234
+ fields.actor_id = telemetry.actor_id;
235
+ }
158
236
  }
159
237
  const structuredContent = structuredContentFrom(result);
160
238
  if (toolName === "kb_query" || toolName === "kb_search") {
@@ -171,6 +249,10 @@ export function deriveDiagnosticFields(toolName, args, telemetry, result) {
171
249
  fields.result_summary =
172
250
  violationCount === 0 ? "0 violations" : `${violationCount} violations`;
173
251
  }
252
+ if (toolName === "kb_coverage" && structuredContent) {
253
+ appendCoverageFields(fields, args, structuredContent);
254
+ fields.result_summary = `${String(fields.coverage_proven_count)} proven; ${String(fields.coverage_proof_gap_count)} proof gaps`;
255
+ }
174
256
  if (toolName === "kb_semantic_advisor" && structuredContent) {
175
257
  appendSemanticAdvisorFields(fields, structuredContent.receipt);
176
258
  const readiness = fields.semantic_logic_readiness;
@@ -189,6 +271,7 @@ export function deriveDiagnosticFields(toolName, args, telemetry, result) {
189
271
  : `${count} predicate candidates`;
190
272
  }
191
273
  if (toolName === "kb_upsert" && structuredContent) {
274
+ appendMutationFields(fields, args);
192
275
  const created = Number(structuredContent.created ?? 0);
193
276
  const updated = Number(structuredContent.updated ?? 0);
194
277
  fields.upsert_created = created;
@@ -201,6 +284,15 @@ export function deriveDiagnosticFields(toolName, args, telemetry, result) {
201
284
  fields.result_summary = `upsert ${created > 0 ? "created" : "updated"}; semantic ${readiness}`;
202
285
  }
203
286
  }
287
+ if (toolName === "kb_validate_upsert" && structuredContent) {
288
+ appendMutationFields(fields, args);
289
+ fields.validation_valid = structuredContent.valid === true;
290
+ appendSemanticAdvisorFields(fields, structuredContent.semanticAdvisor);
291
+ fields.result_summary =
292
+ structuredContent.valid === true
293
+ ? "upsert payload valid"
294
+ : "upsert payload invalid";
295
+ }
204
296
  if (!fields.result_summary) {
205
297
  fields.result_summary = `${toolName} completed`;
206
298
  }
@@ -104,7 +104,7 @@ export const PROMPTS = [
104
104
  "- `kb_query`: Exact lookup of entities by type, ID, tags, or source file",
105
105
  "- `kb_status`: Branch, snapshot, and freshness inspection",
106
106
  "- `kb_find_gaps`: Bulk missing/present relationship analysis",
107
- "- `kb_coverage`: Curated coverage reporting",
107
+ "- `kb_coverage`: Curated proof reporting plus deterministic read-only repair batches for requirements",
108
108
  "- `kb_graph`: Bounded graph traversal from seed IDs",
109
109
  "- `kb_upsert`: Create or update entities and their relationships",
110
110
  "- `kb_delete`: Remove entities by ID (with dependency safety checks)",
@@ -138,9 +138,11 @@ export const PROMPTS = [
138
138
  "4. **Validate intent**: If creating links, call `kb_query` for both endpoint IDs first to ensure they exist.",
139
139
  "5. **Model requirements as facts**: For new/updated reqs, create/reuse fact entities first, then express req semantics with `constrains` + `requires_property` (automated via `kb_model_requirement`).",
140
140
  "6. **Suggest predicates before prose**: For ontology-lane requirements, spell out the prose claim and call `kb_suggest_predicates` before writing `fact_kind: observation`. Apply the selected `fact_kind: predicate` applyPlan, then attach the returned `relationshipPlan` as `requires_predicate` while preserving existing req metadata; use the returned `review:ontology-gap` observation when no predicate fits.",
141
- "7. **Mutate**: Call `kb_upsert` for create/update, or `kb_delete` for explicit removals.",
142
- "8. **Targeted checks**: Run `kb_check` after meaningful mutations; specify only the rules you need so scoped validation stays fast and skips the full-KB advisory scan.",
143
- "9. **Final check**: Run `kb_check` without `rules` before completion so hard `violations[]` and advisory full-KB `qualityDiagnostics[]` are both reviewed.",
141
+ "7. **Plan repairs**: Requirement `kb_coverage` returns `repairPlan`; require `repairPlan.scope.complete`, apply only a batch whose state is `ready`, and treat every batch as non-auto-applicable guidance.",
142
+ "8. **Mutate sequentially**: Query current endpoints, validate each payload, then call `kb_upsert` one at a time or `kb_delete` for explicit removals. Re-run `kb_coverage` after each batch rather than continuing from a stale plan.",
143
+ "9. **Targeted checks**: Run `kb_check` after meaningful mutations; specify only the rules you need so scoped validation stays fast and skips the full-KB advisory scan.",
144
+ "10. **Final check**: Run `kb_check` without `rules` before completion so hard `violations[]` and advisory full-KB `qualityDiagnostics[]`—including telemetry acceptance when usage evidence exists—are both reviewed.",
145
+ "11. **Telemetry gate**: When `.kb/usage.log` exists, run the CLI-only `kibi usage-metrics --format json --require-acceptance`; stale, partial, or insufficient `kibi.telemetry-acceptance.v1` evidence is not a pass.",
144
146
  "",
145
147
  "If a tool returns empty results, do not assume failure. Re-check filters (type, id, tags, sourceFile, limit, or offset).",
146
148
  ].join("\n"),
@@ -217,8 +219,10 @@ function registerDocResources() {
217
219
  "",
218
220
  "## Find missing coverage",
219
221
  '1. `kb_find_gaps` with `{ "type": "req", "missingRelationships": ["specified_by", "verified_by"] }` to find under-linked requirements',
220
- '2. `kb_coverage` with `{ "by": "req", "includePassing": false }` to review evaluated coverage rows',
221
- '3. `kb_graph` with `{ "seedIds": ["REQ-001"], "direction": "both", "depth": 2 }` to inspect neighboring entities',
222
+ '2. `kb_coverage` with `{ "by": "req", "includePassing": false }` to review proof rows and `repairPlan`; require `repairPlan.scope.complete` before treating it as a project-wide inventory',
223
+ "3. Apply only a `repairPlan` batch whose state is `ready`; batches are non-auto-applicable guidance, so query current endpoints, validate every write, and keep `kb_upsert` sequential",
224
+ "4. Re-run `kb_coverage` after each batch instead of continuing from a stale plan",
225
+ '5. `kb_graph` with `{ "seedIds": ["REQ-001"], "direction": "both", "depth": 2 }` to inspect neighboring entities',
222
226
  "",
223
227
  "## Add a requirement and link it to a test",
224
228
  '1. `kb_query` with `{ "type": "test" }` to check for existing test IDs',
@@ -41,6 +41,18 @@ export function jsonSchemaToZod(schema) {
41
41
  return z.any();
42
42
  }
43
43
  const obj = schema;
44
+ if (Object.hasOwn(obj, "const")) {
45
+ const description = typeof obj.description === "string" ? obj.description : undefined;
46
+ const value = obj.const;
47
+ if (typeof value === "string" ||
48
+ typeof value === "number" ||
49
+ typeof value === "boolean" ||
50
+ value === null) {
51
+ const literal = z.literal(value);
52
+ return description ? literal.describe(description) : literal;
53
+ }
54
+ return description ? z.any().describe(description) : z.any();
55
+ }
44
56
  if (Array.isArray(obj.enum) && obj.enum.length > 0) {
45
57
  const description = typeof obj.description === "string" ? obj.description : undefined;
46
58
  const literals = obj.enum.filter((value) => typeof value === "string" ||
@@ -1,4 +1,4 @@
1
- import { stat } from "node:fs/promises";
1
+ import { readFile, stat } from "node:fs/promises";
2
2
  import path from "node:path";
3
3
  export class KbRefreshError extends Error {
4
4
  constructor(message) {
@@ -21,7 +21,17 @@ export async function readBranchKbStamp(branchPath) {
21
21
  stamp.dirMissing = true;
22
22
  errors.push(formatStatError(branchPath, error));
23
23
  }
24
- const rdfPath = path.join(branchPath, "kb.rdf");
24
+ const markerPath = path.join(branchPath, "storage.json");
25
+ let journaled = false;
26
+ try {
27
+ journaled = (await readFile(markerPath, "utf8")).includes("kibi.rdf-journal.v1");
28
+ }
29
+ catch {
30
+ journaled = false;
31
+ }
32
+ // Journaled stores expose CURRENT as their cheap, atomic freshness marker;
33
+ // legacy stores retain kb.rdf for compatibility.
34
+ const rdfPath = path.join(branchPath, journaled ? "CURRENT" : "kb.rdf");
25
35
  try {
26
36
  const rdfStat = await stat(rdfPath);
27
37
  stamp.rdfDev = rdfStat.dev;
@@ -18,6 +18,7 @@
18
18
  import fs from "node:fs";
19
19
  import { createRequire } from "node:module";
20
20
  import process from "node:process";
21
+ import { EngineClient } from "kibi-cli/engine";
21
22
  import { PrologProcess } from "kibi-cli/prolog";
22
23
  import { copyCleanSnapshot, getBranchDiagnostic, isValidBranchName, resolveActiveBranch, } from "kibi-cli/public/branch-resolver";
23
24
  import { getBranchOverride, isMcpDebugEnabled } from "../env.js";
@@ -202,6 +203,7 @@ function usesBranchKbPath(kbPath) {
202
203
  async function ensurePrologUnsafe() {
203
204
  const generationAtStart = prologResetGeneration;
204
205
  const workspaceRoot = sessionDeps.resolveWorkspaceRoot();
206
+ const useEngine = sessionDeps.PrologProcess === defaultSessionDeps.PrologProcess;
205
207
  const assertGeneration = async () => {
206
208
  if (generationAtStart !== prologResetGeneration) {
207
209
  const current = prologProcess;
@@ -236,6 +238,19 @@ async function ensurePrologUnsafe() {
236
238
  targetBranch = branchResult.branch;
237
239
  }
238
240
  // Check if we need to switch branches
241
+ if (isInitialized && useEngine && prologProcess?.isRunning()) {
242
+ const kbPath = sessionDeps.resolveKbPath(workspaceRoot, targetBranch);
243
+ if (targetBranch === activeBranchName) {
244
+ attachedBranchKbPath = kbPath;
245
+ attachedBranchStamp = await readBranchKbStamp(kbPath);
246
+ return prologProcess;
247
+ }
248
+ await prologProcess.terminate();
249
+ prologProcess = null;
250
+ isInitialized = false;
251
+ attachedBranchKbPath = null;
252
+ attachedBranchStamp = null;
253
+ }
239
254
  if (isInitialized && prologProcess?.isRunning()) {
240
255
  const kbPath = sessionDeps.resolveKbPath(workspaceRoot, targetBranch);
241
256
  if (targetBranch === activeBranchName) {
@@ -298,7 +313,13 @@ async function ensurePrologUnsafe() {
298
313
  }
299
314
  // First initialization
300
315
  debugLog("[KIBI-MCP] Initializing Prolog process...");
301
- prologProcess = new sessionDeps.PrologProcess({ timeout: 120000 });
316
+ prologProcess = useEngine
317
+ ? new EngineClient({
318
+ workspaceRoot,
319
+ branch: targetBranch,
320
+ timeout: 120000,
321
+ })
322
+ : new sessionDeps.PrologProcess({ timeout: 120000 });
302
323
  await prologProcess.start();
303
324
  await assertGeneration();
304
325
  // Startup debug: resolve which kibi-cli is being used and its version (best-effort).
@@ -340,16 +361,18 @@ async function ensurePrologUnsafe() {
340
361
  activeBranchName = targetBranch;
341
362
  const createdEmptyBranch = ensureBranchKbExists(workspaceRoot, targetBranch);
342
363
  const kbPath = sessionDeps.resolveKbPath(workspaceRoot, targetBranch);
343
- const attachResult = await prologProcess.query(`kb_attach('${kbPath}')`);
344
- await assertGeneration();
345
- if (!attachResult.success) {
346
- throw new Error(`Failed to attach KB: ${attachResult.error || "Unknown error"}`);
347
- }
348
- if (createdEmptyBranch) {
349
- const initialSaveResult = await prologProcess.query("kb_save");
364
+ if (!useEngine) {
365
+ const attachResult = await prologProcess.query(`kb_attach('${kbPath}')`);
350
366
  await assertGeneration();
351
- if (!initialSaveResult.success) {
352
- throw new Error(`Failed to initialize empty branch KB: ${initialSaveResult.error || "Unknown error"}`);
367
+ if (!attachResult.success) {
368
+ throw new Error(`Failed to attach KB: ${attachResult.error || "Unknown error"}`);
369
+ }
370
+ if (createdEmptyBranch) {
371
+ const initialSaveResult = await prologProcess.query("kb_save");
372
+ await assertGeneration();
373
+ if (!initialSaveResult.success) {
374
+ throw new Error(`Failed to initialize empty branch KB: ${initialSaveResult.error || "Unknown error"}`);
375
+ }
353
376
  }
354
377
  }
355
378
  attachedBranchKbPath = kbPath;
@@ -39,7 +39,7 @@ export function registerConfiguredTools(server, runtime, registerTool) {
39
39
  });
40
40
  register({
41
41
  name: "kb_status",
42
- execute: async (context, args) => runtime.handleKbStatus(prologFor(context), args),
42
+ execute: async (context, args) => runtime.handleKbStatus(prologFor(context), args, context),
43
43
  });
44
44
  register({
45
45
  name: "kb_skills_list",
@@ -59,7 +59,7 @@ export function registerConfiguredTools(server, runtime, registerTool) {
59
59
  });
60
60
  register({
61
61
  name: "kb_coverage",
62
- execute: async (context, args) => runtime.handleKbCoverage(prologFor(context), args),
62
+ execute: async (context, args) => runtime.handleKbCoverage(prologFor(context), args, context),
63
63
  });
64
64
  register({
65
65
  name: "kb_graph",
@@ -1,4 +1,5 @@
1
1
  import { getSpec } from "kibi-cli/operations";
2
+ import { nodeGit } from "kibi-cli/operations/node-ports";
2
3
  import { DIAGNOSTIC_MODE_ENABLED, appendUsageLogLine, classifyDiagnosticError, deriveDiagnosticFields, extractToolCallPayload, } from "../diagnostics.js";
3
4
  import { isMcpDebugEnabled } from "../env.js";
4
5
  import { createMcpRuntime } from "../runtime/mcp-runtime.js";
@@ -61,6 +62,30 @@ function adaptProlog(prolog) {
61
62
  return result;
62
63
  },
63
64
  save: () => prolog.query("kb_save"),
65
+ ...(typeof prolog.queryEntities ===
66
+ "function"
67
+ ? {
68
+ queryEntities: (input) => prolog.queryEntities(input),
69
+ }
70
+ : {}),
71
+ ...(typeof prolog.searchEntities ===
72
+ "function"
73
+ ? {
74
+ searchEntities: (input) => prolog.searchEntities(input),
75
+ }
76
+ : {}),
77
+ ...(typeof prolog.storageStatus ===
78
+ "function"
79
+ ? {
80
+ storageStatus: () => prolog.storageStatus(),
81
+ }
82
+ : {}),
83
+ ...(typeof prolog.queryStatusJson ===
84
+ "function"
85
+ ? {
86
+ queryStatusJson: () => prolog.queryStatusJson(),
87
+ }
88
+ : {}),
64
89
  };
65
90
  prologPorts.set(prolog, port);
66
91
  return port;
@@ -71,6 +96,7 @@ const operationRuntime = createMcpRuntime({
71
96
  attachedBranchKbPath: async () => (await getSessionModule()).attachedBranchKbPath,
72
97
  ensureProlog: async () => (await getSessionModule()).ensureProlog(),
73
98
  adaptProlog,
99
+ git: nodeGit,
74
100
  net: { fetch: (input, init) => globalThis.fetch(input, init) },
75
101
  refreshAttachedBranchStamp: async () => {
76
102
  const session = await getSessionModule();
@@ -30,6 +30,7 @@ export async function runAggregatedChecks(prolog, rulesAllowlist, requireAdr) {
30
30
  description: v.description,
31
31
  ...(v.suggestion ? { suggestion: v.suggestion } : {}),
32
32
  ...(v.source ? { source: v.source } : {}),
33
+ ...(v.evidence ? { evidence: v.evidence } : {}),
33
34
  });
34
35
  }
35
36
  }
@@ -1,14 +1,6 @@
1
- import { executeCoverage } from "kibi-cli/operations";
1
+ import { executeCoverage, } from "kibi-cli/operations";
2
+ import { createDiscoveryContext } from "./discovery-adapter.js";
2
3
  // implements REQ-002, REQ-013
3
- export async function handleKbCoverage(prolog, args) {
4
- return executeCoverage({ ...args }, {
5
- workspaceRoot: process.cwd(),
6
- signal: new AbortController().signal,
7
- clock: () => new Date(),
8
- prolog: {
9
- query: (goal) => prolog.query(goal),
10
- nextSolution: async () => null,
11
- save: () => prolog.query("kb_save"),
12
- },
13
- });
4
+ export async function handleKbCoverage(prolog, args, context) {
5
+ return executeCoverage({ ...args }, createDiscoveryContext(prolog, context));
14
6
  }
@@ -1,5 +1,5 @@
1
1
  import { resolveWorkspaceRoot } from "../workspace.js";
2
- export function createDiscoveryContext(prolog) {
2
+ export function createDiscoveryContext(prolog, baseContext) {
3
3
  // implements REQ-kibi-operation-interface-parity
4
4
  let lastResult = null;
5
5
  const port = {
@@ -13,11 +13,18 @@ export function createDiscoveryContext(prolog) {
13
13
  return result;
14
14
  },
15
15
  save: () => prolog.query("kb_save"),
16
+ ...(typeof prolog.queryStatusJson ===
17
+ "function"
18
+ ? {
19
+ queryStatusJson: () => prolog.queryStatusJson(),
20
+ }
21
+ : {}),
16
22
  };
17
23
  return {
18
- workspaceRoot: resolveWorkspaceRoot(),
19
- signal: new AbortController().signal,
20
- clock: () => new Date(),
24
+ ...(baseContext ?? {}),
25
+ workspaceRoot: baseContext?.workspaceRoot ?? resolveWorkspaceRoot(),
26
+ signal: baseContext?.signal ?? new AbortController().signal,
27
+ clock: baseContext?.clock ?? (() => new Date()),
21
28
  prolog: port,
22
29
  };
23
30
  }
@@ -1,10 +1,10 @@
1
1
  import { statusSpec } from "kibi-cli/operations";
2
2
  import { createDiscoveryContext } from "./discovery-adapter.js";
3
- export async function handleKbStatus(prolog, args) {
3
+ export async function handleKbStatus(prolog, args, context) {
4
4
  // implements REQ-kibi-operation-interface-parity
5
5
  // Freshness is read-after-write sensitive: invalidate the PrologProcess query
6
6
  // cache so kb_status always reflects the current workspace state rather than
7
7
  // a stale earlier-in-session result.
8
8
  prolog.invalidateCache();
9
- return statusSpec.execute(args, createDiscoveryContext(prolog));
9
+ return statusSpec.execute(args, createDiscoveryContext(prolog, context));
10
10
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kibi-mcp",
3
- "version": "0.20.1",
3
+ "version": "0.22.0",
4
4
  "dependencies": {
5
5
  "@modelcontextprotocol/sdk": "^1.26.0",
6
6
  "ajv": "^8.18.0",
@@ -9,8 +9,8 @@
9
9
  "fast-glob": "^3.2.12",
10
10
  "gray-matter": "^4.0.3",
11
11
  "js-yaml": "^4.1.0",
12
- "kibi-cli": "^0.17.0",
13
- "kibi-core": "^0.8.0",
12
+ "kibi-cli": "^0.19.0",
13
+ "kibi-core": "^0.10.0",
14
14
  "mcpcat": "^0.1.12",
15
15
  "ts-morph": "^23.0.0",
16
16
  "zod": "^4.3.6"
@@ -30,8 +30,7 @@
30
30
  },
31
31
  "files": ["dist", "bin"],
32
32
  "engines": {
33
- "node": ">=18",
34
- "bun": ">=1.0"
33
+ "node": ">=18"
35
34
  },
36
35
  "exports": {
37
36
  ".": "./dist/server.js"