io.github.bbik52/docmost-mcp-remote
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@io.github.bbik52/docmost-mcp-remotesearch the wiki for our onboarding docs and summarize the setup steps"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
docmost-mcp-remote
A self-hosted remote MCP server for Docmost Community Edition. Run it next to your Docmost, put it behind your domain, and let AI clients such as Claude, Claude Code, Cursor or VS Code read and edit the wiki on behalf of each member, with that member's own Docmost account and rights.
One server, one Docmost, many members. Each member signs in with their own Docmost account in the browser. Everything their AI client does is done as them in Docmost.
Authorization is mandatory. OAuth 2.1 for remote connectors and personal bearer tokens for scripts. There is no unauthenticated mode.
Safe by default.
readis the only scope granted without asking. Writing and moving to Trash need explicit scopes. Nothing is deleted permanently, and the server keeps an encrypted snapshot of a page body before every change.Self-hosted. One container plus Postgres, with a ready
compose.yaml.
Supported Docmost versions
Docmost Community Edition 0.70.0 or newer. Older versions are refused at sign-in. CI runs the integration tests against Docmost 0.70.3, 0.96.0 and 0.97.0; newer releases work in most cases and log a warning until they are added to the tested range. Docmost users who sign in with SSO only (an Enterprise feature) cannot use this server: it signs in with email and password.
Related MCP server: MediaWiki MCP Server
Tools
Tool | Scope | What it does |
| read | The Docmost account, scopes and Docmost version of this connection |
| read | Spaces you can access, with your role |
| read | Page tree of a space, one level at a time |
| read | Recently updated pages |
| read | One page as Markdown, by id, slug id or Docmost URL |
| read | Full-text search with snippets |
| read | Comments and replies on a page |
| read | Pages in the Trash of a space |
| read | Snapshots this server saved before your changes to a page |
| write | New page with a Markdown body, optionally under a parent |
| write | Append, prepend or replace a page body with Markdown |
| write | Change a page title |
| write | Move a page within its space, to the start, the end or after a sibling |
| write | Comment on a page or reply to a comment |
| write | Put a page body back to a snapshot |
| delete | Move a page to the Trash |
| delete | Restore a page from the Trash |
Page bodies, comments and snippets are returned inside a
<docmost-untrusted-content> envelope so the model treats them as data.
Before every body change the server saves the current body as a snapshot in
its own database, encrypted, for SNAPSHOT_RETENTION_DAYS; if the snapshot
cannot be saved, nothing is written. After the change it reads the page back
and reports an error if Docmost did not apply it (this happens when Docmost
runs with COLLAB_DISABLE_REDIS). Snapshots can hold content of pages that
were later deleted in Docmost until they expire.
Security model
Members sign in with their own Docmost account; everything a client does is
done as that member, with their Docmost rights. The server keeps the Docmost
session token encrypted with a key derived from SECRET_KEY and does not
store passwords unless RELOGIN_MODE=stored_password. Personal tokens are
stored as hashes and shown once. The sign-in page has CSRF protection and
per-IP and per-email rate limits.
The server is its own OAuth 2.1 authorization server, following the MCP
authorization spec: dynamic client registration (limited per IP, redirect
URIs must be https, loopback http or a native app scheme), authorization
code with PKCE (S256 only), exact redirect URI match, tokens bound to this
server's /mcp resource, one-hour access tokens and 30-day refresh tokens
that rotate on every use. A reused refresh token or a replayed code revokes
the whole grant. OAuth grants and personal tokens are listed and revoked on
the same account page.
Page content is treated as untrusted data and labelled as such for the model.
Prompt injection in a page can still make a client act within the scopes the
member granted, so grant write and delete only to clients you trust.
Tool calls are limited per member and recorded in an audit log. See the
threat model, SECURITY.md for
how to report a vulnerability and the design.
Quick start
You need Docker with Compose, a Docmost reachable from the server, and a host
name with https for the server itself, for example mcp.example.com.
Download the compose file and the settings template:
mkdir docmost-mcp && cd docmost-mcp curl -fsSLO https://raw.githubusercontent.com/bbik52/docmost-mcp-remote/master/compose.yaml curl -fsSL -o .env https://raw.githubusercontent.com/bbik52/docmost-mcp-remote/master/.env.exampleEdit
.env: setPUBLIC_URL(the https URL of this server),DOCMOST_URL, a long randomPOSTGRES_PASSWORDandSECRET_KEY(openssl rand -hex 32gives a good value for both). ConsiderALLOWED_EMAILSto limit who can sign in.Start it and check that it is up:
docker compose up -d curl http://127.0.0.1:8000/healthzPut a reverse proxy with https in front of
127.0.0.1:8000(see below) and openPUBLIC_URL/loginin a browser to check that you can sign in with your Docmost account.Connect a client (see Connecting a client).
The server applies its database migrations at startup. Back up the Postgres
volume like you back up Docmost: it holds the encrypted sessions, the
snapshots and the audit log. Losing SECRET_KEY signs every member out and
makes the snapshots unreadable.
# docmost-mcp-remote: the server and its Postgres.
# Copy .env.example to .env and fill in the required values first, then put a
# reverse proxy with https in front of port 8000.
services:
server:
# "1" follows 1.x releases; set IMAGE_TAG to a full version such as 1.0.0 to pin one.
image: ghcr.io/bbik52/docmost-mcp-remote:${IMAGE_TAG:-1}
restart: unless-stopped
environment:
PUBLIC_URL: ${PUBLIC_URL:?set PUBLIC_URL to the public https URL of this server}
DOCMOST_URL: ${DOCMOST_URL:?set DOCMOST_URL to the base URL of your Docmost}
DOCMOST_ALLOW_INSECURE_HTTP: ${DOCMOST_ALLOW_INSECURE_HTTP:-false}
DATABASE_URL: postgresql://docmost_mcp:${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD}@postgres:5432/docmost_mcp
SECRET_KEY: ${SECRET_KEY:?set SECRET_KEY to a random value of at least 32 characters}
SECRET_KEY_PREVIOUS: ${SECRET_KEY_PREVIOUS:-}
ALLOWED_EMAILS: ${ALLOWED_EMAILS:-}
ALLOWED_SPACES: ${ALLOWED_SPACES:-}
RELOGIN_MODE: ${RELOGIN_MODE:-ask}
SNAPSHOT_RETENTION_DAYS: ${SNAPSHOT_RETENTION_DAYS:-30}
AUDIT_RETENTION_DAYS: ${AUDIT_RETENTION_DAYS:-90}
TOOL_CALLS_PER_MINUTE: ${TOOL_CALLS_PER_MINUTE:-60}
MAX_PAGE_CHARS: ${MAX_PAGE_CHARS:-60000}
# The port is published on 127.0.0.1 only, so every client is a local proxy.
FORWARDED_ALLOW_IPS: ${FORWARDED_ALLOW_IPS:-*}
LOG_LEVEL: ${LOG_LEVEL:-info}
ports:
- "127.0.0.1:8000:8000"
depends_on:
postgres:
condition: service_healthy
read_only: true
tmpfs:
- /tmp
cap_drop:
- ALL
security_opt:
- no-new-privileges:true
postgres:
image: postgres:17-alpine
restart: unless-stopped
environment:
POSTGRES_USER: docmost_mcp
POSTGRES_DB: docmost_mcp
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD}
volumes:
- postgres-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U docmost_mcp -d docmost_mcp"]
interval: 10s
timeout: 5s
retries: 5
volumes:
postgres-data:The server is also on PyPI (pip install docmost-mcp-remote or
uvx docmost-mcp-remote) for setups without containers; it needs Postgres
and the same settings as environment variables.
Reverse proxy
The server listens on plain http and expects a reverse proxy that terminates https. Serve it at the root of its own host name; a sub-path is not supported. The proxy must not buffer responses, because MCP streams them.
Caddy (gets certificates by itself):
mcp.example.com {
reverse_proxy 127.0.0.1:8000
}nginx:
server {
listen 443 ssl;
server_name mcp.example.com;
ssl_certificate /etc/letsencrypt/live/mcp.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mcp.example.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_buffering off;
proxy_read_timeout 1h;
}
}The server uses X-Forwarded-For for its per-IP rate limits. The compose
file publishes the port on 127.0.0.1 only and trusts the header from every
client; if you publish the port elsewhere, set FORWARDED_ALLOW_IPS to the
proxy's address.
Connecting a client
The MCP endpoint is PUBLIC_URL/mcp, for example
https://mcp.example.com/mcp. Clients that support MCP authorization open a
browser window: sign in with your Docmost email and password and choose what
the client may do. read is always granted; tick write or delete only
for clients you trust.
Claude.ai and Claude Desktop: Settings, Connectors, Add custom connector, then enter the endpoint URL. The server must be reachable from the internet over https for Claude.ai.
Claude Code:
claude mcp add --transport http docmost https://mcp.example.com/mcpThen run /mcp in Claude Code to sign in.
Cursor (~/.cursor/mcp.json):
{
"mcpServers": {
"docmost": { "url": "https://mcp.example.com/mcp" }
}
}VS Code (.vscode/mcp.json):
{
"servers": {
"docmost": { "type": "http", "url": "https://mcp.example.com/mcp" }
}
}With a personal token (scripts and clients without OAuth):
Open
PUBLIC_URL/loginand sign in with your Docmost email and password.On the account page, create a personal token with the scopes you need.
Configure the client with the endpoint and the header
Authorization: Bearer <token>:claude mcp add --transport http docmost https://mcp.example.com/mcp \ --header "Authorization: Bearer dmr_..."
Connected apps and tokens are listed and revoked on the account page,
PUBLIC_URL/account.
Administration
The admin command runs where the server runs, with the same environment:
docker compose exec server docmost-mcp-remote admin members
docker compose exec server docmost-mcp-remote admin migrate
docker compose exec server docmost-mcp-remote admin grants anna@example.com
docker compose exec server docmost-mcp-remote admin revoke-grant <grant id>
docker compose exec server docmost-mcp-remote admin revoke-member anna@example.com
docker compose exec server docmost-mcp-remote admin disable-member anna@example.com
docker compose exec server docmost-mcp-remote admin audit --email anna@example.comrevoke-member revokes every grant of the member and drops their stored
Docmost session; disable-member blocks them until enable-member. Every
tool call is recorded in the audit log with the tool, the page or space id
and the outcome, never with content or arguments.
To rotate SECRET_KEY: set the old value as SECRET_KEY_PREVIOUS and a new
SECRET_KEY, restart, run admin rotate-key, then remove
SECRET_KEY_PREVIOUS and restart again.
Upgrading
Read the changelog for "Upgrade notes".
Back up the database:
docker compose exec -T postgres pg_dump -U docmost_mcp -Fc docmost_mcp > docmost-mcp-$(date +%F).dumpPull the new image and restart:
docker compose pull && docker compose up -d
The server upgrades its database schema at startup, in one transaction and
one process at a time, so a failed upgrade leaves the old schema in place.
docker compose exec server docmost-mcp-remote admin migrate shows the
schema revision.
The image tag 1 follows 1.x releases; set IMAGE_TAG in .env to pin a
version. Going back to an older version after its schema was upgraded is not
supported: an older server refuses to start on a newer schema. To roll back,
restore the backup with the old image:
docker compose stop server
docker compose exec -T postgres pg_restore -U docmost_mcp -d docmost_mcp --clean --if-exists < docmost-mcp-2026-01-31.dump
IMAGE_TAG=1.0.0 docker compose up -dConfiguration
Variable | Required | Default | Meaning |
| yes | Public https URL of this server | |
| yes | Base URL of your Docmost | |
| no |
| Allow an |
| yes | Postgres URL ( | |
| yes | At least 32 characters; encrypts stored Docmost sessions and signs cookies | |
| no | The old key during a rotation | |
| no | empty | Comma-separated emails allowed to sign in; empty allows every Docmost user |
| no | empty | Comma-separated space slugs or ids members may use through this server; empty allows all |
| no |
| Longest page body returned; longer bodies are truncated |
| no |
| Days a snapshot of a page body is kept |
| no |
| Days an audit log entry is kept |
| no |
| Tool calls one member may make per minute, over all their clients |
| no |
|
|
| no |
| Timeout for one request to Docmost |
| no |
| Largest Docmost response the server reads |
| no |
| Proxies trusted for |
| no |
| Listen address |
| no |
|
|
| no |
| Image tag used by |
Development
uv sync
uv run ruff check . && uv run ruff format --check .
uv run mypy
DATABASE_TEST_URL=postgresql://test:test@localhost:5433/test uv run pytestTests that need Postgres are skipped without DATABASE_TEST_URL; for example
docker run -d -p 5433:5432 -e POSTGRES_USER=test -e POSTGRES_PASSWORD=test postgres:17-alpine.
Integration tests run against a real Docmost:
DOCMOST_VERSION=0.97.0 docker compose -f tests/integration/compose.yaml up -d
DOCMOST_TEST_URL=http://localhost:3000 uv run pytest tests/integrationTo run the compose stack with a local build:
docker build -t ghcr.io/bbik52/docmost-mcp-remote:dev .
IMAGE_TAG=dev docker compose up -dSee CONTRIBUTING.md and the roadmap. Русская версия: README.ru.md.
License
Apache License 2.0. The license does not cover the project name: forks are welcome under another name. This project is an independent implementation and is not affiliated with Docmost. It was inspired by docmost-mcp-oss.
This server cannot be deployed
Maintenance
Related MCP Connectors
- hiveWikiOAuthai.hivewiki
Shared project wiki for AI agents: read and write pages, next actions, and activity logs over MCP.
Hosted markdown project wikis your team's AI assistants read, search, and update over MCP.
OAuth 2.1 short-link tools for AI agents with scoped tokens, approvals, audit logs, and revocation.
Governed memory and workspace for any AI: tasks, calendar, mail and pages, with per-action consent.
Related MCP Servers
- AlicenseNot gradedqualityBmaintenanceEnables AI assistants to turn conversations into a searchable personal wiki, read and organize pages, and propose edits such as merges, translations, and fact-checks as reviewable changesets.2MIT
- AlicenseNot gradedqualityAmaintenanceEnables LLM clients to read, search, create, edit, move, and delete pages and files across any MediaWiki wiki, including extension data from Wikibase, Semantic MediaWiki, Cargo, Bucket, and NeoWiki. Supports multiple wikis with per-wiki resources and OAuth-backed permissions.8 npmMIT
- AlicenseNot gradedqualityAmaintenanceEnables LLM clients to read, search, create, edit, manage, and upload content across any MediaWiki wiki, including extension-backed querying and OAuth-authenticated writes.8 npmMIT
- FlicenseNot gradedqualityAmaintenanceEnables AI assistants to search, read, create, edit, and archive documents, manage collections, add and view threaded comments, find backlinks, and access content through direct resource URIs with automatic rate limiting.-