← Writing
On disk

Your notes don't need an MCP server

In April Bear shipped a CLI, a Claude connector and an MCP server so AI tools can reach your notes. I haven't built any of those for Margin, and I don't think I need to.

Bear 2.8 came out in April with three things for people who want AI tools near their notes: BearCLI, which can "read, search, create, and edit notes from outside the app", a Claude connector, and an MCP server for Claude Code and IDEs.

I like Bear, and I think they built the right thing for Bear. It did make me look at why they needed it though, because Margin has none of the three and agents work with it fine.

Why Bear needs a bridge

Bear's notes are Markdown, but they don't live in Markdown files. They live in one SQLite database at ~/Library/Group Containers/9K33E3U3T4.net.shinyfrog.bear/Application Data/database.sqlite.

Reading it was always possible. Bear's own FAQ says it's "safe to access the database for reading only", and people had written unofficial MCP servers that did exactly that more than a year before 2.8. Writing is the problem. The same FAQ asks you to quit Bear before changing anything, because changes "can cause crashes or problems in Bear, especially on flags and foreign keys".

So an agent could look but not touch. My guess is that this is what the CLI and the MCP server are for: they put the app in the middle, so every write goes through code that knows the schema. I haven't seen how they're built, but if your notes live in a database I can't think of another safe way to do it.

What a folder gives you for free

A space in Margin is a folder, and each note is one .md file. So an agent with a shell already has everything it needs:

cd ~/Margin/Work
claude "find every note that mentions the migration and list what's still open"

rg searches it, git versions it, and Claude Code or codex edit it the same way they edit code. There is nothing to install, and nothing that has to keep up with the app's releases.

The usual objection is scale: a folder can't filter or sort, so at a few thousand notes the agent is reading everything into context. It isn't. It greps first and reads the handful of files that matched, the same way it works in a codebase with a few thousand source files.

Margin watches the folder, so an edit made by an agent shows up in the app a moment later. The one case that needs care is an agent writing to the note you have open, which is the same problem as editing it in vim while Margin is running. I wrote about how that works in The watcher that cried delete.

What the app knows that the folder doesn't

An MCP server can know things a folder can't: tags, backlinks, which note a link goes to. This is what Margin keeps outside the notes so far. It's one file per space, .margin/meta.json, and it holds:

  • which notes are pinned
  • the order you dragged notes into
  • which lines you folded
  • which tags you pinned to the sidebar
  • where each trashed note came from, so restore puts it back

Tags aren't stored anywhere, they're read from the note text. Links are plain [Title](slug.md), the same form GitHub, Obsidian and VS Code follow. The meaning is in the files, and the sidecar only holds how you arranged them. An agent doesn't need to know what's pinned or folded to answer a question or work on a note.

One thing to know: the trash is .margin/trash/, inside the space. An agent that runs grep -r will find your deleted notes too. Tell it to skip dot folders, or let it, depending on whether you want them back.

What happens when an agent gets it wrong

Agents can edit the files. The more interesting question is what happens when they do something the app didn't expect.

If it deletes the frontmatter: every note carries a margin_id there so the app can follow it across renames. Remove it and Margin gives the note a new id next time it reads it, keeping the file's modified date so it doesn't jump to the top of your list. Links still work, because they point at the filename, not the id. What you lose is the pin, the position and the folds, because the sidecar knew the note by its old id.

If it copies a note: two files now share an id. Margin keeps it on the first one and gives the copy a new one.

If it renames a note: this is the real gap, and not only for Margin. Someone on XDA pointed Claude at their Obsidian vault without an MCP server and found that Obsidian fixes wikilinks for renames made inside the app and does nothing for a rename from outside. Margin is the same: rename a note in the app and every link to it gets rewritten, rename it with mv and nothing does. The links mostly keep working, because when the filename doesn't match, Margin looks for the one note whose title matches the link text:

src/lib/pageLink.tsts
const wanted = label?.trim().toLowerCase();
if (!wanted) return undefined;
const byTitle = live.filter((n) => noteTitle(n).toLowerCase() === wanted);
return byTitle.length === 1 ? byTitle[0] : undefined;

If two notes share that title, or the agent changed the title too, the link shows as a missing page rather than a guess. That's the one place where a command on the app side would be worth having.

The CLI I did build

Margin does have a margin command (Command Palette, "Install margin command in PATH"). It doesn't touch your notes. The comment at the top of src-tauri/src/cli.rs says so: "Nothing here reads or writes a note."

margin open ~/Margin/Work/standup.md
echo "- ask about the deploy" | margin new --title "Monday" --tags work
margin search migration

Each of those turns into a margin:// link and hands it to the app. The agent reads and writes the files directly, and uses the CLI when it wants to show you something or leave you a note. Bear's CLI gets you to the notes, this one gets you to the app.

A margin rename that moves the file and fixes the links would be the first command that writes. After the last section I think it should probably exist.

Permissions

The strongest argument for an MCP server is scope. The server decides what the agent can see and do, so you could expose one tag and nothing else, or reads and no writes.

That only limits an agent with nothing else though. Claude Code has a shell, and if it can run sqlite3 it can read Bear's database no matter what the MCP server allows. What matters is what the process can reach on disk, and that's the same in both designs.

With folders, that boundary is a directory. Start the agent in ~/Margin/Work and your personal space isn't in its working directory. Claude Code and codex both already understand paths in their permission settings, so I didn't have to design a permission model. There already is one.

If you want to see what an agent did, git init inside the space. Every change is a diff you can read and revert, which an MCP write tool would have to build for itself. It's also how AI edits work inside Margin: every change arrives as a diff you accept or reject.


None of this is a new idea. Steph Ango's File over app from 2023 is about files outliving the tools that made them, and it's why Margin stores notes as plain files at all. What I didn't expect is that the same decision would turn out to be the integration too. If you keep notes next to a terminal: what would you want a margin command to do that a shell can't?

Margin is the app this came out of
Local-first Markdown notes for the Mac. Free while it is alpha.
Download the alpha
More writing
Parsing
The edge cases I hit building a live-preview Markdown editor

I assumed Markdown would be the easy part of building a notes app. Pipes, round-tripping, paste and the cursor each ate a weekend.

23 Aug 2026·4 min·/blog/markdown-edge-cases
Parsing
Three things I decided not to parse

Unmatched embeds, tables that refuse to be repaired, and display options with nowhere to live. Sometimes declining to parse is the safer failure.

16 Aug 2026·2 min·/blog/not-to-parse
On disk
The watcher that cried delete

Some editors save by replacing the whole file, so a file watcher briefly sees a deletion. Believe that event and your app tells someone their note is gone.

8 Aug 2026·3 min·/blog/atomic-saves