@dikolab/kbdb 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.
Files changed (193) hide show
  1. package/README.md +30 -9
  2. package/dist/cli.cjs +181 -50
  3. package/dist/cli.cjs.map +3 -3
  4. package/dist/cli.mjs +181 -50
  5. package/dist/cli.mjs.map +3 -3
  6. package/dist/kbdb-worker.cjs +283 -29
  7. package/dist/kbdb-worker.cjs.map +4 -4
  8. package/dist/mod.cjs +13 -2
  9. package/dist/mod.cjs.map +2 -2
  10. package/dist/mod.mjs +13 -2
  11. package/dist/mod.mjs.map +2 -2
  12. package/dist/src/shared/cli/functions/format-output.function.d.ts +7 -7
  13. package/dist/src/shared/cli/functions/run-search.function.d.ts +25 -16
  14. package/dist/src/shared/cli/index.d.ts +1 -1
  15. package/dist/src/shared/cli/typings/cli-options.interface.d.ts +2 -0
  16. package/dist/src/shared/cli/typings/search-display.model.d.ts +25 -7
  17. package/dist/src/shared/mcp/functions/handle-recall.function.d.ts +29 -0
  18. package/dist/src/shared/mcp/typings/mcp-client.interface.d.ts +30 -11
  19. package/dist/src/shared/version/constants/version.constant.d.ts +1 -1
  20. package/dist/src/shared/wasm-codec/functions/decode-recall-result.function.d.ts +28 -0
  21. package/dist/src/shared/wasm-codec/functions/decode-scored-results.function.d.ts +14 -7
  22. package/dist/src/shared/wasm-codec/functions/encode-recall-params.function.d.ts +21 -0
  23. package/dist/src/shared/wasm-codec/functions/encode-search-params.function.d.ts +1 -1
  24. package/dist/src/shared/wasm-codec/index.d.ts +5 -2
  25. package/dist/src/shared/worker-client/classes/worker-client.class.d.ts +13 -3
  26. package/dist/src/shared/worker-client/index.d.ts +2 -1
  27. package/dist/src/shared/worker-client/typings/recall-result.model.d.ts +94 -0
  28. package/dist/src/shared/worker-client/typings/search-params.model.d.ts +2 -0
  29. package/dist/src/shared/worker-client/typings/search-result.model.d.ts +23 -7
  30. package/dist/src/shared/worker-daemon/classes/worker-daemon.class.d.ts +1 -0
  31. package/dist/wasm/fs-database/kbdb_fs_database.d.ts +18 -0
  32. package/dist/wasm/fs-database/kbdb_fs_database.js +30 -0
  33. package/dist/wasm/fs-database/kbdb_fs_database_bg.wasm +0 -0
  34. package/dist/wasm/fs-database/kbdb_fs_database_bg.wasm.d.ts +2 -0
  35. package/dist/wasm/kb-worker/kbdb_worker.d.ts +38 -0
  36. package/dist/wasm/kb-worker/kbdb_worker.js +56 -0
  37. package/dist/wasm/kb-worker/kbdb_worker_bg.wasm +0 -0
  38. package/dist/wasm/kb-worker/kbdb_worker_bg.wasm.d.ts +3 -0
  39. package/dist/worker.mjs +283 -29
  40. package/dist/worker.mjs.map +4 -4
  41. package/docs/details/README.md +26 -0
  42. package/docs/details/cli.md +608 -0
  43. package/docs/details/library-api.md +406 -0
  44. package/docs/details/mcp-server.md +430 -0
  45. package/docs/details/search-and-ranking.md +457 -0
  46. package/docs/details/storage.md +529 -0
  47. package/docs/goals/agents.md +751 -0
  48. package/docs/goals/architecture.svg +198 -0
  49. package/docs/goals/cli.md +2308 -0
  50. package/docs/goals/content-composer.md +609 -0
  51. package/docs/goals/content-parser.md +279 -0
  52. package/docs/goals/database.md +1452 -0
  53. package/docs/goals/document.md +368 -0
  54. package/docs/goals/mcp.md +1467 -0
  55. package/docs/goals/overview.md +124 -0
  56. package/docs/goals/query-parser.md +271 -0
  57. package/docs/goals/query-result.md +693 -0
  58. package/docs/goals/skills.md +738 -0
  59. package/docs/goals/worker-client.md +944 -0
  60. package/docs/goals/worker-daemon.md +1447 -0
  61. package/docs/modules/overview.md +298 -0
  62. package/docs/modules/rust/fs-database/functions/document.md +48 -0
  63. package/docs/modules/rust/fs-database/functions/integrity.md +68 -0
  64. package/docs/modules/rust/fs-database/functions/io.md +87 -0
  65. package/docs/modules/rust/fs-database/functions/module.md +22 -0
  66. package/docs/modules/rust/fs-database/functions/query-exec.md +44 -0
  67. package/docs/modules/rust/fs-database/functions/section.md +59 -0
  68. package/docs/modules/rust/fs-database/indexes/btree.md +35 -0
  69. package/docs/modules/rust/fs-database/indexes/corpus.md +61 -0
  70. package/docs/modules/rust/fs-database/indexes/inverted.md +60 -0
  71. package/docs/modules/rust/fs-database/indexes/module.md +64 -0
  72. package/docs/modules/rust/fs-database/indexes/positional.md +39 -0
  73. package/docs/modules/rust/fs-database/module.md +149 -0
  74. package/docs/modules/rust/fs-database/types/catalog.md +53 -0
  75. package/docs/modules/rust/fs-database/types/module.md +12 -0
  76. package/docs/modules/rust/fs-database/types/section.md +101 -0
  77. package/docs/modules/rust/kb-worker/functions/compose.md +57 -0
  78. package/docs/modules/rust/kb-worker/functions/module.md +20 -0
  79. package/docs/modules/rust/kb-worker/functions/retrieve.md +194 -0
  80. package/docs/modules/rust/kb-worker/functions/search.md +173 -0
  81. package/docs/modules/rust/kb-worker/functions/write.md +172 -0
  82. package/docs/modules/rust/kb-worker/module.md +171 -0
  83. package/docs/modules/rust/kb-worker/types/cache.md +90 -0
  84. package/docs/modules/rust/kb-worker/types/context.md +26 -0
  85. package/docs/modules/rust/kb-worker/types/module.md +16 -0
  86. package/docs/modules/rust/kb-worker/types/status.md +29 -0
  87. package/docs/modules/rust/kb-worker/types/token.md +50 -0
  88. package/docs/modules/rust/overview.md +495 -0
  89. package/docs/modules/rust/query-parser/functions/extract.md +56 -0
  90. package/docs/modules/rust/query-parser/functions/module.md +16 -0
  91. package/docs/modules/rust/query-parser/functions/parse.md +33 -0
  92. package/docs/modules/rust/query-parser/functions/pipeline.md +103 -0
  93. package/docs/modules/rust/query-parser/functions/rank.md +85 -0
  94. package/docs/modules/rust/query-parser/module.md +136 -0
  95. package/docs/modules/rust/query-parser/types/cache.md +39 -0
  96. package/docs/modules/rust/query-parser/types/keyphrase.md +60 -0
  97. package/docs/modules/rust/query-parser/types/module.md +17 -0
  98. package/docs/modules/rust/query-parser/types/token.md +42 -0
  99. package/docs/modules/rust/shared/content-composer/functions.md +114 -0
  100. package/docs/modules/rust/shared/content-composer/module.md +147 -0
  101. package/docs/modules/rust/shared/content-composer/types.md +93 -0
  102. package/docs/modules/rust/shared/content-parser/functions.md +72 -0
  103. package/docs/modules/rust/shared/content-parser/module.md +99 -0
  104. package/docs/modules/rust/shared/content-parser/types.md +71 -0
  105. package/docs/modules/rust/shared/corpus/module.md +24 -0
  106. package/docs/modules/rust/shared/corpus/types.md +141 -0
  107. package/docs/modules/rust/shared/document/module.md +25 -0
  108. package/docs/modules/rust/shared/document/types.md +154 -0
  109. package/docs/modules/rust/shared/encode/module.md +22 -0
  110. package/docs/modules/rust/shared/encode/traits.md +304 -0
  111. package/docs/modules/rust/shared/error/module.md +28 -0
  112. package/docs/modules/rust/shared/error/types.md +302 -0
  113. package/docs/modules/rust/shared/kbid/module.md +24 -0
  114. package/docs/modules/rust/shared/kbid/types.md +147 -0
  115. package/docs/modules/rust/shared/memory/functions.md +209 -0
  116. package/docs/modules/rust/shared/memory/module.md +24 -0
  117. package/docs/modules/rust/shared/module.md +168 -0
  118. package/docs/modules/rust/shared/query/module.md +27 -0
  119. package/docs/modules/rust/shared/query/types.md +236 -0
  120. package/docs/modules/rust/shared/section/module.md +25 -0
  121. package/docs/modules/rust/shared/section/types.md +294 -0
  122. package/docs/modules/rust/shared/term/module.md +25 -0
  123. package/docs/modules/rust/shared/term/types.md +139 -0
  124. package/docs/modules/typescript/cli.md +129 -0
  125. package/docs/modules/typescript/kbdb-worker.md +135 -0
  126. package/docs/modules/typescript/overview.md +378 -0
  127. package/docs/modules/typescript/shared/cli/constants.md +23 -0
  128. package/docs/modules/typescript/shared/cli/functions.md +630 -0
  129. package/docs/modules/typescript/shared/cli/module.md +125 -0
  130. package/docs/modules/typescript/shared/cli/typings.md +172 -0
  131. package/docs/modules/typescript/shared/hash/functions.md +20 -0
  132. package/docs/modules/typescript/shared/hash/module.md +21 -0
  133. package/docs/modules/typescript/shared/mcp/classes.md +179 -0
  134. package/docs/modules/typescript/shared/mcp/functions.md +386 -0
  135. package/docs/modules/typescript/shared/mcp/module.md +160 -0
  136. package/docs/modules/typescript/shared/mcp/typings.md +522 -0
  137. package/docs/modules/typescript/shared/module.md +94 -0
  138. package/docs/modules/typescript/shared/platform/functions.md +42 -0
  139. package/docs/modules/typescript/shared/platform/module.md +25 -0
  140. package/docs/modules/typescript/shared/runtime/functions.md +26 -0
  141. package/docs/modules/typescript/shared/runtime/module.md +27 -0
  142. package/docs/modules/typescript/shared/runtime/typings.md +13 -0
  143. package/docs/modules/typescript/shared/version/module.md +27 -0
  144. package/docs/modules/typescript/shared/wasm-codec/functions.md +391 -0
  145. package/docs/modules/typescript/shared/wasm-codec/module.md +98 -0
  146. package/docs/modules/typescript/shared/worker-client/classes.md +264 -0
  147. package/docs/modules/typescript/shared/worker-client/functions.md +175 -0
  148. package/docs/modules/typescript/shared/worker-client/module.md +84 -0
  149. package/docs/modules/typescript/shared/worker-client/typings.md +508 -0
  150. package/docs/modules/typescript/shared/worker-daemon/classes.md +239 -0
  151. package/docs/modules/typescript/shared/worker-daemon/constants.md +37 -0
  152. package/docs/modules/typescript/shared/worker-daemon/functions.md +221 -0
  153. package/docs/modules/typescript/shared/worker-daemon/module.md +112 -0
  154. package/docs/modules/typescript/shared/worker-daemon/typings.md +126 -0
  155. package/docs/overview.md +188 -0
  156. package/docs/release-notes/0.1.0.md +189 -0
  157. package/docs/release-notes/0.1.1.md +46 -0
  158. package/docs/release-notes/0.1.2.md +38 -0
  159. package/docs/release-notes/0.1.3.md +42 -0
  160. package/docs/release-notes/0.2.0.md +147 -0
  161. package/docs/release-notes/README.md +9 -0
  162. package/package.json +8 -2
  163. package/src/shared/cli/functions/dispatch-command.function.ts +3 -3
  164. package/src/shared/cli/functions/format-output.function.ts +41 -34
  165. package/src/shared/cli/functions/parse-args.function.ts +7 -0
  166. package/src/shared/cli/functions/run-search.function.ts +53 -27
  167. package/src/shared/cli/index.ts +4 -1
  168. package/src/shared/cli/typings/cli-options.interface.ts +2 -0
  169. package/src/shared/cli/typings/search-display.model.ts +26 -7
  170. package/src/shared/mcp/functions/create-tool-definitions.function.ts +64 -4
  171. package/src/shared/mcp/functions/handle-recall.function.ts +66 -0
  172. package/src/shared/mcp/functions/handle-tool-call.function.ts +11 -1
  173. package/src/shared/mcp/typings/mcp-client.interface.ts +33 -15
  174. package/src/shared/version/constants/version.constant.ts +1 -1
  175. package/src/shared/wasm-codec/functions/decode-recall-result.function.ts +267 -0
  176. package/src/shared/wasm-codec/functions/decode-scored-results.function.ts +81 -27
  177. package/src/shared/wasm-codec/functions/encode-recall-params.function.ts +68 -0
  178. package/src/shared/wasm-codec/functions/encode-search-params.function.ts +4 -1
  179. package/src/shared/wasm-codec/index.ts +11 -3
  180. package/src/shared/worker-client/classes/worker-client.class.ts +24 -4
  181. package/src/shared/worker-client/index.ts +11 -1
  182. package/src/shared/worker-client/typings/recall-result.model.ts +98 -0
  183. package/src/shared/worker-client/typings/search-params.model.ts +2 -0
  184. package/src/shared/worker-client/typings/search-result.model.ts +24 -7
  185. package/src/shared/worker-daemon/classes/worker-daemon.class.ts +25 -4
  186. package/src/wasm/fs-database/kbdb_fs_database.d.ts +18 -0
  187. package/src/wasm/fs-database/kbdb_fs_database.js +30 -0
  188. package/src/wasm/fs-database/kbdb_fs_database_bg.wasm +0 -0
  189. package/src/wasm/fs-database/kbdb_fs_database_bg.wasm.d.ts +2 -0
  190. package/src/wasm/kb-worker/kbdb_worker.d.ts +38 -0
  191. package/src/wasm/kb-worker/kbdb_worker.js +56 -0
  192. package/src/wasm/kb-worker/kbdb_worker_bg.wasm +0 -0
  193. package/src/wasm/kb-worker/kbdb_worker_bg.wasm.d.ts +3 -0
@@ -0,0 +1,1467 @@
1
+ # MCP -- Model Context Protocol Server
2
+
3
+ *An MCP server mode that exposes the knowledge base
4
+ to AI agents -- search, retrieve, and manage knowledge
5
+ programmatically over the Model Context Protocol.*
6
+
7
+ ## Goal
8
+
9
+ When invoked as `kbdb mcp`, the executable starts as a
10
+ long-lived MCP server. It communicates with the AI
11
+ agent host over **stdio** using **JSON-RPC 2.0** and
12
+ delegates all knowledge base operations to the worker
13
+ daemon via the worker client module (see
14
+ [Worker Client](worker-client.md)).
15
+
16
+ The MCP server exposes the knowledge base's search,
17
+ retrieval, and content management capabilities as MCP
18
+ tools and resources. AI agents -- Claude, LangChain
19
+ agents, custom harnesses, or any MCP-compatible
20
+ client -- interact with the knowledge base through
21
+ these primitives.
22
+
23
+ The MCP server has no knowledge of which AI agent is
24
+ connected. It serves any MCP-compatible client
25
+ identically.
26
+
27
+ ## Invocation
28
+
29
+ ```
30
+ kbdb mcp [--db <path>]
31
+ ```
32
+
33
+ The `--db` flag specifies the absolute path to the
34
+ `.kbdb` database directory. If omitted, the server
35
+ reads the `KBDB_DIR` environment variable. One of the
36
+ two must be provided -- the MCP server does not fall
37
+ back to the current working directory.
38
+
39
+ Resolution order:
40
+
41
+ 1. `--db <path>` command-line flag.
42
+ 2. `KBDB_DIR` environment variable.
43
+ 3. Error: no database directory specified.
44
+
45
+ The MCP server does not fall back to the current
46
+ working directory because the server's working
47
+ directory is determined by the host application, not
48
+ the user.
49
+
50
+ See [CLI -- Run Modes](cli.md#run-modes) for how
51
+ the `kbdb` executable dispatches to MCP mode.
52
+
53
+ ## Installation and Wiring
54
+
55
+ Installation is the same as the CLI:
56
+
57
+ - **Node.js**: `npm install -g @dikolab/kbdb`
58
+ - **Deno**: `deno install` or `deno add @dikolab/kbdb`
59
+ (via [jsr.io](https://jsr.io))
60
+
61
+ To wire the MCP server to an AI agent, add a server
62
+ entry to the agent host's MCP configuration.
63
+
64
+ ### Claude Desktop
65
+
66
+ Add to `claude_desktop_config.json`:
67
+
68
+ ```json
69
+ {
70
+ "mcpServers": {
71
+ "kbdb": {
72
+ "command": "npx",
73
+ "args": [
74
+ "@dikolab/kbdb", "mcp",
75
+ "--db", "/path/to/.kbdb"
76
+ ]
77
+ }
78
+ }
79
+ }
80
+ ```
81
+
82
+ ### Claude Code
83
+
84
+ Add to `.claude/settings.json` or project settings:
85
+
86
+ ```json
87
+ {
88
+ "mcpServers": {
89
+ "kbdb": {
90
+ "command": "npx",
91
+ "args": [
92
+ "@dikolab/kbdb", "mcp",
93
+ "--db", "/path/to/.kbdb"
94
+ ]
95
+ }
96
+ }
97
+ }
98
+ ```
99
+
100
+ ### Deno
101
+
102
+ ```json
103
+ {
104
+ "mcpServers": {
105
+ "kbdb": {
106
+ "command": "deno",
107
+ "args": [
108
+ "run", "--allow-all",
109
+ "jsr:@dikolab/kbdb", "mcp",
110
+ "--db", "/path/to/.kbdb"
111
+ ]
112
+ }
113
+ }
114
+ }
115
+ ```
116
+
117
+ ### Environment Variable
118
+
119
+ The `--db` flag can be replaced by `KBDB_DIR`:
120
+
121
+ ```json
122
+ {
123
+ "mcpServers": {
124
+ "kbdb": {
125
+ "command": "npx",
126
+ "args": ["@dikolab/kbdb", "mcp"],
127
+ "env": {
128
+ "KBDB_DIR": "/path/to/.kbdb"
129
+ }
130
+ }
131
+ }
132
+ }
133
+ ```
134
+
135
+ ### Multiple Knowledge Bases
136
+
137
+ Register multiple server instances pointing to
138
+ different databases:
139
+
140
+ ```json
141
+ {
142
+ "mcpServers": {
143
+ "kbdb-docs": {
144
+ "command": "npx",
145
+ "args": [
146
+ "@dikolab/kbdb", "mcp",
147
+ "--db", "/home/user/docs/.kbdb"
148
+ ]
149
+ },
150
+ "kbdb-project": {
151
+ "command": "npx",
152
+ "args": [
153
+ "@dikolab/kbdb", "mcp",
154
+ "--db", "/home/user/project/.kbdb"
155
+ ]
156
+ }
157
+ }
158
+ }
159
+ ```
160
+
161
+ Each registration spawns a separate `kbdb mcp`
162
+ process with its own worker client connection. The
163
+ worker daemon disambiguates by context ID (SHA-256
164
+ of the database path), so multiple MCP instances
165
+ hitting different databases work without conflict.
166
+
167
+ ## Transport
168
+
169
+ The MCP server uses **stdio** transport:
170
+
171
+ - Reads JSON-RPC 2.0 requests from **stdin**.
172
+ - Writes JSON-RPC 2.0 responses to **stdout**.
173
+ - Diagnostic messages go to **stderr**.
174
+
175
+ The AI agent host (Claude Desktop, Claude Code, or
176
+ any MCP-compatible client) spawns `kbdb mcp` as a
177
+ child process and communicates over its stdin/stdout
178
+ streams.
179
+
180
+ ## Protocol
181
+
182
+ The MCP server implements the **Model Context Protocol
183
+ version 2025-11-25** over **JSON-RPC 2.0**. This is
184
+ the same wire format the worker daemon uses for IPC
185
+ (see [Worker Daemon](worker-daemon.md)), but with
186
+ MCP-defined method names and semantics.
187
+
188
+ Every MCP-compatible AI agent host -- Claude Desktop,
189
+ Claude Code, Cursor, Windsurf, or any custom harness
190
+ -- uses this same protocol. The server has no knowledge
191
+ of which host is connected.
192
+
193
+ ### Lifecycle
194
+
195
+ Three methods form the mandatory startup handshake.
196
+ Nothing else may be called before `initialize`
197
+ completes.
198
+
199
+ #### 1. `initialize` (request)
200
+
201
+ The host sends its identity and supported capabilities.
202
+ The server responds with its own identity, the
203
+ protocol version it speaks, and which capability
204
+ groups it supports.
205
+
206
+ **Host request:**
207
+
208
+ ```json
209
+ {
210
+ "jsonrpc": "2.0",
211
+ "id": 1,
212
+ "method": "initialize",
213
+ "params": {
214
+ "protocolVersion": "2025-11-25",
215
+ "capabilities": {},
216
+ "clientInfo": {
217
+ "name": "ExampleHost",
218
+ "version": "1.0.0"
219
+ }
220
+ }
221
+ }
222
+ ```
223
+
224
+ **Server response:**
225
+
226
+ ```json
227
+ {
228
+ "jsonrpc": "2.0",
229
+ "id": 1,
230
+ "result": {
231
+ "protocolVersion": "2025-11-25",
232
+ "serverInfo": {
233
+ "name": "kbdb",
234
+ "version": "0.1.0"
235
+ },
236
+ "capabilities": {
237
+ "tools": {},
238
+ "resources": {}
239
+ }
240
+ }
241
+ }
242
+ ```
243
+
244
+ **Version negotiation:** the host sends the latest
245
+ version it supports. If the server supports it, it
246
+ responds with the same version. Otherwise, the server
247
+ responds with another version it supports. If the
248
+ host does not support the server's version, it should
249
+ disconnect.
250
+
251
+ #### 2. `notifications/initialized` (notification)
252
+
253
+ The host sends this notification (no `id`, no
254
+ response) to confirm that the handshake is complete.
255
+ The server flips its internal ready state and begins
256
+ accepting tool and resource requests.
257
+
258
+ ```json
259
+ {
260
+ "jsonrpc": "2.0",
261
+ "method": "notifications/initialized"
262
+ }
263
+ ```
264
+
265
+ #### 3. `ping` (request)
266
+
267
+ Either party can send a `ping` to check liveness.
268
+ The receiver must respond promptly with an empty
269
+ result.
270
+
271
+ ```json
272
+ {
273
+ "jsonrpc": "2.0",
274
+ "id": 99,
275
+ "method": "ping"
276
+ }
277
+ ```
278
+
279
+ Response:
280
+
281
+ ```json
282
+ {
283
+ "jsonrpc": "2.0",
284
+ "id": 99,
285
+ "result": {}
286
+ }
287
+ ```
288
+
289
+ ### Capability Negotiation
290
+
291
+ The `capabilities` object in the `initialize` response
292
+ tells the host which method groups the server supports.
293
+ The host must not call methods for capabilities the
294
+ server did not advertise.
295
+
296
+ kbdb advertises:
297
+
298
+ ```json
299
+ {
300
+ "tools": {},
301
+ "resources": {},
302
+ "prompts": {},
303
+ "logging": {},
304
+ "completions": {}
305
+ }
306
+ ```
307
+
308
+ This means the host can call `tools/list`,
309
+ `tools/call`, `resources/list`, `resources/read`,
310
+ `resources/templates/list`, `prompts/list`,
311
+ `prompts/get`, `logging/setLevel`, and
312
+ `completion/complete`.
313
+
314
+ Optional capability flags:
315
+
316
+ | Flag | Meaning |
317
+ |------|---------|
318
+ | `tools.listChanged` | Server emits `notifications/tools/list_changed` |
319
+ | `resources.listChanged` | Server emits `notifications/resources/list_changed` |
320
+ | `resources.subscribe` | Client can subscribe to resource changes |
321
+ | `prompts` | Server supports `prompts/list` and `prompts/get` |
322
+ | `logging` | Server supports `logging/setLevel` and emits log notifications |
323
+ | `completions` | Server supports `completion/complete` |
324
+
325
+ ## MCP Tools
326
+
327
+ Tools are callable actions that the AI agent invokes.
328
+ Each tool sends a JSON-RPC 2.0 request to the worker
329
+ daemon via the worker client.
330
+
331
+ ### search
332
+
333
+ Search the knowledge base. Returns ranked results
334
+ with headings and snippets for relevance evaluation.
335
+ Use `recall` to get full content of specific results.
336
+
337
+ **Parameters:**
338
+
339
+ | Name | Type | Required | Description |
340
+ |-----------|---------|----------|----------------------------|
341
+ | `query` | string | yes | Search query text |
342
+ | `mode` | string | no | `"sections"` (default), `"documents"`, or `"stats"` |
343
+ | `limit` | number | no | Max results (default: 20) |
344
+ | `offset` | number | no | Zero-based result offset (default: 0) |
345
+ | `content` | boolean | no | When `true`, include full section text in each result (default: `false`) |
346
+
347
+ **Returns:** Paged JSON envelope containing ranked
348
+ results. Each result includes contextual metadata
349
+ the AI agent needs to judge relevance without
350
+ additional calls:
351
+
352
+ ```json
353
+ {
354
+ "items": [
355
+ {
356
+ "kbid": "a1b2c3d4e5f6g7h8j9k0l1m2n3",
357
+ "heading": "Architecture Overview",
358
+ "type": "text/markdown",
359
+ "docids": ["doc-5678"],
360
+ "snippet": "The system is organized...",
361
+ "matched_terms": ["architecture", "system"]
362
+ }
363
+ ],
364
+ "total": 42,
365
+ "offset": 0,
366
+ "limit": 20,
367
+ "has_more": true
368
+ }
369
+ ```
370
+
371
+ - `heading` -- the section's title text, or `null`
372
+ when the section has no title.
373
+ - `type` -- section MIME type (e.g.
374
+ `"text/markdown"`, `"text/typescript"`).
375
+ - `docids` -- document identifiers this section
376
+ belongs to (may be empty for standalone sections).
377
+ - `snippet` -- KWIC (keyword-in-context) excerpt,
378
+ ~150 characters centered on the highest-scoring
379
+ matched term. Empty string for image sections.
380
+ - `matched_terms` -- query terms that matched, as a
381
+ flat `string[]`. No frequency counts.
382
+
383
+ When `content` is `true`, each item also includes
384
+ a `content` field with the full section text.
385
+
386
+ Results are ordered by relevance (highest first).
387
+ The ordering itself carries the ranking signal --
388
+ no numeric score is exposed.
389
+
390
+ Result is serialised with 2-space indentation.
391
+
392
+ Maps to `client.search()`.
393
+
394
+ ### learn
395
+
396
+ Import content into the knowledge base. The daemon
397
+ decomposes the content into sections, extracts
398
+ keywords, builds indexes, and assigns ranking
399
+ weights.
400
+
401
+ **Parameters:**
402
+
403
+ | Name | Type | Required | Description |
404
+ |---------------|--------|----------|------------------|
405
+ | `content` | string | yes | Text content or base64-encoded image data |
406
+ | `type` | string | no | `"text/markdown"` (default), `text/*` MIME type, `"application/json"`, or `image/*` MIME type |
407
+ | `title` | string | no* | Section title. ***Required** for `image/*` types.* Optional for text and code types. |
408
+ | `description` | string | no | Optional section description |
409
+ | `docid` | string | no | Group under this document ID |
410
+
411
+ **Content type rules:**
412
+
413
+ 1. **`type` is `text/*` or omitted** (default
414
+ `text/markdown`) -- `title` and `description` are
415
+ optional. `content` is the raw text.
416
+ 2. **`type` is `image/*`** -- **`title` is required.**
417
+ `content` must be base64-encoded binary image data.
418
+ Omitting `title` returns a tool error
419
+ (`isError: true`). `description` is optional.
420
+ 3. **`description`** -- always optional for all types.
421
+
422
+ Text and code content is preprocessed (BOM removal,
423
+ line ending normalization, Unicode NFC, whitespace
424
+ trimming) before the kbid hash is computed. Image
425
+ content is stored verbatim. See
426
+ [Database -- Content Preprocessing](database.md)
427
+ for the full pipeline.
428
+
429
+ For code sections (`text/*` or `application/json`),
430
+ `content` is the raw source text. For image sections
431
+ (`image/*`), `content` is the base64-encoded binary
432
+ image data. See
433
+ [Database -- Section Types](database.md).
434
+
435
+ **Returns:** JSON (compact, no indentation) with the
436
+ new section's `AddSectionResult` from the daemon.
437
+ Fields include the assigned kbid, content type, title
438
+ (if provided), description (if provided), indexed
439
+ term count, elapsed time, and an `attached` flag.
440
+ Text and code sections return a positive
441
+ `indexed_terms_count`. Image sections return
442
+ `indexed_terms_count: 0`.
443
+
444
+ If the content already exists in the database (same
445
+ kb-id) and `docid` is provided, the section is not
446
+ duplicated. Instead, the docid is added to the
447
+ existing section's `docids` list. The result reports
448
+ `attached: true` and `indexed_terms_count: 0` (no
449
+ re-indexing). If no `docid` is provided and the
450
+ content already exists, the section is skipped. If
451
+ the docid is already in the section's `docids` array,
452
+ the operation is idempotent: `attached: false`.
453
+
454
+ Maps to `client.addSection()`. Internally maps the
455
+ `type` tool parameter to the `sectionType` field
456
+ expected by `McpWorkerClient.addSection()`.
457
+
458
+ ### unlearn
459
+
460
+ Remove content from the knowledge base by kb-id.
461
+ Cascades deletion to associated index entries and
462
+ ranking data.
463
+
464
+ **Parameters:**
465
+
466
+ | Name | Type | Required | Description |
467
+ |---------|--------|----------|-------------------|
468
+ | `kbid` | string | yes | KB ID of section to remove |
469
+
470
+ **Returns:** Compact JSON `{ "removed": bool,
471
+ "elapsed_ms": number }` where `removed` is `true`
472
+ when the section was found and removed.
473
+
474
+ Maps to `client.removeSection()`.
475
+
476
+ ### retrieve
477
+
478
+ Low-level fetch of a section or document by
479
+ identifier. For AI agent workflows, prefer `recall`
480
+ which includes metadata, context, and
481
+ back-references.
482
+
483
+ **Parameters:**
484
+
485
+ | Name | Type | Required | Description |
486
+ |---------|--------|----------|------------------|
487
+ | `kbid` | string | no | KB ID of section |
488
+ | `docid` | string | no | Document ID |
489
+
490
+ Neither field is marked required in the schema, but
491
+ at least one must be provided. Omitting both returns
492
+ `isError: true` with the message `Provide kbid or
493
+ docid`.
494
+
495
+ When `kbid` is provided, maps to
496
+ `client.readSections([kbid])` and returns a JSON
497
+ array of section objects: `[{ kbid, sectionType,
498
+ content, size }]`. When `docid` is provided, maps to
499
+ `client.retrieveDocument(docid)` and returns the raw
500
+ document record from the daemon.
501
+
502
+ Maps to `client.readSections()` or
503
+ `client.retrieveDocument()`.
504
+
505
+ ### recall
506
+
507
+ Retrieve full content and context for one or more
508
+ sections by identifier. Use after `search` to read
509
+ relevant results. Returns section text, metadata,
510
+ references, and back-references.
511
+
512
+ **Parameters:**
513
+
514
+ | Name | Type | Required | Description |
515
+ |---------|----------|----------|--------------------------|
516
+ | `kbid` | string | no* | Single section identifier |
517
+ | `kbids` | string[] | no* | Batch section identifiers |
518
+ | `depth` | number | no | Expansion depth (0--3, default: 0) |
519
+
520
+ *At least one of `kbid` or `kbids` is required.
521
+ Omitting both returns `isError: true`. When both
522
+ are provided, `kbids` takes precedence and `kbid`
523
+ is appended to the list.
524
+
525
+ **Expansion levels:**
526
+
527
+ | Depth | Returns |
528
+ |-------|---------------------------------------|
529
+ | 0 | Full section content with heading, |
530
+ | | type, and docids. |
531
+ | 1 | Depth-0 content, plus parent document |
532
+ | | manifests (title, all section kbids |
533
+ | | with headings and types) for each |
534
+ | | docid, plus back-references (sections |
535
+ | | that reference this section, from the |
536
+ | | reference graph index, each with |
537
+ | | marker_type and context_snippet). |
538
+ | 2 | Depth-1 content, plus full text of |
539
+ | | sibling sections (other sections in |
540
+ | | the same documents), plus forward |
541
+ | | references from the section's own |
542
+ | | content markers. |
543
+ | 3 | Depth-2 content, plus full text of |
544
+ | | referenced sections (one level deep), |
545
+ | | plus their back-references. |
546
+
547
+ Depth values above 3 are clamped to 3.
548
+
549
+ **Single result shape (depth 0):**
550
+
551
+ ```json
552
+ {
553
+ "kbid": "a1b2c3d4e5f6g7h8j9k0l1m2n3",
554
+ "heading": "Architecture Overview",
555
+ "type": "text/markdown",
556
+ "content": "Full section text...",
557
+ "docids": ["doc-5678"]
558
+ }
559
+ ```
560
+
561
+ **Single result shape (depth 1+):**
562
+
563
+ ```json
564
+ {
565
+ "kbid": "a1b2c3d4e5f6g7h8j9k0l1m2n3",
566
+ "heading": "Architecture Overview",
567
+ "type": "text/markdown",
568
+ "content": "Full section text...",
569
+ "docids": ["doc-5678"],
570
+ "documents": [
571
+ {
572
+ "docid": "doc-5678",
573
+ "title": "System Architecture",
574
+ "sections": [
575
+ {
576
+ "kbid": "...",
577
+ "heading": "...",
578
+ "type": "..."
579
+ }
580
+ ]
581
+ }
582
+ ],
583
+ "back_references": [
584
+ {
585
+ "kbid": "ref-section-kbid",
586
+ "heading": "Related Section",
587
+ "type": "text/markdown",
588
+ "marker_type": "link",
589
+ "context_snippet": "For details, see ...",
590
+ "direction": "back"
591
+ }
592
+ ],
593
+ "siblings": [ ... ],
594
+ "references": [ ... ]
595
+ }
596
+ ```
597
+
598
+ Fields beyond `content` and `docids` are present
599
+ only at the corresponding depth level. At depth 0,
600
+ `documents`, `back_references`, `siblings`, and
601
+ `references` are absent. At depth 1, `siblings`
602
+ and `references` are absent. And so on.
603
+
604
+ When batch `kbids` is used, the response is a JSON
605
+ array of result objects (one per kbid). The depth
606
+ parameter applies to all sections in the batch.
607
+
608
+ Maps to `client.recall()`.
609
+
610
+ ### content
611
+
612
+ Compose a rendered Markdown document from one or
613
+ more kbid or docid identifiers.
614
+
615
+ **Parameters:**
616
+
617
+ | Name | Type | Required | Description |
618
+ |-------|----------|----------|-------------------|
619
+ | `ids` | string[] | yes | One or more kbid or docid identifiers (mixed) |
620
+
621
+ **Returns:** Tool result with text content containing
622
+ JSON: `{ "type": "text/markdown", "data": "...",
623
+ "total": <char count> }`. The `total` field is the
624
+ character count of `data` (not byte count).
625
+
626
+ Maps to `client.content()`.
627
+
628
+ See [Content Composer](content-composer.md) for the
629
+ full composition specification.
630
+
631
+ ### status
632
+
633
+ Return database status and cache statistics.
634
+
635
+ **Parameters:** None.
636
+
637
+ **Returns:** JSON with the following fields:
638
+
639
+ | Field | Type | Description |
640
+ |-------|------|-------------|
641
+ | `initialized` | boolean | Whether the daemon has finished loading its WASM modules |
642
+ | `contextPath` | string | Absolute path to the database directory the daemon serves |
643
+ | `cacheStats.contentCount` | number | Number of content entries currently in the in-memory cache |
644
+ | `cacheStats.indexCount` | number | Number of index entries currently in the in-memory cache |
645
+
646
+ Maps to `client.dbStatus()`.
647
+
648
+ ### check
649
+
650
+ Verify the integrity of the knowledge base. Reports
651
+ checksum mismatches, orphan sections and documents,
652
+ broken marker references, type mismatches, and
653
+ circular reference chains.
654
+
655
+ **Parameters:** None.
656
+
657
+ **Returns:** JSON with `ok` boolean, `errors` array
658
+ (each with `type`, `entity`, `detail`),
659
+ `sections_checked`, `documents_checked`,
660
+ `references_checked`, and `elapsed_ms`. When all
661
+ checks pass, `ok` is `true` and `errors` is empty.
662
+
663
+ Error types: `checksum_mismatch`, `orphan_section`,
664
+ `orphan_document`, `broken_reference`,
665
+ `type_mismatch`, `circular_reference`. See
666
+ [Database -- Integrity and
667
+ Maintenance](database.md).
668
+
669
+ Maps to `client.integrityCheck()`.
670
+
671
+ ### gc
672
+
673
+ Remove unreferenced sections from the knowledge
674
+ base. A section is eligible for removal when no
675
+ document manifest references it.
676
+
677
+ **Parameters:** None.
678
+
679
+ **Returns:** JSON with `removed_sections` (count),
680
+ `removed_bytes`, and `elapsed_ms`. When no sections
681
+ are eligible, counts are `0`.
682
+
683
+ Maps to `client.gc()`.
684
+
685
+ ### rebuild
686
+
687
+ Reconstruct all index files from section files and
688
+ document manifests on disk. Text and code sections
689
+ are re-tokenized; image sections are skipped. Use
690
+ this to recover from index corruption.
691
+
692
+ **Parameters:** None.
693
+
694
+ **Returns:** JSON with `sections_reindexed`,
695
+ `terms_indexed`, and `elapsed_ms`.
696
+
697
+ Maps to `client.rebuildIndexes()`.
698
+
699
+ ### skill-learn
700
+
701
+ Create a new skill definition and store it in the
702
+ knowledge base as a section with `sectionType:
703
+ 'skill'`.
704
+
705
+ **Parameters:**
706
+
707
+ | Name | Type | Required | Description |
708
+ |---------------|--------|----------|------------------------------------------|
709
+ | `name` | string | yes | Skill name (kebab-case identifier) |
710
+ | `description` | string | yes | What the skill does |
711
+ | `arguments` | array | no | Prompt argument definitions |
712
+ | `body` | string | yes | Template body with `{{argName}}` placeholders |
713
+
714
+ **Returns:** Compact JSON `AddSectionResult` with the
715
+ assigned `kbid`, `name`, and auto-detected `arguments`
716
+ array extracted from `{{...}}` placeholders in `body`.
717
+
718
+ Maps to `client.addSection()` with
719
+ `sectionType: 'skill'`.
720
+
721
+ ### skill-list
722
+
723
+ List all skill definitions stored in the knowledge
724
+ base.
725
+
726
+ **Parameters:** None.
727
+
728
+ **Returns:** JSON array of skill summary objects:
729
+ `[{ kbid, name, description, argumentCount }]`.
730
+ Result is serialised with 2-space indentation.
731
+
732
+ Maps to `client.listByType('skill')`.
733
+
734
+ ### skill-get
735
+
736
+ Retrieve a single skill definition by name or kb-id.
737
+
738
+ **Parameters:**
739
+
740
+ | Name | Type | Required | Description |
741
+ |--------|--------|----------|-------------------------------------|
742
+ | `name` | string | no* | Skill name to look up |
743
+ | `kbid` | string | no* | Skill kb-id to look up |
744
+
745
+ *At least one of `name` or `kbid` is required.
746
+ Omitting both returns `isError: true`. When both are
747
+ provided, `kbid` takes precedence.
748
+
749
+ **Returns:** Full `SkillDefinition` JSON with `kbid`,
750
+ `name`, `description`, `arguments`, and `body`.
751
+ Result is serialised with 2-space indentation.
752
+
753
+ Maps to `client.readSections([kbid])` (by kbid) or
754
+ `client.listByType('skill')` filtered by name (by
755
+ name).
756
+
757
+ ### skill-delete
758
+
759
+ Remove a skill definition by kb-id. The skill section
760
+ is removed from the database. Agent documents that
761
+ reference this kbid will have a dangling reference.
762
+
763
+ **Parameters:**
764
+
765
+ | Name | Type | Required | Description |
766
+ |--------|--------|----------|-----------------------|
767
+ | `kbid` | string | yes | Skill kb-id to remove |
768
+
769
+ **Returns:** Compact JSON `{ "kbid": "...",
770
+ "removed": true }`.
771
+
772
+ Maps to `client.removeSection()`.
773
+
774
+ ### agent-create
775
+
776
+ Create a new agent document in the knowledge base.
777
+ An agent is a document with `type: 'agent'` that
778
+ holds a persona and an ordered list of skill kbid
779
+ references.
780
+
781
+ **Parameters:**
782
+
783
+ | Name | Type | Required | Description |
784
+ |---------------|----------|----------|--------------------------------------|
785
+ | `name` | string | yes | Agent name (kebab-case identifier) |
786
+ | `description` | string | yes | What the agent does |
787
+ | `persona` | string | yes | System prompt text for the agent |
788
+ | `skills` | string[] | yes | Ordered skill kbid list |
789
+
790
+ **Returns:** Compact JSON `{ "docid": "agent-...",
791
+ "name": "...", "skills": [...] }`.
792
+
793
+ Maps to `client.groupSections()` with
794
+ `type: 'agent'` and `[agent]` metadata.
795
+
796
+ ### agent-list
797
+
798
+ List all agent documents in the knowledge base.
799
+
800
+ **Parameters:** None.
801
+
802
+ **Returns:** JSON array of agent summary objects:
803
+ `[{ docid, name, description, skillCount }]`.
804
+ Result is serialised with 2-space indentation.
805
+
806
+ Maps to `client.listDocumentsByType('agent')`.
807
+
808
+ ### agent-get
809
+
810
+ Retrieve a single agent document with its resolved
811
+ skill definitions.
812
+
813
+ **Parameters:**
814
+
815
+ | Name | Type | Required | Description |
816
+ |---------|--------|----------|--------------------------|
817
+ | `docid` | string | yes | Agent document ID |
818
+
819
+ **Returns:** Full `AgentDefinition` JSON with `docid`,
820
+ `name`, `description`, `persona`, and `skills` array.
821
+ Each skill entry includes `kbid`, `name`, and
822
+ `position`. If a referenced skill has been deleted,
823
+ its `name` is `null`. Result is serialised with
824
+ 2-space indentation.
825
+
826
+ Maps to `client.retrieveDocument(docid)` followed by
827
+ `client.readSections(kbids)` for skill resolution.
828
+
829
+ ### agent-delete
830
+
831
+ Remove an agent document. Only the document manifest
832
+ is deleted; the referenced skill sections remain.
833
+
834
+ **Parameters:**
835
+
836
+ | Name | Type | Required | Description |
837
+ |---------|--------|----------|--------------------------|
838
+ | `docid` | string | yes | Agent document ID |
839
+
840
+ **Returns:** Compact JSON `{ "docid": "...",
841
+ "removed": true }`.
842
+
843
+ Maps to `client.removeGrouping()`.
844
+
845
+ ## MCP Resources
846
+
847
+ Resources are data items the AI agent can read by
848
+ URI. They provide direct access to knowledge base
849
+ contents without going through search.
850
+
851
+ The MCP `2025-11-25` spec distinguishes two listing
852
+ methods:
853
+
854
+ ### `resources/list` -- Static Resources
855
+
856
+ Returns resources with concrete URIs. kbdb has no
857
+ static resources, so this returns an empty list:
858
+
859
+ ```json
860
+ { "resources": [] }
861
+ ```
862
+
863
+ ### `resources/templates/list` -- URI Templates
864
+
865
+ Returns parameterized URI templates (RFC 6570) that
866
+ the client can expand with arguments. kbdb exposes
867
+ two templates:
868
+
869
+ | URI Template | MIME Type | Description |
870
+ |-------------|----------|-------------|
871
+ | `kbdb://section/{kbid}` | `text/plain` | Section by kb-id |
872
+ | `kbdb://document/{docid}` | `application/json` | Document + sections |
873
+
874
+ ### `resources/read` -- Fetch Resource
875
+
876
+ **URI:** `kbdb://section/{kbid}`
877
+
878
+ Returns the content of a single section identified
879
+ by kb-id. For text sections, returns the raw text
880
+ content. For code sections (`text/*` or
881
+ `application/json`), returns the raw source text
882
+ with the MIME type. For image sections (`image/*`
883
+ type), returns the base64-encoded content with the
884
+ MIME type.
885
+
886
+ **URI:** `kbdb://document/{docid}`
887
+
888
+ Returns a document and all its sections. Sections
889
+ are ordered by position within the document.
890
+
891
+ ## MCP Prompts
892
+
893
+ Prompts are reusable templates that the AI agent host
894
+ can discover and render. kbdb exposes two categories
895
+ of prompts: **skills** (stored as sections with
896
+ `sectionType: 'skill'`) and **agents** (stored as
897
+ documents with `type: 'agent'`, identified by an
898
+ `agent:` name prefix).
899
+
900
+ ### prompts/list
901
+
902
+ Returns all available prompts. Skills appear as
903
+ `McpPrompt` objects; agents appear with the `agent:`
904
+ name prefix and no arguments.
905
+
906
+ **Request:**
907
+
908
+ ```json
909
+ {
910
+ "jsonrpc": "2.0",
911
+ "id": 1,
912
+ "method": "prompts/list"
913
+ }
914
+ ```
915
+
916
+ **Response:**
917
+
918
+ ```json
919
+ {
920
+ "jsonrpc": "2.0",
921
+ "id": 1,
922
+ "result": {
923
+ "prompts": [
924
+ {
925
+ "name": "summarize-document",
926
+ "description": "Summarize a document into
927
+ key points with configurable depth",
928
+ "arguments": [
929
+ {
930
+ "name": "docid",
931
+ "description": "Document identifier",
932
+ "required": true
933
+ },
934
+ {
935
+ "name": "max_points",
936
+ "description": "Max bullet points",
937
+ "required": false
938
+ }
939
+ ]
940
+ },
941
+ {
942
+ "name": "agent:code-reviewer",
943
+ "description": "Reviews code for bugs,
944
+ style, and best practices",
945
+ "arguments": []
946
+ }
947
+ ]
948
+ }
949
+ }
950
+ ```
951
+
952
+ Maps to `client.listByType('skill')` and
953
+ `client.listDocumentsByType('agent')`.
954
+
955
+ ### prompts/get
956
+
957
+ Retrieves a single prompt rendered with the given
958
+ argument values.
959
+
960
+ **Request params:**
961
+
962
+ | Parameter | Type | Required | Description |
963
+ |-------------|--------|----------|--------------------------|
964
+ | `name` | string | yes | Prompt name |
965
+ | `arguments` | object | no | Key-value argument map |
966
+
967
+ **Response for a skill prompt** (single user message
968
+ with the rendered template body):
969
+
970
+ ```json
971
+ {
972
+ "jsonrpc": "2.0",
973
+ "id": 2,
974
+ "result": {
975
+ "messages": [
976
+ {
977
+ "role": "user",
978
+ "content": {
979
+ "type": "text",
980
+ "text": "Summarize the document
981
+ identified by DOC-001.\nExtract
982
+ at most 5 key points.\nReturn as
983
+ a bulleted markdown list."
984
+ }
985
+ }
986
+ ]
987
+ }
988
+ }
989
+ ```
990
+
991
+ **Response for an agent prompt** (assistant message
992
+ with persona, then user message with skill listing):
993
+
994
+ ```json
995
+ {
996
+ "jsonrpc": "2.0",
997
+ "id": 3,
998
+ "result": {
999
+ "messages": [
1000
+ {
1001
+ "role": "assistant",
1002
+ "content": {
1003
+ "type": "text",
1004
+ "text": "You are an expert code
1005
+ reviewer. You focus on
1006
+ correctness, readability, and
1007
+ maintainability."
1008
+ }
1009
+ },
1010
+ {
1011
+ "role": "user",
1012
+ "content": {
1013
+ "type": "text",
1014
+ "text": "Available skills:\n- summarize-document: Summarize a document...\n- review-diff: Review a code diff..."
1015
+ }
1016
+ }
1017
+ ]
1018
+ }
1019
+ }
1020
+ ```
1021
+
1022
+ Maps to `client.readSections([kbid])` (skill) or
1023
+ `client.retrieveDocument(docid)` with
1024
+ `client.readSections(skillKbids)` (agent).
1025
+
1026
+ ### Prompt Discovery Flow
1027
+
1028
+ How an AI agent discovers and invokes a skill using
1029
+ the prompt protocol:
1030
+
1031
+ 1. Agent calls `prompts/list` to enumerate all
1032
+ available prompts (skills and agents).
1033
+ 2. Agent selects a prompt by name based on its
1034
+ description and argument list.
1035
+ 3. Agent calls `prompts/get` with the prompt name
1036
+ and a key-value map of argument values.
1037
+ 4. Agent receives one or more rendered
1038
+ `McpPromptMessage` objects with the substituted
1039
+ template text.
1040
+ 5. Agent uses the rendered message(s) in its
1041
+ workflow (as a system prompt, user turn, or
1042
+ context injection).
1043
+
1044
+ ## Tool Annotations
1045
+
1046
+ Tool annotations provide hints to the MCP host about
1047
+ the nature of each tool. The `McpToolAnnotations`
1048
+ type adds metadata to the tool definition:
1049
+
1050
+ ```typescript
1051
+ interface McpToolAnnotations {
1052
+ readonly title?: string;
1053
+ readonly readOnlyHint?: boolean;
1054
+ readonly destructiveHint?: boolean;
1055
+ readonly idempotentHint?: boolean;
1056
+ readonly openWorldHint?: boolean;
1057
+ }
1058
+ ```
1059
+
1060
+ Annotations for all 18 kbdb tools:
1061
+
1062
+ | Tool | title | readOnly | destructive | idempotent | openWorld |
1063
+ |----------------|-------------------|----------|-------------|------------|-----------|
1064
+ | `search` | Search KB | true | false | true | false |
1065
+ | `learn` | Import Content | false | false | true | false |
1066
+ | `unlearn` | Remove Section | false | true | true | false |
1067
+ | `retrieve` | Fetch Content | true | false | true | false |
1068
+ | `recall` | Recall Context | true | false | true | false |
1069
+ | `content` | Compose Content | true | false | true | false |
1070
+ | `status` | DB Status | true | false | true | false |
1071
+ | `check` | Integrity Check | true | false | true | false |
1072
+ | `gc` | Garbage Collect | false | true | false | false |
1073
+ | `rebuild` | Rebuild Indexes | false | false | false | false |
1074
+ | `skill-learn` | Create Skill | false | false | true | false |
1075
+ | `skill-list` | List Skills | true | false | true | false |
1076
+ | `skill-get` | Get Skill | true | false | true | false |
1077
+ | `skill-delete` | Delete Skill | false | true | true | false |
1078
+ | `agent-create` | Create Agent | false | false | true | false |
1079
+ | `agent-list` | List Agents | true | false | true | false |
1080
+ | `agent-get` | Get Agent | true | false | true | false |
1081
+ | `agent-delete` | Delete Agent | false | true | true | false |
1082
+
1083
+ ## Completions
1084
+
1085
+ The `completion/complete` handler provides
1086
+ autocomplete suggestions for prompt names and
1087
+ resource URIs. Clients use this to offer tab
1088
+ completion in UI surfaces.
1089
+
1090
+ **Request params:**
1091
+
1092
+ | Parameter | Type | Required | Description |
1093
+ |------------|--------|----------|-------------------------------------|
1094
+ | `ref` | object | yes | Reference describing what to complete |
1095
+ | `argument` | object | no | Argument being completed |
1096
+
1097
+ **Ref types:**
1098
+
1099
+ - `ref/prompt` with `name`: autocomplete skill and
1100
+ agent prompt names that match the given prefix.
1101
+ Returns all prompts whose name starts with the
1102
+ prefix string.
1103
+ - `ref/resource` with `uri`: autocomplete kbid or
1104
+ docid in URI patterns (`kbdb://section/...` or
1105
+ `kbdb://document/...`) that match the given prefix.
1106
+
1107
+ **Response (`McpCompletionResult`):**
1108
+
1109
+ ```json
1110
+ {
1111
+ "completion": {
1112
+ "values": [
1113
+ "summarize-document",
1114
+ "search-and-report"
1115
+ ],
1116
+ "hasMore": false,
1117
+ "total": 2
1118
+ }
1119
+ }
1120
+ ```
1121
+
1122
+ ## Sampling
1123
+
1124
+ The sampling capability allows the kbdb MCP server
1125
+ to request the AI agent host to generate text using
1126
+ its own language model. The server sends a
1127
+ `sampling/createMessage` request; the host runs the
1128
+ LLM and returns the generated text.
1129
+
1130
+ **Request params:**
1131
+
1132
+ | Parameter | Type | Required | Description |
1133
+ |-------------|--------|----------|----------------------------|
1134
+ | `messages` | array | yes | Message array to send |
1135
+ | `maxTokens` | number | yes | Maximum response tokens |
1136
+
1137
+ Before using sampling, the server checks the host's
1138
+ capabilities from the `initialize` response to
1139
+ confirm `sampling` is supported.
1140
+
1141
+ **Use cases:**
1142
+
1143
+ 1. Auto-generate a skill body from a name and
1144
+ description (used by `skill-learn` when `body`
1145
+ is omitted).
1146
+ 2. Extract keywords from content before indexing
1147
+ (alternative to WASM keyword extraction).
1148
+ 3. Summarise content for preview generation in
1149
+ `skill-list` and `agent-list` responses.
1150
+
1151
+ ## Roots
1152
+
1153
+ The `roots/list` handler returns the filesystem roots
1154
+ that the server considers relevant to its operation.
1155
+ kbdb returns the `.kbdb` database directory as its
1156
+ single root.
1157
+
1158
+ **Response:**
1159
+
1160
+ ```json
1161
+ {
1162
+ "roots": [
1163
+ {
1164
+ "uri": "file:///path/to/.kbdb",
1165
+ "name": "kbdb database"
1166
+ }
1167
+ ]
1168
+ }
1169
+ ```
1170
+
1171
+ The URI uses the `file://` scheme with the absolute
1172
+ path to the context directory. The name is always
1173
+ `"kbdb database"`.
1174
+
1175
+ ## Logging
1176
+
1177
+ The `logging/setLevel` handler controls the verbosity
1178
+ of server-to-client log notifications. Clients set
1179
+ the level once after initialization; the server
1180
+ applies it for the lifetime of the connection.
1181
+
1182
+ **Parameter:** `level` (one of the `McpLogLevel`
1183
+ string values).
1184
+
1185
+ **Log levels** (in ascending severity order):
1186
+
1187
+ - `debug`
1188
+ - `info`
1189
+ - `notice`
1190
+ - `warning`
1191
+ - `error`
1192
+ - `critical`
1193
+ - `alert`
1194
+ - `emergency`
1195
+
1196
+ When the log level is set, the server emits
1197
+ `notifications/message` for any event at or above
1198
+ the configured level:
1199
+
1200
+ ```json
1201
+ {
1202
+ "jsonrpc": "2.0",
1203
+ "method": "notifications/message",
1204
+ "params": {
1205
+ "level": "info",
1206
+ "logger": "kbdb",
1207
+ "data": "Indexed 42 terms for section abc123"
1208
+ }
1209
+ }
1210
+ ```
1211
+
1212
+ ## Resource Subscriptions
1213
+
1214
+ Clients can subscribe to individual resources to
1215
+ receive change notifications without polling.
1216
+
1217
+ - **`resources/subscribe`** -- client provides a
1218
+ resource URI; the server adds it to the active
1219
+ subscription set.
1220
+ - **`resources/unsubscribe`** -- client provides a
1221
+ URI; the server removes it from the subscription
1222
+ set.
1223
+
1224
+ When a subscribed resource changes (section added,
1225
+ updated, or deleted; document manifest modified),
1226
+ the server emits `notifications/resources/updated`
1227
+ with the affected URI:
1228
+
1229
+ ```json
1230
+ {
1231
+ "jsonrpc": "2.0",
1232
+ "method": "notifications/resources/updated",
1233
+ "params": {
1234
+ "uri": "kbdb://section/a1b2c3d4e5f6g7h8j9k0"
1235
+ }
1236
+ }
1237
+ ```
1238
+
1239
+ ## Execution Model
1240
+
1241
+ ```
1242
+ AI agent host (Claude Desktop, Claude Code, etc.)
1243
+
1244
+ │ spawns child process
1245
+
1246
+ kbdb mcp --db /path/to/.kbdb
1247
+
1248
+ │ stdio: JSON-RPC 2.0 (stdin/stdout)
1249
+
1250
+ MCP Server (src/cli.ts -- MCP mode)
1251
+
1252
+ │ imports src/shared/worker-client/
1253
+
1254
+ Worker Client
1255
+
1256
+ │ IPC: JSON-RPC 2.0 (Unix socket / named pipe)
1257
+
1258
+ Worker Daemon (src/worker.ts)
1259
+ ```
1260
+
1261
+ The MCP server is a long-lived process. It creates a
1262
+ worker client on startup, holds the IPC connection
1263
+ open, and routes all incoming MCP requests through
1264
+ it. The daemon handles concurrency, caching, and WASM
1265
+ module orchestration.
1266
+
1267
+ When the AI agent host terminates the connection
1268
+ (closes stdin), the MCP server disconnects from the
1269
+ worker daemon and exits. The daemon may continue
1270
+ running for other clients or shut down on idle
1271
+ timeout.
1272
+
1273
+ ## Relationship to CLI Mode
1274
+
1275
+ The MCP server and CLI mode share:
1276
+
1277
+ - The same `kbdb` executable and installation.
1278
+ - The same worker client module
1279
+ (`src/shared/worker-client/`).
1280
+ - The same worker daemon and WASM modules.
1281
+ - The same `.kbdb` database directory.
1282
+
1283
+ Changes made via CLI commands are visible to the MCP
1284
+ server and vice versa -- both operate on the same
1285
+ database through the same daemon.
1286
+
1287
+ The difference is the interface:
1288
+
1289
+ | Aspect | CLI Mode | MCP Mode |
1290
+ |-----------|------------------------|------------------------|
1291
+ | Lifecycle | Short-lived (one cmd) | Long-lived (persistent)|
1292
+ | Interface | Command-line arguments | MCP protocol (stdio) |
1293
+ | Consumer | Human / shell script | AI agent |
1294
+ | Output | stdout (JSON/text/MCP) | MCP tool result format |
1295
+ | DB path | CWD or `--db` flag | `--db` flag or `KBDB_DIR` env |
1296
+
1297
+ See [CLI](cli.md) for CLI mode details,
1298
+ [Worker Client](worker-client.md) for the shared
1299
+ client module, and [Database](database.md) for
1300
+ storage details.
1301
+
1302
+ ## Notifications
1303
+
1304
+ Notifications are one-way JSON-RPC messages with no
1305
+ `id` and no response expected.
1306
+
1307
+ ### Client -> Server
1308
+
1309
+ | Notification | When |
1310
+ |-------------|------|
1311
+ | `notifications/initialized` | After `initialize` response received (required) |
1312
+ | `notifications/cancelled` | Client cancels an in-flight request |
1313
+ | `notifications/roots/list_changed` | If `roots.listChanged` advertised |
1314
+
1315
+ ### Server -> Client
1316
+
1317
+ | Notification | When |
1318
+ |-------------|------|
1319
+ | `notifications/tools/list_changed` | Tool set changed (if `tools.listChanged`) |
1320
+ | `notifications/resources/list_changed` | Resource set changed (if `resources.listChanged`) |
1321
+ | `notifications/resources/updated` | Subscribed resource changed |
1322
+ | `notifications/prompts/list_changed` | Prompt set changed (if `prompts.listChanged`) |
1323
+ | `notifications/message` | Structured log message (if `logging` capability) |
1324
+ | `notifications/progress` | Long-running request progress update |
1325
+
1326
+ kbdb does not currently emit any server-to-client
1327
+ notifications. It handles `notifications/initialized`
1328
+ from the client and ignores unknown notifications.
1329
+
1330
+ ## Error Handling
1331
+
1332
+ ### Protocol Errors
1333
+
1334
+ Protocol-level errors use JSON-RPC 2.0 error
1335
+ responses:
1336
+
1337
+ | Code | Meaning |
1338
+ |------|---------|
1339
+ | `-32700` | Parse error -- malformed JSON |
1340
+ | `-32601` | Method not found |
1341
+ | `-32602` | Invalid params |
1342
+ | `-32603` | Internal error |
1343
+ | `-32002` | Resource not found (MCP-specific) |
1344
+
1345
+ ### Tool Execution Errors
1346
+
1347
+ Tool-level failures are **not** protocol errors.
1348
+ They are returned as successful JSON-RPC responses
1349
+ with `isError: true` in the tool result:
1350
+
1351
+ ```json
1352
+ {
1353
+ "jsonrpc": "2.0",
1354
+ "id": 5,
1355
+ "result": {
1356
+ "content": [
1357
+ {
1358
+ "type": "text",
1359
+ "text": "Section not found: abc123"
1360
+ }
1361
+ ],
1362
+ "isError": true
1363
+ }
1364
+ }
1365
+ ```
1366
+
1367
+ `handleToolCall` wraps every tool dispatch in a
1368
+ `try/catch`. When an error is thrown, the handler
1369
+ returns `{ content: [{ type: 'text', text:
1370
+ err.message }], isError: true }` where `err.message`
1371
+ is the message string when `err` is an `Error`
1372
+ instance, or `String(err)` otherwise. Validation
1373
+ errors within a tool handler (e.g. missing `title`
1374
+ for `image/*` types, unknown tool name, or `retrieve`
1375
+ called without `kbid` or `docid`) follow the same
1376
+ format but are returned directly rather than thrown.
1377
+
1378
+ All successful tool results are wrapped as:
1379
+ ```json
1380
+ { "content": [{ "type": "text", "text": "<JSON>" }] }
1381
+ ```
1382
+ where `<JSON>` is the result serialised with
1383
+ `JSON.stringify`. Most tools use 2-space indentation;
1384
+ `learn`, `unlearn`, and `content` return compact JSON
1385
+ (no indentation).
1386
+
1387
+ Reserve JSON-RPC error responses for protocol
1388
+ violations (bad JSON, unknown method, missing
1389
+ required params). Application errors from tool
1390
+ execution go in the result.
1391
+
1392
+ ### Prompt and Skill Errors
1393
+
1394
+ Additional error cases for the prompts and skill/agent
1395
+ tools:
1396
+
1397
+ | Condition | Response |
1398
+ |-----------|----------|
1399
+ | `prompts/get` with unknown prompt name | JSON-RPC error `-32002` (resource not found) |
1400
+ | `skill-learn` with empty `body` | Tool result with `isError: true`, message: `"skill body must not be empty"` |
1401
+ | `skill-get` called without `name` or `kbid` | Tool result with `isError: true`, message: `"Provide name or kbid"` |
1402
+ | `skill-learn` with duplicate name | Not an error -- duplicate names are allowed, each gets a distinct kbid |
1403
+ | `agent-get` with skill kbid that has been deleted | Not an error -- the skill entry appears with `"name": null` in the skills array |
1404
+
1405
+ ## Required vs Optional Methods
1406
+
1407
+ Methods are grouped by the capability that gates
1408
+ them. A server must implement all methods for every
1409
+ capability it advertises.
1410
+
1411
+ | Method | Gate | kbdb Status |
1412
+ |--------|------|-------------|
1413
+ | `initialize` | required | implemented |
1414
+ | `notifications/initialized` | required | implemented |
1415
+ | `ping` | required | implemented |
1416
+ | `tools/list` | `tools` capability | implemented |
1417
+ | `tools/call` | `tools` capability | implemented |
1418
+ | `resources/list` | `resources` capability | empty list |
1419
+ | `resources/read` | `resources` capability | implemented |
1420
+ | `resources/templates/list` | `resources` capability | implemented |
1421
+ | `resources/subscribe` | `resources.subscribe` | planned |
1422
+ | `resources/unsubscribe` | `resources.subscribe` | planned |
1423
+ | `prompts/list` | `prompts` capability | implemented |
1424
+ | `prompts/get` | `prompts` capability | implemented |
1425
+ | `completion/complete` | `completions` capability | implemented |
1426
+ | `sampling/createMessage` | `sampling` capability | planned |
1427
+ | `roots/list` | `roots` capability | implemented |
1428
+ | `logging/setLevel` | `logging` capability | planned |
1429
+
1430
+ Methods listed as "planned" are documented for
1431
+ future implementation. Until implemented, the server
1432
+ returns `-32601` if they are called.
1433
+
1434
+ ## Design Constraints
1435
+
1436
+ - The MCP server conforms to the Model Context
1437
+ Protocol specification version **2025-11-25**.
1438
+ - Output follows MCP tool result conventions. The
1439
+ CLI's output format flags do not apply in MCP mode.
1440
+ - The server runs as a persistent process. It stays
1441
+ alive and handles multiple requests from the
1442
+ connected agent until the host terminates the
1443
+ connection.
1444
+ - The server works with both Deno and Node.js
1445
+ runtimes, consistent with the project's
1446
+ dual-runtime requirement.
1447
+ - The database path must be explicitly configured
1448
+ via `--db` or `KBDB_DIR`. No working directory
1449
+ fallback.
1450
+ - The MCP server does not perform keyword extraction,
1451
+ indexing, ranking, or database I/O itself. All
1452
+ processing is delegated to the worker daemon via
1453
+ the worker client.
1454
+
1455
+ ### Wire Format Rules
1456
+
1457
+ - **stdout is sacred** -- only JSON-RPC messages may
1458
+ be written to stdout. Debug output, diagnostics,
1459
+ and progress messages must go to stderr. Any
1460
+ non-JSON-RPC output on stdout corrupts the stream.
1461
+ - **One message per line** -- each JSON-RPC message
1462
+ is serialized as a single line of JSON with no
1463
+ embedded newlines, terminated by `\n`.
1464
+ - **Request ID must not be null** -- unlike standard
1465
+ JSON-RPC 2.0, MCP requires the `id` field to be a
1466
+ non-null `string` or `number`. Notifications omit
1467
+ `id` entirely.