MCP.Market

Datanotes MCP server

by davidefornelli·io.github.davidefornelli/datanotes·v3.0.0

The engine of your second brain: Markdown notes as database tables, for you and your agents.

A92/100grade A
What users say
No reviews yet
Be the first
Safety scan
A92/100

full report

Adoption
Growing

0 stars1.8k downloads/wk

Reviews

Write one

Nobody has reviewed Datanotes yet.

If you have run it, two minutes of your experience saves the next person an afternoon.

Datanotes tools (56, 14 write)

write = sends, deletes, buys or posts

Read from the package source without running it. The installed server may list more.

  • add_column

    Add a typed column. Sparse by default (written only on rows that have a value \u2014 use for metrics, e.g. `{"name": "metric_mood", "type": "integer", "min": 1, "max": 5, "label": "Mood", "aliases": ["mood"], "description": "Mood of the day, 1 = bad, 5 = great"}`). `description` is required: what the column holds, for the agents and people who read the schema (the engine writes it for `identity` "

  • add_constraint

    ALTER TABLE ADD CONSTRAINT `name` CHECK: `check` is a where filter every row must match, e.g. `{"value": {"gte": 1, "lte": 5}}`. A condition on a column the row leaves empty passes, like SQL; inside `or` / `and` / `not` an empty value is tested as it is (`{"exists": true}` there fails). A key may follow a link column to the row it names, as in queries: `{"parent.kind": "project"}` (further dots fo

  • adopt_rows

    Turn existing notes (not rows of any table yet) into rows of `table`, keeping their body and links: `rename` keys (`{"data": "occurred_at"}`), `set` for all, `per_row` values by note path (`{"Home/x.md": {"zone": "[[Kitchen]]"}}`), `drop` keys the table does not have. Every note gets `table` and a system `id`; with `relocate` (default true, unlike move_rows: notes become rows where the table keeps

  • align_relations

    Add the reciprocal links missing on a table's `inverse` link columns (e.g. Alice lists Carol in `friends` but Carol does not list Alice). Run it after declaring `inverse` on existing data; check_table reports such rows (code `inverse`). Single-value links already pointing elsewhere are conflicts (nothing written). The links it adds are checked like other writes (CHECKs that follow links, `ref_wher

  • alter_column

    Change a column's attributes (type, min/max/step, values, required, default, label, aliases, description, note, `ref_where`, `ref_by` (see list_link_targets); `null` removes an attribute, except `description`, which changes but never goes (null or "" is refused); `dense` true/false). Refused with the list of violating rows when existing values do not satisfy the new definition. A different scale m

  • alter_table

    Alter a table: move it (`catalog`, `schema`), rename it (`name`), change `partition` / `filename` patterns, `description` (changes, never goes: "" is refused), `aliases`, `exclude` folders, `row_template` ("" removes it), `history` (true | false | "default"), `autolink_target` (true | false | "default": may automatic links link its rows? default: yes, unless its rows are named by a date or a time)

  • batch

    Several writes that succeed or fail together. `operations`: `[{"op": ..., ...arguments}]` where `op` is a row operation (`insert_row`, `update_row`, `update_rows`, `delete_rows`, `merge_rows`, `move_rows`, `adopt_rows`, `recompute_columns`, `align_relations`, `restore_table`) or a DDL op (`create_table`, `add_column`, `alter_column`, \u2026), with the same arguments as the operation (an unknown on

  • check_table

    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

  • clone_tablewrite action

    CREATE TABLE `target` CLONE `source`: same definition plus independent copies of its rows (deep clone), optionally as of a `version` / `timestamp`. `copy_rows: false` copies the definition only (CREATE TABLE LIKE). `target`: `catalog.schema.table`, `schema.table` (in the source's catalog) or a name (source's catalog and schema). Useful for experiments, e.g. a sandbox copy in the `agent` catalog. T

  • comment_on

    COMMENT ON CATALOG / SCHEMA: set the `description` of a catalog (`catalog` alone) or of one of its schemas (`catalog` and `schema`) in metastore.yaml: what it holds, so agents pick the right place. `description` "" removes it. An unknown catalog or schema is refused with the existing ones. describe_database and `system.information_schema.catalogs` / `schemata` show it. Undo with `undo_migration`.

  • configure_database

    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:

  • create_viewwrite action

    Create (or `replace`) a view: a named select stored in metastore.yaml. Name it with the prefix `vw_` (e.g. `vw_open_tasks`): views share names and folders with tables. `query` takes the select_rows parameters (table, columns, where, order_by, limit, join, group_by, aggregates, expand; relative dates keep it current) and must run now. Or `query: {union: [{table, columns, where}, \u2026], columns, w

  • create_webhookwrite action

    Push row changes to a URL (a service that would rather be called than poll `list_changes`): batches of up to 100 events POSTed as `{webhook, events, last}`, signed with `X-Datanotes-Signature: sha256=<HMAC of the body>`, retried with backoff until a 2xx. Events are those of `list_changes` (hand edits with their `violations`; the hand edits the service has seen are recorded before it stops). Starts

  • define_basewrite action

    Create or replace a base: a named set of columns (same spec as `create_table`) that tables inherit, like a parent class (`bases` in `metastore.yaml`). Tables using it get the columns with the same name and meaning; `ref: "self"` means the inheriting table (e.g. a `parent` column with `hierarchy: true`). `bases` builds on other bases. Descriptions are required, as in create_table: `description` say

  • delete_rowswrite action

    Delete rows matching `where`. `mode`: "archive" (default, move to the table's archive folder) or "delete" (trash; content journaled for undo). `on_referenced`: "restrict" (default, refuse rows other notes link to), "set_null" (clear front matter links to them) or "ignore" (the links stay, to no row: an archived row is gone as a trashed one, so check_table reports them as `broken_link` and new link

  • delete_webhookwrite action

    Stop and remove a webhook (by `id` from list_webhooks).

  • describe_database

    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` \u2192 `sche

  • describe_history

    DESCRIBE HISTORY: the table's versions, newest first \u2014 `version`, `timestamp`, `operation` (CREATE TABLE, WRITE, UPDATE, DELETE, MERGE, ALTER TABLE, ADD COLUMNS, RESTORE, UNDO, \u2026; `EXTERNAL_EDIT` = changed outside the engine: an editor, git, sync), `operation_metrics` and `migration_id` (undo). An EXTERNAL_EDIT's `operation_metrics.violations` counts the rules this table's rows break bec

  • describe_semantic_index

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

  • describe_table

    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`, `b

  • drop_columnwrite action

    Remove a column from the schema and every row. Previous values are journaled; revert with `undo_migration`. Refused while a CHECK, `ref_where` or `ref_by` of any table reads the column (directly or through a link): the conflicts name them; drop or change them first. The schema changes only through operations like this one: never edit metastore.yaml by hand (no validation, no undo).

  • drop_constraintwrite action

    Remove the CHECK constraint `name` from `table`. The schema changes only through operations like this one: never edit metastore.yaml by hand (no validation, no undo).

  • drop_tablewrite action

    Drop a table. Refused while it has rows unless `mode: "archive"`, which removes the definition from `metastore.yaml` and moves all rows to the table's archive folder (nothing is hard-deleted; undo restores). The transaction log is kept: `restore_table` can bring it back. Refused while a CHECK that follows links, or a `ref_where` / `ref_by`, of another table reads this table through a link (link ta

  • drop_viewwrite action

    Remove a view from `metastore.yaml` (undo with `undo_migration`). The schema changes only through operations like this one: never edit metastore.yaml by hand (no validation, no undo).

  • graph_neighbors

    Direct neighbours of notes: what they link to (`out`) and what links to them (`in`, backlinks), with counts per edge label. `direction`: out, in or both (default). `from_nodes` selects the notes: `{"paths": [...]}` and/or `{"table": ..., "where": {...}}`. Edges are labelled with their link column (`people`, `event`, \u2026) or `link` for other links.

  • graph_path

    Shortest chain of links between two sets of notes (each `{"paths": [...]}` and/or `{"table", "where"}`): `found`, `length` and `path`: the steps (`from`, `label`, `direction`, `to`). `direction` both by default; `max_depth` default 6 (max 10).

  • graph_traverse

    Breadth-first walk over links from `from_nodes` (`{"paths": [...]}` and/or `{"table", "where"}`). - `direction`: out (default, follow links), in (follow backlinks) or both. - `edges`: edge labels to follow (link columns such as `people`, `event`, or `link`). - `tables`: return only notes of these tables; `through`: only walk on through these tables. - `min_depth` (default 1) / `max_depth` (default

  • infer_table

    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`

  • insert_rowwrite action

    Insert a row (new note). Values are validated against the columns; the note path comes from the table's `path`/`filename` patterns (e.g. an event logged today about last night lands in last night's day folder when you set `occurred_at` to last night). `body` is the note text. Generated / identity columns are computed (do not pass them); CHECK constraints are enforced. Returns `migration_id` (undo)

  • list_changes

    Change feed across all tables: numbered row changes (`seq`), oldest first, from engine writes and from hand edits (`source: external`). Each has `table`, `kind` (insert, update, delete, move, metastore, unreadable), `op` (the operation that made it), `path`, `row_id`, `changes` ({column: {before, after}}), `actor`, `migration_id`. Hand edits are compared in batches (0.7 s after the last vault chan

  • list_docs

    List the pages of the Datanotes documentation of this version (read offline, from the package): path, title and description, one per line. `prefix` keeps the pages under a folder (`guides/`, `reference/`, `start/`). Read one with read_docs(path).

  • list_folder

    The direct children of a vault folder: `{folder, folders, files}`, each a vault path, sorted; dot-files and dot-folders are left out. `folder` "" is the vault root. A missing folder is an error.

  • list_link_targets

    The rows a link column may point to, for one row: what an agent or a picker offers before writing the link. A link column can filter its targets: - `ref_where`: a `where` filter every target must match (`{"kind": {"in": ["area", "project"]}}`). - `ref_by`: a column of the row picks the targets' level: `{"column": "kind", "map": {"area": null, "project": ["area"], "workstream": ["project"]}}`: a wo

  • list_migrations

    The operation journal, newest first: `total` (the matching operations) and `migrations`, each with `migration_id` (for undo_migration), `op`, `summary`, `table` (when it was about one), `executed_at`, `notes_changed`, `files_changed`, `undone`, `undoes`, `files_failed`, `by` (the agent), and `members` (a batch's operations) or `batch` (the batch of an operation). Filters: `op` (e.g. "update_rows")

  • list_tables

    List every table: `name`, `catalog`, `schema`, `qualified` (`personal.metrics.mood` \u2014 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 \u2192 schema \u2192 table): read it freely, but it is read-only for age

  • list_webhooks

    Webhooks of the change feed: id, url, filter (tables, ops, columns, exclude_actor), `cursor` (last change delivered), `status` (ok, failing, disabled), `last_delivery`, `last_error`. Secrets are not shown.

  • merge_rows

    MERGE (upsert) `rows` into `table` by the key columns `on` (e.g. `["occurred_at"]` or `["id"]`): a row matching an existing one updates it (`when_matched`: "update" default or "ignore"), the others are inserted (`when_not_matched`: "insert" default or "ignore"). Date-times are compared after completion with the database time zone. A source key matching several rows, or repeated, is a conflict. One

  • move_rows

    Move rows matching `where` (required: `{}` is every row) to another table (e.g. split a domain out of `log` into its own table): sets each row's `table` to the destination, applies `rename` (`{"metric_distance_km": "distance_km"}`), `set` and `drop`, adds the destination's missing dense fields, and validates every row against the destination first. Keys unknown to the destination are reported, nev

  • read_docs

    Read a page of the Datanotes documentation of this version as Markdown, or one section of it: `guides/read-and-write/read-and-filter`, or `guides/read-and-write/read-and-filter#compare-values-with-operators` (the anchor of its heading, as in the docs links of the errors; the datanotes.dev addresses work too). Read a section rather than a whole page: list_docs lists the pages, search_docs finds the

  • read_note

    Read a note or another file of the vault: `{path, content, front_matter, tags, modified_at, created_at, size}`. `content` is the whole text, front matter included; `tags` are without `#`, from the text and the front matter; the times are in the database's time zone. A missing file is an error. `path`: vault-relative, forward slashes.

  • recompute_columns

    Bring generated and identity columns up to date (all rows, or only `paths`), e.g. after rows were edited by hand (an editor, git, sync) or a generated expression changed with `alter_column`. Also gives rows without an `id` a new one, and a duplicated note (same `id` as an older row) a new id. `new_ids=true` regenerates every id in scope (new ones on every call): only on the user's explicit request

  • rename_column

    Rename a column in metastore.yaml and on every row. Refused if `to_column` is already a column of the table; a row that has a stray `to_column` key with a different value is a conflict, and nothing is written. CHECKs, `ref_where` and `ref_by` that read the column (in this table, or through a link from another table: `parent.kind`) follow the new name. Views and note text that mention the old name

  • rename_value

    Rename one value of an enum column (e.g. `high` \u2192 `very high`) in metastore.yaml and every row, keeping its position, so an ordered scale is unchanged. CHECKs and `ref_where` conditions on the column (also through a link from another table) and `ref_by` levels / maps that name the value use the new one. Note text (queries, prose) is not rewritten. Refused if `to_value` already exists. Undo wi

  • restore_database

    RESTORE DATABASE to a `timestamp` (each table as of its last version committed at or before it) or to `before_migration` (a `migration_id` or a `batch`: every table as it was just before that operation ran \u2014 to rewind an agent's run). Every table that keeps a transaction log goes back, rows and definition: rows added since are deleted, changed rows get their old content, removed rows come bac

  • restore_table

    RESTORE TABLE to a `version` or `timestamp`: rows and definition return to that state \u2014 rows added since are deleted, changed rows get their old content, removed rows come back (a dropped table is re-created). History is not rewritten: the restore is a new version, and `undo_migration` reverts it. Refused (rows listed, with the way out) when the rows it writes, or rows that link to them, woul

  • search_docs

    Search the Datanotes documentation of this version for the sections on a topic, best first: each with the path to pass to read_docs (`guides/read-and-write/read-and-filter#compare-values-with-operators`), its page and heading, and a short excerpt. Words in a heading count most; a word matches in any form (`rows`, `row`) and its synonyms too (`revert` for `undo`). Syntax: a quoted phrase ("time tra

  • search_notes

    Plain-text search: every word of `query` must occur, case- and accent-insensitive, in the note's path or text; there are no operators. Returns `{query, results: [{path, score, matches: [{start, end, context}]}], total}`, best first: at most 200 notes (`total` counts them all) and 20 matches per note. `context_length`: characters of context on each side (default 100, max 1000).

  • select_rows

    Query rows: `{table, total, rows: [{path, ...}]}`. `table` may be a view, `system.information_schema.<catalogs|schemata|tables|columns|views|check_constraints>`, or `base:<name>` \u2014 every table that extends that base (e.g. `base:record`: all event-like tables), on the base's columns, each row tagged `_source` with its table. - `where`: as in update_rows; relative dates `"{today}"`, `"{today-7d

  • semantic_search

    Find notes by meaning, not exact words: `{query, results: [{path, score, heading, snippet, table?}]}`, one result per note (its best passage), best first. Use it for vague questions ("the dinner where we talked about moving", "what did I decide about the car") and to find the rows to read or update; then read_note / select_rows for the details. Filters: `tables` (qualified or short names), `folder

  • set_table_bases

    Set the bases a table inherits from (`bases`, in order; `[]` removes them). Inherited columns come after `id` and before the table's own columns. An own column with the name of an inherited one is replaced by the inherited definition (rows must fit it, its `ref_where` / `ref_by` included); a table may only restyle an inherited column (label, description, aliases, note, dense) with `alter_column`.

  • sync_semantic_index

    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 \u2014 ask first.

  • table_changes

    Change data feed between two versions (both included, end defaults to latest): one entry per row change with its values plus `_change_type` (insert, delete, update_preimage, update_postimage, metadata), `_commit_version`, `_commit_timestamp`, `_operation`, `path`. Use it to answer "what changed since \u2026" without diffing full tables.

  • undo_migration

    Revert a journaled table operation by its `migration_id`. Refused (nothing written) when any touched note changed since; the conflicts are listed. Also refused when the revert would leave rows breaking a CHECK that follows links or a `ref_where` / `ref_by` (rows it writes, or rows that link to them), listed like the refusals of other writes with the way out (fix the row, or drop the rule). The rul

  • update_rowwrite action

    Update exactly ONE row, addressed by its `id` (the system UUID) or its `path`; refused when the row does not exist (or id and path disagree). Same validation, journal and history as `update_rows`. - `set` / `unset`: columns to set or remove. - `body`: replace the whole note body; or edit it keeping the rest: `body_sections` `{"History": "\u2026"}` replaces the text under that heading (any level, u

  • update_rowswrite action

    Update every row matching `where` (required: `{}` is every row). `where`: keys AND-ed; values are equality or operators eq, ne, gt, gte, lt, lte, in, contains, icontains (case/accent-insensitive, also inside lists \u2014 use it for names and aliases), exists, within (a hierarchy link: that row and everything below); combine with `or` / `and` / `not` (nestable); `path` is a pseudo-column. A dotted

  • vacuum_tablewrite action

    Delete transaction-log history older than `retain_from_version` (default: keep only the latest version); time travel before it becomes impossible. Rows are not touched. `dry_run` defaults to true: it lists the log files that would go. Only on the user's explicit request.

Public scan report

scanner v0.1.10 · 2026-10-12 · same rubric, same numbers if you re-run it

no findings
  • Code scan20 source files scanned25/25
  • –Live reliabilityno gateway calls yet and no remote to proben/a
  • –Tool poisoningtools not inspected (local package is not executed); not countedn/a
  • Auth qualitylocal package, no credentials required12/15
  • Maintenancelast push 0 days ago15/15
  • Maintainer identityregistry namespace matches repository owner; GitHub account older than a year8/10
Overall 92/100. Components that don't apply are left out of the denominator. Any critical finding is an F.RubricAppeal a findingJSON

How Datanotes compares

Against every graded Databases MCP server, from our own scans and uptime checks. Updated after each scan run.

Safety score
92/100
higher than 90% of 803 Databases servers
Tools
56
the typical Databases server has 8
Tools that change things
25%
typical: 10%. Fewer write tools means less an agent can break
Downloads a week
1,844
more than 95% of 315 Databases servers with a package

What its tools let an agent do: 33 read · 6 create · 10 change · 6 delete · 1 send or post

Install Datanotes in Claude Code, Cursor or VS Code

Runs npx -y datanotes on your machine. Read the scan report first; the gateway never runs local packages.

claude mcp add datanotes -- npx -y datanotes
Add to Cursor

What the publisher says

From the Datanotes repository's README, as published. We do not edit it. Read it on GitHub

Datanotes

Datanotes is the open-source database engine for Markdown: it runs a folder of notes as typed, validated tables that your programs and AI agents query, write and undo over MCP or HTTP, while every row stays a plain file you own.

<!-- Hero GIF goes here: an agent writes a row over MCP, the engine refuses a bad value and explains the fix, then the note opens as plain Markdown. -->

Documentation: datanotes.dev

Why Datanotes

  • Agents can't write garbage. Every write is checked against its table: types, links, unique values and CHECK constraints. A refused write changes nothing. Its answer says which value broke which rule and how to fix it.
  • Every change can be undone. The engine journals every write it makes. It records who made it: the agent, its session and its token. undo_migration takes any change back.
  • It's still just Markdown. A row is a note, and its front matter keys are the columns. Read it, edit it, grep it or commit it to Git. The engine reads your hand edits and checks them too.
  • Local first. Datanotes is Apache-2.0 and runs on your machine. Nothing leaves it unless you turn that feature on.

When not to use it

Datanotes keeps every row as a file, so it isn't a replacement for SQLite or Postgres. Choose a classic database for:

  • Large analytical datasets
  • High write throughput
  • Many concurrent writers on one folder

Datanotes is comfortable at 10,000 notes. At 50,000 notes, the engine takes 22 to 115 seconds to start.

Quick start

You need Node.js 22 or newer. On Windows, use Node.js 24.16 or newer, or 26.1 or newer.

Start the engine on a folder, which becomes your database. It can be empty, or hold notes already:

npx -y datanotes serve --database your_database_folder

Run Datanotes on your notes walks you through your first table.

Connect your agents

Agents reach the engine through its Model Context Protocol (MCP) server, datanotes mcp. It uses the engine that runs on the folder, or starts one. Every client runs the same command:

npx -y datanotes mcp --database your_database_folder

Claude Code

claude mcp add datanotes -- \
  npx -y datanotes mcp --database your_database_folder

Claude Desktop

Add the server to claudedesktopconfig.json:

{
  "mcpServers": {
    "datanotes": {
      "command": "npx",
      "args": [
        "-y", "datanotes", "mcp", "--database", "your_database_folder"
      ]
    }
  }
}

Cursor

Add the server to .cursor/mcp.json in your project, or to ~/.cursor/mcp.json:

{
  "mcpServers": {
    "datanotes": {
      "command": "npx",
      "args": [
        "-y", "datanotes", "mcp", "--database", "your_database_folder"
      ]
    }
  }
}

VS Code

Add the server to .vscode/mcp.json in your workspace:

{
  "servers": {
    "datanotes": {
      "type": "stdio",
      "command": "npx",
      "args": [
        "-y", "datanotes", "mcp", "--database", "your_database_folder"
      ]
    }
  }
}

Codex

Add the server to ~/.codex/config.toml:

[mcp_servers.datanotes]
command = "npx"
args = ["-y", "datanotes", "mcp", "--database", "your_database_folder"]

Windows

On Windows, clients start npx through cmd /c. For Claude Code, outside Windows Subsystem for Linux (WSL):

Shortened. The full README is on GitHub.

Nothing above is checked by us. What we check is on the safety report.

Datanotes: common questions

Is Datanotes MCP server safe?
Yes, by our scan: it is graded A (92/100). Read the Datanotes safety report
How do I install Datanotes?
It runs on your machine. Copy the Claude Code, Cursor, VS Code or Claude Desktop config from the install section.
Does Datanotes need an API key?
Not as far as the registry entry and our scan can tell: no credentials are declared or required.
Is Datanotes maintained?
The last commit was 20 days ago (2026-10-12). The latest release is v3.0.0.
What can I use instead of Datanotes?
Servers from other publishers that do the same job: Airtable MCP server, Microsoft Access Database MCP server and Emerald MCP server. Compare all Datanotes alternatives.
How does Datanotes compare with other Databases MCP servers?
safety score 92/100 (higher than 90% of 803 Databases servers); tools 56 (the typical Databases server has 8); tools that change things 25% (typical: 10%. Fewer write tools means less an agent can break). Full comparison.

Alternatives to Datanotes

Same job from other publishers: the closest match first, then the best rated.

All Datanotes alternatives →
  • Airtable
    Read and write access to Airtable database schemas, tables, and records.
    B
  • Microsoft Access Database
    Read and edit Microsoft Access databases (.accdb/.mdb) - forms, VBA, tables, queries. Windows.
    A
  • Emerald
    The database under the chat: a local SQLite file a model asks for rows, not notes to re-read.
    A
  • sqlite-graph-memory
    Recall over your markdown notes: vector search plus your [[wikilinks]] as a graph, in SQLite.
    A
  • CogniCore
    Memory, reflection and safety for AI agents. Hosted or local, no vector database.
    A