# Auxiliary operations

> Operations that describe and check the database, configure it and maintain its indexes.

Operations that describe and check the database, configure it and maintain its indexes. The [overview](https://datanotes.dev/reference/operations/) lists every operation by kind. The MCP server, `datanotes mcp`, offers each operation as an MCP tool of the same name, and `engineTools()` of `datanotes/mcp` gives the same definitions to [your own MCP server](https://datanotes.dev/develop/build-on-datanotes/#build-your-own-mcp-server). `DatanotesClient.call(name, args)` runs one from code. Over HTTP each one is `POST /datanotes/operations/<name>/`, with its arguments as the JSON body: the [HTTP API reference](https://datanotes.dev/api/) lists them.

Every write is validated. Writes to rows and to the schema are journaled and undone with `undo_migration`; `configure_database`, the webhook operations, `vacuum_table` and `sync_semantic_index` are not journaled.

## `list_tables`

**List Tables** · read-only

List every table: `name`, `catalog`, `schema`, `qualified` (`personal.metrics.mood` — use it wherever a table is expected; `metrics.mood` or `mood` also work when unambiguous), `path` and, when declared, `description`, `aliases` (other words for what it records) and `tags`. Tables are defined in `metastore.yaml` (catalog → schema → table): read it freely, but it is read-only for agents and changes only through the schema operations (create_table, add_column, …). Returns `{tables, views}`: `views` lists the stored views (same fields, no path): select them like tables. `system.information_schema` is read with `select_rows`.

Call this first to find the table for what the user reports (match their words against name, description and aliases), and before creating tables or columns so you reuse existing ones instead of creating duplicates.

Examples: [Tables](https://datanotes.dev/guides/database-objects/tables/), [Views](https://datanotes.dev/guides/database-objects/views/).

## `describe_table`

**Describe Table** · read-only

Describe a table (`catalog.schema.table` or a shorter unambiguous name): `qualified`, `name`, `catalog`, `schema`, `description`, `aliases`, `layout` (`folder`, `row_folder`: the folder pattern of new rows, `archive`), `options` (`partition`, `filename`, `archive`, `exclude`), typed `columns` with label/aliases/description and the dense flag, `untyped_fields`, `row_count`, and when set: `tags`, `bases` (the bases it inherits from, in order), `constraints` (its CHECKs, name → where), `row_template`, `history`, `autolink_target`, `fields` (their values).

Before adding a column (e.g. a new metric), read `columns` and match your concept against `name`, `label`, `aliases` and `description`; reuse an existing column when it means the same.

`missing_descriptions` (`{table, columns}`), present only when something has no description (a table defined before descriptions were required), names what lacks one: write them with alter_table `description` and alter_column `changes.description`, asking the user when the meaning is unclear.

Examples: [Catalogs, schemas and the database](https://datanotes.dev/guides/database-objects/catalogs-and-schemas/), [Tables](https://datanotes.dev/guides/database-objects/tables/), [Bases](https://datanotes.dev/guides/database-objects/bases/), [Relations and hierarchies](https://datanotes.dev/guides/database-objects/relations/).

| Parameter | Type   | Required | Default | Description |
| --------- | ------ | -------- | ------- | ----------- |
| `table`   | string | yes      |         |             |

## `describe_database`

**Describe Database** · read-only

Describe the database: its folder (`root`), `metastore` (`metastore.yaml`: read it freely, but it is read-only for agents and changes only through the schema operations), configuration (default catalog and schema, row partition and file-name formats, archive folder, time zone, history, automatic links), journal folder, `bases` (shared column sets and the tables using them), `catalogs` → `schemas` → `tables` (with `row_count`, `tags`, and `unreadable_count` when some rows’ front matter cannot be read) and `views`; catalogs and schemas show their `comment` (set with `comment_on`). A table or base defined before descriptions were required has `missing_descriptions`: what lacks one, for alter_table / alter_column (define_base for a base) to fill, so every table and column says what it holds.

Examples: [Catalogs, schemas and the database](https://datanotes.dev/guides/database-objects/catalogs-and-schemas/), [Hand edits](https://datanotes.dev/guides/data-quality/hand-edits/).

## `configure_database`

**Configure Database** · destructive write

Configure the database (persisted in metastore.yaml `config:`): `root` (rename the database folder; links follow; revert by renaming back), `default_catalog`, `default_schema`, `default_partition` (“” = flat) and `default_filename` (date formats for new time-based tables), `archive_folder`, `timezone` (IANA; completes date-times written without offset), `history` (transaction log for every table: true in a database the engine creates, false when `config` lacks it, as in a metastore from before 3.0.0; change it only on the user’s request), `autolink` (the text a write puts in a body links the notes it mentions; on by default). Returns describe_database. Renaming `root` moves the folder (links to its notes are rewritten; the tables’ archive and `exclude` folders inside it follow); the move is listed in the journal as `move_database` (undo and time travel read older entries with the new paths) and cannot be undone. Settings changes are not journaled (no `migration_id`, nothing for undo_migration): to revert, call it again with the previous values.

The metastore changes only through operations: never edit metastore.yaml by hand (no validation).

Examples: [Catalogs, schemas and the database](https://datanotes.dev/guides/database-objects/catalogs-and-schemas/), [Tables](https://datanotes.dev/guides/database-objects/tables/), [Automatic links](https://datanotes.dev/guides/read-and-write/automatic-links/), [Table history and time travel](https://datanotes.dev/guides/history/table-history/).

| Parameter           | Type       | Required | Default | Description |
| ------------------- | ---------- | -------- | ------- | ----------- |
| `root`              | string \\  | null     |         | `null`      |
| `default_catalog`   | string \\  | null     |         | `null`      |
| `default_schema`    | string \\  | null     |         | `null`      |
| `default_partition` | string \\  | null     |         | `null`      |
| `default_filename`  | string \\  | null     |         | `null`      |
| `archive_folder`    | string \\  | null     |         | `null`      |
| `timezone`          | string \\  | null     |         | `null`      |
| `history`           | boolean \\ | null     |         | `null`      |
| `autolink`          | boolean \\ | null     |         | `null`      |

## `check_table`

**Check Table** · read-only

Validate every row against the table (required, types, ranges, enums, links, unknown columns, CHECK constraints, those that follow links included, filtered link targets (ref_where / ref_by), stale generated/identity values, missing inverse links, front matter that cannot be read: code `unreadable`, with no column, for a note whose `table` line names the table but whose YAML is broken, which every other read leaves out). A CHECK violation has code `check` and the CHECK’s name as `constraint` (every other code names its `column`), as in the `violations` of list_changes. Use it to find rows edited by hand that break the schema. Without `table`, every table is checked: each row then names its `table`, `tables_checked` counts the tables checked, and a table that cannot be checked is listed in `errors` ({table, error}) while the others are. The rows with violations are paged: `limit` (default 500, at most 5000) from `offset`; `total` counts them all. (Hand edits are also checked as they happen: see `violations` in list_changes.)

Examples: [Relations and hierarchies](https://datanotes.dev/guides/database-objects/relations/), [Hand edits](https://datanotes.dev/guides/data-quality/hand-edits/), [Find rows that break the schema](https://datanotes.dev/guides/data-quality/check-table/).

| Parameter | Type      | Required | Default | Description                                  |
| --------- | --------- | -------- | ------- | -------------------------------------------- |
| `table`   | string \\ | null     |         | `null`                                       |
| `limit`   | integer   |          | `500`   | Rows with violations returned (paging).      |
| `offset`  | integer   |          | `0`     | Rows with violations skipped first (paging). |

## `infer_table`

**Infer Table** · read-only

Read-only schema inference from notes’ front matter.

* `folder` (recursive; “” = whole vault) and/or `paths`: notes not yet in a table. Returns `columns` (type, enum `values`, link `ref` to the table most targets belong to, `required`, `unique`, `dense`, `from` when the front matter key is not a valid column name, `stats`), `proposal`, the create_table arguments (`name`, `description`, `filename` or `time_column`, `columns`), and `adopt` ready for adopt_rows (`paths`, `rename`, `relocate: false`), plus `hints` to read. The notes cannot say what the table and its columns mean: `description` is null on the proposal and on every column. Write each one (ask the user when unsure), and review the names, enums and required columns, before you pass the proposal to create_table, which refuses null descriptions.
* `table`: keys the table’s rows use but the table does not declare (candidates for add_column, each with a description to write, or keys to drop from rows). A string column becomes an enum when its values repeat: at least 3 notes, at most `max_enum_values` distinct values (default 12), each used twice on average, short texts.

Examples: [Hand edits](https://datanotes.dev/guides/data-quality/hand-edits/), [Import existing notes](https://datanotes.dev/guides/read-and-write/import-notes/).

| Parameter         | Type         | Required | Default | Description |
| ----------------- | ------------ | -------- | ------- | ----------- |
| `folder`          | string \\    | null     |         | `null`      |
| `paths`           | string\[] \\ | null     |         | `null`      |
| `table`           | string \\    | null     |         | `null`      |
| `name`            | string \\    | null     |         | `null`      |
| `max_enum_values` | integer \\   | null     |         | `null`      |

## `describe_semantic_index`

**Describe Semantic Index** · read-only

The semantic search index: `enabled`, `provider`, `model`, `files`, `passages`, `pending`, `running`, `last_sync`, `last_error`. sync_semantic_index brings it up to date.

Examples: [Find notes by meaning](https://datanotes.dev/guides/search/semantic/).

## `sync_semantic_index`

**Sync Semantic Index** · destructive write

Bring the semantic search index up to date: embed the notes changed since the last run (the engine also does it on its own about ten seconds after edits). `rebuild: true` re-embeds everything: slow, and costs money with a paid provider — ask first.

Examples: [Find notes by meaning](https://datanotes.dev/guides/search/semantic/).

| Parameter | Type    | Required | Default | Description                                     |
| --------- | ------- | -------- | ------- | ----------------------------------------------- |
| `rebuild` | boolean |          | `false` | Re-embed every note, not only the changed ones. |
