Skip to main content
Glama

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 ──▶ Postgres

Wiki.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

Затем:

  1. Откройте Wiki.js и завершите мастер настройки.

  2. В Wiki.js: Administration → API, включите его, создайте токен и поместите его в .env как WIKI_API_TOKEN.

  3. docker compose up -d снова, чтобы подхватить изменения.

  4. Откройте панель управления и войдите с помощью 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" }
    }
  }
}

Инструменты

Инструмент

Что делает

search_knowledge

Поиск по ключевым словам и семантический, объединённый. Каждый результат содержит путь.

get_page

Полный Markdown одной страницы

get_page_structure

Структура заголовков, без содержимого

append_to_page

Добавить под заголовок, оставляя остальное нетронутым

create_page

Новая страница в Markdown

update_page

Заменить содержимое страницы

move_page

Переместить или переименовать

delete_page

Удалить и удалить из индекса

save_conversation

Сохранить разговор в conversations/YYYY/MM/

capture_note

Быстрая заметка в inbox/ для последующей сортировки

list_pages

Всё с путями и временными метками

get_wiki_stats

Размер, форма и устаревание, чтобы ИИ мог узнать, чего не хватает

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.example.com

Wiki.js и панель управления по адресу /dashboard/

athena-mcp.example.com

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.com

4. Обратный прокси

Ни один контейнер не публикует порт. Всё находится в сети Docker athena, к которой присоединяется ваш прокси. Маршрутизируйте:

Хост

Кому

Примечания

wiki.example.com

wikijs:3000

WebSocket upgrade, лимит тела 100M

wiki.example.com/dashboard/

dashboard:8082

athena-mcp.example.com

mcp:8080

не должен буферизировать, потоки 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

нет, перестраивается или подключается заново

.env

нет, храните копию в менеджере паролей

Контейнер 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_PASSWORD

postgres, mcp, indexer

полный доступ к базе данных

WIKI_API_TOKEN

mcp, indexer

API Wiki.js

MCP_TOKEN

mcp

MCP-эндпоинт

DASHBOARD_TOKEN

dashboard

вход в панель управления

DASHBOARD_DB_PASSWORD

dashboard, mcp, indexer

роль базы данных только SELECT

Что работает

Сервис

Порт

Что это

postgres

внутренний

Данные Wiki.js, журнал активности и векторы через pgvector

wikijs

3000

Вики, которую вы читаете и редактируете

embeddings

внутренний

Модель эмбеддингов на CPU

mcp

8080

То, к чему подключается ваш ИИ

indexer

8081

Поддерживает векторный индекс в актуальном состоянии

dashboard

8082

Метрики

backup

нет

Ежечасный дамп, проверка, отправка

Нет отдельной векторной базы данных. Векторы хранятся в Postgres, поэтому одна резервная копия покрывает всё.

На ARM-хостах образ эмбеддингов опубликован только для linux/amd64 и не будет работать нативно. Вместо этого укажите EMBEDDINGS_PROVIDER=openai на OpenAI-совместимый эндпоинт, например Ollama.

Переменная

По умолчанию

Примечания

ATHENA_DATA_DIR

./data

Корень для всех монтирований bind

ATHENA_INSTANCE_NAME

Athena

Отображается на странице входа и панели управления

ATHENA_LOG_LEVEL

info

debug, info, warn, error

TZ

UTC

Штампы происхождения и датированные пути

POSTGRES_DB

wiki

База данных Wiki.js

ATHENA_DB

athena

Журнал активности и векторы, создается автоматически

WIKI_LOCALE

en

Язык содержимого

WIKI_PUBLIC_URL

http://localhost:3000

Используется для ссылок на панели управления

MCP_PUBLIC_URL

обязательно

Голый https-источник, без пути

METRICS_CACHE_SECONDS

60

Как долго повторно используются данные панели управления

EMBEDDINGS_MODEL

intfloat/multilingual-e5-small

Изменение приводит к переиндексации всего

EMBEDDINGS_PROVIDER

tei

tei или openai для совместимой конечной точки

INDEX_INTERVAL_SECONDS

300

Интервал полной синхронизации

CHUNK_MAX_CHARS

1200

Максимальный размер чанка

BACKUP_*

см. .env.example

Расписание, хранение, пункт назначения 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 реализует один:

  1. Claude регистрируется и получает сгенерированный идентификатор клиента. Ваш секрет не задействован.

  2. Claude отправляет вас на страницу входа на вашем собственном сервере.

  3. Вы вводите MCP_TOKEN в качестве пароля. Это этап одобрения человеком.

  4. 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

Симптом

Причина

Сервис завершает работу при загрузке, указывая на конфиг

Отсутствует обязательная переменная или она все еще CHANGE_ME

Claude не может подключиться, нет страницы входа

MCP_PUBLIC_URL содержит путь или не является https

Вход отклоняет правильный пароль

Ограничение скорости после 5 неудач, подождите минуту

Нет результатов семантического поиска

embeddings все еще загружается, проверьте его логи

Панель управления показывает страницы с отставанием

Индексатор догоняет, проверьте его логи

Вызовы инструментов завершаются с 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

Пакет

Что это

packages/core

Клиент Wiki.js, разбиение на чанки, слияние поиска, векторы, аутентификация, конфигурация

packages/mcp

MCP-сервер, OAuth-сервер авторизации, инструменты

packages/indexer

Цикл синхронизации, встраивания, запись векторов, внутренний поисковый API

packages/dashboard

Интерфейс метрик

docker/backup

Контейнер резервного копирования и восстановления

website/

Одностраничный сайт

themes/wikijs/

Опциональные 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.

-
license - not tested
-
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

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

View all MCP Connectors

Latest Blog Posts

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