kiri-mcp-server 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.
Files changed (212) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +399 -0
  3. package/config/default.example.yml +12 -0
  4. package/config/denylist.yml +15 -0
  5. package/config/scoring-profiles.yml +37 -0
  6. package/config/security.yml +10 -0
  7. package/dist/client/cli.js +68 -0
  8. package/dist/client/cli.js.map +1 -0
  9. package/dist/client/index.js +5 -0
  10. package/dist/client/index.js.map +1 -0
  11. package/dist/config/default.example.yml +12 -0
  12. package/dist/config/denylist.yml +15 -0
  13. package/dist/config/scoring-profiles.yml +37 -0
  14. package/dist/config/security.yml +10 -0
  15. package/dist/eval/metrics.js +47 -0
  16. package/dist/eval/metrics.js.map +1 -0
  17. package/dist/indexer/cli.js +362 -0
  18. package/dist/indexer/cli.js.map +1 -0
  19. package/dist/indexer/codeintel.js +182 -0
  20. package/dist/indexer/codeintel.js.map +1 -0
  21. package/dist/indexer/git.js +30 -0
  22. package/dist/indexer/git.js.map +1 -0
  23. package/dist/indexer/language.js +34 -0
  24. package/dist/indexer/language.js.map +1 -0
  25. package/dist/indexer/pipeline/filters/denylist.js +71 -0
  26. package/dist/indexer/pipeline/filters/denylist.js.map +1 -0
  27. package/dist/indexer/schema.js +101 -0
  28. package/dist/indexer/schema.js.map +1 -0
  29. package/dist/package.json +93 -0
  30. package/dist/server/bootstrap.js +19 -0
  31. package/dist/server/bootstrap.js.map +1 -0
  32. package/dist/server/context.js +2 -0
  33. package/dist/server/context.js.map +1 -0
  34. package/dist/server/fallbacks/degradeController.js +69 -0
  35. package/dist/server/fallbacks/degradeController.js.map +1 -0
  36. package/dist/server/handlers.js +800 -0
  37. package/dist/server/handlers.js.map +1 -0
  38. package/dist/server/main.js +151 -0
  39. package/dist/server/main.js.map +1 -0
  40. package/dist/server/observability/metrics.js +56 -0
  41. package/dist/server/observability/metrics.js.map +1 -0
  42. package/dist/server/observability/tracing.js +58 -0
  43. package/dist/server/observability/tracing.js.map +1 -0
  44. package/dist/server/rpc.js +477 -0
  45. package/dist/server/rpc.js.map +1 -0
  46. package/dist/server/runtime.js +47 -0
  47. package/dist/server/runtime.js.map +1 -0
  48. package/dist/server/scoring.js +111 -0
  49. package/dist/server/scoring.js.map +1 -0
  50. package/dist/server/stdio.js +76 -0
  51. package/dist/server/stdio.js.map +1 -0
  52. package/dist/shared/duckdb.js +121 -0
  53. package/dist/shared/duckdb.js.map +1 -0
  54. package/dist/shared/embedding.js +85 -0
  55. package/dist/shared/embedding.js.map +1 -0
  56. package/dist/shared/index.js +9 -0
  57. package/dist/shared/index.js.map +1 -0
  58. package/dist/shared/security/config.js +64 -0
  59. package/dist/shared/security/config.js.map +1 -0
  60. package/dist/shared/security/masker.js +56 -0
  61. package/dist/shared/security/masker.js.map +1 -0
  62. package/dist/shared/tokenizer.js +5 -0
  63. package/dist/shared/tokenizer.js.map +1 -0
  64. package/dist/shared/utils/simpleYaml.js +90 -0
  65. package/dist/shared/utils/simpleYaml.js.map +1 -0
  66. package/dist/sql/schema.sql +6 -0
  67. package/dist/src/client/cli.d.ts +3 -0
  68. package/dist/src/client/cli.d.ts.map +1 -0
  69. package/dist/src/client/cli.js +68 -0
  70. package/dist/src/client/cli.js.map +1 -0
  71. package/dist/src/client/index.d.ts +5 -0
  72. package/dist/src/client/index.d.ts.map +1 -0
  73. package/dist/src/client/index.js +5 -0
  74. package/dist/src/client/index.js.map +1 -0
  75. package/dist/src/client/proxy.d.ts +9 -0
  76. package/dist/src/client/proxy.d.ts.map +1 -0
  77. package/dist/src/client/proxy.js +198 -0
  78. package/dist/src/client/proxy.js.map +1 -0
  79. package/dist/src/client/start-daemon.d.ts +30 -0
  80. package/dist/src/client/start-daemon.d.ts.map +1 -0
  81. package/dist/src/client/start-daemon.js +175 -0
  82. package/dist/src/client/start-daemon.js.map +1 -0
  83. package/dist/src/daemon/daemon.d.ts +9 -0
  84. package/dist/src/daemon/daemon.d.ts.map +1 -0
  85. package/dist/src/daemon/daemon.js +149 -0
  86. package/dist/src/daemon/daemon.js.map +1 -0
  87. package/dist/src/daemon/lifecycle.d.ts +101 -0
  88. package/dist/src/daemon/lifecycle.d.ts.map +1 -0
  89. package/dist/src/daemon/lifecycle.js +266 -0
  90. package/dist/src/daemon/lifecycle.js.map +1 -0
  91. package/dist/src/daemon/socket.d.ts +26 -0
  92. package/dist/src/daemon/socket.d.ts.map +1 -0
  93. package/dist/src/daemon/socket.js +132 -0
  94. package/dist/src/daemon/socket.js.map +1 -0
  95. package/dist/src/eval/metrics.d.ts +23 -0
  96. package/dist/src/eval/metrics.d.ts.map +1 -0
  97. package/dist/src/eval/metrics.js +47 -0
  98. package/dist/src/eval/metrics.js.map +1 -0
  99. package/dist/src/index.d.ts +11 -0
  100. package/dist/src/index.d.ts.map +1 -0
  101. package/dist/src/index.js +11 -0
  102. package/dist/src/index.js.map +1 -0
  103. package/dist/src/indexer/cli.d.ts +9 -0
  104. package/dist/src/indexer/cli.d.ts.map +1 -0
  105. package/dist/src/indexer/cli.js +402 -0
  106. package/dist/src/indexer/cli.js.map +1 -0
  107. package/dist/src/indexer/codeintel.d.ts +28 -0
  108. package/dist/src/indexer/codeintel.d.ts.map +1 -0
  109. package/dist/src/indexer/codeintel.js +451 -0
  110. package/dist/src/indexer/codeintel.js.map +1 -0
  111. package/dist/src/indexer/git.d.ts +4 -0
  112. package/dist/src/indexer/git.d.ts.map +1 -0
  113. package/dist/src/indexer/git.js +30 -0
  114. package/dist/src/indexer/git.js.map +1 -0
  115. package/dist/src/indexer/language.d.ts +2 -0
  116. package/dist/src/indexer/language.d.ts.map +1 -0
  117. package/dist/src/indexer/language.js +34 -0
  118. package/dist/src/indexer/language.js.map +1 -0
  119. package/dist/src/indexer/pipeline/filters/denylist.d.ts +10 -0
  120. package/dist/src/indexer/pipeline/filters/denylist.d.ts.map +1 -0
  121. package/dist/src/indexer/pipeline/filters/denylist.js +71 -0
  122. package/dist/src/indexer/pipeline/filters/denylist.js.map +1 -0
  123. package/dist/src/indexer/schema.d.ts +9 -0
  124. package/dist/src/indexer/schema.d.ts.map +1 -0
  125. package/dist/src/indexer/schema.js +125 -0
  126. package/dist/src/indexer/schema.js.map +1 -0
  127. package/dist/src/indexer/watch.d.ts +97 -0
  128. package/dist/src/indexer/watch.d.ts.map +1 -0
  129. package/dist/src/indexer/watch.js +264 -0
  130. package/dist/src/indexer/watch.js.map +1 -0
  131. package/dist/src/server/bootstrap.d.ts +11 -0
  132. package/dist/src/server/bootstrap.d.ts.map +1 -0
  133. package/dist/src/server/bootstrap.js +19 -0
  134. package/dist/src/server/bootstrap.js.map +1 -0
  135. package/dist/src/server/context.d.ts +9 -0
  136. package/dist/src/server/context.d.ts.map +1 -0
  137. package/dist/src/server/context.js +2 -0
  138. package/dist/src/server/context.js.map +1 -0
  139. package/dist/src/server/fallbacks/degradeController.d.ts +24 -0
  140. package/dist/src/server/fallbacks/degradeController.d.ts.map +1 -0
  141. package/dist/src/server/fallbacks/degradeController.js +135 -0
  142. package/dist/src/server/fallbacks/degradeController.js.map +1 -0
  143. package/dist/src/server/handlers.d.ts +105 -0
  144. package/dist/src/server/handlers.d.ts.map +1 -0
  145. package/dist/src/server/handlers.js +954 -0
  146. package/dist/src/server/handlers.js.map +1 -0
  147. package/dist/src/server/indexBootstrap.d.ts +13 -0
  148. package/dist/src/server/indexBootstrap.d.ts.map +1 -0
  149. package/dist/src/server/indexBootstrap.js +109 -0
  150. package/dist/src/server/indexBootstrap.js.map +1 -0
  151. package/dist/src/server/main.d.ts +10 -0
  152. package/dist/src/server/main.d.ts.map +1 -0
  153. package/dist/src/server/main.js +217 -0
  154. package/dist/src/server/main.js.map +1 -0
  155. package/dist/src/server/observability/metrics.d.ts +35 -0
  156. package/dist/src/server/observability/metrics.d.ts.map +1 -0
  157. package/dist/src/server/observability/metrics.js +70 -0
  158. package/dist/src/server/observability/metrics.js.map +1 -0
  159. package/dist/src/server/observability/tracing.d.ts +3 -0
  160. package/dist/src/server/observability/tracing.d.ts.map +1 -0
  161. package/dist/src/server/observability/tracing.js +58 -0
  162. package/dist/src/server/observability/tracing.js.map +1 -0
  163. package/dist/src/server/rpc.d.ts +39 -0
  164. package/dist/src/server/rpc.d.ts.map +1 -0
  165. package/dist/src/server/rpc.js +551 -0
  166. package/dist/src/server/rpc.js.map +1 -0
  167. package/dist/src/server/runtime.d.ts +21 -0
  168. package/dist/src/server/runtime.d.ts.map +1 -0
  169. package/dist/src/server/runtime.js +59 -0
  170. package/dist/src/server/runtime.js.map +1 -0
  171. package/dist/src/server/scoring.d.ts +20 -0
  172. package/dist/src/server/scoring.d.ts.map +1 -0
  173. package/dist/src/server/scoring.js +112 -0
  174. package/dist/src/server/scoring.js.map +1 -0
  175. package/dist/src/server/stdio.d.ts +4 -0
  176. package/dist/src/server/stdio.d.ts.map +1 -0
  177. package/dist/src/server/stdio.js +88 -0
  178. package/dist/src/server/stdio.js.map +1 -0
  179. package/dist/src/shared/duckdb.d.ts +16 -0
  180. package/dist/src/shared/duckdb.d.ts.map +1 -0
  181. package/dist/src/shared/duckdb.js +121 -0
  182. package/dist/src/shared/duckdb.js.map +1 -0
  183. package/dist/src/shared/embedding.d.ts +19 -0
  184. package/dist/src/shared/embedding.d.ts.map +1 -0
  185. package/dist/src/shared/embedding.js +85 -0
  186. package/dist/src/shared/embedding.js.map +1 -0
  187. package/dist/src/shared/index.d.ts +3 -0
  188. package/dist/src/shared/index.d.ts.map +1 -0
  189. package/dist/src/shared/index.js +9 -0
  190. package/dist/src/shared/index.js.map +1 -0
  191. package/dist/src/shared/security/config.d.ts +23 -0
  192. package/dist/src/shared/security/config.d.ts.map +1 -0
  193. package/dist/src/shared/security/config.js +66 -0
  194. package/dist/src/shared/security/config.js.map +1 -0
  195. package/dist/src/shared/security/masker.d.ts +10 -0
  196. package/dist/src/shared/security/masker.d.ts.map +1 -0
  197. package/dist/src/shared/security/masker.js +56 -0
  198. package/dist/src/shared/security/masker.js.map +1 -0
  199. package/dist/src/shared/tokenizer.d.ts +2 -0
  200. package/dist/src/shared/tokenizer.d.ts.map +1 -0
  201. package/dist/src/shared/tokenizer.js +5 -0
  202. package/dist/src/shared/tokenizer.js.map +1 -0
  203. package/dist/src/shared/utils/lockfile.d.ts +46 -0
  204. package/dist/src/shared/utils/lockfile.d.ts.map +1 -0
  205. package/dist/src/shared/utils/lockfile.js +136 -0
  206. package/dist/src/shared/utils/lockfile.js.map +1 -0
  207. package/dist/src/shared/utils/simpleYaml.d.ts +6 -0
  208. package/dist/src/shared/utils/simpleYaml.d.ts.map +1 -0
  209. package/dist/src/shared/utils/simpleYaml.js +90 -0
  210. package/dist/src/shared/utils/simpleYaml.js.map +1 -0
  211. package/package.json +91 -0
  212. package/sql/schema.sql +6 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 CAPHTECH
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,399 @@
1
+ # KIRI
2
+
3
+ > Context extraction platform for LLMs - Minimal, relevant code fragments from Git repositories
4
+
5
+ [![Version](https://img.shields.io/badge/version-0.2.0-blue.svg)](package.json)
6
+ [![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
7
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.6-blue.svg)](https://www.typescriptlang.org/)
8
+
9
+ **KIRI** is a context extraction platform that indexes Git repositories into DuckDB and provides MCP (Model Context Protocol) tools for semantic code search. It extracts minimal, relevant code fragments (snippets) based on structure, history, and proximity to minimize LLM token usage.
10
+
11
+ ## 🎯 Key Features
12
+
13
+ - **🔍 Smart Code Search**: Full-text search with multi-word queries, FTS/BM25 ranking, and graceful fallback
14
+ - **📦 Context Bundling**: Extract relevant code fragments based on task goals
15
+ - **🔗 Dependency Analysis**: Bidirectional dependency graphs (outbound and inbound closure)
16
+ - **⚡ Fast Response**: Time to first useful result ≤ 1.0s
17
+ - **🛡️ Degrade-First Architecture**: Works without VSS/FTS extensions via fallback
18
+ - **🔌 MCP Integration**: JSON-RPC 2.0 over stdio/HTTP
19
+ - **👁️ Watch Mode**: Automatic re-indexing on file changes with debouncing
20
+
21
+ ## 📝 Supported Languages
22
+
23
+ KIRI currently supports AST-based symbol extraction for:
24
+
25
+ | Language | Extensions | Symbol Types | Parser |
26
+ | -------------- | ------------- | ------------------------------------------------------------------------------ | ----------------------- |
27
+ | **TypeScript** | `.ts`, `.tsx` | `class`, `interface`, `enum`, `function`, `method` | TypeScript Compiler API |
28
+ | **Swift** | `.swift` | `class`, `struct`, `protocol`, `enum`, `extension`, `func`, `init`, `property` | tree-sitter-swift |
29
+
30
+ Other languages are detected and indexed but use full-file snippets instead of symbol-level extraction. Support for additional languages (Rust, Go, Python, etc.) is planned.
31
+
32
+ ## 🚀 Quick Start
33
+
34
+ ### Installation
35
+
36
+ #### For End Users (after npm publication)
37
+
38
+ ```bash
39
+ # Global installation (recommended)
40
+ npm install -g kiri-mcp-server
41
+
42
+ # Or use npx (no installation required)
43
+ npx kiri-mcp-server --repo . --db .kiri/index.duckdb
44
+ ```
45
+
46
+ #### For Development
47
+
48
+ ```bash
49
+ # Clone and install dependencies
50
+ git clone https://github.com/CAPHTECH/kiri.git
51
+ cd kiri
52
+ pnpm install
53
+
54
+ # Build the project
55
+ pnpm run build
56
+
57
+ # Link the package globally (makes 'kiri' command available)
58
+ npm link
59
+ ```
60
+
61
+ ### Start MCP Server
62
+
63
+ **Note**: Since v0.1.0, the server automatically indexes your repository on first startup if the database doesn't exist. No manual indexing step required!
64
+
65
+ #### Stdio Mode (for MCP clients like Codex)
66
+
67
+ ```bash
68
+ # Start stdio server (auto-indexes if DB doesn't exist)
69
+ kiri-server --repo . --db .kiri/index.duckdb
70
+
71
+ # Force re-indexing
72
+ kiri-server --repo . --db .kiri/index.duckdb --reindex
73
+
74
+ # Start with watch mode (auto-reindex on file changes)
75
+ kiri-server --repo . --db .kiri/index.duckdb --watch
76
+
77
+ # Customize debounce timing (default: 500ms)
78
+ kiri-server --repo . --db .kiri/index.duckdb --watch --debounce 1000
79
+ ```
80
+
81
+ > インストールなしで試す場合は `npx kiri-mcp-server@latest kiri-server --repo . --db .kiri/index.duckdb` を利用できる。
82
+
83
+ #### Manual Indexing (Optional)
84
+
85
+ If you prefer to index manually before starting the server:
86
+
87
+ ```bash
88
+ # Run once to create the database, then exit
89
+ kiri-server --repo . --db .kiri/index.duckdb --reindex
90
+
91
+ # Or use the daemon for background indexing
92
+ kiri-daemon --repo . --db .kiri/index.duckdb --watch
93
+ ```
94
+
95
+ #### HTTP Mode (for testing)
96
+
97
+ ```bash
98
+ # Start HTTP server on port 8765
99
+ kiri-server --repo . --db .kiri/index.duckdb --port 8765
100
+
101
+ # Or specify custom port
102
+ kiri-server --repo . --db .kiri/index.duckdb --port 9000
103
+
104
+ # With watch mode enabled
105
+ kiri-server --repo . --db .kiri/index.duckdb --port 8765 --watch --debounce 1000
106
+ ```
107
+
108
+ ## 📋 MCP Tools
109
+
110
+ KIRI provides 5 MCP tools for code exploration:
111
+
112
+ | Tool | Description |
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) |
119
+
120
+ ### Search Query Syntax
121
+
122
+ **files.search** supports multi-word queries automatically:
123
+
124
+ - `"tools call implementation"` → Finds files containing ANY of these words (OR logic)
125
+ - `"MCP-server-handler"` → Splits on hyphens and searches for each part
126
+ - Single words work as expected: `"DuckDB"` → Exact match
127
+
128
+ When DuckDB's FTS extension is available, searches use BM25 ranking for better relevance. Otherwise, the system falls back to pattern matching (ILIKE) with graceful degradation.
129
+
130
+ ### File Type Boosting
131
+
132
+ Control search ranking behavior with the `boost_profile` parameter:
133
+
134
+ - **`"default"`** (default): Prioritizes implementation files (src/\*.ts) over documentation
135
+ - **`"docs"`**: Prioritizes documentation files (\*.md) over implementation
136
+ - **`"none"`**: Pure BM25 scoring without file type adjustments
137
+
138
+ ```javascript
139
+ // Find implementation files (default behavior)
140
+ mcp__kiri__files_search({ query: "filesSearch implementation" });
141
+
142
+ // Find documentation
143
+ mcp__kiri__files_search({ query: "setup guide", boost_profile: "docs" });
144
+
145
+ // Pure BM25 ranking
146
+ mcp__kiri__files_search({ query: "authentication", boost_profile: "none" });
147
+ ```
148
+
149
+ ## 🔧 Configuration
150
+
151
+ ### Watch Mode
152
+
153
+ Watch mode monitors your repository for file changes and automatically re-indexes when changes are detected:
154
+
155
+ - **Debouncing**: Aggregates rapid consecutive changes to minimize reindex operations (default: 500ms)
156
+ - **Denylist Integration**: Respects both `denylist.yml` and `.gitignore` patterns
157
+ - **Lock Management**: Prevents concurrent indexing using lock files
158
+ - **Graceful Shutdown**: Supports `SIGINT`/`SIGTERM` for clean termination
159
+ - **Statistics**: Tracks reindex count, duration, and queue depth
160
+
161
+ ```bash
162
+ # Enable watch mode with default debounce (500ms)
163
+ kiri-server --repo . --db .kiri/index.duckdb --watch
164
+
165
+ # Customize debounce timing for slower hardware or network filesystems
166
+ kiri-server --repo . --db .kiri/index.duckdb --watch --debounce 1000
167
+
168
+ # Watch mode works with both stdio and HTTP modes
169
+ kiri-server --repo . --db .kiri/index.duckdb --port 8765 --watch
170
+ ```
171
+
172
+ **Note**: Watch mode runs in parallel with the MCP server. File changes trigger reindexing in the background without interrupting ongoing queries.
173
+
174
+ ### MCP Client Integration
175
+
176
+ #### Option 1: Global Installation (Recommended for End Users)
177
+
178
+ ```bash
179
+ npm install -g kiri-mcp-server
180
+ ```
181
+
182
+ Create `~/.config/codex/mcp.json` or `.claude/mcp.json`:
183
+
184
+ ```json
185
+ {
186
+ "mcpServers": {
187
+ "kiri": {
188
+ "command": "kiri",
189
+ "args": [
190
+ "--repo",
191
+ "/path/to/your/project",
192
+ "--db",
193
+ "/path/to/your/project/.kiri/index.duckdb",
194
+ "--watch"
195
+ ]
196
+ }
197
+ }
198
+ }
199
+ ```
200
+
201
+ #### Option 2: npx (No Installation Required)
202
+
203
+ ```json
204
+ {
205
+ "mcpServers": {
206
+ "kiri": {
207
+ "command": "npx",
208
+ "args": [
209
+ "kiri-mcp-server",
210
+ "--repo",
211
+ "/path/to/your/project",
212
+ "--db",
213
+ "/path/to/your/project/.kiri/index.duckdb"
214
+ ]
215
+ }
216
+ }
217
+ }
218
+ ```
219
+
220
+ **Note**: `npx` automatically downloads and caches the package on first use. Subsequent starts are faster.
221
+
222
+ #### Option 3: Local Development (with npm link)
223
+
224
+ After running `npm link` in the KIRI repository:
225
+
226
+ ```json
227
+ {
228
+ "mcpServers": {
229
+ "kiri": {
230
+ "command": "kiri",
231
+ "args": [
232
+ "--repo",
233
+ "/path/to/your/project",
234
+ "--db",
235
+ "/path/to/your/project/.kiri/index.duckdb",
236
+ "--watch"
237
+ ]
238
+ }
239
+ }
240
+ }
241
+ ```
242
+
243
+ **Note**: The `kiri` command will use the symlinked version from your local development directory. Changes require rebuilding with `pnpm run build`.
244
+
245
+ See [examples/README.md](examples/README.md) for detailed usage examples.
246
+
247
+ ## 🏗️ Architecture
248
+
249
+ ```
250
+ ┌────────────────────┐ ┌─────────────────────────────┐ ┌────────────────────┐
251
+ │ MCP Client │<--->│ KIRI MCP Server (JSON-RPC) │<--->│ DuckDB │
252
+ │ (Codex CLI, etc.) │ │ tools: search/bundle/... │ │ index.duckdb │
253
+ └────────────────────┘ └─────────────────────────────┘ └────────────────────┘
254
+ ^
255
+
256
+ ┌─────────┴──────────┐
257
+ │ Indexer │
258
+ │ git scan / AST │
259
+ │ embedding (opt) │
260
+ └────────────────────┘
261
+ ```
262
+
263
+ ### Three-Tier Architecture
264
+
265
+ 1. **Indexer** (`src/indexer/`): Scans Git worktrees, extracts metadata and content, persists to DuckDB
266
+ 2. **MCP Server** (`src/server/`): JSON-RPC 2.0 server exposing search and context tools
267
+ 3. **Client** (`src/client/`): CLI utilities and integration helpers
268
+
269
+ ## 📊 Data Model
270
+
271
+ KIRI uses a **blob/tree separation** pattern (similar to Git internals):
272
+
273
+ - **`blob`**: Stores unique file content by hash (deduplicates renamed/copied files)
274
+ - **`tree`**: Maps `repo_id + commit_hash + path → blob_hash`
275
+ - **`file`**: Convenience view of HEAD state for fast queries
276
+ - **`symbol`**: AST-based function/class/method boundaries
277
+ - **`snippet`**: Line-range chunks aligned to symbol boundaries
278
+
279
+ See [docs/data-model.md](docs/data-model.md) for complete schema details.
280
+
281
+ ## 🧪 Development
282
+
283
+ ### Run Tests
284
+
285
+ ```bash
286
+ # Run all tests with coverage (requires ≥80%)
287
+ pnpm run test
288
+
289
+ # Run specific test file
290
+ pnpm exec vitest run tests/server/handlers.spec.ts
291
+
292
+ # Run tests in watch mode
293
+ pnpm exec vitest
294
+ ```
295
+
296
+ ### Code Quality
297
+
298
+ ```bash
299
+ # Lint and test
300
+ pnpm run check
301
+
302
+ # Fix linting issues
303
+ pnpm exec eslint --fix "src/**/*.ts"
304
+ ```
305
+
306
+ ### Project Structure
307
+
308
+ ```
309
+ kiri/
310
+ ├── src/
311
+ │ ├── indexer/ # Git scanning, language detection, schema management
312
+ │ ├── server/ # MCP server, JSON-RPC handlers, context resolution
313
+ │ ├── shared/ # DuckDB client wrapper, common utilities
314
+ │ └── client/ # CLI and integration utilities
315
+ ├── tests/ # Test files (mirrors src/ structure)
316
+ ├── docs/ # Architecture documentation
317
+ ├── config/ # YAML configuration schemas
318
+ ├── sql/ # SQL schema definitions
319
+ ├── examples/ # Usage examples and integration guides
320
+ └── var/ # Generated files and databases (gitignored)
321
+ ```
322
+
323
+ ## 📚 Documentation
324
+
325
+ - [Overview](docs/overview.md) - Core design and architecture
326
+ - [Data Model](docs/data-model.md) - Database schema details
327
+ - [Indexer](docs/indexer.md) - Indexing logic and patterns
328
+ - [Search & Ranking](docs/search-ranking.md) - Search algorithms
329
+ - [API Reference](docs/api-and-client.md) - API documentation
330
+ - [Codex Setup](docs/codex-setup.md) - Codex integration guide
331
+ - [Examples](examples/README.md) - Usage examples
332
+
333
+ ## 🎯 Performance Targets
334
+
335
+ | Metric | Target | Description |
336
+ | ------------------- | ------ | ------------------------------------------- |
337
+ | **P@10** | ≥ 0.7 | Precision at 10 - Top 10 snippets relevance |
338
+ | **TTFU** | ≤ 1.0s | Time to first useful result |
339
+ | **Token Reduction** | ≥ 40% | Compared to naive copy-paste approach |
340
+ | **Coverage** | ≥ 80% | Statement and line coverage for tests |
341
+
342
+ ## 🔐 Security
343
+
344
+ - Sensitive paths (`.env*`, `*.pem`, `secrets/**`) are filtered by both `.gitignore` and indexer
345
+ - All responses mask sensitive values with `***`
346
+ - No credentials or secrets are stored in the database
347
+
348
+ ## 🛠️ Commands Reference
349
+
350
+ ```bash
351
+ # Build
352
+ pnpm run build # Compile TypeScript to dist/
353
+
354
+ # Development
355
+ pnpm run dev # Start HTTP server with hot reload on :8765
356
+
357
+ # Testing
358
+ pnpm run test # Run all tests with coverage
359
+ pnpm run check # Lint + test
360
+
361
+ # Server modes (installed globally or via npx)
362
+ kiri-server --repo <path> --db <db-path> # stdio mode (auto-indexes if needed)
363
+ kiri-server --repo <path> --db <db-path> --port 8765 # HTTP mode (auto-indexes if needed)
364
+ kiri-server --repo <path> --db <db-path> --reindex # Force re-indexing
365
+ kiri-server --repo <path> --db <db-path> --watch # Enable watch mode
366
+ kiri-server --repo <path> --db <db-path> --watch --debounce 1000 # Custom debounce timing
367
+
368
+ # npx without global install
369
+ npx kiri-mcp-server@latest kiri-server --repo <path> --db <db-path>
370
+ ```
371
+
372
+ ## 🤝 Contributing
373
+
374
+ We follow these conventions:
375
+
376
+ - **Code Style**: 2-space indentation, `camelCase` for variables, `PascalCase` for types
377
+ - **Commits**: [Conventional Commits](https://www.conventionalcommits.org/) format
378
+ - **Testing**: Maintain ≥80% coverage for new code
379
+ - **Documentation**: Update relevant docs with code changes
380
+
381
+ See [AGENTS.md](AGENTS.md) for detailed guidelines.
382
+
383
+ ## 📄 License
384
+
385
+ MIT License - See [LICENSE](LICENSE) for details.
386
+
387
+ ## 🙏 Acknowledgments
388
+
389
+ Built with:
390
+
391
+ - [DuckDB](https://duckdb.org/) - Embedded analytical database
392
+ - [tree-sitter](https://tree-sitter.github.io/) - Parser generator for AST extraction
393
+ - [MCP](https://modelcontextprotocol.io/) - Model Context Protocol
394
+
395
+ ---
396
+
397
+ **Status**: v0.2.0 (Alpha) - Active development
398
+
399
+ For questions or issues, please open a [GitHub issue](https://github.com/CAPHTECH/kiri/issues).
@@ -0,0 +1,12 @@
1
+ mcp:
2
+ port: 8765
3
+ host: 127.0.0.1
4
+ tools:
5
+ - context.bundle
6
+ - files.search
7
+ indexer:
8
+ repoRoot: "../../target-repo"
9
+ database: "var/index.duckdb"
10
+ exclude:
11
+ - "**/node_modules/**"
12
+ - "**/dist/**"
@@ -0,0 +1,15 @@
1
+ # Paths that must never be indexed or surfaced
2
+ patterns:
3
+ - secrets/**
4
+ - "*.pem"
5
+ - .env*
6
+ # Binary and archive files
7
+ - "*.zip"
8
+ - "*.tar"
9
+ - "*.tar.gz"
10
+ - "*.tgz"
11
+ - "*.rar"
12
+ - "*.7z"
13
+ - "*.jar"
14
+ - "*.war"
15
+ - "*.ear"
@@ -0,0 +1,37 @@
1
+ # Scoring weight profiles for context.bundle
2
+ # Each profile defines weights for different ranking signals
3
+
4
+ default:
5
+ textMatch: 1.0 # Text/keyword match weight
6
+ editingPath: 2.0 # Currently editing file weight
7
+ dependency: 0.5 # Dependency relationship weight
8
+ proximity: 0.25 # Same directory weight
9
+ structural: 0.75 # Structural similarity weight (LSH-based, not semantic embeddings)
10
+
11
+ bugfix:
12
+ textMatch: 1.0
13
+ editingPath: 1.8
14
+ dependency: 0.7 # Higher: bugs often in dependencies
15
+ proximity: 0.35
16
+ structural: 0.9 # Higher: structural understanding helps
17
+
18
+ testfail:
19
+ textMatch: 1.0
20
+ editingPath: 1.6
21
+ dependency: 0.85 # Very high: failed tests reveal dependencies
22
+ proximity: 0.3
23
+ structural: 0.8
24
+
25
+ typeerror:
26
+ textMatch: 1.0
27
+ editingPath: 1.4
28
+ dependency: 0.6
29
+ proximity: 0.4 # Higher: type errors cluster in modules
30
+ structural: 0.6 # Lower: type errors are structural
31
+
32
+ feature:
33
+ textMatch: 1.0
34
+ editingPath: 1.5
35
+ dependency: 0.45 # Lower: new features less dependent
36
+ proximity: 0.5 # Higher: features cluster spatially
37
+ structural: 0.7
@@ -0,0 +1,10 @@
1
+ # Security baseline for KIRI MCP deployment
2
+ allowed_paths:
3
+ - ./
4
+ - ../shared
5
+ allow_network_egress: false
6
+ allow_subprocess: false
7
+ sensitive_tokens:
8
+ - "sk-"
9
+ - "ghp_"
10
+ - "-----BEGIN"
@@ -0,0 +1,68 @@
1
+ #!/usr/bin/env node
2
+ import process from "node:process";
3
+ import { bootstrapServer } from "../server/bootstrap.js";
4
+ import { evaluateSecurityStatus, updateSecurityLock } from "../shared/security/config.js";
5
+ function printUsage() {
6
+ console.info(`Usage: pnpm exec tsx src/client/cli.ts <command> [options]\n`);
7
+ console.info(`Commands:`);
8
+ console.info(` security verify [--write-lock] Verify security baseline matches lock file`);
9
+ }
10
+ function formatStatus() {
11
+ const status = evaluateSecurityStatus();
12
+ const lockInfo = status.lockHash ? `hash=${status.lockHash}` : "missing";
13
+ const matchState = status.matches ? "MATCH" : "MISMATCH";
14
+ return [
15
+ `config: ${status.configPath}`,
16
+ `lock: ${status.lockPath} (${lockInfo})`,
17
+ `state: ${matchState}`,
18
+ ].join("\n");
19
+ }
20
+ function handleSecurityVerify(argv) {
21
+ const writeLock = argv.includes("--write-lock");
22
+ const status = evaluateSecurityStatus();
23
+ if (!status.lockHash && writeLock) {
24
+ updateSecurityLock(status.hash);
25
+ console.info("Security lock created.");
26
+ const refreshed = evaluateSecurityStatus();
27
+ console.info([
28
+ `config: ${refreshed.configPath}`,
29
+ `lock: ${refreshed.lockPath} (hash=${refreshed.lockHash})`,
30
+ "state: MATCH",
31
+ ].join("\n"));
32
+ return 0;
33
+ }
34
+ try {
35
+ bootstrapServer({ allowWriteLock: writeLock });
36
+ console.info("Security baseline verified.");
37
+ console.info(formatStatus());
38
+ return 0;
39
+ }
40
+ catch (error) {
41
+ console.error(error instanceof Error ? error.message : String(error));
42
+ console.info(formatStatus());
43
+ return 1;
44
+ }
45
+ }
46
+ export function main(argv = process.argv.slice(2)) {
47
+ const [command, ...rest] = argv;
48
+ switch (command) {
49
+ case "security": {
50
+ const [subcommand, ...subArgs] = rest;
51
+ if (subcommand === "verify") {
52
+ return handleSecurityVerify(subArgs);
53
+ }
54
+ break;
55
+ }
56
+ case undefined:
57
+ printUsage();
58
+ return 1;
59
+ default:
60
+ break;
61
+ }
62
+ printUsage();
63
+ return 1;
64
+ }
65
+ if (process.argv[1] && new URL(import.meta.url).pathname === process.argv[1]) {
66
+ process.exitCode = main();
67
+ }
68
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/client/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export function buildContextBundleRequest(snippets) {
2
+ // TODO: align with MCP client schema
3
+ return JSON.stringify({ snippets }, null, 2);
4
+ }
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,yBAAyB,CACvC,QAAkD;IAElD,qCAAqC;IACrC,OAAO,IAAI,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AAC/C,CAAC"}
@@ -0,0 +1,12 @@
1
+ mcp:
2
+ port: 8765
3
+ host: 127.0.0.1
4
+ tools:
5
+ - context.bundle
6
+ - files.search
7
+ indexer:
8
+ repoRoot: "../../target-repo"
9
+ database: "var/index.duckdb"
10
+ exclude:
11
+ - "**/node_modules/**"
12
+ - "**/dist/**"
@@ -0,0 +1,15 @@
1
+ # Paths that must never be indexed or surfaced
2
+ patterns:
3
+ - secrets/**
4
+ - "*.pem"
5
+ - .env*
6
+ # Binary and archive files
7
+ - "*.zip"
8
+ - "*.tar"
9
+ - "*.tar.gz"
10
+ - "*.tgz"
11
+ - "*.rar"
12
+ - "*.7z"
13
+ - "*.jar"
14
+ - "*.war"
15
+ - "*.ear"
@@ -0,0 +1,37 @@
1
+ # Scoring weight profiles for context.bundle
2
+ # Each profile defines weights for different ranking signals
3
+
4
+ default:
5
+ textMatch: 1.0 # Text/keyword match weight
6
+ editingPath: 2.0 # Currently editing file weight
7
+ dependency: 0.5 # Dependency relationship weight
8
+ proximity: 0.25 # Same directory weight
9
+ structural: 0.75 # Structural similarity weight (LSH-based, not semantic embeddings)
10
+
11
+ bugfix:
12
+ textMatch: 1.0
13
+ editingPath: 1.8
14
+ dependency: 0.7 # Higher: bugs often in dependencies
15
+ proximity: 0.35
16
+ structural: 0.9 # Higher: structural understanding helps
17
+
18
+ testfail:
19
+ textMatch: 1.0
20
+ editingPath: 1.6
21
+ dependency: 0.85 # Very high: failed tests reveal dependencies
22
+ proximity: 0.3
23
+ structural: 0.8
24
+
25
+ typeerror:
26
+ textMatch: 1.0
27
+ editingPath: 1.4
28
+ dependency: 0.6
29
+ proximity: 0.4 # Higher: type errors cluster in modules
30
+ structural: 0.6 # Lower: type errors are structural
31
+
32
+ feature:
33
+ textMatch: 1.0
34
+ editingPath: 1.5
35
+ dependency: 0.45 # Lower: new features less dependent
36
+ proximity: 0.5 # Higher: features cluster spatially
37
+ structural: 0.7
@@ -0,0 +1,10 @@
1
+ # Security baseline for KIRI MCP deployment
2
+ allowed_paths:
3
+ - ./
4
+ - ../shared
5
+ allow_network_egress: false
6
+ allow_subprocess: false
7
+ sensitive_tokens:
8
+ - "sk-"
9
+ - "ghp_"
10
+ - "-----BEGIN"