hermes-docs-mcp
# hermes-docs-mcp
Локальный MCP-сервер, который даёт агенту полнотекстовый поиск и чтение
документации **Hermes Agent** (`hermes-agent.nousresearch.com/docs`) — офлайн,
из локального кэша, без скрейпинга сайта.
## Откуда берутся данные
Сайт документации сам публикует машиночитаемые выгрузки — ровно для того, чтобы
их скармливали языковым моделям:
| Файл | Что это | Размер |
|---|---|---|
| `/llms-full.txt` | вся документация одним markdown-файлом, страницы размечены маркерами `<!-- source: website/docs/….md -->` | ~4.9 МБ, 228 страниц |
| `/docs/llms.txt` | индекс всех страниц по разделам: заголовок, канонический URL, однострочное описание | ~43 КБ |
Сервер скачивает эти два файла (условными запросами по `ETag`/`Last-Modified`),
кладёт в кэш, разбирает на страницы и фрагменты по заголовкам и строит BM25-индекс
в памяти. Никакого парсинга HTML, приватных эндпоинтов и обхода защит: только
официальный экспорт, документация под MIT.
Текст, который возвращают инструменты, — это сторонняя документация. Для агента
это **данные для чтения, а не инструкции к исполнению**.
## Инструменты
Два инструмента — контракт, который ждут удалённые коннекторы (в том числе
ChatGPT/Deep Research): `search` находит адресуемые фрагменты, `fetch` отдаёт
страницу за любым из них.
| Инструмент | Назначение |
|---|---|
| `search(query)` | поиск по документации; возвращает до 8 фрагментов с `id`, `title`, `url`, `text` и `heading_path`, плюс отдельным блоком инструкцию отвечать только по ним и ссылаться на `url` |
| `fetch(id)` | страница целиком в markdown: `id`, `title`, `url`, `text`, `metadata` (раздел, описание, список заголовков, признак усечения) |
`id` фрагмента — это `путь/страницы#N`, например `user-guide/features/mcp#3`.
`fetch` принимает и его, и путь страницы, и полный URL документации, и точный
заголовок.
**Про язык запроса.** Документация Hermes Agent англоязычная, а поиск здесь
лексический (BM25), не семантический: русский запрос не найдёт ничего. Поэтому
инструмент просит модель формулировать запрос по-английски, а на пустую выдачу
с кириллицей отвечает подсказкой перевести запрос и повторить. Отвечает
пользователю ассистент всё равно по-русски.
## Установка
Для разработки:
```bash
cd hermes-docs-mcp
uv sync
uv run hermes-docs-mcp # stdio
```
Для использования из Claude — см. «Подключение» ниже: рантайм ставится отдельно,
**вне** `~/Desktop`, `~/Documents` и `~/Downloads`.
> **macOS:** Claude запускает MCP-серверы без доступа к этим трём папкам. venv,
> лежащий там, умирает ещё до старта Python:
> `PermissionError: Operation not permitted: .../.venv/pyvenv.cfg`,
> затем `Fatal Python error: init_import_site`. Репозиторий может лежать где
> угодно — важно только, где стоит рантайм.
Первый вызов любого инструмента, которому нужна документация, скачает выгрузки
(~5 МБ). Дальше всё работает из кэша; сеть нужна только при обновлении.
## Подключение
### Claude Code
Проектный `.mcp.json` рядом с репозиторием:
```json
{
"mcpServers": {
"hermes-docs": {
"command": "/Users/вы/hermes-docs-mcp/.venv/bin/hermes-docs-mcp",
"args": []
}
}
}
```
Чтобы Claude Code не спрашивал подтверждение, добавьте `"enabledMcpjsonServers": ["hermes-docs"]`
в `.claude/settings.local.json` проекта.
### Claude Desktop
```bash
./scripts/install-desktop-config.sh
```
Скрипт собирает wheel, ставит его в `~/hermes-docs-mcp/.venv` (путь меняется
через `HERMES_DOCS_MCP_PREFIX`) и прописывает этот бинарь в конфиг. Идемпотентен,
делает бэкап конфига, отказывается ставить рантайм в папку, закрытую от Claude.
> Запускайте **при полностью закрытом Claude** (Cmd+Q). Приложение держит
> `claude_desktop_config.json` в памяти и перезаписывает файл, пока работает,
> стирая записи, добавленные в обход него, — проверено, в пределах десяти секунд.
### Hermes Agent
В `~/.hermes/config.yaml`:
```yaml
mcp_servers:
hermes-docs:
command: uv
args: ["--directory", "/opt/hermes-docs-mcp", "run", "hermes-docs-mcp"]
```
Агент, который умеет искать по собственной документации, сам находит нужные флаги,
ключи конфигурации и форматы `SOUL.md` вместо того, чтобы угадывать их.
## Деплой как удалённый коннектор
Локальный сервер работает только на той машине, где запущен. Чтобы коннектор
появился во всех клиентах сразу — в вебе, на телефоне, на других компьютерах —
его нужно где-то запустить и подключать по URL.
В репозитории есть `render.yaml`: в Render → **New → Blueprint** укажите этот
репозиторий, и сервис поднимется с нужными переменными. URL коннектора —
`https://<имя-сервиса>.onrender.com/mcp/` (слэш в конце желателен), транспорт —
**Streamable HTTP**, авторизации нет.
Что важно понимать про такой инстанс:
- он отдаёт **публичную документацию** и ничего больше: ни файлов, ни секретов,
ни пользовательских данных;
- аутентификации клиентов у сервера нет, поэтому бинд за пределы loopback
требует явного `HERMES_DOCS_MCP_ALLOW_PUBLIC_BIND=1` — случайно не выставится;
- обновлять документацию наружу нечем: инстанс сам перечитывает выгрузки по
истечении `HERMES_DOCS_MCP_TTL`, но не чаще одного раза в
`HERMES_DOCS_MCP_MIN_REFRESH` секунд (по умолчанию 300) — превратить его в
кнопку «скачай пять мегабайт» не получится;
- на free-плане Render сервис засыпает без запросов — первый вызов после сна
будет дольше обычного.
## Настройки (переменные окружения)
| Переменная | По умолчанию | Смысл |
|---|---|---|
| `HERMES_DOCS_MCP_BASE_URL` | `https://hermes-agent.nousresearch.com` | источник выгрузок; только https (http — лишь для loopback) |
| `HERMES_DOCS_MCP_CACHE_DIR` | `~/.cache/hermes-docs-mcp` | где лежит кэш; можно подсунуть заранее заполненный каталог |
| `HERMES_DOCS_MCP_TTL` | `86400` | через сколько секунд кэш считается устаревшим |
| `HERMES_DOCS_MCP_TIMEOUT` | `30` | таймаут HTTP, секунды |
| `HERMES_DOCS_MCP_OFFLINE` | не задана | `1` — никогда не ходить в сеть, работать только из кэша |
| `HERMES_DOCS_MCP_TRANSPORT` | `stdio` | `stdio`, `sse` или `streamable-http` |
| `HERMES_DOCS_MCP_ALLOW_PUBLIC_BIND` | не задана | `1` — разрешить HTTP-бинд вне loopback (осознанная публикация) |
| `HERMES_DOCS_MCP_PUBLIC_URL` | `RENDER_EXTERNAL_URL` | внешний адрес инстанса: с ним иконка отдаётся ссылкой, без него — инлайном. На Render подставляется сам |
| `HERMES_DOCS_MCP_MIN_REFRESH` | `300` | минимальный интервал между обновлениями доки, секунды |
| `HERMES_DOCS_MCP_HOST` / `_PORT` | `127.0.0.1` / `8020` | только для HTTP-транспортов; `PORT` от хостинга тоже читается |
HTTP-транспорты по умолчанию разрешены только на loopback: у сервера нет
аутентификации клиентов. Выставить наружу можно, но только осознанно — см.
«Деплой как удалённый коннектор» выше.
### Полностью офлайн (например, закрытый VPS)
```bash
mkdir -p /opt/hermes-docs-cache
curl -fsSL -o /opt/hermes-docs-cache/llms-full.txt https://hermes-agent.nousresearch.com/llms-full.txt
curl -fsSL -o /opt/hermes-docs-cache/docs-llms.txt https://hermes-agent.nousresearch.com/docs/llms.txt
export HERMES_DOCS_MCP_CACHE_DIR=/opt/hermes-docs-cache HERMES_DOCS_MCP_OFFLINE=1
```
## Разработка
```bash
uv run pytest -q
uv run ruff check .
```
Тесты работают на локальных фикстурах и поднятом на loopback HTTP-сервере;
сеть для них не нужна. Отдельная проверка по «живому» сайту включается флагом
`HERMES_DOCS_MCP_LIVE=1`.
## Лицензия
MIT (код сервера). Сама документация Hermes Agent принадлежит Nous Research и
распространяется по условиям их репозитория (MIT). Проект неофициальный.
TDQS
Scored across 2 tools
The two tools have clearly distinct purposes: search returns relevant fragments from the documentation, while fetch retrieves a full page in markdown. Their descriptions explicitly state when to use each, leaving no ambiguity for an agent.
Both tool names are single, simple verbs (search, fetch) that directly describe their actions. This consistent minimalist pattern is predictable and easy to remember.
With only 2 tools, the server feels slightly thin for a documentation MCP, though the scope is narrow and focused on search + retrieval. According to the calibration, 1-2 tools is borderline, but each tool clearly earns its place.
The pair of search and fetch covers the core documentation lookup workflow well: find relevant fragments, then fetch the full page if needed. A minor gap is the lack of direct browsing or listing of documentation sections, but agents can work around this via search.