Athena MCP
Athena
あなたのAIが書き込み、あなた自身が閲覧できるパーソナルwiki。
Athena は Wiki.js の前に MCP サーバーを置きます。アシスタントは wiki を検索し、ページを読み、ノートやドキュメント、会話全体を新しいページとして書き戻します。書き込まれたものはすべて普通の 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 が真実を保持します。ベクターインデックスは検索を助けるだけであり、いつでも削除・再構築できます。
Quickstart
ローカルで約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 -dWiki.js を開き、セットアップウィザードを完了します。
Wiki.js で Administration → API を有効にし、トークンを作成して、
.envにWIKI_API_TOKENとして入れます。再度
docker compose up -dを実行して反映します。ダッシュボードを開き、
DASHBOARD_TOKENでサインインします。
データはチェックアウトの隣の data/ ディレクトリに書き込まれ、チェックアウトの内部には書き込まれません。そのため、git 操作でデータが削除されることは決してありません。別の場所にしたい場合は ATHENA_DATA_DIR を変更します。
ポートを公開するものは何もないため、リバースプロキシ経由でサービスにアクセスするか、試しに一時的な ports: マッピングを追加してください。
初回起動時には数百 MB の埋め込みモデルをダウンロードします。インデクサーは準備ができるまでリトライするので、初回起動時に embeddings が1〜2分間 unhealthy に見えるのは正常です。
Related MCP server: wiki-js-mcp
Connect your AI
すべては MCP_PUBLIC_URL から配信されます。これはパスなしの https:// オリジンである必要があります。/mcp ではありません。
Claude.ai → Settings → Connectors → Add custom connector
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" }
}
}
}Tools
Tool | 機能 |
| キーワード検索とセマンティック検索の融合。各ヒットにはパスが含まれます。 |
| 1ページの完全な Markdown |
| 見出しのアウトライン(本文なし) |
| 見出しの下に追加し、残りは変更しない |
| 新しい Markdown ページ |
| ページ本文の置き換え |
| 移動または名前の変更 |
| 削除し、インデックスからも除去 |
| 会話を |
| 後で整理するための簡単なメモを |
| パスとタイムスタンプ付きの全ページ |
| サイズ、構成、鮮度。AI が何が欠けているかを答えられるようにする |
知っておくと便利なのは append_to_page です。事実を追加するのに、ページ全体を書き換えるのではなく、1段落分のコストで済みます。
なぜ検索結果が良いのか。 正確な語句は Wiki.js の全文検索インデックスにヒットし、曖昧な質問はベクターインデックスにヒットし、結果は相互ランク融合で融合されるため、どちらか一方がもう一方を埋もれさせることがありません。チャンクはその上の見出しを記録するため、返ってきた内容はコンテキストを保持します。アシスタントが触れたすべてのページには、モデルが自分について主張することではなく、認証されたクライアントから取得した、どのアシスタントがいつ触れたかが刻印されます。
Dashboard
専用サービスで、ポート 8082 です。DASHBOARD_TOKEN でサインインします。URL にトークンは含まれません。スクリプトではベアラーヘッダーを使用します:
curl -H "Authorization: Bearer $DASHBOARD_TOKEN" \
https://wiki.example.com/dashboard/api/metrics?days=30Panel | 表示内容 |
コンテンツ | ページ、単語、領域別、最大、古くなりつつあるもの |
AI アクティビティ | 1日あたりの呼び出し、使用ツール、アシスタント、読み取りと書き込み |
何も見つからなかった検索 | wiki が答えられなかった内容 |
インデックスの健全性 | 保存されたチャンク、インデックスされたページ、遅延状況 |
バックアップ | 最後の実行が終了した時刻、サイズ、保存先 |
3行目が価値ある行です。各エントリは、書く価値のあるページです。
読み取り専用である点が二重に確保されています。書き込みは一切行わず、Postgres には SELECT のみを持つロール athena_readonly として接続します。数値は Postgres で集計されキャッシュされるため、リフレッシュのコストはほぼかかりません。
Deploy to a server
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 enableDocker をインストールし、デプロイメントを所有するユーザーを作成します:
sudo useradd --create-home --shell /bin/bash athena
sudo usermod -aG docker athenacompose はそのユーザーで実行し、決して sudo を使わないでください。そうしないとバインドマウントが root 所有になってしまいます。docker グループへの所属はホスト上での root と同等なので、メンバーは最小限にしてください。
2. DNS
ホストを指す2つの A レコード:
Name | 役割 |
| Wiki.js、および |
| MCP エンドポイント |
3. レイアウトと設定
Athena が書き込むものはすべて、ATHENA_DATA_DIR という1つの設定を経由します。したがって、インストール全体を1つのディレクトリの下に置くことができます。ライフサイクルが異なる2つのサブディレクトリを使用してください:
/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 は無視されたファイルを削除するため、チェックアウト内のデータは、確認も元に戻すこともなく消去されるまで、日常的なコマンド1つ分です。兄弟ディレクトリにはどの git 操作でも到達できません。
デフォルトの ATHENA_DATA_DIR=../data がこのレイアウトを自動的に提供するので、覚えておくことは何もありません。
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.jsonpostgres/ だけが代替不可能で、バックアップコンテナが毎時ダンプします。それ以外はすべて自動的に再生成されるか、再接続1回で済みます。
ファイルシステム階層の慣習に従いたい場合は、代わりにデータを /srv/athena に、チェックアウトを /opt/athena に置いてください。上記の単一ルート構成は、1つのジョブを行うマシンではよりシンプルで、どちらでも機能します。決めるのは ATHENA_DATA_DIR だけです。
4. リバースプロキシ
どのコンテナもポートを公開しません。サービスは2つのネットワーク上に配置されます:
athena、内部用。Postgres、埋め込みモデル、インデクサーのみがここに存在するため、侵害されたプロキシでもデータベースには到達できません。athena-edge、リバースプロキシが参加するネットワーク。以下の3つのサービスだけがここに存在します。
次のようにルーティングします:
Host | To | メモ |
|
| WebSocket アップグレード、ボディ上限 100M |
|
| |
|
| バッファリングしてはいけません、MCP ストリーム |
X-Forwarded-For を転送してください。ログインはアドレスごとにスロットリングされるため、これがないとすべての試行がプロキシからのものに見えます。
nginx を、以下のように athena-edge ネットワークに参加するコンテナとして実行するか、127.0.0.1 にバインドした ports: マッピングを付けてホスト上で実行します。エッジネットワークに参加することで、プロキシは 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 を終端します。
ここにあるものは特定のプラットフォームに依存しません。Compose を実行し、独自のプロキシを提供する PaaS では、.env に3つの設定だけが必要です:
ATHENA_DATA_DIR=../files # Dokploy's persistent directory
ATHENA_EDGE_NETWORK=dokploy-network
ATHENA_EDGE_EXTERNAL=true最も重要なのは ATHENA_DATA_DIR です。Dokploy は再デプロイ時に絶対パスのバインドマウントを削除するため、そこに絶対パスを指定するとデータベースが破壊されます。アプリディレクトリからの相対パスなら残ります。
次に、プラットフォームの UI でドメインを追加し、サービスとそのポートを指定します:
Domain | Service | Port |
|
| 3000 |
|
| 8080 |
|
| 8082 |
プラットフォームが独自のルーティングラベルを生成し TLS を処理するため、nginx のセクションは完全にスキップしてください。compose ファイルを含め、それ以外のすべては変更不要です。
イメージをレジストリに公開する必要はありません。Dokploy はリポジトリからビルドするためです。4つのイメージをビルドすると、Postgres や埋め込みモデルとメモリを競合するため、小さなホストでは CI でビルドしてプルするほうがよいかもしれません。
5. 起動してから wiki をロックダウンする
docker compose up -d && docker compose psWiki.js のウィザードをすぐに完了してください。完了するまで、ホストを見つけた誰でも管理者アカウントを乗っ取ることができます。次に Wiki.js で:
Groups → Guests: wiki を公開したくない場合は、読み取りアクセスを削除します。
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: 401Backups
1回の 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 で完全に設定します。S3、Backblaze、Wasabi、MinIO、Hetzner など、あらゆる rclone の転送先が利用可能です。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> は復元せずにバックアップをダウンロードし、各ダンプが読み取り可能かどうかを報告します。
検索インデックスはその後自動的に修復されます。インデクサーがすべてのページを再読み込みし、内容が変更されたものはすべて再埋め込みされます。
設定
すべては環境変数から取得されます。各サービスは起動時に自身の設定を検証し、問題があれば一覧を表示して終了するため、入力ミスは午前3時ではなく即座に検出されます。
5つのシークレットはすべてあなたが生成します。Claude、OpenAI、その他の誰の認証情報も.envに保存されることはありません。
シークレット | 保持者 | 保護対象 |
| postgres, mcp, indexer | データベースへの完全アクセス |
| mcp, indexer | Wiki.js API |
| mcp | MCP エンドポイント |
| dashboard | ダッシュボードへのサインイン |
| dashboard, mcp, indexer | SELECT のみのデータベースロール |
実行されるもの
サービス | ポート | 説明 |
| 内部 | Wiki.js データ、アクティビティログ、pgvector によるベクトル |
| 3000 | あなたが読み書きする Wiki |
| 内部 | CPU 上で動作する埋め込みモデル |
| 8080 | あなたの AI が接続するもの |
| 8081 | ベクトルインデックスを Wiki と同期させる |
| 8082 | メトリクス |
| なし | 1時間ごとのダンプ、検証、プッシュ |
別のベクトルデータベースはありません。ベクトルは Postgres 内に存在するため、1つのバックアップですべてをカバーできます。
ARM ホスト上では、埋め込みイメージは
linux/amd64でのみ公開されており、ネイティブでは実行されません。代わりにEMBEDDINGS_PROVIDER=openaiを Ollama などの OpenAI 互換エンドポイントに向けてください。
変数 | デフォルト | 備考 |
|
| すべてのバインドマウントのルート、チェックアウトの兄弟ディレクトリ |
|
| ログインページとダッシュボードに表示される名前 |
|
| リバースプロキシが参加するネットワーク |
|
| プラットフォームがそのネットワークを提供する場合に |
|
|
|
|
| 証明タイムスタンプと日付パス |
|
| Wiki.js データベース |
|
| アクティビティログとベクトル、自動的に作成される |
|
| コンテンツ言語 |
|
| ダッシュボードリンクに使用される |
| 必須 | ベアの https オリジン、パスは含めない |
|
| ダッシュボードの数値が再利用される期間 |
|
| 変更するとすべてが再インデックスされる |
|
|
|
|
| 完全な調整間隔 |
|
| チャンクサイズの上限 |
|
| スケジュール、保持期間、rclone の転送先 |
EMBEDDINGS_MODEL を変更するとベクトルの幅が変わり、異なるモデルのベクトルは比較できなくなるため、インデクサーはテーブルを再構築し、すべてのページを再埋め込みします。Wiki.js のコンテンツは影響を受けません。
セキュリティ
各コンテナには、使用する認証情報のみが渡されます。ダッシュボードは POSTGRES_PASSWORD も WIKI_API_TOKEN も受け取らないため、ダッシュボードが侵害されても読み取りアクセス以上の権限は得られません。以下のコマンドでいつでも確認できます:
docker compose exec dashboard env | grep -iE 'PASSWORD|TOKEN'認証されていない MCP リクエストには 401 と説明なしの応答が返ります。
両方のログインパスは、1 アドレスあたり 5 回の失敗後にスロットリングされます。ログインリンクは 3 回の試行後に無効になります。
ダッシュボードセッションは、有効期限と nonce を含む署名付きクッキーで、トークンは含まれません。
HttpOnly、SameSite=Strict、クロスサイト POST は拒否されます。シークレットの比較は定数時間で行われます。
プロキシヘッダーはループバックからのみ信頼されるため、リモートクライアントがアドレスを偽装してスロットリングを回避することはできません。
コンテナは非 root ユーザーとして実行されます。
意図的に省略: ツールごとの権限。認証されたクライアントは delete_page を含むすべてのツールを呼び出せます。Wiki.js はページ履歴を保持するため削除は復元可能ですが、MCP_TOKEN をあなたの Wiki への完全な書き込みアクセスとして扱ってください。また、Athena は単一の所有者を想定しています。Wiki.js には Wiki を読むための独自のユーザーがいます。
MCP_TOKEN は 2 つの方法で機能します。これは AI クライアントが 2 つの方法で認証するためです。
ヘッダークライアント (Cursor、Claude Desktop など) は Authorization: Bearer <MCP_TOKEN> を送信します。これが全体の仕組みです。
ブラウザ上の Claude.ai はそれができません。カスタムコネクタは OAuth のみをサポートしており、MCP 仕様では動的クライアント登録が必要なため、ブラウザ Claude を受け入れるサーバーは認可サーバーである必要があります。Athena は次のように実装しています:
Claude が自身を登録し、生成されたクライアント ID を受け取ります。あなたのシークレットは関与しません。
Claude があなたを自分のサーバー上のログインページに送ります。
パスワードとして
MCP_TOKENを入力します。これが人間による承認ステップです。Athena が自身で生成した Claude トークンを発行します。
これらのトークンは 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回失敗後にスロットリングされた、1分待つ |
セマンティック検索結果が表示されない |
|
ダッシュボードにページの遅れが表示される | インデクサーが追いついていない、ログを確認する |
ツール呼び出しが 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 |
| メトリクスインターフェース |
| バックアップおよび復元コンテナ |
| 1ページサイト |
| オプションの Wiki.js CSS および JS |
Bun は TypeScript を直接実行するため、ビルドステップはなく、コンテナはソースを実行します。bun run --cwd packages/dashboard preview はサンプルデータを含む preview.html を書き込みます。
全体の構成:
インデクサーはインクリメンタルです。各ページのフィンガープリントを取得し、変更されていないものはスキップするため、変更のない Wiki に対するパスはコストがかかりません。
管理資格情報を持つすべてのサービスは、アドバイザリロックのもとで起動時にデータベースを準備するため、起動順序は重要ではありません。
ダッシュボードはインライン SVG グラフを含むサーバーサイドレンダリングの HTML です。クライアント 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