fix(app): resolve MCP and HTTP schemas at runtime - #7661
Conversation
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b0b3ce663c
ℹ️ 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".
| const toolSetId = | ||
| (mcpToolsetVal && 'toolId' in mcpToolsetVal ? mcpToolsetVal.toolId : undefined) ?? | ||
| String(authApp?._id ?? ''); |
There was a problem hiding this comment.
Resolve the embedded toolset ID before hydrating children
When an Agent selects an ordinary workflow whose sole node is an MCP or HTTP toolset, authApp is the wrapper workflow and the persisted toolset snapshot has no toolId; this fallback therefore uses the wrapper app's _id. Both getMCPChildren and getHTTPToolList now reject non-toolset app types, so the wrapper expands to zero tools even though its inner node still has the actual toolset ID in pluginId. Use the inner toolset node's pluginId (or preserve it in formatPersonalAppNode) before hydrating either branch.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
🟡 Changes recommended
There are confirmed edge cases where legacy HTTP toolset data can fail runtime parsing (dropping baseUrl/customHeaders) and where Copy/Transition storageModules bypass sanitization, potentially reintroducing invalid persisted fields.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR revises how MCP and HTTP tool schemas are handled by stripping schema snapshots from workflow persistence and re-hydrating tool definitions/schemas from the current toolset Apps at runtime (workflow runtime + Agent runtime), addressing MongoDB $-prefixed field storage failures and reducing stale schema snapshots.
Changes:
- Introduces dedicated “storage boundary” Zod schemas for workflow nodes/tool configs to strip runtime schema fields during persistence/migration.
- Updates workflow dispatch + Agent tool expansion to authorize toolset Apps at runtime and load MCP/HTTP tool lists + schemas dynamically.
- Adjusts client preview/toolset UI paths to avoid returning executable schema fields and to support toolset references.
File summaries
| File | Description |
|---|---|
| projects/app/src/web/core/app/api/tool.ts | Safer access to HTTP toolset toolList for template/tool listing. |
| projects/app/src/pages/api/core/app/version/publish.ts | Persists sanitized workflow nodes via StoreWorkflowNodeItemTypeSchema. |
| projects/app/src/pages/api/core/app/create.ts | Sanitizes stored workflow nodes; encodes toolset schemas for toolset Apps. |
| projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/components/ToolSetList.tsx | Guards toolList access for MCP/HTTP toolset config unions. |
| projects/app/src/pageComponents/app/detail/Edit/HTTPTools/SchemaConfigModal.tsx | Handles HTTP toolset config unions when opening schema modal. |
| projects/app/src/pageComponents/app/detail/Edit/HTTPTools/ManualToolModal.tsx | Handles HTTP toolset config unions when reading/updating toolList. |
| projects/app/src/pageComponents/app/detail/Edit/HTTPTools/Edit.tsx | Handles HTTP toolset config unions for edit page state. |
| packages/service/test/core/workflow/dispatch/utils.test.ts | Updates rewriteRuntimeWorkFlow tests for tmbId + runtime toolset resolution. |
| packages/service/test/core/workflow/dispatch/tools/runTool.test.ts | Updates runtime auth + schema loading expectations for MCP/HTTP tools. |
| packages/service/test/core/workflow/dispatch/ai/agent/sub/tool/utils.test.ts | Updates Agent runtime tool expansion to load current toolset schemas. |
| packages/service/test/core/workflow/dispatch/ai/agent/sub/tool/index.test.ts | Updates Agent tool dispatch tests for toolset auth + no version loading. |
| packages/service/test/core/app/tool/utils/client.test.ts | Ensures client preview nodes omit runtime schema fields; legacy MCP hydration coverage. |
| packages/service/test/core/app/mcp.test.ts | Adds type guarding: non-MCP apps should not be treated as MCP toolsets. |
| packages/service/test/core/app/http.test.ts | Adds getHTTPToolList regression test for legacy customHeaders type. |
| packages/service/core/workflow/dispatch/utils/index.ts | Runtime toolset expansion now authorizes toolset Apps and loads tool lists/schemas dynamically. |
| packages/service/core/workflow/dispatch/index.ts | Passes tmbId into rewriteRuntimeWorkFlow for runtime authorization. |
| packages/service/core/workflow/dispatch/child/runTool.ts | Validates HTTP params using latest toolset schema; resolves MCP/HTTP configs from toolset Apps at runtime. |
| packages/service/core/workflow/dispatch/ai/agent/sub/tool/utils.ts | Agent runtime tool expansion now reads schemas from current toolset Apps; decodes toolset schema storage. |
| packages/service/core/workflow/dispatch/ai/agent/sub/tool/index.ts | Agent tool execution resolves toolset config/tool list from authorized toolset Apps at runtime. |
| packages/service/core/app/utils.ts | Tool node hydration uses toolId derived from toolConfig when pluginId is absent. |
| packages/service/core/app/tool/utils/client.ts | Client tool preview omits nested schema fields and reads MCP/HTTP tool definitions from toolset Apps. |
| packages/service/core/app/mcp.ts | getMCPChildren now type-gated to MCP toolset Apps and supports legacy child-app format. |
| packages/service/core/app/http.ts | Adds getHTTPToolList with type gating + schema-safe parsing. |
| packages/global/test/core/workflow/migration/schema.test.ts | Adds tests for storage boundary schema stripping and Agent selected-tools schema stripping. |
| packages/global/core/workflow/utils.ts | Uses NodeToolConfigStorageTypeSchema to strip schema fields when building toolset node IO. |
| packages/global/core/workflow/type/node.ts | Adds runtime vs storage toolset config schemas + StoreWorkflowNodeItemTypeSchema. |
| packages/global/core/workflow/migration/schema.ts | Migration parsing now uses storage tool-config schema for Agent selected tools. |
| packages/global/core/workflow/migration/legacy/workflow.ts | Safer legacy headerSecret parsing during migration. |
| packages/global/core/app/tool/mcpTool/utils.ts | Removes runtime mcpToolSet snapshot injection from MCP runtime node builder. |
Review details
- Files reviewed: 29/29 changed files
- Comments generated: 3
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| customHeaders: z.string().optional().meta({ | ||
| description: 'HTTP 工具集公共请求头 JSON 字符串' | ||
| }), |
| const storageNodes = | ||
| storageModules ?? | ||
| (type === AppTypeEnum.mcpToolSet | ||
| ? encodeMcpToolSetNodesForStorage(normalizedWorkflow.nodes) | ||
| : type === AppTypeEnum.httpToolSet | ||
| ? encodeHttpToolSetNodesForStorage(normalizedWorkflow.nodes) | ||
| : StoreWorkflowNodeItemTypeSchema.array().parse(normalizedWorkflow.nodes)); |
| const getAuthorizedToolSet = async (toolSetId: string) => { | ||
| try { | ||
| return ( | ||
| await authAppByTmbId({ | ||
| tmbId, | ||
| appId: toolSetId, | ||
| per: ReadPermissionVal | ||
| }) | ||
| ).app; | ||
| } catch { | ||
| return undefined; | ||
| } | ||
| }; |
|
✅ Admin Preview Image Ready! 🕒 Time: 2026-09-07 13:09:28 (UTC+8) |
Coverage Report
File CoverageNo changed files found. |
|
✅ Build and publish successful - Preview fastgpt Image: 🕒 Time: 2026-09-07 13:10:23 (UTC+8) |
bc5641e to
72a3aa5
Compare
72a3aa5 to
e7a15e8
Compare
需求背景
MCP/HTTP 的 JSON Schema 属于工具的执行定义。添加工作流节点时,不应把原始 Schema 一起放进节点对象,形成一份重复快照。
本 PR 收敛到“新增节点不携带执行 Schema”,不再扩展到存量数据清理、保存/发布过滤或 debug 响应过滤。运行时保留必要的服务端回源逻辑,确保节点不带 Schema 仍可正确执行。
本 PR 替代 #7634 的实现方案。
Fixes #7477
简化后的范围
保留
不纳入本 PR
因此,本 PR 不是“所有客户端响应都不含 Schema”:工具集编辑、独立调试及原有接口仍可使用完整定义;本次约束的是新添加进工作流的节点对象。
改动方案
1. 列表按已知父项类型分流
列表项已经包含 appType,前端保留该信息,根据 parentId 找到父项类型,不再为了判断类型额外查询详情。
2. 添加节点统一通过 getPreviewNode
三个标签点击添加仍统一调用:
GET /api/core/app/tool/getPreviewNode3. 保留新节点执行所需的回源能力
getHTTPToolRuntimeSchemas,兼容标量、缺失或空 requestSchema 后再校验。普通工作流和 Agent 使用相同逻辑,不回退到节点快照。4. 旧 MCP 只做兼容,不迁移
验证
pnpm --filter @fastgpt/app exec tsc --noEmit --incremental false。git diff --check通过;本次简化提交通过提交钩子。已知检查限制
PR 中 HTTPTools/Edit.tsx 仍存在修改前已有的 react-hooks/set-state-in-effect lint 错误,本次不扩大范围修改。此前完整提交曾因此跳过钩子;本次简化提交未涉及该错误位置。