11---
2- # QMD MCP Server
2+ # QMD Documentation Search
33# Local on-device search engine for the project documentation, agents, and workflow instructions
44#
55# Documentation: https://github.com/tobi/qmd
66#
7- # Available tools (via MCP):
8- # - query: Search with typed sub-queries (lex/vec/hyde), combined via RRF + reranking
9- # - get: Retrieve a document by path or docid (with fuzzy matching suggestions)
10- # - multi_get: Batch retrieve by glob pattern, comma-separated list, or docids
11- # - status: Index health and collection info
12- #
137# Usage:
148# imports:
159# - shared/mcp/qmd-docs.md
1610
17- mcp-servers :
18- qmd :
19- type : http
20- url : http://localhost:8181/mcp
21- allowed :
22- - query
23- - get
24- - multi_get
25- - status
26-
2711resources :
2812 - .github/workflows/qmd-docs-indexer.yml
2913
@@ -40,152 +24,29 @@ steps:
4024 path : ~/.cache/qmd
4125 key : qmd-docs-${{ hashFiles('docs/src/content/docs/**', '.github/agents/**', '.github/aw/**') }}
4226 restore-keys : qmd-docs-
43- - name : Start QMD MCP server
27+ - name : Register QMD collections
28+ run : |
29+ qmd collection add "${GITHUB_WORKSPACE}" --name gh-aw --glob "docs/src/content/docs/**,.github/agents/**,.github/aw/**" 2>/dev/null || true
30+
31+ mcp-scripts :
32+ qmd-query :
33+ description : " Find relevant file paths in project documentation using vector similarity search. Returns file paths and scores."
34+ inputs :
35+ query :
36+ type : string
37+ required : true
38+ description : " Natural language search query"
39+ min_score :
40+ type : number
41+ required : false
42+ default : 0.4
43+ description : " Minimum relevance score threshold (0–1)"
4444 run : |
4545 set -e
46- mkdir -p /tmp/gh-aw/mcp-logs/qmd/
47-
48- # Re-register collections so qmd MCP tools are available.
49- # The cache restore only restores the index data; qmd requires collections
50- # to be registered in the current session for MCP tools to be served.
51- DOCS_DIR="${GITHUB_WORKSPACE}/docs/src/content/docs"
52- AGENTS_DIR="${GITHUB_WORKSPACE}/.github/agents"
53- AW_DIR="${GITHUB_WORKSPACE}/.github/aw"
54-
55- [ -d "$DOCS_DIR" ] && qmd collection add "$DOCS_DIR" --name docs 2>/dev/null || true
56- [ -d "$AGENTS_DIR" ] && qmd collection add "$AGENTS_DIR" --name agents 2>/dev/null || true
57- [ -d "$AW_DIR" ] && qmd collection add "$AW_DIR" --name aw 2>/dev/null || true
46+ qmd query "$INPUT_QUERY" --files --min-score "${INPUT_MIN_SCORE:-0.4}"
5847
59- # Start QMD MCP server in the background (explicit nohup rather than
60- # --daemon to ensure the process survives the step and stays running)
61- nohup qmd mcp --http > /tmp/gh-aw/mcp-logs/qmd/server.log 2>&1 &
62- echo $! > /tmp/gh-aw/mcp-logs/qmd/server.pid
63- echo "QMD MCP server started (PID $(cat /tmp/gh-aw/mcp-logs/qmd/server.pid))"
64-
65- # Poll until the server is healthy (up to 15 seconds)
66- for i in $(seq 1 30); do
67- if curl -sf http://localhost:8181/health > /dev/null 2>&1; then
68- echo "QMD MCP server is healthy"
69- echo "Status: $(curl -s http://localhost:8181/health)"
70- break
71- fi
72- sleep 0.5
73- done
74-
75- if ! curl -sf http://localhost:8181/health > /dev/null 2>&1; then
76- echo "QMD MCP server health check timed out after 15 seconds"
77- echo "Server logs:"
78- cat /tmp/gh-aw/mcp-logs/qmd/server.log || true
79- exit 1
80- fi
81-
82- # Verify the MCP tools endpoint is responding with actual tools.
83- # Without this check, a server with no registered collections will pass
84- # the health check but return an empty tools list to the MCP Gateway.
85- for i in $(seq 1 20); do
86- TOOLS=$(curl -sf -X POST http://localhost:8181/mcp \
87- -H "Content-Type: application/json" \
88- -H "Accept: application/json, text/event-stream" \
89- -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' 2>/dev/null \
90- | grep -o '"name":"[^"]*"' | wc -l || echo "0")
91- if [ "$TOOLS" -gt "0" ]; then
92- echo "QMD MCP server started successfully with $TOOLS tools available"
93- exit 0
94- fi
95- sleep 1
96- done
97-
98- echo "QMD MCP server started but no tools available after 20 seconds"
99- echo "Server logs:"
100- cat /tmp/gh-aw/mcp-logs/qmd/server.log || true
101- exit 1
10248---
10349
104- <!--
105-
106- ## QMD MCP Server
107-
108- Provides the QMD MCP server for on-device documentation search over the project docs,
109- agent definitions, and workflow authoring instructions.
110-
111- QMD (Query Markup Documents) is a local search engine that combines BM25 full-text
112- search, vector semantic search, and LLM re-ranking — all running locally via
113- node-llama-cpp with GGUF models.
114-
115- This shared configuration indexes three collections and starts a local HTTP
116- MCP server for the agent to query:
117-
118- - `docs` — `docs/src/content/docs/` (documentation guides and reference)
119- - `agents` — `.github/agents/` (custom agent definitions and instructions)
120- - `aw` — `.github/aw/` (workflow authoring instructions and templates)
121-
122- ### Available Tools
123-
124- - **`query`** — Search with typed sub-queries
125- - Supports `lex` (BM25 keyword), `vec` (semantic), and `hyde` (LLM-expanded) query types
126- - Combined via RRF + reranking for best quality
127- - Parameters: `query` (string), `collections` (optional), `limit` (optional)
128-
129- - **`get`** — Retrieve a specific document by path or docid
130- - Supports fuzzy matching suggestions when path is not found
131- - Parameters: `path` (string, e.g. `"docs/guides/getting-started.md"` or `"#abc123"`)
132-
133- - **`multi_get`** — Batch retrieve by glob pattern or comma-separated list
134- - Parameters: `pattern` (string, e.g. `"docs/reference/*.md"`)
135-
136- - **`status`** — Index health and collection information
137- - Returns collection names, document counts, and MCP server uptime
138-
139- ### Setup
140-
141- Import this configuration in your workflow:
142-
143- ```yaml
144- imports:
145- - shared/mcp/qmd-docs.md
146- ```
147-
148- ### Example Usage
149-
150- ```yaml
151- ---
152- on: workflow_dispatch
153- engine: copilot
154- imports:
155- - shared/mcp/qmd-docs.md
156- ---
157-
158- # Documentation Search Workflow
159-
160- Use the qmd tool to search the project documentation and answer questions.
161-
162- 1. Use `status` to see what collections are indexed
163- 2. Use `query` with `lex` type for fast keyword search
164- 3. Use `get` to retrieve specific documentation pages
165- ```
166-
167- ### How It Works
168-
169- The QMD index is pre-built by the `qmd-docs-indexer.yml` workflow on every trusted push
170- to `main` (path-filtered to the indexed directories) and on a daily schedule. This ensures
171- the index always reflects verified content.
172-
173- At runtime (when this shared module is imported):
174-
175- 1. Node.js 24 is installed
176- 2. QMD is installed globally from npm (`@tobilu/qmd`)
177- 3. The pre-built qmd index is restored from `actions/cache` using a key derived from a hash of the docs, agents, and aw content
178- 4. Collections are re-registered in the current session (`docs`, `agents`, `aw`) — required even after cache restore for qmd MCP tools to be served
179- 5. The HTTP MCP server starts on `localhost:8181` (via `nohup`) and is verified to have tools available before the step completes
180-
181- The `query` tool supports BM25 full-text search (`lex` type) out of the box.
182- For semantic vector search (`vec`/`hyde` types), run `qmd embed` before starting
183- the server to generate local GGUF model embeddings.
184-
185- ### Documentation
186-
187- - **GitHub Repository**: https://github.com/tobi/qmd
188- - **npm Package**: https://www.npmjs.com/package/@tobilu/qmd
189- - **MCP Server docs**: https://github.com/tobi/qmd#mcp-server
190-
191- -->
50+ <qmd >
51+ Use ` qmd-query ` to find relevant documentation files with a natural language request — it queries a local vector database of project docs, agents, and workflow files. Read the returned file paths to get full content.
52+ </qmd >
0 commit comments