Metadata-Version: 2.4
Name: bearnotes-mcp
Version: 0.3.0
Summary: Local MCP server to read and edit macOS Bear notes from Claude
Project-URL: Homepage, https://github.com/samcrudge/bearnotes-mcp
Project-URL: Repository, https://github.com/samcrudge/bearnotes-mcp
Project-URL: Issues, https://github.com/samcrudge/bearnotes-mcp/issues
License-Expression: Apache-2.0
License-File: LICENSE
Keywords: bear,claude,mcp,model-context-protocol,notes
Classifier: Environment :: Console
Classifier: Operating System :: MacOS
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Utilities
Requires-Python: >=3.11
Requires-Dist: mcp>=1.9
Description-Content-Type: text/markdown

# bearnotes-mcp

A tiny local [MCP](https://modelcontextprotocol.io) server that lets any local
MCP client on macOS — [Claude Code](https://claude.com/claude-code), Claude
Desktop, Cursor, VS Code — read and edit your [Bear](https://bear.app) notes:
search, read, create, append, and overwrite (e.g. tick a checkbox).

**No Bear API token is needed.** Reads use Bear's local database (opened
read-only); writes use Bear's `bear://x-callback-url` scheme. Neither requires a
token, and nothing here ever touches the network.

## Requirements

- **macOS** with **Bear installed and opened at least once** (the database only
  exists after Bear has run).
- **[uv](https://docs.astral.sh/uv/)** — install with `curl -LsSf https://astral.sh/uv/install.sh | sh` (or `brew install uv`).

No Python setup, no token.

## Install — Claude Code

**1. Warm the cache** (first run downloads ~30 packages — may take a minute; ends with `selfcheck ok`):

```sh
uvx bearnotes-mcp --selfcheck
```

**2. Register** — one command, at user scope so it's available in every project:

```sh
claude mcp add bear -s user -- uvx bearnotes-mcp
```

**3. Verify:**

```sh
claude mcp list        # → bear: ✔ Connected
```

> If the very first connect times out, just **retry** (the cache is warm after
> one attempt), or start Claude once with `MCP_TIMEOUT=60000 claude`.

## Install — Claude Desktop, Cursor, VS Code

Add an `mcpServers` entry. **Use the full path to `uvx`** — GUI apps don't see
your shell `PATH` (`which uvx`, e.g. `/opt/homebrew/bin/uvx`):

```json
{
  "mcpServers": {
    "bear": {
      "command": "/opt/homebrew/bin/uvx",
      "args": ["bearnotes-mcp"]
    }
  }
}
```

- **Claude Desktop** — Settings → Developer → Edit Config (creates
  `~/Library/Application Support/Claude/claude_desktop_config.json`); paste, then
  **fully quit and restart**. Logs: `~/Library/Logs/Claude/mcp-server-bear.log`.
- **Cursor** — same block in `~/.cursor/mcp.json`.
- **VS Code (Copilot)** — `.vscode/mcp.json`, but the top-level key is `servers` (not `mcpServers`).
- **Windsurf / Cline / Zed / LM Studio** — same stdio pattern; check their docs for the exact file.

**Cannot work:** claude.ai in the browser, mobile apps, remote/hosted connectors,
and non-Mac machines — they can't spawn a local process, and Bear lives only on
your Mac.

<details>
<summary>Alternatives: bleeding edge, or run from a clone</summary>

Latest `main` without waiting for a release (builds from GitHub each install):

```sh
claude mcp add bear -s user -- uvx --from git+https://github.com/samcrudge/bearnotes-mcp bearnotes-mcp
```

Clone it to read/hack the code first:

```sh
git clone https://github.com/samcrudge/bearnotes-mcp
claude mcp add bear -s user -- uv --directory /absolute/path/to/bearnotes-mcp run bearnotes-mcp
```

To point at a non-default Bear database, add `-e BEAR_DB=/path/to/database.sqlite`
to the `claude mcp add` command.
</details>

## How it works

- **Reads** — Bear's local SQLite DB, opened **read-only** (`mode=ro`).
- **Writes** — Bear's [`x-callback-url`](https://bear.app/faq/x-callback-url-scheme-documentation/)
  scheme (`create`, `add-text` in `append` / `replace_all` mode).

The DB is never written directly (that corrupts Bear's sync). Before any
full-body overwrite, the note's current text is snapshotted to
`~/.bear-mcp-backups/` as a timestamped `.md` file.

## Tools

| Tool | What it does |
|------|--------------|
| `search_notes(query="", tag="", limit=20)` | Search non-trashed notes, optional tag filter (incl. subtags); returns id, title, tags, pinned, modified |
| `read_note(id)` | Full note + tags, pinned, and open/done checkbox counts |
| `list_tags()` | Every tag with its live-note count |
| `get_backlinks(id)` | Notes linking to this one, and notes it links to (Bear `[[wiki-link]]` graph) |
| `create_note(title, text="", tags=[])` | Create a new note |
| `append_note(id, text)` | Append to a note |
| `prepend_note(id, text)` | Prepend to a note (after the title line) |
| `replace_note(id, text)` | Overwrite a note's entire text; backs up first |
| `toggle_task(id, match, done=None)` | Check/uncheck one checkbox line by substring (`done` None=flip); errors if ambiguous |
| `open_note(id)` | Open and focus a note in the Bear app |

**Resources** (read-only, `@`-mentionable): `bear://notes` (index of recent notes) and `bear://note/{id}` (a note's full text).

## What this can access

Once connected, the client can **read every non-trashed note** (encrypted notes
are refused) and **create, append to, or overwrite** notes. Everything runs
**locally with no network calls**; the database is opened **strictly read-only**;
and before any full-body overwrite the current text is backed up to
`~/.bear-mcp-backups/`. Tools carry MCP annotations (reads marked read-only,
`replace_note` marked destructive) so clients can surface the right warnings.

## Troubleshooting

- **First connect times out** — retry (cache is warm now), or `MCP_TIMEOUT=60000 claude`.
- **Desktop fails instantly** — `"command"` must be the *full path* to `uvx` (`which uvx`).
- **No notes found** — open Bear at least once so its database exists.

## License

Apache-2.0. See [LICENSE](LICENSE).
