kiri-mcp-server 0.3.0 → 0.4.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/README.md CHANGED
@@ -111,15 +111,15 @@ KIRI provides 5 MCP tools for code exploration:
111
111
 
112
112
  | Tool | Description |
113
113
  | ------------------- | --------------------------------------------------------------------- |
114
- | **context.bundle** | Extract relevant code context based on task goals |
115
- | **semantic.rerank** | Re-rank candidates by semantic similarity |
116
- | **files.search** | Full-text search with multi-word queries (FTS/BM25 or ILIKE fallback) |
117
- | **snippets.get** | Retrieve code snippets with symbol boundaries |
118
- | **deps.closure** | Get dependency graph neighborhood (outbound/inbound) |
114
+ | **context_bundle** | Extract relevant code context based on task goals |
115
+ | **semantic_rerank** | Re-rank candidates by semantic similarity |
116
+ | **files_search** | Full-text search with multi-word queries (FTS/BM25 or ILIKE fallback) |
117
+ | **snippets_get** | Retrieve code snippets with symbol boundaries |
118
+ | **deps_closure** | Get dependency graph neighborhood (outbound/inbound) |
119
119
 
120
120
  ### Search Query Syntax
121
121
 
122
- **files.search** supports multi-word queries automatically:
122
+ **files_search** supports multi-word queries automatically:
123
123
 
124
124
  - `"tools call implementation"` → Finds files containing ANY of these words (OR logic)
125
125
  - `"MCP-server-handler"` → Splits on hyphens and searches for each part
@@ -2,8 +2,8 @@ mcp:
2
2
  port: 8765
3
3
  host: 127.0.0.1
4
4
  tools:
5
- - context.bundle
6
- - files.search
5
+ - context_bundle
6
+ - files_search
7
7
  indexer:
8
8
  repoRoot: "../../target-repo"
9
9
  database: "var/index.duckdb"
@@ -1,4 +1,4 @@
1
- # Scoring weight profiles for context.bundle
1
+ # Scoring weight profiles for context_bundle
2
2
  # Each profile defines weights for different ranking signals
3
3
 
4
4
  default:
@@ -2,8 +2,8 @@ mcp:
2
2
  port: 8765
3
3
  host: 127.0.0.1
4
4
  tools:
5
- - context.bundle
6
- - files.search
5
+ - context_bundle
6
+ - files_search
7
7
  indexer:
8
8
  repoRoot: "../../target-repo"
9
9
  database: "var/index.duckdb"
@@ -1,4 +1,4 @@
1
- # Scoring weight profiles for context.bundle
1
+ # Scoring weight profiles for context_bundle
2
2
  # Each profile defines weights for different ranking signals
3
3
 
4
4
  default:
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kiri-mcp-server",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "KIRI context extraction platform",
5
5
  "type": "module",
6
6
  "packageManager": "pnpm@9.0.0",
@@ -68,7 +68,7 @@ export class DegradeController {
68
68
  }
69
69
  async withResource(operation, reason) {
70
70
  if (this.state.active) {
71
- throw new Error(`Server is running in degrade mode: ${this.state.reason ?? "unknown"}. Only files.search is available.`);
71
+ throw new Error(`Server is running in degrade mode: ${this.state.reason ?? "unknown"}. Only files_search is available.`);
72
72
  }
73
73
  try {
74
74
  const result = await operation();
@@ -453,7 +453,7 @@ export async function filesSearch(context, params) {
453
453
  const { db, repoId } = context;
454
454
  const { query } = params;
455
455
  if (!query || query.trim().length === 0) {
456
- throw new Error("files.search requires a non-empty query. Provide a search keyword to continue.");
456
+ throw new Error("files_search requires a non-empty query. Provide a search keyword to continue.");
457
457
  }
458
458
  const limit = normalizeLimit(params.limit);
459
459
  const hasFTS = context.features?.fts ?? false;
@@ -550,7 +550,7 @@ export async function filesSearch(context, params) {
550
550
  export async function snippetsGet(context, params) {
551
551
  const { db, repoId } = context;
552
552
  if (!params.path) {
553
- throw new Error("snippets.get requires a file path. Specify a tracked text file path to continue.");
553
+ throw new Error("snippets_get requires a file path. Specify a tracked text file path to continue.");
554
554
  }
555
555
  const rows = await db.all(`
556
556
  SELECT f.path, f.lang, f.ext, f.is_binary, b.content
@@ -630,7 +630,7 @@ export async function contextBundle(context, params) {
630
630
  const { db, repoId } = context;
631
631
  const goal = params.goal?.trim() ?? "";
632
632
  if (goal.length === 0) {
633
- throw new Error("context.bundle requires a non-empty goal. Describe your objective to receive context.");
633
+ throw new Error("context_bundle requires a non-empty goal. Describe your objective to receive context.");
634
634
  }
635
635
  const limit = normalizeBundleLimit(params.limit);
636
636
  const artifacts = params.artifacts ?? {};
@@ -880,7 +880,7 @@ export async function contextBundle(context, params) {
880
880
  export async function semanticRerank(context, params) {
881
881
  const text = params.text?.trim() ?? "";
882
882
  if (text.length === 0) {
883
- throw new Error("semantic.rerank requires non-empty text. Describe the intent to compute semantic similarity.");
883
+ throw new Error("semantic_rerank requires non-empty text. Describe the intent to compute semantic similarity.");
884
884
  }
885
885
  if (!Array.isArray(params.candidates) || params.candidates.length === 0) {
886
886
  return { candidates: [] };
@@ -948,7 +948,7 @@ export async function semanticRerank(context, params) {
948
948
  export async function depsClosure(context, params) {
949
949
  const { db, repoId } = context;
950
950
  if (!params.path) {
951
- throw new Error("deps.closure requires a file path. Provide a tracked source file path to continue.");
951
+ throw new Error("deps_closure requires a file path. Provide a tracked source file path to continue.");
952
952
  }
953
953
  const direction = params.direction ?? "outbound";
954
954
  const maxDepth = params.max_depth ?? 3;
@@ -8,7 +8,7 @@ const SERVER_INFO = {
8
8
  };
9
9
  const TOOL_DESCRIPTORS = [
10
10
  {
11
- name: "context.bundle",
11
+ name: "context_bundle",
12
12
  description: "🎯 PRIMARY TOOL: Extracts relevant code context for a specific task or question.\n\n" +
13
13
  "Use this tool as your first step for any code-related task. It intelligently finds and ranks relevant files and code snippets using keyword matching, dependency analysis, and semantic similarity.\n\n" +
14
14
  "IMPORTANT: The 'goal' parameter MUST be a clear and specific description of your objective. Use concrete keywords, not abstract verbs.\n\n" +
@@ -82,7 +82,7 @@ const TOOL_DESCRIPTORS = [
82
82
  },
83
83
  },
84
84
  {
85
- name: "semantic.rerank",
85
+ name: "semantic_rerank",
86
86
  description: "Re-rank a list of file candidates by semantic similarity to a query text. Uses structural embeddings to compute similarity scores and combines them with existing scores. Use as a REFINEMENT step after files.search or when you have a list of candidates and want to prioritize them by semantic relevance. Not needed with context.bundle (which already does semantic ranking internally). Returns candidates sorted by combined score (base + semantic similarity). Example: after getting 20 search results, rerank them by semantic similarity to 'user authentication flow' to surface the most contextually relevant files.",
87
87
  inputSchema: {
88
88
  type: "object",
@@ -108,7 +108,7 @@ const TOOL_DESCRIPTORS = [
108
108
  },
109
109
  },
110
110
  {
111
- name: "files.search",
111
+ name: "files_search",
112
112
  description: "Search files by specific keywords or identifiers. Use when you know EXACT terms to search for: function names, class names, error messages, or code patterns.\n\n" +
113
113
  "IMPORTANT: For broader exploration like 'understand feature X' or 'how does Y work', use context.bundle instead. This tool is for TARGETED searches with specific identifiers.\n\n" +
114
114
  "✅ GOOD EXAMPLES (specific identifiers):\n" +
@@ -161,7 +161,7 @@ const TOOL_DESCRIPTORS = [
161
161
  },
162
162
  },
163
163
  {
164
- name: "snippets.get",
164
+ name: "snippets_get",
165
165
  description: "Retrieve code snippets from a specific file path. Intelligently extracts relevant code sections using symbol boundaries (functions, classes, methods) when available. Use when you already know the exact file path and want to read its content efficiently without loading the entire file. Automatically selects appropriate snippet based on start_line or returns symbol-aligned chunks. Reduces token usage compared to reading full files. Use context.bundle instead if you don't know which file to read. Example: path='src/auth/login.ts' returns the most relevant function or class in that file.",
166
166
  inputSchema: {
167
167
  type: "object",
@@ -175,7 +175,7 @@ const TOOL_DESCRIPTORS = [
175
175
  },
176
176
  },
177
177
  {
178
- name: "deps.closure",
178
+ name: "deps_closure",
179
179
  description: "Traverse the dependency graph from a starting file. Finds all files that depend on the target (inbound) or that the target depends on (outbound). Essential for impact analysis: understanding what breaks if you change a file, tracing import chains, or mapping module relationships. Returns nodes (files/packages) and edges (import statements) with depth levels. Use when: planning refactoring, understanding module boundaries, finding circular dependencies, or analyzing affected files. Example: path='src/utils.ts', direction='inbound' shows all files importing utils.ts. Set max_depth to limit traversal (default 3).",
180
180
  inputSchema: {
181
181
  type: "object",
@@ -417,17 +417,17 @@ export function validateJsonRpcRequest(payload) {
417
417
  // Helper function to execute a tool by name
418
418
  async function executeToolByName(toolName, toolParams, context, degrade, allowDegrade) {
419
419
  switch (toolName) {
420
- case "context.bundle": {
420
+ case "context_bundle": {
421
421
  const params = parseContextBundleParams(toolParams);
422
- const handler = async () => await withSpan("context.bundle", async () => await contextBundle(context, params));
423
- return await degrade.withResource(handler, "duckdb:context.bundle");
422
+ const handler = async () => await withSpan("context_bundle", async () => await contextBundle(context, params));
423
+ return await degrade.withResource(handler, "duckdb:context_bundle");
424
424
  }
425
- case "semantic.rerank": {
425
+ case "semantic_rerank": {
426
426
  const params = parseSemanticRerankParams(toolParams);
427
- const handler = async () => await withSpan("semantic.rerank", async () => await semanticRerank(context, params));
428
- return await degrade.withResource(handler, "duckdb:semantic.rerank");
427
+ const handler = async () => await withSpan("semantic_rerank", async () => await semanticRerank(context, params));
428
+ return await degrade.withResource(handler, "duckdb:semantic_rerank");
429
429
  }
430
- case "files.search": {
430
+ case "files_search": {
431
431
  const params = parseFilesSearchParams(toolParams);
432
432
  if (degrade.current.active && allowDegrade) {
433
433
  return {
@@ -443,19 +443,19 @@ async function executeToolByName(toolName, toolParams, context, degrade, allowDe
443
443
  };
444
444
  }
445
445
  else {
446
- const handler = async () => await withSpan("files.search", async () => await filesSearch(context, params));
447
- return await degrade.withResource(handler, "duckdb:files.search");
446
+ const handler = async () => await withSpan("files_search", async () => await filesSearch(context, params));
447
+ return await degrade.withResource(handler, "duckdb:files_search");
448
448
  }
449
449
  }
450
- case "snippets.get": {
450
+ case "snippets_get": {
451
451
  const params = parseSnippetsGetParams(toolParams);
452
- const handler = async () => await withSpan("snippets.get", async () => await snippetsGet(context, params));
453
- return await degrade.withResource(handler, "duckdb:snippets.get");
452
+ const handler = async () => await withSpan("snippets_get", async () => await snippetsGet(context, params));
453
+ return await degrade.withResource(handler, "duckdb:snippets_get");
454
454
  }
455
- case "deps.closure": {
455
+ case "deps_closure": {
456
456
  const params = parseDepsClosureParams(toolParams);
457
- const handler = async () => await withSpan("deps.closure", async () => await depsClosure(context, params));
458
- return await degrade.withResource(handler, "duckdb:deps.closure");
457
+ const handler = async () => await withSpan("deps_closure", async () => await depsClosure(context, params));
458
+ return await degrade.withResource(handler, "duckdb:deps_closure");
459
459
  }
460
460
  default:
461
461
  throw new Error(`Unknown tool: ${toolName}`);
@@ -546,31 +546,31 @@ export function createRpcHandler(dependencies) {
546
546
  break;
547
547
  }
548
548
  // Legacy direct method invocation (backward compatibility)
549
- case "context.bundle": {
550
- result = await executeToolByName("context.bundle", payload.params, context, degrade, allowDegrade);
549
+ case "context_bundle": {
550
+ result = await executeToolByName("context_bundle", payload.params, context, degrade, allowDegrade);
551
551
  break;
552
552
  }
553
- case "semantic.rerank": {
554
- result = await executeToolByName("semantic.rerank", payload.params, context, degrade, allowDegrade);
553
+ case "semantic_rerank": {
554
+ result = await executeToolByName("semantic_rerank", payload.params, context, degrade, allowDegrade);
555
555
  break;
556
556
  }
557
- case "files.search": {
558
- result = await executeToolByName("files.search", payload.params, context, degrade, allowDegrade);
557
+ case "files_search": {
558
+ result = await executeToolByName("files_search", payload.params, context, degrade, allowDegrade);
559
559
  break;
560
560
  }
561
- case "snippets.get": {
562
- result = await executeToolByName("snippets.get", payload.params, context, degrade, allowDegrade);
561
+ case "snippets_get": {
562
+ result = await executeToolByName("snippets_get", payload.params, context, degrade, allowDegrade);
563
563
  break;
564
564
  }
565
- case "deps.closure": {
566
- result = await executeToolByName("deps.closure", payload.params, context, degrade, allowDegrade);
565
+ case "deps_closure": {
566
+ result = await executeToolByName("deps_closure", payload.params, context, degrade, allowDegrade);
567
567
  break;
568
568
  }
569
569
  default: {
570
570
  return hasResponseId
571
571
  ? {
572
572
  statusCode: 404,
573
- response: errorResponse(payload.id, "Requested method is not available. Use tools/call, or legacy methods: context.bundle, semantic.rerank, files.search, snippets.get, or deps.closure.", -32601),
573
+ response: errorResponse(payload.id, "Requested method is not available. Use tools/call, or legacy methods: context_bundle, semantic_rerank, files_search, snippets_get, or deps_closure.", -32601),
574
574
  }
575
575
  : null;
576
576
  }
@@ -601,8 +601,8 @@ export function createRpcHandler(dependencies) {
601
601
  ? {
602
602
  statusCode: 503,
603
603
  response: errorResponse(payload.id, degrade.current.reason
604
- ? `Backend degraded due to ${degrade.current.reason}. Only files.search is operational.`
605
- : "Backend degraded. Only files.search is operational."),
604
+ ? `Backend degraded due to ${degrade.current.reason}. Only files_search is operational.`
605
+ : "Backend degraded. Only files_search is operational."),
606
606
  }
607
607
  : null;
608
608
  }
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * スコアリングウェイトの設定
3
- * context.bundle の候補ファイルに対するスコアリング重みを定義
3
+ * context_bundle の候補ファイルに対するスコアリング重みを定義
4
4
  */
5
5
  export interface ScoringWeights {
6
6
  /** テキストマッチ(キーワード検索)の重み */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kiri-mcp-server",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "KIRI context extraction platform",
5
5
  "type": "module",
6
6
  "packageManager": "pnpm@9.0.0",