NotePlan / NotePlan/noteplan-mcp

Space notes created after server start are readable but not writable

Open
#9 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
16
Forks
4
PR merge metrics
No merged PRs in 30d

Description

Summary

Any teamspace note created after the MCP server starts can be read but cannot be
written. Every write form fails with Note not found: <id> — including the exact id
that a read returns successfully seconds earlier. Restarting the MCP server fixes it
until the next note is created.

In practice this means: create a note in a space, then try to write to it in the same
session, and the write fails.

Reproduce

  1. Start the MCP server.
  2. In NotePlan (or any other process), create a note in a teamspace — e.g. let a
    scheduled job write today's teamspace calendar note.
  3. noteplan_get_notes by that note's id → succeeds, full content returned.
  4. noteplan_edit_content (append/insert) on the same note → fails,
    Note not found: <id>. Same for noteplan_paragraphs (which surfaces it as
    Cannot read properties of undefined (reading 'toLowerCase')).
    Addressing by date, filename, spaceId, or direct id all fail identically.
  5. Restart the MCP server, retry step 4 unchanged → succeeds.

Possible Cause

Space reads go through the HTTP bridge to the running app, so they are always
fresh. Space writes resolve the row through sql.js
(sqlite-writer.tsgetSpaceNode()sqlite-reader.ts getDatabase()).

Per sqlite-loader.ts's own comment, sql.js is in-memory and "loaded at startup after
checkpointing the WAL". That snapshot is taken once and never refreshed, while NotePlan
continues writing to the real file via WAL. So rows the host app creates after startup
are permanently invisible to the writer, and getSpaceNode() throws Note not found.

Suggested fix

Re-checkpoint and reload on a miss, using the machinery already present:

  1. closeDatabase() — also reset dbChecked = false and cachedDbPath = null, so a
    subsequent getDatabase() genuinely reopens.
  2. getSpaceNode() — on a miss, reload the snapshot (checkpointWal() + reopen) and
    re-query once before throwing.

Both changes sit on the failure path, which today is an unconditional throw, so they
can't regress the success path. A cheaper variant, if a reload per miss is too eager:
reload at most once per N seconds.

Environment

  • NotePlan 3.21.1 (build 1512), Setapp
  • macOS 26.5.2 (arm64)

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Read sqlite-loader.ts, sqlite-writer.ts around getSpaceNode(), and sqlite-reader.ts around getDatabase(); trace how the startup WAL snapshot is opened and how a missing row is handled. Reproduce the post-start teamspace-note workflow, then verify that a miss refreshes the snapshot and the same note can be written without restarting the MCP server.

Written by the indexing model from the issue text.

Assessment

Tech stack
sqlite, typescript
Domain
database
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
74/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.