cd ../writing
Engineering Jun 25, 2026 7 min read

My Notes, Everywhere: An n8n MCP Server for Obsidian

Building a bridge from my notes to any AI client, and knowing when not to.

Safwan Siddiq
Safwan Siddiq
Automation engineer · KL

My notes, everywhere

I’d already wired my Obsidian vault into Claude Code and Cowork. At my desk, an AI agent could read my notes and help me write against them. That worked well, and it never left the desk.

The trouble is that most of the moments I want my notes, I don’t have a laptop open. Standing in a queue. In the back of a car, half-remembering something I wrote down weeks ago. What I have then is a Claude thread on my phone with no connection to anything I’ve ever written.

So I set a narrow goal: open a chat on my phone, describe a situation, have Claude pull from my own notes, and when it makes sense, write back into them. Access to my own knowledge base, from the device I actually carry.

This is how it went together. I’m including the bugs, because the bugs taught me more than the parts that worked.

The mental model

Four layers. Once you see them, the rest is detail.

Obsidian → GitHub → n8n → Claude chat.

Obsidian is where I write. GitHub holds a synced copy of the vault; it was already serving as my backup, and it gives me a clean API plus free version history. n8n runs a small server that exposes the vault to an AI as a set of callable tools. Claude chat is the surface I touch from my phone.

The bridge is the interesting layer. It’s an MCP server. MCP (Model Context Protocol) is the standard for handing an LLM tools it can call, and the payoff of building the bridge this way is that I build it once and any MCP client can use it. Claude chat today, Claude Code, whatever I’m using in a year.

Designing the tools

A knowledge base needs three verbs, so the AI got three tools.

  • list_vault_notes returns the whole file tree. The map.
  • fetch_vault_note reads one note in full.
  • write_vault_note creates a new note or overwrites an existing one.

One constraint shaped everything, and it’s worth stating plainly: there’s no search. The tools list paths and read a named file. They can’t look inside my notes for a phrase. Discovery leans on two things instead. Good filenames, and an index note, one file that lists what exists with a short “use this when…” next to each entry. The model reads the index first, decides what’s relevant, then fetches it. Cheap, and it works better than I expected.

The build, and the bugs

Reading was easy. Writing is where it got interesting.

The tool that never ran. My update-a-note tool had never executed. Not once. It sat in the tool list looking healthy. Its inputs were wired to placeholder text instead of the values the AI was passing, and the workflow behind it had never been published into an active version. So it was callable and completely dead at the same time. A tool showing up in the menu tells you nothing about whether it runs. The execution log does.

The misdiagnosis. When the write finally threw an error, I asked the chat model what broke. It told me, with total confidence, that a specific parameter mechanism had failed. It hadn’t. The execution log showed that exact mechanism working fine, and the real fault sat somewhere else. The model was reading symptoms and guessing; the log was the record of what actually happened. I stopped letting the AI diagnose its own plumbing after that.

The silent encoding trap. GitHub wants file content base64-encoded, and I’d written that encoding inline in the HTTP request. It kept returning invalid JSON. n8n’s expression sandbox doesn’t reliably run certain JavaScript, things like Buffer or spreading an object, so my expression was quietly evaluating to nothing. Moving the logic into a Code node fixed it, because a Code node runs real Node.js and the HTTP step just passes the finished string through. Sandbox JavaScript and runtime JavaScript are not the same language, even when they look identical.

One thing went right, and I’m a little proud of it. Instead of a separate create tool and update tool, there’s one. GitHub identifies an existing file by a sha, so the tool looks the file up first. Found a sha, it’s an update. No sha, it’s a create. One tool, both behaviours, and no way for the model to reach for the wrong one.

The use case that justified it

The push to finish came from a friend. He keeps a library of analytical frameworks and runs his problems through them in another tool: describe a situation, it picks a framework and applies it. He wanted that in Claude chat instead, for the model choice and the flexibility, with his own library underneath.

That’s exactly what I’d built. To test it, I dropped a set of frameworks into the vault. Variance Analysis, SWOT, Porter’s Five Forces, DuPont Analysis, Cost-Volume-Profit. I wrote the index note and gave a Claude project one instruction: when I describe a situation, read the index, pick the frameworks that fit, fetch them, apply them step by step, and end with a recommendation.

Then I gave it a messy one. A division that missed its profit target even though volume was up. It read the index and went for Variance Analysis and Cost-Volume-Profit, the two that actually diagnose a volume-up, profit-down problem. It skipped Porter’s Five Forces on purpose, with a clear reason: an industry-structure framework has nothing to say about an internal profit variance. Then it fetched the two it chose and produced a genuinely useful breakdown. The moment it declined Porter’s, on its own, with a reason that held up, is the moment I believed the thing worked.

When not to build this

Here’s the part that matters. I built all of it, and I told my friend not to.

His need is narrow and mostly fixed. Mine isn’t. If you only want a chat that applies a set list of documents, you don’t need a server at all. There’s a ladder, and most people should stop before the top rung.

  • Claude Projects. Upload your knowledge into a project. No infrastructure to run, and the best built-in search of the three. Works on phone and web. Right for most people.
  • A GitHub repo with the GitHub connector. A living, version-controlled library you can write back to, still with no server to run.
  • Your own MCP server, which is what I did. Worth it when your notes are a living, central knowledge base you want every surface to read and write, and especially when it plugs into a wider automation setup the way mine feeds and is fed by other workflows.

I should be straight about the cost of my route. I now own uptime and the occasional reconnect, plus bugs like the three above. My setup still has that no-search limitation that Projects solve out of the box. Fancier isn’t better. Mine is right for me for specific reasons, not because more plumbing wins.

What’s next

The obvious gap is search. I lean on filenames and an index, which holds up until a vault gets big, and mine is getting big. The next build is a real search tool so the AI finds things by meaning instead of guessing at paths.

The core of it is smaller than this writeup makes it sound. List, read, write, over an API I already had. If your notes already sit in something with an API, and most do, the distance to “everywhere” is shorter than the plumbing suggests.

Found this useful? Reply by email — I read every one. $ get in touch →
// keep reading