Featured

Deploy OpenClaw in 60 seconds — 20% off logoDeploy OpenClaw in 60 seconds — 20% off

Launch OpenClaw on Hostinger in about 60 seconds and keep your agent live 24/7. Our referral link gives you 20% off, no coupon code needed.

Launch on Hostinger
Run your Hermes agent on Hostinger, fully managed logoRun your Hermes agent on Hostinger, fully managed

Launch Hermes on Hostinger in one click, fully managed, no VPS knowledge needed. Use code ZACAARON10 for 10% off.

Launch on Hostinger
Crawl and scrape any site into clean data, 10% off logoCrawl and scrape any site into clean data, 10% off

Firecrawl crawls and scrapes any site into clean markdown for your agent. Get 1,000 free credits, and new users get 10% off their first purchase.

Try Firecrawl free
6,000+ web scrapers for your AI agent, start free logo6,000+ web scrapers for your AI agent, start free

Apify gives your agent live web data: 6,000+ prebuilt scrapers and actors, MCP-ready. Sign up free with $5 in usage credits.

Try Apify free
One API to scrape, enrich, and extract the internet. logoOne API to scrape, enrich, and extract the internet.

Context.dev gives your agents a single API to scrape, enrich, and extract live web data — no proxies, no parsers, no maintenance.

Start building free
SetupClaw: done-for-you OpenClaw for founders & exec teams logoSetupClaw: done-for-you OpenClaw for founders & exec teams

White-glove OpenClaw for founders and exec teams (4–50+ employees): we install, harden, integrate your tools, and maintain it — secured from day one.

Get it set up for you
SEO data APIs for your agent, $1 free credit logoSEO data APIs for your agent, $1 free credit

DataForSEO gives your agent live access to SERP results, keyword data, backlinks, and on-page SEO data through one API. New accounts get a $1 credit, good for up to 20,000 keyword or backlink lookups.

Try DataForSEO free
Reach 48,000+ AI builders

A flat monthly placement in front of developers actively installing AI tools. No lock-in, cancel anytime.

Advertise here

Works with

Claude CodeClaude DesktopCursorVS CodeClineCodex CLIOpenClaw+ any MCP client

Install to Claude Code

This server doesn't publish a one-line install command. Follow the setup in the source repository.

Summary

Enables AI agents to read and write UpNote notes locally via SQLite and URL schemes, supporting search, creation, editing, and organization.

README.md

upnote-mcp

A local Model Context Protocol server for UpNote. It lets Claude Code, Cursor, and other AI agents read and write your UpNote library.

UpNote has no public cloud API, so this server works with the two integration surfaces UpNote exposes locally:

  • Reads come from UpNote's local SQLite database (read-only).
  • Note/notebook creation uses UpNote's official upnote:// URL scheme (app-native).
  • Edits, moves, deletes, restores, and tagging are written directly into the SQLite database (guarded by backups and a "quit the app first" preflight), because UpNote provides no edit/delete endpoint.

Features

Read tools:

  • search_notes - full-text-ish search over title/body, scoped optionally to a notebook or tag
  • get_note - a note's content (markdown / html / text) plus metadata, notebooks, and tags
  • list_notebooks - the notebook tree with per-notebook note counts
  • list_notes - by filter: recent, notebook, tag, bookmarked, pinned, trashed, templates
  • list_tags - all tags with note counts
  • get_note_attachments / read_attachment - attachment metadata and bytes
  • get_stats - library counts and the resolved DB path

Write tools:

  • create_note, create_notebook - via the upnote:// URL scheme (works while the app is running)
  • update_note, move_note, delete_note, restore_note, tag_note, untag_note - direct SQLite writes (app should be quit)
  • append_note - append content to the end of a note without rewriting its existing body (safe for rich/image-heavy notes)
  • merge_notes - fold one note into another (append its body under an ## <source title> divider, migrate its images so nothing is orphaned, then trash the source)
  • open_in_upnote - open a note or run a search in the app

How it works

flowchart LR
  agent["Claude Code / Cursor"] -->|stdio MCP| server["upnote-mcp"]
  server -->|read-only| readdb[("upnote.sqlite3")]
  server -->|"create (default)"| scheme["upnote:// URL scheme"]
  scheme --> app["UpNote app"]
  server -->|"edit / move / delete (app quit)"| writer["backup + preflight + tx"]
  writer --> writedb[("upnote.sqlite3")]
  app --> writedb

When a row is changed directly, the server sets synced = 0, bumps revision, and updates updatedAt. UpNote re-pushes those rows to its sync backend the next time it launches.

Safety model

Editing a live, syncing database is inherently risky. This server defends your data:

  • Reads use a read-only connection and never lock or modify anything.
  • Before any direct write it takes a timestamped backup of upnote.sqlite3 (plus -wal/-shm) into a MCP Backups/ folder.
  • Direct writes are refused while UpNote is running (it caches rows in memory and could overwrite your change). Quit UpNote first, or set UPNOTE_ALLOW_WHILE_RUNNING=1 to override (not recommended).
  • Each mutation runs in a single transaction and checkpoints the WAL afterward.
  • Destructive tools accept dry_run=true to preview without writing.

Recommended workflow for edits/deletes: quit UpNote, run the changes, then reopen UpNote to let it sync. Creating notes via the default URL scheme is safe while the app is open.

Inbox / whiteboard workflow

A capture-then-triage loop keeps the library tidy:

  1. Capture (app open). Dump quick thoughts as notes into a single 📥 Inbox notebook — type them in UpNote, or have the agent create_note them. No structure required.
  2. Triage (ask the agent). Tell the agent "triage my inbox". It reads every note in 📥 Inbox, then proposes, per note, one of: move to the right notebook, merge into an existing note, or create a new note — and shows the plan for you to review.
  3. Accept. On your OK (and with UpNote quit), it applies the plan with move_note / merge_notes / append_note. A timestamped backup is taken first; merged sources go to Trash (recoverable) and their images are migrated so nothing is orphaned.

merge_notes and append_note make this safe: the destination note's existing content (including images) is preserved verbatim and the new material is appended under a labelled ## divider.

Requirements

  • UpNote desktop app installed (macOS verified; Windows/Linux best-effort).
  • uv installed.
  • Python 3.10+.

Install

git clone https://github.com/bug-breeder/upnote-mcp.git
cd upnote-mcp
uv sync

Run it directly (stdio):

uv run upnote-mcp

Configuration

All paths are auto-detected per platform and can be overridden with environment variables.

| Variable | Purpose | Default (macOS) | | --- | --- | --- | | UPNOTE_DB | Path to upnote.sqlite3 | <data dir>/upnote.sqlite3 | | UPNOTE_DATA_DIR | UpNote data directory | ~/Library/Containers/com.getupnote.desktop/Data/Library/Application Support/UpNote | | UPNOTE_IMAGES_DIR | Attachment blob directory | <data dir>/images | | UPNOTE_BACKUPS_DIR | Where pre-write backups go | <data dir>/MCP Backups | | UPNOTE_WRITE_MODE | Create backend: url (default) or sqlite | url | | UPNOTE_ALLOW_WHILE_RUNNING | Permit direct writes while UpNote runs | unset (off) |

Default data directories: macOS uses the container path above; Windows uses %APPDATA%/UpNote; Linux uses ~/.config/UpNote.

Client setup

Replace the path below with your local clone if different: /Users/alanguyen/Code/Personal/upnote-mcp.

Cursor

Add to ~/.cursor/mcp.json (global) or .cursor/mcp.json (per project):

{
  "mcpServers": {
    "upnote": {
      "command": "uv",
      "args": ["run", "--directory", "/Users/alanguyen/Code/Personal/upnote-mcp", "upnote-mcp"]
    }
  }
}

Claude Code

claude mcp add upnote -- uv run --directory /Users/alanguyen/Code/Personal/upnote-mcp upnote-mcp

Or add it to .mcp.json with the same command/args shown above.

uvx alternative

If you prefer uvx, use "command": "uvx" with "args": ["--from", "/Users/alanguyen/Code/Personal/upnote-mcp", "upnote-mcp"].

Limitations and caveats

  • The URL scheme is fire-and-forget: create_note/create_notebook do not return the id of what they create. Set UPNOTE_WRITE_MODE=sqlite to create via SQLite and receive the new note id (requires the app to be quit).
  • UpNote must be quit for edits/moves/deletes to be reliable.
  • Direct writes set synced = 0 so UpNote re-syncs on next launch; the first time you use the write tools, verify a test edit appears correctly in the app before trusting it with important notes.
  • Search is substring-based (LIKE) over title and plain text, not a ranked full-text index.

Development

uv sync
uv run pytest

Tests run against a throwaway SQLite database in a temp directory and never touch your real UpNote data.

License

MIT

See related servers & alternatives →

Related MCP servers

Browse all →

Related guides

Hand-picked reading to help you choose and use Databases servers.