notes-mcp
by Vontk
README.md
# notes-mcp
A remote MCP server that captures notes into a Git-backed Markdown vault (Obsidian-friendly). Deploy your own instance to Cloudflare Workers in one click.
[](./LICENSE)
[](https://deploy.workers.cloudflare.com/?url=https://github.com/Vontk/notes-mcp)
## What & why
`notes-mcp` lets any MCP client — Claude, Claude Desktop, Cursor, and others — append and create Markdown notes directly in a GitHub repository. It's designed for an [Obsidian](https://obsidian.md/) vault synced via git ([obsidian-git](https://github.com/Vinzent03/obsidian-git)): capture a thought from a chat with Claude, and it shows up in your vault the next time Obsidian pulls.
Each deployment is single-tenant — you run your own instance, pointed at your own notes repo, protected by your own auth token. Nothing is hardcoded; everything is configuration.
## Features
- **Five focused tools**: append to a note, create/overwrite a note, append to today's daily note, read a note, list a directory.
- **Single-file edge deploy** — one Cloudflare Worker, no servers to manage.
- **Runs on Cloudflare's free tier.**
- **Works with any Git-backed Markdown vault**, not just Obsidian.
- **Token-guarded** — every request to `/mcp` requires a bearer token you control.
## How it works
```
MCP client → Worker (/mcp) → GitHub Contents API → your notes repo → Obsidian Git pulls it
```
Your MCP client calls a tool (e.g. `append_note`). The Worker authenticates the request, then reads/writes the target file through the GitHub Contents API, which creates a commit. The note appears on your other devices the next time Obsidian Git pulls — tune its auto-pull / pull-on-startup settings for how fresh you want that to be.
## Prerequisites
- A [Cloudflare](https://dash.cloudflare.com/sign-up) account (free tier is enough).
- A GitHub repository to hold your notes (can be the same repo as your Obsidian vault).
- A fine-grained GitHub Personal Access Token scoped to that repo.
## Create the PAT
1. Go to [github.com/settings/personal-access-tokens](https://github.com/settings/personal-access-tokens).
2. Click **Fine-grained tokens** → **Generate new token**.
3. Set **Resource owner** to yourself (or the org that owns your notes repo).
4. Under **Repository access**, choose **Only select repositories** and pick your notes repo.
5. Under **Repository permissions**, set **Contents** to **Read and write**. Leave everything else as **No access**.
6. Generate the token and copy it — you'll only see it once.
## Deploy
### A. One-click deploy
1. Click the **Deploy to Cloudflare** button above.
2. Cloudflare will fork/clone this repo and prompt you for the two secrets below (`GITHUB_PAT`, `MCP_AUTH_TOKEN`) during setup.
3. After deploying, open your Worker in the Cloudflare dashboard and set the `vars` (`GITHUB_OWNER`, `GITHUB_REPO`, etc.) under **Settings → Variables**.
### B. CLI
```bash
git clone https://github.com/Vontk/notes-mcp.git
cd notes-mcp
npm install
# Edit the "vars" block in wrangler.jsonc for your repo/timezone/etc.
npx wrangler secret put GITHUB_PAT
npx wrangler secret put MCP_AUTH_TOKEN # e.g. generate with: openssl rand -hex 32
npm run deploy
```
## Configuration
| Name | Kind | Required | Description | Example |
|---|---|---|---|---|
| `GITHUB_OWNER` | var | yes | GitHub username or org that owns the notes repo. | `Vontk` |
| `GITHUB_REPO` | var | yes | Name of the notes repo. | `my-vault` |
| `GITHUB_BRANCH` | var | no | Branch to commit to. Empty string uses the repo's default branch. | `main` |
| `DEFAULT_NOTE_PATH` | var | no | File used by `append_note` when no `path` is given. Defaults to `inbox.md`. | `inbox.md` |
| `TIMEZONE` | var | no | IANA timezone used to compute daily note dates. Defaults to `UTC`. | `America/Argentina/Buenos_Aires` |
| `GITHUB_PAT` | secret | yes | Fine-grained PAT with **Contents: Read and write** on the notes repo only. | *(set via `wrangler secret put`)* |
| `MCP_AUTH_TOKEN` | secret | yes | Shared secret required on every request to `/mcp`. | *(set via `wrangler secret put`)* |
## Connect to Claude
**Claude.ai (custom connector):**
1. Go to [claude.ai/customize/connectors](https://claude.ai/customize/connectors).
2. Click **+ Add custom connector**.
3. URL: `https://<your-worker>.<your-subdomain>.workers.dev/mcp`
4. Pass your token either as an `Authorization: Bearer <MCP_AUTH_TOKEN>` header, or by appending `?token=<MCP_AUTH_TOKEN>` to the URL.
**Claude Desktop / other clients (via `mcp-remote`):**
```json
{
"mcpServers": {
"notes-mcp": {
"command": "npx",
"args": [
"mcp-remote",
"https://<your-worker>.<your-subdomain>.workers.dev/mcp?token=<MCP_AUTH_TOKEN>"
]
}
}
}
```
## Tools
| Tool | Params | What it does | Example |
|---|---|---|---|
| `append_note` | `path?`, `text` | Appends a line to a note, creating it if needed. `path` defaults to `DEFAULT_NOTE_PATH`. | Append "buy milk" to `inbox.md`. |
| `create_note` | `path`, `content` | Creates a note, or overwrites it if it already exists. | Write a new `Projects/notes-mcp.md`. |
| `append_daily` | `text`, `folder?` | Appends a line to today's daily note (`<folder><YYYY-MM-DD>.md`). | Append "stand-up notes" to `Daily/2026-08-25.md`. |
| `read_note` | `path` | Returns the contents of a note. | Read `inbox.md`. |
| `list_notes` | `path?` | Lists files and folders in a directory (repo root if omitted). | List `Daily/`. |
## Security
- Each deployment is single-tenant: one Worker, one notes repo, one token.
- Keep `MCP_AUTH_TOKEN` secret — anyone with it can read and write to your notes repo through this Worker.
- Scope `GITHUB_PAT` to exactly one repository with **Contents: Read and write** only.
- Never commit secrets. `.dev.vars` and `.wrangler` are gitignored; use `.dev.vars.example` as a template.
- To rotate a credential, generate a new value and run `wrangler secret put <NAME>` again — it overwrites the existing secret immediately.
## Local dev
```bash
npm start
```
Test it with the [MCP Inspector](https://github.com/modelcontextprotocol/inspector):
```bash
npx @modelcontextprotocol/inspector
```
Point it at `http://localhost:8787/mcp` with your `MCP_AUTH_TOKEN` from `.dev.vars`.
## Testing / CI
```bash
npm run typecheck
npm run lint
npm test
```
`ci.yml` runs all three on every pull request and push. `deploy.yml` deploys to Cloudflare on every push to `main`, once those checks pass — it needs two repo secrets under **Settings → Secrets and variables → Actions**:
- `CLOUDFLARE_API_TOKEN`
- `CLOUDFLARE_ACCOUNT_ID`
## Contributing
Issues and pull requests are welcome. Please run `npm run lint`, `npm run typecheck`, and `npm test` before submitting.
## License
[MIT](./LICENSE)
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues