Recall Select

recall.select
最小限のエージェント記憶システム - 任意のエージェントに1つのURLを与えるだけで、ほぼゼロセットアップで長期記憶を獲得できます。Qdrant + FastMCP + FastAPI/Bootstrap 上に構築されています。
完全な設計と段階的なビルド計画については docs/specs/initial_specification.md を、注目すべき変更の実行記録については docs/specs/changelog.md を参照してください。
仕組み
記憶はベクトルとして保存されます。各記憶ストアは Qdrantコレクション であり、(user, project) ペアに 1対1 でマッピングされます。これらのベクトルに関するメタデータ(ユーザー、APIキー、プロジェクト、コレクションごとの使用量/制限統計)は MongoDB に保存されます。
flowchart LR
agent[Agent] --> web[FastAPI / MCP]
web <-->qdrant[Qdrant]
web <--> mongo[MongoDB]
web <--> embed[Embedding API]Qdrantコレクションは 遅延的に 作成されます。最初の記憶が (user, project) ペアに保存されるまで、Qdrantには何も触れません。
Related MCP server: LedgerMem MCP Server
アーキテクチャ
app/main.py- FastAPIアプリ。Bootstrapのランディングページを提供し、起動時にMongoのインデックスが存在することを確認します(コールド/リモートDBに対して耐性があります)。app/mcp_server.py- メモリリンクの背後にあるMCPサーバー。エージェントのMCPクライアントは{PUBLIC_BASE_URL}/m/{key}を指します(Streamable HTTP、ステートレス、JSONレスポンス)。パス内のAPIキーが完全な認証情報であり、ツールをキー所有者のデフォルトプロジェクトにスコープします。基本ツール:store_memory/recall_memory/delete_memory。セマンティックレイヤーツール(vector_semantics.pyを参照):link_memories/unlink_memories/annotate_memory/memory_connections/recall_connected- 接続されたエージェントはクライアント側で関係推論を行い(明示的な要求があった場合のみ)、これらは結果を取り込むかトラバースします。同じキーは、キーレスな/mcpエンドポイントに対してAuthorization: Bearerとして送信することもでき、シークレットをURL/ログから隠すことができます。{...}/m/{key}.md(app/api/connect.py内)は、対応するセットアップ手順(両方の形式)を提供します。app/dependencies.py- コアDIコンテナ(injector)。共有シングルトン(Qdrantクライアント、Mongoクライアント/DB、リモートエンベッダー)を構築します。FastAPIの依存関係(app/api/deps.py)と起動時は、クライアントを自分で構築するのではなく、app_containerから解決します。app/services/- サービスレイヤー(HTTP/ルートコードはなく、I/Oのみ):qdrant_store.py- Qdrantクライアント +ensure_collection/upsert_memory/search/delete_memory、およびセマンティックレイヤーが必要とするポイントレベルのプリミティブ(neighbors、scroll_points、retrieve_points、set_payload)。vector_semantics.py- ベクトルメモリユーティリティレイヤー: ストアを意味のグラフとして扱います。各ポイントのペイロード内の予約済み_semantics名前空間には、deixisアンカー(所有者、保存時刻。保存時に書き込まれる)、クライアントが抽出したエンティティ、およびクライアントが宣言した型付き関係(upsert_relationsはそれらを検証して保存します - サーバー側でLLM呼び出しはありません)が保持されます。宣言された関係には2つの品質ヘッジがあります:confidence(0-1]、エッジのトラバーサル強度をスケーリング)とvalid_till(ISO 8601; 期限切れのエッジはすべての読み取りパスで無視されるため、古い構造は自動的に廃止されます)。衛生管理:remove_relationsは間違ったエッジを削除し(upsert_relationsの修正版)、memory.delete_memoryはprune_relations_toを呼び出すため、メモリの削除後もぶら下がったエッジは残りません。 プラグイン可能な レンズ(topical/temporal/entity/declared)は型付きエッジを導出します。その上にsemantic_graph(マルチグラフ)、spreading_activation(接続による検索)、concept_clusters(創発的オントロジー)、infer_relation(宣言された真実が優先され、その後に幾何学的ヒューリスティック)が配置されます。パフォーマンスメモ: 入力エッジのルックアップ(relations_of(include_incoming=True))は現在、境界付きスクロールアンドスキャンです。逆トラバーサルがホットになった場合の修正は、Qdrantの ペイロードインデックス を_semantics.relations[].targetに作成し(create_payload_index、キーワードスキーマ)、スキャンの代わりにフィルタリングクエリを使用することです - 同じストア、インデックスのみ。スキーマは何も変わりません。mongo.py- Mongoクライアント、get_db()、およびensure_indexes()(一意の複合インデックスで1対1の(user, project)ルールを強制)。users.py-add_user、get_user、get_user_by_email、update_user。api_keys.py- ユーザーにバインドされたキー。SHA-256ハッシュとして保存(平文はadd_api_keyから一度だけ返され、永続化されません):add_api_key、delete_api_key、delete_user_keys、list_api_keys、get_labeled_key、get_by_key(提示されたトークンをハッシュ化し、ダイジェストと照合; MCP認証ゲートでrecord_use=Trueとするとlast_used_atがスタンプされます)。保存時、各キーは非秘密の表示ヒントも保持します -key_prefix+key_last4。masked()によってrs_ab12…wxyzとしてレンダリングされるため、シークレットを再公開することなくキーをリスト表示して区別できます。projects.py-add_project、get_project、list_projects、update_project、delete_project。collections.py-(user, project) ↔ Qdrantコレクションのレジストリ。collection_name(user_id, project_id)は内部命名標準(rs_{user}_{project})です。制限と統計のためにpoints_count/calls_countを追跡します。collection_provisioning.py- 両面のcreate_collection/destroy_collectionステップ。コレクションは、Mongoレジストリ行 と そのバッキングQdrantコレクションの両方が存在する場合にのみ存在します。これはcollectionsレジストリとqdrant_storeを1つのアトミックで冪等な操作に構成し、2つのストアが同期しなくなることがないようにします。作成は遅延的であるため、唯一の作成呼び出し元は最初のメモリ書き込み(memory.store_memory)です。コレクションAPIの削除はdestroy_collectionを使用します。embeddings.py-Embedder抽象化;embeddings_remote.py- 具体的なテキスト→ベクトルバックエンド(リモート埋め込みAPI、例: DeepInfra)。monobank.py- 最小限のMonobankアクワイアリングクライアント(create_invoice、fetch_invoice_status)とWebhook認証(fetch_pubkey/verify_signature、生のボディに対するECDSA-SHA256)。mcp-api.netのマーチャントトークンを再利用します。recall.selectは独自の請求書/リダイレクト/Webhookを所有します。billing.py- プランカタログと、MonobankのinvoiceIdをキーとする支払い記録。チェックアウト時にrecord_pending。apply_webhookは、success時に購入者のtierを 1回だけ 切り替えます(リトライ/重複に対して冪等)。reconcileはWebhookが見逃したものを解決します(以下参照)。ティアは 時間制限付き です:grant_tierはエンタイトルメントが付与される唯一の場所(支払い済み請求書または所有者の好意)であり、tier_expires_atとtier_grantsの監査行を書き込みます。effective_tier(user)はすべてのチェックが読み取る必要があるものです。保存されたpaid_2xの日付が過ぎている場合は無料アカウントになります。また、ティアごとの許容量の単一の真実の情報源でもあります:call_allowance(tier)/project_allowance(tier)(None= 無制限; 未知のティアは無料にフォールバック)。usage.py- 月間呼び出しメーターと価格モデルゲート。受け入れられた store/recall/delete のたびに、(user, カレンダー月)ごとのusage行にカウントされます。check_call_allowedは、ティアの月間call_allowanceが使い果たされると呼び出しを拒否し、QuotaExceededを発生させます。memory.pyで強制され(MCPツールとHTTPメモリAPIの両方がカバーされます)、app/main.pyによって HTTP 429 にマッピングされます。MCPトランスポートはツールエラーとして表面化します。全期間のcollections.calls_countとは別です。account.py- サインインした/accountページが表示する読み取り専用スナップショット(プラン、月間使用量、プロジェクトごとの保存数、マスクされた形式と作成日/最終使用日付のAPIキーリスト)。billing/usage/projects/collections/api_keysから構成されます。docs.py- 公開/docs統合ガイドのコンテンツ。MCPクライアント設定を1か所で構築します(mcp_config/mcp_config_json)。ドキュメントページ とapp/api/connect.pyのキーごとの.mdの両方で再利用されるため、2つがずれることはありません。INTEGRATIONSはガイドレジストリです(エントリを追加することでページを追加)。
公開ページ(app/main.py から提供、Bootstrap + Jinja、app/translations/*.yml によるi18n): / ランディング、/plans、/account(サインイン済み)、および /docs/integrations ガイド。FastAPIの組み込みAPIドキュメントは /docs から /api/docs(/api/redoc、/api/openapi.json)に移動され、公開サイトが /docs を所有します。
支払いはHTTPレイヤーを介して app/api/payments.py で処理されます: POST /api/me/checkout(サインイン済み)は請求書を作成し、Monobankの pay_url を返します。検証済みの POST /webhooks/monobank はティアを付与します。GET /payment/success|fail は化粧的なブラウザ戻りページです(エンタイトルメントはWebhook駆動であり、これらではありません)。
エンタイトルメントはWebhookだけに依存しません。 Monobankは各ステータス変更を1回だけ送信し、再送信しないため、再起動やプロキシの不具合でコールバックが失われると、支払った顧客が古いティアのままになり、こちら側で気付く手段がありません。そのため、アプリはプルも行います: PAYMENT_RECONCILE_MINUTES ごとにバックグラウンドスイープ(billing.reconcile_with_monobank、app/main.py のライフスパンで開始)が、5分経過してもまだ処理中の各支払いの実際のステータスを取得し、それを 同じ apply_webhook 遷移にプッシュします。プッシュとプルは互いに冪等です - どちらかが先に到達するとティアが付与され、もう一方は何もしません。payments の行はチェックアウトが 開始 されたときに書き込まれるため、created は「支払いページを開いた」ことを意味し、「支払った」ではありません。/admin/payments はその区別を明示的に表示します。
購入は1か月分(SUBSCRIPTION_DAYS)であり、永久ではありません: grant_tier は tier_expires_at をスタンプし、同じバックグラウンドループは期限切れのアカウントを無料に戻します(downgrade_expired)。アカウントページにはプランの有効期限が表示されます。まだ自動更新はありません - ユーザーが再度購入し、クレジットが残っている間に購入すると、ウィンドウが 延長 され、再開されるわけではありません。エンタイトルメントは effective_tier を通じて読み取られるため、期限切れの付与は、スイープが保存されたフィールドを書き換える前でもすぐに支払いを停止します。
自動更新がないため、アプリは 尋ねます: billing.renewal_state(user) は /account のプロンプトを駆動します - プランの最後の RENEWAL_WARNING_DAYS(7)日間の警告とワンクリック更新ボタン、および「プランが終了しました。更新してください」というプロンプトが LAPSED_PROMPT_DAYS(30)日間表示されます(ダウングレードスイープは lapsed_tier / tier_lapsed_at を記録するため、ページは何が期限切れになったかをまだ表示できます)。更新は、プランページが使用するのと同じ /api/me/checkout に投稿し、保持していたプランに事前設定されます。まだメールはありません - プロンプトは訪問したユーザーにのみ届きます。
すべてのCRUD関数はオプションの db=/client= 引数を取るため、ライブバックエンドなしでテストで駆動できます。
設定
環境変数で設定します(ローカルの .env は自動的に読み込まれます。コミットしないでください - .env.example を参照):
変数 | デフォルト値 | 目的 |
| (必須) | リモートのマネージドMongoDB接続文字列。 |
|
| データベース名。 |
|
| Qdrantエンドポイント(内部Composeネットワーク)。 |
| (ローカルではなし、本番では必須) | アプリとQdrant間で共有されるシークレット。Composeは |
|
| すべてのコレクションのベクトル次元数。リモートの埋め込みAPIには( |
| (必須) | リモート埋め込みAPIのAPIキー。 |
|
| OpenAI互換の埋め込みAPIベースURL。 |
| (サインインに必須) | Google OAuth 2.0 WebクライアントID。 |
| (サインインに必須) | Google OAuth 2.0クライアントシークレット。 |
| (開発用フォールバック) | セッションクッキーに署名します。本番環境では安定した値を設定してください。 |
|
| 公開オリジン。メモリリンクとOAuthリダイレクトURIを構築します。 |
|
| uvicornが信頼する |
| (支払いに必須) | Monobankアクワイアリングマーチャントトークン。mcp-api.netプラットフォームと共有 - 同一マーチャント、単一アカウント。請求書は |
|
| 購入者が支払い後にブラウザがリダイレクトされるURL。 |
|
| サーバー間コールバックで、ティアを付与します。公開アクセス可能である必要があります。 |
|
| マーチャント公開鍵に対してWebhookの |
|
| Monobankから処理中の支払いの実際のステータスを取得する間隔(分)。これにより、Webhookが失われても支払い中の顧客が取り残されることを防ぎます。 |
| (未設定 - エリア無効) |
|
|
| アンロックされた管理セッションが再ロックされるまでの時間。 |
オーナー管理エリア(/admin)
サポートやユーザーの視点確認のために、任意のユーザーの個人エリアへの読み取り専用ウィンドウです。ADMIN_SECRETを設定し(生成: python -c "import secrets; print(secrets.token_urlsafe(32))")、Webコンテナを再作成した後、{PUBLIC_BASE_URL}/adminを開き、セッションごとに一度キーを入力します。/admin/usersはすべてのアカウントを一覧表示します(メール、名前、ユーザーIDで検索可能)。各行から、そのユーザーのプラン、今期間の使用量、メモリカウント付きのプロジェクト、マスクされた形式のメモリリンクを開くことができます。
境界は意図的に設定されています。キーはPOSTで送信され(URLパラメータではないため、履歴やアクセスログに残りません)、間違った推測を繰り返すとクライアントは5分間ロックアウトされます。セッションはADMIN_SESSION_HOURS後に自動的に再ロックされ、このエリアのルートは何も書き込まず、メモリテキストやキーシークレットを公開しません。オーナーはアカウントの構造を見ることができても、その内容は見ることができません。ADMIN_SECRETが未設定の場合、このエリアはまったく存在しません。
認証(Googleサインイン)
サインインはメモリリンクへのゲートです。ユーザーはGoogleでサインインし、メモリリンクをコピーをクリックしてデフォルトのプロジェクト、コレクション、APIキーをプロビジョニングし、エージェントに渡すURLを取得します。シークレットは一度だけ表示されます(ハッシュのみが保存されます)。その後、ランディングページはリンクをマスクして表示し(GET /api/me/link経由)、ボタンは明示的で確認が必要な「新しいリンクを取得」に変わります。再生成は古いリンクを無効にし、サイレントに行われることはありません。キーは/accountで管理されます。マスクされたリスト、作成日/最終使用日、ラベル付き作成(一度だけ表示)、取り消し。Google認証情報を設定するには:
Google Cloud Console → APIs & Services → OAuth同意画面 - 設定します(外部。未検証の間はテストユーザーとしてメールアドレスを追加)。
認証情報 → 認証情報を作成 → OAuthクライアントID → Webアプリケーション。
承認済みのリダイレクトURIを追加:
{PUBLIC_BASE_URL}/auth/callback- 例: ローカル開発ではhttp://localhost:8000/auth/callback、本番ではhttps://recall.select/auth/callback(ローカルでテストする場合は両方を追加)。クライアントIDとクライアントシークレットを
.envにコピーします(GOOGLE_CLIENT_ID/GOOGLE_CLIENT_SECRET)。安定したSESSION_SECRETを設定します(python -c "import secrets; print(secrets.token_urlsafe(48))")。
ローカルでの実行
Docker Composeを使用したフルスタック(Web + Qdrant):
cp .env.example .env # then fill in MONGODB_URI
docker compose up --build
# open http://localhost:8000または、独自のQdrant/Mongoに対してアプリのみを実行:
pip install -e ".[dev]"
uvicorn app.main:app --reloadテスト
pip install -e ".[dev]"
pytestCRUDテストはインメモリMongo(mongomock)に対して実行され、Qdrant/埋め込みクライアントは偽装されています。ライブバックエンドは不要です。
デプロイ
./deploy/deploy.sh同じコマンドが2つの場所から機能します。実行された場所を検出します:
開発マシンから(またはエージェントのボックスから): ローカルコミットをプッシュし、
recall-serverSSHエイリアス経由でサーバー上でデプロイを実行します。サーバー上で(
setti@setti-server:~/recall_select$ ./deploy/deploy.sh): その場でデプロイ。SSHホップはありません。
どちらのパスも同じワーカーを実行します - deploy/_server_deploy.sh: masterのgit同期、Composeスタック(FastAPI web + Qdrant)の再ビルド、共有Caddyプロキシのリロード(recall.selectの自動HTTPS)、古いイメージの削除。MongoDBはリモート/マネージドであるため、認証/MONGODB_URI環境変数(.env参照)がサーバー上に存在している必要があります。
サーバー上で実行する人は、リポジトリへのGitHubプルアクセス(~/.ssh内の認証済みSSHキー)とdockerグループのメンバーシップが必要です。これはclaude-agentとsettiの両方で当てはまります。ワーカーはリポジトリをgitのsafe.directoryとして自動登録するため、リポジトリの所有者でないデプロイ担当者が「疑わしい所有権」によってブロックされることはありません。
自動デプロイ(CI)
masterへのすべてのプッシュは、GitHub Actions(.github/workflows/deploy.yml)を介して自動デプロイされます。上記と同じフローですが、人間ではなくCIによってトリガーされます。ジョブはサーバーにSSH接続し、deploy/_server_deploy.shを標準入力にパイプするため、プッシュされたコミット自身のデプロイロジックが実行されます。デプロイは直列化され(concurrency)、Run workflowボタン(workflow_dispatch)を使用してオンデマンドでデプロイすることもできます。
一度だけの設定 - Settings → Secrets and variables → Actionsの下に追加:
シークレット | 必須 | 目的 |
| はい | 公開鍵がデプロイユーザーの |
| はい | サーバーアドレスとデプロイを実行するSSHユーザー。 |
| いいえ | SSHポート(デフォルト |
| いいえ | サーバーのホストキーを固定します。未設定の場合、CIは |
アプリのシークレット(MONGODB_URI、OAuthなど)はサーバーの.envに残ります。CIがそれらを見ることはありません。
ライセンス
GNU Affero General Public License v3.0 に基づいてライセンスされています。ネットワークサービスとして修正版を実行する場合、AGPL はそのソースコードをユーザーに提供することを要求します。Copyright © 2026 Sergii Setti.
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 Servers
- AlicenseAqualityDmaintenancePersistent memory for AI agents. Store, recall, and share knowledge across sessions with five MCP tools: remember, recall, context, forget, and share. Includes semantic search and agent/user/org scoping.52Apache 2.0

LedgerMem MCP Serverofficial
AlicenseNot gradedqualityBmaintenanceEnables persistent memory storage and retrieval for MCP clients, allowing AI assistants to remember facts and context across conversations.10MIT- AlicenseNot gradedqualityCmaintenanceProvides persistent, local-first AI memory across sessions via MCP tools for storing, searching, and retrieving context from past interactions.1MIT
- AlicenseAqualityAmaintenanceProvides persistent memory for AI agents via 10 MCP tools that map to the AgentRAM REST API, enabling store, retrieve, search, and share memories across personal and shared namespaces.10191MIT
Related MCP Connectors
Shared, governed long-term memory for AI agents across tools and sessions via MCP and REST.
Shared long-term memory vault for AI agents with 20 MCP tools.
Your memory, everywhere AI goes. Build knowledge once, access it via MCP anywhere.
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/SergeySetti/recall_select'
If you have feedback or need assistance with the MCP directory API, please join our Discord server