Skip to main content
Glama
README.md
# foundation

個人用の長期記憶基盤。Obsidian Vault・Claude Code のセッション履歴・会議録などを
PostgreSQL + Qdrant に取り込み、MCP (Model Context Protocol) サーバー経由で
Claude / ChatGPT 等の LLM クライアントから検索・書き込みできるようにする。
GPU を要するモデル (埋め込み・リランカ・文字起こし・OCR) は専用スケジューラに集約し、
複数サービスから排他制御された状態で共有する。

このリポジトリは個人利用向けに開発されたものの公開用コピーであり、大学 LMS 連携など
一部モジュールは公開版から除外されている。詳細は本文末尾の「注意事項」を参照。

## 目次

- [アーキテクチャ](#アーキテクチャ)
- [主要機能 (MCP ツール)](#主要機能-mcp-ツール)
- [技術スタック](#技術スタック)
- [セットアップ](#セットアップ)
- [設定](#設定)
- [ディレクトリ構成](#ディレクトリ構成)
- [注意事項](#注意事項)

## アーキテクチャ

構成要素とその役割:

```
                    ┌─────────────────────────────────────────┐
                    │      Claude Code / claude.ai / ChatGPT   │
                    └───────────────────┬───────────────────────┘
                                        │ MCP (stdio / streamable-http)
                                        ▼
                    ┌─────────────────────────────────────────┐
                    │   src/mcp_server.py  (140 tools)         │
                    │   ・OAuth 2.0 Authorization Server        │
                    │     (src/oauth_provider.py, Google Sign-In)│
                    └──────┬───────────────┬──────────┬────────┘
                            │               │          │
                            ▼               ▼          ▼
                    ┌───────────┐   ┌────────────┐  ┌─────────────┐
                    │ PostgreSQL │   │   Qdrant    │  │ gpu-scheduler│
                    │ (turns,    │   │ (knowledge / │  │  :9400 HTTP  │
                    │  facts,    │   │  sessions    │  │  FastAPI     │
                    │  tasks...) │   │  collections)│  │ (排他キュー) │
                    └───────────┘   └────────────┘  └──────┬───────┘
                                                             │
                                    ┌────────────────────────┼───────────────────┐
                                    ▼                        ▼                    ▼
                            埋め込み/リランカ           音声認識/話者分離        OCR
                       (Ruri-v3, embedder.py /     (Kotoba-Whisper, NeMo    (Surya OCR)
                        reranker.py)                TitaNet, Silero-VAD)
```

他に、以下の常駐/バッチプロセスが同じ DB / Qdrant / gpu-scheduler を共有する。

- `src/meeting_server.py` + `src/meeting_pipeline.py` (FastAPI, port 8315): 会議録音の
  WebSocket ストリーミング取り込みから話者分離・構造化要約・矛盾検出までを行う。
- `src/session_watcher.py` / `src/session_ingest.py` / `src/conversation_indexer.py`:
  Claude Code の JSONL セッションログを監視・解析し、ファクト抽出とベクトル化を行う。
- `src/indexer.py`: Obsidian Vault の Markdown を差分検知 → チャンク分割 → 埋め込み →
  PostgreSQL/Qdrant への upsert を行う定期インデクサ。
- `src/orchestrator/`: tmux 上に Claude Code エージェントを spawn し、長期記憶を
  注入した状態で走らせ、完了後に結果を回収する (`agent_*` MCP ツール群)。
- `src/dashboard_server.py` (port 8600): PostgreSQL を読み取り専用で参照する管理コンソール。
- `src/morning_digest/`: Slack/Discord/Teams 等のメッセージを DSL ルールに基づき
  スコアリングし、朝刊として Discord に配信するバッチジョブ。
- `src/deep_research.py`: MCP ツール呼び出しをトリガーに Web 検索・要約を行い、
  結果を Vault に保存する自律調査エンジン。
- `src/defrag.py`: 週次メンテナンス (vacuum, orphan cleanup, embedding integrity check)。
- `frontend-meeting/` (React + Vite): meeting-app 用フロントエンド。

## 主要機能 (MCP ツール)

`src/mcp_server.py` に `@mcp.tool()` で登録されている MCP ツールは 140 個 (実カウント)。
`src/mcp_categories.py` により、ツール名のプレフィックスで以下のカテゴリに分割され、
ChatGPT 等のツール数上限に合わせて複数のコネクタ (`/ops/mcp`, `/sheets/mcp`, ...) として
公開することもできる (`FOUNDATION_MCP_SPLIT=1`)。フル機能の単一エンドポイント (`/mcp`) は
Claude Code / claude.ai 向けに常時提供される。

| カテゴリ | 主なツール名プレフィックス | 内容 |
| --- | --- | --- |
| ops | `vault_*`, `reindex`, `tmux_list`, `agent_*` | Vault メンテナンス、tmux エージェント spawn/監視 |
| sheets | `sheets_*` | Google Sheets 読み書き |
| memory | `recall`, `forget_*`, `commit_memory`, `memory_*`, `rag_fullload`, `deep_research`, `citations_format`, `ingest_session`, `mf_*` | 長期記憶の検索・書込・訂正、Web 調査、MoneyForward 連携 |
| comms | `teams_*`, `discord_send` | Microsoft Teams 参照、Discord 通知 |
| tasks | `gtasks_*`, `tasks_sync`, `web_*`, `local_*`, `attachment_*`, `flight_search`, `taildrop_*`, `gpu_status`, `kakeibo_*` | Google Tasks、ローカル LLM 呼出、添付ファイル授受、航空券検索、家計簿 |
| search | `hybrid_search`, `semantic_search`, `keyword_search`, `get_note`, `get_related`, `get_session`, `read_file`, `search_facts`, `search_turns`, `list_sessions`, `list_tags`, `reminders_*`, `meeting_*`, `pdf_*` | Vault/セッションのハイブリッド検索、リマインダー、会議文字起こし、PDF OCR |
| smarthome | `smarthome_*` | HomeKit ブリッジ経由のスマートホーム操作 |

## 技術スタック

- 言語: Python 3.13 (バックエンド), TypeScript / React 19 + Vite (フロントエンド)
- MCP サーバー: `mcp` SDK (streamable-http / stdio 両対応)、独自 OAuth 2.0 Authorization Server
- Web フレームワーク: FastAPI + uvicorn (meeting-server / gpu-scheduler)
- データベース: PostgreSQL 17 (会話・ファクト・タスク等の構造化データ)
- ベクトル検索: Qdrant (knowledge / sessions コレクション、ハイブリッド検索 + RRF)
- 埋め込み/リランカ: `cl-nagoya/ruri-v3-310m` (sentence-transformers)
- 音声認識: Kotoba-Whisper (whisper.cpp 経由)、NeMo (TitaNet 話者ID / MSDD)、Silero-VAD
- OCR: Surya OCR (surya-ocr)
- LLM 呼び出し: ローカル (Ollama / llama-server, Qwen3.6 系) + 外部 OpenAI 互換
  エンドポイント経由の外部モデル (任意設定)
- コンテナ: Docker Compose (postgres, qdrant, gpu-scheduler, meeting-app, caddy)
- リバースプロキシ: Caddy 2 (HTTPS, Tailscale tailnet 経由での公開を想定)

## セットアップ

### 前提

- Docker / Docker Compose v2
- NVIDIA GPU + nvidia-container-toolkit (gpu-scheduler を Docker で動かす場合)
- ホスト側で Ollama (`0.0.0.0:11434`) が起動していること
- 外部 OpenAI 互換エンドポイント (既定 `0.0.0.0:8317`、`OPENAI_COMPAT_URL` で変更可) を
  使う機能を有効にする場合は、そのエンドポイントが起動していること (ローカル LLM
  のみで運用する場合は不要)
- Python 3.13、Node.js 22 (ホストで直接実行する場合)

### 1. リポジトリ取得と依存インストール (ホストで直接実行する場合)

```bash
python3.13 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
```

GPU / meeting-app の各サービスを個別に Docker ビルドする場合は
`docker/requirements-gpu.txt` / `docker/requirements-meeting.txt`
がそれぞれのイメージでインストールされる (トップレベル `requirements.txt` はホストでの
直接実行・開発用の統合版)。

### 2. PostgreSQL / Qdrant

Docker Compose 経由で起動する場合は次の手順のみで済む (`docker/init-db.sql` が
初回起動時にスキーマを自動作成する)。ホストに直接インストールする場合は
PostgreSQL 17 系と Qdrant を用意し、`config.yaml` の `database` セクションと
`config/qdrant.yaml` に合わせて設定する。

### 3. 環境変数ファイル

`docker/.env` (gitignore 対象、リポジトリには含まれない) を作成し、最低限
`POSTGRES_PASSWORD` と `DATABASE_URL` を設定する。

```bash
cat > docker/.env <<'EOF'
POSTGRES_DB=foundation
POSTGRES_USER=user
POSTGRES_PASSWORD=change-me
DATABASE_URL=postgresql://user:change-me@postgres:5432/foundation
VAULT_OUTPUT_HOST_DIR=/path/to/your/obsidian/vault
MODEL_CACHE_HOST_DIR=/path/to/huggingface/cache
EOF
```

### 4. docker-compose での起動

```bash
# 全サービスをコンテナで起動 (GPU コンテナは nvidia-container-toolkit が必要)
docker compose --env-file docker/.env up -d

# PostgreSQL/Qdrant/gpu-scheduler をホスト側 systemd 等で既に動かしている場合は
# docker-compose.override.yml で該当コンテナを無効化できる
docker compose --env-file docker/.env -f docker-compose.yml -f docker-compose.override.yml up -d
```

HTTPS 終端が必要な場合は `docker/Caddyfile.example` を `docker/Caddyfile` にコピーし、
basic_auth のハッシュ等プレースホルダを実値に置き換える (`docker/Caddyfile` は
gitignore 対象)。

### 5. Claude Code への MCP サーバー登録 (stdio)

```bash
python src/mcp_server.py              # stdio モード
python src/mcp_server.py http         # streamable-http + OAuth モード (claude.ai 等向け)
```

Claude Code の `mcp` 設定に、上記コマンドを stdio サーバーとして登録する。

## 設定

### config.yaml

トップレベルの `config.yaml` は個人パス (`~/Documents/obsidian/vault` 等) や
ユーザー名を汎用プレースホルダに置き換えたダミー値のみで構成されており、そのまま
利用開始できる。主な項目:

- `vault`: Obsidian Vault のルートパスと索引除外パターン
- `database`: PostgreSQL / Qdrant の接続先とコレクション定義
- `embedding` / `search.rerank`: 埋め込み・リランカモデルとハイブリッド検索のパラメータ
- `gpu_scheduler`: GPU メモリ管理の advisory 値
- `llm`: 用途別 (realtime / batch / meeting.*) の LLM モデル割当と生成パラメータ
- `whisper`: 音声認識モデルと言語設定
- `maintenance`: 週次メンテナンスのスケジュール

実運用のパス (Vault の実際の場所、モデルキャッシュの場所等) は環境変数
(`VAULT_OUTPUT_HOST_DIR` 等、docker-compose.yml 参照) または `config.yaml` 本体を
自分の環境に合わせて編集して指定する。

### 主な環境変数

| 変数 | 用途 | 既定値/備考 |
| --- | --- | --- |
| `DATABASE_URL` | PostgreSQL 接続文字列 (Docker サービス間) | 必須 (docker-compose) |
| `POSTGRES_PASSWORD` | PostgreSQL パスワード | 必須 (docker-compose) |
| `QDRANT_HOST` / `QDRANT_PORT` | Qdrant 接続先 | `localhost` / `6333` |
| `OLLAMA_URL` | ローカル LLM (Ollama) エンドポイント | `http://localhost:11434` |
| `LLAMA_SERVER_BATCH_URL` | バッチ用 llama-server エンドポイント | `http://localhost:11435` |
| `OPENAI_COMPAT_URL` | 外部 LLM 用 OpenAI 互換エンドポイント | `http://localhost:8317` |
| `GPU_SCHEDULER_URL` | gpu-scheduler の HTTP エンドポイント | `http://gpu-scheduler:9400` |
| `GPU_SCHEDULER_OWNS_EMBEDDER` | 埋め込みモデルの直接ロードを gpu-scheduler だけに限定するガード | gpu-scheduler コンテナのみ `1` |
| `VAULT_OUTPUT_DIR` | コンテナ内での Vault 出力先マウントポイント | `/output` |
| `HF_TOKEN` | HuggingFace の認証トークン (ゲート付きモデル利用時) | 任意 |
| `LOG_LEVEL` | ログレベル | `INFO` |
| `FOUNDATION_ALLOWED_EMAILS` | OAuth (streamable-http モード) の許可メールアドレス一覧 | 必須 (http モード時) |

これ以外にも `WHISPER_*` / `RRF_*` / `MEETING_V2_*` / `RERANK_*` 等、機能ごとの
チューニング用環境変数が多数存在する。既定値は各モジュールのソース (`os.getenv` 呼び出し
箇所) を参照。

## ディレクトリ構成

```
.
├── bin/                    運用スクリプト (Discord webhook 登録、通知用ラッパー等)
├── config/                 Qdrant 設定 (config/qdrant.yaml)
├── config.yaml             アプリケーション設定 (DB接続・モデル・スケジューラ等)
├── docker/                 Dockerfile 2 種、サービス別 requirements、Caddyfile 例、init-db.sql
├── docs/                   設計・レビュー・テスト計画ドキュメント
├── frontend-meeting/       meeting-app 用フロントエンド (React + Vite)
├── src/                    Python バックエンド一式
│   ├── mcp_server.py       MCP サーバー本体 (140 tools)
│   ├── meeting_server.py   会議録音処理サーバー
│   ├── meeting_pipeline.py 会議処理パイプライン (v2〜v5)
│   ├── gpu_scheduler_server.py  GPU タスクの排他スケジューラ
│   ├── indexer.py          Vault インデクサ
│   ├── orchestrator/       tmux エージェント spawn/管理
│   ├── morning_digest/     朝刊集約バッチ
│   └── ...
├── tests/                  pytest テスト一式 (レイヤ別統合テスト、PII マスキングテスト等)
├── docker-compose.yml       本番構成 (全サービスをコンテナで起動)
├── docker-compose.override.yml  ホスト常駐サービスを使う場合の上書き構成
├── requirements.txt         統合 Python 依存 (本リポジトリ整備で新規作成)
└── pytest.ini
```

## 注意事項

- 本リポジトリは個人 (1 ユーザー) の長期記憶基盤として開発されたものであり、
  マルチテナント運用や不特定多数の同時利用は想定していない。OAuth の承認も
  単一のメールアドレス allow-list (`FOUNDATION_ALLOWED_EMAILS`) を前提とした設計。
- 公開版では大学 LMS (TLMS) 連携モジュール等、個人・所属先に紐づく一部モジュールを
  除外している。`config.yaml` や各モジュールのコメントに元機能への言及が残っている
  箇所があるが、対応する実装ファイルは本リポジトリに含まれない。
- 公開版では iPhone PWA バックエンドと専用フロントエンドを除外している。
  meeting-app 等の他機能が使う外部 LLM 呼び出しは、任意の外部 OpenAI 互換エンドポイント
  (`OPENAI_COMPAT_URL`) を指す汎用 HTTP クライアントに一般化済み。
- 実運用には GPU (音声認識/OCR/埋め込み用)、Tailscale 等の tailnet、ローカル LLM
  サーバー (Ollama / llama-server) など、このリポジトリ単体では完結しない周辺環境が
  必要になる。