Skip to main content
Glama

Athena

あなたのAIが書き込み、自分で閲覧できる個人用Wiki

AthenaはWiki.jsの前にMCPサーバーを配置します。アシスタントはWikiを検索し、ページを読み、新しいページ(メモ、ドキュメント、会話全体)を書き戻します。AIが書くものはすべて、特定のモデルが消えた後もずっと開いて編集・保存できる普通の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が真実を保持します。ベクトルインデックスは検索を助けるだけで、いつでも削除して再構築できます。


クイックスタート

ローカルで、約5分。インターネット上のものについては、最初にサーバーにデプロイするをお読みください。

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で: 管理 → API を有効にし、トークンを作成して .envWIKI_API_TOKEN として設定します。

  3. docker compose up -d を再度実行して反映させます。

  4. ダッシュボードを開き、DASHBOARD_TOKEN でサインインします。

ポートは公開されないため、リバースプロキシ経由でサービスにアクセスするか、試用中は一時的に ports: マッピングを追加してください。

初回起動時には数百MBの埋め込みモデルがダウンロードされます。インデクサーは準備ができるまでリトライするため、初回起動時に embeddings が1~2分間異常に見えるのは想定内です。


AIを接続する

すべては MCP_PUBLIC_URL から提供されます。これは パスなし のベア https:// オリジンである必要があります。/mcp ではありません。

Claude.ai → 設定 → コネクタ → カスタムコネクタを追加

  • URL: https://athena-mcp.example.com/mcp

  • クライアントIDとシークレットは空のままにします。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

1ページの完全な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

サイズ、形状、鮮度。AIが何が不足しているかを回答できるように

append_to_page は知っておく価値があります: 事実を追加するのにページ全体を書き換えるのではなく、1段落で済みます。

なぜ検索がうまくいくのか。 正確な用語はWiki.jsの全文検索インデックスにヒットし、曖昧な質問はベクトルインデックスにヒットし、結果は相互ランク融合で融合されるため、どちらかのソースが他方を埋もれさせることはありません。チャンクはその上の見出しを記録するため、返ってきたものはコンテキストを保持します。アシスタントが触れたすべてのページには、モデルが自分自身について主張する内容ではなく、認証されたクライアントから取得した、どのアシスタントがいつ触れたかがスタンプされます。


ダッシュボード

独自のサービスで、ポート8082。DASHBOARD_TOKEN でサインインします。URLにトークンは含まれません。スクリプトの場合は、Bearer ヘッダーを使用します:

curl -H "Authorization: Bearer $DASHBOARD_TOKEN" \
  https://wiki.example.com/dashboard/api/metrics?days=30

パネル

回答

コンテンツ

ページ数、単語数、エリア別、最大、古くなっているもの

AIアクティビティ

1日あたりの呼び出し数、どのツール、どのアシスタント、読み取り vs 書き込み

何も見つからなかった検索

Wikiが答えられなかったこと

インデックスの健全性

保存されたチャンク数、インデックスされたページ数、遅延状況

バックアップ

最後の実行がいつ終了したか、サイズ、保存先

3行目が価値を発揮します。すべてのエントリは書く価値のあるページです。

これは二重に読み取り専用です: 書き込みは一切行わず、Postgresには athena_readonly ロール(SELECTのみ)で接続します。数値はPostgresで集計されキャッシュされるため、リフレッシュのコストはほぼゼロです。


サーバーにデプロイする

4 GBのVPSで、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

ホストを指す2つの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. リバースプロキシ

どのコンテナもポートを公開しません。すべては athena Dockerネットワーク上にあり、プロキシが参加します。以下をルーティング:

ホスト

転送先

備考

wiki.example.com

wikijs:3000

WebSocketアップグレード、100Mボディ制限

wiki.example.com/dashboard/

dashboard:8082

athena-mcp.example.com

mcp:8080

バッファリング禁止、MCPストリーム

X-Forwarded-For を転送: ログインはアドレスごとにスロットルされ、これがないとすべての試行がプロキシからのように見えます。

nginxを athena ネットワークに参加したコンテナとして実行するか(以下)、または 127.0.0.1 にバインドした ports: マッピングでホスト上で実行します。

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. 起動し、Wikiをロックダウンする

docker compose up -d && docker compose ps

Wiki.jsのウィザードを すぐに 完了してください。完了するまで、ホストを見つけた誰でも管理者アカウントを取得できます。その後、Wiki.jsで:

  • グループ → ゲスト: 読み取りアクセスを削除(Wikiを公開しない場合)

  • 認証: 自己登録をオフにする

  • 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

バックアップ

1つの pg_dump で完全バックアップになります。 Wiki.jsはページ、履歴、ユーザー、権限、設定、アップロードされたすべてのファイルのバイト をPostgresに保持します。アップロードは assetData テーブルに保存され、data/wikijs/uploads 下のファイルはキャッシュにすぎません。Athenaのアクティビティログと検索ベクトルは同じサーバー上の別のデータベースにあります。

データ

バックアップに含まれる

ページ、履歴、ユーザー、設定

はい

アップロードされた画像とファイル

はい

アクティビティログと検索ベクトル

はい

インデックス管理情報、OAuth登録

いいえ(再構築または再接続)

.env

いいえ(パスワードマネージャーにコピーを保管)

backup コンテナは1時間ごとに実行されます。各実行では両方のデータベースをダンプし、すべてのダンプが読み取り可能かを確認し、ローカルコピーを保持し、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> は復元せずにバックアップをダウンロードし、各ダンプが読み取り可能かを報告します。

検索インデックスはその後自動的に修復されます: インデクサーがすべてのページを再読み取りし、内容が変更されたものを再埋め込みします。


設定

すべては環境変数から取得されます。各サービスは起動時に自身の設定を検証し、問題がある場合はリストを表示して終了するため、タイプミスは早朝ではなく即座に失敗します。

5つのシークレット、すべてあなたが生成します。Claude、OpenAI、その他の資格情報が .env に保存されることは決してありません。

シークレット

保持者

保護対象

POSTGRES_PASSWORD

postgres, mcp, indexer

データベースへの完全アクセス

WIKI_API_TOKEN

mcp, indexer

Wiki.js API

MCP_TOKEN

mcp

MCPエンドポイント

DASHBOARD_TOKEN

dashboard

ダッシュボードサインイン

DASHBOARD_DB_PASSWORD

dashboard, mcp, indexer

SELECTのみのデータベースロール

実行されるもの

サービス

ポート

説明

postgres

内部

Wiki.jsデータ、アクティビティログ、pgvectorによるベクトル

wikijs

3000

あなたが読んで編集するWiki

embeddings

内部

埋め込みモデル(CPU上)

mcp

8080

AIが接続するもの

indexer

8081

ベクトルインデックスをWikiと同期させる

dashboard

8082

メトリクス

backup

なし

1時間ごとのダンプ、検証、プッシュ

独立したベクトルデータベースはありません。ベクトルはPostgresに保存されるため、1つのバックアップですべてをカバーします。

ARMホストでは 埋め込みイメージは linux/amd64 のみで公開されており、ネイティブでは動作しません。代わりに EMBEDDINGS_PROVIDER=openai をOllamaなどのOpenAI互換エンドポイントに向けてください。

変数

デフォルト

備考

ATHENA_DATA_DIR

./data

すべてのバインドマウントのルート

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

required

パスなしのベア 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 を変更するとベクトルの幅が変わり、2つのモデルのベクトルを比較できなくなるため、インデクサーはテーブルを再構築し、すべてのページを再埋め込みします。Wiki.js のコンテンツは影響を受けません。


セキュリティ

各コンテナには、使用する認証情報のみが渡されます。ダッシュボードには POSTGRES_PASSWORDWIKI_API_TOKEN も渡されないため、万一侵害されても読み取りアクセスしか得られません。いつでも確認できます:

docker inspect athena-dashboard -f '{{range .Config.Env}}{{println .}}{{end}}' | grep -iE 'PASSWORD|TOKEN'
  • 認証されていない MCP リクエストは 401 と説明なしで拒否されます。

  • 両方のログインパスは、アドレスあたり 5 回の失敗でスロットリングされます。ログインリンクは 3 回の試行で無効になります。

  • ダッシュボードのセッションは、有効期限と nonce を含む署名付き Cookie であり、トークンは含まれません。HttpOnlySameSite=Strict で、クロスサイト POST は拒否されます。

  • シークレットの比較は定数時間で行われます。

  • プロキシヘッダーはループバックからのみ信頼されるため、リモートクライアントが自身のアドレスを偽装してスロットリングを逃れることはできません。

  • コンテナは非 root ユーザーで実行されます。

意図的に欠落しているもの: ツールごとの権限。認証されたクライアントは delete_page を含むすべてのツールを呼び出せます。Wiki.js はページ履歴を保持するため削除は復元可能ですが、MCP_TOKEN はウィキへの完全な書き込みアクセス権とみなしてください。Athena は単一の所有者を想定しています。Wiki.js にはウィキを読むための独自のユーザーが存在します。

MCP_TOKEN は 2 つの方法で機能します。AI クライアントが 2 つの方法で認証するためです。

ヘッダークライアント(Cursor や Claude Desktop など)は Authorization: Bearer <MCP_TOKEN> を送信します。これが仕組みのすべてです。

ブラウザ内の Claude.ai はこれを行うことができません。そのカスタムコネクタは OAuth のみをサポートしており、MCP 仕様では動的クライアント登録が必要なため、ブラウザの Claude を受け入れるサーバーは認可サーバーである必要があります。Athena はそれを実装しています:

  1. Claude が自身を登録し、生成されたクライアント ID を受け取ります。あなたのシークレットは一切関与しません。

  2. Claude があなたを自分のサーバーのログインページに送ります。

  3. パスワードとして MCP_TOKEN を入力します。これが人間による承認ステップです。

  4. Athena が自身で生成したトークンを Claude に発行します。

これらのトークンは 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

症状

原因

起動時に設定を表示してサービスが終了する

必須の変数が欠けているか、まだ CHANGE_ME のまま

Claude が接続できない、ログインページが表示されない

MCP_PUBLIC_URL にパスが含まれている、または https ではない

正しいパスワードでログインが拒否される

5 回失敗後にスロットリングされています。1 分待ってください

セマンティック検索の結果がない

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/

オプションの Wiki.js CSS および JS

Bun は TypeScript を直接実行するため、ビルドステップはなく、コンテナはソースを実行します。bun run --cwd packages/dashboard preview はサンプルデータを含む preview.html を書き出します。

各コンポーネントの連携:

  • インデクサーはインクリメンタルです。各ページのフィンガープリントを取得し、変更がないものはスキップするため、未変更のウィキに対するパスはコストがかかりません。

  • 管理資格情報を持つすべてのサービスは、起動時にアドバイザリロックの下でデータベースを準備するため、起動順序は問題になりません。

  • ダッシュボードは、インライン SVG チャートを使用したサーバーサイドレンダリング HTML です。クライアント JavaScript もチャートライブラリもビルドステップもありません。

ウェブサイトの公開。 website/index.html は、そのファイルに変更があるプッシュごとに GitHub Pages にデプロイされます。最初に手動で 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