doc-search
OfficialClick on "Install 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., "@doc-search仕訳の二重登録を防ぐ仕組みは?"
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.
doc-search — Hybrid Search + RAG Chat for Document Repositories
A hybrid search engine combining keyword search (BM25) × vector search (semantic search) for an internal document repository (glossary, review criteria, design documents), plus a RAG chat (Claude API, model selection, streaming output) built on top of it.
The UI design follows SodaShikenn/LLM-RAG_KBQA (left sidebar: model selection / knowledge settings / conversation history; right: chat + Send / Cancel).
Four ways to use it:
RAG chat (
/) — Pick a model and ask a question. Search → stream answers with citationsSearch explorer (
/search.html) — Incremental search, KW/VEC/RRF score displayCLI —
docsearch search "..."MCP server — Registered as a tool for Claude Code (Agentic RAG)
Setup (lightweight: no ML dependencies, ~30MB)
cd doc-search
brew install uv # 未導入の場合
uv venv --python 3.12 .venv
uv pip install -p .venv/bin/python -r requirements.txt
cp .env.example .env # ANTHROPIC_API_KEY を記入(チャット用)Only when using a local embedding model (e5 / bge-m3), add the heavy ML stack:
uv pip install -p .venv/bin/python -r requirements-local.txtRelated MCP server: LLMDoc
Usage
# 1) インデックス構築
.venv/bin/python -m docsearch index sample_docs # 自動選択
.venv/bin/python -m docsearch index /path/to/docs --embedder voyage # クラウド埋め込み
# 2) サーバー起動 → http://127.0.0.1:8765
.venv/bin/python -m docsearch serve --port 8765
# 3) CLI検索
.venv/bin/python -m docsearch search "解約率" --mode vectorEven without an API key, you can verify the chat UI behavior with the "Demo (offline)" model.
Choosing an embedding model (--embedder)
name | Location | Weight | Characteristics |
| Cloud | Zero local dependencies | voyage-3.5. Anthropic's recommended embedding partner. Top-tier quality. Requires |
| Local | ~470MB + torch | multilingual-e5-small. Fully local, a safe default for Japanese/English support |
| Local | ~2.2GB + torch | Higher-accuracy version of e5 |
| Local | ~2.3GB + torch | The strongest local-class multilingual model. However, it is the opposite of "lightweight" and CPU inference is also slow |
| Local | Zero dependencies | Character-hash (no semantic search, degraded mode) |
How to choose: If you want both quality and lightweight setup, go with voyage (when cloud is permitted).
If it must be fully local, use e5; for higher accuracy, bge-m3 (if you can tolerate the weight).
BM25 (lexical matching) always runs locally, so the embedding's role is only to absorb "paraphrases" —
model differences only matter there, and bge-m3's multi-vector/sparse features are unnecessary in this setup.
How chat (RAG) works
質問 → 検索の深さ(effort)を解決(auto は確信度シグナルで自動判断)
→ 検索実行(hard は選択モデルがクエリを言い換え → 全変種を検索して RRF 融合)
→ system プロンプトに参照資料として注入([n] path:line 付き)
→ Claude API へストリーミング要求(output_config.effort も連動)
→ data: {status|sources|delta|done|error} を SSE 配信
→ UI が逐次描画 + 「なぜこの検索をしたか」の説明 + 引用チップ。会話は localStorageSearch depth (effort) — hiding hybrid/keyword/vector
Users don't choose IR terminology. They only choose "how thoroughly to search," and what was actually done is shown in Japanese below the answer (e.g., "Auto → Thorough — no keyword matches… generated paraphrases and searched deeply").
effort | Behavior | When to use |
Auto (auto) | Probes once, then auto-selects easy/medium/hard based on confidence | Default. Use this when unsure |
Easy (easy) | One hybrid search, top 4 results. Model effort is also low | Direct term lookup. Fastest and cheapest |
Medium (medium) | Standard hybrid search, 6 results | Previous default behavior |
Thorough (hard) | The selected model generates 3 paraphrases → searches with all queries and fuses via RRF, 10 results. Model effort is high | Questions where the wording differs from the documents (e.g., "pay for overtime" → overtime premium) |
Auto decision signals: presence of keyword matches, strength of vector similarity, and top matches from both searches.
If paraphrase generation is unavailable (Demo model / no key set), hard automatically degrades to "expanded result count."
The raw search modes (keyword/vector/hybrid) remain available to engineers in /search.html and the CLI.
Models: Claude Opus 5 (default) / Sonnet 5 / Haiku 4.5 / Demo (offline)
Opus 5 enables server-side refusal fallback (when the model declines to answer for safety, it automatically falls back to an alternative model within the same request)
The generation API uses the official Anthropic SDK. The key is
ANTHROPIC_API_KEYin.env
Integration with Claude Code (MCP / Agentic RAG)
.mcp.json (in the target repository or home directory):
{
"mcpServers": {
"docsearch": {
"command": "/ABSOLUTE/PATH/doc-search/.venv/bin/python",
"args": ["-m", "docsearch.mcp_server"],
"env": { "DOCSEARCH_INDEX": "/ABSOLUTE/PATH/doc-search/index" }
}
}
}Tools: search_docs(query, mode, k) / docs_repo_info().
Since Claude Code itself handles query planning → re-search → file reading → cited answers,
Agentic RAG works inside the editor, separate from the chat UI.
Swapping in real data (on a machine with access permissions)
This repository only contains placeholders (sample_docs). The link to real data and the internal repository is swapped on the machine that has access, without any code changes. Priority order:
Environment variables (Docker uses these): in
.env, setDOCSEARCH_DOCS_HOST=/path/to/real-docs(the mount source into the container) andDOCSEARCH_GITHUB_BASE=https://github.example.com/org/repo/blob/mainConfig file (local execution):
cp datasource.example.json datasource.jsonthen editdocs_dir/github_base/embedder→docsearch index(no arguments).datasource.jsonis gitignored, so pointers to the internal repository are never pushedPlaceholder: if nothing is configured,
sample_docs/is indexed
The resolution logic is consolidated into a single function, get_datasource(), in docsearch/datasource.py.
GitHub links for citations
Search results, citation chips, and [path:line] in answers become deep links to the
corresponding lines on GitHub in the document repository (in the blob/<SHA-at-index-time>/path#L<line>
format, so line anchors don't break even as the repository advances).
Auto-detected at index time from the docs repository's
git remote(GHE also works)If auto-detection fails (e.g., when docs are mounted in Docker), set
DOCSEARCH_GITHUB_BASE=https://github.com/o/r/blob/main/docsin.env(or--github-basein the CLI)
Search engine design points
Japanese keyword search: CJK strings are expanded into bigrams and indexed in SQLite FTS5. On the query side, bigram phrase search handles adjacent matching (works without a morphological analyzer)
RRF fusion: BM25 scores and cosine similarity are scale-incompatible, so they are fused by rank
Breadcrumbs on chunks: The heading hierarchy is prepended to each chunk (in the glossary, headings = terms)
Interesting queries to try
Query | Expected result |
| Keyword search hits the glossary directly |
| Vector search discovers "churn rate" (paraphrase) |
| Answers citing idempotency / Idempotency-Key |
| Tenant isolation from security review criteria |
Deployment
Local resident (macOS / LaunchAgent)
bash deploy/install-launchd.sh # ログイン時自動起動・クラッシュ時自動再起動Logs:
logs/docsearch.log/logs/docsearch.err.logStop and remove:
launchctl bootout gui/$(id -u)/com.sodashikenn.docsearch && rm ~/Library/LaunchAgents/com.sodashikenn.docsearch.plistmacOS TCC note: If the repository is under a protected folder such as
~/Desktop, the python launched by launchd may be denied file access and enter a startup loop. In that case, grant python access permissions in "System Settings > Privacy & Security," or move the repository outside the protected area (e.g., to~/dev/)
Docker (fastest way to share with another machine)
git clone https://github.com/SodaShikenn/doc-search.git && cd doc-search
cp .env.example .env # ANTHROPIC_API_KEY を記入
docker compose up --build -d # → http://127.0.0.1:8765For a Mac without Docker (when not using Docker Desktop):
brew install colima docker docker-compose && colima start mkdir -p ~/.docker/cli-plugins && ln -sfn $(brew --prefix)/opt/docker-compose/bin/docker-compose ~/.docker/cli-plugins/docker-composeFor fully local vector search (recommended on M-series Macs with spare memory): write
WITH_LOCAL_ML=1andDOCSEARCH_EMBEDDER=e5in.env, then rundocker compose up --build -d(image ~2-3GB, first run includes model download. Embedding model changes are detected at startup and automatically re-indexed)Default slim image (~300MB): vector search uses the cloud if
VOYAGE_API_KEYis set, otherwise degrades to hash (keyword search always works fully)For real documents, replace
./sample_docs:/docs:roindocker-compose.yml; to re-index after content updates, runDOCSEARCH_REINDEX=1 docker compose up -dKeys are injected from the host's
.env(not baked into the image)There is no authentication. For public exposure, keep the local bind and use a reverse proxy (with auth) or VPN
Third-party
webui/vendor/ contains self-hosted third-party libraries, each under its own license:
marked v13.0.2 (MIT) and
DOMPurify 3.1.6 (Apache-2.0 OR MPL-2.0).
Everything else is MIT (see LICENSE).
Limitations and future work
Indexing is full rebuild only (incremental updates not implemented)
Conversation history is stored in browser localStorage (no server-side persistence)
Evaluation: it would be good to compare hybrid vs. individual modes and embedding models using recall@k on question → correct-file pairs
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceMCP server for semantic and hybrid search over RHEL documentation using docs2db RAG, with cross-encoder reranking and support for multiple MCP clients.4Apache 2.0
- AlicenseAqualityDmaintenanceMCP server for semantic search across llms.txt documentation sources, with hybrid two-stage retrieval and automatic background refresh.5MIT
- AlicenseNot gradedqualityDmaintenanceMCP server for documentation search that automatically indexes web documentation sites and provides semantic, full-text, or hybrid search capabilities.11MIT
- AlicenseNot gradedqualityBmaintenanceMCP server for local RAG over personal notes, PDFs, and documents, enabling plain-English querying and hybrid search with multi-hop context expansion.MIT
Related MCP Connectors
MCP server for AgentDocs (agentdocs.eu): read, search, write, comment on & share Markdown docs.
Hosted MCP memory: save sessions/decisions once, search from Claude, Cursor, ChatGPT. EU-hosted FTS.
Serve a folder of Markdown notes as an MCP server: hybrid search, reading, and sourced answers.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/SodaShikenn/doc-search'
If you have feedback or need assistance with the MCP directory API, please join our Discord server