Athena MCP
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 ──▶ PostgresWiki.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次に:
Wiki.jsを開き、セットアップウィザードを完了します。
Wiki.jsで: 管理 → API を有効にし、トークンを作成して
.envにWIKI_API_TOKENとして設定します。docker compose up -dを再度実行して反映させます。ダッシュボードを開き、
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" }
}
}
}ツール
ツール | 機能 |
| キーワードとセマンティック検索を融合。すべてのヒットにパスが付きます。 |
| 1ページの完全なMarkdown |
| 見出しのアウトライン(本文なし) |
| 見出しの下に追加し、残りはそのまま |
| 新しいMarkdownページ |
| ページ本文を置き換え |
| 移動または名前変更 |
| 削除し、インデックスからも削除 |
| 会話を |
| 後で整理するために |
| すべてのページ(パスとタイムスタンプ付き) |
| サイズ、形状、鮮度。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 enableDockerをインストールし、デプロイメントを所有するユーザーを作成します:
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.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. リバースプロキシ
どのコンテナもポートを公開しません。すべては athena Dockerネットワーク上にあり、プロキシが参加します。以下をルーティング:
ホスト | 転送先 | 備考 |
|
| WebSocketアップグレード、100Mボディ制限 |
|
| |
|
| バッファリング禁止、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 psWiki.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登録 | いいえ(再構築または再接続) |
| いいえ(パスワードマネージャーにコピーを保管) |
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, 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 データベース |
|
| アクティビティログとベクトル。自動的に作成される |
|
| コンテンツの言語 |
|
| ダッシュボードのリンクに使用される |
| required | パスなしのベア https オリジン |
|
| ダッシュボードの数値が再利用される期間 |
|
| 変更するとすべてのインデックスが再作成される |
|
|
|
|
| 完全な同期間隔 |
|
| チャンクサイズの上限 |
|
| スケジュール、保存期間、rclone の宛先 |
EMBEDDINGS_MODEL を変更するとベクトルの幅が変わり、2つのモデルのベクトルを比較できなくなるため、インデクサーはテーブルを再構築し、すべてのページを再埋め込みします。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 回の試行で無効になります。
ダッシュボードのセッションは、有効期限と nonce を含む署名付き Cookie であり、トークンは含まれません。
HttpOnly、SameSite=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 はそれを実装しています:
Claude が自身を登録し、生成されたクライアント ID を受け取ります。あなたのシークレットは一切関与しません。
Claude があなたを自分のサーバーのログインページに送ります。
パスワードとして
MCP_TOKENを入力します。これが人間による承認ステップです。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症状 | 原因 |
起動時に設定を表示してサービスが終了する | 必須の変数が欠けているか、まだ |
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 |
| メトリクスインターフェース |
| バックアップ・リストアコンテナ |
| 単一ページのサイト |
| オプションの 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 を参照してください。
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