MCP Server
透過 streamable HTTP 或 stdio 讓 MCP client 連上 KuraDB,並理解它暴露的兩個唯讀 tool。
兩種 transport,同一份實作
KuraDB 以官方 github.com/modelcontextprotocol/go-sdk 實作 Model Context Protocol,並用兩種 transport 提供同一份 server 定義:
| Transport | Endpoint | Process | 需要 daemon 在跑 |
|---|---|---|---|
| Streamable HTTP | daemon listener 上的 POST /mcp |
Daemon | 是 |
| Stdio | kura mcp |
由 client spawn 的獨立 process | 否 |
兩者都用 internal/mcp 建立相同的 tool 集合,並在各自的 process 內以 search.Search 回答。兩種 transport 都不呼叫 REST API,stdio 這條也不是 daemon 的代理。
以 stdio 連線
把任何 MCP client 指向 kura 執行檔:
{
"mcpServers": {
"kuradb": {
"command": "kura",
"args": ["mcp"]
}
}
}
kura mcp 以唯讀方式開啟已註冊的資料庫、從 SQLite 重建自己的 vector cache,並在 stdin 與 stdout 上進行 JSON-RPC。診斷訊息走 stderr,因此不會污染協定串流。stdin 關閉時 session 結束,exit code 為 0。
由於 vector cache 是在 spawn 當下載入,它看到的是一份快照:daemon 之後新索引的檔案,要等該 MCP session 重啟才會出現。
以 HTTP 連線
Daemon 將 MCP handler 掛在與 REST API 相同的 listener 上:
BASE="$(cat ~/.config/kuradb/endpoint)"
curl -X POST "$BASE/mcp" \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"probe","version":"0"}}}'
Response 會帶 Mcp-Session-Id header,後續請求必須沿用。未固定 port 的 daemon 每次重啟都綁隨機 port,因此把 URL 寫進 client 設定前先固定:
kura port set 8080
Server instructions
initialize 階段 server 會回傳 instructions,說明它是什麼,以及同等重要的:它不是什麼。
- KuraDB 是針對「使用者放進監控資料夾的靜態檔案」的唯讀檢索來源。
- 當答案取決於那些檔案的內容而非通用知識時就該使用它。
- 它不存放對話歷史、session 記憶或使用者輪廓。
最後一點是刻意的。被宣稱成記憶體的工具會被選去回答它答不了的問題;標明邊界能讓路由誠實。
list_rag
列出可搜尋的資料庫,不需要參數。
{
"loaded": ["notes"],
"registered": [
{ "db": "notes", "createAt": "2026-07-14T07:00:00Z" }
]
}
loaded 是這個 process 內可查詢的名稱;registered 來自 db.json。啟動後才新增的資料庫只會出現在 registered。
search_rag
搜尋單一資料庫,回傳依 source 分組的 file chunk。
| 參數 | 必填 | 預設 | 行為 |
|---|---|---|---|
db |
是 | — | 目標資料庫名稱,由 list_rag 取得 |
q |
是 | — | 查詢文字 |
mode |
否 | 兩者 | keyword 或 semantic;省略則兩者都跑 |
limit |
否 | 10 |
每個 mode 最多回傳的 chunk 數,1–100 |
schema 內宣告了 mode 的 enum 與 limit 的 default,因此 SDK 會在 handler 執行前完成驗證與套用預設值。非法 enum 值或缺少必填欄位會直接以 tool error 回絕,不會碰到 SQLite。
結構化輸出與 REST response 一致,只是沒跑的分支不會出現:
{
"keyword": [
{
"source": "/Users/example/Kura_notes/rag.md",
"matches": [{ "chunk": 1, "content": "RAG combines retrieval with generation." }]
}
],
"semantic": []
}
每次呼叫都同時回傳 JSON 文字區塊與 structuredContent,因此支援 output schema 的 client 與只讀文字的 client 都能運作。
錯誤
| 情況 | 結果 |
|---|---|
未知 mode、缺少 db 或 q |
由 schema 驗證擋下,以 tool error 回傳 |
| 資料庫未載入 | Tool error:invalid argument: "name" not exist |
| Keyword 或 semantic 分支失敗 | Tool error,附帶底層錯誤訊息 |
參數錯誤一律以 search.ErrInvalidArgument 標記。REST transport 把這個 sentinel 對應到 HTTP 400;MCP transport 則交給 SDK 標記為 isError。
Tool 命名
Tool 名稱與參數對齊 Agenvoy 既有的 KuraDB client tool,因此消費端可以從自家 HTTP wrapper 換成這個 MCP server 而不必改寫 prompt。要改 tool 名或參數時,兩邊必須同步。