Documentation v0.5.0

MCP Server

Connect an MCP client to KuraDB over streamable HTTP or stdio, and understand the two read-only tools it exposes.

Two transports, one implementation

KuraDB implements the Model Context Protocol with the official github.com/modelcontextprotocol/go-sdk. It serves the same server definition through two transports:

Transport Endpoint Process Requires a running daemon
Streamable HTTP POST /mcp on the daemon listener Daemon Yes
Stdio kura mcp Separate process spawned by the client No

Both build the same tool set from internal/mcp and answer from search.Search in their own process. Neither transport calls the REST API, and the stdio bridge does not proxy the daemon.

Connect over stdio

Point any MCP client at the kura binary:

{
  "mcpServers": {
    "kuradb": {
      "command": "kura",
      "args": ["mcp"]
    }
  }
}

kura mcp opens the registered databases read-only, restores its own vector cache from SQLite, and speaks JSON-RPC over stdin and stdout. Diagnostics go to stderr, so they never corrupt the protocol stream. Closing stdin ends the session with exit code 0.

Because the process loads the vector cache at spawn time, its view is a snapshot: files indexed by the daemon afterwards appear only after the MCP session restarts.

Connect over HTTP

The daemon mounts the MCP handler on the same listener as the REST API:

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"}}}'

The response carries an Mcp-Session-Id header that subsequent requests must repeat. Because an unpinned daemon binds a random port on every restart, pin one before writing the URL into a client configuration:

kura port set 8080

Server instructions

During initialize the server returns instructions describing what it is and, equally important, what it is not:

The last point is deliberate. A tool advertised as a memory store gets selected to answer questions it cannot answer; the boundary keeps routing honest.

list_rag

Lists the databases that can be searched. It takes no arguments.

{
  "loaded": ["notes"],
  "registered": [
    { "db": "notes", "createAt": "2026-07-14T07:00:00Z" }
  ]
}

loaded names are queryable in this process; registered entries come from db.json. A database added after startup appears only in registered.

search_rag

Searches one database and returns file chunks grouped by source.

Parameter Required Default Behavior
db Yes Target database name, as reported by list_rag
q Yes Query text
mode No Both keyword or semantic; omit to run both
limit No 10 Maximum chunks per mode, 1–100

The schema declares the mode enum and the limit default, so the SDK validates arguments and applies defaults before the handler runs. An invalid enum value or a missing required field is rejected as a tool error without touching SQLite.

Structured output mirrors the REST response, minus the branches that did not run:

{
  "keyword": [
    {
      "source": "/Users/example/Kura_notes/rag.md",
      "matches": [{ "chunk": 1, "content": "RAG combines retrieval with generation." }]
    }
  ],
  "semantic": []
}

Every call returns both a JSON text block and structuredContent, so clients that understand output schemas and clients that only read text both work.

Errors

Condition Result
Unknown mode, missing db or q Rejected by schema validation, returned as a tool error
Database not loaded Tool error: invalid argument: "name" not exist
Keyword or semantic branch failure Tool error carrying the underlying message

Argument mistakes are reported through search.ErrInvalidArgument. The REST transport maps that sentinel to HTTP 400; the MCP transport lets the SDK mark the result with isError.

Tool naming

The tool names and parameters match the KuraDB client tools already shipped by Agenvoy, so a consumer can switch from its own HTTP wrapper to this MCP server without rewriting prompts. Renaming a tool or changing a parameter requires updating both sides.

中文