Skip to content

🛡️ MCP Scope 模型与权限边界 ​

代码:app/mcp/provider.py、app/mcp/tools.py;用户文档:docs/config/mcp.md「授权与权限」「安全建议」。

现状(read / write 两档) ​

scope工具说明
read(默认)get_logs、get_current_config配置读取时敏感字段已掩码(含 auth.password / auth.secret_key)
writeupdate_config可写配置,当前包含敏感字段(llm.api_key、notify-*.smtp_password、trakt.client_secret 等);[bangumi] 段为段级只读,不在此列

三层 scope 概念(勿混用) ​

层字段/常量作用落点
允许集_ALLOWED_SCOPES / valid_scopesDCR / CIMD 校验请求 scope 是否合法(越权 → invalid_scope)provider.py 构造参数 + 装配函数
发放默认值_default_scopes客户端未显式请求 scope 时实际签发的值(read)authorize / register_client / CIMD default_scope 三处
准入底线required_scopes(默认 ["read"])/mcp 传输层校验 access token 的 scope,不含 read 即 403 insufficient_scopeprovider.py 构造参数 + server.py 装配

硬性边界(与 scope 无关):

  • 登录通道本身禁写(auth.enabled / auth.secret_key / auth.password):这三项改完用户无法自行恢复,故无论 scope 如何都拒绝;
  • 段级只读:[bangumi](Web 无写入口,写入会被迁移为数据库账号);
  • MCP 工具集固定为 3 个,不存在任意 API / 命令执行;
  • 客户端请求的 scope 必须 ⊆ 其注册/声明的 scope(SDK validate_scope 校验,越权返回 invalid_scope);
  • 客户端不请求 scope 时默认只发 read(DCR 注册、CIMD default_scope、authorize 三处一致);
  • /mcp 传输层要求 read(required_scopes=["read"]):仅含 write 的 token 被 403 拒绝;工具级 _require_read_scope 为 defense-in-depth(传输层已先拦一道)。

未来可选:三档分级(暂缓) ​

档位scope授予能力
只读(默认)readget_logs + get_current_config
读写read write+ update_config,但拒绝敏感字段(is_sensitive_field 命中即拒)
全权read write admin+ 允许写敏感字段(登录通道三键仍禁)

更细粒度(logs:read / config:read / config:write / secrets:write)暂不考虑:OAuth scope 无继承语义、consent 页与客户端适配成本高。

代码索引 ​

  • _require_read_scope()(tools.py):read 校验;update_config 内 write 校验(均为 defense-in-depth)
  • valid_scopes:provider.py 两处(provider 默认参数、装配函数)
  • required_scopes:provider.py 构造参数(默认 ["read"])+ app/mcp/server.py::_create_provider 装配
  • consent 页展示 scopes(provider.py handle_consent)