Skip to content

feat(mcp): 支持用户个人凭证并优化配置交互 - #1153

Merged
xerrors merged 2 commits into
mainfrom
codex/mcp-personal-credentials
Nov 6, 2026
Merged

xerrors merged 2 commits into
mainfrom
codex/mcp-personal-credentials

Conversation

@xerrors

@xerrors xerrors commented Nov 6, 2026 •

Copy link
Copy Markdown
Owner

变更说明

同一个 MCP 服务可以由每名用户分别填写 Bearer Token 或 API Key,工具发现、连接测试与 Agent 调用都使用该用户的凭证。管理员继续维护服务地址和接入方式;个人凭证操作收进右侧按钮组,共享身份的填写位置与文案更明确。

  • 任务类型:feature
  • 目标:增加个人静态凭证,复用现有 OAuth 连接、加密、修订与并发机制;保留无认证、OAuth、共享请求头和内置委托。
  • 非目标:用户自建服务地址、通用凭证框架、Basic/查询参数认证、多字段凭证或供应商专用接入代码。
  • substantial:涉及用户身份、加密持久化、出站请求和业务 Schema 升级。

工程主张与 Owner

  • MCP 目录由超级管理员维护;保存、清除和个人测试只能操作当前登录用户的连接。API 路由拥有认证边界,MCP service/repository 拥有当前配置及连接事实。
  • 个人秘密加密写入现有连接表,保存成功以后才显示已配置;每次出站读取本人当前凭证,替换/清除/修订失效影响后续请求。事务、世代与行锁由 MCP connection service/repository 拥有。
  • 401 使对应世代的凭证失效,403 保留凭证并显示权限问题;旧响应不能撤销新凭证。个人运行时不使用共享身份兜底。
  • McpConnectionControls.vue 统一拥有预览与详情页的凭证交互;保存与测试分开,测试结果直接体现在主按钮,替换和清除放在菜单。
  • 决策记录:MCP 个人静态凭证与鉴权表单。配置说明与状态契约分别由 MCP 集成、MCP 机制 维护。

验证情况

CI 管理连接回归

  • 失败面:共享连接失败的既有字符串响应被替换;管理测试沿用旧依赖覆盖,实际把普通用户当作管理员。
  • 语义 Owner:MCP 管理路由的错误契约与模式权限;委托生命周期测试的当前登录身份。
  • 直接证据 / 命令:修改前本地复现管理 API 4 个失败和委托管理 2 个失败;修改后以下三文件一组 94 passed / 1 skipped,全部后端 unit 3656 passed / 127 skipped,Ruff check/format、工程契约及其 56 项 unit 通过。
  • 负向案例:普通用户被 403 拒绝且无 MCP 出站,超管可测试启用/停用服务;共享错误保留原字符串且不泄露远端响应;个人 403 保留具体提示与已保存密文。
  • 结果:Passed。对象存储用例因缺少专用隔离存储跳过,远端 service CI 同样跳过该用例。
  • 远端证据:修复提交 ba433c25e 的 CI 运行 已完成,20 个 CI job 全部成功,包含原先失败的 service、运行时契约和 CI required;CodeQL 同样通过。
docker compose exec -T api uv run --no-sync --group test pytest test/integration/api/test_mcp_router.py test/integration/services/test_mcp_delegation_lifecycle.py test/integration/services/test_mcp_oauth.py -q
docker compose exec -T api uv run --no-sync --group test pytest test/unit -m "not slow" -q

个人凭证与运行身份

  • 失败面:跨用户身份混用、旧工具继续使用旧凭证、401/403 错误处理、停用与清除后重新出现连接。
  • 语义 Owner:MCP connection service/repository、个人 HTTP auth、MCP service。
  • 直接证据 / 命令:真实 PostgreSQL/HTTP integration 三文件 86 passed;API + worker E2E 2 passed,独立 MCP 核对两种个人凭证,模型消费真实工具结果,最终输出回读 result Run。
  • 负向案例:两名用户返回不同身份;替换后的旧 401 不使新凭证失效;403 不清空凭证;清除/停用阻止后续调用;停用服务清除后再更新配置仍不显示。
  • 结果:Passed。

Schema 与已有 OAuth 兼容

  • 失败面:历史 OAuth 修订漂移、字段缺失、重复迁移或不支持的版本启动。
  • 语义 Owner:oauth_config.py、业务 Schema、显式 mcp_personal_credentials migration。
  • 直接证据 / 命令:上述 integration 包含 v1→v2 迁移、幂等和初始化;后端 unit 3656 passed / 127 skipped,宿主 config unit 209 passed;Ruff check/format/import 检查。
  • 负向案例:未知 Schema 拒绝、迁移重复执行保留已有数据、空新字段保持固定的旧 OAuth 修订值。
  • 结果:Passed;127 项容器内跳过不计入通过。

凭证表单与操作层级

  • 失败面:共享与个人身份误解、切换方式残留秘密、保存失败丢失草稿、操作等权并列、测试结果脱离操作、菜单 Escape 关闭整个弹窗。
  • 语义 Owner:MCP form、connection controls、card/detail 生产组件。
  • 直接证据 / 命令:工作区前端 unit 1044 passed,最终相关用例 21 passed;仅包含 MCP 的独立快照也通过完整前端 unit 1044 passed、lint、build 和 docs build;真实浏览器加载生产组件验证浅/深色、错误状态、1024px/768px 布局和弹窗基础高度。
  • 负向案例:失败保留输入;取消不删除旧凭证;保存不隐式测试;替换时隐藏旧测试结果;停用仍可清除;共享请求头直接可见;切换为个人方式不提交共享凭证;Escape 只收起菜单。
  • 结果:Passed。

文档与提交边界

  • 失败面:配置说明和实现不一致、迁移遗漏、无关任务进入 PR。
  • 语义 Owner:MCP 集成/机制/决策记录、精确提交文件集合。
  • 直接证据 / 命令:工程契约检查、检查器 56 tests、docs build、git diff --check;初始功能验证从 main 导出并仅叠加 MCP 的 32 个文件,独立执行前端及文档检查。
  • 负向案例:保留工作区原有非 MCP 暂存与未提交修改;PR 仅包含 MCP 的 33 个文件,不包含登录页、项目目录、Skill 图标等任务。
  • 结果:Passed。

实际执行的主要命令:

python3 scripts/ci/verify_engineering_contracts.py
python3 -m unittest scripts.ci.test_verify_engineering_contracts
docker compose exec api uv run --no-sync --group test pytest test/unit -m "not slow" -q
docker compose exec api uv run --no-sync --group test pytest test/integration/services/test_mcp_oauth.py test/integration/services/test_schema_migration_version.py test/integration/services/test_app_initialization.py -q
docker compose exec api uv run --no-sync --group test pytest test/e2e/test_mcp_personal_credentials.py -q
uv run --project backend --no-sync --group test pytest backend/test/unit/config -q
(cd frontend && pnpm run lint:check)
(cd frontend && pnpm run test:unit)
(cd frontend && pnpm run build)
(cd docs && pnpm run build)
playwright-cli -s=mcp-auth-ux --raw run-code --filename=frontend/test/browser/mcpPersonalCredentials.js
git diff --check

前端命令在宿主环境执行;浏览器命令在已打开 5173 验证页的 CLI session 中执行。独立快照复用相同依赖,关闭 pnpm 的自动安装检查,不改变依赖或锁文件。

简化 / 删除验收

不涉及独立能力删除。静态凭证复用既有连接表与运行时;预览和详情共用一个凭证交互组件。

独立语义 Review

CI 修复由全新 Grok 上下文审查三处增量、原有管理 API oracle、委托身份及个人 403 断言;结论为“可提交,必要项无”,未要求增加抽象或防御分支。Reviewer 未亲自重跑测试,本次修复快照未包含认证模式常量及通用错误解释器全文;实际回归结果独立记录在上方。

本机 Grok CLI 以全新上下文审查了原始需求、完整 MCP staged diff、32 个最终文件、适用规范及新增测试断言,重点检查必要性、现有能力复用、冗余逻辑和心智负担。结论:可提交;需先修复项:无;可选改进:无。本轮未增加抽象、配置或防御分支。

Reviewer 未亲自运行测试,未阅读快照外的通用 base.js、全局异常格式及初始化器全文;审查结论与实际测试证据分别记录。

未验证范围与风险

  • 其他第三方 MCP 供应商:Not run。腾讯会议真实服务已发现 33 项工具并完成预约后回读;凭证、账号及会议内容不进入仓库。
  • worker E2E 直接登记一次性 HTTP fixture,验证跨进程凭证和最终结果;HTTPS 配置及来源拒绝由 integration 独立验证。
  • 清除影响后续出站检查,已经发送的远端请求不会回滚。
  • 现有部署必须显式迁移并重启 API/worker。API 启动不自动变更 Schema。

事故反馈

未达到高影响逃逸事故门槛;相关失败场景作为功能负向用例覆盖。

界面变更

凭证区的主要操作为右侧“测试连接”按钮,成功后显示“连接正常”;替换/清除放在相邻菜单。管理员按凭证提供者选择接入方式,共享请求头直接填写;预览弹窗保留基础高度。浅色、深色和失败状态截图已在交付对话提供,仓库保留可复现的生产组件浏览器验证脚本与 fixture,不提交运行截图或真实凭证。

关联事项

无。

补充说明

business Schema 由 1 升到 2,只新增可空 api_key_header;运行一次:

docker compose exec api uv run --no-sync python -m yuxi.migrations.mcp_personal_credentials
docker compose restart api worker

升级幂等,保留已有连接及共享配置。共享身份不会自动复制为个人凭证;管理员按服务自行选择接入方式。

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 6, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-06T12:19:43.209608Z aa91016 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: aa91016b51

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +45 to 46
request.headers[header] = value
response = yield request

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Prevent personal API keys from following cross-origin redirects

When an API-key MCP endpoint returns a redirect to another origin, the personal secret can be forwarded to that destination. personal_mcp_tools uses the SDK's default HTTP client, which follows redirects, but HTTPX processes those redirects inside a single auth-flow invocation, so the origin check above does not run again. HTTPX strips Authorization on cross-origin redirects but preserves custom headers such as X-API-Key. I reproduced this with the actual PersonalMCPAuth class and HTTPX MockTransport: both the configured endpoint and a second origin received the personal key after a 307 response. Disable redirects for personal connections or enforce the origin boundary on every redirected request before sending credentials.

Useful? React with 👍 / 👎.

@xerrors
xerrors merged commit 9bf9a78 into main Nov 6, 2026
24 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant