- {FIELD_GROUPS.map((group) => (
+ {fieldGroups.map((group: FieldGroup) => (
{group.label}
- {group.fields.map((field) => {
+ {group.fields.map((field: RequiredFieldDef) => {
const active = requiredFields.includes(field.key);
return (
@@ -256,15 +266,18 @@ type MCPServerCardProps = {
};
function MCPServerCard({ server, onApprove, onReject, requiredFields }: MCPServerCardProps) {
+ const { t } = useTranslation();
const approvalStatus = (server.approval_status ?? "active") as MCPStatus;
const statusCfg = STATUS_CONFIG[approvalStatus] ?? STATUS_CONFIG["active"];
- const checks = MCP_REQUIRED_FIELD_DEFS.filter((f) => requiredFields.includes(f.key)).map((f) => ({
- key: f.key,
- label: f.label,
- description: f.description,
- passed: f.check(server),
- }));
+ const checks = getMcpRequiredFieldDefs(t)
+ .filter((f: RequiredFieldDef) => requiredFields.includes(f.key))
+ .map((f: RequiredFieldDef) => ({
+ key: f.key,
+ label: f.label,
+ description: f.description,
+ passed: f.check(server),
+ }));
const passCount = checks.filter((c) => c.passed).length;
const failCount = checks.length - passCount;
const allPassed = checks.length > 0 && failCount === 0;
diff --git a/ui/litellm-dashboard/src/locales/en.json b/ui/litellm-dashboard/src/locales/en.json
index 80f6042ed28..eaaa999750b 100644
--- a/ui/litellm-dashboard/src/locales/en.json
+++ b/ui/litellm-dashboard/src/locales/en.json
@@ -3043,5 +3043,129 @@
"updateFailed": "Failed to update guardrail",
"notFound": "Guardrail not found"
}
+ },
+ "mcpTools": {
+ "byokCredentialModal": {
+ "pleaseEnterApiKey": "Please enter your API key",
+ "connectedSuccess": "Connected to {{name}}",
+ "failedToConnect": "Failed to connect",
+ "connectTitle": "Connect {{name}}",
+ "connectDesc": "LiteLLM needs access to {{name}} to complete your request.",
+ "howItWorksTitle": "How it works",
+ "howItWorksDesc": "LiteLLM acts as a secure bridge. Your requests are routed through our MCP client directly to {{name}}'s API.",
+ "requestedAccess": "Requested Access",
+ "continueToAuth": "Continue to Authentication",
+ "provideApiKeyTitle": "Provide API Key",
+ "provideApiKeyDesc": "Enter your {{name}} API key to authorize this connection.",
+ "apiKeyLabel": "{{name}} API Key",
+ "apiKeyPlaceholder": "Enter your API key",
+ "whereIsMyApiKey": "Where do I find my API key?",
+ "saveKeyLabel": "Save key for future use",
+ "securityNote": "Your key is stored securely and transmitted over HTTPS. It is never shared with third parties.",
+ "connectAndAuthorize": "Connect & Authorize"
+ },
+ "envVarsSection": {
+ "sectionTitle": "Variables",
+ "tooltipDefine": "Define variables you can interpolate in Static Headers or Authentication using",
+ "tooltipInstance": "admin-defined value used for every user.",
+ "tooltipPerUser": "each user supplies their own value (e.g. personal credentials) via the MCP Gateway dashboard.",
+ "referenceHint": "Reference these in Static Headers or Authentication as",
+ "exampleLabel": "For example:",
+ "colVarName": "Variable Name",
+ "colValueDesc": "Value / Description",
+ "colScope": "Scope",
+ "scopeInstance": "Instance",
+ "scopePerUser": "Per-user",
+ "varNameRequired": "Variable name is required",
+ "varNamePattern": "Use letters, digits, underscores; cannot start with a digit.",
+ "perUserHintTooltip": "Per-user variables have no shared value. This text is only a hint shown to each user when they fill in their own value.",
+ "hintLabel": "Hint",
+ "perUserPlaceholder": "e.g. Your DB username",
+ "valuePlaceholder": "e.g. postgresql",
+ "addVariable": "Add Variable"
+ },
+ "mcpLogoSelector": {
+ "logoLabel": "Logo",
+ "logoTooltip": "Select a well-known logo or paste a URL to any image. The logo is shown on the admin and chat pages.",
+ "selectedLogoAlt": "Selected logo",
+ "customUrlPlaceholder": "Or paste a custom logo URL..."
+ },
+ "mcpNetworkSettings": {
+ "privateIpRangesTitle": "Private IP Ranges",
+ "privateIpRangesDesc": "Define which IP ranges are part of your private network. Callers from these IPs can see all MCP servers. Callers from any other IP can only see servers marked \"Available on Public Internet\".",
+ "yourCurrentIp": "Your current IP:",
+ "suggestedRange": "Suggested range:",
+ "yourPrivateNetworkRanges": "Your Private Network Ranges",
+ "rangesPlaceholder": "Leave empty to use defaults: 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 127.0.0.0/8",
+ "cidrHelp": "Enter CIDR ranges (e.g., 10.0.0.0/8). When empty, standard private IP ranges are used."
+ },
+ "mcpPermissionManagement": {
+ "panelTitle": "Permission Management / Access Control",
+ "panelSubtitle": "Configure access permissions and security settings (Optional)",
+ "allowAllKeysLabel": "Allow All LiteLLM Keys",
+ "allowAllKeysTooltip": "When enabled, every API key can access this MCP server.",
+ "allowAllKeysDesc": "Enable if this server should be \"public\" to all keys.",
+ "internalNetworkOnlyLabel": "Internal network only",
+ "internalNetworkOnlyTooltip": "When on, only requests from within your internal network are accepted. Turn off to allow external clients (other clusters, ChatGPT, etc). API key authentication is always required regardless of this setting.",
+ "internalNetworkOnlyDesc": "Turn on to restrict access to callers within your internal network only.",
+ "delegateAuthLabel": "Delegate auth to upstream (PKCE passthrough)",
+ "delegateAuthTooltip": "When on, LiteLLM skips its own API key/SSO check for this server and lets the client complete PKCE directly with the upstream MCP server. Only honored when Auth Type is oauth2. No spend tracking or per-key rate limiting will run on this route.",
+ "delegateAuthDesc": "Bypass LiteLLM auth so clients authenticate directly with the upstream OAuth MCP server.",
+ "oauthPassthroughLabel": "OAuth pass-through",
+ "oauthPassthroughTooltip": "When on, this server is treated as an OAuth pass-through: the gateway proxies the upstream /.well-known/oauth-protected-resource metadata, emits spec-compliant 401 challenges when no bearer is supplied, and propagates upstream 401/403 responses. Only honored when Auth Type is None and 'Authorization' is in Extra Headers.",
+ "oauthPassthroughDesc": "Forward upstream OAuth discovery and 401 challenges so clients negotiate OAuth directly with the upstream MCP server.",
+ "internalDelegateWarningTitle": "Internal server with upstream OAuth delegation",
+ "internalDelegateWarningDesc": "This MCP server is configured as internal-only but delegates auth to upstream. Anonymous users will be able to reach the upstream OAuth2 /authorize flow without a LiteLLM session. Ensure your upstream provider and network enforce access controls.",
+ "accessGroupsLabel": "MCP Access Groups",
+ "accessGroupsTooltip": "Specify access groups for this MCP server. Users must be in at least one of these groups to access the server.",
+ "accessGroupsPlaceholder": "Select existing groups or type to create new ones",
+ "extraHeadersLabel": "Extra Headers",
+ "extraHeadersTooltip": "Forward custom headers from incoming requests to this MCP server (e.g., Authorization, X-Custom-Header, User-Agent)",
+ "configuredCount": "{{count}} configured",
+ "extraHeadersCurrently": "Currently: {{headers}}",
+ "extraHeadersPlaceholder": "Enter header names (e.g., Authorization, X-Custom-Header)",
+ "staticHeadersLabel": "Static Headers",
+ "staticHeadersTooltip": "Send these key-value headers with every request to this MCP server.",
+ "headerNameRequired": "Header name is required",
+ "headerNamePlaceholder": "Header name (e.g., X-API-Key)",
+ "headerValueRequired": "Header value is required",
+ "headerValuePlaceholder": "Header value",
+ "addStaticHeader": "Add Static Header"
+ },
+ "mcpServerCard": {
+ "testConnection": "Test Connection",
+ "serverActionsAriaLabel": "Server actions",
+ "logoAlt": "{{name}} logo",
+ "public": "Public",
+ "internal": "Internal",
+ "missingUserFieldsTitle": "Missing user fields:",
+ "missingUserFields_one": "{{count}} user field missing",
+ "missingUserFields_other": "{{count}} user fields missing",
+ "setButton": "Set",
+ "checking": "Checking",
+ "healthLabel": "Health: {{status}}",
+ "lastCheck": "Last check: {{time}}",
+ "noHealthData": "No health data",
+ "clickToRecheck": "Click to recheck",
+ "byokCredential": "BYOK credential",
+ "connected": "Connected",
+ "connectButton": "Connect"
+ },
+ "mcpStandardsSettings": {
+ "groupDocumentation": "Documentation",
+ "fieldDescriptionLabel": "Description",
+ "fieldDescriptionDesc": "Must have a non-empty description",
+ "fieldAliasLabel": "Alias",
+ "fieldAliasDesc": "Must have a display alias",
+ "groupSource": "Source",
+ "fieldSourceUrlLabel": "GitHub / Source URL",
+ "fieldSourceUrlDesc": "Must link to a source repository",
+ "groupConnection": "Connection",
+ "fieldServerUrlLabel": "Server URL",
+ "fieldServerUrlDesc": "Must have a URL configured",
+ "groupSecurity": "Security",
+ "fieldAuthLabel": "Auth configured",
+ "fieldAuthDesc": "Must use authentication (not 'none')"
+ }
}
}
diff --git a/ui/litellm-dashboard/src/locales/zh-CN.json b/ui/litellm-dashboard/src/locales/zh-CN.json
index b9cc777b0ff..529c5daba14 100644
--- a/ui/litellm-dashboard/src/locales/zh-CN.json
+++ b/ui/litellm-dashboard/src/locales/zh-CN.json
@@ -3043,5 +3043,129 @@
"updateFailed": "更新护栏失败",
"notFound": "未找到护栏"
}
+ },
+ "mcpTools": {
+ "byokCredentialModal": {
+ "pleaseEnterApiKey": "请输入您的 API 密钥",
+ "connectedSuccess": "已连接到 {{name}}",
+ "failedToConnect": "连接失败",
+ "connectTitle": "连接 {{name}}",
+ "connectDesc": "LiteLLM 需要访问 {{name}} 以完成您的请求。",
+ "howItWorksTitle": "工作原理",
+ "howItWorksDesc": "LiteLLM 充当安全桥梁。您的请求通过我们的 MCP 客户端直接路由到 {{name}} 的 API。",
+ "requestedAccess": "请求的访问权限",
+ "continueToAuth": "继续进行认证",
+ "provideApiKeyTitle": "提供 API 密钥",
+ "provideApiKeyDesc": "请输入您的 {{name}} API 密钥以授权此连接。",
+ "apiKeyLabel": "{{name}} API 密钥",
+ "apiKeyPlaceholder": "输入您的 API 密钥",
+ "whereIsMyApiKey": "在哪里可以找到我的 API 密钥?",
+ "saveKeyLabel": "保存密钥以供以后使用",
+ "securityNote": "您的密钥已安全存储并通过 HTTPS 传输,不会与第三方共享。",
+ "connectAndAuthorize": "连接并授权"
+ },
+ "envVarsSection": {
+ "sectionTitle": "变量",
+ "tooltipDefine": "定义可在静态请求头或认证中使用的变量,插值方式为",
+ "tooltipInstance": "由管理员定义,对所有用户生效。",
+ "tooltipPerUser": "每位用户通过 MCP Gateway 仪表盘填入自己的值(例如个人凭据)。",
+ "referenceHint": "在静态请求头或认证中以此方式引用这些变量:",
+ "exampleLabel": "例如:",
+ "colVarName": "变量名",
+ "colValueDesc": "值 / 说明",
+ "colScope": "作用域",
+ "scopeInstance": "实例",
+ "scopePerUser": "按用户",
+ "varNameRequired": "变量名为必填项",
+ "varNamePattern": "只能使用字母、数字、下划线,且不能以数字开头。",
+ "perUserHintTooltip": "按用户变量没有共享值。此文本仅作为提示,在每位用户填写自己的值时显示。",
+ "hintLabel": "提示",
+ "perUserPlaceholder": "例如:您的数据库用户名",
+ "valuePlaceholder": "例如:postgresql",
+ "addVariable": "添加变量"
+ },
+ "mcpLogoSelector": {
+ "logoLabel": "Logo",
+ "logoTooltip": "选择常用 Logo 或粘贴任意图片 URL。Logo 将显示在管理页面和对话页面。",
+ "selectedLogoAlt": "已选 Logo",
+ "customUrlPlaceholder": "或粘贴自定义 Logo URL..."
+ },
+ "mcpNetworkSettings": {
+ "privateIpRangesTitle": "私有 IP 范围",
+ "privateIpRangesDesc": "定义哪些 IP 范围属于您的私有网络。来自这些 IP 的调用方可以看到所有 MCP 服务器;来自其他 IP 的调用方只能看到标记为「可在公共互联网上访问」的服务器。",
+ "yourCurrentIp": "您当前的 IP:",
+ "suggestedRange": "建议范围:",
+ "yourPrivateNetworkRanges": "您的私有网络范围",
+ "rangesPlaceholder": "留空以使用默认值:10.0.0.0/8、172.16.0.0/12、192.168.0.0/16、127.0.0.0/8",
+ "cidrHelp": "输入 CIDR 范围(例如:10.0.0.0/8)。留空时使用标准私有 IP 范围。"
+ },
+ "mcpPermissionManagement": {
+ "panelTitle": "权限管理 / 访问控制",
+ "panelSubtitle": "配置访问权限和安全设置(可选)",
+ "allowAllKeysLabel": "允许所有 LiteLLM 密钥",
+ "allowAllKeysTooltip": "启用后,每个 API 密钥都可以访问此 MCP 服务器。",
+ "allowAllKeysDesc": "若希望此服务器对所有密钥「公开」,请启用此选项。",
+ "internalNetworkOnlyLabel": "仅限内部网络",
+ "internalNetworkOnlyTooltip": "开启后,仅接受来自内部网络的请求。关闭后可允许外部客户端(其他集群、ChatGPT 等)访问。无论此设置如何,始终需要 API 密钥认证。",
+ "internalNetworkOnlyDesc": "开启后将访问限制为仅限内部网络中的调用方。",
+ "delegateAuthLabel": "将认证委托给上游(PKCE 透传)",
+ "delegateAuthTooltip": "开启后,LiteLLM 跳过自身的 API 密钥/SSO 检查,让客户端直接与上游 MCP 服务器完成 PKCE 认证。仅在认证类型为 oauth2 时生效。此路由不会执行花费追踪或按密钥速率限制。",
+ "delegateAuthDesc": "绕过 LiteLLM 认证,让客户端直接与上游 OAuth MCP 服务器进行认证。",
+ "oauthPassthroughLabel": "OAuth 透传",
+ "oauthPassthroughTooltip": "开启后,此服务器将作为 OAuth 透传处理:网关代理上游 /.well-known/oauth-protected-resource 元数据,在未提供 bearer 令牌时发出符合规范的 401 挑战,并传播上游 401/403 响应。仅在认证类型为 None 且「Authorization」在额外请求头中时生效。",
+ "oauthPassthroughDesc": "转发上游 OAuth 发现信息和 401 挑战,让客户端直接与上游 MCP 服务器协商 OAuth 认证。",
+ "internalDelegateWarningTitle": "内部服务器已启用上游 OAuth 委托",
+ "internalDelegateWarningDesc": "此 MCP 服务器配置为仅限内部访问,但已将认证委托给上游。匿名用户将能在没有 LiteLLM 会话的情况下访问上游 OAuth2 /authorize 流程。请确保您的上游提供商和网络已实施访问控制。",
+ "accessGroupsLabel": "MCP 访问组",
+ "accessGroupsTooltip": "为此 MCP 服务器指定访问组。用户必须属于至少一个访问组才能访问此服务器。",
+ "accessGroupsPlaceholder": "选择现有组或输入新组名",
+ "extraHeadersLabel": "额外请求头",
+ "extraHeadersTooltip": "将传入请求中的自定义请求头转发到此 MCP 服务器(例如:Authorization、X-Custom-Header、User-Agent)",
+ "configuredCount": "已配置 {{count}} 个",
+ "extraHeadersCurrently": "当前:{{headers}}",
+ "extraHeadersPlaceholder": "输入请求头名称(例如:Authorization、X-Custom-Header)",
+ "staticHeadersLabel": "静态请求头",
+ "staticHeadersTooltip": "向此 MCP 服务器的每次请求发送这些键值对请求头。",
+ "headerNameRequired": "请求头名称为必填项",
+ "headerNamePlaceholder": "请求头名称(例如:X-API-Key)",
+ "headerValueRequired": "请求头值为必填项",
+ "headerValuePlaceholder": "请求头值",
+ "addStaticHeader": "添加静态请求头"
+ },
+ "mcpServerCard": {
+ "testConnection": "测试连接",
+ "serverActionsAriaLabel": "服务器操作",
+ "logoAlt": "{{name}} Logo",
+ "public": "公开",
+ "internal": "内部",
+ "missingUserFieldsTitle": "缺少用户字段:",
+ "missingUserFields_one": "缺少 {{count}} 个用户字段",
+ "missingUserFields_other": "缺少 {{count}} 个用户字段",
+ "setButton": "设置",
+ "checking": "检查中",
+ "healthLabel": "健康状态:{{status}}",
+ "lastCheck": "上次检查:{{time}}",
+ "noHealthData": "暂无健康数据",
+ "clickToRecheck": "点击重新检查",
+ "byokCredential": "BYOK 凭据",
+ "connected": "已连接",
+ "connectButton": "连接"
+ },
+ "mcpStandardsSettings": {
+ "groupDocumentation": "文档",
+ "fieldDescriptionLabel": "描述",
+ "fieldDescriptionDesc": "必须有非空描述",
+ "fieldAliasLabel": "别名",
+ "fieldAliasDesc": "必须有显示别名",
+ "groupSource": "来源",
+ "fieldSourceUrlLabel": "GitHub / 源码 URL",
+ "fieldSourceUrlDesc": "必须链接到源码仓库",
+ "groupConnection": "连接",
+ "fieldServerUrlLabel": "服务器 URL",
+ "fieldServerUrlDesc": "必须配置 URL",
+ "groupSecurity": "安全",
+ "fieldAuthLabel": "已配置认证",
+ "fieldAuthDesc": "必须使用认证(不能为 'none')"
+ }
}
}