-
Notifications
You must be signed in to change notification settings - Fork 787
feat(mcp): 支持动态鉴权连接管理并优化运行态稳定性 #749
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
supreme0597
wants to merge
37
commits into
xerrors:release/0-6-3
Choose a base branch
from
supreme0597:codex/mcp-auth-orchestrator
base: release/0-6-3
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
37 commits
Select commit
Hold shift + click to select a range
c949f66
feat: 支持MCP动态鉴权连接与可视化配置
supreme0597 b1a44c9
fix: 修复MCP个人连接代理越权
supreme0597 815a570
fix: 修复 MCP 鉴权工具缓存隔离与 Redis 分级缓存
supreme0597 2bb296f
fix: 修复 MCP 鉴权代理缓存失效问题
supreme0597 d295102
fix: 统一 MCP 个人连接运行态用户标识
supreme0597 61bfd75
fix: 修复运行时 MCP 工具执行注册
supreme0597 f51bae0
refactor: 简化 current_user 工号使用
supreme0597 5736090
refactor: 同步 skills_middleware 内部用户标识为 work_id
supreme0597 125c68f
test: 修复 5 个预存测试失败
supreme0597 41e4371
refactor(mcp): save intermediate progress before pure architecture re…
supreme0597 7053d3b
feat(mcp): complete mcp gateway proxy streaming refactor and purge mc…
supreme0597 2ad8f77
feat(ui): update MCP scope id inputs to dropdown select
supreme0597 a943370
test: 修复重构引发的端到端及单元测试错误并调整路由命名防冲突
supreme0597 fc77ddc
fix(mcp-auth): 修复 MCP 鉴权与代理链路的三个关键隐患并完善规范
supreme0597 8065a16
style: 自动格式化 Python 代码以符合 Ruff 规范
supreme0597 5de697a
fix(mcp): 修复鉴权系统代码审计中发现的内存泄漏与并发缺陷
supreme0597 17cc449
refactor(mcp_auth): 深度重构 MCP Auth 模块,修复安全隐患与并发瓶颈
supreme0597 7002976
fix(web): 修复 MCP 连接配置中用户下拉框显示异常及重复的问题
supreme0597 89d4e8c
feat(web): 连接管理面板支持显示可读的认证方式名称
supreme0597 0e63bf4
style(web): MCP 信息详情页只读模式下隐藏冗长的认证配置 JSON,改用简略提示
supreme0597 81f08e9
feat(web): 支持只读模式渲染认证配置 (McpAuthConfigBuilder)
supreme0597 3ab2b32
fix(web): 修复 McpAuthConfigBuilder 组件中重复的 v-if 属性导致的编译报错
supreme0597 5063a8b
style(web): 优化只读模式下 McpAuthConfigBuilder 的样式,避免输入框和按钮看起来像禁用的灰色
supreme0597 7b03335
feat(backend): 支持在 MCP 认证模板中使用 context.work_id 获取工号,并区分 user_id
supreme0597 9655d4e
feat(web): MCP 认证配置快捷按钮增加对员工工号 (work_id) 的支持
supreme0597 f5c794e
feat(mcp): 优化无密钥 MCP 服务器测试和运行体验,如果 auth_config 没有配置 ${secret.xxx} 字段,…
supreme0597 115e85e
fix(backend): 补充 MCPAuthConfig 中的 get_secret_fields 实例方法,修复测试服务无秘钥跳过连…
supreme0597 9f1ca54
fix(mcp): fix missing work_id in proxy token payload
supreme0597 2bb97b8
feat(mcp-auth): 优化免密钥连接测试,修复长连接断开失效及 Demo 服务的响应冲突
supreme0597 bafaaac
docs(roadmap): 更新 0.6.3 开发路线图关于 MCP 多鉴权场景测试与修复的开发日志
supreme0597 22e2c7c
fix(mcp): 统一个人范围绑定连接 ID 语义,使用用户自增主键映射 scope_id 并通过 work_id 进行工号匹配,修复因…
supreme0597 35c4221
test(mcp): 增加个人、部门和全局范围连接的 E2E 接口集成测试
supreme0597 855c611
fix(mcp): 修复 MCP 服务器详情页测试按钮在已绑定连接时仍报错的问题
supreme0597 fabfabb
fix(mcp): 修复:no-secret 动态 MCP 代理入口允许无 connection;user scope connectio…
supreme0597 48be3bd
feat(mcp): 优化连接配置与管理体验
supreme0597 29576d9
Merge branch 'refs/heads/codex/mcp-auth-orchestrator' into release/0-6-3
supreme0597 73fa656
fix(mcp): 优化运行态加载与离线降噪
supreme0597 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -79,4 +79,7 @@ docs/vibe | |
|
|
||
| /models | ||
|
|
||
| .taskr/ | ||
| .taskr/ | ||
|
|
||
| .workbuddy | ||
| .worktrees/ | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -15,7 +15,8 @@ | |||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| from yuxi.agents.toolkits import get_all_tool_instances | ||||||||||||||||||||||||||||||||||||||||||
| from yuxi.repositories.skill_repository import SkillRepository | ||||||||||||||||||||||||||||||||||||||||||
| from yuxi.services.mcp_service import get_enabled_mcp_tools | ||||||||||||||||||||||||||||||||||||||||||
| from yuxi.services.mcp.tool_registry_service import get_enabled_mcp_tools | ||||||||||||||||||||||||||||||||||||||||||
| from yuxi.services.mcp_auth.orchestrator import AuthContext | ||||||||||||||||||||||||||||||||||||||||||
| from yuxi.services.skill_service import _normalize_string_list, is_valid_skill_slug | ||||||||||||||||||||||||||||||||||||||||||
| from yuxi.storage.postgres.manager import pg_manager | ||||||||||||||||||||||||||||||||||||||||||
| from yuxi.utils.logging_config import logger | ||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -79,6 +80,21 @@ async def get_dependency_map(db: AsyncSession | None = None) -> dict[str, SkillD | |||||||||||||||||||||||||||||||||||||||||
| return result | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| async def collect_context_mcp_names_for_preload(context, *, skills_context_name: str = "skills") -> list[str]: | ||||||||||||||||||||||||||||||||||||||||||
| """收集图构建阶段需要预注册的 MCP 名称。""" | ||||||||||||||||||||||||||||||||||||||||||
| names: list[str] = [] | ||||||||||||||||||||||||||||||||||||||||||
| names.extend(normalize_selected_skills(getattr(context, "mcps", None) or [])) | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| dependency_map = await get_dependency_map() | ||||||||||||||||||||||||||||||||||||||||||
| configured_skills = normalize_selected_skills(getattr(context, skills_context_name, None) or []) | ||||||||||||||||||||||||||||||||||||||||||
| for slug in expand_skill_closure(configured_skills, dependency_map): | ||||||||||||||||||||||||||||||||||||||||||
| node = dependency_map.get(slug) | ||||||||||||||||||||||||||||||||||||||||||
| if node: | ||||||||||||||||||||||||||||||||||||||||||
| names.extend(node.get("mcps", [])) | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| return normalize_selected_skills(names) | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| def normalize_selected_skills(selected_skills: list[str] | None) -> list[str]: | ||||||||||||||||||||||||||||||||||||||||||
| """规范化 skills 列表,去重并过滤无效值""" | ||||||||||||||||||||||||||||||||||||||||||
| return _normalize_string_list(selected_skills) | ||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -338,20 +354,42 @@ async def _get_mcp_tools_from_context( | |||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| # 去重 | ||||||||||||||||||||||||||||||||||||||||||
| unique_mcp_names = list(dict.fromkeys(all_mcp_names)) | ||||||||||||||||||||||||||||||||||||||||||
| loaded_mcp_tools: dict[str, int] = {} | ||||||||||||||||||||||||||||||||||||||||||
| unavailable_mcp_servers: list[str] = [] | ||||||||||||||||||||||||||||||||||||||||||
| failed_mcp_servers: list[str] = [] | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| async def load_mcp_tools(server_name: str) -> list: | ||||||||||||||||||||||||||||||||||||||||||
| """加载单个 MCP 服务器的工具""" | ||||||||||||||||||||||||||||||||||||||||||
| try: | ||||||||||||||||||||||||||||||||||||||||||
| mcp_tools = await get_enabled_mcp_tools(server_name) | ||||||||||||||||||||||||||||||||||||||||||
| user_id = getattr(context, "user_id", None) | ||||||||||||||||||||||||||||||||||||||||||
| work_id = getattr(context, "work_id", None) | ||||||||||||||||||||||||||||||||||||||||||
| mcp_tools = await get_enabled_mcp_tools( | ||||||||||||||||||||||||||||||||||||||||||
| server_name, | ||||||||||||||||||||||||||||||||||||||||||
| auth_context=AuthContext( | ||||||||||||||||||||||||||||||||||||||||||
| user_id=user_id, | ||||||||||||||||||||||||||||||||||||||||||
| department_id=getattr(context, "department_id", None), | ||||||||||||||||||||||||||||||||||||||||||
| work_id=work_id, | ||||||||||||||||||||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+364
to
+373
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 类似于运行时配置中间件,这里的
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||
| if not mcp_tools: | ||||||||||||||||||||||||||||||||||||||||||
| logger.warning(f"SkillsMiddleware: mcp dependency unavailable, skip: {server_name}") | ||||||||||||||||||||||||||||||||||||||||||
| unavailable_mcp_servers.append(server_name) | ||||||||||||||||||||||||||||||||||||||||||
| logger.debug(f"SkillsMiddleware: mcp dependency unavailable, skip: {server_name}") | ||||||||||||||||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||||||||||||||||
| loaded_mcp_tools[server_name] = len(mcp_tools) | ||||||||||||||||||||||||||||||||||||||||||
| return mcp_tools | ||||||||||||||||||||||||||||||||||||||||||
| except Exception as e: | ||||||||||||||||||||||||||||||||||||||||||
| failed_mcp_servers.append(server_name) | ||||||||||||||||||||||||||||||||||||||||||
| logger.warning(f"SkillsMiddleware: failed to load mcp dependency '{server_name}': {e}") | ||||||||||||||||||||||||||||||||||||||||||
| return [] | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| # 并行加载所有 MCP 工具 | ||||||||||||||||||||||||||||||||||||||||||
| results = await asyncio.gather(*[load_mcp_tools(name) for name in unique_mcp_names]) | ||||||||||||||||||||||||||||||||||||||||||
| if unique_mcp_names: | ||||||||||||||||||||||||||||||||||||||||||
| logger.info( | ||||||||||||||||||||||||||||||||||||||||||
| "SkillsMiddleware MCP dependency selection: " | ||||||||||||||||||||||||||||||||||||||||||
| f"selected={unique_mcp_names}, loaded={loaded_mcp_tools}, " | ||||||||||||||||||||||||||||||||||||||||||
| f"unavailable={unavailable_mcp_servers}, failed={failed_mcp_servers}" | ||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||
| selected_tools = [] | ||||||||||||||||||||||||||||||||||||||||||
| for tools in results: | ||||||||||||||||||||||||||||||||||||||||||
| selected_tools.extend(tools) | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
在运行时,
context可能会因为runtime_context未能成功解析而为None。直接对context调用getattr会触发AttributeError异常。建议在调用前增加None安全保护,以提高运行时的稳定性。