Skip to content

feat(agents): 支持自定义 MCP 服务器配置 - #218

Open
pxguan wants to merge 8 commits into
mainfrom
codex/issue-217-custom-mcp-server
Open

feat(agents): 支持自定义 MCP 服务器配置#218
pxguan wants to merge 8 commits into
mainfrom
codex/issue-217-custom-mcp-server

Conversation

@pxguan

@pxguan pxguan commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator

变更摘要

  • 保留 CMA 官方 Add MCP server Popover 与 Directory 搜索交互,并增加 Directory / 自定义 MCP 双页签
  • Create 与 Edit Agent 共用 MCP Picker;自定义 MCP 支持名称与远程 HTTP/HTTPS URL 校验
  • 原子增删 mcp_servers 与同名 mcp_toolset,默认权限为 always_ask
  • 移除 Rendered 模式新增 Custom Tool 的入口,保留已有 Custom Tool 的编辑、删除与 Raw 往返
  • 修复 Directory 搜索、同名自定义 MCP 识别、URL 运行时兼容及 Escape 焦点恢复
  • 更新 Create/Edit Agent 设计文档和中英文文案

测试

  • pre-commit hook(本次暂存文件)全部通过
  • ./scripts/pre-commit.sh run check-added-large-files --all-files
  • cd web && bun test(419 pass)
  • cd web && bun run build
  • cd web && bun run format:check
  • TypeScript 命名、重复代码和复杂度检查
  • Chrome 验收 Create/Edit、Directory 搜索、自定义 MCP、Escape、暗色主题与窄屏布局

已知问题

  • ./scripts/pre-commit.sh run --all-files 仍受已跟踪的 web/node_modules/flatted/golang/pkg/flatted/flatted.go 两条既有 govet inline 告警影响;与本次前端改动无关,近期 PR Complete Yourbatis migration and remove sqlx #209 已记录同一问题

依赖

Closes #217

Summary by CodeRabbit

  • New Features

    • Added searchable MCP directory selection with custom server support.
    • Added validation for MCP names, URLs, duplicates, and server limits.
    • Improved agent creation and editing for MCP servers, skills, permissions, and existing custom tools.
    • Added clearer rendered/raw configuration handling for unsupported or duplicate toolsets.
    • Added improved MCP server icons with reliable favicon fallbacks.
  • Bug Fixes

    • Preserved custom tool schemas and configuration during editing and serialization.
    • Improved loading, error, retry, and reset behavior across agent configuration pickers.

@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@pxguan, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 34 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: dcfc77c8-2766-4557-9d70-b24f369246cf

📥 Commits

Reviewing files that changed from the base of the PR and between aee67f2 and 8fbbb1c.

📒 Files selected for processing (1)
  • docs/design/fe/agent/create-agent-editor.md
📝 Walkthrough

Walkthrough

The Create/Edit Agent editor now supports Directory and custom MCP selection, validates MCP inputs and duplicate toolsets, preserves existing custom tools, updates Directory icon fallbacks, and expands localized integration and test coverage.

Changes

Agent editor

Layer / File(s) Summary
MCP draft contracts and validation
docs/design/fe/agent/*.md, web/src/features/managed-agents/agents/create-dialog-model.ts, web/src/features/managed-agents/agents/create-dialog-model.test.ts, web/src/features/managed-agents/agents/use-agent-edit-draft.test.ts
MCP inputs now use structured validation. Server and matching toolset updates are atomic. Unsafe URLs, duplicate names, capacity limits, duplicate toolsets, and unsupported Rendered configurations are rejected.
MCP picker and rendered tool editing
web/src/features/managed-agents/agents/create-dialog-picker.tsx, web/src/features/managed-agents/agents/create-dialog-mcp-picker.tsx, web/src/features/managed-agents/agents/create-dialog-tools-editor.tsx, web/src/shared/i18n/messages/*.json
Rendered tools now use reusable picker controls with Directory and Custom MCP tabs. Custom schemas preserve editable text and publish parsed objects when valid.
Directory icon fallback behavior
web/src/features/managed-agents/agents/tools/RemoteServerIcon.tsx, web/src/features/managed-agents/agents/tools/RemoteServerIcon.test.tsx, web/src/features/managed-agents/agents/tools/AgentToolsSection.tsx
MCP cards use Directory icon metadata, then Directory-origin and public favicon candidates, before the default server icon.
Create/Edit integration and test infrastructure
web/src/features/managed-agents/ManagedAgentsPage.agents.suite.tsx, web/src/features/managed-agents/ManagedAgentsPage.test-utils.tsx, web/src/features/managed-agents/ManagedAgentsPage.test-utils.test.tsx
Integration tests cover MCP failures, validation, tab state, serialization, custom-tool editing, icon fallbacks, and adding MCPs during editing. Test rendering now seeds models for the selected workspace query key.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant AgentEditor
  participant CreateDialogMcpPicker
  participant DraftModel
  participant AgentAPI
  AgentEditor->>CreateDialogMcpPicker: open Directory or Custom MCP picker
  CreateDialogMcpPicker->>DraftModel: validate MCP name and URL
  DraftModel-->>CreateDialogMcpPicker: return server and matching toolset
  CreateDialogMcpPicker-->>AgentEditor: update rendered draft
  AgentEditor->>AgentAPI: save serialized MCP configuration
Loading

Possibly related PRs

Suggested reviewers: cursor

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 标题准确概括了本次 PR 的主要变更:支持 Agent 配置自定义 MCP 服务器。
Linked Issues check ✅ Passed 变更覆盖 Issue [#217] 的自定义 MCP、双页签、校验、原子增删、Custom Tool 兼容及相关测试要求。
Out of Scope Changes check ✅ Passed 所有代码、测试、文档和文案变更均服务于 Issue [#217] 的功能目标,未发现明显无关改动。
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/issue-217-custom-mcp-server

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@pxguan
pxguan marked this pull request as ready for review August 7, 2026 06:12
@pxguan

pxguan commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator Author
image

@pxguan pxguan self-assigned this Aug 7, 2026
@pxguan pxguan added the ready-for-agent Specification confirmed and ready for implementation label Aug 7, 2026
@pxguan
pxguan changed the base branch from codex/issue-214-create-agent-web-ui to main August 7, 2026 06:17
@pxguan
pxguan marked this pull request as draft August 7, 2026 06:18
@pxguan
pxguan marked this pull request as ready for review August 7, 2026 06:18
@pxguan

pxguan commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

1 similar comment
@pxguan

pxguan commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Something went wrong. Try again later by commenting “@codex review”.

Unknown error
ℹ️ 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".

@jh0904

jh0904 commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

@codex review

@coderabbitai coderabbitai 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.

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
web/src/features/managed-agents/agentConfig.ts (1)

402-413: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Model-generated multiagent reaches a throwing parser without validation. quickstartBuildAgentConfigInput casts an arbitrary record to AgentMultiagentInput. That value flows into replaceDraft, which calls normalizeCreateAgentDraft. normalizeCreateAgentDraft uses createAgentDraftSchema.parse and throws a ZodError. The user then sees a raw Zod message in the create dialog.

  • web/src/features/managed-agents/agentConfig.ts#L402-L413: validate the record with multiagentSchema before returning it, or omit the field when it does not match.
  • web/src/features/managed-agents/agents/create-dialog-model.ts#L192-L206: add a safeParse-based variant that returns a typed failure, so callers that accept untrusted configuration do not depend on exceptions.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/src/features/managed-agents/agentConfig.ts` around lines 402 - 413,
Validate the derived multiagent record with multiagentSchema before returning it
from quickstartBuildAgentConfigInput, omitting it when validation fails instead
of casting arbitrary data. In
web/src/features/managed-agents/agents/create-dialog-model.ts lines 192-206, add
a safeParse-based normalization variant that returns a typed failure for
untrusted configuration, and update the relevant callers to use it rather than
relying on thrown ZodError exceptions.
🧹 Nitpick comments (10)
web/src/features/managed-agents/agents/use-create-agent-draft.ts (1)

7-10: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

Normalize the initial draft once.

Line 7 and Line 10 each call normalizeCreateAgentDraft(initialDraft). Each call runs a full schema parse and a deep clone. Compute the value once and reuse it.

♻️ Proposed refactor
-  const [draft, setDraftState] = useState(() => normalizeCreateAgentDraft(initialDraft));
+  const [draft, setDraftState] = useState(() => normalizeCreateAgentDraft(initialDraft));
   const [view, setViewState] = useState<CreateAgentView>('rendered');
   const [format, setFormatState] = useState<CodeFormat>('YAML');
-  const [rawText, setRawText] = useState(() => createAgentConfigText(normalizeCreateAgentDraft(initialDraft), 'YAML'));
+  const [rawText, setRawText] = useState(() => createAgentConfigText(draft, 'YAML'));

Note: draft is declared before rawText, so the lazy initializer can read it.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/src/features/managed-agents/agents/use-create-agent-draft.ts` around
lines 7 - 10, Normalize initialDraft once in the useCreateAgentDraft
initialization flow, store the result via the existing draft state initializer,
and reuse draft when initializing rawText instead of calling
normalizeCreateAgentDraft again. Preserve the current YAML format and state
behavior.
web/src/features/managed-agents/agents/create-dialog-model.ts (2)

192-206: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

normalizeCreateAgentDraft throws on invalid input.

Line 193 calls createAgentDraftSchema.parse, which throws a ZodError. replaceDraft in use-create-agent-draft.ts (Line 29) calls it with model-generated configuration from generateCreateAgentConfig. That value is not validated before the call. The generate path catches the error, but the user then sees a raw Zod message instead of a configuration error. Consider a safeParse variant that returns a typed failure, or validate before replaceDraft.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/src/features/managed-agents/agents/create-dialog-model.ts` around lines
192 - 206, Update normalizeCreateAgentDraft and the
generateCreateAgentConfig-to-replaceDraft flow so invalid generated
configuration is handled as a typed validation failure instead of allowing
createAgentDraftSchema.parse to throw a raw ZodError. Prefer safeParse or
equivalent validation, and ensure replaceDraft receives only validated data
while preserving the existing configuration-error handling.

135-135: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Replace the deprecated .passthrough() call.

This file depends on Zod 4 (web/package.json: zod: ^4.4.3 and web/bun.lock: zod@4.4.3). In Zod 4, use z.looseObject() instead of .passthrough() to avoid the deprecation path.

♻️ Proposed refactor
-    input_schema: z.object({ type: z.literal('object') }).passthrough(),
+    input_schema: z.looseObject({ type: z.literal('object') }),
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/src/features/managed-agents/agents/create-dialog-model.ts` at line 135,
Update the input_schema definition to replace the deprecated
z.object(...).passthrough() usage with the Zod 4 z.looseObject() API, preserving
the existing object type constraint and acceptance of additional fields.
web/src/features/managed-agents/agents/use-agent-edit-draft.ts (2)

33-40: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

renderedAgentEditDraft runs on every render.

Line 33 calls renderedAgentEditDraft(initialConfig) in the component body. The result is consumed only by the useState initializers on Lines 35-37, which ignore it after mount. Each subsequent render still performs a full schema parse, a normalization, and a deep clone. Wrap the call in useMemo, or move it into a single lazy initializer.

♻️ Proposed refactor
-  const initialRendered = renderedAgentEditDraft(initialConfig);
+  const initialRendered = useMemo(() => renderedAgentEditDraft(initialConfig), [initialConfig]);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/src/features/managed-agents/agents/use-agent-edit-draft.ts` around lines
33 - 40, Memoize the initial rendered draft computation around
renderedAgentEditDraft(initialConfig) so it is not re-run on every render.
Preserve the existing initial state behavior for renderedDraft, renderedError,
and view, and ensure the memoization dependencies reflect when initialConfig
changes.

99-114: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

selectFormat and validateRawText duplicate use-create-agent-draft.ts.

These two callbacks, plus the issue-formatting logic at Lines 46-51, are near-identical to use-create-agent-draft.ts Lines 71-86 and Lines 15-20. Only the codec function differs. The repository sets a 1.1% duplicate-code budget for frontend production code. Extract the shared parts into a helper that takes the codec functions.

As per coding guidelines: "修改生产 TypeScript/TSX 后运行 bun run lint:duplicates;前端生产代码重复率上限为 1.1%,不得通过扩大 ignore、提高阈值或机械改名绕过检查。"

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/src/features/managed-agents/agents/use-agent-edit-draft.ts` around lines
99 - 114, Extract the duplicated format-selection, raw-text validation, and
issue-formatting logic shared by useAgentEditDraft and useCreateAgentDraft into
a reusable helper that accepts the respective codec functions, then update both
hooks to use it while preserving their current behavior. Run bun run
lint:duplicates and resolve any reported duplication without changing ignore
settings or thresholds.

Source: Coding guidelines

web/src/features/managed-agents/agents/create-dialog-model.test.ts (1)

110-127: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Add raw-path coverage for the URL rules.

Lines 121-126 verify that addMcpServer rejects credentials and fragments. No test verifies createAgentDraftSchema for the same URLs. The Raw editor validates only through the schema, so this gap hides the mismatch reported on create-dialog-model.ts Line 90. Add the same URLs to the invalidDrafts list at Line 232 after the schema is fixed.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/src/features/managed-agents/agents/create-dialog-model.test.ts` around
lines 110 - 127, The existing raw-editor draft validation does not cover
rejecting MCP URLs with credentials or fragments. Update createAgentDraftSchema
to apply the same invalid-URL rules, then add drafts using
https://user:secret@example.com/mcp and https://example.com/mcp#tools to the
invalidDrafts list, preserving the expected schema rejection behavior.
web/src/features/managed-agents/agents/create-dialog-api.ts (1)

31-62: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Add a maximum page count to the skills pagination loop.

listCreateAgentSkills only stops when the API omits next_page or repeats a cursor. If the backend returns a long chain of unique cursors, this loop issues unbounded sequential requests on the create-dialog path. searchAgentsByName in web/src/features/managed-agents/api.ts already caps pages with agentSearchMaxPages. Apply the same bound here.

♻️ Proposed page cap
+const skillsMaxPages = 50;
+
 export async function listCreateAgentSkills(workspaceId: string): Promise<AgentSkillOption[]> {
   const rows: AgentSkillOption[] = [];
   let page: string | undefined;
   const seenPages = new Set<string>();
-  while (true) {
+  for (let pageCount = 0; pageCount < skillsMaxPages; pageCount += 1) {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/src/features/managed-agents/agents/create-dialog-api.ts` around lines 31
- 62, Update listCreateAgentSkills to enforce the existing
agentSearchMaxPages-style maximum page bound during skills pagination. Track the
number of fetched pages and stop or throw once the configured cap is reached,
while preserving termination on missing next_page and repeated cursors.
web/src/features/managed-agents/agents/create-dialog-rendered.tsx (1)

69-76: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Replace the manual focus listener with TanStack Query focus refetching.

This effect refetches the subagents and skills queries on every window focus. It ignores staleTime and runs even when the picker is closed, so it issues extra requests on each tab switch. TanStack Query already refetches on window focus through its focus manager. Set refetchOnWindowFocus on the two queries instead.

♻️ Proposed refactor
-  const refetchAgents = agentsQuery.refetch;
-  const refetchSkills = skillsQuery.refetch;
-
-  useEffect(() => {
-    const refresh = () => {
-      void refetchAgents();
-      void refetchSkills();
-    };
-    window.addEventListener('focus', refresh);
-    return () => window.removeEventListener('focus', refresh);
-  }, [refetchAgents, refetchSkills]);
-

Add the option to both queries:

const agentsQuery = useQuery({
  queryKey: ['agent-config', 'subagents', workspaceId, debouncedAgentSearch.trim()],
  queryFn: () => searchCreateAgentSubagents(workspaceId, debouncedAgentSearch),
  retry: false,
  refetchOnWindowFocus: true,
});
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/src/features/managed-agents/agents/create-dialog-rendered.tsx` around
lines 69 - 76, Remove the manual window focus useEffect and its refresh
listener, then configure both the agents and skills useQuery calls with
refetchOnWindowFocus: true. Preserve their existing query keys, query functions,
and other options.
web/src/features/managed-agents/agents/tools/RemoteServerIcon.test.tsx (1)

25-46: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Add cases for rejected and absent URLs.

The suite covers the fallback chain well. Two branches of remoteServerIconCandidates stay uncovered:

  • No iconUrl and no serverUrl. The component must render the Server icon and no img.
  • A non-HTTP value, for example file:///icon.png. parseHTTPURL must reject it, so no img is rendered.

These cases protect the URL protocol guard against future edits.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/src/features/managed-agents/agents/tools/RemoteServerIcon.test.tsx`
around lines 25 - 46, Add tests for RemoteServerIcon covering both missing
iconUrl/serverUrl and a non-HTTP serverUrl such as file:///icon.png. Verify each
case renders no img and displays the Server icon, exercising the rejected and
absent branches of remoteServerIconCandidates and parseHTTPURL.
web/src/features/managed-agents/agents/create-dialog-picker.tsx (1)

24-67: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Reuse CreateDialogPickerListProps in CreateDialogPicker.

The inline props of CreateDialogPicker repeat all ten members of CreateDialogPickerListProps. Extend the exported type instead. This keeps both components in sync when the list contract changes.

♻️ Proposed refactor
-}: {
-  label: string;
-  placeholder: string;
-  searchPlaceholder: string;
-  emptyLabel: string;
-  options: CreateDialogPickerOption[];
-  selectedIds: string[];
-  loading?: boolean;
-  error?: boolean;
-  onRetry?: () => void;
-  onToggle: (id: string) => void;
-  searchValue?: string;
-  onSearchChange?: (value: string) => void;
-  createLabel?: string;
-  onCreate?: () => void;
-}) {
+}: CreateDialogPickerListProps & {
+  label: string;
+  placeholder: string;
+  createLabel?: string;
+  onCreate?: () => void;
+}) {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/src/features/managed-agents/agents/create-dialog-picker.tsx` around lines
24 - 67, Update the CreateDialogPicker props declaration to extend or reuse the
exported CreateDialogPickerListProps type instead of redeclaring its shared
members inline. Keep only the picker-specific createLabel and onCreate fields in
the component’s additional props so both component contracts stay synchronized.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@web/src/features/managed-agents/agents/create-dialog-model.ts`:
- Around line 229-248: Update toggleSkill to preserve the original draft.skills
entries when adding or removing a skill, rather than rebuilding them from
selectedSkillReferences and introducing default versions. Use
selectedSkillReferences only to determine whether the toggled skill exists, then
filter the original entries by skill ID when removing or append the new skill
reference when adding.
- Around line 90-96: The MCP server schema accepts URLs that the rendered-picker
validation rejects; update mcpServerSchema to validate the URL with isHTTPURL
via a z.string().max(2048).refine(...) rule, preserving the required HTTP/HTTPS,
no-credentials, and no-fragment behavior. In
web/src/features/managed-agents/agents/create-dialog-model.ts lines 90-96, make
this schema change; in
web/src/features/managed-agents/agents/create-dialog-model.test.ts lines
110-127, add ftp://internal.example/mcp, https://user:secret@example.com/mcp,
and https://example.com/mcp#tools to invalidDrafts so the raw schema path is
covered.

In `@web/src/features/managed-agents/agents/create-dialog-tools-editor.tsx`:
- Around line 368-381: Update the input schema editor around schemaText and its
Textarea onChange handler to maintain the raw user-entered text in local state,
rather than deriving and re-stringifying it from tool.input_schema on every
render. Publish parsed JSON when valid and the raw text when invalid, while
preserving the visible text exactly as entered so typing and pasting do not
reformat or move the caret.

In `@web/src/features/managed-agents/agents/tools/RemoteServerIcon.tsx`:
- Around line 50-59: Update remoteServerIconCandidates to remove both
publicFaviconCandidate calls, preventing user-configured MCP server hostnames
from being sent to Google. Preserve the remaining directory and origin favicon
candidates, allowing the existing Server icon fallback to handle cases where
they are unavailable.

In `@web/src/features/managed-agents/ManagedAgentsPage.test-utils.tsx`:
- Around line 70-76: The model fixture is seeded under the hard-coded "default"
workspace key while CreateAgentDialog reads the workspace-specific query key.
Update renderManagedAgentsPage and its test utilities to seed
MockAgentsApiOptions.models under the provided workspaceId, or configure
queries.staleTime to 0 so the API fixture controls the result; preserve existing
defaults when no custom models are supplied.

---

Outside diff comments:
In `@web/src/features/managed-agents/agentConfig.ts`:
- Around line 402-413: Validate the derived multiagent record with
multiagentSchema before returning it from quickstartBuildAgentConfigInput,
omitting it when validation fails instead of casting arbitrary data. In
web/src/features/managed-agents/agents/create-dialog-model.ts lines 192-206, add
a safeParse-based normalization variant that returns a typed failure for
untrusted configuration, and update the relevant callers to use it rather than
relying on thrown ZodError exceptions.

---

Nitpick comments:
In `@web/src/features/managed-agents/agents/create-dialog-api.ts`:
- Around line 31-62: Update listCreateAgentSkills to enforce the existing
agentSearchMaxPages-style maximum page bound during skills pagination. Track the
number of fetched pages and stop or throw once the configured cap is reached,
while preserving termination on missing next_page and repeated cursors.

In `@web/src/features/managed-agents/agents/create-dialog-model.test.ts`:
- Around line 110-127: The existing raw-editor draft validation does not cover
rejecting MCP URLs with credentials or fragments. Update createAgentDraftSchema
to apply the same invalid-URL rules, then add drafts using
https://user:secret@example.com/mcp and https://example.com/mcp#tools to the
invalidDrafts list, preserving the expected schema rejection behavior.

In `@web/src/features/managed-agents/agents/create-dialog-model.ts`:
- Around line 192-206: Update normalizeCreateAgentDraft and the
generateCreateAgentConfig-to-replaceDraft flow so invalid generated
configuration is handled as a typed validation failure instead of allowing
createAgentDraftSchema.parse to throw a raw ZodError. Prefer safeParse or
equivalent validation, and ensure replaceDraft receives only validated data
while preserving the existing configuration-error handling.
- Line 135: Update the input_schema definition to replace the deprecated
z.object(...).passthrough() usage with the Zod 4 z.looseObject() API, preserving
the existing object type constraint and acceptance of additional fields.

In `@web/src/features/managed-agents/agents/create-dialog-picker.tsx`:
- Around line 24-67: Update the CreateDialogPicker props declaration to extend
or reuse the exported CreateDialogPickerListProps type instead of redeclaring
its shared members inline. Keep only the picker-specific createLabel and
onCreate fields in the component’s additional props so both component contracts
stay synchronized.

In `@web/src/features/managed-agents/agents/create-dialog-rendered.tsx`:
- Around line 69-76: Remove the manual window focus useEffect and its refresh
listener, then configure both the agents and skills useQuery calls with
refetchOnWindowFocus: true. Preserve their existing query keys, query functions,
and other options.

In `@web/src/features/managed-agents/agents/tools/RemoteServerIcon.test.tsx`:
- Around line 25-46: Add tests for RemoteServerIcon covering both missing
iconUrl/serverUrl and a non-HTTP serverUrl such as file:///icon.png. Verify each
case renders no img and displays the Server icon, exercising the rejected and
absent branches of remoteServerIconCandidates and parseHTTPURL.

In `@web/src/features/managed-agents/agents/use-agent-edit-draft.ts`:
- Around line 33-40: Memoize the initial rendered draft computation around
renderedAgentEditDraft(initialConfig) so it is not re-run on every render.
Preserve the existing initial state behavior for renderedDraft, renderedError,
and view, and ensure the memoization dependencies reflect when initialConfig
changes.
- Around line 99-114: Extract the duplicated format-selection, raw-text
validation, and issue-formatting logic shared by useAgentEditDraft and
useCreateAgentDraft into a reusable helper that accepts the respective codec
functions, then update both hooks to use it while preserving their current
behavior. Run bun run lint:duplicates and resolve any reported duplication
without changing ignore settings or thresholds.

In `@web/src/features/managed-agents/agents/use-create-agent-draft.ts`:
- Around line 7-10: Normalize initialDraft once in the useCreateAgentDraft
initialization flow, store the result via the existing draft state initializer,
and reuse draft when initializing rawText instead of calling
normalizeCreateAgentDraft again. Preserve the current YAML format and state
behavior.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 4da66c85-fe68-4896-badf-015076e21e7a

📥 Commits

Reviewing files that changed from the base of the PR and between b13bd8b and 88e4c7e.

📒 Files selected for processing (29)
  • docs/design/fe/agent/create-agent-editor.md
  • docs/design/fe/agent/edit-agent-editor.md
  • web/src/features/managed-agents/ManagedAgentsPage.agents.suite.tsx
  • web/src/features/managed-agents/ManagedAgentsPage.quickstart.suite.tsx
  • web/src/features/managed-agents/ManagedAgentsPage.test-utils.tsx
  • web/src/features/managed-agents/agentConfig.test.ts
  • web/src/features/managed-agents/agentConfig.ts
  • web/src/features/managed-agents/agents/AgentsResourcePage.tsx
  • web/src/features/managed-agents/agents/create-dialog-api.ts
  • web/src/features/managed-agents/agents/create-dialog-mcp-picker.tsx
  • web/src/features/managed-agents/agents/create-dialog-model.test.ts
  • web/src/features/managed-agents/agents/create-dialog-model.ts
  • web/src/features/managed-agents/agents/create-dialog-picker.tsx
  • web/src/features/managed-agents/agents/create-dialog-rendered.tsx
  • web/src/features/managed-agents/agents/create-dialog-tools-editor.tsx
  • web/src/features/managed-agents/agents/create-dialog.tsx
  • web/src/features/managed-agents/agents/detail.tsx
  • web/src/features/managed-agents/agents/tools/AgentToolsSection.tsx
  • web/src/features/managed-agents/agents/tools/RemoteServerIcon.test.tsx
  • web/src/features/managed-agents/agents/tools/RemoteServerIcon.tsx
  • web/src/features/managed-agents/agents/tools/model.ts
  • web/src/features/managed-agents/agents/use-agent-edit-draft.test.ts
  • web/src/features/managed-agents/agents/use-agent-edit-draft.ts
  • web/src/features/managed-agents/agents/use-create-agent-draft.ts
  • web/src/features/managed-agents/types.ts
  • web/src/shared/api/anthropic.test.ts
  • web/src/shared/api/anthropic.ts
  • web/src/shared/i18n/messages/en.json
  • web/src/shared/i18n/messages/zh-CN.json
💤 Files with no reviewable changes (1)
  • web/src/features/managed-agents/agents/tools/model.ts

Comment thread web/src/features/managed-agents/agents/create-dialog-model.ts
Comment thread web/src/features/managed-agents/agents/create-dialog-model.ts
Comment thread web/src/features/managed-agents/agents/tools/RemoteServerIcon.tsx Outdated
Comment thread web/src/features/managed-agents/ManagedAgentsPage.test-utils.tsx Outdated

@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: 88e4c7e0aa

ℹ️ 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 thread web/src/features/managed-agents/agents/tools/RemoteServerIcon.tsx Outdated
Comment thread web/src/features/managed-agents/agents/create-dialog-model.ts
pxguan added 3 commits August 7, 2026 14:26
…to codex/issue-217-custom-mcp-server

# Conflicts:
#	docs/design/fe/agent/create-agent-editor.md
#	docs/design/fe/agent/edit-agent-editor.md
#	web/src/features/managed-agents/ManagedAgentsPage.agents.suite.tsx
#	web/src/features/managed-agents/agents/create-dialog-model.test.ts
#	web/src/features/managed-agents/agents/create-dialog-model.ts
#	web/src/features/managed-agents/agents/create-dialog-picker.tsx
#	web/src/features/managed-agents/agents/create-dialog-tools-editor.tsx
#	web/src/shared/i18n/messages/en.json
#	web/src/shared/i18n/messages/zh-CN.json

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/design/fe/agent/create-agent-editor.md`:
- Line 39: Update the MCP constraints statement in the design document to
require case-sensitive uniqueness for custom names within the current Agent,
limit names to 255 characters, limit URLs to 2048 characters, and limit each
Agent to 20 MCP servers. Preserve the existing atomic add/delete requirement and
URL validity restrictions.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 5c0fe39b-2181-40a9-b8fb-47c19400ab2f

📥 Commits

Reviewing files that changed from the base of the PR and between 88e4c7e and aee67f2.

📒 Files selected for processing (13)
  • docs/design/fe/agent/create-agent-editor.md
  • docs/design/fe/agent/edit-agent-editor.md
  • web/src/features/managed-agents/ManagedAgentsPage.agents.suite.tsx
  • web/src/features/managed-agents/ManagedAgentsPage.test-utils.test.tsx
  • web/src/features/managed-agents/ManagedAgentsPage.test-utils.tsx
  • web/src/features/managed-agents/agents/create-dialog-mcp-picker.tsx
  • web/src/features/managed-agents/agents/create-dialog-model.test.ts
  • web/src/features/managed-agents/agents/create-dialog-model.ts
  • web/src/features/managed-agents/agents/create-dialog-tools-editor.tsx
  • web/src/features/managed-agents/agents/tools/AgentToolsSection.tsx
  • web/src/features/managed-agents/agents/tools/RemoteServerIcon.test.tsx
  • web/src/features/managed-agents/agents/tools/RemoteServerIcon.tsx
  • web/src/features/managed-agents/agents/use-agent-edit-draft.test.ts
🚧 Files skipped from review as they are similar to previous changes (5)
  • web/src/features/managed-agents/agents/tools/AgentToolsSection.tsx
  • web/src/features/managed-agents/agents/use-agent-edit-draft.test.ts
  • docs/design/fe/agent/edit-agent-editor.md
  • web/src/features/managed-agents/agents/create-dialog-tools-editor.tsx
  • web/src/features/managed-agents/agents/create-dialog-mcp-picker.tsx

Comment thread docs/design/fe/agent/create-agent-editor.md Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-for-agent Specification confirmed and ready for implementation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Agents] Create/Edit Agent 支持自定义 MCP 双模式选择器并移除自定义工具入口

2 participants