The same block
whichever agent you run
CameoDB exposes a native MCP endpoint. Drop one entry into your client's config and the knowledge base becomes a tool the agent can reach directly.
{
"mcpServers": {
"cameodb": {
"url": "http://localhost:9480/mcp"
}
}
}
Claude Code
Project or user scope.
Claude Desktop
App config file.
Cursor
Workspace MCP settings.
Windsurf
Cascade MCP config.
Six tools, and the agent
teaches itself the rest
Nobody pastes a schema into a prompt. The agent finds the indexes, reads the types of the one it wants, has its query checked and corrected before spending a search on it, then asks. Every step answers the next one, so the knowledge base teaches the agent how to query it, and a new index joins that loop the moment it exists.
list_indexesWhat is here. Every index the key can see, with document counts and field names. A new index appears without configuration.describe_indexOne index in detail: field types, the indexed, fast and shadow flags, and per-type query hints.validate_queryThe syntax guide, a dry run and a correction. Reports what parses, what the engine would rewrite it to, which clauses would be dropped, and names the field you meant: Unknown field ‘titel’. Did you mean: title?search_indexFull-text search over one index.search_across_indexesThe same question against several indexes at once, run concurrently and merged into one ranked list.get_catalog_statsCounts and sizes, for one index or across all of them.Read-only, closed world
Every tool is annotated readOnlyHint and openWorldHint: false. They reach this node’s own indexes and nothing else, which is a property an agent host can check rather than a promise it has to take.
A typo is refused, not ignored
Each schema sets additionalProperties: false, so a call carrying an argument its tool does not take fails by name. A misspelled limit would otherwise return the default ten hits and read as the whole answer.
One result shape
Read content[0].text and let isError decide whether to parse it or read it. Every protocol revision gets that same shape, so a client needs no branch for the one it negotiated.
Indexes are also MCP resources: cameodb://indexes for the catalog, cameodb://indexes/{index}/schema for one schema. Transport is Streamable HTTP on POST /mcp, with the older SSE pair kept for clients already configured against it.
Declare it once.
Query it any way
Eleven core raw types, with aliases so a schema written in SQL, Python or JavaScript terms maps cleanly onto the engine.
float, double, decimal → f64Python, SQLinteger, int, number, signed → i64Python, JavaScriptunsigned, uint → u64C/C++, Rustdatetime, timestamp → dateSQL, Pythonobject, document → jsonJavaScript, Pythoncategory, tag → facetCommon terminologyLists
Every field is multivalued, so there is no array type to declare. Give a field i64 and [9, 12] stores two values of it, each one matched on its own by an exact or range query. Text and json fields take a list whole, as their own JSON.
Built for operators
not just scripts
Launch with ./cameodb client -i for a REPL that completes against your live schema, and types the same grammar the agent sends.
Completion from the node
Index names and searchable fields, annotated [text] or [numeric], refreshed after connect so a suggestion is never stale.
Load from anywhere
CSV, TSV and JSON families, local or over HTTP(S), Gzip and Zip decompressed in flight.
Left open all day
Persistent history with Ctrl-R, colorized output that falls back to plain in a pipe, and a prompt a slow query cannot freeze.
The commands, the completion behaviour and the ingest flags are on the client page.
Composable by design
Operators combine, so an agent can narrow a result set incrementally rather than reformulating from scratch.
status:active AND region:IN [eu us]Term match intersected with a set.title:"index segment"~2Phrase with slop, tolerating word distance.created:>=2024-01-01 AND level:errorOpen-ended date bound plus an exact term.src_ip:[10.0.0.1 TO 10.0.0.255]Inclusive range across an IP field.path:var* AND NOT level:debugPrefix match with a negation."thanks for your contrib"*Phrase prefix: the last term is a wildcard.Why this matters for agents
A predictable grammar is one an LLM can generate reliably. Combined with sub-millisecond point lookups, the agent can probe and refine many times inside one reasoning step.
Every operator, with the field types it applies to, is on the query syntax page. An agent gets the same reference from validate_query without leaving the conversation.
No agent, no client
just the endpoint
MCP is one way in and the REPL is another. An application wants neither. It wants JSON over HTTP against the same indexes, with the same query grammar in the body.
curl -s -X POST http://localhost:9480/api/books/search \
-H 'content-type: application/json' \
-d '{"query":"title:\"Harry Potter\"","limit":7}'
POST /api/{index}/searchSearch one index. /search/stream returns NDJSON, one hit per line. readPUT /api/{index}/documentWrite one document; DELETE removes it. writePOST /api/{index}/_bulkBatched write, and where the throughput is. _bulk/delete is its counterpart. writePATCH /api/{index}/_schemaPromote discovered fields, or add new ones. index-adminGET /_indexesEvery index this key may see. readGET /_admin/memoryProcess and allocator statistics; /_admin/workers reports the pool. node-adminGET /_cluster/healthThe one public route. noneA key travels in Authorization: Bearer and nowhere else: a query parameter is not a credential and is refused. An unknown path answers 401 without a key and 404 with one, so probing tells an unauthenticated caller nothing.