MCP integration

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.

mcp.json
{
  "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.

Self-learning agents

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.

Field types

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.

textstringi64u64 f64datebooleanbytes ipjsonfacet
float, double, decimal → f64Python, SQL
integer, int, number, signed → i64Python, JavaScript
unsigned, uint → u64C/C++, Rust
datetime, timestamp → dateSQL, Python
object, document → jsonJavaScript, Python
category, tag → facetCommon terminology

Lists

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.

Client

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.

In practice

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.

HTTP API

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.

terminal
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. read
PUT /api/{index}/documentWrite one document; DELETE removes it. write
POST /api/{index}/_bulkBatched write, and where the throughput is. _bulk/delete is its counterpart. write
PATCH /api/{index}/_schemaPromote discovered fields, or add new ones. index-admin
GET /_indexesEvery index this key may see. read
GET /_admin/memoryProcess and allocator statistics; /_admin/workers reports the pool. node-admin
GET /_cluster/healthThe one public route. none

A 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.