hedgedoc-mcp
README.md
# hedgedoc-mcp
An [MCP](https://modelcontextprotocol.io) server that lets AI agents — Claude Code, Codex, Hermes, or any MCP-compatible client — read and write notes on a **self-hosted HedgeDoc 1.x** instance.
HedgeDoc 1.x has no API token system, so this server handles the real auth model (session cookies from email/password login) and exposes it as a clean, agent-friendly toolset.
---
## Why this exists
[HedgeDoc](https://hedgedoc.org) is a great self-hosted, open-source, collaborative markdown editor. But if you want an AI agent to write notes to it programmatically, you hit a wall immediately: **HedgeDoc 1.x has no API tokens.** Every write endpoint (`POST /new`, etc.) requires an authenticated browser-style session, tracked via an Express `connect.sid` cookie.
This project does the unglamorous work of handling that correctly — login, cookie storage, automatic re-authentication on expiry — and wraps it in an MCP server so any agent can just call `hedgedoc_create_note` and not think about any of it.
## Features
- 🔐 **Handles HedgeDoc 1.x's real auth model** (session cookies, not tokens)
- 🔁 **Auto re-login on session expiry** — no manual cookie refresh needed
- 🛠️ **6 MCP tools**: create, read, update, info, whoami, history
- 🐍 **Standalone Python client** (`hedgedoc_mcp.client.HedgeDocClient`) usable outside MCP too
- ✅ **Fully tested** — mocked HTTP, no live server required to run the test suite
- 📦 **Works with any MCP client**: Claude Code, Codex, Hermes, Cursor, custom clients
## Quick start
### 1. Install
**With [uv](https://docs.astral.sh/uv/) (recommended — no venv management needed):**
```bash
# Run directly without installing (uvx downloads + caches automatically)
uvx hedgedoc-mcp
# Or install as a persistent tool
uv tool install hedgedoc-mcp
```
> **Not yet on PyPI?** Run straight from GitHub instead — same zero-install experience:
> ```bash
> uvx --from git+https://github.com/mrsunglasses-experiments/hedgedoc-mcp hedgedoc-mcp
> ```
> Use this exact form in the agent config examples below (as `args`) until the package is published.
**With pip:**
```bash
pip install hedgedoc-mcp
```
**From source:**
```bash
git clone https://github.com/mrsunglasses-experiments/hedgedoc-mcp.git
cd hedgedoc-mcp
uv pip install -e . # or: pip install -e .
```
### 2. Get a session cookie
HedgeDoc 1.x has no API tokens, so you authenticate once via the login endpoint and reuse the resulting session cookie:
```bash
hedgedoc-mcp-login --url https://md.example.com \
--email you@example.com --password 'your-password' \
--write-env .env
```
This prints (and optionally saves) `HEDGEDOC_SESSION_COOKIE=...`.
Alternatively, set `HEDGEDOC_EMAIL` + `HEDGEDOC_PASSWORD` directly and the server will log in automatically on first use, re-authenticating whenever the session expires — no manual refresh needed.
### 3. Configure environment variables
```bash
export HEDGEDOC_URL=https://md.example.com
export HEDGEDOC_SESSION_COOKIE=s%3A... # from step 2, OR:
export HEDGEDOC_EMAIL=you@example.com # for auto re-login
export HEDGEDOC_PASSWORD=your-password
```
At minimum you need `HEDGEDOC_URL` plus either the cookie or the email+password pair. Setting both is recommended — the cookie is used as a fast path, and email/password is the automatic fallback whenever it expires.
### 4. Wire it into your agent
<details>
<summary><b>Claude Code</b></summary>
```bash
claude mcp add hedgedoc -- uvx hedgedoc-mcp
```
Or add to `.claude/mcp.json`:
```json
{
"mcpServers": {
"hedgedoc": {
"command": "uvx",
"args": ["hedgedoc-mcp"],
"env": {
"HEDGEDOC_URL": "https://md.example.com",
"HEDGEDOC_EMAIL": "you@example.com",
"HEDGEDOC_PASSWORD": "your-password"
}
}
}
}
```
</details>
<details>
<summary><b>Codex CLI</b></summary>
Add to `~/.codex/config.toml`:
```toml
[mcp_servers.hedgedoc]
command = "uvx"
args = ["hedgedoc-mcp"]
env = { HEDGEDOC_URL = "https://md.example.com", HEDGEDOC_EMAIL = "you@example.com", HEDGEDOC_PASSWORD = "your-password" }
```
</details>
<details>
<summary><b>Hermes</b></summary>
Add an MCP server entry in your Hermes config with `command: uvx`, `args: [hedgedoc-mcp]`, and the same environment variables. See the [Hermes MCP docs](https://docs.hermes.dev) for the exact config location on your install.
</details>
<details>
<summary><b>Any other MCP client</b></summary>
This is a standard stdio MCP server. Point your client at `uvx hedgedoc-mcp` (or the installed `hedgedoc-mcp` executable) with the environment variables above set, and it will discover the 6 tools automatically via the standard MCP `list_tools` handshake. Using `uvx` means the client never needs a separate install step — `uv` downloads and caches the package on first run.
</details>
## Available tools
| Tool | Description |
|---|---|
| `hedgedoc_create_note` | Create a new note (optionally with a custom URL alias). Returns the note ID and URL. |
| `hedgedoc_read_note` | Fetch a note's raw markdown content by ID or alias. |
| `hedgedoc_update_note` | Overwrite an existing note's content (alias-based notes only — see [Limitations](docs/LIMITATIONS.md)). |
| `hedgedoc_note_info` | Get a note's title, description, view count, and timestamps. |
| `hedgedoc_whoami` | Verify the session is valid and show the logged-in user. |
| `hedgedoc_list_history` | List the logged-in user's recently viewed/pinned notes. |
## Using the Python client directly
You don't need MCP to use this — the underlying client is a normal Python class:
```python
from hedgedoc_mcp.client import HedgeDocClient
client = HedgeDocClient("https://md.example.com")
client.login(email="you@example.com", password="your-password")
result = client.create_note("# Research notes\n\nSome findings...")
print(result.url)
content = client.read_note(result.note_id)
info = client.note_info(result.note_id)
```
## Known limitations
HedgeDoc 1.x's HTTP API is genuinely limited compared to newer forks — see [docs/LIMITATIONS.md](docs/LIMITATIONS.md) for the full rundown, including:
- No API tokens (session-cookie auth only)
- No generic "update note by ID" endpoint (alias-based notes only)
- No delete endpoint over HTTP
These are constraints of the HedgeDoc 1.x server itself, not this client — the docs explain the workarounds this project uses and what genuinely isn't possible.
## Development
```bash
git clone https://github.com/mrsunglasses-experiments/hedgedoc-mcp.git
cd hedgedoc-mcp
uv venv && source .venv/bin/activate
uv pip install -e ".[dev]"
pytest # run tests (fully mocked, no live server needed)
ruff check . # lint
```
See [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) for how the auth flow and MCP layer fit together, and [CONTRIBUTING.md](CONTRIBUTING.md) for contribution guidelines.
## License
MIT — see [LICENSE](LICENSE).
TDQS
A4.4/5.0
Scored across 6 tools
Disambiguation5/5
Each tool performs a distinct function: create, read, update, metadata, session validation, and history. Even read_note and note_info are clearly separated by raw content vs. metadata.
Naming Consistency5/5
All tools use the 'hedgedoc_' prefix with clear verb_noun or noun_info naming in consistent snake_case. The pattern is uniform and predictable.
Tool Count5/5
Six tools is a well-scoped set for a HedgeDoc server, covering core note operations plus session and history. No unnecessary duplication or bloat.
Completeness4/5
Core lifecycle (create, read, update) is present, along with metadata and history. Missing delete is a notable gap, and update's alias-only limitation creates a dead end for non-alias notes, but the overall surface is reasonably complete.
Maintenance
ActivityMaintained
ResponsivenessNo issues