My org-roam knowledge base is the center of how I think and work. But it lives in Emacs, which means I can only capture ideas when I’m at my computer. I wanted a way to feed my second brain from anywhere, using just my phone—but I refused to put my notes in someone else’s cloud. The solution had to be entirely self-hosted. What I built combines Matrix for messaging, n8n for orchestration, and an MCP server that bridges to org-roam, all running on my own infrastructure.

The Capture Problem#

The best ideas rarely arrive at convenient times. Standing in line, walking the dog, half-asleep at 2 AM; these are when insights strike. Traditional approaches fail here:

  • Emacs requires a proper keyboard and focused attention
  • Note apps create silos that need manual integration later
  • Voice memos pile up unprocessed

I wanted something that would slot directly into my org-roam workflow with zero friction. Type a message, and it appears in my knowledge base, properly structured and linked.

Architecture#

The system has four layers:

Matrix (Element app)
n8n Workflow Engine
org-roam MCP Server
Emacs + org-roam files

When I send a message to a dedicated Matrix room, n8n receives it via webhook, parses the command, calls the appropriate MCP tool, and sends a response back to Matrix. The MCP server communicates with a running Emacs instance via emacsclient, so changes appear immediately in my org-roam database.

Structured Capture Commands#

I settled on slash commands that mirror my org-roam node types:

Command Creates Example
/note Unstructured capture /note Look into vector databases for embeddings
/person Person node /person Jane Smith - met at conference, works on ML
/project Project with next action /project Home server migration - order new RAM
/idea Idea with one-liner /idea Use git hooks for automatic org-roam sync
/journal Daily note entry /j Finally figured out the caching issue
/blog Full blog post draft /blog MI60 cooling solutions

The /person command is particularly valuable. When I meet someone, I can immediately capture context while it’s fresh:

/person Alex Chen - DevOps lead at Acme Corp, interested in
GitOps workflows, mentioned they're hiring

This creates a properly structured person node with the context field populated, ready for follow-up items later.

The MCP Bridge#

The org-roam MCP server exposes Emacs Lisp functions via HTTP. Each capture command maps to an MCP tool:

Command MCP Tool Elisp Function
/note log_to_inbox sb/inbox
/person create_person sb/core-create-node
/project create_project sb/core-create-node
/idea create_idea sb/core-create-node
/search semantic_search org-roam-semantic-get-similar-data

The MCP server runs on the same machine as Emacs, communicating via emacsclient --eval. This keeps everything local; my notes never leave my infrastructure.

Proactive Surfacing#

Capture is only half the equation. A second brain should also surface relevant information without being asked. Every morning at 7 AM, a scheduled n8n workflow calls get_digest_data and sends me:

  • Active projects with their next actions (top 3)
  • Pending follow-ups listing people I need to contact
  • Stale projects that have not been touched in 5+ days
  • Dangling links where I mentioned someone who does not have a person node

This arrives as a Matrix message alongside my other notifications. The digest keeps projects from falling through the cracks and reminds me of commitments I have made.

On Sundays, a weekly review summarizes everything captured that week, broken down by type. It is a forcing function for processing my inbox and updating project statuses.

Blog Post Creation with Claude Code#

The most recent addition is /blog, which creates full blog post drafts. This one is different; instead of calling the MCP server directly, n8n SSHs to my desktop PC and invokes Claude Code:

Matrix: /blog MI60 cooling solutions

n8n: SSH to workstation
     └─→ claude --dangerously-skip-permissions -p "/blog-post MI60 cooling..."
         └─→ Creates ~/org-roam/blog/mi60-cooling-*.org
             └─→ Returns markdown content

Matrix: [Full blog post draft displayed in chat]

Claude Code has access to my entire codebase context via CLAUDE.md, so it writes posts that match my style and reference my actual infrastructure. I can review the draft in Matrix, then open the org file in Emacs to refine it before export.

Why This Architecture?#

The single biggest factor driving these decisions was self-hosting. My second brain contains everything: work projects, personal notes, contacts, ideas that might become something. The last thing I wanted was that data sitting on someone else’s servers. Cloud-hosted solutions are convenient until they change their terms, get acquired, or shut down. My notes need to outlive any particular service.

This ruled out the obvious alternatives:

Obsidian Sync would give mobile capture but requires their cloud for sync. It would also create a separate system from org-roam.

Notion, Roam Research, etc. are entirely cloud-hosted. Non-starters.

Logseq has better mobile support and can work locally, but lacks org-roam’s mature ecosystem and my years of accumulated workflow.

Plain text files via Syncthing would stay local but would not integrate with org-roam’s database, backlinks, or my custom node types.

The n8n + MCP approach keeps everything on my infrastructure while preserving org-roam as the single source of truth. Matrix runs on my server, n8n runs on my server, the MCP server talks to Emacs on my workstation. Nothing leaves my network. I can access it from anywhere, but the data stays home.

What I Learned#

Building this taught me a few things:

  1. MCP solves the quotation problem. My first attempt called Emacs Lisp directly via shell commands in n8n. This quickly became a nightmare of escaped quotes when note content included apostrophes or special characters. Wrapping everything in an MCP server with proper JSON payloads eliminated the escaping issues entirely. It also provides a clean abstraction; any tool can integrate with org-roam now, not just n8n.

  2. Structured capture beats free-form. Having distinct commands for people, projects, and ideas forces me to think about what I am actually capturing. This pays off when searching later.

  3. Proactive surfacing changes behavior. The daily digest is more valuable than I expected. Seeing stale projects every morning creates gentle pressure to either update them or mark them done.

  4. Local LLMs enable new workflows. The /blog command would not be practical with API calls. Having Llama 3.3 70B running locally means I can generate substantial content without latency or cost concerns.

The system continues to evolve. The org-roam MCP server now has semantic search powered by local embeddings, so /search finds conceptually related notes, not just keyword matches. And the daily digest might soon include “notes you should probably link” based on embedding similarity.

But even in its current form, it has fundamentally changed how I capture and retrieve knowledge. The gap between having a thought and recording it in my second brain has shrunk to the time it takes to type a message.