qmd as an MCP server: hybrid doc search; embeddings/rerank via any OpenAI-spec provider.
261
qmd (fork of tobi/qmd) served as an MCP endpoint over HTTP, with embeddings and reranking done remotely against any OpenAI-spec provider (OpenAI, OpenRouter, your own gateway) — no local GGUF inference, no GPU.
On boot the container clones/mounts the sources you declare (git repos — private via token, optional subdir sparse-checkout and mask glob — or local folders), indexes and embeds them, then serves MCP. /mcp is protected by a bearer token (QMD_MCP_AUTH_TOKEN).
Standalone — no need to clone the repo, just this file plus a sources/sources.yaml:
services:
qmd-mcp:
image: josenerydev/qmd-mcp:latest
environment:
XDG_CACHE_HOME: /data
QMD_LLM_PROVIDER: remote
# any OpenAI-spec endpoint; the adapter appends /embeddings and /rerank
QMD_LLM_BASE_URL: https://openrouter.ai/api/v1
QMD_LLM_API_KEY: ${QMD_LLM_API_KEY:?set it in .env}
QMD_EMBED_MODEL: openai/text-embedding-3-small
QMD_RERANK_MODEL: cohere/rerank-4-fast
# bearer required on /mcp (leave unset = open endpoint, boot warning)
QMD_MCP_AUTH_TOKEN: ${QMD_MCP_AUTH_TOKEN:?set it in .env}
# optional: seconds between automatic pull + reindex + embed
REFRESH_INTERVAL: ${REFRESH_INTERVAL:-}
ports:
- "127.0.0.1:8181:8181"
volumes:
- qmd-data:/data # clones + index + vectors
- ./sources:/sources:ro # sources.yaml (+ local folders)
healthcheck:
test: ["CMD-SHELL", "wget -qO- http://localhost:8181/health"]
interval: 30s
timeout: 5s
retries: 3
start_period: 120s # first boot blocks until indexed
restart: unless-stopped
volumes:
qmd-data:
sources/sources.yaml next to it:
sources:
- name: docs
git: https://github.com/<org>/<repo> # private? add tokenEnv: MY_TOKEN (var in .env)
branch: main
# subdir: docs # optional: index only this folder (sparse-checkout)
# mask: "**/*.{md,txt}" # optional: files to index (default **/*.md)
context: "Product documentation."
# local folder — drop it inside ./sources/ (mounted read-only at /sources)
# - name: notes
# path: notes # host: ./sources/notes
# context: "Local notes."
Then:
printf 'QMD_LLM_API_KEY=...\nQMD_MCP_AUTH_TOKEN=...\n' > .env
docker compose up -d && docker compose logs -f qmd-mcp
curl http://localhost:8181/health
Full guide (env reference, MCP client setup for Claude Code/Cursor): deploy/README.md
Using an AI coding agent (Claude Code, Copilot, Codex…)? Install the repo's self-contained deploy-setup skill — it ships its own compose/env/sources templates and walks the agent through this whole setup:
mkdir -p ~/.claude/skills/deploy-setup && curl -fsSL https://github.com/josenerydev/qmd/tarball/main \
| tar -xz --strip-components=3 -C ~/.claude/skills/deploy-setup --wildcards '*/skills/deploy-setup/*'
Then ask the agent to "set up qmd-mcp".
| Variable | Purpose |
|---|---|
QMD_LLM_PROVIDER | remote (OpenAI-spec adapter) |
QMD_LLM_BASE_URL | Provider base URL — adapter appends /embeddings and /rerank |
QMD_LLM_API_KEY | Provider API key |
QMD_EMBED_MODEL / QMD_RERANK_MODEL | Model names in the provider's format |
QMD_MCP_AUTH_TOKEN | Bearer required on /mcp (empty = open, with a boot warning) |
REFRESH_INTERVAL | Optional seconds between automatic pull+reindex+embed |
Upstream search / query / get plus this fork's get_raw (raw file bytes of any type) and refresh (pull + reindex + embed on demand).
latest — tracks the fork's main2.6.3-fork.1 — immutable release of this buildContent type
Image
Digest
sha256:24980223e…
Size
1.2 GB
Last updated
2 months ago
docker pull josenerydev/qmd-mcp