{"id":"72d0740f-2602-4a24-9815-ae8f8bbf613a","slug":"hedgedoc-mcp","kind":"mcp","name":"hedgedoc-mcp","summary":"Multitenant MCP Server for HedgeDoc","owner":"homeserverhq","repoUrl":"https://github.com/homeserverhq/hedgedoc-mcp","license":"GPL-3.0","licenseTier":"strong-copyleft","trust":"community","stars":1,"match":null,"fewStars":true,"format":"mcp","createdAt":"2026-07-28T06:04:04.000Z","addedAt":"2026-10-21T21:36:56.564Z","logoUrl":"https://avatars.githubusercontent.com/u/118991087?u=daf55a45cc8fc270db277a1f3299c30df98ef2b8&v=4","linkOnly":false,"collection":null,"skillPath":null,"categories":["cloud-infra"],"tags":[],"runtime":"binary","local":true,"cloudCapable":false,"cloudCapability":"unknown","cloudReadyOnPlatform":false,"needsApiKey":false,"reviewed":false,"syncedAt":"2026-10-23T00:06:03.584Z","sample":false,"url":"https://conduits.dev/tools/hedgedoc-mcp","language":"Python","transports":["stdio"],"install":{},"requirements":{"env":[],"upstreamMayCharge":false},"tools":null,"readme":"# HedgeDoc MCP Multitenant Proxy Server\n\nThis repository contains a Model Context Protocol (MCP) server that acts\nas a secure, multi-tenant proxy between an AI Assistant and the HedgeDoc\nbackend API. It exposes **27 MCP tools** covering 5 resource domains\nwith full CRUD and permission management.\n\n## ✨ Features\n\n- **🔑 Identity Passthrough** — Extracts the `Authorization: Bearer <token>`\n  header from incoming HTTP requests and forwards it to the HedgeDoc API\n  without server-side authentication.\n- **👥 Multi-Tenancy** — Uses Python `contextvars` to maintain thread-safe\n  user identity isolation, ensuring all AI-driven actions are scoped to\n  the authenticated user's permissions.\n- **📊 Full HedgeDoc Coverage** — 27 tools mapped to HedgeDoc API endpoints\n  across 5 resource domains.\n- **⚡ TOON Optimization** — Bulk list responses are automatically compressed\n  using TOON (Token-Optimized Object Notation) to reduce token consumption\n  and maximize context window efficiency.\n- **🚀 Efficient Gets** — GET responses return only commonly used fields by\n  default. Full objects are available via an `include_all_fields` flag.\n- **🧪 Comprehensive Testing** — 39 automated tests covering all tool\n  domains, run via the test runner pipeline.\n- **🏷️ Tool Annotations** — All tools expose standard MCP ToolAnnotations hints (readOnlyHint, destructiveHint, idempotentHint, openWorldHint). The tags field carries grouping metadata (basic/primary/advanced + hedgedoc).\n\n## 🔧 Environment Variables\n\n| Variable | Required | Description |\n|----------|----------|-------------|\n| `HEDGEDOC_BASE_URL` | Yes | Docker-internal URL of the HedgeDoc API (e.g. `http://hedgedoc-backend:3000`). |\n| `MCP_SERVER_PORT` | Yes | Port number the MCP server listens on. |\n| `ALLOW_ALL_AGGREGATE` | No | When `true`, aggregate listing tools honor the `include_all_fields` parameter. When `false` (default), the parameter is silently forced to `False` for aggregate list operations. |\n| `IS_STATEFUL` | No | When `true`, uses stateful Streamable HTTP with session tracking. When `false` (default), uses stateless mode. |\n| `HEDGEDOC_PUBLIC_URL` | No | Public-facing URL for `note_url` in responses. Defaults to `HEDGEDOC_BASE_URL` if not set. |\n\n## 📦 Installation & Local Development\n\n1. Ensure you have Python 3.12+ installed.\n2. Install dependencies:\n    ```bash\n    pip install fastmcp httpx pydantic uvicorn toon-mcp-server\n    ```\n3. Run the server:\n    ```bash\n    export HEDGEDOC_BASE_URL=http://localhost:7462\n    export HEDGEDOC_PUBLIC_URL=https://hedgedoc.example.com\n    export MCP_SERVER_PORT=80\n    python -m src.main\n    ```\n\n## 🐳 Docker Deployment\n\nBuild and run the server using Docker:\n\n```bash\ndocker build -t hedgedoc-mcp:latest .\ndocker run -d --name hedgedoc-mcp \\\n    -e HEDGEDOC_BASE_URL=\"http://hedgedoc-backend:3000\" \\\n    -e HEDGEDOC_PUBLIC_URL=\"https://hedgedoc.example.com\" \\\n    -e MCP_SERVER_PORT=80 \\\n    -e IS_STATEFUL=false \\\n    hedgedoc-mcp:latest\n\nThe MCP server serves at `http://hedgedoc-mcp:80/mcp` (Streamable HTTP).\n```\n\n## ⚠️ Important Notes\n\n- **📋 `include_all_fields`** — The `include_all_fields` parameter (available\n  on all `get_*` and `list_*` tools) controls whether all available fields\n  are included in responses. Defaults to `False` for performance; set to\n  `True` only when additional fields are needed.\n- **⚡ TOON Compression** — All bulk list responses are automatically\n  compressed using TOON to reduce token consumption by 30–60%.\n- **📝 Required Fields & Defaults** — Each `create_*` tool requires specific\n  key fields. All other fields default to empty strings or reasonable values.\n  The owner field is automatically set to the authenticated user for most\n  resources.\n\n## 🛠️ API Tool Mapping\n\nThe server implements 27 MCP tools organized into the following categories:\n\n### 📄 Notes Core (6 tools)\n\n- `create_note` — Create a new note from markdown content\n- `get_note_by_id` — Get a single note by ID or alias\n- `update_note` — Update an existing note's content\n- `delete_note_by_id` — Delete a note by ID or alias\n- `get_note_content` — Get raw markdown content of a note\n- `get_note_metadata` — Get a note's metadata (title, tags, etc.)\n\n### 📎 Notes Advanced (7 tools)\n\n- `list_note_media` — List all media files attached to a note\n- `list_note_revisions` — List all revisions of a note\n- `get_note_revision_by_id` — Get a specific revision by UUID\n- `revert_to_revision` — Revert a note to a previous revision\n- `add_alias` — Add an alias to a note\n- `make_alias_primary` — Set an alias as primary or non-primary\n- `remove_alias` — Remove an alias from a note\n\n### 🔐 Notes Permissions (6 tools)\n\n- `get_note_permissions` — Get a note's permission settings\n- `set_note_user_permission` — Set a user's permission on a note\n- `remove_note_user_permission` — Remove a user's permission from a note\n- `set_note_group_permission` — Set a group's permission on a note\n- `remove_note_group_permission` — Remove a group's permission from a note\n- `change_note_owner` — Change the owner of a note\n\n### 📋 Notes Listing (4 tools)\n\n- `list_all_my_notes` — List notes owned by the current user\n- `list_all_shared_notes` — List notes shared with the current user\n- `list_all_public_notes` — List public notes visible to the current user\n- `list_all_pinned_notes` — List notes pinned by the current user\n\n### 👤 Profile & Media (4 tools)\n\n- `get_my_profile` — Get the current user's profile information\n- `list_all_my_media` — List all media files owned by the current user\n- `get_media_by_id` — Get a single media file by UUID\n- `delete_media_by_id` — Delete a media file by UUID\n"}