rerofumi/fm-link-stash
If you are the rightful owner of fm-link-stash and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to henry@mcphub.com.
The Model Context Protocol (MCP) server is a robust backend solution designed to facilitate seamless integration with AI-powered applications, providing a standardized protocol for managing and interacting with model contexts.
fm-link-stash
Web リンクを効率的に整理・管理できる、モダンで AI 搭載のブックマーク管理アプリケーションです。LLM による自動タグ付け機能を備え、Web インターフェースと MCP (Model Context Protocol) サーバーの両方からアクセス可能で、AI アシスタントとの統合も可能です。
✨ 特徴
主要機能
- 🔖 クイック URL 登録: URL を貼り付けるだけで自動的にページ情報を取得
- 🤖 AI による整理: LLM を使用した自動タイトル最適化とタグ候補の提案
- 🏷️ タグベースの整理: 柔軟なタグ付けシステムとタグ検索・フィルタリング
- ⭐ お気に入り: 重要なブックマークをマークして素早くアクセス
- 📊 複数の表示モード: 最近登録・アクセス・更新順でソート可能
- 🎨 2つの表示形式: カード形式とリスト形式を切り替え可能
- 📱 レスポンシブデザイン: デスクトップとモバイルでシームレスに動作
高度な機能
- 🔐 セキュアな認証: PocketBase 認証を基盤とした安全な仕組み
- 🌐 CORS フリーの取得: バックエンドが URL 取得を処理し CORS 問題を回避
- 📈 アクセス追跡: ブックマークにアクセスした日時を記録
- 🌗 テーマサポート: ライトモードとダークモードのテーマ切り替え
- 🔄 リアルタイム更新: すべてのデバイス間で同期
MCP サーバー統合
- 🤝 LLM 統合: AI チャットアプリケーションから直接ブックマークを利用
- 🔑 トークンベースアクセス: 安全な MCP トークン管理
- 📡 JSON-RPC 2.0: ツール呼び出しの標準プロトコル
- 🛠️ 豊富な API: MCP ツールを通じた完全な CRUD 操作、検索、フィルタリング
🏗️ アーキテクチャ
フロントエンド + バックエンド構成
┌─────────────────────┐
│ React フロントエンド │ ← ユーザーインターフェース (Vite + React + Tailwind)
│ (ブラウザアプリ) │
└──────────┬──────────┘
│ PocketBase JWT 認証
↓
┌─────────────────────┐
│ PocketBase │ ← バックエンド (DB + 認証 + API + 静的サーバー)
│ v0.23 (JSVM) │
└──────────┬──────────┘
│
├──→ データベース (SQLite)
├──→ MCP JSON-RPC サーバー (POST /mcp/bookmark)
└──→ LLM プロバイダ (OpenAI API 互換)
技術スタック
フロントエンド:
- React 19.1
- TypeScript
- Tailwind CSS v4
- Vite
- Zustand (状態管理)
- PocketBase SDK
バックエンド:
- PocketBase v0.23 (JSVM)
- SQLite データベース
- JSON-RPC 2.0 (MCP)
- OpenAI 互換 LLM API
🚀 はじめに
前提条件
- Docker (推奨)
- Node.js 18+ (フロントエンド開発用)
- PocketBase v0.23+ (ローカル開発時)
- OpenAI API 互換サービス (例: OpenRouter, OpenAI)
🐳 Docker での利用(推奨)
-
イメージのビルド
git clone https://github.com/yourusername/fm-link-stash.git cd fm-link-stash docker build -t fm-link-stash . -
コンテナの起動
docker run -it --rm -p 8090:8090 \ -v ./pb_data:/pb/pb_data \ -v ./pb_public:/pb/pb_public \ fm-link-stash -
初回起動時の管理者作成
pb_dataが空の場合、コンテナ起動時にコンソールログに表示される superuser 作成用 URL にアクセス- 管理者アカウントを作成してセットアップを完了
重要: pb_data ディレクトリは必ず永続化してください。データベースとアップロードされたファイルが格納されます。
💻 ローカル開発
インストールと起動
-
リポジトリのクローン
git clone https://github.com/yourusername/fm-link-stash.git cd fm-link-stash -
環境変数の設定
ルートディレクトリに
.envファイルを作成:LLM_API_KEY=your_api_key_here LLM_BASE_URL=https://openrouter.ai/api/v1/ LLM_MODEL_NAME=openrouter/auto HTTP_FETCH_USER_AGENT=fm-link-stash/0.1 -
PocketBase のセットアップ
- pocketbase.io から PocketBase をダウンロード
- プロジェクトルートに
pocketbase(またはpocketbase.exe) を配置 - PocketBase を起動:
./pocketbase serve --http 0.0.0.0:8090
-
フロントエンドの開発環境設定
frontend/.envファイルを作成:VITE_API_URL=http://localhost:8090フロントエンドの起動:
cd frontend npm install npm run dev開発サーバーは
http://localhost:5173で起動します -
CORS 設定
PocketBase 管理画面 (
http://localhost:8090/_/) の Settings > API > CORS origins に開発サーバーのURL(http://localhost:5173)を追加してください。
本番デプロイ用ビルド
-
フロントエンドのビルド
cd frontend npm install npm run build -
静的ファイルの配置
# frontend/dist/ の中身を pb_public/ 直下にコピー cp -r frontend/dist/* pb_public/これにより PocketBase が静的ファイルを配信し、フロントエンドにアクセス可能になります。
初回セットアップ
- PocketBase 管理画面を開く:
http://localhost:8090/_/ - 初回アクセス時に表示される画面で管理者アカウントを作成
- フロントエンドにアクセスして新規ユーザー登録またはログイン
📖 使い方
Web インターフェース
-
ブックマークの登録
- ヘッダーの入力欄に URL を貼り付け
- Enter キーを押す
- アプリが自動的にページコンテンツを取得し、タグを提案
-
ブックマークの閲覧
- ナビゲーションタブで以下の条件で絞り込み:
- 最近登録
- 最近アクセス
- 最近更新
- お気に入り
- タグ一覧
- ナビゲーションタブで以下の条件で絞り込み:
-
検索とフィルタリング
- 検索ボックスでタグによるブックマークの絞り込み
- タグ一覧のタグをクリックして関連するブックマークを表示
-
ブックマークの管理
- 編集ボタンをクリックしてタイトル、URL、タグを変更
- 星アイコンをクリックしてお気に入りを切り替え
- ブックマークをクリックして開く (アクセス時刻を記録)
MCP サーバー (AI アシスタント向け)
-
MCP トークンの生成
- フロントエンドにログイン
- 設定/トークンに移動
- 新しい MCP トークンを作成
-
AI アシスタントの設定 MCP サーバー設定を追加:
{ "mcpServers": { "fm-link-stash": { "url": "http://127.0.0.1:8090/mcp/bookmark", "headers": { "Authorization": "Bearer YOUR_MCP_TOKEN" } } } } -
利用可能な MCP ツール
bookmark.createFromUrl- 新規ブックマーク登録bookmark.list- ブックマークの検索とフィルタリングbookmark.get- ブックマーク詳細の取得bookmark.update- ブックマークの編集bookmark.delete- ブックマークの削除bookmark.toggleFavorite- お気に入り状態の切り替えbookmark.registerAccess- アクセスの記録tag.listWithCounts- タグの統計情報取得tag.search- タグの検索token.introspect- トークン状態の確認
🔧 設定
環境変数
| 変数名 | 説明 | デフォルト値 |
|---|---|---|
LLM_API_KEY | LLM プロバイダの API キー | 必須 |
LLM_BASE_URL | LLM API のベース URL | https://openrouter.ai/api/v1/ |
LLM_MODEL_NAME | デフォルトのモデル名 | openrouter/auto |
HTTP_FETCH_USER_AGENT | URL 取得時の User-Agent | fm-link-stash/0.1 |
FETCH_TIMEOUT_MS | URL 取得のタイムアウト | 15000 |
MAX_FETCH_SIZE_BYTES | 取得するページの最大サイズ | 4194304 (4MB) |
セキュリティ設定
バックエンドは以下のセキュリティ対策を実装:
- SSRF 保護: プライベート IP 範囲へのアクセスをブロック
- URL 検証: 取得前に URL を検証・正規化
- レート制限: ユーザーごとのレート制限で乱用を防止
- Content-Type 検証: HTML コンテンツのみを取得
- トークン認証: 安全な MCP トークン管理
📚 API ドキュメント
MCP JSON-RPC エンドポイント
エンドポイント: POST /mcp/bookmark
認証:
Authorization: Bearer {MCP_TOKEN}
リクエスト形式 (JSON-RPC 2.0):
{
"jsonrpc": "2.0",
"method": "bookmark.createFromUrl",
"params": {
"url": "https://example.com",
"options": {
"dedupe": true
}
},
"id": "1"
}
レスポンス形式:
{
"jsonrpc": "2.0",
"result": {
"data": {
"id": "abc123",
"title": "Example Page",
"url": "https://example.com",
"tags": ["example", "website"],
"registered_at": "2025-01-01T00:00:00Z"
}
},
"id": "1"
}
詳細な API 仕様については を参照してください。
🗄️ データベーススキーマ
アプリケーションは以下の主要なコレクションを使用:
- users - ユーザーアカウント (PocketBase 認証)
- bookmarks - メタデータ付きブックマークレコード
- tags - 色付きタグ定義
- bookmark_tags - 多対多リレーション
- mcp_tokens - MCP アクセストークン
詳細なスキーマ情報については を参照してください。
📁 ディレクトリ構成
fm-link-stash/
├── frontend/ # フロントエンドソースコード
│ ├── src/ # React アプリケーション
│ ├── dist/ # ビルド成果物(npm run build 後)
│ └── .env # 開発時の環境変数
├── pb_public/ # PocketBase が配信する静的ファイル
│ # (frontend/dist の内容をここにコピー)
├── pb_data/ # PocketBase データベースとアップロードファイル
│ # ※必ずバックアップ・永続化が必要
├── pb_hooks/ # PocketBase JSVM フック
├── pb_migrations/ # データベースマイグレーション
├── .env # バックエンド環境変数
├── pocketbase # PocketBase バイナリ(ローカル開発時)
└── Dockerfile # Docker イメージビルド用
📋 バックアップとリストア
バックアップ
- サーバー停止: PocketBase を適切に停止
- データアーカイブ:
pb_data/ディレクトリ全体をアーカイブtar -czf backup-$(date +%Y%m%d-%H%M%S).tar.gz pb_data/
リストア
- サーバー停止: PocketBase を停止
- データリストア: バックアップした
pb_data/で置き換え - サーバー再起動: PocketBase を再起動
🛣️ ロードマップ
- Favicon のファイル保存 (現在は URL を保存)
- インポート/エクスポート機能 (HTML, JSON)
- ブラウザ拡張機能
- 検索強化
- 高度なフィルタリングオプション
🤝 コントリビューション
コントリビューションを歓迎します! お気軽に Pull Request を送信してください。
- リポジトリをフォーク
- フィーチャーブランチを作成 (
git checkout -b feature/AmazingFeature) - 変更をコミット (
git commit -m 'Add some AmazingFeature') - ブランチにプッシュ (
git push origin feature/AmazingFeature) - Pull Request を開く
📝 ライセンス
このプロジェクトは MIT ライセンスの下でライセンスされています。詳細は ファイルを参照してください。
🙏 謝辞
- PocketBase - 優れた BaaS (Backend as a Service)
- React - フロントエンドフレームワーク
- Tailwind CSS - スタイリング
- Model Context Protocol - AI 統合標準
📞 サポート
問題が発生した場合や質問がある場合:
- GitHub で Issue を開く
- を確認
👤 作者
rerofumi
⭐ このプロジェクトが役に立つと思ったら、GitHub でスターを付けていただけると嬉しいです!