kibi-mcp 0.1.6 → 0.2.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/server.js CHANGED
@@ -15,6 +15,7 @@
15
15
  You should have received a copy of the GNU Affero General Public License
16
16
  along with this program. If not, see <https://www.gnu.org/licenses/>.
17
17
  */
18
+ import fs from "node:fs";
18
19
  import { createRequire } from "node:module";
19
20
  /*
20
21
  How to apply this header to source files (examples)
@@ -47,22 +48,14 @@ import process from "node:process";
47
48
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
48
49
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
49
50
  import { PrologProcess } from "kibi-cli/prolog";
51
+ import { copyCleanSnapshot, getBranchDiagnostic, isValidBranchName, resolveActiveBranch, } from "kibi-cli/public/branch-resolver";
50
52
  import { z } from "zod";
51
53
  import { loadDefaultEnvFile } from "./env.js";
52
54
  import { attachMcpcat } from "./mcpcat.js";
53
55
  import { TOOLS } from "./tools-config.js";
54
- import { handleKbBranchEnsure, handleKbBranchGc, } from "./tools/branch.js";
55
56
  import { handleKbCheck } from "./tools/check.js";
56
- import { handleKbContext } from "./tools/context.js";
57
- import { handleKbCoverageReport, } from "./tools/coverage-report.js";
58
57
  import { handleKbDelete } from "./tools/delete.js";
59
- import { handleKbDerive } from "./tools/derive.js";
60
- import { handleKbImpact } from "./tools/impact.js";
61
- import { handleKbListEntityTypes, handleKbListRelationshipTypes, } from "./tools/list-types.js";
62
- import { handleKbQueryRelationships, } from "./tools/query-relationships.js";
63
58
  import { handleKbQuery } from "./tools/query.js";
64
- import { handleSuggestSharedFacts, } from "./tools/suggest-shared-facts.js";
65
- import { handleKbSymbolsRefresh, } from "./tools/symbols.js";
66
59
  import { handleKbUpsert } from "./tools/upsert.js";
67
60
  import { resolveKbPath, resolveWorkspaceRoot } from "./workspace.js";
68
61
  function renderToolsDoc() {
@@ -93,9 +86,9 @@ const PROMPTS = [
93
86
  "",
94
87
  "- Encode requirements as linked facts: `req --constrains--> fact` plus `req --requires_property--> fact`.",
95
88
  "- Reuse canonical fact IDs across requirements; shared constrained facts make contradictions detectable.",
96
- "- Use read tools first (`kb_query`, `kb_query_relationships`, `kbcontext`) to establish context.",
97
- "- Use mutation tools (`kb_upsert`, `kb_delete`, branch tools) only after you can justify the change.",
98
- "- Use inference tools (`kb_derive`, `kb_impact`, `kb_coverage_report`) for deterministic analysis.",
89
+ "- Use `kb_query` first to confirm current state before any mutation.",
90
+ "- Use `kb_upsert` and `kb_delete` only for intentional, traceable KB changes.",
91
+ "- Run `kb_check` after meaningful mutations to catch integrity issues early.",
99
92
  "- Prefer explicit IDs and enum values to avoid invalid parameters.",
100
93
  "- Assume every write can affect downstream traceability queries.",
101
94
  ].join("\n"),
@@ -108,15 +101,13 @@ const PROMPTS = [
108
101
  "",
109
102
  "Follow this sequence for reliable operation:",
110
103
  "",
111
- "1. **Discover**: Call `kb_list_entity_types`/`kb_list_relationship_types` if you are unsure about allowed values.",
112
- "2. **Inspect**: Call `kb_query` or `kbcontext` to confirm current state before any mutation.",
113
- "3. **Model requirements as facts**: For new/updated reqs, create/reuse fact entities first, then express req semantics with `constrains` + `requires_property`.",
114
- "4. **Validate intent**: If creating links, call `kb_query` for both endpoint IDs first.",
115
- "5. **Mutate**: Call `kb_upsert` for create/update, or `kb_delete` for explicit removals.",
116
- "6. **Verify integrity**: Call `kb_check` after mutations.",
117
- "7. **Assess impact**: Call `kb_impact`, `kb_derive`, or `kb_coverage_report` as needed.",
104
+ "1. **Inspect**: Call `kb_query` to confirm current state before any mutation.",
105
+ "2. **Model requirements as facts**: For new/updated reqs, create/reuse fact entities first, then express req semantics with `constrains` + `requires_property`.",
106
+ "3. **Validate intent**: If creating links, call `kb_query` for both endpoint IDs first.",
107
+ "4. **Mutate**: Call `kb_upsert` for create/update, or `kb_delete` for explicit removals.",
108
+ "5. **Verify integrity**: Call `kb_check` after mutations.",
118
109
  "",
119
- "If a tool returns empty results, do not assume failure. Re-check filters (type, id, tags, sourceFile, or relationship type).",
110
+ "If a tool returns empty results, do not assume failure. Re-check filters (type, id, tags, sourceFile, limit, or offset).",
120
111
  ].join("\n"),
121
112
  },
122
113
  {
@@ -129,10 +120,8 @@ const PROMPTS = [
129
120
  "",
130
121
  "- `kb_upsert` validates entity and relationship payloads against JSON Schema.",
131
122
  "- `kb_delete` blocks deletion when dependents still reference the entity.",
132
- "- `kb_branch_gc` may permanently remove stale branch KB directories when `dry_run` is `false`.",
133
123
  "- Relationship and rule names are strict enums; unknown values fail validation.",
134
- "- Branch names are sanitized; path traversal patterns are rejected.",
135
- "- `kb_symbols_refresh` can rewrite the symbols manifest unless `dryRun` is enabled.",
124
+ "- Branch KB setup is automatic at server startup; lifecycle maintenance stays outside the public MCP tool surface.",
136
125
  ].join("\n"),
137
126
  },
138
127
  ];
@@ -144,9 +133,8 @@ function registerDocResources() {
144
133
  "",
145
134
  "Scope:",
146
135
  "- Entity CRUD-like operations for KB records",
147
- "- Relationship inspection",
148
- "- Validation and branch KB maintenance",
149
- "- Deterministic inference for traceability and impact analysis",
136
+ "- Validation of KB integrity after changes",
137
+ "- Automatic branch-local attachment for the active workspace",
150
138
  "",
151
139
  "Use this server when you need branch-local, machine-readable project memory.",
152
140
  ].join("\n");
@@ -157,7 +145,7 @@ function registerDocResources() {
157
145
  "",
158
146
  "- `-32602 INVALID_PARAMS`: Tool arguments are missing/invalid. Recover by checking enum values and required fields.",
159
147
  "- `-32601 METHOD_NOT_FOUND`: Unknown MCP method. Recover by using supported methods (`tools/*`, `prompts/*`, `resources/*`).",
160
- "- `-32000 PROLOG_QUERY_FAILED`: Prolog query failed. Recover by validating IDs, rule names, and relationship types.",
148
+ "- `-32000 PROLOG_QUERY_FAILED`: Prolog query failed. Recover by validating IDs, rule names, and branch KB availability.",
161
149
  "- `VALIDATION_ERROR` message: `kb_upsert` payload failed schema checks. Recover by fixing required fields and enum values.",
162
150
  "- Delete blocked by dependents: `kb_delete` detected incoming references. Recover by removing/rewiring relationships first.",
163
151
  "- Empty results: filters may be too strict. Recover by loosening type/id/tags/source filters and retrying.",
@@ -171,20 +159,10 @@ function registerDocResources() {
171
159
  "3. Reuse the same constrained fact ID across related requirements; vary property facts only when semantics differ",
172
160
  '4. `kb_check` with `{ "rules": ["required-fields","no-dangling-refs"] }`',
173
161
  "",
174
- "## Discover requirement coverage gaps",
175
- '1. `kb_query` with `{ "type": "req", "limit": 20 }`',
176
- '2. `kb_coverage_report` with `{ "type": "req" }`',
177
- '3. `kb_derive` with `{ "rule": "coverage_gap" }`',
178
- "",
179
162
  "## Add a requirement and link it to a test",
180
163
  "1. `kb_query` for existing IDs to avoid collisions",
181
164
  "2. `kb_upsert` with entity payload and `relationships` containing `verified_by`",
182
165
  '3. `kb_check` with `{ "rules": ["required-fields","no-dangling-refs"] }`',
183
- "",
184
- "## Safe cleanup of stale branch KBs",
185
- '1. `kb_branch_gc` with `{ "dry_run": true }`',
186
- "2. Review `structuredContent.stale`",
187
- '3. `kb_branch_gc` with `{ "dry_run": false }` only when deletion is intended',
188
166
  ].join("\n");
189
167
  return [
190
168
  {
@@ -265,6 +243,22 @@ let activeBranchName = "develop";
265
243
  let isShuttingDown = false;
266
244
  let shutdownTimeout = null;
267
245
  const inFlightRequests = new Map();
246
+ function ensureBranchKbExists(workspaceRoot, branch) {
247
+ if (!isValidBranchName(branch)) {
248
+ throw new Error(`Invalid branch name: ${branch}`);
249
+ }
250
+ const branchPath = resolveKbPath(workspaceRoot, branch);
251
+ if (fs.existsSync(branchPath)) {
252
+ return;
253
+ }
254
+ const templateBranch = ["develop", "main"].find((candidate) => candidate !== branch &&
255
+ fs.existsSync(resolveKbPath(workspaceRoot, candidate)));
256
+ if (!templateBranch) {
257
+ throw new Error(`No template branch KB found for '${branch}'. Expected '.kb/branches/develop' or '.kb/branches/main'.`);
258
+ }
259
+ // Use clean snapshot copy that excludes volatile artifacts
260
+ copyCleanSnapshot(resolveKbPath(workspaceRoot, templateBranch), branchPath);
261
+ }
268
262
  function debugLog(...args) {
269
263
  if (process.env.KIBI_MCP_DEBUG) {
270
264
  console.error(...args);
@@ -316,9 +310,55 @@ async function initiateGracefulShutdown(exitCode = 0) {
316
310
  process.exit(exitCode);
317
311
  }
318
312
  async function ensureProlog() {
313
+ const workspaceRoot = resolveWorkspaceRoot();
314
+ // Determine target branch: respect KIBI_BRANCH override or resolve from git
315
+ const envBranch = process.env.KIBI_BRANCH?.trim();
316
+ let targetBranch;
317
+ if (envBranch) {
318
+ // KIBI_BRANCH override is set - use it without re-resolving from git
319
+ if (!isValidBranchName(envBranch)) {
320
+ throw new Error(`Invalid branch name from KIBI_BRANCH: '${envBranch}'`);
321
+ }
322
+ targetBranch = envBranch;
323
+ }
324
+ else {
325
+ // No override - resolve active branch from git (may change between requests)
326
+ const branchResult = resolveActiveBranch(workspaceRoot);
327
+ if ("error" in branchResult) {
328
+ const diagnostic = getBranchDiagnostic(undefined, branchResult.error);
329
+ console.error(`[KIBI-MCP] ${diagnostic}`);
330
+ throw new Error(`Failed to resolve active branch: ${branchResult.error}`);
331
+ }
332
+ targetBranch = branchResult.branch;
333
+ }
334
+ // Check if we need to switch branches
319
335
  if (isInitialized && prologProcess?.isRunning()) {
336
+ if (targetBranch === activeBranchName) {
337
+ // Still on the same branch - return existing connection
338
+ return prologProcess;
339
+ }
340
+ // Branch changed - need to detach and re-attach
341
+ debugLog(`[KIBI-MCP] Branch changed: ${activeBranchName} -> ${targetBranch}`);
342
+ // Detach from old KB
343
+ const detachResult = await prologProcess.query("kb_detach");
344
+ if (!detachResult.success) {
345
+ debugLog(`[KIBI-MCP] Warning: failed to detach from old KB: ${detachResult.error || "Unknown error"}`);
346
+ // Continue anyway - we'll try to attach to the new KB
347
+ }
348
+ // Ensure new branch KB exists
349
+ ensureBranchKbExists(workspaceRoot, targetBranch);
350
+ const newKbPath = resolveKbPath(workspaceRoot, targetBranch);
351
+ // Attach to new branch KB
352
+ const attachResult = await prologProcess.query(`kb_attach('${newKbPath}')`);
353
+ if (!attachResult.success) {
354
+ throw new Error(`Failed to attach to new branch KB: ${attachResult.error || "Unknown error"}`);
355
+ }
356
+ activeBranchName = targetBranch;
357
+ debugLog(`[KIBI-MCP] Re-attached to branch: ${targetBranch}`);
358
+ debugLog(`[KIBI-MCP] KB path: ${newKbPath}`);
320
359
  return prologProcess;
321
360
  }
361
+ // First initialization
322
362
  debugLog("[KIBI-MCP] Initializing Prolog process...");
323
363
  prologProcess = new PrologProcess({ timeout: 120000 });
324
364
  await prologProcess.start();
@@ -355,33 +395,12 @@ async function ensureProlog() {
355
395
  debugLog("[KIBI-MCP] Failed to create require() for debug lookup:", err.message);
356
396
  }
357
397
  }
358
- const workspaceRoot = resolveWorkspaceRoot();
359
- let branch = process.env.KIBI_BRANCH || "develop";
360
- let gitBranch;
361
- if (!process.env.KIBI_BRANCH) {
362
- try {
363
- const { execSync } = await import("node:child_process");
364
- const detected = execSync("git branch --show-current", {
365
- cwd: workspaceRoot,
366
- encoding: "utf8",
367
- timeout: 3000,
368
- }).trim();
369
- if (detected) {
370
- gitBranch = detected === "master" ? "develop" : detected;
371
- branch = gitBranch;
372
- }
373
- }
374
- catch {
375
- // fall back to develop
376
- }
377
- }
378
398
  debugLog("[KIBI-MCP] Branch selection:");
379
399
  debugLog(`[KIBI-MCP] KIBI_BRANCH env: ${process.env.KIBI_BRANCH || "not set"}`);
380
- debugLog(`[KIBI-MCP] Git branch: ${gitBranch || "n/a"}`);
381
- debugLog(`[KIBI-MCP] Attached to: ${branch}`);
382
- debugLog("[KIBI-MCP] To change branch: set KIBI_BRANCH=<branch> and restart");
383
- activeBranchName = branch;
384
- const kbPath = resolveKbPath(workspaceRoot, branch);
400
+ debugLog(`[KIBI-MCP] Resolved branch: ${targetBranch}`);
401
+ activeBranchName = targetBranch;
402
+ ensureBranchKbExists(workspaceRoot, targetBranch);
403
+ const kbPath = resolveKbPath(workspaceRoot, targetBranch);
385
404
  const attachResult = await prologProcess.query(`kb_attach('${kbPath}')`);
386
405
  if (!attachResult.success) {
387
406
  throw new Error(`Failed to attach KB: ${attachResult.error || "Unknown error"}`);
@@ -537,7 +556,7 @@ function addTool(server, name, description, inputSchema, handler) {
537
556
  }
538
557
  export async function startServer() {
539
558
  loadDefaultEnvFile();
540
- const server = new McpServer({ name: "kibi-mcp", version: "0.1.0" });
559
+ const server = new McpServer({ name: "kibi-mcp", version: "0.2.0" });
541
560
  attachMcpcat(server);
542
561
  for (const prompt of PROMPTS) {
543
562
  server.prompt(prompt.name, prompt.description, async () => ({
@@ -582,49 +601,6 @@ export async function startServer() {
582
601
  const prolog = await ensureProlog();
583
602
  return handleKbCheck(prolog, args);
584
603
  });
585
- addTool(server, "kb_branch_ensure", toolDef("kb_branch_ensure").description, toolDef("kb_branch_ensure").inputSchema, async (args) => {
586
- const prolog = await ensureProlog();
587
- return handleKbBranchEnsure(prolog, args);
588
- });
589
- addTool(server, "kb_branch_gc", toolDef("kb_branch_gc").description, toolDef("kb_branch_gc").inputSchema, async (args) => {
590
- const prolog = await ensureProlog();
591
- return handleKbBranchGc(prolog, args);
592
- });
593
- addTool(server, "kb_query_relationships", toolDef("kb_query_relationships").description, toolDef("kb_query_relationships").inputSchema, async (args) => {
594
- const prolog = await ensureProlog();
595
- return handleKbQueryRelationships(prolog, args);
596
- });
597
- addTool(server, "kb_derive", toolDef("kb_derive").description, toolDef("kb_derive").inputSchema, async (args) => {
598
- const prolog = await ensureProlog();
599
- return handleKbDerive(prolog, args);
600
- });
601
- addTool(server, "kb_impact", toolDef("kb_impact").description, toolDef("kb_impact").inputSchema, async (args) => {
602
- const prolog = await ensureProlog();
603
- return handleKbImpact(prolog, args);
604
- });
605
- addTool(server, "kb_coverage_report", toolDef("kb_coverage_report").description, toolDef("kb_coverage_report").inputSchema, async (args) => {
606
- const prolog = await ensureProlog();
607
- return handleKbCoverageReport(prolog, args);
608
- });
609
- addTool(server, "kb_symbols_refresh", toolDef("kb_symbols_refresh").description, toolDef("kb_symbols_refresh").inputSchema, async (args) => handleKbSymbolsRefresh(args));
610
- addTool(server, "kb_list_entity_types", toolDef("kb_list_entity_types").description, toolDef("kb_list_entity_types").inputSchema, handleKbListEntityTypes);
611
- addTool(server, "kb_list_relationship_types", toolDef("kb_list_relationship_types").description, toolDef("kb_list_relationship_types").inputSchema, handleKbListRelationshipTypes);
612
- addTool(server, "kbcontext", toolDef("kbcontext").description, toolDef("kbcontext").inputSchema, async (args) => {
613
- const prolog = await ensureProlog();
614
- return handleKbContext(prolog, args, activeBranchName);
615
- });
616
- addTool(server, "get_help", toolDef("get_help").description, toolDef("get_help").inputSchema, async (args) => {
617
- const topic = typeof args?.topic === "string" ? args.topic : undefined;
618
- const text = getHelpText(topic);
619
- return {
620
- content: [{ type: "text", text }],
621
- structuredContent: { topic: topic ?? "overview" },
622
- };
623
- });
624
- addTool(server, "analyze_shared_facts", toolDef("analyze_shared_facts").description, toolDef("analyze_shared_facts").inputSchema, async (args) => {
625
- const prolog = await ensureProlog();
626
- return handleSuggestSharedFacts(prolog, args);
627
- });
628
604
  const transport = new StdioServerTransport();
629
605
  transport.onerror = (error) => {
630
606
  // Stdio transport surfaces JSON parse / schema validation failures via onerror.
@@ -44,6 +44,15 @@
44
44
  */
45
45
  import * as path from "node:path";
46
46
  import { parsePairList } from "./prolog-list.js";
47
+ function formatDiagnosticsForMcp(diagnostics) {
48
+ return diagnostics.map((d) => ({
49
+ category: d.category,
50
+ severity: d.severity,
51
+ message: d.message,
52
+ file: d.file,
53
+ suggestion: d.suggestion,
54
+ }));
55
+ }
47
56
  /**
48
57
  * Handle kb_check tool calls - run validation rules on the KB
49
58
  * Reuses validation logic from CLI check command
@@ -77,7 +86,13 @@ export async function handleKbCheck(prolog, args) {
77
86
  if (rulesToRun.includes("symbol-coverage")) {
78
87
  violations.push(...(await checkSymbolCoverage(prolog)));
79
88
  }
80
- // Return MCP structured response
89
+ const diagnostics = violations.map((v) => ({
90
+ category: "SYNC_ERROR",
91
+ severity: "error",
92
+ message: v.description,
93
+ file: v.source,
94
+ suggestion: v.suggestion,
95
+ }));
81
96
  const summary = violations.length === 0
82
97
  ? "No violations found"
83
98
  : `${violations.length} violations found`;
@@ -91,6 +106,7 @@ export async function handleKbCheck(prolog, args) {
91
106
  structuredContent: {
92
107
  violations,
93
108
  count: violations.length,
109
+ diagnostics: formatDiagnosticsForMcp(diagnostics),
94
110
  },
95
111
  };
96
112
  }
@@ -15,18 +15,8 @@
15
15
  You should have received a copy of the GNU Affero General Public License
16
16
  along with this program. If not, see <https://www.gnu.org/licenses/>.
17
17
  */
18
- export async function handleKbContext(prolog, args, activeBranch) {
19
- const { sourceFile, branch } = args;
20
- if (branch && activeBranch && branch !== activeBranch) {
21
- return {
22
- content: [
23
- {
24
- type: "text",
25
- text: `Error: branch parameter is not supported server-side; set KIBI_BRANCH at startup or restart server on the desired branch. (Requested: ${branch}, Active: ${activeBranch})`,
26
- },
27
- ],
28
- };
29
- }
18
+ export async function handleKbContext(prolog, args) {
19
+ const { sourceFile } = args;
30
20
  try {
31
21
  const safeSource = sourceFile.replace(/'/g, "\\'");
32
22
  const entityGoal = `findall([Id,Type,Props], (kb_entities_by_source('${safeSource}', SourceIds), member(Id, SourceIds), kb_entity(Id, Type, Props)), Results)`;
@@ -234,215 +234,19 @@ export const TOOLS = [
234
234
  properties: {
235
235
  rules: {
236
236
  type: "array",
237
- items: { type: "string" },
237
+ items: {
238
+ type: "string",
239
+ enum: [
240
+ "must-priority-coverage",
241
+ "no-dangling-refs",
242
+ "no-cycles",
243
+ "required-fields",
244
+ "symbol-coverage",
245
+ ],
246
+ },
238
247
  description: "Optional rule subset. Allowed: must-priority-coverage, no-dangling-refs, no-cycles, required-fields, symbol-coverage. If omitted, server runs all.",
239
248
  },
240
249
  },
241
250
  },
242
251
  },
243
- {
244
- name: "kb_branch_ensure",
245
- description: "Ensure a branch KB exists, creating it from develop when missing. Use when targeting non-develop branches. Do not use to switch git branches. Side effects: creates .kb/branches/<branch>.",
246
- inputSchema: {
247
- type: "object",
248
- required: ["branch"],
249
- properties: {
250
- branch: {
251
- type: "string",
252
- description: "Required git branch name. Example: 'feature/auth-hardening'. Path traversal patterns are rejected.",
253
- },
254
- },
255
- },
256
- },
257
- {
258
- name: "kb_branch_gc",
259
- description: "Find or delete stale branch KB directories not present in git. Use for repository hygiene. Do not use if you need historical branch KBs. Side effects: can delete branch KB folders when dry_run is false.",
260
- inputSchema: {
261
- type: "object",
262
- properties: {
263
- dry_run: {
264
- type: "boolean",
265
- default: true,
266
- description: "Optional safety flag. true = report only; false = delete stale branch KBs. Default: true.",
267
- },
268
- },
269
- },
270
- },
271
- {
272
- name: "kb_query_relationships",
273
- description: "Read relationship edges with optional from/to/type filters. Use for traceability traversal. Do not use to create links. No mutation side effects.",
274
- inputSchema: {
275
- type: "object",
276
- properties: {
277
- from: {
278
- type: "string",
279
- description: "Optional source entity ID filter. Example: 'REQ-001'.",
280
- },
281
- to: {
282
- type: "string",
283
- description: "Optional target entity ID filter. Example: 'TEST-010'.",
284
- },
285
- type: {
286
- type: "string",
287
- enum: [
288
- "depends_on",
289
- "specified_by",
290
- "verified_by",
291
- "validates",
292
- "implements",
293
- "covered_by",
294
- "constrained_by",
295
- "constrains",
296
- "requires_property",
297
- "guards",
298
- "publishes",
299
- "consumes",
300
- "supersedes",
301
- "relates_to",
302
- ],
303
- description: "Optional relationship type filter. Allowed enum values only. Example: 'implements'.",
304
- },
305
- },
306
- },
307
- },
308
- {
309
- name: "kb_derive",
310
- description: "Run deterministic inference predicates and return rows. Use for impact, coverage, and consistency analysis. Do not use for entity CRUD. No mutation side effects.",
311
- inputSchema: {
312
- type: "object",
313
- required: ["rule"],
314
- properties: {
315
- rule: {
316
- type: "string",
317
- enum: [
318
- "transitively_implements",
319
- "transitively_depends",
320
- "impacted_by_change",
321
- "affected_symbols",
322
- "coverage_gap",
323
- "untested_symbols",
324
- "stale",
325
- "orphaned",
326
- "conflicting",
327
- "deprecated_still_used",
328
- "current_adr",
329
- "adr_chain",
330
- "superseded_by",
331
- "domain_contradictions",
332
- ],
333
- description: "Required inference rule name. Allowed values are the enum options. Example: 'coverage_gap'.",
334
- },
335
- params: {
336
- type: "object",
337
- description: "Optional rule-specific parameters. Example: { changed: 'REQ-001' } for impacted_by_change.",
338
- },
339
- },
340
- },
341
- },
342
- {
343
- name: "kb_impact",
344
- description: "Return entities impacted by a changed entity ID. Use for quick change blast radius checks. Do not use for general querying. No mutation side effects.",
345
- inputSchema: {
346
- type: "object",
347
- required: ["entity"],
348
- properties: {
349
- entity: {
350
- type: "string",
351
- description: "Required changed entity ID. Example: 'REQ-001'.",
352
- },
353
- },
354
- },
355
- },
356
- {
357
- name: "kb_coverage_report",
358
- description: "Compute aggregate traceability coverage for requirements and/or symbols. Use for health snapshots. Do not use for raw entity dumps. No mutation side effects.",
359
- inputSchema: {
360
- type: "object",
361
- properties: {
362
- type: {
363
- type: "string",
364
- enum: ["req", "symbol"],
365
- description: "Optional focus scope: 'req' or 'symbol'. Omit to include both.",
366
- },
367
- },
368
- },
369
- },
370
- {
371
- name: "kb_symbols_refresh",
372
- description: "Refresh generated symbol coordinates in the symbols manifest. Use after refactors that move symbols. Do not use for semantic edits. Side effects: may rewrite symbols.yaml unless dryRun is true.",
373
- inputSchema: {
374
- type: "object",
375
- properties: {
376
- dryRun: {
377
- type: "boolean",
378
- default: false,
379
- description: "Optional preview mode. true = report only, false = apply file updates. Default: false.",
380
- },
381
- },
382
- },
383
- },
384
- {
385
- name: "kb_list_entity_types",
386
- description: "List supported entity type names. Use when building valid tool arguments. Do not use for entity data retrieval. No mutation side effects.",
387
- inputSchema: { type: "object", properties: {} },
388
- },
389
- {
390
- name: "kb_list_relationship_types",
391
- description: "List supported relationship type names. Use before asserting or filtering relationships. Do not use for graph traversal. No mutation side effects.",
392
- inputSchema: { type: "object", properties: {} },
393
- },
394
- {
395
- name: "kbcontext",
396
- description: "Return KB entities linked to a source file plus first-hop relationships. Use for file-centric traceability. Do not use for cross-repo search. No mutation side effects.",
397
- inputSchema: {
398
- type: "object",
399
- required: ["sourceFile"],
400
- properties: {
401
- sourceFile: {
402
- type: "string",
403
- description: "Required source path substring. Example: 'src/auth/login.ts'.",
404
- },
405
- branch: {
406
- type: "string",
407
- description: "Optional branch hint for clients. Must match the server's active branch or will return an error.",
408
- },
409
- },
410
- },
411
- },
412
- {
413
- name: "get_help",
414
- description: "Returns documentation for this MCP server. Call this first if you are unsure how to proceed or which tool to use. Available topics: overview, tools, workflow, constraints, examples, errors.",
415
- inputSchema: {
416
- type: "object",
417
- properties: {
418
- topic: {
419
- type: "string",
420
- enum: [
421
- "overview",
422
- "tools",
423
- "workflow",
424
- "constraints",
425
- "examples",
426
- "errors",
427
- "branching",
428
- ],
429
- description: "Optional documentation section. Omit to return overview. Example: 'workflow'.",
430
- },
431
- },
432
- },
433
- },
434
- {
435
- name: "analyze_shared_facts",
436
- description: "Analyze requirements and suggest shared domain facts for extraction. LLMs call this to identify missed semantic opportunities before upserting. Lightweight heuristic: finds overlapping capitalized terms and repeated phrases across requirements.",
437
- inputSchema: {
438
- type: "object",
439
- properties: {
440
- min_frequency: {
441
- type: "number",
442
- default: 2,
443
- description: "Minimum frequency threshold for shared concepts. Default: 2. Example: 3 to only show concepts mentioned in 3+ requirements.",
444
- },
445
- },
446
- },
447
- },
448
252
  ];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kibi-mcp",
3
- "version": "0.1.6",
3
+ "version": "0.2.0",
4
4
  "dependencies": {
5
5
  "@modelcontextprotocol/sdk": "^1.26.0",
6
6
  "ajv": "^8.18.0",
@@ -9,7 +9,7 @@
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.1.7",
12
+ "kibi-cli": "^0.2.0",
13
13
  "kibi-core": "^0.1.6",
14
14
  "mcpcat": "^0.1.12",
15
15
  "ts-morph": "^23.0.0",