Picard MCP サーバー
概要
Picard MCPは、モデルコンテキストプロトコル(MCP)標準に基づいて構築された完全なメモリ管理システムです。セキュアなメモリ保存および取得サービスを提供するMCPサーバーと、MCPサーバーとの統合方法を示すDjangoクライアントアプリケーションの2つの主要コンポーネントで構成されています。このシステムにより、ユーザーはアクセス権限を制御しながらメモリを保存、取得、管理することができ、保存されたメモリに基づくセマンティック検索やAIを活用したクエリを実行できます。
MCPコンプライアンス
この実装は、LLMアプリケーションが標準化された方法でサーバーとやり取りできるようにするモデルコンテキストプロトコル標準に準拠しています。MCPサーバーは以下を公開します。
リソース: LLMにデータを提供する読み取り専用エンドポイント(メモリコンテンツ)
ツール: アクション(メモリの作成、更新、クエリ)を実行する機能エンドポイント
認証: 保護されたリソースへの安全なアクセスのための OAuth 2.0 実装
主要コンポーネント
MCP サーバー: 次の機能を提供するモデル コンテキスト プロトコルの FastAPI ベースの実装。
PKCEサポートによるOAuth 2.0認証と認可
ベクトル埋め込みによるメモリストレージ
許可ベースのメモリアクセス制御
メモリベースのクエリのためのLLM統合
Django クライアント: MCP サーバーとの統合を示す Web アプリケーション:
ユーザー登録と認証
OAuth 2.0 クライアント実装
メモリの作成、取得、管理UI
ペルソナベースのクエリインターフェース
Related MCP server: Memory Cache Server
システムアーキテクチャ
全体的なアーキテクチャ
Picard MCP システムは、次のコンポーネントを持つクライアント サーバー アーキテクチャに従います。
MCP サーバー: メモリの保存、取得、AI 操作を処理するコア バックエンド サービス
高性能と非同期サポートを実現するFastAPI(FastMCP)を搭載
ベクトルストレージとセマンティック検索のために、pgvector拡張機能を備えたPostgreSQLを使用します。
ユーザー、メモリ(ベクトル埋め込み付き)、OAuth クライアント、トークンのデータ モデルを実装します。
データベース管理にはSQLAlchemy ORMとAlembicマイグレーションを使用します
安全な認証と認可のためにOAuth 2.0を実装
メモリ埋め込み用の OpenAI API と統合します (text-embedding-3-small)
利用可能な場合は LangChain を LLM 操作に使用します
ステートフルとステートレスの両方の動作モードを提供
スケーラビリティ向上のため、ストリーミング可能な HTTP トランスポートをサポート
Django クライアント: MCP サーバーとの統合を示す Web アプリケーション
ユーザー登録、認証、プロファイル管理を提供します
MCP サーバーとの安全な通信のために OAuth 2.0 クライアントを実装します
メモリ管理とクエリのためのユーザーフレンドリーなインターフェースを提供します
MCPサーバーとは別に独自のPostgreSQLデータベースを使用する
Docker インフラストラクチャ: コンテナ化されたデプロイメントにより、セットアップとスケーリングが簡単
MCP サーバー (ポート 8001)、Django クライアント (ポート 8000)、および PostgreSQL データベース用の個別のコンテナ
安全なコンテナ間通信のためのネットワーク構成
永続的なデータストレージ用のボリュームマウント
ローカル Docker デプロイメントと Render クラウド デプロイメントの両方に対応
認証アプローチ
システムでは、主に 2 つの認証方法を提供しています。
1. ユーザーコンテキストトークンフローを使用した直接接続(推奨)
この簡略化されたアプローチにより、ユーザーは Django クライアントで 1 回だけ認証することができ、個別の MCP サーバー認証が必要なくなります。
クライアント登録:
Djangoクライアントは
/api/admin/clients/registerエンドポイントを使用してMCPサーバーに登録します。登録には管理者認証が必要で、クライアント名、リダイレクトURI、要求されたスコープが含まれます。
MCPサーバーはUUIDベースのクライアントIDと暗号化されたクライアントシークレットを発行します。
クライアントの資格情報は安全に保存され、クライアント側のコードで公開されないようにする必要があります。
ユーザー認証フロー:
ユーザーはDjangoクライアントでのみ認証されます
ユーザーがMCPサーバーへの接続を開始すると、DjangoクライアントはMCPの
/api/user-tokens/user-tokenエンドポイントにサーバー側のリクエストを送信します。リクエストには以下が含まれます:
クライアント資格情報(client_id と client_secret)
ユーザー情報(ユーザー名とメールアドレス)
存在しない場合にユーザーを作成するオプション
MCPサーバーはクライアントの資格情報を検証し、対応するユーザーを見つけるか作成します。
MCPサーバーはユーザーにアクセストークンとリフレッシュトークンを発行します
Djangoクライアントはこれらのトークンを安全に保存し、APIリクエストに使用します。
APIアクセス:
クライアントは、すべてのAPIリクエストのAuthorizationヘッダー(
Authorization: Bearer {token})にアクセストークンを含めます。MCPサーバーはトークンの署名、有効期限、およびオーディエンスクレームを検証します。
MCPサーバーは各エンドポイントに対してスコープベースの権限を適用します
アクセストークンの有効期限が切れると、クライアントはリフレッシュトークンを使用して新しいトークンを取得します。
セキュリティ機能:
機密クライアントのみがこのメソッドを使用できるため、サーバー間のセキュリティが確保されます。
クライアントの資格情報はトークンリクエストごとに検証されます
リプレイ攻撃を防ぐために、トークンは使用後にブラックリストに登録されます。
リフレッシュトークンはローテーションを使用します。使用するたびに新しいリフレッシュトークンが生成され、古いものは無効になります。
2. PKCE を使用した標準 OAuth 2.0 認可コードフロー(レガシー)
システムは、RFC 6749およびRFC 7636標準に準拠した、PKCEを使用した標準OAuth 2.0認可コードフローもサポートしており、セキュリティを強化しています。このアプローチでは、ユーザーはクライアントとMCPサーバーの両方で認証を行う必要があります。
承認フロー:
ユーザーはDjangoクライアントを通じてログインを開始する
クライアントはCSRF保護のために暗号的に安全なランダム
stateパラメータを生成するクライアントはランダムなPKCE
code_verifierを生成し、SHA-256を使用してcode_challengeを導出します。クライアントは次のように MCP サーバーの
/authorizeエンドポイントにリダイレクトします。response_type=codeclient_id(UUID形式)redirect_uriscope(スペース区切りのリスト、例:memories:read memories:write)state(CSRF保護のため)PKCEパラメータ(
code_challengeおよびcode_challenge_method=S256)
MCP サーバーがユーザーを認証します (まだ認証されていない場合)
MCPサーバーはすべてのパラメータを検証し、短命の認証コードでクライアントにリダイレクトします。
トークン交換:
クライアントは返された
stateパラメータが認可リクエストで送信されたものと一致することを確認します。クライアントは
/tokenエンドポイント経由でアクセストークンとリフレッシュトークンの認証コードを交換します。MCPサーバーはJWTアクセストークン、リフレッシュトークン、有効期限、および許可されたスコープを発行します。
APIアクセス:
ダイレクトコネクトアプローチと同じ
データベースモデル
MCP サーバーは、次の主要モデルで SQLAlchemy ORM を使用します。
ユーザーモデル:
メールアドレス、ユーザー名、ハッシュ化されたパスワードなどのユーザー情報を保存します
アカウントステータスのブールフラグ(is_active、is_superuser)が含まれます
1対多の関係を通じて記憶にリンク
ベクトルストレージを備えたメモリモデル:
pgvector拡張機能を使用してベクトル埋め込み(1536次元)を保存およびクエリします。
オプションの暗号化によるテキストコンテンツをサポート
権限制御(プライベート/パブリック)が含まれます
期間限定のメモリの有効期限をサポート
外部キー関係を通じてユーザーに関連付けられる
OAuth モデル:
OAuthClient : client_id、client_secret、リダイレクトURI、承認済みスコープなどのクライアントアプリケーションの詳細を保存します。
AuthorizationCode : PKCE サポートによる一時認証コードを管理します
トークン: 有効期限追跡機能付きでアクセストークンとリフレッシュトークンを保存します
このシステムでは、データベースの移行に Alembic を使用し、スキーマのバージョン管理と簡単な更新を保証します。
メモリ管理システム
Picard MCP のコア機能は、次のコンポーネントによるメモリ管理を中心に展開されます。
メモリストレージ:
記憶は関連するメタデータとともにテキストとして保存されます
ベクトル埋め込み(テキスト埋め込み3小モデルを使用)によりセマンティック検索機能が有効になります
権限は各メモリに誰がアクセスできるかを制御します
タイムスタンプは作成、変更、有効期限を追跡します
メモリテキストは保存時に暗号化されますが、メタデータは検索可能なままです
すべての識別子は、スケーラビリティのために連続した整数ではなくUUID形式を使用します。
各メモリはOpenAIの埋め込みモデルを使用してベクトル埋め込みに変換されます。
埋め込みによりセマンティック検索と類似性マッチングが可能
pgvector拡張機能を備えたPostgreSQLは、効率的なベクトルの保存と取得を提供します。
権限管理:
各メモリには権限レベル(プライベートまたはパブリック)があります
プライベートな記憶は所有者のみがアクセスできます
公開メモリは他のユーザーがペルソナクエリのためにアクセスできます
システムは、将来の許可タイプ(例:統計/集計使用)に合わせて拡張できるように設計されています。
共有メモリは特定のユーザーまたはグループがアクセスできます
権限はメモリ所有者によっていつでも変更できます
記憶の想起:
ユーザーはフィルタリングや並べ替えのオプションを使って自分の思い出を検索できる
セマンティック検索では、キーワードだけでなく意味に基づいて記憶を見つけることができます
ベクトル類似度(コサイン)により、データベース全体で関連する記憶を見つけることができます。
クエリの関連性に基づいて、最も類似した上位N個のメモリが返されます。
権限チェックにより、ユーザーは許可されたメモリのみにアクセスできます
LLM統合:
メモリはLLMクエリのコンテキストとして使用できます
ユーザーは公開された記憶に基づいてペルソナを作成できます
他のユーザーはこれらのペルソナに問い合わせて、記憶に基づいた回答を得ることができます。
システムはコンテキスト管理と迅速なエンジニアリングを自動的に処理します。
主な特徴
MCP サーバーの機能
OAuth 2.0認証:
セキュリティ強化のためのPKCEによる認証コードフロー
スコープベースの権限システム (
memories:read、memories:write、memories:admin)リフレッシュトークンをサポートするトークン管理
クライアントの登録と管理
メモリ管理:
思い出を作成、読み取り、更新、削除する
セマンティック検索のためのベクトル埋め込み
許可ベースのアクセス制御
効率的なメモリ管理のためのバッチ操作
ユーザー管理:
ユーザー登録と認証
プロフィール管理と設定
アクティビティの追跡と分析
システム管理のための管理者コントロール
AI統合:
埋め込みとLLMクエリのためのOpenAI API統合
ユーザーの記憶に基づいたペルソナ作成
コンテキスト認識クエリ処理
カスタマイズ可能なAIパラメータと設定
Djangoクライアントの機能
ユーザーインターフェース:
デスクトップとモバイル向けのクリーンでレスポンシブなデザイン
直感的なメモリ管理インターフェース
高度な検索とフィルタリングオプション
ペルソナ作成とクエリインターフェース
OAuth クライアント実装:
安全なトークンの保管と管理
自動トークン更新
スコープベースの機能の可用性
エラー処理と回復
メモリツール:
リッチテキストサポートによるメモリ作成
一括インポートとエクスポート
権限管理インターフェース
タグ付けと分類
MCPインターフェース
MCPリソース
メモリリソース:
memories://{memory_id}権限チェック付きで特定のメモリの内容を返します
パラメータ:memory_id (UUID)
応答: メタデータを含むメモリコンテンツ
ユーザーメモリーリソース:
users://{user_id}/memories権限チェックを行った特定のユーザーの思い出のリストを返します
パラメータ: user_id (UUID)、オプションのフィルタ
応答: メモリ概要のリスト
MCPツール
メモリツールを送信: 新しいメモリを作成します
パラメータ: テキスト (文字列)、権限 (文字列)
戻り値: UUIDで作成されたメモリの詳細
メモリ更新ツール: 既存のメモリを更新します
パラメータ:memory_id (UUID)、text (文字列)
戻り値: 更新されたメモリの詳細
メモリ削除ツール: メモリを削除します
パラメータ:memory_id (UUID)
戻り値: 成功確認
クエリメモリツール:記憶の意味的検索を実行する
パラメータ: クエリ (文字列)、制限 (整数)
戻り値: 関連するメモリのリスト
ユーザーのクエリ: 記憶に基づいてユーザーのペルソナを照会します
パラメータ: user_id (UUID)、query (文字列)
戻り値: ユーザーの記憶に基づいた応答
APIエンドポイント
OAuthエンドポイント
クライアント登録:
/registerメソッド: POST
説明: 新しいOAuthクライアントを登録する
リクエスト: クライアントの詳細 (ID、シークレット、リダイレクト URI、スコープ)
回答: クライアントの資格情報と登録情報
承認:
/authorizeメソッド: GET
説明: OAuth 認証フローを開始する
パラメータ: response_type、client_id、redirect_uri、scope、state、code_challenge、code_challenge_method
レスポンス: 認証コードを使用してクライアントにリダイレクトします
トークン交換:
/tokenメソッド: POST
説明: 認証コードをトークンと交換する
リクエスト: grant_type、code、redirect_uri、client_id、client_secret、code_verifier
レスポンス: アクセストークン、リフレッシュトークン、有効期限、スコープ情報
メモリエンドポイント
思い出を取得:
/api/tools(ツール:get_memories)メソッド: POST
説明: オプションのフィルタリングを使用して思い出を検索します
認証: ベアラートークン
リクエスト: オプションのフィルターパラメータ (user_id、権限、有効期限ステータス)
応答: ユーザーがアクセスできるメモリのリスト
リクエスト例:
{ "tool": "get_memories", "data": { "user_id": "550e8400-e29b-41d4-a716-446655440000", "permission": "private" } }
メモリの送信:
/api/tools(ツール:submit_memory)メソッド: POST
説明: 新しいメモリを作成する
認証: ベアラートークン
リクエスト: メモリテキスト、権限レベル、有効期限 (ISO 8601 形式、例: "2025-12-31T23:59:59Z")
応答: UUID識別子を含む作成されたメモリの詳細
リクエスト例:
{ "tool": "submit_memory", "data": { "text": "This is my memory content", "permission": "private" } }
思い出の取得:
/api/tools(ツール:retrieve_memories)メソッド: POST
説明: 認証されたユーザーのすべてのメモリを取得します
認証: ベアラートークン
応答: UUID識別子を持つメモリオブジェクトのリスト
リクエスト例:
{ "tool": "retrieve_memories", "data": {} }
メモリの更新:
/api/tools(ツール:update_memory)メソッド: POST
説明: 既存のメモリを更新する
認証: ベアラートークン
リクエスト: メモリ ID、更新されたコンテンツ、およびオプションで更新された有効期限 (ISO 8601 形式)
応答: メモリの詳細を更新しました
リクエスト例:
{ "tool": "update_memory", "data": { "memory_id": "550e8400-e29b-41d4-a716-446655440000", "text": "Updated memory content", "expiration_date": "2026-01-01T00:00:00Z" } }
権限の変更:
/api/tools(ツール:modify_permissions)メソッド: POST
説明: メモリの権限レベルを更新する
認証: ベアラートークン
リクエスト: メモリUUIDと新しい権限レベル
応答: メモリの詳細を更新しました
リクエスト例:
{ "tool": "modify_permissions", "data": { "memory_id": "550e8400-e29b-41d4-a716-446655440000", "permission": "public" } }
クエリユーザー:
/api/tools(ツール:query_user)メソッド: POST
説明: 思い出に基づいてユーザーのペルソナを照会します (他のユーザーには公開、自分には公開+非公開)
認証: ベアラートークン
リクエスト: ユーザーUUIDとクエリプロンプト
レスポンス: 期限切れでないメモリ(すべての有効なメモリまたはクエリに最も類似する上位Nのメモリ)を含むJSON
応答: ユーザーの記憶に基づいて AI が生成した応答
リクエスト例:
{ "tool": "query_user", "data": { "user_id": "550e8400-e29b-41d4-a716-446655440000", "prompt": "What are your thoughts on artificial intelligence?" } }
セットアップと展開
前提条件
Docker と Docker Compose
Python 3.10以上
OpenAI APIキー
完全なセットアップガイド
リポジトリをクローンします。
git clone https://github.com/yourusername/picard_mcp.git cd picard_mcp両方のコンポーネントの環境ファイルを作成します。
# For MCP server cp mcp_server/.env.example mcp_server/.env # For Django client cp django_client/.env.example django_client/.env環境ファイルを編集して構成を設定します。
mcp_server/.envで、データベースの資格情報、OpenAI API キー、管理者の資格情報を設定します。django_client/.envでデータベースの認証情報とOAuth設定を設定します
Docker Compose を使用してサービスを開始します。
docker-compose up -dこれにより、次のサービスが開始されます。
db-mcp: MCP サーバー用の PostgreSQL データベースdb-django: Django クライアント用の PostgreSQL データベースmcp_server: http://localhost:8001で実行されている MCP サーバーdjango_client: http://localhost:8000で実行されている Django クライアント
MCP サーバーの管理者ユーザーを作成します。
docker-compose exec mcp_server python scripts/create_admin_user.pyこれにより、環境変数で指定された資格情報を持つ管理者ユーザーが作成されます。
Django クライアントを MCP サーバーに登録します。
docker-compose exec django_client python register_oauth_client.pyこれにより、Django クライアントが MCP サーバーに登録され、Django クライアントの
.envファイルがクライアントの資格情報で更新されます。アプリケーションにアクセスします。
MCP サーバー: http://localhost:8001
Django クライアント: http://localhost:8000
Django クライアントでユーザー アカウントを作成し、アプリケーションの使用を開始します。
初期テスト
セットアップが正しく動作していることを確認するには、次のテストを実行します。
MCP サーバーテスト:
docker-compose exec mcp_server python -m pytestこれにより、OAuth エンドポイント、管理機能、メモリ管理など、MCP サーバーのすべての単体テストが実行されます。
Django クライアントテスト:
docker-compose exec django_client python manage.py testこれにより、Django クライアントと MCP サーバーの統合がテストされます。
手動テスト:
Djangoクライアントでhttp://localhost:8000/registerにユーザーアカウントを作成します。
OAuth経由でMCPサーバーにログインして接続する
思い出を作成、取得、管理する
セマンティック検索機能をテストする
セキュリティに関する考慮事項
データ保護
メモリテキストコンテンツはPythonのFernet対称暗号化(PKCS7パディング付きCBCモードのAES-128)を使用して保存時に暗号化されますが、メタデータは検索可能です。
個人を特定できる情報(PII)はテキストフィールドの暗号化によって保護されます
アクセストークンには、露出を制限するために1時間の有効期限があります。
リフレッシュトークンは長期間有効ですが、ローテーションを使用します。使用するたびに新しいリフレッシュトークンが生成され、古いトークンは無効になります。
OAuthトークンはDjangoクライアントのPostgreSQLデータベースに安全に保存されます。
UUIDの使用法
システム内のすべての識別子は、いくつかの理由により、連続した整数ではなく UUID v4 形式を使用します。
セキュリティ: UUIDはシステム情報やレコード数を公開しません
スケーラビリティ: UUIDはデータベース調整なしで生成できるため、分散システムが可能になります。
推測不可能: UUIDは推測することが事実上不可能であり、列挙攻撃を防止します。
一貫性: システム全体でUUIDを使用すると、他のサービスとの統合が簡単になります。
API 内のすべての ID (user_id、memory_id、client_id など) は UUID 形式である必要があります。
OAuth のベストプラクティス
実稼働環境では、すべての OAuth 通信に HTTPS を使用する必要があります。
認証コードは1回限り有効で、有効期間は短い(最大5分)
多層防御のため、すべてのクライアント(機密クライアントも含む)にPKCEが必要です。
リフレッシュトークンは長期間有効ですが、ユーザーまたは管理者によって取り消される可能性があります。
システムは失効したトークンのブラックリストを維持します
ドキュメント
APIドキュメント
MCP サーバーには、すべてのエンドポイントの Swagger/OpenAPI ドキュメントが含まれています。
サーバーが実行中のときに
/docsで Swagger UI にアクセスします。OpenAPI仕様は
/openapi.jsonで入手可能です。すべてのAPIエンドポイントは、リクエスト/レスポンススキーマと例とともに完全に文書化されています。
追加のドキュメントファイル
TESTING.md : アプリケーションをテストするための包括的なガイド
実装されたすべてのテストとその目的を説明します
ローカルおよび CI/CD でテストを実行する手順
テスト範囲を文書化し、追加テストが必要な領域を特定します
DEBUGGING.md : 問題とその解決策を追跡します
まだ修正されていない既知のバグを記録します
以前に解決されたバグとその解決策を文書化する
一般的な問題に対するトラブルシューティングのガイダンスを提供します
PLANNING.md : サイトの実装に必要なタスクの内訳を追跡します
サイトの実装に必要なタスクとサブタスクをリストします
タスクが完了したかどうかをチェックボックスで記録します
展開
このプロジェクトには、ローカル開発用のdocker-compose.ymlと、Render へのデプロイ用のrender.yamlブループリントが含まれています。同じコードベースが、Docker コンテナ内のローカル環境でも、Render クラウドサービスへのデプロイでも動作します。
MCP サーバーの展開
Docker デプロイメント(本番環境に推奨):
docker-compose up -dDocker Compose 構成には以下が含まれます。
コンテナ間通信のためのネットワーク構成
永続的なデータストレージ用のボリュームマウント
.env ファイルからの環境変数の設定
ポートマッピング(Django クライアントの場合は 8000、MCP サーバーの場合は 8001)
サービス依存関係のヘルスチェック
Render クラウド デプロイメント: 付属の
render.yamlブループリントを使用して Render にデプロイします。
ライセンス
マサチューセッツ工科大学