RBAC MCP代理演示
一个小型全栈演示应用程序,展示了如何 AI代理可以使用基于角色的访问控制(RBAC)安全地调用工具.
该代理由LLM提供支持,并与 模型上下文协议(MCP) 工具,但 每个工具调用都是根据当前用户的权限授权的.
此存储库旨在:
- 学习项目
- 参考实现
- 权限感知代理的一个具体示例
______________________________________________________________________
这个应用程序做什么
- 允许用户以不同角色登录
- 运行一个AI代理,可以:
- 用户提示的原因 - 决定调用哪些工具 - 执行MCP工具 仅当用户被允许时
- 记录:
- 代理运行 - 工具调用 - 授权决定
- 支持:
- 权限请求+审批工作流 - 角色/权限分配和用户角色映射 - 授予“他人”权限 - 通知和事件流 - 使用服务器端转录的按键通话语音输入
简言之: 法学硕士可以自由思考,但不能自由行动。
LLM访问
此演示 不提供共享LLM密钥.
此演示使用单个后端级别 OPENAI_API_KEY 从 backend/.env.
这意味着:
- UI中没有每个用户的API密钥条目
- 后端直接调用OpenAI进行代理响应和转录
- 没有
OPENAI_API_KEY,/agent/run和/agent/transcribe将失败
密钥仍然通过环境配置外部化(不是在源代码中硬编码)。
______________________________________________________________________
这个应用程序是什么 *不*
这是 不:
- 一个生产就绪的RBAC框架
- 通用代理平台
- 一种安全的企业身份验证解决方案
- 完整的MCP展示
- 针对规模或性能进行了优化
它有意地小而明确。
______________________________________________________________________
为什么RBAC+MCP适用于代理?
现代代理演示通常假设:
“如果代理可以调用该工具,那么它应该调用。”
此应用程序演示了相反的情况:
- 工具独立于权限而存在
- 权限已解决 每用户
- 代理必须在运行时尊重这些权限
- 未经授权的工具调用被阻止和审核
这反映了 真正的内部工具 需要表现。
______________________________________________________________________
建筑(高级)
- 前端:用于登录、代理聊天、跟踪检查和管理员访问管理的React UI
- 后端:FastAPI API处理身份验证、RBAC、权限请求、通知和代理运行
- 代理运行时:
- LLM推理 - 工具选择 - MCP执行 - 权限检查
- MCP服务器:
- 身份验证工具 - Notes工具 - 任务工具 - 气象工具 - 报警工具 - 审批工具 - 权限请求工具 - 用户查找工具(用于在委托的“代表”操作中解析帐户所有者)
所有代理操作都会被记录下来以供检查。
技术栈
后端
- 快速API
- SQLAlchemy
- PostgreSQL
- JWT身份验证
- FastMCP
- OpenAI API
前端
- React(Vite)
- TypeScript
- Mantine用户界面
- 阿西奥斯
- React路由器
______________________________________________________________________
设置:环境变量
创建一个 .env 文件在 backend/ 目录包含:
# Required for startup
DATABASE_URL=postgresql+psycopg2://postgres:your-password@localhost:5432/rbac_mcp_app
# Required for /agent/run and /agent/transcribe
OPENAI_API_KEY=your-openai-api-key-here
# Optional
MCP_SERVER_URL=http://127.0.0.1:8001/mcp
LLM_MODEL=gpt-4.1-mini
REVIEWER_MODEL=gpt-4.1-mini
TRANSCRIPTION_MODEL=gpt-4o-mini-transcribe
# Optional runtime/config
APP_TIMEZONE=UTC
LOG_LEVEL=INFO
LOG_FORMAT=text
LOG_REDACT_FIELDS=password,token,secret,authorization,api_key,openai_api_key,jwt_secret
CORS_ALLOW_ORIGINS=http://localhost:5173,http://127.0.0.1:5173
LOGIN_RATE_LIMIT_ATTEMPTS=10
LOGIN_RATE_LIMIT_WINDOW_SECONDS=60
SSE_CONNECT_RATE_LIMIT_ATTEMPTS=30
SSE_CONNECT_RATE_LIMIT_WINDOW_SECONDS=60
# defaults to false in prod, true otherwise
SSE_ALLOW_QUERY_TOKEN=true
MCP_HOST=0.0.0.0
MCP_PORT=8001
AGENT_MAX_STEPS=8
JWT_SECRET=change-me-in-non-dev
JWT_EXP_HOURS=24
APP_ENV=dev
# Database pool + timeout tuning
DB_POOL_SIZE=10
DB_MAX_OVERFLOW=20
DB_POOL_TIMEOUT_SECONDS=30
DB_POOL_RECYCLE_SECONDS=1800
DB_CONNECT_TIMEOUT_SECONDS=10
DB_STATEMENT_TIMEOUT_MS=15000
DB_LOCK_TIMEOUT_MS=5000
DB_IDLE_TX_TIMEOUT_MS=30000前端可选变量(frontend/.env.local):
VITE_API_BASE_URL=http://localhost:8000后端还支持语音转文本 /agent/transcribe (在代理页面中由hold-to-talk使用),模型由控制 TRANSCRIPTION_MODEL.
其他已实现的后端功能包括:
- 会话生命周期API(
/agent/conversations,/agent/conversations/{id},/agent/conversations/approvals) - 用户时区API(
/timezones,/me/timezone) - 通知SSE流(
/api/events/stream) - 中返回了令牌使用情况摘要
/me以及对话列表响应 - 健康/就绪/ops端点(
/healthz,/readyz,/metrics/runtime)
注: DATABASE_URL API服务器和MCP服务器启动都需要。该应用程序目前需要PostgreSQL。
从获取API密钥 开放人工智能.
______________________________________________________________________
角色和权限(演示设置)
在第一次运行时,数据库中会播种演示用户:
| 用户 | 密码 | 角色 | 可以执行 |
|---|---|---|---|
| alice@example.com | 密码 | 基本 | 天气、笔记、通知、请求权限 |
| bob@example.com | 密码 | pro | 基本+任务、警报、“为他人”操作 |
| admin@example.com | admin | admin | 所有工具+批准请求+完全跟踪可见性 |
同一代理的行为因登录者而异。
注意:委派请求也可以由目标用户(帐户所有者)批准/拒绝,而不仅仅是管理员。
______________________________________________________________________
运行应用程序
后端API
cd backend
python -m venv venv
# Windows PowerShell:
./venv/Scripts/Activate.ps1
# macOS/Linux:
# source venv/bin/activate
pip install -r requirements.txt
uvicorn app.main:app --reload运行时间: http://localhost:8000
MCP服务器(独立终端)
cd backend
# Windows PowerShell:
./venv/Scripts/Activate.ps1
python -m mcp_app.server运行时间: http://localhost:8001/mcp
前端
cd frontend
npm install
npm run dev运行时间: http://localhost:5173
对于“保持通话”语音输入,请在浏览器中允许麦克风权限。
PostgreSQL设置(必需)
后端目前需要PostgreSQL通过 DATABASE_URL.
在本地安装PostgreSQL之后:
- 创建数据库(PowerShell示例):
psql -U postgres -h localhost -p 5432 -c "CREATE DATABASE rbac_mcp_app;"- 集
DATABASE_URL在backend/.env:
DATABASE_URL=postgresql+psycopg2://postgres:your-password@localhost:5432/rbac_mcp_app- 安装依赖项并运行迁移(推荐):
cd backend
./venv/Scripts/Activate.ps1
pip install -r requirements.txt
alembic upgrade head如果您跳过Alembic,API启动程序仍然从SQLAlchemy模型创建表(Base.metadata.create_all),但建议进行迁移以保持一致性。
- 启动/重新启动后端API+MCP服务器,以便
LISTEN/NOTIFY事件转发处于活动状态。
语音输入
- 代理页面支持在浏览器中进行通话录音。
- 音频发布到
POST /agent/transcribe并附加到提示中。 - 可选切换:转录后立即自动运行。
- 转录音频的当前后端有效负载限制为3 MB。
设计说明
- RBAC在LLM之外强制执行
- 代理人从不决定自己可以做什么
- MCP工具不知道用户身份
- 授权发生在编排层
- 审计日志和通知被视为一级数据
- SSE用于近乎实时的通知更新
实时信令(SSE、Postgres、Redis)
- 浏览器更新通过SSE交付(
/api/events/stream). - 通知始终持久地存储在数据库中,然后推送到连接的客户端。
- 使用PostgreSQL,该应用程序使用
LISTEN/NOTIFY用于交叉过程事件信令(API+MCP服务器)。 - 对于演示/小型部署(例如,事件量适中的几个到几百个并发SSE客户端)来说,这是一个很强的默认值。
- 如果部署增长(更高的扇出、更高的事件/秒、多个应用节点、不断上升的实时延迟),将信号转移到Redis发布/订阅(或另一个专用代理),同时保持数据库作为事实来源。
- SSE身份验证首选
Authorization: Bearer;查询令牌身份验证已弃用,由控制SSE_ALLOW_QUERY_TOKEN(在prod外部默认启用,在prod中默认禁用)。 - 大约5分钟后,每个SSE连接都会被有意回收(
SSE_MAX_STREAM_SECONDS=300),因此客户端应自动重新连接。
记录和补救
- 默认日志格式为文本。集
LOG_FORMAT=json对于结构化日志。 - 请求相关性通过以下方式传播
X-Request-ID(如果缺失,则生成)。 - 敏感值使用以下方式进行编辑
LOG_REDACT_FIELDS跨日志消息参数。 - 内置掩码还可以编辑承载令牌、类似JWT的值,并掩盖电子邮件的本地部分。
健康、准备和运行时指标
GET /healthz:活性和运行时生命周期状态。GET /readyz:准备就绪检查(退货503在关机期间或DB不可用时)。GET /metrics/runtime:启动/关闭计数器和最新关闭持续时间(需要身份验证+agent:trace:view_all).
违约注意事项
- 在开发中,
JWT_SECRET默认为dev-secret;为非开发环境设置明确的强值。 - 生产中(
APP_ENV=prod|production),启动失败,如果JWT_SECRET保留为默认值。
重试策略(操作指南)
- 数据库可靠性:已启用连接池预ping;保持语句/锁/空闲事务超时保守。
- API客户端(前端/集成):仅重试等幂请求(
GET,安全读取),使用带抖动的有界指数退避。 - 不要盲目地重试变异端点(
POST,PUT,DELETE)除非你实现幂等性密钥。 - 对待
429和瞬态5xx可重试;不要重试身份验证/权限拒绝(401,403)无需用户操作。 POST /login和GET /api/events/stream包含在内存速率限制中,并可能返回429随着Retry-After.- 限流器状态是针对每个进程的(单节点友好,不跨多个应用程序实例共享)。
这是给谁的
- 开发人员正在试验代理工具
- 任何对MCP+权限感兴趣的人
- 团队考虑安全的内部AI代理
- 人们厌倦了“无限制特工”演示
许可证
麻省理工学院
