Built on the Django framework for web application development, providing the foundation for the MCP server's functionality including user authentication, admin interface, and database interactions.
Supports containerized deployment using Docker and Docker Compose, enabling consistent and isolated execution across different environments.
Uses .env files for configuration management, allowing customization of server settings through environment variables.
Integrates with Git for version control and deployment, providing instructions for cloning the repository as part of the setup process.
Implements testing with pytest, enabling automated verification of server functionality and ensuring reliability.
Built with Python programming language, requiring Python 3.9+ for operation and development.
Offers API documentation through Swagger UI, providing interactive exploration of the available API endpoints and operations.
Picard MCP Server
Overview
Picard MCP is a complete memory management system built on the Model Context Protocol (MCP) standard. It consists of two main components: an MCP server that provides secure memory storage and retrieval services, and a Django client application that demonstrates how to integrate with the MCP server. The system enables users to store, retrieve, and manage their memories while controlling access permissions, and allows for semantic search and AI-powered queries based on stored memories.
MCP Compliance
This implementation follows the Model Context Protocol standard, which allows LLM applications to interact with the server in a standardized way. The MCP server exposes:
Resources: Read-only endpoints that provide data to LLMs (memory content)
Tools: Functional endpoints that perform actions (memory creation, updates, queries)
Authentication: OAuth 2.0 implementation for secure access to protected resources
Key Components
MCP Server: A FastAPI-based implementation of the Model Context Protocol that provides:
OAuth 2.0 authentication and authorization with PKCE support
Memory storage with vector embeddings
Permission-based memory access control
LLM integration for memory-based queries
Django Client: A web application that demonstrates integration with the MCP server:
User registration and authentication
OAuth 2.0 client implementation
Memory creation, retrieval, and management UI
Persona-based querying interface
System Architecture
Overall Architecture
The Picard MCP system follows a client-server architecture with the following components:
MCP Server: Core backend service that handles memory storage, retrieval, and AI operations
Built with FastAPI (FastMCP) for high performance and async support
Uses PostgreSQL with pgvector extension for vector storage and semantic search
Implements data models for Users, Memories (with vector embeddings), OAuth Clients, and Tokens
Uses SQLAlchemy ORM with Alembic migrations for database management
Implements OAuth 2.0 for secure authentication and authorization
Integrates with OpenAI API for memory embeddings (text-embedding-3-small)
Uses LangChain for LLM operations when available
Provides both stateful and stateless operation modes
Supports streamable HTTP transport for better scalability
Django Client: Web application that demonstrates integration with the MCP server
Provides user registration, authentication, and profile management
Implements OAuth 2.0 client for secure communication with the MCP server
Offers a user-friendly interface for memory management and querying
Uses its own PostgreSQL database separate from the MCP server
Docker Infrastructure: Containerized deployment for easy setup and scaling
Separate containers for MCP server (port 8001), Django client (port 8000), and PostgreSQL databases
Configured networking for secure inter-container communication
Volume mounting for persistent data storage
Compatible with both local Docker deployment and Render cloud deployment
Authentication Approaches
The system offers two main authentication approaches:
1. Direct Connect with User Context Token Flow (Recommended)
This simplified approach allows users to authenticate only once with the Django client, avoiding the need for separate MCP server authentication:
Client Registration:
The Django client registers with the MCP server using the
/api/admin/clients/register
endpointRegistration requires admin authentication and includes client name, redirect URIs, and requested scopes
The MCP server issues a UUID-based client ID and cryptographically secure client secret
Client credentials should be stored securely and never exposed in client-side code
User Authentication Flow:
User authenticates only with the Django client
When the user initiates connection to the MCP server, the Django client makes a server-side request to the MCP's
/api/user-tokens/user-token
endpointThe request includes:
Client credentials (client_id and client_secret)
User information (username and email)
Option to create user if not exists
The MCP server verifies client credentials and either finds or creates a corresponding user
MCP server issues access and refresh tokens for the user
Django client securely stores these tokens and uses them for API requests
API Access:
Client includes the access token in the Authorization header (
Authorization: Bearer {token}
) for all API requestsMCP server validates the token signature, expiration, and audience claims
MCP server enforces scope-based permissions for each endpoint
When the access token expires, client uses the refresh token to obtain a new one
Security Features:
Only confidential clients can use this method, providing server-to-server security
Client credentials are verified for each token request
Tokens are blacklisted after use to prevent replay attacks
Refresh tokens use rotation: each use generates a new refresh token and invalidates the old one
2. Standard OAuth 2.0 Authorization Code Flow with PKCE (Legacy)
The system also supports the standard OAuth 2.0 Authorization Code flow with PKCE for enhanced security, following RFC 6749 and RFC 7636 standards. This approach requires users to authenticate with both the client and the MCP server:
Authorization Flow:
User initiates login through the Django client
Client generates a cryptographically secure random
state
parameter for CSRF protectionClient generates a random PKCE
code_verifier
and derivescode_challenge
using SHA-256Client redirects to MCP server's
/authorize
endpoint with:response_type=code
client_id
(UUID format)redirect_uri
scope
(space-separated list, e.g.,memories:read memories:write
)state
(for CSRF protection)PKCE parameters (
code_challenge
andcode_challenge_method=S256
)
MCP server authenticates the user (if not already authenticated)
MCP server validates all parameters and redirects back to the client with a short-lived authorization code
Token Exchange:
Client verifies the returned
state
parameter matches the one sent in the authorization requestClient exchanges the authorization code for access and refresh tokens via
/token
endpointMCP server issues a JWT access token, refresh token, expiration time, and granted scopes
API Access:
Same as in the Direct Connect approach
Database Models
The MCP Server uses SQLAlchemy ORM with the following key models:
User Model:
Stores user information with email, username, and hashed password
Includes boolean flags for account status (is_active, is_superuser)
Linked to memories through one-to-many relationship
Memory Model with Vector Storage:
Uses pgvector extension to store and query vector embeddings (1536 dimensions)
Supports text content with optional encryption
Includes permission controls (private/public)
Supports expiration dates for time-limited memories
Associated with users through foreign key relationship
OAuth Models:
OAuthClient: Stores client application details, including client_id, client_secret, redirect URIs, and authorized scopes
AuthorizationCode: Manages temporary authorization codes with PKCE support
Token: Stores access and refresh tokens with expiration tracking
The system uses Alembic for database migrations, ensuring schema versioning and easy updates.
Memory Management System
The core functionality of Picard MCP revolves around memory management with the following components:
Memory Storage:
Memories are stored as text with associated metadata
Vector embeddings (using text-embedding-3-small model) enable semantic search capabilities
Permissions control who can access each memory
Timestamps track creation, modification, and expiration
Memory text is encrypted at rest while metadata remains searchable
All identifiers use UUID format instead of sequential integers for scalability
Each memory is converted to a vector embedding using OpenAI's embedding model
Embeddings enable semantic search and similarity matching
PostgreSQL with pgvector extension provides efficient vector storage and retrieval
Permission Management:
Each memory has a permission level (private or public)
Private memories are only accessible to the owner
Public memories can be accessed by other users for persona queries
System is designed to be extensible for future permission types (e.g., for statistical/aggregated use)
Shared memories can be accessed by specific users or groups
Permissions can be modified by the memory owner at any time
Memory Retrieval:
Users can retrieve their own memories with filtering and sorting options
Semantic search allows finding memories based on meaning, not just keywords
Vector similarity (cosine) enables finding related memories across the database
Top-N most similar memories are returned based on query relevance
Permission checks ensure users only access authorized memories
LLM Integration:
Memories can be used as context for LLM queries
Users can create personas based on their public memories
Other users can query these personas to get responses informed by the memories
The system handles context management and prompt engineering automatically
Key Features
MCP Server Features
OAuth 2.0 Authentication:
Authorization Code flow with PKCE for enhanced security
Scope-based permission system (
memories:read
,memories:write
,memories:admin
)Token management with refresh token support
Client registration and management
Memory Management:
Create, read, update, and delete memories
Vector embedding for semantic search
Permission-based access control
Batch operations for efficient memory management
User Management:
User registration and authentication
Profile management and settings
Activity tracking and analytics
Admin controls for system management
AI Integration:
OpenAI API integration for embeddings and LLM queries
Persona creation based on user memories
Context-aware query processing
Customizable AI parameters and settings
Django Client Features
User Interface:
Clean, responsive design for desktop and mobile
Intuitive memory management interface
Advanced search and filtering options
Persona creation and query interface
OAuth Client Implementation:
Secure token storage and management
Automatic token refresh
Scope-based feature availability
Error handling and recovery
Memory Tools:
Memory creation with rich text support
Batch import and export
Permission management interface
Tagging and categorization
MCP Interface
MCP Resources
Memory Resource:
memories://{memory_id}
Returns the content of a specific memory with permission checks
Parameters: memory_id (UUID)
Response: Memory content with metadata
User Memories Resource:
users://{user_id}/memories
Returns a list of memories for a specific user with permission checks
Parameters: user_id (UUID), optional filters
Response: List of memory summaries
MCP Tools
Submit Memory Tool: Creates a new memory
Parameters: text (string), permission (string)
Returns: Created memory details with UUID
Update Memory Tool: Updates an existing memory
Parameters: memory_id (UUID), text (string)
Returns: Updated memory details
Delete Memory Tool: Deletes a memory
Parameters: memory_id (UUID)
Returns: Success confirmation
Query Memory Tool: Performs semantic search on memories
Parameters: query (string), limit (integer)
Returns: List of relevant memories
Query User: Queries a user's persona based on memories
Parameters: user_id (UUID), query (string)
Returns: Response based on user's memories
API Endpoints
OAuth Endpoints
Client Registration:
/register
Method: POST
Description: Register a new OAuth client
Request: Client details (ID, secret, redirect URIs, scopes)
Response: Client credentials and registration information
Authorization:
/authorize
Method: GET
Description: Initiate OAuth authorization flow
Parameters: response_type, client_id, redirect_uri, scope, state, code_challenge, code_challenge_method
Response: Redirects to client with authorization code
Token Exchange:
/token
Method: POST
Description: Exchange authorization code for tokens
Request: grant_type, code, redirect_uri, client_id, client_secret, code_verifier
Response: Access token, refresh token, expiration, and scope information
Memory Endpoints
Get Memories:
/api/tools
(tool:get_memories
)Method: POST
Description: Retrieve memories with optional filtering
Authentication: Bearer token
Request: Optional filter parameters (user_id, permission, expiration status)
Response: List of memories accessible to the user
Example Request:
{ "tool": "get_memories", "data": { "user_id": "550e8400-e29b-41d4-a716-446655440000", "permission": "private" } }
Submit Memory:
/api/tools
(tool:submit_memory
)Method: POST
Description: Create a new memory
Authentication: Bearer token
Request: Memory text, permission level, and expiration date (ISO 8601 format, e.g., "2025-12-31T23:59:59Z")
Response: Created memory details including UUID identifier
Example Request:
{ "tool": "submit_memory", "data": { "text": "This is my memory content", "permission": "private" } }
Retrieve Memories:
/api/tools
(tool:retrieve_memories
)Method: POST
Description: Get all memories for the authenticated user
Authentication: Bearer token
Response: List of memory objects with UUID identifiers
Example Request:
{ "tool": "retrieve_memories", "data": {} }
Update Memory:
/api/tools
(tool:update_memory
)Method: POST
Description: Update an existing memory
Authentication: Bearer token
Request: Memory ID, updated content, and optionally updated expiration date (ISO 8601 format)
Response: Updated memory details
Example Request:
{ "tool": "update_memory", "data": { "memory_id": "550e8400-e29b-41d4-a716-446655440000", "text": "Updated memory content", "expiration_date": "2026-01-01T00:00:00Z" } }
Modify Permissions:
/api/tools
(tool:modify_permissions
)Method: POST
Description: Update memory permission level
Authentication: Bearer token
Request: Memory UUID and new permission level
Response: Updated memory details
Example Request:
{ "tool": "modify_permissions", "data": { "memory_id": "550e8400-e29b-41d4-a716-446655440000", "permission": "public" } }
Query User:
/api/tools
(tool:query_user
)Method: POST
Description: Query a user's persona based on memories (public for other users, public+private for self)
Authentication: Bearer token
Request: User UUID and query prompt
Response: JSON containing non-expired memories, either all valid memories or top-N most similar to query
Response: AI-generated response based on user's memories
Example Request:
{ "tool": "query_user", "data": { "user_id": "550e8400-e29b-41d4-a716-446655440000", "prompt": "What are your thoughts on artificial intelligence?" } }
Setup and Deployment
Prerequisites
Docker and Docker Compose
Python 3.10+
OpenAI API key
Complete Setup Guide
Clone the repository:
git clone https://github.com/yourusername/picard_mcp.git cd picard_mcpCreate environment files for both components:
# For MCP server cp mcp_server/.env.example mcp_server/.env # For Django client cp django_client/.env.example django_client/.envEdit the environment files to set your configuration:
In
mcp_server/.env
: Set your database credentials, OpenAI API key, and admin credentialsIn
django_client/.env
: Set your database credentials and OAuth settings
Start the services using Docker Compose:
docker-compose up -dThis will start the following services:
db-mcp
: PostgreSQL database for the MCP serverdb-django
: PostgreSQL database for the Django clientmcp_server
: MCP server running on http://localhost:8001django_client
: Django client running on http://localhost:8000
Create an admin user for the MCP server:
docker-compose exec mcp_server python scripts/create_admin_user.pyThis will create an admin user with the credentials specified in your environment variables.
Register the Django client with the MCP server:
docker-compose exec django_client python register_oauth_client.pyThis will register the Django client with the MCP server and update the Django client's
.env
file with the client credentials.Access the applications:
MCP Server: http://localhost:8001
Django Client: http://localhost:8000
Create a user account in the Django client and start using the application.
Initial Testing
To verify your setup is working correctly, run the following tests:
MCP Server Tests:
docker-compose exec mcp_server python -m pytestThis will run all the unit tests for the MCP server, including OAuth endpoints, admin functionality, and memory management.
Django Client Tests:
docker-compose exec django_client python manage.py testThis will test the Django client's integration with the MCP server.
Manual Testing:
Create a user account in the Django client at http://localhost:8000/register
Log in and connect to the MCP server via OAuth
Create, retrieve, and manage memories
Test the semantic search functionality
Security Considerations
Data Protection
Memory text content is encrypted at rest using Python's Fernet symmetric encryption (AES-128 in CBC mode with PKCS7 padding) while metadata remains searchable
Personal identifiable information (PII) is protected through text field encryption
Access tokens have a 1-hour expiration time to limit exposure
Refresh tokens are long-lived but use rotation: each use generates a new refresh token and invalidates the old one
OAuth tokens are securely stored in the Django client's PostgreSQL database
UUID Usage
All identifiers in the system use UUID v4 format instead of sequential integers for several reasons:
Security: UUIDs don't expose system information or record counts
Scalability: UUIDs can be generated without database coordination, enabling distributed systems
Non-guessability: UUIDs are practically impossible to guess, preventing enumeration attacks
Consistency: Using UUIDs throughout the system simplifies integration with other services
All IDs in the API (user_id, memory_id, client_id, etc.) must be in UUID format.
OAuth Best Practices
All OAuth communication must use HTTPS in production environments
Authorization codes are single-use and short-lived (max 5 minutes)
PKCE is required for all clients, even confidential ones, for defense in depth
Refresh tokens are long-lived but can be revoked by users or administrators
The system maintains a token blacklist for revoked tokens
Documentation
API Documentation
The MCP server includes Swagger/OpenAPI documentation for all endpoints:
Access the Swagger UI at
/docs
when the server is runningThe OpenAPI specification is available at
/openapi.json
All API endpoints are fully documented with request/response schemas and examples
Additional Documentation Files
TESTING.md: Comprehensive guide to testing the application
Describes all implemented tests and their purposes
Instructions for running tests locally and in CI/CD
Documents test coverage and identifies areas needing additional testing
DEBUGGING.md: Tracks issues and their resolutions
Logs known bugs that have not yet been fixed
Documents previously solved bugs and their solutions
Provides troubleshooting guidance for common issues
PLANNING.md: Tracks the breakdown of tasks required to implement the site
Lists tasks and subtasks required to implement the site
Documents if a task has been completed with a checkbox
Deployment
This project includes a docker-compose.yml
for local development and render.yaml
blueprint for deploying to Render. The same codebase works both locally in Docker containers and when deployed to Render cloud services.
MCP Server Deployment
Docker Deployment (recommended for production):
docker-compose up -dThe Docker Compose configuration includes:
Network configuration for inter-container communication
Volume mounts for persistent data storage
Environment variable configuration from .env files
Port mappings (8000 for Django client, 8001 for MCP server)
Health checks for service dependencies
Render Cloud Deployment: Use the included
render.yaml
blueprint to deploy to Render.
License
MIT
This server cannot be installed
remote-capable server
The server can be hosted and run remotely because it primarily relies on remote services or has no dependency on the local environment.
A Django-based implementation of the Model Context Protocol (MCP) for managing political preferences and visions for the future.
Related MCP Servers
- AsecurityAlicenseAqualityModel Context Protocol (MCP) is a new, standardized protocol for managing context between large language models (LLMs) and external systems. In this repository, we provide an installer as well as an MCP Server for Upstash Developer API's.Last updated -33548MIT License
- AsecurityFlicenseAqualityA Model Context Protocol (MCP) server that optimizes token usage by caching data during language model interactions, compatible with any language model and MCP client.Last updated -42
- -securityFlicense-qualityA Model Context Protocol service that wraps Django's migration commands as MCP endpoints, making it easy to manage migrations across multiple services and integrate with CI/CD pipelines.Last updated -5
- -securityFlicense-qualityA Python-based implementation of the Model Context Protocol that enables communication between a model context management server and client through a request-response architecture.Last updated -