# MCP tools

> Every tool on SkimmerDB's MCP server, its arguments, what it answers and which connections see it.

The tools on `https://api.skimmerdb.com/mcp`. Each runs the same code as its REST call, with
the same limits, metering and errors. See [Connect an agent](/mcp) to set it up.

**Results are typed.** Every tool declares an `outputSchema` (JSON Schema) in `tools/list`, and
a call answers `structuredContent` matching it: the same fields as the REST call's answer
(the [API reference](/api) describes them). The same JSON also comes as one text content item,
for clients that read only text. A failed call answers `isError: true` with the error's JSON
(`{"error", "code"}`).

Each tool's output schema is its REST call's answer, from the same OpenAPI component, so the
typed result can't drift from the API:

| Tool | Output schema |
|---|---|
| `list_namespaces` | [`NamespaceList`](/api/namespaces#op-listNamespaces) |
| `create_namespace`, `update_namespace` | [`Namespace`](/api/namespaces#op-createNamespace) |
| `delete_namespace` | `{"deleted": true}` |
| `write_documents`, `delete_documents` | [`WriteResult`](/api/documents#op-writeDocuments) |
| `search` | [`SearchResult`](/api/search#op-search) |
| `count` | [`CountResult`](/api/search#op-count) |
| `get_document` | [`StoredDocument`](/api/documents#op-getDocument) |
| `warm_namespace` | [`WarmResult`](/api/search#op-warmNamespace) |
| `sql_query` | [`SqlResult`](/api/sql#op-querySql) |

```json title="tools/call answer"
{"jsonrpc": "2.0", "id": 2, "result": {
  "content": [{"type": "text", "text": "{\"namespace\":\"support\",\"hits\":[...],\"next\":\"\",...}"}],
  "structuredContent": {"namespace": "support", "hits": [...], "next": "", "docs": 2, "took_ms": 0.41, "partial": false},
  "isError": false}}
```

| Tool | Title | Kind | Seen by | REST equivalent |
|---|---|---|---|---|
| `list_namespaces` | List namespaces | read | every connection | `GET /v1/namespaces` |
| `create_namespace` | Create a namespace | write | read-and-write | `POST /v1/namespaces` |
| `update_namespace` | Change a namespace's embedding model | write | read-and-write | `PATCH /v1/namespaces/{name}` |
| `delete_namespace` | Delete a namespace | destructive | read-and-write | `DELETE /v1/namespaces/{name}` |
| `write_documents` | Write documents | write | read-and-write | `POST /v1/namespaces/{name}/docs` |
| `delete_documents` | Delete documents | destructive | read-and-write | `POST /v1/namespaces/{name}/delete` |
| `search` | Search documents | read | every connection | `POST /v1/namespaces/{name}/search` |
| `count` | Count documents | read | every connection | `POST /v1/namespaces/{name}/count` |
| `get_document` | Read a document | read | every connection | `GET /v1/namespaces/{name}/docs/{id}` |
| `sql_query` | Query with SQL | read | every connection | `POST /v1/namespaces/{name}/sql` |
| `warm_namespace` | Warm a namespace | read | every connection | `POST /v1/namespaces/{name}/warm` |

Read tools carry `readOnlyHint: true`; `delete_namespace` and `delete_documents` carry
`destructiveHint: true`. A read-only connection (or a `read` key) is offered only the read tools.
Namespace limits on the connection apply to every tool.

## list_namespaces

Lists your namespaces by name, with what each stores.

| Argument | Type | |
|---|---|---|
| `after` | string | list names after this one (the previous page's `next`) |
| `limit` | integer | how many (default 100) |

## create_namespace

Creates an empty namespace. With `dims`, it stores your own embeddings too; with
`embed_provider`, documents' text is embedded for you (see [Embeddings](/guides/embeddings)) and
`search` takes `semantic`. Writing documents to a new name also creates it, so this is only
needed to choose vector settings up front.

| Argument | Type | |
|---|---|---|
| `name` | string, required | 1 to 64 of `a-z`, `0-9`, `-`, `_` and `.` |
| `dims` | integer | embeddings' length (e.g. 768); leave out for text only |
| `metric` | string | `cosine` (default) or `euclidean` |
| `embed_provider` | string | `openai`, `voyage`, `gemini` or `cohere` (the tenant's own key, stored in the dashboard), or `skimmerdb` (hosted, at cost) |
| `embed_model` | string | the provider's model (defaults per provider: see [Embeddings](/guides/embeddings#2-make-a-namespace-with-a-model)) |

## update_namespace

Sets, changes or stops a namespace's embedding model. The model must make vectors of the
namespace's length. Leave `embed_provider` out (or empty) to stop embedding. Provider keys are
not an MCP tool on purpose: they're pasted in the dashboard.

| Argument | Type | |
|---|---|---|
| `name` | string, required | the namespace |
| `embed_provider` | string | as for `create_namespace`; empty: stop embedding |
| `embed_model` | string | the provider's model |

## delete_namespace

Deletes a namespace and every document in it, for good. Answers `{"deleted": true}`.

| Argument | Type | |
|---|---|---|
| `name` | string, required | the namespace |

## write_documents

Stores (upserts) documents: an id written again replaces its earlier version. May also delete
ids in the same call. Durable when it answers; searchable within about a second, or before it
answers with `wait`.

| Argument | Type | |
|---|---|---|
| `namespace` | string, required | the namespace (made if it doesn't exist) |
| `docs` | array of `{id, text, meta, vector}` | `id` required; `meta` an object of strings, numbers and booleans; `vector` as many numbers as the namespace's dims |
| `deletes` | array of strings | ids to delete |
| `wait` | boolean | answer only once the documents are searchable |

## delete_documents

Deletes documents by id, for good. Ids that don't exist are ignored.

| Argument | Type | |
|---|---|---|
| `namespace` | string, required | the namespace |
| `ids` | array of strings, required | the ids |
| `wait` | boolean | answer only once the deletes are visible |

## search

Finds documents containing some text or matching a regex, optionally only those whose `meta`
matches a filter. Newest first; each hit has the id, the matched text, the line around it,
`meta` and when it was written. With `vector` (or `semantic`, a text, in a namespace with an
embedding model): the nearest documents by meaning (among those matching `query` and `filter`,
if given), with a score.

| Argument | Type | |
|---|---|---|
| `namespace` | string, required | the namespace |
| `query` | string | plain text, matched literally and ignoring case; empty lists documents |
| `regex` | boolean | read `query` as an RE2 regex (case-sensitive unless it starts with `(?i)`) |
| `filter` | object | `{"type": "invoice"}`, `{"type": ["a", "b"]}`, `{"amount": {"gte": 10, "lt": 100}}`, `{"tag": {"ne": "x"}}`: see [Filters](/reference/filters) |
| `limit` | integer | how many results (default 20, at most 1,000) |
| `cursor` | string | the previous answer's `next`, for the next page |
| `vector` | array of numbers | the query's embedding: nearest first |
| `semantic` | string | a text embedded with the namespace's model, then searched like `vector` |

## count

Counts every document that contains some text or matches a regex (and the filter), exactly,
with a sample of ids; or estimates fast with `exact: false`.

| Argument | Type | |
|---|---|---|
| `namespace` | string, required | the namespace |
| `query` | string | as for `search` |
| `regex` | boolean | as for `search` |
| `filter` | object | as for `search` |
| `exact` | boolean | `false`: a fast estimate for big namespaces (no filter); default `true` |

## get_document

Reads one document whole: its text, `meta`, vector (if any) and when it was written.

| Argument | Type | |
|---|---|---|
| `namespace` | string, required | the namespace |
| `id` | string, required | the document's id |

## sql_query

Counts, groups, aggregates and filters a namespace's documents with SQL over their metadata,
combined with exact text or regex matches. Answers columns, types and rows (at most 10,000).
Run `SHOW COLUMNS` first to see the columns. See the [SQL reference](/reference/sql).

| Argument | Type | |
|---|---|---|
| `namespace` | string, required | the namespace |
| `sql` | string, required | one `SELECT ... FROM docs`, or `SHOW COLUMNS` |

## warm_namespace

Opens a namespace the agent is about to search, and fetches what the given searches will need,
so they answer at warm speed. Says how warm it was (`warm`, `local` or `cold`).

| Argument | Type | |
|---|---|---|
| `namespace` | string, required | the namespace |
| `queries` | array of strings | searches about to run (up to 20) |
| `regex` | boolean | the queries are regexes |
