From ffccf0b0fa2ab762ecc3f5c5e12a7ea4c25ff421 Mon Sep 17 00:00:00 2001 From: euvre <93761161+euvre@users.noreply.github.com> Date: Wed, 22 Jul 2026 17:25:18 +0800 Subject: [PATCH] fix(web): preserve MCP authorization token across edits (#17177) --- .../user-setting/mcp/edit-mcp-dialog.tsx | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/web/src/pages/user-setting/mcp/edit-mcp-dialog.tsx b/web/src/pages/user-setting/mcp/edit-mcp-dialog.tsx index efa316f86a..5e18c0933a 100644 --- a/web/src/pages/user-setting/mcp/edit-mcp-dialog.tsx +++ b/web/src/pages/user-setting/mcp/edit-mcp-dialog.tsx @@ -39,8 +39,13 @@ const DefaultValues = { name: '', server_type: ServerType.SSE, url: '', + authorization_token: '', }; +// Mask shown in the token field when editing an existing server that already +// has a token, so the user knows a secret is stored without exposing it. +const TokenMask = '********'; + export function EditMcpDialog({ hideModal, loading, @@ -78,9 +83,15 @@ export function EditMcpDialog({ }, []); const handleOk = async (values: z.infer) => { + // When the field still holds the mask, the user did not change the token; + // send the previously stored token so it is not overwritten with empty. + const token = + values.authorization_token === TokenMask + ? data.variables?.authorization_token + : values.authorization_token; const nextValues = { ...omit(values, 'authorization_token'), - variables: { authorization_token: values.authorization_token }, + variables: { authorization_token: token }, headers: { Authorization: 'Bearer ${authorization_token}' }, }; if (isTriggeredBySaving) { @@ -95,7 +106,12 @@ export function EditMcpDialog({ useEffect(() => { if (!isEmpty(data)) { - form.reset(pick(data, ['name', 'server_type', 'url'])); + form.reset({ + ...pick(data, ['name', 'server_type', 'url']), + authorization_token: data.variables?.authorization_token + ? TokenMask + : '', + }); } }, [data, form]);