Picard MCP 服务器
概述
Picard MCP 是一个基于模型上下文协议 (MCP)标准构建的完整内存管理系统。它由两个主要组件组成:一个提供安全内存存储和检索服务的 MCP 服务器,以及一个演示如何与 MCP 服务器集成的 Django 客户端应用程序。该系统允许用户在控制访问权限的同时存储、检索和管理他们的内存,并允许基于存储的内存进行语义搜索和 AI 查询。
MCP 合规性
此实现遵循模型上下文协议 (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 应用程序
提供用户注册、身份验证和配置文件管理
实现 OAuth 2.0 客户端与 MCP 服务器进行安全通信
提供用户友好的内存管理和查询界面
使用独立于 MCP 服务器的 PostgreSQL 数据库
Docker 基础设施:容器化部署,易于设置和扩展
MCP 服务器(端口 8001)、Django 客户端(端口 8000)和 PostgreSQL 数据库的独立容器
配置网络以实现安全的容器间通信
用于持久数据存储的卷安装
兼容本地 Docker 部署和渲染云部署
身份验证方法
该系统提供两种主要的身份验证方法:
1. 直接连接用户上下文令牌流程(推荐)
这种简化的方法允许用户仅使用 Django 客户端进行一次身份验证,从而避免了单独的 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: Bearer {token})MCP 服务器验证令牌签名、有效期和受众声明
MCP 服务器为每个端点强制执行基于范围的权限
当访问令牌过期时,客户端使用刷新令牌获取新的访问令牌
安全功能:
只有机密客户端才能使用此方法,从而提供服务器到服务器的安全性
针对每个令牌请求验证客户端凭据
令牌使用后会被列入黑名单,以防止重放攻击
刷新令牌使用轮换:每次使用都会生成一个新的刷新令牌并使旧令牌无效
2. 使用 PKCE 的标准 OAuth 2.0 授权码流程(遗留)
该系统还支持带有 PKCE 的标准 OAuth 2.0 授权码流程,以增强安全性,遵循 RFC 6749 和 RFC 7636 标准。此方法要求用户同时在客户端和 MCP 服务器上进行身份验证:
授权流程:
用户通过 Django 客户端发起登录
客户端生成加密安全的随机
state参数以进行 CSRF 保护客户端生成随机 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)
通过一对多关系链接到记忆
具有向量存储的内存模型:
使用 pgvector 扩展来存储和查询向量嵌入(1536 维)
支持可选加密的文本内容
包括权限控制(私人/公共)
支持限时记忆的到期日期
通过外键关系与用户关联
OAuth 模型:
OAuthClient :存储客户端应用程序详细信息,包括 client_id、client_secret、重定向 URI 和授权范围
AuthorizationCode :使用 PKCE 支持管理临时授权码
令牌:存储访问和刷新令牌,并跟踪到期时间
该系统使用 Alembic 进行数据库迁移,确保模式版本控制和轻松更新。
内存管理系统
Picard MCP 的核心功能围绕内存管理,包含以下组件:
内存存储:
记忆以文本形式存储,并附带相关元数据
向量嵌入(使用 text-embedding-3-small 模型)支持语义搜索功能
权限控制谁可以访问每个内存
时间戳跟踪创建、修改和到期
内存文本处于静态加密状态,但元数据仍可搜索
所有标识符均使用 UUID 格式,而不是连续整数,以实现可扩展性
使用 OpenAI 的嵌入模型将每个记忆转换为向量嵌入
嵌入支持语义搜索和相似性匹配
带有 pgvector 扩展的 PostgreSQL 提供高效的向量存储和检索
权限管理:
每个内存都有一个权限级别(私有或公共)
私人记忆只有主人才能访问
其他用户可以访问公共记忆以进行角色查询
系统设计为可扩展以适应未来的权限类型(例如,用于统计/汇总用途)
特定用户或群组可以访问共享记忆
内存所有者可以随时修改权限
记忆检索:
用户可以通过筛选和排序选项检索自己的记忆
语义搜索允许根据含义(而不仅仅是关键词)查找记忆
向量相似度(余弦)可以在数据库中找到相关的记忆
根据查询相关性返回 Top-N 最相似的记忆
权限检查确保用户只能访问授权的记忆
LLM 集成:
记忆可以用作 LLM 查询的上下文
用户可以根据自己的公开记忆创建角色
其他用户可以查询这些角色,以获得记忆中的信息
系统自动处理上下文管理和提示工程
主要特点
MCP 服务器功能
OAuth 2.0身份验证:
授权码流与 PKCE 配合使用,增强安全性
基于范围的权限系统(
memories:read、memories:write、memories:admin)支持刷新令牌的令牌管理
客户注册和管理
内存管理:
创建、读取、更新和删除记忆
用于语义搜索的向量嵌入
基于权限的访问控制
批量操作以实现高效的内存管理
用户管理:
用户注册和身份验证
配置文件管理和设置
活动追踪和分析
系统管理的管理员控制
人工智能集成:
用于嵌入和 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和查询提示
响应:包含未过期记忆的 JSON,可以是所有有效记忆,也可以是与查询最相似的前 N 个记忆
响应:基于用户记忆的人工智能生成的响应
示例请求:
{ "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这将向 MCP 服务器注册 Django 客户端,并使用客户端凭据更新 Django 客户端的
.env文件。访问应用程序:
MCP 服务器: http://localhost:8001
Django 客户端: http://localhost:8000
在 Django 客户端中创建用户帐户并开始使用该应用程序。
初步测试
要验证您的设置是否正常工作,请运行以下测试:
MCP 服务器测试:
docker-compose exec mcp_server python -m pytest这将运行 MCP 服务器的所有单元测试,包括 OAuth 端点、管理功能和内存管理。
Django 客户端测试:
docker-compose exec django_client python manage.py test这将测试 Django 客户端与 MCP 服务器的集成。
手动测试:
在 Django 客户端的http://localhost:8000/register中创建用户帐户
通过 OAuth 登录并连接到 MCP 服务器
创建、检索和管理记忆
测试语义搜索功能
安全注意事项
数据保护
内存文本内容使用 Python 的 Fernet 对称加密(CBC 模式下的 AES-128 和 PKCS7 填充)进行静态加密,同时元数据仍然可搜索
个人身份信息 (PII) 通过文本字段加密进行保护
访问令牌的有效期为 1 小时,以限制暴露
刷新令牌是长期有效的,但使用轮换:每次使用都会生成一个新的刷新令牌并使旧令牌无效
OAuth 令牌安全地存储在 Django 客户端的 PostgreSQL 数据库中
UUID 用法
系统中的所有标识符都使用 UUID v4 格式而不是连续整数,原因如下:
安全性:UUID 不会暴露系统信息或记录计数
可扩展性:无需数据库协调即可生成 UUID,从而实现分布式系统
不可猜测性:UUID 几乎不可能被猜测,从而防止枚举攻击
一致性:在整个系统中使用 UUID 简化了与其他服务的集成
API 中的所有 ID(user_id、memory_id、client_id 等)都必须是 UUID 格式。
OAuth最佳实践
在生产环境中,所有 OAuth 通信都必须使用 HTTPS
授权码是一次性的,并且有效期很短(最多 5 分钟)
所有客户端(甚至是机密客户端)都需要 PKCE 才能进行纵深防御
刷新令牌有效期较长,但可以被用户或管理员撤销
系统维护已撤销令牌的黑名单
文档
API 文档
MCP 服务器包含所有端点的 Swagger/OpenAPI 文档:
当服务器运行时,访问
/docs上的 Swagger UIOpenAPI 规范可在
/openapi.json中找到所有 API 端点均有完整记录,包括请求/响应模式和示例
附加文档文件
TESTING.md :应用程序测试的综合指南
描述所有实施的测试及其目的
在本地和 CI/CD 中运行测试的说明
记录测试覆盖范围并确定需要额外测试的区域
DEBUGGING.md :跟踪问题及其解决方案
记录尚未修复的已知错误
记录之前解决的 bug 及其解决方案
提供常见问题的故障排除指导
PLANNING.md :跟踪实施网站所需的任务细分
列出实施网站所需的任务和子任务
使用复选框记录任务是否已完成
部署
该项目包含用于本地开发的docker-compose.yml文件和用于部署到 Render 的render.yaml蓝图。相同的代码库既可以在本地 Docker 容器中运行,也可以部署到 Render 云服务中运行。
MCP 服务器部署
Docker 部署(推荐用于生产):
docker-compose up -dDocker Compose 配置包括:
容器间通信的网络配置
用于持久数据存储的卷挂载
.env 文件中的环境变量配置
端口映射(Django 客户端为 8000,MCP 服务器为 8001)
服务依赖关系的健康检查
渲染云部署:使用包含的
render.yaml蓝图部署到渲染。
执照
麻省理工学院