feat(ui): i18n for MCP server edit form

This commit is contained in:
吹雪 2026-06-10 21:02:42 +09:00
parent 4faf76ef3f
commit 359cc2920d
3 changed files with 239 additions and 81 deletions

View file

@ -2,6 +2,7 @@ import React, { useState, useEffect } from "react";
import { Form, Select, Button as AntdButton, Tooltip, Input, InputNumber } from "antd";
import { InfoCircleOutlined } from "@ant-design/icons";
import { Button, TabGroup, TabList, Tab, TabPanels, TabPanel } from "@tremor/react";
import { useTranslation } from "react-i18next";
import {
AUTH_TYPE,
OAUTH_FLOW,
@ -46,6 +47,7 @@ const MCPServerEdit: React.FC<MCPServerEditProps> = ({
onSuccess,
availableAccessGroups,
}) => {
const { t } = useTranslation();
const [form] = Form.useForm();
const [costConfig, setCostConfig] = useState<MCPServerCostInfo>({});
const [tools, setTools] = useState<any[]>([]);
@ -161,7 +163,7 @@ const MCPServerEdit: React.FC<MCPServerEditProps> = ({
form.setFieldsValue({ credentials });
NotificationsManager.success(
"OAuth authorization successful! Please click 'Update MCP Server' to save the credentials.",
t("mcpTools.mcpServerEdit.oauthAuthSuccess"),
);
}
},
@ -355,7 +357,7 @@ const MCPServerEdit: React.FC<MCPServerEditProps> = ({
: null);
if (!token) {
setTools([]);
setToolsError("Authenticate with this server in the Tools tab to load and configure its tools.");
setToolsError(t("mcpTools.mcpServerEdit.authenticateToLoadTools"));
return;
}
customHeaders = buildMcpPassthroughAuthHeader(mcpServer.alias, token);
@ -373,11 +375,11 @@ const MCPServerEdit: React.FC<MCPServerEditProps> = ({
setTools(toolsResponse.tools);
} else {
setTools([]);
setToolsError(toolsResponse.message || "Failed to load tools");
setToolsError(toolsResponse.message || t("mcpTools.mcpServerEdit.failedToLoadTools"));
}
} catch (error) {
setTools([]);
setToolsError(error instanceof Error ? error.message : "Failed to load tools");
setToolsError(error instanceof Error ? error.message : t("mcpTools.mcpServerEdit.failedToLoadTools"));
} finally {
setIsLoadingTools(false);
}
@ -406,7 +408,7 @@ const MCPServerEdit: React.FC<MCPServerEditProps> = ({
<div className="flex items-center gap-2">
<div className="w-2 h-2 bg-blue-500 rounded-full"></div>
<span className="font-medium">{searchValue}</span>
<span className="text-gray-400 text-xs ml-1">create new group</span>
<span className="text-gray-400 text-xs ml-1">{t("mcpTools.mcpServerEdit.createNewGroup")}</span>
</div>
),
});
@ -539,11 +541,11 @@ const MCPServerEdit: React.FC<MCPServerEditProps> = ({
};
if (!stdioFields.command) {
NotificationsManager.fromBackend("Stdio configuration must include a command");
NotificationsManager.fromBackend(t("mcpTools.mcpServerEdit.stdioMissingCommand"));
return;
}
} catch {
NotificationsManager.fromBackend("Invalid JSON in stdio configuration");
NotificationsManager.fromBackend(t("mcpTools.mcpServerEdit.invalidJsonStdio"));
return;
}
} else {
@ -560,7 +562,7 @@ const MCPServerEdit: React.FC<MCPServerEditProps> = ({
}, {});
}
} catch {
NotificationsManager.fromBackend("Invalid JSON in stdio env configuration");
NotificationsManager.fromBackend(t("mcpTools.mcpServerEdit.invalidJsonStdioEnv"));
return;
}
}
@ -570,7 +572,7 @@ const MCPServerEdit: React.FC<MCPServerEditProps> = ({
const parsedCommand = rawCommand ? String(rawCommand).trim() : "";
if (!parsedCommand) {
NotificationsManager.fromBackend("Stdio transport requires a command");
NotificationsManager.fromBackend(t("mcpTools.mcpServerEdit.stdioRequiresCommand"));
return;
}
@ -593,7 +595,7 @@ const MCPServerEdit: React.FC<MCPServerEditProps> = ({
try {
tokenValidation = JSON.parse(rawTokenValidationJson);
} catch {
NotificationsManager.fromBackend("Invalid JSON in Token Validation Rules");
NotificationsManager.fromBackend(t("mcpTools.mcpServerEdit.invalidJsonTokenValidation"));
return;
}
}
@ -711,30 +713,30 @@ const MCPServerEdit: React.FC<MCPServerEditProps> = ({
} catch (error: unknown) {
const message = error instanceof Error ? error.message : "";
NotificationsManager.fromBackend(
"MCP Server updated, but failed to persist OAuth token" + (message ? `: ${message}` : ""),
t("mcpTools.mcpServerEdit.oauthTokenPersistFailed", { message: message || "" }),
);
return;
}
}
NotificationsManager.success("MCP Server updated successfully");
NotificationsManager.success(t("mcpTools.mcpServerEdit.updateSuccess"));
onSuccess(updated);
} catch (error: any) {
NotificationsManager.fromBackend("Failed to update MCP Server" + (error?.message ? `: ${error.message}` : ""));
NotificationsManager.fromBackend(t("mcpTools.mcpServerEdit.updateFailed", { message: error?.message || "" }));
}
};
return (
<TabGroup>
<TabList className="grid w-full grid-cols-2">
<Tab>Server Configuration</Tab>
<Tab>Cost Configuration</Tab>
<Tab>{t("mcpTools.mcpServerEdit.tabServerConfig")}</Tab>
<Tab>{t("mcpTools.mcpServerEdit.tabCostConfig")}</Tab>
</TabList>
<TabPanels className="mt-6">
<TabPanel>
<Form form={form} onFinish={handleSave} initialValues={initialValues} layout="vertical">
<Form.Item
label="MCP Server Name"
label={t("mcpTools.mcpServerEdit.serverNameLabel")}
name="server_name"
rules={[
{
@ -745,7 +747,7 @@ const MCPServerEdit: React.FC<MCPServerEditProps> = ({
<Input className="rounded-lg border-gray-300 focus:border-blue-500 focus:ring-blue-500" />
</Form.Item>
<Form.Item
label="Alias"
label={t("mcpTools.mcpServerEdit.aliasLabel")}
name="alias"
rules={[
{
@ -758,26 +760,26 @@ const MCPServerEdit: React.FC<MCPServerEditProps> = ({
className="rounded-lg border-gray-300 focus:border-blue-500 focus:ring-blue-500"
/>
</Form.Item>
<Form.Item label="Description" name="description">
<Form.Item label={t("common.description")} name="description">
<Input className="rounded-lg border-gray-300 focus:border-blue-500 focus:ring-blue-500" />
</Form.Item>
<MCPLogoSelector value={logoUrl} onChange={setLogoUrl} />
<Form.Item label="Transport Type" name="transport" rules={[{ required: true }]}>
<Form.Item label={t("mcpTools.mcpServerEdit.transportLabel")} name="transport" rules={[{ required: true }]}>
<Select onChange={handleTransportChange}>
<Select.Option value="http">Streamable HTTP (Recommended)</Select.Option>
<Select.Option value="sse">Server-Sent Events (SSE)</Select.Option>
<Select.Option value="stdio">Standard Input/Output (stdio)</Select.Option>
<Select.Option value={TRANSPORT.OPENAPI}>OpenAPI Spec</Select.Option>
<Select.Option value="http">{t("mcpTools.mcpServerEdit.transportHttp")}</Select.Option>
<Select.Option value="sse">{t("mcpTools.mcpServerEdit.transportSse")}</Select.Option>
<Select.Option value="stdio">{t("mcpTools.mcpServerEdit.transportStdio")}</Select.Option>
<Select.Option value={TRANSPORT.OPENAPI}>{t("mcpTools.mcpServerEdit.transportOpenapi")}</Select.Option>
</Select>
</Form.Item>
{/* URL field - only for HTTP/SSE */}
{isMCPTransport && (
<Form.Item
label="MCP Server URL"
label={t("mcpTools.mcpServerEdit.serverUrlLabel")}
name="url"
rules={[
{ required: true, message: "Please enter a server URL" },
{ required: true, message: t("mcpTools.mcpServerEdit.serverUrlRequired") },
{ validator: (_, value) => validateMCPServerUrl(value) },
]}
>
@ -793,14 +795,14 @@ const MCPServerEdit: React.FC<MCPServerEditProps> = ({
<Form.Item
label={
<span className="text-sm font-medium text-gray-700 flex items-center">
OpenAPI Spec URL
<Tooltip title="URL to an OpenAPI specification (JSON or YAML). MCP tools will be automatically generated from the API endpoints defined in the spec.">
{t("mcpTools.mcpServerEdit.specUrlLabel")}
<Tooltip title={t("mcpTools.mcpServerEdit.specUrlTooltip")}>
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
</Tooltip>
</span>
}
name="spec_path"
rules={[{ required: true, message: "Please enter an OpenAPI spec URL" }]}
rules={[{ required: true, message: t("mcpTools.mcpServerEdit.specUrlRequired") }]}
>
<Input
placeholder="https://petstore3.swagger.io/api/v3/openapi.json"
@ -811,15 +813,15 @@ const MCPServerEdit: React.FC<MCPServerEditProps> = ({
{/* Authentication - for HTTP, SSE, and OpenAPI */}
{!isStdioTransport && (
<Form.Item label="Authentication" name="auth_type" rules={[{ required: true }]}>
<Form.Item label={t("mcpTools.mcpServerEdit.authLabel")} name="auth_type" rules={[{ required: true }]}>
<Select>
<Select.Option value="none">None</Select.Option>
<Select.Option value="api_key">API Key</Select.Option>
<Select.Option value="bearer_token">Bearer Token</Select.Option>
<Select.Option value="token">Token</Select.Option>
<Select.Option value="basic">Basic Auth</Select.Option>
<Select.Option value="oauth2">OAuth</Select.Option>
<Select.Option value="aws_sigv4">AWS SigV4 (Bedrock AgentCore MCPs)</Select.Option>
<Select.Option value="none">{t("mcpTools.mcpServerEdit.authNone")}</Select.Option>
<Select.Option value="api_key">{t("mcpTools.mcpServerEdit.authApiKey")}</Select.Option>
<Select.Option value="bearer_token">{t("mcpTools.mcpServerEdit.authBearerToken")}</Select.Option>
<Select.Option value="token">{t("mcpTools.mcpServerEdit.authToken")}</Select.Option>
<Select.Option value="basic">{t("mcpTools.mcpServerEdit.authBasic")}</Select.Option>
<Select.Option value="oauth2">{t("mcpTools.mcpServerEdit.authOauth")}</Select.Option>
<Select.Option value="aws_sigv4">{t("mcpTools.mcpServerEdit.authAwsSigv4")}</Select.Option>
</Select>
</Form.Item>
)}
@ -827,14 +829,13 @@ const MCPServerEdit: React.FC<MCPServerEditProps> = ({
{isStdioTransport && (
<div className="rounded-lg border border-gray-200 p-4 space-y-4">
<p className="text-sm text-gray-600">
Configure the stdio transport used to launch the MCP server process. You can either fill in the fields
below or paste a JSON configuration.
{t("mcpTools.mcpServerEdit.stdioDesc")}
</p>
<Form.Item
label="Command"
label={t("mcpTools.mcpServerEdit.stdioCommandLabel")}
name="command"
rules={[{ required: true, message: "Please enter a command for stdio transport" }]}
rules={[{ required: true, message: t("mcpTools.mcpServerEdit.stdioCommandRequired") }]}
>
<Input
placeholder="e.g., npx"
@ -842,18 +843,18 @@ const MCPServerEdit: React.FC<MCPServerEditProps> = ({
/>
</Form.Item>
<Form.Item label="Args" name="args">
<Form.Item label={t("mcpTools.mcpServerEdit.stdioArgsLabel")} name="args">
<Select
mode="tags"
size="large"
tokenSeparators={[","]}
placeholder="Add args (press enter or comma)"
placeholder={t("mcpTools.mcpServerEdit.stdioArgsPlaceholder")}
className="rounded-lg"
/>
</Form.Item>
<Form.Item
label="Environment (JSON object)"
label={t("mcpTools.mcpServerEdit.stdioEnvLabel")}
name="env_json"
rules={[
{
@ -864,9 +865,9 @@ const MCPServerEdit: React.FC<MCPServerEditProps> = ({
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
return Promise.resolve();
}
return Promise.reject(new Error("Env must be a JSON object"));
return Promise.reject(new Error(t("mcpTools.mcpServerEdit.stdioEnvMustBeObject")));
} catch {
return Promise.reject(new Error("Please enter valid JSON"));
return Promise.reject(new Error(t("mcpTools.mcpServerEdit.stdioEnvInvalidJson")));
}
},
},
@ -888,8 +889,8 @@ const MCPServerEdit: React.FC<MCPServerEditProps> = ({
<Form.Item
label={
<span className="text-sm font-medium text-gray-700 flex items-center">
Authentication Value
<Tooltip title="Token, password, or header value to send with each request for the selected auth type.">
{t("mcpTools.mcpServerEdit.authValueLabel")}
<Tooltip title={t("mcpTools.mcpServerEdit.authValueTooltip")}>
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
</Tooltip>
</span>
@ -899,13 +900,13 @@ const MCPServerEdit: React.FC<MCPServerEditProps> = ({
{
validator: (_, value) =>
value && typeof value === "string" && value.trim() === ""
? Promise.reject(new Error("Authentication value cannot be empty"))
? Promise.reject(new Error(t("mcpTools.mcpServerEdit.authValueEmpty")))
: Promise.resolve(),
},
]}
>
<Input.Password
placeholder="Enter token or secret (leave blank to keep existing)"
placeholder={t("mcpTools.mcpServerEdit.authValuePlaceholder")}
className="rounded-lg border-gray-300 focus:border-blue-500 focus:ring-blue-500"
/>
</Form.Item>
@ -916,8 +917,8 @@ const MCPServerEdit: React.FC<MCPServerEditProps> = ({
<Form.Item
label={
<span className="text-sm font-medium text-gray-700 flex items-center">
OAuth Client ID (optional)
<Tooltip title="Provide only if your MCP server cannot handle dynamic client registration.">
{t("mcpTools.mcpServerEdit.oauthClientIdLabel")}
<Tooltip title={t("mcpTools.mcpServerEdit.oauthClientIdTooltip")}>
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
</Tooltip>
</span>
@ -925,15 +926,15 @@ const MCPServerEdit: React.FC<MCPServerEditProps> = ({
name={["credentials", "client_id"]}
>
<Input.Password
placeholder="Enter OAuth client ID (leave blank to keep existing)"
placeholder={t("mcpTools.mcpServerEdit.oauthClientIdPlaceholder")}
className="rounded-lg border-gray-300 focus:border-blue-500 focus:ring-blue-500"
/>
</Form.Item>
<Form.Item
label={
<span className="text-sm font-medium text-gray-700 flex items-center">
OAuth Client Secret (optional)
<Tooltip title="Provide only if your MCP server cannot handle dynamic client registration.">
{t("mcpTools.mcpServerEdit.oauthClientSecretLabel")}
<Tooltip title={t("mcpTools.mcpServerEdit.oauthClientSecretTooltip")}>
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
</Tooltip>
</span>
@ -941,15 +942,15 @@ const MCPServerEdit: React.FC<MCPServerEditProps> = ({
name={["credentials", "client_secret"]}
>
<Input.Password
placeholder="Enter OAuth client secret (leave blank to keep existing)"
placeholder={t("mcpTools.mcpServerEdit.oauthClientSecretPlaceholder")}
className="rounded-lg border-gray-300 focus:border-blue-500 focus:ring-blue-500"
/>
</Form.Item>
<Form.Item
label={
<span className="text-sm font-medium text-gray-700 flex items-center">
OAuth Scopes (optional)
<Tooltip title="Add scopes to override the default scope list used for this MCP server.">
{t("mcpTools.mcpServerEdit.oauthScopesLabel")}
<Tooltip title={t("mcpTools.mcpServerEdit.oauthScopesTooltip")}>
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
</Tooltip>
</span>
@ -959,7 +960,7 @@ const MCPServerEdit: React.FC<MCPServerEditProps> = ({
<Select
mode="tags"
tokenSeparators={[","]}
placeholder="Add scopes"
placeholder={t("mcpTools.mcpServerEdit.oauthScopesPlaceholder")}
className="rounded-lg"
size="large"
/>
@ -967,8 +968,8 @@ const MCPServerEdit: React.FC<MCPServerEditProps> = ({
<Form.Item
label={
<span className="text-sm font-medium text-gray-700 flex items-center">
Authorization URL Override (optional)
<Tooltip title="Optional override for the authorization endpoint.">
{t("mcpTools.mcpServerEdit.authorizationUrlLabel")}
<Tooltip title={t("mcpTools.mcpServerEdit.authorizationUrlTooltip")}>
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
</Tooltip>
</span>
@ -983,8 +984,8 @@ const MCPServerEdit: React.FC<MCPServerEditProps> = ({
<Form.Item
label={
<span className="text-sm font-medium text-gray-700 flex items-center">
Token URL Override (optional)
<Tooltip title="Optional override for the token endpoint.">
{t("mcpTools.mcpServerEdit.tokenUrlLabel")}
<Tooltip title={t("mcpTools.mcpServerEdit.tokenUrlTooltip")}>
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
</Tooltip>
</span>
@ -999,8 +1000,8 @@ const MCPServerEdit: React.FC<MCPServerEditProps> = ({
<Form.Item
label={
<span className="text-sm font-medium text-gray-700 flex items-center">
Registration URL Override (optional)
<Tooltip title="Optional override for the dynamic client registration endpoint.">
{t("mcpTools.mcpServerEdit.registrationUrlLabel")}
<Tooltip title={t("mcpTools.mcpServerEdit.registrationUrlTooltip")}>
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
</Tooltip>
</span>
@ -1017,8 +1018,8 @@ const MCPServerEdit: React.FC<MCPServerEditProps> = ({
<Form.Item
label={
<span className="text-sm font-medium text-gray-700 flex items-center">
Token Validation Rules (optional)
<Tooltip title='JSON object of key-value rules checked against the OAuth token response before storing. Supports dot-notation for nested fields (e.g. {"organization": "my-org", "team.id": "123"}). Tokens that fail validation are rejected with HTTP 403.'>
{t("mcpTools.mcpServerEdit.tokenValidationLabel")}
<Tooltip title={t("mcpTools.mcpServerEdit.tokenValidationTooltip")}>
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
</Tooltip>
</span>
@ -1032,7 +1033,7 @@ const MCPServerEdit: React.FC<MCPServerEditProps> = ({
JSON.parse(value);
return Promise.resolve();
} catch {
return Promise.reject(new Error("Must be valid JSON"));
return Promise.reject(new Error(t("mcpTools.mcpServerEdit.tokenValidationMustBeJson")));
}
},
},
@ -1047,22 +1048,21 @@ const MCPServerEdit: React.FC<MCPServerEditProps> = ({
<Form.Item
label={
<span className="text-sm font-medium text-gray-700 flex items-center">
Token Storage TTL (seconds, optional)
<Tooltip title="How long to cache each user's OAuth access token in Redis before evicting it (regardless of the token's own expires_in). Leave blank to derive the TTL from the token's expires_in, or fall back to the 12-hour default.">
{t("mcpTools.mcpServerEdit.tokenStorageTtlLabel")}
<Tooltip title={t("mcpTools.mcpServerEdit.tokenStorageTtlTooltip")}>
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
</Tooltip>
</span>
}
name="token_storage_ttl_seconds"
>
<InputNumber min={1} placeholder="e.g. 3600" style={{ width: "100%" }} className="rounded-lg" />
<InputNumber min={1} placeholder={t("mcpTools.mcpServerEdit.tokenStorageTtlPlaceholder")} style={{ width: "100%" }} className="rounded-lg" />
</Form.Item>
</>
)}
<div className="rounded-lg border border-dashed border-gray-300 p-4 space-y-2">
<p className="text-sm text-gray-600">
Use OAuth to fetch a fresh access token and temporarily save it in the session as the authentication
value.
{t("mcpTools.mcpServerEdit.oauthFlowDesc")}
</p>
<Button
variant="secondary"
@ -1070,15 +1070,15 @@ const MCPServerEdit: React.FC<MCPServerEditProps> = ({
disabled={oauthStatus === "authorizing" || oauthStatus === "exchanging"}
>
{oauthStatus === "authorizing"
? "Waiting for authorization..."
? t("mcpTools.mcpServerEdit.oauthWaiting")
: oauthStatus === "exchanging"
? "Exchanging authorization code..."
: "Authorize & Fetch Token"}
? t("mcpTools.mcpServerEdit.oauthExchanging")
: t("mcpTools.mcpServerEdit.oauthAuthorize")}
</Button>
{oauthError && <p className="text-sm text-red-500">{oauthError}</p>}
{oauthStatus === "success" && oauthTokenResponse?.access_token && (
<p className="text-sm text-green-600">
Token fetched. Expires in {oauthTokenResponse.expires_in ?? "?"} seconds.
{t("mcpTools.mcpServerEdit.oauthTokenFetched", { seconds: oauthTokenResponse.expires_in ?? "?" })}
</p>
)}
</div>
@ -1088,21 +1088,21 @@ const MCPServerEdit: React.FC<MCPServerEditProps> = ({
{!isStdioTransport && isAwsSigV4AuthType && (
<>
<p className="text-sm text-gray-500 mb-2">
For MCP servers hosted on AWS Bedrock AgentCore.{" "}
{t("mcpTools.mcpServerEdit.awsSigv4Desc")}{" "}
<a
href="https://docs.litellm.ai/docs/mcp_aws_sigv4"
target="_blank"
rel="noopener noreferrer"
className="text-blue-500 hover:text-blue-700"
>
View docs &rarr;
{t("mcpTools.mcpServerEdit.awsSigv4ViewDocs")} &rarr;
</a>
</p>
<Form.Item
label={
<span className="text-sm font-medium text-gray-700 flex items-center">
AWS Region
<Tooltip title="AWS region for SigV4 signing (e.g., us-east-1)">
{t("mcpTools.mcpServerEdit.awsRegionLabel")}
<Tooltip title={t("mcpTools.mcpServerEdit.awsRegionTooltip")}>
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
</Tooltip>
</span>
@ -1111,7 +1111,7 @@ const MCPServerEdit: React.FC<MCPServerEditProps> = ({
rules={[]}
>
<Input
placeholder="us-east-1 (leave blank to keep existing)"
placeholder={t("mcpTools.mcpServerEdit.awsRegionPlaceholder")}
className="rounded-lg border-gray-300 focus:border-blue-500 focus:ring-blue-500"
/>
</Form.Item>

View file

@ -3568,6 +3568,85 @@
"copyResultFailed": "Failed to copy result",
"toolNameCopied": "Tool name copied to clipboard",
"copyToolNameFailed": "Failed to copy tool name"
},
"mcpServerEdit": {
"oauthAuthSuccess": "OAuth authorization successful! Please click 'Update MCP Server' to save the credentials.",
"authenticateToLoadTools": "Authenticate with this server in the Tools tab to load and configure its tools.",
"failedToLoadTools": "Failed to load tools",
"createNewGroup": "create new group",
"stdioMissingCommand": "Stdio configuration must include a command",
"invalidJsonStdio": "Invalid JSON in stdio configuration",
"invalidJsonStdioEnv": "Invalid JSON in stdio env configuration",
"stdioRequiresCommand": "Stdio transport requires a command",
"invalidJsonTokenValidation": "Invalid JSON in Token Validation Rules",
"oauthTokenPersistFailed": "MCP Server updated, but failed to persist OAuth token{{message}}",
"updateSuccess": "MCP Server updated successfully",
"updateFailed": "Failed to update MCP Server{{message}}",
"tabServerConfig": "Server Configuration",
"tabCostConfig": "Cost Configuration",
"serverNameLabel": "MCP Server Name",
"aliasLabel": "Alias",
"transportLabel": "Transport Type",
"transportHttp": "Streamable HTTP (Recommended)",
"transportSse": "Server-Sent Events (SSE)",
"transportStdio": "Standard Input/Output (stdio)",
"transportOpenapi": "OpenAPI Spec",
"serverUrlLabel": "MCP Server URL",
"serverUrlRequired": "Please enter a server URL",
"specUrlLabel": "OpenAPI Spec URL",
"specUrlTooltip": "URL to an OpenAPI specification (JSON or YAML). MCP tools will be automatically generated from the API endpoints defined in the spec.",
"specUrlRequired": "Please enter an OpenAPI spec URL",
"authLabel": "Authentication",
"authNone": "None",
"authApiKey": "API Key",
"authBearerToken": "Bearer Token",
"authToken": "Token",
"authBasic": "Basic Auth",
"authOauth": "OAuth",
"authAwsSigv4": "AWS SigV4 (Bedrock AgentCore MCPs)",
"stdioDesc": "Configure the stdio transport used to launch the MCP server process. You can either fill in the fields below or paste a JSON configuration.",
"stdioCommandLabel": "Command",
"stdioCommandRequired": "Please enter a command for stdio transport",
"stdioArgsLabel": "Args",
"stdioArgsPlaceholder": "Add args (press enter or comma)",
"stdioEnvLabel": "Environment (JSON object)",
"stdioEnvMustBeObject": "Env must be a JSON object",
"stdioEnvInvalidJson": "Please enter valid JSON",
"authValueLabel": "Authentication Value",
"authValueTooltip": "Token, password, or header value to send with each request for the selected auth type.",
"authValueEmpty": "Authentication value cannot be empty",
"authValuePlaceholder": "Enter token or secret (leave blank to keep existing)",
"oauthClientIdLabel": "OAuth Client ID (optional)",
"oauthClientIdTooltip": "Provide only if your MCP server cannot handle dynamic client registration.",
"oauthClientIdPlaceholder": "Enter OAuth client ID (leave blank to keep existing)",
"oauthClientSecretLabel": "OAuth Client Secret (optional)",
"oauthClientSecretTooltip": "Provide only if your MCP server cannot handle dynamic client registration.",
"oauthClientSecretPlaceholder": "Enter OAuth client secret (leave blank to keep existing)",
"oauthScopesLabel": "OAuth Scopes (optional)",
"oauthScopesTooltip": "Add scopes to override the default scope list used for this MCP server.",
"oauthScopesPlaceholder": "Add scopes",
"authorizationUrlLabel": "Authorization URL Override (optional)",
"authorizationUrlTooltip": "Optional override for the authorization endpoint.",
"tokenUrlLabel": "Token URL Override (optional)",
"tokenUrlTooltip": "Optional override for the token endpoint.",
"registrationUrlLabel": "Registration URL Override (optional)",
"registrationUrlTooltip": "Optional override for the dynamic client registration endpoint.",
"tokenValidationLabel": "Token Validation Rules (optional)",
"tokenValidationTooltip": "JSON object of key-value rules checked against the OAuth token response before storing. Supports dot-notation for nested fields (e.g. {\"organization\": \"my-org\", \"team.id\": \"123\"}). Tokens that fail validation are rejected with HTTP 403.",
"tokenValidationMustBeJson": "Must be valid JSON",
"tokenStorageTtlLabel": "Token Storage TTL (seconds, optional)",
"tokenStorageTtlTooltip": "How long to cache each user's OAuth access token in Redis before evicting it (regardless of the token's own expires_in). Leave blank to derive the TTL from the token's expires_in, or fall back to the 12-hour default.",
"tokenStorageTtlPlaceholder": "e.g. 3600",
"oauthFlowDesc": "Use OAuth to fetch a fresh access token and temporarily save it in the session as the authentication value.",
"oauthWaiting": "Waiting for authorization...",
"oauthExchanging": "Exchanging authorization code...",
"oauthAuthorize": "Authorize & Fetch Token",
"oauthTokenFetched": "Token fetched. Expires in {{seconds}} seconds.",
"awsSigv4Desc": "For MCP servers hosted on AWS Bedrock AgentCore.",
"awsSigv4ViewDocs": "View docs",
"awsRegionLabel": "AWS Region",
"awsRegionTooltip": "AWS region for SigV4 signing (e.g., us-east-1)",
"awsRegionPlaceholder": "us-east-1 (leave blank to keep existing)"
}
}
}

View file

@ -3568,6 +3568,85 @@
"copyResultFailed": "复制结果失败",
"toolNameCopied": "工具名称已复制到剪贴板",
"copyToolNameFailed": "复制工具名称失败"
},
"mcpServerEdit": {
"oauthAuthSuccess": "OAuth 授权成功!请点击「更新 MCP 服务器」以保存凭据。",
"authenticateToLoadTools": "请在「工具」选项卡中对此服务器进行身份验证,以加载和配置其工具。",
"failedToLoadTools": "加载工具失败",
"createNewGroup": "新建分组",
"stdioMissingCommand": "stdio 配置必须包含命令",
"invalidJsonStdio": "stdio 配置中的 JSON 无效",
"invalidJsonStdioEnv": "stdio 环境变量配置中的 JSON 无效",
"stdioRequiresCommand": "stdio 传输需要一个命令",
"invalidJsonTokenValidation": "Token 验证规则中的 JSON 无效",
"oauthTokenPersistFailed": "MCP 服务器已更新,但 OAuth Token 持久化失败{{message}}",
"updateSuccess": "MCP 服务器更新成功",
"updateFailed": "MCP 服务器更新失败{{message}}",
"tabServerConfig": "服务器配置",
"tabCostConfig": "成本配置",
"serverNameLabel": "MCP 服务器名称",
"aliasLabel": "别名",
"transportLabel": "传输类型",
"transportHttp": "Streamable HTTP(推荐)",
"transportSse": "Server-Sent Events(SSE)",
"transportStdio": "标准输入/输出(stdio)",
"transportOpenapi": "OpenAPI Spec",
"serverUrlLabel": "MCP 服务器 URL",
"serverUrlRequired": "请输入服务器 URL",
"specUrlLabel": "OpenAPI Spec URL",
"specUrlTooltip": "OpenAPI 规范的 URL(JSON 或 YAML 格式)。MCP 工具将根据规范中定义的 API 端点自动生成。",
"specUrlRequired": "请输入 OpenAPI Spec URL",
"authLabel": "身份验证",
"authNone": "无",
"authApiKey": "API 密钥",
"authBearerToken": "Bearer Token",
"authToken": "Token",
"authBasic": "Basic Auth",
"authOauth": "OAuth",
"authAwsSigv4": "AWS SigV4(Bedrock AgentCore MCPs)",
"stdioDesc": "配置用于启动 MCP 服务器进程的 stdio 传输。您可以填写以下字段或粘贴 JSON 配置。",
"stdioCommandLabel": "命令",
"stdioCommandRequired": "请输入 stdio 传输的命令",
"stdioArgsLabel": "参数",
"stdioArgsPlaceholder": "添加参数(按回车或逗号分隔)",
"stdioEnvLabel": "环境变量(JSON 对象)",
"stdioEnvMustBeObject": "环境变量必须是 JSON 对象",
"stdioEnvInvalidJson": "请输入有效的 JSON",
"authValueLabel": "身份验证值",
"authValueTooltip": "针对所选身份验证类型,随每次请求发送的 Token、密码或请求头值。",
"authValueEmpty": "身份验证值不能为空",
"authValuePlaceholder": "输入 Token 或密钥(留空则保留现有值)",
"oauthClientIdLabel": "OAuth Client ID(可选)",
"oauthClientIdTooltip": "仅在您的 MCP 服务器无法处理动态客户端注册时提供。",
"oauthClientIdPlaceholder": "输入 OAuth Client ID(留空则保留现有值)",
"oauthClientSecretLabel": "OAuth Client Secret(可选)",
"oauthClientSecretTooltip": "仅在您的 MCP 服务器无法处理动态客户端注册时提供。",
"oauthClientSecretPlaceholder": "输入 OAuth Client Secret(留空则保留现有值)",
"oauthScopesLabel": "OAuth Scopes(可选)",
"oauthScopesTooltip": "添加 Scope 以覆盖此 MCP 服务器默认使用的 Scope 列表。",
"oauthScopesPlaceholder": "添加 Scope",
"authorizationUrlLabel": "授权 URL 覆盖(可选)",
"authorizationUrlTooltip": "授权端点的可选覆盖地址。",
"tokenUrlLabel": "Token URL 覆盖(可选)",
"tokenUrlTooltip": "Token 端点的可选覆盖地址。",
"registrationUrlLabel": "注册 URL 覆盖(可选)",
"registrationUrlTooltip": "动态客户端注册端点的可选覆盖地址。",
"tokenValidationLabel": "Token 验证规则(可选)",
"tokenValidationTooltip": "在存储前与 OAuth Token 响应进行核对的键值规则 JSON 对象。支持点分隔符访问嵌套字段(如 {\"organization\": \"my-org\", \"team.id\": \"123\"})。验证不通过的 Token 将被 HTTP 403 拒绝。",
"tokenValidationMustBeJson": "必须是有效的 JSON",
"tokenStorageTtlLabel": "Token 存储 TTL(秒,可选)",
"tokenStorageTtlTooltip": "在 Redis 中缓存每个用户 OAuth 访问 Token 的时长(与 Token 自身的 expires_in 无关)。留空则从 Token 的 expires_in 推导 TTL,或回退到默认的 12 小时。",
"tokenStorageTtlPlaceholder": "例如 3600",
"oauthFlowDesc": "使用 OAuth 获取新的访问 Token,并将其作为身份验证值临时保存在会话中。",
"oauthWaiting": "等待授权中……",
"oauthExchanging": "正在交换授权码……",
"oauthAuthorize": "授权并获取 Token",
"oauthTokenFetched": "Token 已获取,将在 {{seconds}} 秒后过期。",
"awsSigv4Desc": "适用于托管在 AWS Bedrock AgentCore 上的 MCP 服务器。",
"awsSigv4ViewDocs": "查看文档",
"awsRegionLabel": "AWS 区域",
"awsRegionTooltip": "用于 SigV4 签名的 AWS 区域(例如 us-east-1)",
"awsRegionPlaceholder": "us-east-1(留空则保留现有值)"
}
}
}