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: Administration → API, включите его, создайте токен и поместите его в
.envкакWIKI_API_TOKEN.docker compose up -dснова, чтобы подхватить изменения.Откройте панель управления и войдите с помощью
DASHBOARD_TOKEN.
Ничего не публикует порт, поэтому обращайтесь к сервисам через ваш обратный прокси или добавьте временное ports: отображение для тестирования.
При первом запуске загружается модель эмбеддингов размером несколько сотен мегабайт. Индексатор повторяет попытки, пока она не будет готова, поэтому embeddings может выглядеть нездоровым в течение минуты-двух при первой загрузке — это нормально.
Подключите свой ИИ
Всё обслуживается по адресу 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 и другие клиенты с заголовками
{
"mcpServers": {
"athena": {
"url": "https://athena-mcp.example.com/mcp",
"headers": { "Authorization": "Bearer YOUR_MCP_TOKEN" }
}
}
}Инструменты
Инструмент | Что делает |
| Поиск по ключевым словам и семантический, объединённый. Каждый результат содержит путь. |
| Полный Markdown одной страницы |
| Структура заголовков, без содержимого |
| Добавить под заголовок, оставляя остальное нетронутым |
| Новая страница в Markdown |
| Заменить содержимое страницы |
| Переместить или переименовать |
| Удалить и удалить из индекса |
| Сохранить разговор в |
| Быстрая заметка в |
| Всё с путями и временными метками |
| Размер, форма и устаревание, чтобы ИИ мог узнать, чего не хватает |
append_to_page — тот, о котором стоит знать: добавление факта стоит одного абзаца, а не перезаписи всей страницы.
Почему он хорошо находит. Точные термины попадают в полнотекстовый индекс Wiki.js, нечёткие запросы — в векторный индекс, а результаты объединяются с помощью reciprocal rank fusion, чтобы ни один источник не мог подавить другой. Фрагменты запоминают заголовки над ними, поэтому возвращаемые данные сохраняют контекст. Каждая страница, к которой прикасается помощник, помечается тем, какой это был помощник и когда, на основе аутентифицированного клиента, а не того, что модель утверждает о себе.
Панель управления
Собственный сервис на порту 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
sudo mkdir -p /srv/athena && sudo chown athena:athena /srv/athenaЗапускайте compose от имени этого пользователя, никогда не с sudo, иначе примонтированные каталоги окажутся принадлежащими root. Членство в группе docker эквивалентно root на хосте, поэтому держите её небольшой.
2. DNS
Две A-записи, указывающие на хост:
Имя | Обслуживает |
| Wiki.js и панель управления по адресу |
| MCP-эндпоинт |
3. Настройка
cd /srv/athena
git clone https://github.com/jannismilz/athena.git .
cp .env.example .env
chmod 600 .env # it holds every secretУстановите как минимум:
ATHENA_DATA_DIR=/srv/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.com4. Обратный прокси
Ни один контейнер не публикует порт. Всё находится в сети Docker athena, к которой присоединяется ваш прокси. Маршрутизируйте:
Хост | Кому | Примечания |
|
| WebSocket upgrade, лимит тела 100M |
|
| |
|
| не должен буферизировать, потоки MCP |
Передавайте X-Forwarded-For: логины ограничивают скорость по адресу, и без него каждая попытка выглядит как пришедшая с прокси.
Запустите nginx как контейнер, присоединённый к сети athena, как указано ниже, или на хосте с отображением ports:, привязанным к 127.0.0.1.
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 там, где вы это уже делаете.
5. Запустите, затем заблокируйте вики
docker compose up -d && docker compose psНемедленно завершите мастер Wiki.js. Пока вы этого не сделаете, любой, кто найдёт хост, может захватить учётную запись администратора. Затем в Wiki.js:
Groups → Guests: удалите доступ на чтение, если не хотите, чтобы вики была публичной.
Auth: отключите самостоятельную регистрацию.
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-remote и укажите 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 |
Что работает
Сервис | Порт | Что это |
| внутренний | Данные Wiki.js, журнал активности и векторы через pgvector |
| 3000 | Вики, которую вы читаете и редактируете |
| внутренний | Модель эмбеддингов на CPU |
| 8080 | То, к чему подключается ваш ИИ |
| 8081 | Поддерживает векторный индекс в актуальном состоянии |
| 8082 | Метрики |
| нет | Ежечасный дамп, проверка, отправка |
Нет отдельной векторной базы данных. Векторы хранятся в Postgres, поэтому одна резервная копия покрывает всё.
На ARM-хостах образ эмбеддингов опубликован только для
linux/amd64и не будет работать нативно. Вместо этого укажитеEMBEDDINGS_PROVIDER=openaiна OpenAI-совместимый эндпоинт, например Ollama.
Переменная | По умолчанию | Примечания |
|
| Корень для всех монтирований bind |
|
| Отображается на странице входа и панели управления |
|
|
|
|
| Штампы происхождения и датированные пути |
|
| База данных Wiki.js |
|
| Журнал активности и векторы, создается автоматически |
|
| Язык содержимого |
|
| Используется для ссылок на панели управления |
| обязательно | Голый https-источник, без пути |
|
| Как долго повторно используются данные панели управления |
|
| Изменение приводит к переиндексации всего |
|
|
|
|
| Интервал полной синхронизации |
|
| Максимальный размер чанка |
| см. | Расписание, хранение, пункт назначения rclone |
Изменение EMBEDDINGS_MODEL меняет ширину векторов, а векторы от двух
моделей нельзя сравнивать, поэтому индексатор перестраивает таблицу и
заново встраивает каждую страницу. Содержимое Wiki.js не затрагивается.
Безопасность
Каждый контейнер получает только те учетные данные, которые использует.
Панель управления не получает ни POSTGRES_PASSWORD, ни WIKI_API_TOKEN,
поэтому ее компрометация дает доступ только на чтение и не более того.
Проверить в любое время:
docker inspect athena-dashboard -f '{{range .Config.Env}}{{println .}}{{end}}' | grep -iE 'PASSWORD|TOKEN'Неаутентифицированные MCP-запросы получают 401 без объяснения.
Оба пути входа ограничивают скорость после 5 неудачных попыток с одного адреса; ссылка для входа сгорает после 3 попыток.
Сессии панели управления — это подписанные cookie с сроком действия и nonce, никогда не содержащие токен.
HttpOnly,SameSite=Strict, межсайтовые POST-запросы отклоняются.Сравнение секретов выполняется за константное время.
Заголовки прокси доверяются только с loopback, поэтому удаленный клиент не может подделать свой адрес, чтобы обойти ограничение скорости.
Контейнеры работают от непривилегированного пользователя.
Намеренно отсутствует: разрешения для отдельных инструментов. Любой
аутентифицированный клиент может вызывать все инструменты, включая
delete_page. Wiki.js хранит историю страниц, поэтому удаление можно
отменить, но относитесь к MCP_TOKEN как к полному доступу на запись к
вашей вики. Athena также предполагает одного владельца; у Wiki.js есть
свои пользователи для чтения вики.
MCP_TOKEN работает двумя способами, потому что AI-клиенты
аутентифицируются двумя способами.
Клиенты с заголовком, такие как Cursor и Claude Desktop, отправляют
Authorization: Bearer <MCP_TOKEN>. Это весь механизм.
Claude.ai в браузере не может этого сделать. Его пользовательские коннекторы поддерживают только OAuth, а спецификация MCP требует динамической регистрации клиента, поэтому сервер, принимающий браузерный Claude, должен быть сервером авторизации. Athena реализует один:
Claude регистрируется и получает сгенерированный идентификатор клиента. Ваш секрет не задействован.
Claude отправляет вас на страницу входа на вашем собственном сервере.
Вы вводите
MCP_TOKENв качестве пароля. Это этап одобрения человеком.Athena выдает токены Claude, которые Athena создала сама.
Эти токены записываются в data/mcp/oauth-state.json, никогда в .env.
Отозвать их можно с помощью:
rm data/mcp/oauth-state.json && docker compose restart mcpЕсли вы никогда не используете браузерный Claude, игнорируйте все это. Путь с заголовком его не затрагивает.
Эксплуатация
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 завершает работу, "файлы базы данных несовместимы" | Основная версия образа изменилась при существующих данных |
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
при каждом push, который его затрагивает. Включите Pages вручную один раз:
Settings → Pages → Build and deployment → Source: GitHub Actions. Это
нельзя автоматизировать, потому что создание сайта Pages требует токена с
правами администратора, а GITHUB_TOKEN их не имеет.
Лицензия
Apache-2.0. См. LICENSE.
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 Connectors
Driflyte MCP server which lets AI assistants query topic-specific knowledge from web and GitHub.
Person-owned, portable AI memory as a remote MCP server, readable and writable by any MCP client.
An MCP server that gives your AI access to the source code and docs of all public github repos
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/jannismilz/athena'
If you have feedback or need assistance with the MCP directory API, please join our Discord server