Athena MCP
Athena
Персональная вики, в которую пишет ваш ИИ, и вы можете просматривать её сами.
Athena размещает MCP-сервер перед Wiki.js. Ваш ассистент ищет в вики, читает страницы и сохраняет новые: заметки, документацию, целые разговоры. Всё, что он пишет, — это обычная Markdown-страница, которую вы можете открыть, редактировать и хранить долго после того, как какая-либо конкретная модель исчезнет.
Claude / ChatGPT / Cursor
│ MCP over HTTPS
▼
athena-mcp ──── search ──▶ Wiki.js (keyword) + Postgres (meaning)
│ read ────▶ Wiki.js
└──────── write ───▶ Wiki.js ──▶ athena-indexer ──▶ PostgresWiki.js хранит истину. Векторный индекс только помогает находить вещи и может быть удалён и перестроен в любое время.
Запуск | |
Использование | |
Реальный запуск | |
Справочник |
Быстрый старт
Локально, примерно за пять минут. Для всего, что в интернете, сначала прочитайте Развернуть на сервере.
git clone https://github.com/jannismilz/athena.git
cd athena
cp .env.example .env
$EDITOR .env # fill in every CHANGE_ME, one per secret:
# openssl rand -hex 32
docker compose up -dОткройте Wiki.js и завершите мастер настройки.
В Wiki.js: Администрирование → API, включите его, создайте токен и поместите его в
.envкакWIKI_API_TOKEN.Снова выполните
docker compose up -d, чтобы он подхватился.Откройте панель управления и войдите с помощью
DASHBOARD_TOKEN.
Данные записываются в каталог data/ рядом с копией репозитория, не внутри него, поэтому никакая операция git никогда не сможет их удалить. Измените ATHENA_DATA_DIR, если хотите другое расположение.
Ничто не публикует порт, поэтому обращайтесь к сервисам через ваш обратный прокси или добавьте временное сопоставление ports: при тестировании.
При первом запуске загружается модель эмбеддингов размером несколько сотен МБ. Индексатор повторяет попытки, пока она не будет готова, поэтому ожидается, что embeddings будет выглядеть нездоровым в течение минуты-двух при первой загрузке.
Related MCP server: wiki-js-mcp
Подключите свой ИИ
Всё обслуживается с MCP_PUBLIC_URL, который должен быть голым https://-источником без пути. Не /mcp.
Claude.ai → Settings → Connectors → Add custom connector
URL:
https://athena-mcp.example.com/mcpОставьте client ID и secret пустыми. Athena регистрирует клиента сама.
Страница браузера запрашивает пароль. Это ваш
MCP_TOKEN.
Cursor, Claude Desktop, and other header clients
{
"mcpServers": {
"athena": {
"url": "https://athena-mcp.example.com/mcp",
"headers": { "Authorization": "Bearer YOUR_MCP_TOKEN" }
}
}
}Инструменты
Инструмент | Что делает |
| Ключевой и семантический поиск, объединённые. Каждый результат содержит путь. |
| Полный Markdown одной страницы |
| Структура заголовков, без тела |
| Добавить под заголовок, оставив остальное нетронутым |
| Новая страница Markdown |
| Заменить тело страницы |
| Переместить или переименовать |
| Удалить и убрать из индекса |
| Сохранить разговор в |
| Быстрая заметка в |
| Всё, с путями и временными метками |
| Размер, структура и устаревание, чтобы ИИ мог ответить, чего не хватает |
append_to_page — это тот, о котором стоит знать: добавление факта стоит одного абзаца, а не переписывания всей страницы.
Почему он хорошо ищет. Точные термины попадают в полнотекстовый индекс Wiki.js, расплывчатые вопросы — в векторный индекс, а результаты объединяются с помощью реципрокного рангового слияния, так что ни один источник не может подавить другой. Фрагменты записывают заголовки над ними, поэтому возвращаемые данные сохраняют свой контекст. Каждая страница, к которой прикасается ассистент, помечается тем, какой именно ассистент и когда, взято из аутентифицированного клиента, а не из того, что модель утверждает о себе.
Панель управления
Отдельный сервис, на порту 8082. Вход с помощью DASHBOARD_TOKEN; токена нет ни в одном URL. Для скриптов используйте заголовок Bearer:
curl -H "Authorization: Bearer $DASHBOARD_TOKEN" \
https://wiki.example.com/dashboard/api/metrics?days=30Панель | Ответы |
Контент | страницы, слова, по областям, самые большие, устаревающие |
Активность ИИ | вызовов в день, какие инструменты, какой ассистент, чтение vs запись |
Поиски, ничего не нашедшие | то, на что ваша вики не смогла ответить |
Здоровье индекса | сохранённые чанки, проиндексированные страницы, насколько отстаёт |
Резервное копирование | когда завершился последний запуск, размер, куда пошло |
Третья строка — та, которая оправдывает своё место. Каждая запись — это страница, которую стоит написать.
Она дважды только для чтения: она никогда не пишет, и подключается к Postgres как athena_readonly — роль, имеющая только SELECT и ничего больше. Показатели агрегируются в Postgres и кэшируются, поэтому обновление почти ничего не стоит.
Развернуть на сервере
VPS с 4 ГБ ОЗУ запускает всё, включая модель эмбеддингов на CPU.
1. Хост и брандмауэр
sudo ufw default deny incoming && sudo ufw default allow outgoing
sudo ufw allow 22/tcp && sudo ufw allow 80/tcp && sudo ufw allow 443/tcp
sudo ufw enableУстановите Docker, затем создайте пользователя, владеющего развёртыванием:
sudo useradd --create-home --shell /bin/bash athena
sudo usermod -aG docker athenaЗапускайте compose от имени этого пользователя, никогда с sudo, иначе привязки монтирования окажутся принадлежащими root. Членство в группе docker эквивалентно root на хосте, поэтому держите её небольшой.
2. DNS
Две A-записи, указывающие на хост:
Имя | Обслуживает |
| Wiki.js и панель управления по адресу |
| конечную точку MCP |
3. Размещение и настройка
Всё, что пишет Athena, проходит через одну настройку, ATHENA_DATA_DIR, поэтому вся установка может жить в одном каталоге. Используйте два подкаталога с разными жизненными циклами:
/athena
├── app/ the git repository replaceable, thrown away on every upgrade
└── data/ postgres, state, irreplaceable, never touched by git
uploads, backupsОни являются соседями, а не вложенными, и в этом вся суть. data/ находится в .gitignore, а git clean -xdf удаляет игнорируемые файлы, поэтому данные внутри копии репозитория находятся на расстоянии одной рутинной команды от уничтожения без подтверждения и отмены. Соседний каталог недоступен для любой операции git.
sudo mkdir -p /athena && sudo chown athena:athena /athena
cd /athena
git clone https://github.com/jannismilz/athena.git app
cd app
cp .env.example .env
chmod 600 .env # it holds every secretATHENA_DATA_DIR по умолчанию равен ../data, который разрешается относительно каталога, содержащего файл compose. Клонируйте в /athena/app, как указано выше, и данные окажутся в /athena/data без необходимости настройки. Установите секреты:
POSTGRES_PASSWORD=...
MCP_TOKEN=...
DASHBOARD_TOKEN=...
DASHBOARD_DB_PASSWORD=...
MCP_PUBLIC_URL=https://athena-mcp.example.com
WIKI_PUBLIC_URL=https://wiki.example.comCompose создаёт /athena/data и его подкаталоги при первом запуске. Выполняйте все команды docker compose из /athena/app.
/athena/data
├── postgres/ the wiki, users, settings, uploads, activity log, vectors
├── wikijs/ Wiki.js config, cache, upload cache
├── mcp/ oauth-state.json, the tokens issued to AI clients
├── indexer/ index bookkeeping, rebuilt automatically if lost
├── embeddings/ the downloaded model
└── backups/ local dumps plus status.jsonТолько postgres/ незаменим, и контейнер резервного копирования дампит его каждый час. Всё остальное либо регенерируется автоматически, либо стоит одного переподключения.
Если вы предпочитаете следовать соглашению об иерархии файловой системы, поместите данные в /srv/athena, а копию репозитория в /opt/athena. Расположение с единым корнем, описанное выше, проще на машине, выполняющей одну задачу, и любой вариант работает: решает только ATHENA_DATA_DIR.
4. Обратный прокси
Ни один контейнер не публикует порт. Сервисы находятся в двух сетях:
athena, внутренняя. Postgres, модель эмбеддингов и индексатор живут только здесь, поэтому скомпрометированный прокси не может добраться до базы данных.athena-edge, к которой подключается ваш обратный прокси. Только три сервиса ниже находятся на ней.
Маршрутизируйте их:
Хост | Куда | Примечания |
|
| Обновление WebSocket, лимит тела 100M |
|
| |
|
| не должен буферизовать, потоки MCP |
Передавайте X-Forwarded-For: логины ограничиваются по адресу, и без него каждая попытка выглядит так, как будто пришла от прокси.
Запустите nginx как контейнер, подключённый к сети athena-edge, как показано ниже, или на хосте с сопоставлением ports:, привязанным к 127.0.0.1. Подключение к edge-сети означает, что прокси может достичь Wiki.js, MCP-сервера и панели управления, и ничего больше.
server {
listen 80;
server_name wiki.example.com;
location / {
proxy_pass http://wikijs:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
client_max_body_size 100M;
proxy_read_timeout 120s;
}
location /dashboard/ {
proxy_pass http://dashboard:8082/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
server {
listen 80;
server_name athena-mcp.example.com;
location / {
proxy_pass http://mcp:8080;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# MCP streams responses. Without these, long tool calls appear to hang.
proxy_set_header Connection "";
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 300s;
}
}Затем выпустите сертификаты с помощью certbot или завершайте TLS там, где вы это уже делаете.
Здесь нет ничего специфичного для платформы. PaaS, которая запускает Compose и предоставляет собственный прокси, нуждается в трёх настройках, все в .env:
ATHENA_DATA_DIR=../files # Dokploy's persistent directory
ATHENA_EDGE_NETWORK=dokploy-network
ATHENA_EDGE_EXTERNAL=trueATHENA_DATA_DIR наиболее важен: Dokploy очищает абсолютные пути привязки монтирования при повторном развёртывании, поэтому абсолютный путь там уничтожит базу данных. Относительный путь к каталогу приложения сохраняется.
Затем добавьте домены в интерфейсе платформы, указывая на сервис и его порт:
Домен | Сервис | Порт |
|
| 3000 |
|
| 8080 |
|
| 8082 |
Платформа генерирует собственные метки маршрутизации и обрабатывает TLS, поэтому полностью пропустите раздел nginx. Всё остальное, включая файл compose, без изменений.
Вам не нужно публиковать образы в реестре: Dokploy собирает из репозитория. Сборка четырёх образов конкурирует с Postgres и моделью эмбеддингов за память, поэтому на маленьком хосте вы можете предпочесть сборку в CI и загрузку вместо этого.
5. Запустите, затем заблокируйте вики
docker compose up -d && docker compose psЗавершите мастер Wiki.js немедленно. Пока вы этого не сделаете, любой, кто найдёт хост, может получить администраторскую учётную запись. Затем в Wiki.js:
Группы → Гости: удалите доступ на чтение, если вы не хотите, чтобы вики была публичной.
Аутентификация: отключите самостоятельную регистрацию.
API: включите его и создайте токен для
WIKI_API_TOKEN.
6. Проверка
curl -s https://athena-mcp.example.com/health
# Must reject unauthenticated calls:
curl -s -o /dev/null -w '%{http_code}\n' -X POST https://athena-mcp.example.com/mcp
# expected: 401Резервное копирование
Один pg_dump — это полная резервная копия. Wiki.js хранит страницы, историю, пользователей, разрешения, настройки и байты каждого загруженного файла в Postgres. Загрузки находятся в таблице assetData; файлы в data/wikijs/uploads — только кэш. Журнал активности Athena и векторы поиска находятся во второй базе данных на том же сервере.
Данные | В резервной копии |
Страницы, история, пользователи, настройки | да |
Загруженные изображения и файлы | да |
Журнал активности и векторы поиска | да |
Учётные данные индекса, регистрации OAuth | нет, перестраивается или переподключается |
| нет, храните копию в менеджере паролей |
Контейнер backup запускается каждый час. Каждый запуск дампит обе базы данных, проверяет, что каждый дамп читаем, сохраняет локальную копию, отправляет в ваш пункт назначения rclone, проверяет соответствие загрузки и только затем удаляет старые. Неудачный запуск никогда не сможет удалить вашу последнюю хорошую резервную копию.
docker compose run --rm backup now # take one now
docker compose run --rm backup restore list # see what exists
docker compose logs -f backup # watch the scheduleНастройте всё в .env. Подходит любой rclone-назначение: S3, Backblaze, Wasabi, MinIO, Hetzner. Оставьте BACKUP_REMOTE пустым, чтобы хранить резервные копии только на хосте.
Добавьте crypt-удалённый ресурс и укажите BACKUP_REMOTE на него. Тогда назначение будет получать только шифротекст, включая имена файлов.
BACKUP_REMOTE=crypt:
RCLONE_CONFIG_CRYPT_TYPE=crypt
RCLONE_CONFIG_CRYPT_REMOTE=s3:my-bucket/athena
RCLONE_CONFIG_CRYPT_PASSWORD=<rclone obscure ...>
RCLONE_CONFIG_CRYPT_PASSWORD2=<rclone obscure ...>Храните оба пароля в своём менеджере паролей. Без них резервные копии нечитаемы, в том числе вами.
Восстановление
Потренируйтесь в этом до того, как понадобится. Восстановление, которое никто не запускал, — это догадка.
docker compose run --rm backup restore list
docker compose stop wikijs mcp indexer dashboard
docker compose run --rm backup restore run 2026-08-18T115529Z
docker compose start wikijs mcp indexer dashboardОно попросит ввести имя базы данных для подтверждения. restore fetch <stamp> загружает резервную копию без восстановления и сообщает, читаем ли каждый дамп.
Поисковый индекс восстанавливается сам после этого: индексатор перечитывает каждую страницу и заново встраивает всё, содержимое чего изменилось.
Конфигурация
Всё берётся из окружения. Каждый сервис проверяет свою конфигурацию при запуске и завершается со списком того, что не так, так что опечатка проявляется сразу, а не в три часа ночи.
Пять секретов, все созданы вами. Никакие учётные данные, принадлежащие Claude, OpenAI или кому-либо ещё, никогда не хранятся в .env.
Секрет | Кому принадлежит | Защищает |
| postgres, mcp, indexer | полный доступ к базе данных |
| mcp, indexer | API Wiki.js |
| mcp | конечную точку MCP |
| dashboard | вход в панель управления |
| dashboard, mcp, indexer | роль базы данных только на SELECT |
Что запускается
Сервис | Порт | Что это такое |
| internal | Данные Wiki.js, журнал активности и векторы через pgvector |
| 3000 | Вики, которую вы читаете и редактируете |
| internal | Модель встраивания, на CPU |
| 8080 | То, к чему подключается ваш ИИ |
| 8081 | Синхронизирует векторный индекс с вики |
| 8082 | Метрики |
| none | Ежечасный дамп, проверка, отправка |
Отдельной векторной базы данных нет. Векторы живут в Postgres, так что одна резервная копия покрывает всё.
На ARM-хостах образ embeddings опубликован только для
linux/amd64и не будет работать нативно. УкажитеEMBEDDINGS_PROVIDER=openaiна совместимую с OpenAI конечную точку, например Ollama.
Переменная | По умолчанию | Примечания |
|
| Корень всех bind-монтирований, рядом с checkout |
|
| Отображается на странице входа и панели управления |
|
| Сеть, к которой подключается ваш reverse proxy |
|
|
|
|
|
|
|
| Метки происхождения и пути с датами |
|
| База данных Wiki.js |
|
| Журнал активности и векторы, создаётся автоматически |
|
| Язык содержимого |
|
| Используется для ссылок в панели управления |
| обязательно | Голый https-источник, без пути |
|
| Как долго повторно используются данные панели |
|
| Изменение приводит к переиндексации всего |
|
|
|
|
| Интервал полной синхронизации |
|
| Максимальный размер чанка |
| см. | Расписание, хранение, rclone-назначение |
Изменение EMBEDDINGS_MODEL меняет ширину вектора, а векторы от двух моделей нельзя сравнивать, поэтому индексатор перестраивает таблицу и заново встраивает каждую страницу. Содержимое Wiki.js не затрагивается.
Безопасность
Каждый контейнер получает только те учётные данные, которые использует. Панель управления не получает ни POSTGRES_PASSWORD, ни WIKI_API_TOKEN, так что её компрометация даёт доступ на чтение и не более. Проверяйте в любое время:
docker compose exec dashboard env | grep -iE 'PASSWORD|TOKEN'Неаутентифицированные MCP-запросы получают 401 без объяснения.
Оба пути входа ограничивают после 5 неудач на адрес; ссылка для входа сгорает после 3 попыток.
Сессии панели управления — это подписанные куки с сроком действия и nonce, никогда не токен.
HttpOnly,SameSite=Strict, межсайтовые POST-запросы отклоняются.Сравнение секретов выполняется за постоянное время.
Заголовки прокси доверяются только с loopback, так что удалённый клиент не может подделать свой адрес, чтобы обойти ограничение.
Контейнеры работают от непривилегированного пользователя.
Намеренно отсутствует: разрешения по инструментам. Любой аутентифицированный клиент может вызывать все инструменты, включая delete_page. Wiki.js хранит историю страниц, так что удаление обратимо, но относитесь к MCP_TOKEN как к полному доступу на запись к вашей вики. Athena также предполагает одного владельца; у Wiki.js есть свои пользователи для чтения вики.
MCP_TOKEN работает двумя способами, потому что ИИ-клиенты аутентифицируются двумя способами.
Клиенты с заголовком, такие как Cursor и Claude Desktop, отправляют Authorization: Bearer <MCP_TOKEN>. Это весь механизм.
Claude.ai в браузере так не может. Его пользовательские коннекторы поддерживают только OAuth, а спецификация MCP требует динамической регистрации клиента, поэтому сервер, принимающий браузерный Claude, должен быть сервером авторизации. Athena реализует один:
Claude регистрируется и получает сгенерированный client id. Никакой ваш секрет не задействован.
Claude отправляет вас на страницу входа на вашем собственном сервере.
Вы вводите
MCP_TOKENкак пароль. Это шаг одобрения человеком.Athena выдаёт Claude токены, которые Athena создала сама.
Эти токены записываются в data/mcp/oauth-state.json, никогда в .env. Отзовите их с помощью:
rm data/mcp/oauth-state.json && docker compose restart mcpЕсли вы никогда не используете браузерный Claude, игнорируйте всё это. Путь с bearer-токеном его не затрагивает.
Эксплуатация
docker compose logs -f mcp
curl -s localhost:8081/stats | python3 -m json.tool
# Force a full reconciliation
docker compose exec -T indexer bun -e 'await fetch("http://127.0.0.1:8081/sync",{method:"POST"})'Обновление. Всегда сначала делайте резервную копию: Wiki.js запускает свои собственные миграции при старте, и их нельзя отменить остановкой контейнера.
docker compose run --rm backup now
git pull && docker compose build && docker compose up -dСимптом | Причина |
Сервис завершается при запуске, выводя конфиг | Отсутствует обязательная переменная или всё ещё |
Claude не может подключиться, нет страницы входа |
|
Вход отклоняет правильный пароль | Ограничение после 5 неудач, подождите минуту |
Нет результатов семантического поиска |
|
Панель управления показывает отстающие страницы | Индексатор догоняет, проверьте его логи |
Вызовы инструментов возвращают 401 | Файл состояния очищен или токен изменён, переподключите клиент |
Postgres завершается, "database files are incompatible" | Основная версия образа изменилась под существующими данными |
Postgres не прочитает каталог данных, записанный другой основной версией. Сделайте дамп, очистите, восстановите:
docker compose run --rm backup now # on the OLD version
docker compose down
mv data/postgres data/postgres.old # keep until you are happy
# edit the image tag in docker-compose.yml and the FROM line in
# docker/backup/Dockerfile to the same new major version
docker compose build backup
docker compose up -d postgres
docker compose run --rm backup restore run <stamp> # once per database
docker compose up -dВекторный индекс восстанавливается вместе со всем остальным, так что ничего не перевстраивается.
Разработка
bun install
bun test # 145 tests
bun run check # typecheck, lint, testПакет | Что это такое |
| Клиент Wiki.js, разбиение на чанки, слияние поиска, векторы, аутентификация, конфигурация |
| MCP-сервер, OAuth-сервер авторизации, инструменты |
| Цикл синхронизации, встраивания, запись векторов, внутренний поисковый API |
| Интерфейс метрик |
| Контейнер резервного копирования и восстановления |
| Одностраничный сайт |
| Опциональные CSS и JS для Wiki.js |
Bun запускает TypeScript напрямую, поэтому этапа сборки нет, и контейнеры работают с исходным кодом. bun run --cwd packages/dashboard preview создаёт preview.html с примерными данными.
Как это работает вместе:
Индексатор инкрементальный. Он снимает отпечаток каждой страницы и пропускает всё неизменённое, так что проход по нетронутой вики ничего не стоит.
Каждый сервис с административными учётными данными подготавливает базу данных при запуске под advisory lock, поэтому порядок запуска не важен.
Панель управления — это серверный HTML с встроенными SVG-диаграммами. Никакого клиентского JavaScript, никакой библиотеки диаграмм, никакого этапа сборки.
Публикация сайта. website/index.html развёртывается на GitHub Pages при каждом пуше, который его затрагивает. Включите Pages один раз вручную: Settings → Pages → Build and deployment → Source: GitHub Actions. Это нельзя автоматизировать, потому что создание сайта Pages требует токена с правами администратора, а GITHUB_TOKEN их не имеет.
Лицензия
Apache-2.0. См. LICENSE.
This server cannot be deployed
Maintenance
Related MCP Connectors
Driflyte MCP server which lets AI assistants query topic-specific knowledge from web and GitHub.
Hosted markdown project wikis your team's AI assistants read, search, and update over MCP.
Markdown-based note-taking with a hosted MCP server. Your notes serve you and your AI.
One memory, every AI. A shared, user-owned markdown memory your AI clients read and write over MCP.
Related MCP Servers
- AlicenseAqualityCmaintenanceAn MCP server that enables AI agents to interact with Wiki.js as a knowledge base through a comprehensive set of 29 tools for content retrieval and management. It supports full-text search, page versioning, and asset browsing with optional write operations secured by safety gates.2928 npm8MIT
- AlicenseAqualityDmaintenanceAn MCP server for Wiki.js that enables AI agents to create, read, update, search, list, and move wiki pages via the GraphQL API. It supports surgical section updates and structured content management through named sections.6MIT
- AlicenseAqualityCmaintenanceAn MCP server that enables AI agents to compile, refine, and interlink knowledge into a persistent wiki, replacing RAG with structured, curated knowledge.1528 npm3MIT
- AlicenseNot gradedqualityCmaintenanceMCP server for Wiki.js integration, enabling AI assistants to create, read, update, delete, search, and move wiki pages via natural language.1MIT