Skip to content

feat(examples): SQLR-40 Node.js MCP-powered notes assistant#141

Merged
joaoh82 merged 1 commit into
mainfrom
sqlr-40-nodejs-mcp-notes
May 16, 2026
Merged

feat(examples): SQLR-40 Node.js MCP-powered notes assistant#141
joaoh82 merged 1 commit into
mainfrom
sqlr-40-nodejs-mcp-notes

Conversation

@joaoh82
Copy link
Copy Markdown
Owner

@joaoh82 joaoh82 commented May 16, 2026

Summary

  • Adds examples/nodejs-notes/ — a Node.js CLI that ingests a folder of markdown notes into SQLRite, then exposes the database to Claude Desktop / any MCP client via sqlrite-mcp --read-only. End-user effect: sqlrite-notes init ~/Documents/notes + one block of JSON into claude_desktop_config.json, then ask Claude about your notes (bm25_search / vector_search / query / ask all light up automatically).
  • Pairs naturally with SQLR-39's Python agent: SQLR-39 is an agent we wrote using SQLRite as memory; SQLR-40 is Claude itself driving SQLRite via the MCP server we ship. Two angles on the agentic story from the same engine.
  • Hits the engine's most distinctive features end-to-end: hybrid HNSW + BM25 retrieval (canonical fused ORDER BY shape from docs/fts.md) and the first-party MCP server. Default embedder is a deterministic offline hash bag-of-words — the demo works fully offline, no API key. --embedder openai switches to text-embedding-3-small (with dimensions: 384 to match the schema).

What's in it

examples/nodejs-notes/
├── README.md             # architecture, Claude Desktop config snippet, demo
├── bin/sqlrite-notes.mjs # entry — calls src/cli.mjs
├── src/
│   ├── cli.mjs           # init / refresh / search / serve / stats / config
│   ├── db.mjs            # schema, migrations, hybrid retrieval SQL
│   ├── ingest.mjs        # plan → delete → reopen → insert pipeline
│   ├── chunker.mjs       # frontmatter + heading-aware chunking
│   ├── embeddings.mjs    # hash (offline) + OpenAI embedders
│   ├── search.mjs        # debug retrieval driver
│   ├── serve.mjs         # spawn sqlrite-mcp --read-only
│   ├── claude-config.mjs # Claude Desktop snippet renderer
│   ├── sqlutil.mjs       # q() / ident() — engine doesn't bind ? yet
│   └── config.mjs        # defaults, path resolution
└── test/                 # 40 node --test tests + 3 markdown fixtures

Pins `@joaoh82/sqlrite@^0.10.0` — installs with prebuilt napi-rs binaries for macOS-arm64, Linux x64/arm64, and Windows x64. No Rust toolchain required on the user's side; `sqlrite-mcp` is the one Rust binary they install separately (or `SQLRITE_MCP_BIN=/path` overrides the lookup).

Engine bug surfaced

`refresh` (DELETE + re-INSERT through an HNSW chunk index) panicked inside `DistanceMetric::compute` with `index out of bounds: the len is 0 but the index is 0`. Worked around in `src/ingest.mjs` by splitting ingest into delete-phase → close/reopen → insert-phase — the reopen forces a clean HNSW rebuild on next open. First-time `init` skips the reopen entirely (only paid when there are actual deletions). Filed as SQLR-8 with a 10-line reproducer; once it lands, `src/ingest.mjs` can drop the `db.reopen()` call.

Cross-references updated

  • `README.md` — new "End-to-end example apps" subsection listing both SQLR-39 and SQLR-40.
  • `examples/README.md` — new "Running the Node.js notes assistant" section + table row.
  • `web/src/app/examples/page.tsx` — second card on `sqlritedb.com/examples` with the right feature tags + matching JSON-LD entry.

Test plan

  • `npm install` against the published `@joaoh82/sqlrite` resolves prebuilt binaries (no `node-gyp`).
  • `npm test` — 40/40 tests pass (chunker, sqlutil, embeddings, db integration, ingest end-to-end against fixtures, serve binary lookup, claude-config snippet).
  • `node bin/sqlrite-notes.mjs init test/fixtures` smoke-tested — ingests 3 files, prints the Claude Desktop snippet.
  • `node bin/sqlrite-notes.mjs search "marathon training"` returns the right fixture chunk.
  • `node bin/sqlrite-notes.mjs refresh test/fixtures` returns `0 updated, 3 unchanged, 0 deleted`.
  • `node bin/sqlrite-notes.mjs stats` returns the correct row counts.
  • `serve` errors cleanly when `sqlrite-mcp` isn't on `PATH`.
  • Workspace cargo build + test + clippy + doc green (`--exclude sqlrite-desktop --exclude sqlrite-python --exclude sqlrite-nodejs --exclude sqlrite-benchmarks` — matches CI).
  • Follow-up — manual verification against Claude Desktop: wire the printed snippet into `claude_desktop_config.json`, restart Claude Desktop, run the demo conversation from the README. Out of scope for the PR itself; record a screencast as part of SQLR-38's "card on sqlritedb.com" deliverable once the umbrella's marketing pass lands.
  • Follow-up — engine bug SQLR-8 fixed → drop the `db.reopen()` workaround in `src/ingest.mjs` and the corresponding "Known limitations" bullet in the README.

🤖 Generated with Claude Code

Adds `examples/nodejs-notes/` — a Node.js CLI that ingests a folder
of markdown notes into SQLRite, then exposes the database to Claude
Desktop (or any MCP client) via `sqlrite-mcp --read-only`. End user
effect: `sqlrite-notes init ~/Documents/notes` + one block of JSON
into Claude Desktop's config, then ask Claude about your notes.

Hits two of the engine's most distinctive features end-to-end:
hybrid HNSW + BM25 retrieval (the canonical fused `ORDER BY` shape
from `docs/fts.md`) and the first-party MCP server. Default
embedder is a deterministic offline hash bag-of-words so the demo
works fully offline; `--embedder openai` switches to
`text-embedding-3-small` for real semantic recall.

Surfaced engine bug SQLR-8 during the `refresh` flow — HNSW panics
on DELETE + INSERT within the same connection — and worked around
it by splitting ingest into delete-phase → close/reopen →
insert-phase. The reopen hop only runs when there are actual
deletions, so first-time `init` skips it. README "Known
limitations" documents it.

Tests: 40 unit + integration tests via `node:test`, all passing
against the prebuilt `@joaoh82/sqlrite@^0.10.0` napi-rs binding.
Integration tests skip cleanly when the binding isn't installed.

Cross-references updated: top-level README points at both
SQLR-39 (python-agent) and SQLR-40 (nodejs-notes) under "End-to-end
example apps"; `examples/README.md` gains a Node.js notes
assistant section; `web/src/app/examples/page.tsx` adds a card for
the new example with the right feature tags and structured-data
entry.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented May 16, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
rust-sqlite Ready Ready Preview, Comment May 16, 2026 4:04pm

Request Review

@joaoh82 joaoh82 merged commit a31fb06 into main May 16, 2026
18 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant