@samanhappy/mcphub 1.0.38 → 1.0.39

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/dist/db/repositories/VectorEmbeddingRepository.js +35 -3
  2. package/dist/db/repositories/VectorEmbeddingRepository.js.map +1 -1
  3. package/dist/services/mcpService.js +85 -2
  4. package/dist/services/mcpService.js.map +1 -1
  5. package/dist/services/vectorSearchService.js +12 -3
  6. package/dist/services/vectorSearchService.js.map +1 -1
  7. package/dist/utils/cacheUtils.js +345 -1
  8. package/dist/utils/cacheUtils.js.map +1 -1
  9. package/dist/utils/packageUpdate.js +242 -0
  10. package/dist/utils/packageUpdate.js.map +1 -0
  11. package/dist/utils/serverConfigPersistence.js +6 -0
  12. package/dist/utils/serverConfigPersistence.js.map +1 -1
  13. package/frontend/dist/assets/{ActivityPage-BZNq-eGE.js → ActivityPage-CDKSVr2I.js} +2 -2
  14. package/frontend/dist/assets/{ActivityPage-BZNq-eGE.js.map → ActivityPage-CDKSVr2I.js.map} +1 -1
  15. package/frontend/dist/assets/CopyClientConfigDialog-DYiucK0d.js +4 -0
  16. package/frontend/dist/assets/CopyClientConfigDialog-DYiucK0d.js.map +1 -0
  17. package/frontend/dist/assets/{CredentialsPage-7kyDJLsX.js → CredentialsPage-DMJE4uT2.js} +2 -2
  18. package/frontend/dist/assets/{CredentialsPage-7kyDJLsX.js.map → CredentialsPage-DMJE4uT2.js.map} +1 -1
  19. package/frontend/dist/assets/Dashboard-Dh_39img.js +2 -0
  20. package/frontend/dist/assets/{Dashboard-CElNx820.js.map → Dashboard-Dh_39img.js.map} +1 -1
  21. package/frontend/dist/assets/EndpointCopy-CQmwGXbD.js +2 -0
  22. package/frontend/dist/assets/EndpointCopy-CQmwGXbD.js.map +1 -0
  23. package/frontend/dist/assets/GroupsPage-BqscWSfR.js +33 -0
  24. package/frontend/dist/assets/GroupsPage-BqscWSfR.js.map +1 -0
  25. package/frontend/dist/assets/{LoginPage-D23s7oM0.js → LoginPage-DcrwvgS6.js} +2 -2
  26. package/frontend/dist/assets/{LoginPage-D23s7oM0.js.map → LoginPage-DcrwvgS6.js.map} +1 -1
  27. package/frontend/dist/assets/{LogsPage-BuQMkmV-.js → LogsPage--Blkr-Ni.js} +2 -2
  28. package/frontend/dist/assets/{LogsPage-BuQMkmV-.js.map → LogsPage--Blkr-Ni.js.map} +1 -1
  29. package/frontend/dist/assets/{MarketPage-g9vEYzIq.js → MarketPage-DWv18j4V.js} +2 -2
  30. package/frontend/dist/assets/{MarketPage-g9vEYzIq.js.map → MarketPage-DWv18j4V.js.map} +1 -1
  31. package/frontend/dist/assets/{OAuthConsentPage-BiX1lpJR.js → OAuthConsentPage-DCKZIMzE.js} +2 -2
  32. package/frontend/dist/assets/{OAuthConsentPage-BiX1lpJR.js.map → OAuthConsentPage-DCKZIMzE.js.map} +1 -1
  33. package/frontend/dist/assets/{PromptsPage-g8SRFY6s.js → PromptsPage-DoVmnVnp.js} +2 -2
  34. package/frontend/dist/assets/{PromptsPage-g8SRFY6s.js.map → PromptsPage-DoVmnVnp.js.map} +1 -1
  35. package/frontend/dist/assets/{ResourcesPage-Ddhxi9Sf.js → ResourcesPage-B8udCQQR.js} +2 -2
  36. package/frontend/dist/assets/{ResourcesPage-Ddhxi9Sf.js.map → ResourcesPage-B8udCQQR.js.map} +1 -1
  37. package/frontend/dist/assets/ServersPage-OLpH1K1I.js +39 -0
  38. package/frontend/dist/assets/ServersPage-OLpH1K1I.js.map +1 -0
  39. package/frontend/dist/assets/{SettingsPage-DZXjQZXS.js → SettingsPage-DlK0Jcta.js} +3 -3
  40. package/frontend/dist/assets/{SettingsPage-DZXjQZXS.js.map → SettingsPage-DlK0Jcta.js.map} +1 -1
  41. package/frontend/dist/assets/{StatusDot-CdzMqjTi.js → StatusDot-DgDU3plH.js} +2 -2
  42. package/frontend/dist/assets/{StatusDot-CdzMqjTi.js.map → StatusDot-DgDU3plH.js.map} +1 -1
  43. package/frontend/dist/assets/{ToggleGroup-CJd8X_31.js → ToggleGroup-11yhmcwY.js} +2 -2
  44. package/frontend/dist/assets/{ToggleGroup-CJd8X_31.js.map → ToggleGroup-11yhmcwY.js.map} +1 -1
  45. package/frontend/dist/assets/{UsersPage-CkP_x9Rt.js → UsersPage-BqPEkoIX.js} +2 -2
  46. package/frontend/dist/assets/{UsersPage-CkP_x9Rt.js.map → UsersPage-BqPEkoIX.js.map} +1 -1
  47. package/frontend/dist/assets/clipboard-BukcCPLt.js +2 -0
  48. package/frontend/dist/assets/clipboard-BukcCPLt.js.map +1 -0
  49. package/frontend/dist/assets/{icons-vendor-VW-UwEhw.js → icons-vendor-Bk5sng-h.js} +66 -61
  50. package/frontend/dist/assets/icons-vendor-Bk5sng-h.js.map +1 -0
  51. package/frontend/dist/assets/index-D4Vy78bV.css +1 -0
  52. package/frontend/dist/assets/index-DhzWX9nb.js +3 -0
  53. package/frontend/dist/assets/{index-Bu4XuAH4.js.map → index-DhzWX9nb.js.map} +1 -1
  54. package/frontend/dist/assets/{resourceService-w-cZ31FD.js → resourceService-D-PRt7tB.js} +2 -2
  55. package/frontend/dist/assets/{resourceService-w-cZ31FD.js.map → resourceService-D-PRt7tB.js.map} +1 -1
  56. package/frontend/dist/assets/{useCostData-C72NC0PQ.js → useCostData-B-uSfiuA.js} +2 -2
  57. package/frontend/dist/assets/{useCostData-C72NC0PQ.js.map → useCostData-B-uSfiuA.js.map} +1 -1
  58. package/frontend/dist/assets/useSettingsData-Bk1AwN5F.js +2 -0
  59. package/frontend/dist/assets/{useSettingsData-JTEMu74D.js.map → useSettingsData-Bk1AwN5F.js.map} +1 -1
  60. package/frontend/dist/assets/variableDetection-B7Ko56CL.js +16 -0
  61. package/frontend/dist/assets/variableDetection-B7Ko56CL.js.map +1 -0
  62. package/frontend/dist/index.html +3 -3
  63. package/package.json +2 -1
  64. package/frontend/dist/assets/Dashboard-CElNx820.js +0 -2
  65. package/frontend/dist/assets/EndpointCopy-8jW5Xtka.js +0 -2
  66. package/frontend/dist/assets/EndpointCopy-8jW5Xtka.js.map +0 -1
  67. package/frontend/dist/assets/GroupsPage-dUkvX_iB.js +0 -33
  68. package/frontend/dist/assets/GroupsPage-dUkvX_iB.js.map +0 -1
  69. package/frontend/dist/assets/ServersPage-DAmKvrPV.js +0 -39
  70. package/frontend/dist/assets/ServersPage-DAmKvrPV.js.map +0 -1
  71. package/frontend/dist/assets/icons-vendor-VW-UwEhw.js.map +0 -1
  72. package/frontend/dist/assets/index-B3OqAhGz.css +0 -1
  73. package/frontend/dist/assets/index-Bu4XuAH4.js +0 -3
  74. package/frontend/dist/assets/toolDescription-Dw3sa28K.js +0 -2
  75. package/frontend/dist/assets/toolDescription-Dw3sa28K.js.map +0 -1
  76. package/frontend/dist/assets/useSettingsData-JTEMu74D.js +0 -2
  77. package/frontend/dist/assets/variableDetection-DfhNyFy-.js +0 -16
  78. package/frontend/dist/assets/variableDetection-DfhNyFy-.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"variableDetection-B7Ko56CL.js","sources":["../../src/utils/serverFormPayload.ts","../../src/utils/shareUserSelection.ts","../../src/utils/openApiSecurityPrefill.ts","../../src/utils/openApiSourceAnalysis.ts","../../src/utils/serverName.ts","../../src/components/ServerForm.tsx","../../src/utils/variableDetection.ts"],"sourcesContent":["import type { EnvVar, ServerConfig, ServerFormData } from '../types';\n\ntype ServerType = NonNullable<ServerConfig['type']>;\n\ninterface BuildServerPayloadInput {\n formData: ServerFormData;\n serverType: ServerType;\n envVars: EnvVar[];\n headerVars: EnvVar[];\n}\n\nconst buildKeyValueRecord = (vars: EnvVar[]): Record<string, string> => {\n const record: Record<string, string> = {};\n\n vars.forEach(({ key, value }) => {\n const trimmedKey = key.trim();\n if (trimmedKey) {\n record[trimmedKey] = value;\n }\n });\n\n return record;\n};\n\nconst parseCommaSeparatedList = (value?: string): string[] => {\n if (!value) {\n return [];\n }\n\n return value\n .split(',')\n .map((item) => item.trim())\n .filter((item) => item.length > 0);\n};\n\nconst normalizeSharedUsers = (usernames?: string[]): string[] => {\n return Array.from(\n new Set(\n (usernames || [])\n .map((username) => username.trim())\n .filter((username) => username.length > 0),\n ),\n );\n};\n\nconst buildOptions = (options?: ServerFormData['options']) => {\n const nextOptions: NonNullable<ServerFormData['options']> = {};\n\n // Always echo the timeout, even when it equals the 60000 default: dropping it\n // makes the payload differ from a stored explicit `timeout: 60000` and trips\n // the backend's \"connection changed\" fast-path check on unrelated edits. The\n // backend comparison normalizes the default timeout, so an explicit 60000 and\n // an absent one compare as equal.\n if (typeof options?.timeout === 'number' && !Number.isNaN(options.timeout)) {\n nextOptions.timeout = options.timeout;\n }\n\n if (typeof options?.resetTimeoutOnProgress === 'boolean') {\n nextOptions.resetTimeoutOnProgress = options.resetTimeoutOnProgress;\n }\n\n if (options?.maxTotalTimeout) {\n nextOptions.maxTotalTimeout = options.maxTotalTimeout;\n }\n\n return nextOptions;\n};\n\nconst buildOAuthConfig = (\n oauth?: ServerFormData['oauth'],\n): Partial<NonNullable<ServerConfig['oauth']>> => {\n if (!oauth) {\n return {};\n }\n\n const nextOAuth: Partial<NonNullable<ServerConfig['oauth']>> = {};\n const clientId = oauth.clientId?.trim();\n const clientSecret = oauth.clientSecret?.trim();\n const scopes = oauth.scopes?.trim();\n const accessToken = oauth.accessToken?.trim();\n const refreshToken = oauth.refreshToken?.trim();\n const authorizationEndpoint = oauth.authorizationEndpoint?.trim();\n const tokenEndpoint = oauth.tokenEndpoint?.trim();\n const resource = oauth.resource?.trim();\n\n if (clientId) nextOAuth.clientId = clientId;\n if (clientSecret) nextOAuth.clientSecret = clientSecret;\n if (scopes) {\n const parsedScopes = scopes\n .split(/[\\s,]+/)\n .map((scope) => scope.trim())\n .filter((scope) => scope.length > 0);\n\n if (parsedScopes.length > 0) {\n nextOAuth.scopes = parsedScopes;\n }\n }\n if (accessToken) nextOAuth.accessToken = accessToken;\n if (refreshToken) nextOAuth.refreshToken = refreshToken;\n if (authorizationEndpoint) nextOAuth.authorizationEndpoint = authorizationEndpoint;\n if (tokenEndpoint) nextOAuth.tokenEndpoint = tokenEndpoint;\n if (resource) nextOAuth.resource = resource;\n\n return nextOAuth;\n};\n\nconst buildOpenApiConfig = (formData: ServerFormData): NonNullable<ServerConfig['openapi']> => {\n const openapi: NonNullable<ServerConfig['openapi']> = {\n version: formData.openapi?.version || '3.1.0',\n passthroughHeaders: parseCommaSeparatedList(formData.openapi?.passthroughHeaders),\n cookieSession: formData.openapi?.cookieSession === true ? true : undefined,\n };\n const oauth2TokenUrl = formData.openapi?.oauth2TokenUrl?.trim();\n const oauth2ClientId = formData.openapi?.oauth2ClientId?.trim();\n const oauth2ClientSecret = formData.openapi?.oauth2ClientSecret?.trim();\n const oauth2Token = formData.openapi?.oauth2Token?.trim();\n\n if (formData.openapi?.inputMode === 'url') {\n openapi.url = formData.openapi?.url || '';\n } else if (formData.openapi?.inputMode === 'schema' && formData.openapi?.schema) {\n try {\n openapi.schema = JSON.parse(formData.openapi.schema);\n } catch {\n throw new Error('Invalid JSON schema format');\n }\n }\n\n if (formData.openapi?.securityType && formData.openapi.securityType !== 'none') {\n openapi.security = {\n type: formData.openapi.securityType,\n ...(formData.openapi.securityType === 'apiKey' && {\n apiKey: {\n name: formData.openapi.apiKeyName || '',\n in: formData.openapi.apiKeyIn || 'header',\n value: formData.openapi.apiKeyValue || '',\n },\n }),\n ...(formData.openapi.securityType === 'http' && {\n http: {\n scheme: formData.openapi.httpScheme || 'bearer',\n credentials: formData.openapi.httpCredentials || '',\n },\n }),\n ...(formData.openapi.securityType === 'oauth2' && {\n oauth2: {\n ...(oauth2TokenUrl && {\n tokenUrl: oauth2TokenUrl,\n }),\n ...(oauth2ClientId && {\n clientId: oauth2ClientId,\n }),\n ...(oauth2ClientSecret && {\n clientSecret: oauth2ClientSecret,\n }),\n ...(oauth2Token && {\n token: oauth2Token,\n }),\n },\n }),\n ...(formData.openapi.securityType === 'openIdConnect' && {\n openIdConnect: {\n url: formData.openapi.openIdConnectUrl || '',\n token: formData.openapi.openIdConnectToken || '',\n },\n }),\n };\n }\n\n // Separate credential for the spec document download (#1079). Only emitted\n // when explicitly enabled; absent means \"share the main `security`\". oauth2\n // here is a static token only — the dynamic client-credentials fetch exists\n // just for the main `security`.\n const specSecurityType = formData.openapi?.specSecurityType;\n if (specSecurityType && specSecurityType !== 'none') {\n openapi.specSecurity = {\n type: specSecurityType,\n ...(specSecurityType === 'apiKey' && {\n apiKey: {\n name: formData.openapi?.specApiKeyName || '',\n in: formData.openapi?.specApiKeyIn || 'header',\n value: formData.openapi?.specApiKeyValue || '',\n },\n }),\n ...(specSecurityType === 'http' && {\n http: {\n scheme: formData.openapi?.specHttpScheme || 'basic',\n credentials: formData.openapi?.specHttpCredentials || '',\n },\n }),\n ...(specSecurityType === 'oauth2' && {\n oauth2: {\n token: formData.openapi?.specOauth2Token || '',\n },\n }),\n };\n }\n\n return openapi;\n};\n\nexport const buildServerPayload = ({\n formData,\n serverType,\n envVars,\n headerVars,\n}: BuildServerPayloadInput) => {\n const env = buildKeyValueRecord(envVars);\n const headers = buildKeyValueRecord(headerVars);\n const options = buildOptions(formData.options);\n const description = formData.description?.trim() || '';\n\n const config: Partial<ServerConfig> = {\n type: serverType,\n description,\n options,\n visibility: formData.visibility ?? 'private',\n sharedWithUsers:\n formData.visibility === 'group' ? normalizeSharedUsers(formData.sharedWithUsers) : undefined,\n credentialTemplate: formData.credentialTemplate?.map((slot) => ({\n ...slot,\n target: serverType === 'stdio' ? 'env' : 'headers',\n })),\n perSessionClient: formData.perSessionClient === true ? true : undefined,\n startOnDemand: formData.startOnDemand === true ? true : undefined,\n idleTimeoutMs:\n formData.startOnDemand === true || formData.credentialTemplate?.length\n ? (formData.idleTimeoutMs ?? 300000)\n : undefined,\n // Round-trip the stored proxychains config (no in-form editor) so an edit\n // of any other field does not drop it and force an avoidable reload.\n proxy: formData.proxy,\n };\n\n if (serverType === 'openapi') {\n config.headers = headers;\n config.openapi = buildOpenApiConfig(formData);\n } else if (serverType === 'sse' || serverType === 'streamable-http') {\n const keepAliveEnabled = formData.keepAlive?.enabled === true;\n\n config.url = formData.url.trim();\n config.env = env;\n config.headers = headers;\n config.passthroughHeaders = parseCommaSeparatedList(formData.passthroughHeaders);\n config.oauth = buildOAuthConfig(formData.oauth);\n config.enableKeepAlive = keepAliveEnabled;\n config.keepAliveInterval = keepAliveEnabled ? formData.keepAlive?.interval || 60000 : undefined;\n } else {\n config.command = formData.command.trim();\n config.args = formData.args;\n config.env = env;\n }\n\n return {\n name: formData.name.trim(),\n config,\n };\n};\n","export const getSelectableShareUsers = (\n selectedUsers: readonly string[] = [],\n shareCandidates: readonly string[] = [],\n): string[] =>\n Array.from(new Set([...selectedUsers, ...shareCandidates])).sort((left, right) =>\n left.localeCompare(right),\n );\n\nexport const filterShareUsers = (users: readonly string[], query: string): string[] => {\n const normalizedQuery = query.trim().toLowerCase();\n if (!normalizedQuery) {\n return [...users];\n }\n\n return users.filter((username) => username.toLowerCase().includes(normalizedQuery));\n};\n\nexport const selectShareUsers = (\n selectedUsers: readonly string[],\n usersToSelect: readonly string[],\n): string[] => Array.from(new Set([...selectedUsers, ...usersToSelect]));\n\nexport const deselectShareUsers = (\n selectedUsers: readonly string[],\n usersToDeselect: readonly string[],\n): string[] => {\n const usersToRemove = new Set(usersToDeselect);\n return selectedUsers.filter((username) => !usersToRemove.has(username));\n};\n","import type { OpenAPIDeclaredSecurity, ServerFormData } from '../types';\n\n/**\n * OpenAPI import security prefill (#1077).\n *\n * When a spec declares a security scheme, the import form can prefill the\n * structural fields (type, scheme, key name/location) and leave the secret for\n * the user. The contract is \"prefill only, never overwrite\": a security\n * section the user has touched is left alone, and any divergence from what the\n * spec declares is surfaced as a warning instead.\n */\n\nexport type OpenApiSecurityNoticeKind = 'info' | 'warning';\n\nexport interface OpenApiSecurityNotice {\n kind: OpenApiSecurityNoticeKind;\n /** i18n key under `server.openapi.*`. */\n messageKey:\n | 'securityPrefillNotice'\n | 'securityMismatchWarning'\n | 'securityUnsupportedNotice'\n | 'securityNotDeclared';\n values: Record<string, string>;\n}\n\n// True when the security section is still at its untouched defaults (no type\n// selected, no value fields filled). This is the only state under which the\n// spec's declared scheme may be prefilled.\nexport function isOpenApiSecurityUntouched(formData: ServerFormData, userTouched = false): boolean {\n if (userTouched) {\n return false;\n }\n\n const openapi = formData.openapi;\n if (openapi && openapi.securityType && openapi.securityType !== 'none') {\n return false;\n }\n return (\n !openapi?.apiKeyValue &&\n !openapi?.httpCredentials &&\n !openapi?.oauth2TokenUrl &&\n !openapi?.oauth2ClientId &&\n !openapi?.oauth2ClientSecret &&\n !openapi?.oauth2Token &&\n !openapi?.openIdConnectUrl &&\n !openapi?.openIdConnectToken\n );\n}\n\n// Returns a new form data with the declared scheme's structural fields filled.\n// Never fills secrets, and never touches a section the user already configured.\nexport function applyDeclaredSecurityPrefill(\n formData: ServerFormData,\n declared: OpenAPIDeclaredSecurity,\n userTouched = false,\n): ServerFormData {\n if (\n !declared.declared ||\n !declared.supported ||\n !declared.prefill ||\n !isOpenApiSecurityUntouched(formData, userTouched)\n ) {\n return formData;\n }\n const prefill = declared.prefill;\n return {\n ...formData,\n openapi: {\n ...formData.openapi,\n securityType: prefill.type,\n apiKeyName: prefill.apiKey?.name || '',\n apiKeyIn: prefill.apiKey?.in || 'header',\n apiKeyValue: '',\n httpScheme: prefill.http?.scheme || 'bearer',\n httpCredentials: '',\n oauth2TokenUrl: prefill.oauth2?.tokenUrl || '',\n oauth2ClientId: '',\n oauth2ClientSecret: '',\n oauth2Token: '',\n openIdConnectUrl: prefill.openIdConnect?.url || '',\n openIdConnectToken: '',\n },\n };\n}\n\n// Whether the user's configured security differs from what the spec declares.\n// Type-level for oauth2/openIdConnect, scheme/name-level for apiKey and http\n// (catches the http/basic vs http/bearer confusion from #1077).\nexport function securityConfigurationsDiffer(\n formData: ServerFormData,\n declared: OpenAPIDeclaredSecurity,\n): boolean {\n if (!declared.prefill) {\n return false;\n }\n const openapi = formData.openapi;\n if (openapi?.securityType !== declared.prefill.type) {\n return true;\n }\n switch (openapi?.securityType) {\n case 'apiKey':\n return (\n openapi.apiKeyName !== declared.prefill.apiKey?.name ||\n openapi.apiKeyIn !== declared.prefill.apiKey?.in\n );\n case 'http':\n return openapi.httpScheme !== declared.prefill.http?.scheme;\n default:\n // oauth2 / openIdConnect: matching the type is close enough to consider\n // the configuration aligned; the endpoint fields are form details.\n return false;\n }\n}\n\n// Short human description of the user's current security selection, used in\n// the mismatch warning (\"…but this server is configured as …\").\nexport function describeConfiguredSecurity(formData: ServerFormData): string | null {\n const openapi = formData.openapi;\n const type = openapi?.securityType;\n if (!type || type === 'none') {\n return null;\n }\n switch (type) {\n case 'apiKey':\n return `API key in ${openapi?.apiKeyIn || 'header'} '${openapi?.apiKeyName || ''}'`;\n case 'http':\n return `HTTP ${openapi?.httpScheme || 'bearer'}`;\n case 'oauth2':\n return 'OAuth2';\n case 'openIdConnect':\n return 'OpenID Connect';\n default:\n return null;\n }\n}\n\n// Build the notice to show next to the security section, based on the declared\n// scheme and the current form state.\nexport function buildOpenApiSecurityNotice(\n formData: ServerFormData,\n declared: OpenAPIDeclaredSecurity | undefined,\n options: { includeNotDeclared?: boolean; securityTouched?: boolean } = {},\n): OpenApiSecurityNotice | null {\n if (!declared?.declared) {\n return options.includeNotDeclared\n ? { kind: 'info', messageKey: 'securityNotDeclared', values: {} }\n : null;\n }\n if (!isOpenApiSecurityUntouched(formData, options.securityTouched)) {\n if (securityConfigurationsDiffer(formData, declared)) {\n return {\n kind: 'warning',\n messageKey: 'securityMismatchWarning',\n values: {\n summary: declared.summary,\n configured: describeConfiguredSecurity(formData) || 'none',\n },\n };\n }\n }\n if (!declared.supported) {\n return {\n kind: 'warning',\n messageKey: 'securityUnsupportedNotice',\n values: { summary: declared.summary, reason: declared.unsupportedReason || '' },\n };\n }\n return {\n kind: 'info',\n messageKey: 'securityPrefillNotice',\n values: { summary: declared.summary },\n };\n}\n","import type { ServerFormData } from '../types';\n\nexport type OpenApiSourceMode = 'url' | 'schema';\n\nexport interface OpenApiSource {\n mode: OpenApiSourceMode;\n value: string;\n key: string;\n}\n\nexport function getOpenApiSource(formData: ServerFormData): OpenApiSource {\n const mode: OpenApiSourceMode = formData.openapi?.inputMode === 'schema' ? 'schema' : 'url';\n const value =\n (mode === 'schema' ? formData.openapi?.schema : formData.openapi?.url)?.trim() || '';\n\n return {\n mode,\n value,\n key: value ? `${mode}:${value}` : '',\n };\n}\n\nexport function isOpenApiSourceReady(source: OpenApiSource): boolean {\n if (!source.value) {\n return false;\n }\n\n if (source.mode === 'schema') {\n try {\n const parsed = JSON.parse(source.value);\n return parsed !== null && typeof parsed === 'object' && !Array.isArray(parsed);\n } catch {\n return false;\n }\n }\n\n try {\n const url = new URL(source.value);\n return url.protocol === 'http:' || url.protocol === 'https:';\n } catch {\n return false;\n }\n}\n\nexport function shouldAutoAnalyzeOpenApiSource(options: {\n isEdit: boolean;\n serverType: ServerFormData['type'];\n source: OpenApiSource;\n analyzedSourceKey: string | null;\n}): boolean {\n return (\n !options.isEdit &&\n options.serverType === 'openapi' &&\n isOpenApiSourceReady(options.source) &&\n options.source.key !== options.analyzedSourceKey\n );\n}\n","/**\n * Frontend server-name helpers.\n *\n * Server names become part of downstream tool identifiers\n * (`${serverName}-${toolName}`), so the MCP tool-name charset applies to them\n * indirectly. These helpers mirror the backend rule in\n * `src/utils/serverNameValidation.ts`.\n */\n\nexport const SERVER_NAME_PATTERN = /^[A-Za-z0-9._-]+$/;\n\nexport const SERVER_NAME_MAX_LENGTH = 128;\n\nexport const isValidServerName = (name: string): boolean => {\n const trimmed = name.trim();\n return (\n trimmed.length > 0 &&\n trimmed.length <= SERVER_NAME_MAX_LENGTH &&\n SERVER_NAME_PATTERN.test(trimmed) &&\n !trimmed.includes('..')\n );\n};\n\n/**\n * Turn an arbitrary string (e.g. an official Registry reverse-DNS name like\n * `io.github.user/weather`) into a charset-safe server name. Characters\n * outside `[A-Za-z0-9._-]` become `-`; consecutive dots collapse; leading /\n * trailing hyphens are trimmed and the result is length-capped. Falls back to\n * `'server'` for an empty result.\n */\nexport const slugifyServerName = (name: string): string => {\n const slugged = name\n .replace(/[^A-Za-z0-9._-]+/g, '-')\n .replace(/\\.{2,}/g, '.')\n .replace(/^-+|-+$/g, '')\n .slice(0, SERVER_NAME_MAX_LENGTH);\n return slugged || 'server';\n};\n","import { useEffect, useRef, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { X } from 'lucide-react';\nimport { Server, EnvVar, ServerFormData, OpenApiToolStats } from '@/types';\nimport { apiGet, apiPost } from '../utils/fetchInterceptor';\nimport { buildServerPayload } from '../utils/serverFormPayload';\nimport {\n deselectShareUsers,\n filterShareUsers,\n getSelectableShareUsers,\n selectShareUsers,\n} from '../utils/shareUserSelection.js';\nimport { OPENAPI_STATS_WARN_TOKENS, formatBytes, formatTokens } from '../utils/contextCost';\nimport {\n applyDeclaredSecurityPrefill,\n buildOpenApiSecurityNotice,\n type OpenApiSecurityNotice,\n} from '../utils/openApiSecurityPrefill';\nimport {\n getOpenApiSource,\n isOpenApiSourceReady,\n shouldAutoAnalyzeOpenApiSource,\n} from '../utils/openApiSourceAnalysis';\nimport {\n isValidServerName,\n SERVER_NAME_MAX_LENGTH,\n SERVER_NAME_PATTERN,\n} from '../utils/serverName';\n\ninterface ServerFormProps {\n onSubmit: (payload: any) => void;\n onCancel: () => void;\n initialData?: Server | null;\n modalTitle: string;\n formError?: string | null;\n /**\n * Which flow this form drives. `initialData` pre-fills the form for the edit\n * flow *and* for create flows that start from an existing configuration\n * (marketplace/registry install, duplicate), so it cannot decide this on its\n * own: it defaults to 'edit' when `initialData` is set, matching the install\n * forms, and callers that create a server pass 'create' explicitly.\n */\n mode?: 'create' | 'edit';\n /**\n * Server whose share candidates the visibility picker loads. Defaults to\n * `initialData.name`, which is right for the edit flow; the duplicate flow\n * points it at the source server because the copy does not exist yet (#1187).\n */\n shareCandidatesFrom?: string | null;\n}\n\nconst ServerForm = ({\n onSubmit,\n onCancel,\n initialData = null,\n modalTitle,\n formError = null,\n mode,\n shareCandidatesFrom = null,\n}: ServerFormProps) => {\n const { t } = useTranslation();\n\n // Native `pattern`/`maxLength` on the name field are enforced on create and\n // on edit of an already-valid name. Editing a legacy (invalid) name without\n // changing it stays allowed, mirroring the backend create/rename-only rule.\n const enforceNamePattern = !initialData?.name || isValidServerName(initialData.name);\n\n // Determine the initial server type from the initialData\n const getInitialServerType = () => {\n if (!initialData || !initialData.config) return 'stdio';\n\n if (initialData.config.type) {\n return initialData.config.type; // Use explicit type if available\n } else if (initialData.config.url) {\n return 'sse'; // Fallback to SSE if URL exists\n } else {\n return 'stdio'; // Default to stdio\n }\n };\n\n const getInitialServerEnvVars = (data: Server | null): EnvVar[] => {\n if (!data || !data.config || !data.config.env) return [];\n\n return Object.entries(data.config.env).map(([key, value]) => ({\n key,\n value,\n description: '', // You can set a default description if needed\n }));\n };\n\n const getInitialOAuthConfig = (data: Server | null): ServerFormData['oauth'] => {\n const oauth = data?.config?.oauth;\n return {\n clientId: oauth?.clientId || '',\n clientSecret: oauth?.clientSecret || '',\n scopes: oauth?.scopes ? oauth.scopes.join(' ') : '',\n accessToken: oauth?.accessToken || '',\n refreshToken: oauth?.refreshToken || '',\n authorizationEndpoint: oauth?.authorizationEndpoint || '',\n tokenEndpoint: oauth?.tokenEndpoint || '',\n resource: oauth?.resource || '',\n };\n };\n\n const [serverType, setServerType] = useState<'stdio' | 'sse' | 'streamable-http' | 'openapi'>(\n getInitialServerType(),\n );\n\n const [formData, setFormData] = useState<ServerFormData>({\n name: (initialData && initialData.name) || '',\n description: (initialData && initialData.config && initialData.config.description) || '',\n url: (initialData && initialData.config && initialData.config.url) || '',\n command: (initialData && initialData.config && initialData.config.command) || '',\n arguments:\n initialData && initialData.config && initialData.config.args\n ? Array.isArray(initialData.config.args)\n ? initialData.config.args.join(' ')\n : String(initialData.config.args)\n : '',\n args: (initialData && initialData.config && initialData.config.args) || [],\n type: getInitialServerType(), // Initialize the type field\n env: getInitialServerEnvVars(initialData),\n headers: [],\n passthroughHeaders: initialData?.config?.passthroughHeaders?.join(', ') || '',\n visibility: (initialData?.config?.visibility ?? 'private') as 'private' | 'group' | 'public',\n sharedWithUsers: initialData?.config?.sharedWithUsers || [],\n options: {\n timeout:\n (initialData &&\n initialData.config &&\n initialData.config.options &&\n initialData.config.options.timeout) ||\n 60000,\n resetTimeoutOnProgress: initialData?.config?.options?.resetTimeoutOnProgress ?? true,\n maxTotalTimeout:\n (initialData &&\n initialData.config &&\n initialData.config.options &&\n initialData.config.options.maxTotalTimeout) ||\n undefined,\n },\n oauth: getInitialOAuthConfig(initialData),\n // KeepAlive configuration initialization\n keepAlive: {\n enabled: initialData?.config?.enableKeepAlive === true,\n interval: initialData?.config?.keepAliveInterval || 60000,\n },\n // Per-session client isolation initialization\n perSessionClient: initialData?.config?.perSessionClient === true,\n credentialTemplate: initialData?.config?.credentialTemplate || [],\n // Proxychains proxy config: round-trip the stored value so editing the\n // server does not silently drop it (there is no in-form editor for it).\n proxy: initialData?.config?.proxy,\n // On-demand spawning initialization\n startOnDemand: initialData?.config?.startOnDemand === true,\n idleTimeoutMs: initialData?.config?.idleTimeoutMs ?? 300000,\n // OpenAPI configuration initialization\n openapi:\n initialData && initialData.config && initialData.config.openapi\n ? {\n url: initialData.config.openapi.url || '',\n schema: initialData.config.openapi.schema\n ? JSON.stringify(initialData.config.openapi.schema, null, 2)\n : '',\n inputMode: initialData.config.openapi.url\n ? 'url'\n : initialData.config.openapi.schema\n ? 'schema'\n : 'url',\n version: initialData.config.openapi.version || '3.1.0',\n securityType: initialData.config.openapi.security?.type || 'none',\n // API Key initialization\n apiKeyName: initialData.config.openapi.security?.apiKey?.name || '',\n apiKeyIn: initialData.config.openapi.security?.apiKey?.in || 'header',\n apiKeyValue: initialData.config.openapi.security?.apiKey?.value || '',\n // HTTP auth initialization\n httpScheme: initialData.config.openapi.security?.http?.scheme || 'bearer',\n httpCredentials: initialData.config.openapi.security?.http?.credentials || '',\n // OAuth2 initialization\n oauth2TokenUrl: initialData.config.openapi.security?.oauth2?.tokenUrl || '',\n oauth2ClientId: initialData.config.openapi.security?.oauth2?.clientId || '',\n oauth2ClientSecret: initialData.config.openapi.security?.oauth2?.clientSecret || '',\n oauth2Token: initialData.config.openapi.security?.oauth2?.token || '',\n // OpenID Connect initialization\n openIdConnectUrl: initialData.config.openapi.security?.openIdConnect?.url || '',\n openIdConnectToken: initialData.config.openapi.security?.openIdConnect?.token || '',\n // Spec-download security initialization (#1079)\n specSecurityType: ['apiKey', 'http', 'oauth2'].includes(\n initialData.config.openapi.specSecurity?.type as string,\n )\n ? (initialData.config.openapi.specSecurity!.type as 'apiKey' | 'http' | 'oauth2')\n : 'none',\n specApiKeyName: initialData.config.openapi.specSecurity?.apiKey?.name || '',\n specApiKeyIn: initialData.config.openapi.specSecurity?.apiKey?.in || 'header',\n specApiKeyValue: initialData.config.openapi.specSecurity?.apiKey?.value || '',\n specHttpScheme:\n initialData.config.openapi.specSecurity?.http?.scheme === 'bearer'\n ? 'bearer'\n : 'basic',\n specHttpCredentials: initialData.config.openapi.specSecurity?.http?.credentials || '',\n specOauth2Token: initialData.config.openapi.specSecurity?.oauth2?.token || '',\n // Passthrough headers initialization\n passthroughHeaders: initialData.config.openapi.passthroughHeaders\n ? initialData.config.openapi.passthroughHeaders.join(', ')\n : '',\n cookieSession: initialData.config.openapi.cookieSession === true,\n }\n : {\n inputMode: 'url',\n url: '',\n schema: '',\n version: '3.1.0',\n securityType: 'none',\n specSecurityType: 'none',\n passthroughHeaders: '',\n cookieSession: false,\n },\n });\n\n const [shareCandidates, setShareCandidates] = useState<string[]>([]);\n const [shareCandidatesLoading, setShareCandidatesLoading] = useState(false);\n const [shareCandidatesError, setShareCandidatesError] = useState(false);\n const [shareUserSearch, setShareUserSearch] = useState('');\n\n const shareCandidatesServer = shareCandidatesFrom || initialData?.name;\n\n useEffect(() => {\n if (formData.visibility !== 'group' || !shareCandidatesServer) {\n return;\n }\n\n let cancelled = false;\n setShareCandidatesLoading(true);\n setShareCandidatesError(false);\n\n void apiGet<{ success: boolean; data?: string[] }>(\n `/servers/${encodeURIComponent(shareCandidatesServer)}/share-candidates`,\n )\n .then((response) => {\n if (cancelled) return;\n\n if (response.success && Array.isArray(response.data)) {\n setShareCandidates(response.data);\n } else {\n setShareCandidatesError(true);\n }\n })\n .catch(() => {\n if (!cancelled) {\n setShareCandidatesError(true);\n }\n })\n .finally(() => {\n if (!cancelled) {\n setShareCandidatesLoading(false);\n }\n });\n\n return () => {\n cancelled = true;\n };\n }, [formData.visibility, shareCandidatesServer]);\n\n const selectableShareUsers = getSelectableShareUsers(\n formData.sharedWithUsers || [],\n shareCandidates,\n );\n const filteredShareUsers = filterShareUsers(selectableShareUsers, shareUserSearch);\n const selectedShareUsers = new Set(formData.sharedWithUsers || []);\n const allFilteredShareUsersSelected =\n filteredShareUsers.length > 0 &&\n filteredShareUsers.every((username) => selectedShareUsers.has(username));\n const noFilteredShareUsersSelected =\n filteredShareUsers.length === 0 ||\n filteredShareUsers.every((username) => !selectedShareUsers.has(username));\n\n const toggleSharedUser = (username: string) => {\n setFormData((previous) => {\n const selected = new Set(previous.sharedWithUsers || []);\n if (selected.has(username)) {\n selected.delete(username);\n } else {\n selected.add(username);\n }\n return { ...previous, sharedWithUsers: Array.from(selected) };\n });\n };\n\n const selectFilteredShareUsers = () => {\n setFormData((previous) => ({\n ...previous,\n sharedWithUsers: selectShareUsers(previous.sharedWithUsers || [], filteredShareUsers),\n }));\n };\n\n const deselectFilteredShareUsers = () => {\n setFormData((previous) => ({\n ...previous,\n sharedWithUsers: deselectShareUsers(previous.sharedWithUsers || [], filteredShareUsers),\n }));\n };\n\n const [envVars, setEnvVars] = useState<EnvVar[]>(\n initialData && initialData.config && initialData.config.env\n ? Object.entries(initialData.config.env).map(([key, value]) => ({ key, value }))\n : [],\n );\n\n const [headerVars, setHeaderVars] = useState<EnvVar[]>(\n initialData && initialData.config && initialData.config.headers\n ? Object.entries(initialData.config.headers).map(([key, value]) => ({ key, value }))\n : [],\n );\n\n // ── OpenAPI source analysis (#1082, #1093) ────────────────────────────────\n // Analyze a new OpenAPI source while the form is being filled. The result is\n // advisory and is shown inline, so submitting the form does not replace the\n // user's current state with a stale async payload.\n const [openApiStats, setOpenApiStats] = useState<OpenApiToolStats | null>(null);\n const [openApiStatsLoading, setOpenApiStatsLoading] = useState(false);\n const [openApiStatsUnavailable, setOpenApiStatsUnavailable] = useState(false);\n const openApiStatsRequestId = useRef(0);\n const analyzedOpenApiSourceKey = useRef<string | null>(null);\n const automaticSecurityAnalysisDone = useRef(false);\n const openApiSecurityTouched = useRef(Boolean(initialData));\n const openApiFormDataRef = useRef(formData);\n openApiFormDataRef.current = formData;\n const openApiEnvVarsRef = useRef(envVars);\n openApiEnvVarsRef.current = envVars;\n const openApiHeaderVarsRef = useRef(headerVars);\n openApiHeaderVarsRef.current = headerVars;\n const [openApiSecurityNotice, setOpenApiSecurityNotice] = useState<OpenApiSecurityNotice | null>(\n null,\n );\n const [securityDetectionLoading, setSecurityDetectionLoading] = useState(false);\n\n const [isRequestOptionsExpanded, setIsRequestOptionsExpanded] = useState<boolean>(false);\n const [isOAuthSectionExpanded, setIsOAuthSectionExpanded] = useState<boolean>(false);\n const [isKeepAliveSectionExpanded, setIsKeepAliveSectionExpanded] = useState<boolean>(false);\n const [isAdvancedExpanded, setIsAdvancedExpanded] = useState<boolean>(false);\n const [error, setError] = useState<string | null>(null);\n const isEdit = mode ? mode === 'edit' : !!initialData;\n\n const markOpenApiSecurityTouched = () => {\n openApiSecurityTouched.current = true;\n setOpenApiSecurityNotice(null);\n };\n\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const { name, value } = e.target;\n setFormData({ ...formData, [name]: value });\n };\n\n // Transform space-separated arguments string into array\n const handleArgsChange = (value: string) => {\n const args = value.split(' ').filter((arg) => arg.trim() !== '');\n setFormData({ ...formData, arguments: value, args });\n };\n\n const updateServerType = (type: 'stdio' | 'sse' | 'streamable-http' | 'openapi') => {\n setServerType(type);\n setFormData((prev) => ({ ...prev, type }));\n };\n\n const handleEnvVarChange = (index: number, field: 'key' | 'value', value: string) => {\n const newEnvVars = [...envVars];\n newEnvVars[index][field] = value;\n setEnvVars(newEnvVars);\n };\n\n const addEnvVar = () => {\n setEnvVars([...envVars, { key: '', value: '' }]);\n };\n\n const removeEnvVar = (index: number) => {\n const newEnvVars = [...envVars];\n newEnvVars.splice(index, 1);\n setEnvVars(newEnvVars);\n };\n\n const handleHeaderVarChange = (index: number, field: 'key' | 'value', value: string) => {\n const newHeaderVars = [...headerVars];\n newHeaderVars[index][field] = value;\n setHeaderVars(newHeaderVars);\n };\n\n const addHeaderVar = () => {\n setHeaderVars([...headerVars, { key: '', value: '' }]);\n };\n\n const removeHeaderVar = (index: number) => {\n const newHeaderVars = [...headerVars];\n newHeaderVars.splice(index, 1);\n setHeaderVars(newHeaderVars);\n };\n\n const handleOAuthChange = <K extends keyof NonNullable<ServerFormData['oauth']>>(\n field: K,\n value: string,\n ) => {\n setFormData((prev) => ({\n ...prev,\n oauth: {\n ...(prev.oauth || {}),\n [field]: value,\n },\n }));\n };\n\n // Handle options changes\n const handleOptionsChange = (\n field: 'timeout' | 'resetTimeoutOnProgress' | 'maxTotalTimeout',\n value: number | boolean | undefined,\n ) => {\n setFormData((prev) => ({\n ...prev,\n options: {\n ...prev.options,\n [field]: value,\n },\n }));\n };\n\n // Shared probe used by automatic source analysis and the explicit retry\n // button. Returns the preview data (including the declared security scheme)\n // or null when the spec cannot be analyzed.\n const runOpenApiSecurityDetection = async (\n payload: ReturnType<typeof buildServerPayload>,\n ): Promise<OpenApiToolStats | null> => {\n try {\n const response = await apiPost<{ success: boolean; data?: OpenApiToolStats }>(\n '/servers/openapi/tool-stats',\n { config: payload.config },\n { signal: AbortSignal.timeout(60000) },\n );\n return response.success && response.data ? response.data : null;\n } catch {\n // The form remains usable when the advisory request fails.\n return null;\n }\n };\n\n const analyzeOpenApiSource = async (\n payload: ReturnType<typeof buildServerPayload>,\n sourceKey: string,\n options: { allowSecurityPrefill: boolean; consumeAutomaticAnalysis: boolean },\n ) => {\n const requestId = ++openApiStatsRequestId.current;\n setOpenApiStatsLoading(true);\n setOpenApiStatsUnavailable(false);\n\n const data = await runOpenApiSecurityDetection(payload);\n if (openApiStatsRequestId.current !== requestId) return;\n\n if (!data) {\n setOpenApiStatsUnavailable(true);\n setOpenApiStatsLoading(false);\n return;\n }\n\n analyzedOpenApiSourceKey.current = sourceKey;\n setOpenApiStats(data);\n\n const latestFormData = openApiFormDataRef.current;\n const securityTouched = openApiSecurityTouched.current;\n const declared = data.declaredSecurity;\n const canPrefillSecurity =\n options.allowSecurityPrefill &&\n !securityTouched &&\n !isEdit &&\n !automaticSecurityAnalysisDone.current;\n\n if (options.consumeAutomaticAnalysis) {\n automaticSecurityAnalysisDone.current = true;\n }\n\n const nextFormData =\n declared?.declared && declared.supported && canPrefillSecurity\n ? applyDeclaredSecurityPrefill(latestFormData, declared, securityTouched)\n : latestFormData;\n\n if (nextFormData !== latestFormData) {\n openApiFormDataRef.current = nextFormData;\n setFormData(nextFormData);\n }\n\n setOpenApiSecurityNotice(\n buildOpenApiSecurityNotice(latestFormData, declared, {\n includeNotDeclared: true,\n securityTouched,\n }),\n );\n setOpenApiStatsLoading(false);\n };\n\n // Explicit retry button for cases where automatic analysis failed or the\n // user wants to inspect the current source again.\n const detectOpenApiSecurity = async () => {\n setSecurityDetectionLoading(true);\n try {\n const payload = buildServerPayload({ formData, serverType, envVars, headerVars });\n await analyzeOpenApiSource(payload, getOpenApiSource(formData).key, {\n allowSecurityPrefill: !isEdit && !openApiSecurityTouched.current,\n consumeAutomaticAnalysis: false,\n });\n } catch {\n // Advisory only.\n } finally {\n setSecurityDetectionLoading(false);\n }\n };\n\n const openApiSource = getOpenApiSource(formData);\n const openApiSourcePresent = serverType === 'openapi' && isOpenApiSourceReady(openApiSource);\n\n useEffect(() => {\n openApiStatsRequestId.current += 1;\n setOpenApiStats(null);\n setOpenApiStatsUnavailable(false);\n setOpenApiStatsLoading(false);\n setOpenApiSecurityNotice(null);\n\n if (\n !shouldAutoAnalyzeOpenApiSource({\n isEdit,\n serverType,\n source: openApiSource,\n analyzedSourceKey: analyzedOpenApiSourceKey.current,\n })\n ) {\n return;\n }\n\n setOpenApiStatsLoading(true);\n const timeoutId = window.setTimeout(() => {\n const payload = buildServerPayload({\n formData: openApiFormDataRef.current,\n serverType,\n envVars: openApiEnvVarsRef.current,\n headerVars: openApiHeaderVarsRef.current,\n });\n void analyzeOpenApiSource(payload, openApiSource.key, {\n allowSecurityPrefill: true,\n consumeAutomaticAnalysis: true,\n });\n }, 600);\n\n return () => {\n window.clearTimeout(timeoutId);\n };\n }, [isEdit, openApiSource.key, serverType]);\n\n // Submit handler for server configuration\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n setError(null);\n\n // Server names become part of downstream tool identifiers, so they must\n // satisfy the MCP tool-name charset. Mirror the backend rule: enforce on\n // create and on rename, but let a no-op edit of a legacy (invalid) name\n // through so existing working installations can still be maintained.\n const isNameChanging = !initialData?.name || formData.name !== initialData.name;\n if (isNameChanging && !isValidServerName(formData.name)) {\n setError(t('server.nameInvalid'));\n return;\n }\n\n try {\n const payload = buildServerPayload({\n formData,\n serverType,\n envVars,\n headerVars,\n });\n\n onSubmit(payload);\n } catch (err) {\n setError(`Error: ${err instanceof Error ? err.message : String(err)}`);\n }\n };\n\n return (\n <div className=\"hub-card p-6 w-full max-w-3xl max-h-screen overflow-y-auto\">\n <div className=\"flex justify-between items-center mb-5\">\n <h2 className=\"text-lg font-semibold text-[var(--hub-ink)]\">{modalTitle}</h2>\n <button onClick={onCancel} className=\"hub-icon-btn\" aria-label=\"Close\">\n <X size={16} />\n </button>\n </div>\n\n {(error || formError) && (\n <div className=\"bg-red-50 text-red-700 p-3 rounded mb-4\">{formError || error}</div>\n )}\n\n <form onSubmit={handleSubmit}>\n {/* ─── Section 1: Basic Info ─── */}\n <div className=\"mb-5\">\n <h3 className=\"text-sm font-semibold text-[var(--hub-ink)] mb-3 pb-2 border-b border-gray-200 dark:border-gray-700\">\n {t('server.sectionBasicInfo', 'Basic Info')}\n </h3>\n\n <div className=\"grid grid-cols-1 md:grid-cols-3 gap-4 mb-4\">\n <div className=\"md:col-span-1\">\n <label\n className=\"block text-sm font-medium mb-1.5 text-[var(--hub-ink-2)]\"\n htmlFor=\"name\"\n >\n {t('server.name')}\n </label>\n <input\n type=\"text\"\n name=\"name\"\n id=\"name\"\n value={formData.name}\n onChange={handleInputChange}\n className=\"w-full py-2 px-3 form-input\"\n placeholder=\"e.g.: time-mcp\"\n pattern={enforceNamePattern ? SERVER_NAME_PATTERN.source : undefined}\n maxLength={enforceNamePattern ? SERVER_NAME_MAX_LENGTH : undefined}\n title={t('server.nameInvalid')}\n required\n />\n <p className=\"text-xs text-[var(--hub-ink-3)] mt-1\">{t('server.nameInvalid')}</p>\n </div>\n\n <div className=\"md:col-span-2\">\n <label\n className=\"block text-sm font-medium mb-1.5 text-[var(--hub-ink-2)]\"\n htmlFor=\"description\"\n >\n {t('server.description')}\n </label>\n <input\n type=\"text\"\n name=\"description\"\n id=\"description\"\n value={formData.description || ''}\n onChange={handleInputChange}\n className=\"w-full py-2 px-3 form-input\"\n placeholder={t('server.descriptionPlaceholder')}\n />\n </div>\n </div>\n </div>\n\n {/* ─── Section 2: Connection ─── */}\n <div className=\"mb-5\">\n <h3 className=\"text-sm font-semibold text-[var(--hub-ink)] mb-3 pb-2 border-b border-gray-200 dark:border-gray-700\">\n {t('server.sectionConnection', 'Connection')}\n </h3>\n\n <div className=\"mb-4\">\n <label className=\"block text-sm font-medium mb-1.5 text-[var(--hub-ink-2)]\">\n {t('server.type')}\n </label>\n <div className=\"flex flex-wrap gap-x-4 gap-y-2\">\n <div>\n <input\n type=\"radio\"\n id=\"command\"\n name=\"serverType\"\n value=\"command\"\n checked={serverType === 'stdio'}\n onChange={() => updateServerType('stdio')}\n className=\"mr-1\"\n />\n <label htmlFor=\"command\" className=\"text-[var(--hub-ink)]\">\n {t('server.typeStdio')}\n </label>\n </div>\n <div>\n <input\n type=\"radio\"\n id=\"url\"\n name=\"serverType\"\n value=\"url\"\n checked={serverType === 'sse'}\n onChange={() => updateServerType('sse')}\n className=\"mr-1\"\n />\n <label htmlFor=\"url\" className=\"text-[var(--hub-ink)]\">\n {t('server.typeSse')}\n </label>\n </div>\n <div>\n <input\n type=\"radio\"\n id=\"streamable-http\"\n name=\"serverType\"\n value=\"streamable-http\"\n checked={serverType === 'streamable-http'}\n onChange={() => updateServerType('streamable-http')}\n className=\"mr-1\"\n />\n <label htmlFor=\"streamable-http\" className=\"text-[var(--hub-ink)]\">\n {t('server.typeStreamableHttp')}\n </label>\n </div>\n <div>\n <input\n type=\"radio\"\n id=\"openapi\"\n name=\"serverType\"\n value=\"openapi\"\n checked={serverType === 'openapi'}\n onChange={() => updateServerType('openapi')}\n className=\"mr-1\"\n />\n <label htmlFor=\"openapi\" className=\"text-[var(--hub-ink)]\">\n {t('server.typeOpenapi')}\n </label>\n </div>\n </div>\n </div>\n\n {/* Connection details — indented to show hierarchy under Server Type */}\n <div className=\"pl-4 border-l-2 border-gray-200 dark:border-gray-700 ml-2\">\n {serverType === 'openapi' ? (\n <>\n {/* Input Mode Selection */}\n <div className=\"mb-4\">\n <label className=\"block text-sm font-medium mb-1.5 text-[var(--hub-ink-2)]\">\n {t('server.openapi.inputMode')}\n </label>\n <div className=\"flex space-x-4\">\n <div>\n <input\n type=\"radio\"\n id=\"input-mode-url\"\n name=\"inputMode\"\n value=\"url\"\n checked={formData.openapi?.inputMode === 'url'}\n onChange={() =>\n setFormData((prev) => ({\n ...prev,\n openapi: { ...prev.openapi!, inputMode: 'url' },\n }))\n }\n className=\"mr-1\"\n />\n <label htmlFor=\"input-mode-url\">{t('server.openapi.inputModeUrl')}</label>\n </div>\n <div>\n <input\n type=\"radio\"\n id=\"input-mode-schema\"\n name=\"inputMode\"\n value=\"schema\"\n checked={formData.openapi?.inputMode === 'schema'}\n onChange={() =>\n setFormData((prev) => ({\n ...prev,\n openapi: { ...prev.openapi!, inputMode: 'schema' },\n }))\n }\n className=\"mr-1\"\n />\n <label htmlFor=\"input-mode-schema\">\n {t('server.openapi.inputModeSchema')}\n </label>\n </div>\n </div>\n </div>\n\n {/* URL Input */}\n {formData.openapi?.inputMode === 'url' && (\n <div className=\"mb-4\">\n <label\n className=\"block text-sm font-medium mb-1.5 text-[var(--hub-ink-2)]\"\n htmlFor=\"openapi-url\"\n >\n {t('server.openapi.specUrl')}\n </label>\n <input\n type=\"url\"\n name=\"openapi-url\"\n id=\"openapi-url\"\n value={formData.openapi?.url || ''}\n onChange={(e) =>\n setFormData((prev) => ({\n ...prev,\n openapi: { ...prev.openapi!, url: e.target.value },\n }))\n }\n className=\"w-full py-2 px-3 form-input\"\n placeholder=\"e.g.: https://api.example.com/openapi.json\"\n required={serverType === 'openapi' && formData.openapi?.inputMode === 'url'}\n />\n </div>\n )}\n\n {/* Schema Input */}\n {formData.openapi?.inputMode === 'schema' && (\n <div className=\"mb-4\">\n <label\n className=\"block text-sm font-medium mb-1.5 text-[var(--hub-ink-2)]\"\n htmlFor=\"openapi-schema\"\n >\n {t('server.openapi.schema')}\n </label>\n <textarea\n name=\"openapi-schema\"\n id=\"openapi-schema\"\n rows={10}\n value={formData.openapi?.schema || ''}\n onChange={(e) =>\n setFormData((prev) => ({\n ...prev,\n openapi: { ...prev.openapi!, schema: e.target.value },\n }))\n }\n className=\"w-full py-2 px-3 form-input font-mono text-sm\"\n placeholder={`{\n \"openapi\": \"3.1.0\",\n \"info\": {\n \"title\": \"API\",\n \"version\": \"1.0.0\"\n },\n \"servers\": [\n {\n \"url\": \"https://api.example.com\"\n }\n ],\n \"paths\": {\n ...\n }\n}`}\n required={\n serverType === 'openapi' && formData.openapi?.inputMode === 'schema'\n }\n />\n <p className=\"text-xs text-[var(--hub-ink-3)] mt-1\">\n {t('server.openapi.schemaHelp')}\n </p>\n </div>\n )}\n\n {!isEdit && openApiSourcePresent && (\n <div\n className=\"mb-4 rounded border border-blue-200 bg-blue-50 p-3 text-sm dark:border-blue-900 dark:bg-blue-950/30\"\n aria-live=\"polite\"\n >\n {openApiStatsLoading ? (\n <p className=\"text-blue-700 dark:text-blue-300\">\n {t('server.openapi.statsMeasuring')}\n </p>\n ) : openApiStats ? (\n <>\n <p className=\"font-medium text-blue-900 dark:text-blue-100\">\n {t('server.openapi.statsSummary', {\n toolCount: openApiStats.toolCount,\n bytes: formatBytes(openApiStats.definitionsBytes),\n tokens: formatTokens(openApiStats.estimatedTokens),\n })}\n </p>\n {openApiStats.estimatedTokens >= OPENAPI_STATS_WARN_TOKENS && (\n <p className=\"mt-1 text-yellow-700 dark:text-yellow-300\">\n {t('server.openapi.statsWarning')}\n </p>\n )}\n </>\n ) : openApiStatsUnavailable ? (\n <p className=\"text-gray-600 dark:text-gray-300\">\n {t('server.openapi.statsUnavailable')}\n </p>\n ) : null}\n </div>\n )}\n\n {/* Security Configuration */}\n <div className=\"mb-4\" onChange={markOpenApiSecurityTouched}>\n <div className=\"flex items-center justify-between mb-1.5\">\n <label className=\"block text-sm font-medium text-[var(--hub-ink-2)]\">\n {t('server.openapi.security')}\n </label>\n <button\n type=\"button\"\n onClick={() => void detectOpenApiSecurity()}\n disabled={\n securityDetectionLoading || openApiStatsLoading || !openApiSourcePresent\n }\n className=\"hub-btn text-xs !h-7 !px-2\"\n >\n {securityDetectionLoading || openApiStatsLoading\n ? t('server.openapi.securityDetecting')\n : t('server.openapi.securityDetect')}\n </button>\n </div>\n <select\n value={formData.openapi?.securityType || 'none'}\n onChange={(e) =>\n setFormData((prev) => {\n setOpenApiSecurityNotice(null);\n return {\n ...prev,\n openapi: {\n ...prev.openapi,\n securityType: e.target.value as any,\n url: prev.openapi?.url || '',\n },\n };\n })\n }\n className=\"w-full py-2 px-3 form-input\"\n >\n <option value=\"none\">{t('server.openapi.securityNone')}</option>\n <option value=\"apiKey\">{t('server.openapi.securityApiKey')}</option>\n <option value=\"http\">{t('server.openapi.securityHttp')}</option>\n <option value=\"oauth2\">{t('server.openapi.securityOAuth2')}</option>\n <option value=\"openIdConnect\">\n {t('server.openapi.securityOpenIdConnect')}\n </option>\n </select>\n {openApiSecurityNotice && (\n <p\n className={`mt-2 text-xs ${\n openApiSecurityNotice.kind === 'warning'\n ? 'text-yellow-700 dark:text-yellow-300'\n : 'text-blue-700 dark:text-blue-300'\n }`}\n >\n {t(\n `server.openapi.${openApiSecurityNotice.messageKey}`,\n openApiSecurityNotice.values,\n )}\n </p>\n )}\n </div>\n\n {/* API Key Configuration */}\n {formData.openapi?.securityType === 'apiKey' && (\n <div className=\"mb-4 p-4 border border-gray-200 dark:border-gray-700 rounded bg-gray-50 dark:bg-gray-800\">\n <h4 className=\"text-sm font-medium mb-3 text-[var(--hub-ink-2)]\">\n {t('server.openapi.apiKeyConfig')}\n </h4>\n <div className=\"grid grid-cols-1 md:grid-cols-3 gap-3\">\n <div>\n <label className=\"block text-xs text-[var(--hub-ink-2)] mb-1\">\n {t('server.openapi.apiKeyName')}\n </label>\n <input\n type=\"text\"\n value={formData.openapi?.apiKeyName || ''}\n onChange={(e) =>\n setFormData((prev) => ({\n ...prev,\n openapi: {\n ...prev.openapi,\n apiKeyName: e.target.value,\n url: prev.openapi?.url || '',\n },\n }))\n }\n className=\"w-full border rounded px-2 py-1 text-sm form-input focus:outline-none\"\n placeholder=\"Authorization\"\n />\n </div>\n <div>\n <label className=\"block text-xs text-[var(--hub-ink-2)] mb-1\">\n {t('server.openapi.apiKeyIn')}\n </label>\n <select\n value={formData.openapi?.apiKeyIn || 'header'}\n onChange={(e) =>\n setFormData((prev) => ({\n ...prev,\n openapi: {\n ...prev.openapi,\n apiKeyIn: e.target.value as any,\n url: prev.openapi?.url || '',\n },\n }))\n }\n className=\"w-full border rounded px-2 py-1 text-sm focus:outline-none form-input\"\n >\n <option value=\"header\">{t('server.openapi.apiKeyInHeader')}</option>\n <option value=\"query\">{t('server.openapi.apiKeyInQuery')}</option>\n <option value=\"cookie\">{t('server.openapi.apiKeyInCookie')}</option>\n </select>\n </div>\n <div>\n <label className=\"block text-xs text-gray-600 mb-1\">\n {t('server.openapi.apiKeyValue')}\n </label>\n <input\n type=\"password\"\n value={formData.openapi?.apiKeyValue || ''}\n onChange={(e) =>\n setFormData((prev) => ({\n ...prev,\n openapi: {\n ...prev.openapi,\n apiKeyValue: e.target.value,\n url: prev.openapi?.url || '',\n },\n }))\n }\n className=\"w-full border rounded px-2 py-1 text-sm focus:outline-none form-input\"\n placeholder=\"your-api-key\"\n />\n </div>\n </div>\n </div>\n )}\n\n {/* HTTP Authentication Configuration */}\n {formData.openapi?.securityType === 'http' && (\n <div className=\"mb-4 p-4 border border-gray-200 dark:border-gray-700 rounded bg-gray-50 dark:bg-gray-800\">\n <h4 className=\"text-sm font-medium mb-3 text-gray-700 dark:text-gray-300\">\n {t('server.openapi.httpAuthConfig')}\n </h4>\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-3\">\n <div>\n <label className=\"block text-xs text-gray-600 mb-1\">\n {t('server.openapi.httpScheme')}\n </label>\n <select\n value={formData.openapi?.httpScheme || 'bearer'}\n onChange={(e) =>\n setFormData((prev) => ({\n ...prev,\n openapi: {\n ...prev.openapi,\n httpScheme: e.target.value as any,\n url: prev.openapi?.url || '',\n },\n }))\n }\n className=\"w-full border rounded px-2 py-1 text-sm focus:outline-none form-input\"\n >\n <option value=\"basic\">{t('server.openapi.httpSchemeBasic')}</option>\n <option value=\"bearer\">{t('server.openapi.httpSchemeBearer')}</option>\n <option value=\"digest\">{t('server.openapi.httpSchemeDigest')}</option>\n </select>\n </div>\n <div>\n <label className=\"block text-xs text-gray-600 mb-1\">\n {t('server.openapi.httpCredentials')}\n </label>\n <input\n type=\"password\"\n value={formData.openapi?.httpCredentials || ''}\n onChange={(e) =>\n setFormData((prev) => ({\n ...prev,\n openapi: {\n ...prev.openapi,\n httpCredentials: e.target.value,\n url: prev.openapi?.url || '',\n },\n }))\n }\n className=\"w-full border rounded px-2 py-1 text-sm focus:outline-none form-input\"\n placeholder={\n formData.openapi?.httpScheme === 'basic'\n ? 'user:password or base64'\n : 'bearer-token'\n }\n />\n {formData.openapi?.httpScheme === 'basic' && (\n <p className=\"text-xs text-[var(--hub-ink-3)] mt-1\">\n {t('server.openapi.httpCredentialsBasicHint')}\n </p>\n )}\n </div>\n </div>\n </div>\n )}\n\n {/* OpenID Connect Configuration */}\n {formData.openapi?.securityType === 'openIdConnect' && (\n <div className=\"mb-4 p-4 border border-gray-200 dark:border-gray-700 rounded bg-gray-50 dark:bg-gray-800\">\n <h4 className=\"text-sm font-medium mb-3 text-gray-700 dark:text-gray-300\">\n {t('server.openapi.openIdConnectConfig')}\n </h4>\n <div className=\"grid grid-cols-1 gap-3\">\n <div>\n <label className=\"block text-xs text-gray-600 mb-1\">\n {t('server.openapi.openIdConnectUrl')}\n </label>\n <input\n type=\"url\"\n value={formData.openapi?.openIdConnectUrl || ''}\n onChange={(e) =>\n setFormData((prev) => ({\n ...prev,\n openapi: {\n ...prev.openapi,\n openIdConnectUrl: e.target.value,\n url: prev.openapi?.url || '',\n },\n }))\n }\n className=\"w-full border rounded px-2 py-1 text-sm focus:outline-none form-input\"\n placeholder=\"https://example.com/.well-known/openid_configuration\"\n />\n </div>\n <div>\n <label className=\"block text-xs text-gray-600 mb-1\">\n {t('server.openapi.openIdConnectToken')}\n </label>\n <input\n type=\"password\"\n value={formData.openapi?.openIdConnectToken || ''}\n onChange={(e) =>\n setFormData((prev) => ({\n ...prev,\n openapi: {\n ...prev.openapi,\n openIdConnectToken: e.target.value,\n url: prev.openapi?.url || '',\n },\n }))\n }\n className=\"w-full border rounded px-2 py-1 text-sm focus:outline-none form-input\"\n placeholder=\"id-token\"\n />\n </div>\n </div>\n </div>\n )}\n\n {/* OAuth2 Configuration */}\n {formData.openapi?.securityType === 'oauth2' && (\n <div className=\"mb-4 p-4 border border-gray-200 dark:border-gray-700 rounded bg-gray-50 dark:bg-gray-800\">\n <h4 className=\"text-sm font-medium mb-3 text-gray-700 dark:text-gray-300\">\n {t('server.openapi.oauth2Config')}\n </h4>\n <div className=\"grid grid-cols-1 gap-3\">\n <div>\n <label className=\"block text-xs text-gray-600 mb-1\">\n {t('server.oauth.tokenEndpoint')}\n </label>\n <input\n type=\"url\"\n value={formData.openapi?.oauth2TokenUrl || ''}\n onChange={(e) =>\n setFormData((prev) => ({\n ...prev,\n openapi: {\n ...prev.openapi,\n oauth2TokenUrl: e.target.value,\n url: prev.openapi?.url || '',\n },\n }))\n }\n className=\"w-full border rounded px-2 py-1 text-sm focus:outline-none form-input\"\n placeholder=\"https://example.com/oauth/token\"\n />\n </div>\n <div>\n <label className=\"block text-xs text-gray-600 mb-1\">\n {t('server.oauth.clientId')}\n </label>\n <input\n type=\"text\"\n value={formData.openapi?.oauth2ClientId || ''}\n onChange={(e) =>\n setFormData((prev) => ({\n ...prev,\n openapi: {\n ...prev.openapi,\n oauth2ClientId: e.target.value,\n url: prev.openapi?.url || '',\n },\n }))\n }\n className=\"w-full border rounded px-2 py-1 text-sm focus:outline-none form-input\"\n placeholder=\"client-id\"\n />\n </div>\n <div>\n <label className=\"block text-xs text-gray-600 mb-1\">\n {t('server.oauth.clientSecret')}\n </label>\n <input\n type=\"password\"\n value={formData.openapi?.oauth2ClientSecret || ''}\n onChange={(e) =>\n setFormData((prev) => ({\n ...prev,\n openapi: {\n ...prev.openapi,\n oauth2ClientSecret: e.target.value,\n url: prev.openapi?.url || '',\n },\n }))\n }\n className=\"w-full border rounded px-2 py-1 text-sm focus:outline-none form-input\"\n placeholder=\"client-secret\"\n />\n </div>\n <div>\n <label className=\"block text-xs text-gray-600 mb-1\">\n {t('server.openapi.oauth2Token')}\n </label>\n <input\n type=\"password\"\n value={formData.openapi?.oauth2Token || ''}\n onChange={(e) =>\n setFormData((prev) => ({\n ...prev,\n openapi: {\n ...prev.openapi,\n oauth2Token: e.target.value,\n url: prev.openapi?.url || '',\n },\n }))\n }\n className=\"w-full border rounded px-2 py-1 text-sm focus:outline-none form-input\"\n placeholder=\"access-token\"\n />\n </div>\n </div>\n </div>\n )}\n\n {/* Specification Download Security (#1079) */}\n <div className=\"mb-4\">\n <div className=\"flex items-center mb-1\">\n <input\n type=\"checkbox\"\n id=\"openapiSpecSecurity\"\n checked={(formData.openapi?.specSecurityType || 'none') !== 'none'}\n onChange={(e) =>\n setFormData((prev) => ({\n ...prev,\n openapi: {\n ...prev.openapi,\n url: prev.openapi?.url || '',\n specSecurityType: e.target.checked ? 'http' : 'none',\n },\n }))\n }\n className=\"mr-2\"\n />\n <label\n htmlFor=\"openapiSpecSecurity\"\n className=\"text-gray-700 dark:text-gray-300 text-sm font-medium\"\n >\n {t('server.openapi.specSecurityToggle')}\n </label>\n </div>\n <p className=\"text-xs text-gray-500 ml-6\">\n {t('server.openapi.specSecurityHelp')}\n </p>\n {(formData.openapi?.specSecurityType || 'none') !== 'none' && (\n <div className=\"mt-2 ml-6 p-4 border border-gray-200 dark:border-gray-700 rounded bg-gray-50 dark:bg-gray-800\">\n <div className=\"mb-3\">\n <label className=\"block text-xs text-gray-600 mb-1\">\n {t('server.openapi.security')}\n </label>\n <select\n value={formData.openapi?.specSecurityType || 'http'}\n onChange={(e) =>\n setFormData((prev) => ({\n ...prev,\n openapi: {\n ...prev.openapi,\n url: prev.openapi?.url || '',\n specSecurityType: e.target.value as any,\n },\n }))\n }\n className=\"w-full border rounded px-2 py-1 text-sm focus:outline-none form-input\"\n >\n <option value=\"http\">{t('server.openapi.securityHttp')}</option>\n <option value=\"apiKey\">{t('server.openapi.securityApiKey')}</option>\n <option value=\"oauth2\">{t('server.openapi.securityOAuth2')}</option>\n </select>\n </div>\n\n {formData.openapi?.specSecurityType === 'http' && (\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-3\">\n <div>\n <label className=\"block text-xs text-gray-600 mb-1\">\n {t('server.openapi.httpScheme')}\n </label>\n <select\n value={formData.openapi?.specHttpScheme || 'basic'}\n onChange={(e) =>\n setFormData((prev) => ({\n ...prev,\n openapi: {\n ...prev.openapi,\n url: prev.openapi?.url || '',\n specHttpScheme: e.target.value as any,\n },\n }))\n }\n className=\"w-full border rounded px-2 py-1 text-sm focus:outline-none form-input\"\n >\n <option value=\"basic\">{t('server.openapi.httpSchemeBasic')}</option>\n <option value=\"bearer\">{t('server.openapi.httpSchemeBearer')}</option>\n </select>\n </div>\n <div>\n <label className=\"block text-xs text-gray-600 mb-1\">\n {t('server.openapi.httpCredentials')}\n </label>\n <input\n type=\"password\"\n value={formData.openapi?.specHttpCredentials || ''}\n onChange={(e) =>\n setFormData((prev) => ({\n ...prev,\n openapi: {\n ...prev.openapi,\n url: prev.openapi?.url || '',\n specHttpCredentials: e.target.value,\n },\n }))\n }\n className=\"w-full border rounded px-2 py-1 text-sm focus:outline-none form-input\"\n placeholder={\n formData.openapi?.specHttpScheme === 'basic'\n ? 'user:password or base64'\n : 'bearer-token'\n }\n />\n </div>\n </div>\n )}\n\n {formData.openapi?.specSecurityType === 'apiKey' && (\n <div className=\"grid grid-cols-1 md:grid-cols-3 gap-3\">\n <div>\n <label className=\"block text-xs text-gray-600 mb-1\">\n {t('server.openapi.apiKeyName')}\n </label>\n <input\n type=\"text\"\n value={formData.openapi?.specApiKeyName || ''}\n onChange={(e) =>\n setFormData((prev) => ({\n ...prev,\n openapi: {\n ...prev.openapi,\n url: prev.openapi?.url || '',\n specApiKeyName: e.target.value,\n },\n }))\n }\n className=\"w-full border rounded px-2 py-1 text-sm focus:outline-none form-input\"\n placeholder=\"X-API-Key\"\n />\n </div>\n <div>\n <label className=\"block text-xs text-gray-600 mb-1\">\n {t('server.openapi.apiKeyIn')}\n </label>\n <select\n value={formData.openapi?.specApiKeyIn || 'header'}\n onChange={(e) =>\n setFormData((prev) => ({\n ...prev,\n openapi: {\n ...prev.openapi,\n url: prev.openapi?.url || '',\n specApiKeyIn: e.target.value as any,\n },\n }))\n }\n className=\"w-full border rounded px-2 py-1 text-sm focus:outline-none form-input\"\n >\n <option value=\"header\">{t('server.openapi.apiKeyInHeader')}</option>\n <option value=\"query\">{t('server.openapi.apiKeyInQuery')}</option>\n <option value=\"cookie\">{t('server.openapi.apiKeyInCookie')}</option>\n </select>\n </div>\n <div>\n <label className=\"block text-xs text-gray-600 mb-1\">\n {t('server.openapi.apiKeyValue')}\n </label>\n <input\n type=\"password\"\n value={formData.openapi?.specApiKeyValue || ''}\n onChange={(e) =>\n setFormData((prev) => ({\n ...prev,\n openapi: {\n ...prev.openapi,\n url: prev.openapi?.url || '',\n specApiKeyValue: e.target.value,\n },\n }))\n }\n className=\"w-full border rounded px-2 py-1 text-sm focus:outline-none form-input\"\n />\n </div>\n </div>\n )}\n\n {formData.openapi?.specSecurityType === 'oauth2' && (\n <div>\n <label className=\"block text-xs text-gray-600 mb-1\">\n {t('server.openapi.oauth2Token')}\n </label>\n <input\n type=\"password\"\n value={formData.openapi?.specOauth2Token || ''}\n onChange={(e) =>\n setFormData((prev) => ({\n ...prev,\n openapi: {\n ...prev.openapi,\n url: prev.openapi?.url || '',\n specOauth2Token: e.target.value,\n },\n }))\n }\n className=\"w-full border rounded px-2 py-1 text-sm focus:outline-none form-input\"\n placeholder=\"access-token\"\n />\n </div>\n )}\n </div>\n )}\n </div>\n\n {/* Cookie Session Handling */}\n <div className=\"mb-4\">\n <div className=\"flex items-center mb-1\">\n <input\n type=\"checkbox\"\n id=\"openapiCookieSession\"\n checked={formData.openapi?.cookieSession || false}\n onChange={(e) =>\n setFormData((prev) => ({\n ...prev,\n openapi: {\n ...prev.openapi,\n passthroughHeaders: prev.openapi?.passthroughHeaders || '',\n url: prev.openapi?.url || '',\n cookieSession: e.target.checked,\n },\n }))\n }\n className=\"mr-2\"\n />\n <label\n htmlFor=\"openapiCookieSession\"\n className=\"text-gray-700 dark:text-gray-300 text-sm font-medium\"\n >\n {t('server.openapi.cookieSession', 'Cookie Session Handling')}\n </label>\n </div>\n <p className=\"text-xs text-gray-500 ml-6\">\n {t(\n 'server.openapi.cookieSessionHelp',\n 'Capture Set-Cookie from upstream login responses and replay them on later calls within the same downstream session. Isolated per MCP session; not persisted.',\n )}\n </p>\n </div>\n\n <div className=\"mb-4\">\n <div className=\"flex justify-between items-center mb-2\">\n <label className=\"block text-sm font-medium text-gray-700 dark:text-gray-300\">\n {t('server.headers')}\n </label>\n <button\n type=\"button\"\n onClick={addHeaderVar}\n className=\"hub-btn primary !w-[30px] !h-[30px] !p-0 justify-center text-base font-bold\"\n >\n +\n </button>\n </div>\n {headerVars.map((headerVar, index) => (\n <div key={index} className=\"flex items-center mb-2\">\n <div className=\"flex items-center space-x-2 flex-grow\">\n <input\n type=\"text\"\n value={headerVar.key}\n onChange={(e) => handleHeaderVarChange(index, 'key', e.target.value)}\n className=\"w-1/2 py-2 px-3 form-input\"\n placeholder=\"Authorization\"\n />\n <span className=\"flex items-center\">:</span>\n <input\n type=\"text\"\n value={headerVar.value}\n onChange={(e) => handleHeaderVarChange(index, 'value', e.target.value)}\n className=\"w-1/2 py-2 px-3 form-input\"\n placeholder=\"Bearer token...\"\n />\n </div>\n <button\n type=\"button\"\n onClick={() => removeHeaderVar(index)}\n className=\"bg-gray-200 hover:bg-gray-300 text-gray-700 font-medium py-1 px-2 rounded text-sm flex items-center justify-center min-w-[30px] min-h-[30px] ml-2 btn-danger\"\n >\n -\n </button>\n </div>\n ))}\n </div>\n </>\n ) : serverType === 'sse' || serverType === 'streamable-http' ? (\n <>\n <div className=\"mb-4\">\n <label\n className=\"block text-sm font-medium mb-1.5 text-gray-700 dark:text-gray-300\"\n htmlFor=\"url\"\n >\n {t('server.url')}\n </label>\n <input\n type=\"url\"\n name=\"url\"\n id=\"url\"\n value={formData.url}\n onChange={handleInputChange}\n className=\"w-full py-2 px-3 form-input\"\n placeholder={\n serverType === 'streamable-http'\n ? 'e.g.: http://localhost:3000/mcp'\n : 'e.g.: http://localhost:3000/sse'\n }\n required={serverType === 'sse' || serverType === 'streamable-http'}\n />\n </div>\n\n <div className=\"mb-4\">\n <div className=\"flex justify-between items-center mb-2\">\n <label className=\"block text-sm font-medium text-gray-700 dark:text-gray-300\">\n {t('server.headers')}\n </label>\n <button\n type=\"button\"\n onClick={addHeaderVar}\n className=\"hub-btn primary !w-[30px] !h-[30px] !p-0 justify-center text-base font-bold\"\n >\n +\n </button>\n </div>\n {headerVars.map((headerVar, index) => (\n <div key={index} className=\"flex items-center mb-2\">\n <div className=\"flex items-center space-x-2 flex-grow\">\n <input\n type=\"text\"\n value={headerVar.key}\n onChange={(e) => handleHeaderVarChange(index, 'key', e.target.value)}\n className=\"w-1/2 py-2 px-3 form-input\"\n placeholder=\"Authorization\"\n />\n <span className=\"flex items-center\">:</span>\n <input\n type=\"text\"\n value={headerVar.value}\n onChange={(e) => handleHeaderVarChange(index, 'value', e.target.value)}\n className=\"w-1/2 py-2 px-3 form-input\"\n placeholder=\"Bearer token...\"\n />\n </div>\n <button\n type=\"button\"\n onClick={() => removeHeaderVar(index)}\n className=\"bg-gray-200 hover:bg-gray-300 text-gray-700 font-medium py-1 px-2 rounded text-sm flex items-center justify-center min-w-[30px] min-h-[30px] ml-2 btn-danger\"\n >\n -\n </button>\n </div>\n ))}\n </div>\n\n <div className=\"mb-4\">\n <div className=\"flex justify-between items-center mb-2\">\n <label className=\"block text-sm font-medium text-gray-700 dark:text-gray-300\">\n {t('server.envVars')}\n </label>\n <button\n type=\"button\"\n onClick={addEnvVar}\n className=\"hub-btn primary !w-[30px] !h-[30px] !p-0 justify-center text-base font-bold\"\n >\n +\n </button>\n </div>\n {envVars.map((envVar, index) => (\n <div key={index} className=\"flex items-center mb-2\">\n <div className=\"flex items-center space-x-2 flex-grow\">\n <input\n type=\"text\"\n value={envVar.key}\n onChange={(e) => handleEnvVarChange(index, 'key', e.target.value)}\n className=\"w-1/2 py-2 px-3 form-input\"\n placeholder={t('server.key')}\n />\n <span className=\"flex items-center\">:</span>\n <input\n type=\"text\"\n value={envVar.value}\n onChange={(e) => handleEnvVarChange(index, 'value', e.target.value)}\n className=\"w-1/2 py-2 px-3 form-input\"\n placeholder={t('server.value')}\n />\n </div>\n <button\n type=\"button\"\n onClick={() => removeEnvVar(index)}\n className=\"bg-gray-200 hover:bg-gray-300 text-gray-700 font-medium py-1 px-2 rounded text-sm flex items-center justify-center min-w-[30px] min-h-[30px] ml-2 btn-danger\"\n >\n -\n </button>\n </div>\n ))}\n </div>\n </>\n ) : (\n <>\n <div className=\"mb-4\">\n <label\n className=\"block text-sm font-medium mb-1.5 text-gray-700 dark:text-gray-300\"\n htmlFor=\"command\"\n >\n {t('server.command')}\n </label>\n <input\n type=\"text\"\n name=\"command\"\n id=\"command\"\n value={formData.command}\n onChange={handleInputChange}\n className=\"w-full py-2 px-3 form-input\"\n placeholder=\"e.g.: npx\"\n required={serverType === 'stdio'}\n />\n </div>\n <div className=\"mb-4\">\n <label\n className=\"block text-sm font-medium mb-1.5 text-gray-700 dark:text-gray-300\"\n htmlFor=\"arguments\"\n >\n {t('server.arguments')}\n </label>\n <input\n type=\"text\"\n name=\"arguments\"\n id=\"arguments\"\n value={formData.arguments}\n onChange={(e) => handleArgsChange(e.target.value)}\n className=\"w-full py-2 px-3 form-input\"\n placeholder=\"e.g.: -y time-mcp\"\n />\n </div>\n\n <div className=\"mb-4\">\n <div className=\"flex justify-between items-center mb-2\">\n <label className=\"block text-sm font-medium text-gray-700 dark:text-gray-300\">\n {t('server.envVars')}\n </label>\n <button\n type=\"button\"\n onClick={addEnvVar}\n className=\"hub-btn primary !w-[30px] !h-[30px] !p-0 justify-center text-base font-bold\"\n >\n +\n </button>\n </div>\n {envVars.map((envVar, index) => (\n <div key={index} className=\"flex items-center mb-2\">\n <div className=\"flex items-center space-x-2 flex-grow\">\n <input\n type=\"text\"\n value={envVar.key}\n onChange={(e) => handleEnvVarChange(index, 'key', e.target.value)}\n className=\"w-1/2 py-2 px-3 form-input\"\n placeholder={t('server.key')}\n />\n <span className=\"flex items-center\">:</span>\n <input\n type=\"text\"\n value={envVar.value}\n onChange={(e) => handleEnvVarChange(index, 'value', e.target.value)}\n className=\"w-1/2 py-2 px-3 form-input\"\n placeholder={t('server.value')}\n />\n </div>\n <button\n type=\"button\"\n onClick={() => removeEnvVar(index)}\n className=\"bg-gray-200 hover:bg-gray-300 text-gray-700 font-medium py-1 px-2 rounded text-sm flex items-center justify-center min-w-[30px] min-h-[30px] ml-2 btn-danger\"\n >\n -\n </button>\n </div>\n ))}\n </div>\n </>\n )}\n </div>\n </div>\n\n {/* ─── Section 3: Advanced Options (collapsible) ─── */}\n <div className=\"mb-4\">\n <div\n className=\"flex items-center justify-between cursor-pointer bg-gray-50 dark:bg-gray-800 hover:bg-gray-100 dark:hover:bg-gray-700 p-3 rounded border border-gray-200 dark:border-gray-700\"\n onClick={() => setIsAdvancedExpanded(!isAdvancedExpanded)}\n >\n <h3 className=\"text-sm font-semibold text-[var(--hub-ink)]\">\n {t('server.sectionAdvanced', 'Advanced Options')}\n </h3>\n <span className=\"text-gray-500 text-sm\">{isAdvancedExpanded ? '▼' : '▶'}</span>\n </div>\n\n {isAdvancedExpanded && (\n <div className=\"border border-gray-200 dark:border-gray-700 rounded-b p-4 bg-white dark:bg-gray-900 border-t-0 space-y-4\">\n <fieldset className=\"space-y-3 rounded-lg border border-gray-200 dark:border-gray-700 p-4\">\n <legend className=\"px-1 font-medium\">{t('credentials.slots')}</legend>\n <p className=\"text-sm text-gray-500\">{t('credentials.slotsHint')}</p>\n {(formData.credentialTemplate || []).map((slot, index) => (\n <div key={index} className=\"flex flex-wrap items-center gap-2\">\n <span className=\"text-sm\">\n {t(serverType === 'stdio' ? 'server.envVars' : 'server.headers')}\n </span>\n <input\n required\n maxLength={128}\n aria-label={t('credentials.fieldName')}\n placeholder={t('credentials.fieldName')}\n value={slot.name}\n className=\"min-w-0 flex-1 py-2 px-3 form-input\"\n onChange={(event) =>\n setFormData({\n ...formData,\n credentialTemplate: formData.credentialTemplate?.map((item, i) =>\n i === index ? { ...item, name: event.target.value } : item,\n ),\n })\n }\n />\n <input\n maxLength={200}\n aria-label={t('credentials.label')}\n placeholder={t('credentials.label')}\n value={slot.label || ''}\n className=\"min-w-0 flex-1 py-2 px-3 form-input\"\n onChange={(event) =>\n setFormData({\n ...formData,\n credentialTemplate: formData.credentialTemplate?.map((item, i) =>\n i === index ? { ...item, label: event.target.value } : item,\n ),\n })\n }\n />\n <button\n type=\"button\"\n aria-label={t('credentials.removeSlot')}\n onClick={() =>\n setFormData({\n ...formData,\n credentialTemplate: formData.credentialTemplate?.filter(\n (_, i) => i !== index,\n ),\n })\n }\n >\n <X size={18} />\n </button>\n </div>\n ))}\n <button\n type=\"button\"\n className=\"text-sm text-blue-600\"\n disabled={(formData.credentialTemplate?.length || 0) >= 32}\n onClick={() =>\n setFormData({\n ...formData,\n credentialTemplate: [\n ...(formData.credentialTemplate || []),\n { target: serverType === 'stdio' ? 'env' : 'headers', name: '' },\n ],\n })\n }\n >\n {t('credentials.addSlot')}\n </button>\n </fieldset>\n\n {/* Visibility */}\n <div>\n <label\n className=\"block text-sm font-medium mb-1.5 text-[var(--hub-ink-2)]\"\n htmlFor=\"visibility\"\n >\n {t('server.visibility', 'Visibility')}\n </label>\n <select\n id=\"visibility\"\n name=\"visibility\"\n value={formData.visibility || 'private'}\n onChange={(e) =>\n setFormData((prev) => ({\n ...prev,\n visibility: e.target.value as 'private' | 'group' | 'public',\n }))\n }\n className=\"w-full py-2 px-3 form-input\"\n >\n <option value=\"private\">\n {t('server.visibilityPrivate', 'Private — only the owner and admins')}\n </option>\n <option value=\"group\">\n {t('server.visibilityGroup', 'Shared — selected users only')}\n </option>\n <option value=\"public\">\n {t('server.visibilityPublic', 'Public — every authenticated user')}\n </option>\n </select>\n <p className=\"text-xs text-gray-500 mt-1\">\n {t(\n 'server.visibilityDescription',\n 'Controls which non-admin users can discover and call this server. Admins always have access.',\n )}\n </p>\n\n {formData.visibility === 'group' && (\n <div className=\"mt-4 rounded border border-gray-200 dark:border-gray-700 p-3\">\n <div className=\"text-sm font-medium text-[var(--hub-ink-2)]\">\n {t('server.shareWithUsers', 'Share with users')}\n </div>\n <p className=\"text-xs text-gray-500 mt-1 mb-3\">\n {t(\n 'server.shareWithUsersDescription',\n 'Selected users can discover and call this server, but cannot manage its configuration.',\n )}\n </p>\n\n {!initialData?.name ? (\n <p className=\"text-sm text-gray-500\">\n {t('server.shareAfterCreate', 'Save the server before selecting users.')}\n </p>\n ) : (\n <>\n {shareCandidatesLoading && (\n <p className=\"text-sm text-gray-500\">\n {t('server.shareCandidatesLoading', 'Loading users...')}\n </p>\n )}\n {shareCandidatesError && (\n <p className=\"text-sm text-red-600 dark:text-red-400\">\n {t('server.shareCandidatesError', 'Failed to load users.')}\n </p>\n )}\n {!shareCandidatesLoading &&\n !shareCandidatesError &&\n selectableShareUsers.length === 0 && (\n <p className=\"text-sm text-gray-500\">\n {t('server.noShareCandidates', 'No other users are available.')}\n </p>\n )}\n {selectableShareUsers.length > 0 && (\n <>\n <div className=\"mb-3 space-y-2\">\n <label\n htmlFor=\"share-user-search\"\n className=\"block text-xs font-medium text-[var(--hub-ink-2)]\"\n >\n {t('server.shareUserSearchLabel', 'Search users')}\n </label>\n <input\n id=\"share-user-search\"\n type=\"search\"\n value={shareUserSearch}\n onChange={(event) => setShareUserSearch(event.target.value)}\n placeholder={t(\n 'server.shareUserSearchPlaceholder',\n 'Search usernames...',\n )}\n className=\"w-full py-2 px-3 form-input text-sm\"\n />\n <div className=\"flex flex-wrap gap-2\">\n <button\n type=\"button\"\n onClick={selectFilteredShareUsers}\n disabled={allFilteredShareUsersSelected}\n className=\"hub-btn text-sm\"\n >\n {t('server.selectAllShareUsers', 'Select all')}\n </button>\n <button\n type=\"button\"\n onClick={deselectFilteredShareUsers}\n disabled={noFilteredShareUsersSelected}\n className=\"hub-btn text-sm\"\n >\n {t('server.deselectAllShareUsers', 'Deselect all')}\n </button>\n </div>\n </div>\n {filteredShareUsers.length === 0 ? (\n <p className=\"text-sm text-gray-500\">\n {t('server.noMatchingShareUsers', 'No users match your search.')}\n </p>\n ) : (\n <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-2\">\n {filteredShareUsers.map((username) => (\n <label\n key={username}\n className=\"flex items-center gap-2 rounded border border-gray-200 dark:border-gray-700 px-3 py-2 text-sm text-[var(--hub-ink-2)]\"\n >\n <input\n type=\"checkbox\"\n checked={selectedShareUsers.has(username)}\n onChange={() => toggleSharedUser(username)}\n />\n <span>{username}</span>\n </label>\n ))}\n </div>\n )}\n </>\n )}\n </>\n )}\n </div>\n )}\n </div>\n\n {/* Passthrough Headers Configuration */}\n <div>\n <label className=\"block text-sm font-medium mb-1.5 text-[var(--hub-ink-2)]\">\n {t('server.openapi.passthroughHeaders')}\n </label>\n {serverType === 'openapi' ? (\n <>\n <input\n type=\"text\"\n value={formData.openapi?.passthroughHeaders || ''}\n onChange={(e) =>\n setFormData((prev) => ({\n ...prev,\n openapi: {\n ...prev.openapi,\n passthroughHeaders: e.target.value,\n url: prev.openapi?.url || '',\n },\n }))\n }\n className=\"w-full py-2 px-3 form-input\"\n placeholder=\"Authorization, X-API-Key, X-Custom-Header\"\n />\n </>\n ) : (\n <input\n type=\"text\"\n value={formData.passthroughHeaders || ''}\n onChange={(e) =>\n setFormData((prev) => ({\n ...prev,\n passthroughHeaders: e.target.value,\n }))\n }\n className=\"w-full py-2 px-3 form-input\"\n placeholder=\"Authorization, X-Custom-User-Id\"\n />\n )}\n <p className=\"text-xs text-gray-500 mt-1\">\n {t('server.openapi.passthroughHeadersHelp')}\n </p>\n </div>\n\n {/* OAuth Configuration - non-OpenAPI types */}\n {serverType !== 'openapi' && (\n <div>\n <div\n className=\"flex items-center justify-between cursor-pointer bg-gray-50 dark:bg-gray-800 hover:bg-gray-100 dark:hover:bg-gray-700 p-3 rounded border border-gray-200 dark:border-gray-700\"\n onClick={() => setIsOAuthSectionExpanded(!isOAuthSectionExpanded)}\n >\n <label className=\"text-sm font-medium text-gray-700 dark:text-gray-300\">\n {t('server.oauth.sectionTitle')}\n </label>\n <span className=\"text-gray-500 text-sm\">\n {isOAuthSectionExpanded ? '▼' : '▶'}\n </span>\n </div>\n\n {isOAuthSectionExpanded && (\n <div className=\"border border-gray-200 dark:border-gray-700 rounded-b p-4 bg-gray-50 dark:bg-gray-800 border-t-0\">\n <p className=\"text-xs text-gray-500 mb-3\">\n {t('server.oauth.sectionDescription')}\n </p>\n <div className=\"grid grid-cols-1 gap-3 md:grid-cols-2\">\n <div>\n <label className=\"block text-xs text-gray-600 mb-1\">\n {t('server.oauth.clientId')}\n </label>\n <input\n type=\"text\"\n value={formData.oauth?.clientId || ''}\n onChange={(e) => handleOAuthChange('clientId', e.target.value)}\n className=\"w-full py-2 px-3 form-input\"\n placeholder=\"client id\"\n autoComplete=\"off\"\n />\n </div>\n <div>\n <label className=\"block text-xs text-gray-600 mb-1\">\n {t('server.oauth.clientSecret')}\n </label>\n <input\n type=\"password\"\n value={formData.oauth?.clientSecret || ''}\n onChange={(e) => handleOAuthChange('clientSecret', e.target.value)}\n className=\"w-full py-2 px-3 form-input\"\n placeholder=\"client secret\"\n autoComplete=\"off\"\n />\n </div>\n </div>\n </div>\n )}\n </div>\n )}\n\n {/* Request Options Configuration */}\n {serverType !== 'openapi' && (\n <div>\n <div\n className=\"flex items-center justify-between cursor-pointer bg-gray-50 dark:bg-gray-800 hover:bg-gray-100 p-3 rounded border border-gray-200 dark:border-gray-700\"\n onClick={() => setIsRequestOptionsExpanded(!isRequestOptionsExpanded)}\n >\n <label className=\"text-sm font-medium text-gray-700 dark:text-gray-300\">\n {t('server.requestOptions')}\n </label>\n <span className=\"text-gray-500 text-sm\">\n {isRequestOptionsExpanded ? '▼' : '▶'}\n </span>\n </div>\n\n {isRequestOptionsExpanded && (\n <div className=\"border border-gray-200 dark:border-gray-700 rounded-b p-4 bg-gray-50 dark:bg-gray-800 border-t-0\">\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <div>\n <label\n className=\"block text-gray-600 text-sm font-medium mb-1\"\n htmlFor=\"timeout\"\n >\n {t('server.timeout')}\n </label>\n <input\n type=\"number\"\n id=\"timeout\"\n value={formData.options?.timeout || 60000}\n onChange={(e) =>\n handleOptionsChange('timeout', parseInt(e.target.value) || 60000)\n }\n className=\"w-full py-2 px-3 form-input\"\n placeholder=\"30000\"\n min=\"1000\"\n max=\"300000\"\n />\n <p className=\"text-xs text-gray-500 mt-1\">\n {t('server.timeoutDescription')}\n </p>\n </div>\n\n <div>\n <label\n className=\"block text-gray-600 text-sm font-medium mb-1\"\n htmlFor=\"maxTotalTimeout\"\n >\n {t('server.maxTotalTimeout')}\n </label>\n <input\n type=\"number\"\n id=\"maxTotalTimeout\"\n value={formData.options?.maxTotalTimeout || ''}\n onChange={(e) =>\n handleOptionsChange(\n 'maxTotalTimeout',\n e.target.value ? parseInt(e.target.value) : undefined,\n )\n }\n className=\"w-full py-2 px-3 form-input\"\n placeholder=\"Optional\"\n min=\"1000\"\n />\n <p className=\"text-xs text-gray-500 mt-1\">\n {t('server.maxTotalTimeoutDescription')}\n </p>\n </div>\n </div>\n\n <div className=\"mt-3\">\n <label className=\"flex items-center\">\n <input\n type=\"checkbox\"\n checked={formData.options?.resetTimeoutOnProgress ?? true}\n onChange={(e) =>\n handleOptionsChange('resetTimeoutOnProgress', e.target.checked)\n }\n className=\"mr-2\"\n />\n <span className=\"text-gray-600 text-sm\">\n {t('server.resetTimeoutOnProgress')}\n </span>\n </label>\n <p className=\"text-xs text-gray-500 mt-1 ml-6\">\n {t('server.resetTimeoutOnProgressDescription')}\n </p>\n </div>\n </div>\n )}\n </div>\n )}\n\n {/* KeepAlive Configuration - only for SSE/Streamable HTTP */}\n {(serverType === 'sse' || serverType === 'streamable-http') && (\n <div>\n <div\n className=\"flex items-center justify-between cursor-pointer bg-gray-50 dark:bg-gray-800 hover:bg-gray-100 p-3 rounded border border-gray-200 dark:border-gray-700\"\n onClick={() => setIsKeepAliveSectionExpanded(!isKeepAliveSectionExpanded)}\n >\n <label className=\"text-sm font-medium text-gray-700 dark:text-gray-300\">\n {t('server.keepAlive', 'Connection Health')}\n </label>\n <span className=\"text-gray-500 text-sm\">\n {isKeepAliveSectionExpanded ? '▼' : '▶'}\n </span>\n </div>\n\n {isKeepAliveSectionExpanded && (\n <div className=\"border border-gray-200 dark:border-gray-700 rounded-b p-4 bg-gray-50 dark:bg-gray-800 border-t-0\">\n <div className=\"flex items-center mb-3\">\n <input\n type=\"checkbox\"\n id=\"enableKeepAlive\"\n checked={formData.keepAlive?.enabled || false}\n onChange={(e) =>\n setFormData((prev) => ({\n ...prev,\n keepAlive: {\n ...prev.keepAlive,\n enabled: e.target.checked,\n },\n }))\n }\n className=\"mr-2\"\n />\n <label htmlFor=\"enableKeepAlive\" className=\"text-gray-600 text-sm\">\n {t('server.enableKeepAlive', 'Enable Health Checks and Auto Reconnect')}\n </label>\n </div>\n <p className=\"text-xs text-gray-500 mb-3\">\n {t(\n 'server.keepAliveDescription',\n 'Run periodic health checks and automatically reconnect this remote server when it becomes disconnected.',\n )}\n </p>\n <div>\n <label\n className=\"block text-gray-600 text-sm font-medium mb-1\"\n htmlFor=\"keepAliveInterval\"\n >\n {t('server.keepAliveInterval', 'Check interval (ms)')}\n </label>\n <input\n type=\"number\"\n id=\"keepAliveInterval\"\n value={formData.keepAlive?.interval || 60000}\n onChange={(e) =>\n setFormData((prev) => ({\n ...prev,\n keepAlive: {\n ...prev.keepAlive,\n interval: parseInt(e.target.value) || 60000,\n },\n }))\n }\n className=\"w-full py-2 px-3 form-input\"\n placeholder=\"60000\"\n min=\"5000\"\n max=\"300000\"\n />\n <p className=\"text-xs text-gray-500 mt-1\">\n {t(\n 'server.keepAliveIntervalDescription',\n 'Time between health checks and automatic reconnect attempts in milliseconds (default: 60000ms = 1 minute)',\n )}\n </p>\n </div>\n </div>\n )}\n </div>\n )}\n\n {/* Per-session client isolation - applies to any server type except openapi */}\n {serverType !== 'openapi' && (\n <div>\n <div className=\"flex items-center mb-1\">\n <input\n type=\"checkbox\"\n id=\"perSessionClient\"\n checked={formData.perSessionClient || false}\n onChange={(e) =>\n setFormData((prev) => ({\n ...prev,\n perSessionClient: e.target.checked,\n }))\n }\n className=\"mr-2\"\n />\n <label\n htmlFor=\"perSessionClient\"\n className=\"text-gray-700 dark:text-gray-300 text-sm font-medium\"\n >\n {t('server.perSessionClient', 'Per-Session Client Isolation')}\n </label>\n </div>\n <p className=\"text-xs text-gray-500 ml-6\">\n {t(\n 'server.perSessionClientDescription',\n 'Create a dedicated upstream connection per session instead of sharing one across all sessions. Enable for stateful servers like Playwright. Increases upstream connections with concurrent sessions.',\n )}\n </p>\n </div>\n )}\n\n {/* On-demand spawning - stdio only */}\n {serverType === 'stdio' && (\n <div>\n <div className=\"flex items-center mb-1\">\n <input\n type=\"checkbox\"\n id=\"startOnDemand\"\n checked={formData.startOnDemand || false}\n onChange={(e) =>\n setFormData((prev) => ({\n ...prev,\n startOnDemand: e.target.checked,\n }))\n }\n className=\"mr-2\"\n />\n <label\n htmlFor=\"startOnDemand\"\n className=\"text-gray-700 dark:text-gray-300 text-sm font-medium\"\n >\n {t('server.startOnDemand', 'Start On Demand')}\n </label>\n </div>\n <p className=\"text-xs text-gray-500 ml-6\">\n {t(\n 'server.startOnDemandDescription',\n 'Skip startup connect and spawn this server only when a tool call arrives. The process is shut down automatically after the idle timeout, then restarted on the next call. Reduces persistent memory usage for rarely-used servers.',\n )}\n </p>\n {(formData.startOnDemand || !!formData.credentialTemplate?.length) && (\n <div className=\"ml-6 mt-2\">\n <label\n htmlFor=\"idleTimeoutMs\"\n className=\"block text-xs text-gray-600 dark:text-gray-400 mb-1\"\n >\n {t('server.idleTimeoutMs', 'Idle shutdown timeout (ms)')}\n </label>\n <input\n type=\"number\"\n id=\"idleTimeoutMs\"\n min={10000}\n step={1000}\n value={formData.idleTimeoutMs ?? 300000}\n onChange={(e) =>\n setFormData((prev) => ({\n ...prev,\n idleTimeoutMs: Number(e.target.value),\n }))\n }\n className=\"hub-input w-40 text-sm\"\n />\n <p className=\"text-xs text-gray-500 mt-1\">\n {t(\n 'server.idleTimeoutMsDescription',\n 'Shut down the process after this many milliseconds with no tool calls. Default: 300000 (5 minutes).',\n )}\n </p>\n </div>\n )}\n </div>\n )}\n </div>\n )}\n </div>\n\n <div className=\"flex justify-end mt-6\">\n <button type=\"button\" onClick={onCancel} className=\"hub-btn mr-2\">\n {t('server.cancel')}\n </button>\n <button type=\"submit\" className=\"hub-btn primary\">\n {isEdit ? t('server.save') : t('server.add')}\n </button>\n </div>\n </form>\n </div>\n );\n};\n\nexport default ServerForm;\n","// Utility function to detect ${} variables in server configurations\nexport const detectVariables = (payload: any): string[] => {\n const variables = new Set<string>();\n const variableRegex = /\\$\\{([^}]+)\\}/g;\n\n const checkString = (str: string) => {\n let match;\n while ((match = variableRegex.exec(str)) !== null) {\n variables.add(match[1]);\n }\n };\n\n const checkObject = (obj: any, path: string = '') => {\n if (typeof obj === 'string') {\n checkString(obj);\n } else if (Array.isArray(obj)) {\n obj.forEach((item, index) => checkObject(item, `${path}[${index}]`));\n } else if (obj && typeof obj === 'object') {\n Object.entries(obj).forEach(([key, value]) => {\n checkObject(value, path ? `${path}.${key}` : key);\n });\n }\n };\n\n checkObject(payload);\n return Array.from(variables);\n};\n"],"names":["buildKeyValueRecord","vars","record","key","value","trimmedKey","parseCommaSeparatedList","item","normalizeSharedUsers","usernames","username","buildOptions","options","nextOptions","buildOAuthConfig","oauth","nextOAuth","clientId","_a","clientSecret","_b","scopes","_c","accessToken","_d","refreshToken","_e","authorizationEndpoint","_f","tokenEndpoint","_g","resource","_h","parsedScopes","scope","buildOpenApiConfig","formData","openapi","oauth2TokenUrl","oauth2ClientId","oauth2ClientSecret","_i","oauth2Token","_k","_j","_l","_m","_n","_o","_p","specSecurityType","_q","_r","_s","_t","_u","_v","_w","buildServerPayload","serverType","envVars","headerVars","env","headers","description","config","slot","keepAliveEnabled","getSelectableShareUsers","selectedUsers","shareCandidates","left","right","filterShareUsers","users","query","normalizedQuery","selectShareUsers","usersToSelect","deselectShareUsers","usersToDeselect","usersToRemove","isOpenApiSecurityUntouched","userTouched","applyDeclaredSecurityPrefill","declared","prefill","securityConfigurationsDiffer","describeConfiguredSecurity","type","buildOpenApiSecurityNotice","getOpenApiSource","mode","isOpenApiSourceReady","source","parsed","url","shouldAutoAnalyzeOpenApiSource","SERVER_NAME_PATTERN","SERVER_NAME_MAX_LENGTH","isValidServerName","name","trimmed","slugifyServerName","ServerForm","onSubmit","onCancel","initialData","modalTitle","formError","shareCandidatesFrom","t","useTranslation","enforceNamePattern","getInitialServerType","getInitialServerEnvVars","data","getInitialOAuthConfig","setServerType","useState","setFormData","_x","_z","_y","_B","_A","_D","_C","_F","_E","_H","_G","_J","_I","_K","_M","_L","_O","_N","_Q","_P","_S","_R","_U","_T","_W","_V","setShareCandidates","shareCandidatesLoading","setShareCandidatesLoading","shareCandidatesError","setShareCandidatesError","shareUserSearch","setShareUserSearch","shareCandidatesServer","useEffect","cancelled","apiGet","response","selectableShareUsers","filteredShareUsers","selectedShareUsers","allFilteredShareUsersSelected","noFilteredShareUsersSelected","toggleSharedUser","previous","selected","selectFilteredShareUsers","deselectFilteredShareUsers","setEnvVars","setHeaderVars","openApiStats","setOpenApiStats","openApiStatsLoading","setOpenApiStatsLoading","openApiStatsUnavailable","setOpenApiStatsUnavailable","openApiStatsRequestId","useRef","analyzedOpenApiSourceKey","automaticSecurityAnalysisDone","openApiSecurityTouched","openApiFormDataRef","openApiEnvVarsRef","openApiHeaderVarsRef","openApiSecurityNotice","setOpenApiSecurityNotice","securityDetectionLoading","setSecurityDetectionLoading","isRequestOptionsExpanded","setIsRequestOptionsExpanded","isOAuthSectionExpanded","setIsOAuthSectionExpanded","isKeepAliveSectionExpanded","setIsKeepAliveSectionExpanded","isAdvancedExpanded","setIsAdvancedExpanded","error","setError","isEdit","markOpenApiSecurityTouched","handleInputChange","e","handleArgsChange","args","arg","updateServerType","prev","handleEnvVarChange","index","field","newEnvVars","addEnvVar","removeEnvVar","handleHeaderVarChange","newHeaderVars","addHeaderVar","removeHeaderVar","handleOAuthChange","handleOptionsChange","runOpenApiSecurityDetection","payload","apiPost","analyzeOpenApiSource","sourceKey","requestId","latestFormData","securityTouched","canPrefillSecurity","nextFormData","detectOpenApiSecurity","openApiSource","openApiSourcePresent","timeoutId","handleSubmit","err","jsxs","jsx","X","Fragment","_X","_Y","_Z","__","_$","_aa","_ba","_ca","formatBytes","formatTokens","OPENAPI_STATS_WARN_TOKENS","_da","_ea","_fa","_ga","_ha","_ia","_ja","_ka","_la","_ma","_na","_oa","_pa","_qa","_ra","_sa","_ta","_ua","_va","_wa","_xa","_ya","_za","_Aa","_Ba","_Ca","_Da","_Ea","_Fa","_Ga","_Ha","_Ia","headerVar","envVar","event","i","_","_Ja","_Ka","_La","_Ma","_Na","_Oa","_Pa","_Qa","_Ra","_Sa","detectVariables","variables","variableRegex","checkString","str","match","checkObject","obj","path"],"mappings":"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"}
@@ -9,11 +9,11 @@
9
9
  <link rel="preconnect" href="https://fonts.googleapis.com">
10
10
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
11
11
  <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
12
- <script type="module" crossorigin src="./assets/index-Bu4XuAH4.js"></script>
12
+ <script type="module" crossorigin src="./assets/index-DhzWX9nb.js"></script>
13
13
  <link rel="modulepreload" crossorigin href="./assets/framework-vendor-_YL27Pfc.js">
14
14
  <link rel="modulepreload" crossorigin href="./assets/i18n-vendor-BMaj5qV8.js">
15
- <link rel="modulepreload" crossorigin href="./assets/icons-vendor-VW-UwEhw.js">
16
- <link rel="stylesheet" crossorigin href="./assets/index-B3OqAhGz.css">
15
+ <link rel="modulepreload" crossorigin href="./assets/icons-vendor-Bk5sng-h.js">
16
+ <link rel="stylesheet" crossorigin href="./assets/index-D4Vy78bV.css">
17
17
  </head>
18
18
 
19
19
  <body class="bg-gray-100">
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@samanhappy/mcphub",
3
- "version": "1.0.38",
3
+ "version": "1.0.39",
4
4
  "description": "Open-source, self-hosted MCP gateway and control plane for connecting, controlling, and operating MCP servers.",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -142,6 +142,7 @@
142
142
  "test:ci": "jest --ci --coverage --watchAll=false",
143
143
  "frontend:dev": "cd frontend && vite",
144
144
  "frontend:build": "cd frontend && vite build",
145
+ "frontend:typecheck": "tsc --noEmit -p frontend/tsconfig.json",
145
146
  "frontend:preview": "cd frontend && vite preview",
146
147
  "dev": "concurrently \"pnpm backend:dev\" \"pnpm frontend:dev\"",
147
148
  "debug": "concurrently \"pnpm backend:debug\" \"pnpm frontend:dev\""
@@ -1,2 +0,0 @@
1
- import{d as $,R as u,r as p,j as e}from"./framework-vendor-_YL27Pfc.js";import{u as L,a as M}from"./useCostData-C72NC0PQ.js";import{d as P}from"./index-Bu4XuAH4.js";import{u as A}from"./useSettingsData-JTEMu74D.js";import{f as U}from"./contextCost-CilWqGWT.js";import{E as h}from"./EndpointCopy-8jW5Xtka.js";import{S as H}from"./StatusDot-CdzMqjTi.js";import{u as O}from"./i18n-vendor-BMaj5qV8.js";import{R as _,P as B,l as C,m as G}from"./icons-vendor-VW-UwEhw.js";const i=({label:r,value:l,tone:a="default"})=>{const o=a==="ok"?"oklch(0.4 0.13 145)":a==="warn"?"oklch(0.45 0.13 80)":a==="err"?"oklch(0.45 0.18 25)":a==="muted"?"var(--hub-ink-3)":"var(--hub-ink)";return e.jsxs("div",{className:"hub-card",style:{padding:"14px 16px"},children:[e.jsx("div",{className:"text-[12px]",style:{color:"var(--hub-ink-3)"},children:r}),e.jsx("div",{className:"hub-num",style:{fontSize:26,fontWeight:500,letterSpacing:"-0.02em",lineHeight:1.1,marginTop:8,color:o},children:l})]})},w=(r,l)=>l?l==="stdio"?r("server.typeStdio")||"stdio":l==="sse"?r("server.typeSse")||"sse":l==="streamable-http"?r("server.typeStreamableHttp")||"http":l==="openapi"?r("server.typeOpenapi")||"openapi":l:null,Y=()=>{var k;const{t:r}=O(),l=$(),{allServers:a,error:o,setError:R,isLoading:b,triggerRefresh:z}=L({refreshOnMount:!0}),{groups:x}=P(),{installConfig:m}=A(),{serverCosts:v}=M(),[E,f]=u.useState(!1),g=u.useRef(!1);u.useEffect(()=>{if(b){g.current=!0;return}if(g.current){f(!0);return}(a.length>0||o)&&f(!0)},[b,a.length,o]);const t=p.useMemo(()=>({total:a.length,online:a.filter(s=>s.status==="connected").length,disabled:a.filter(s=>s.enabled===!1).length,offline:a.filter(s=>s.status==="disconnected"&&s.enabled!==!1).length,connecting:a.filter(s=>(s.status==="connecting"||s.status==="oauth_required")&&s.enabled!==!1).length,tools:a.reduce((s,n)=>{var c;return s+(((c=n.tools)==null?void 0:c.length)||0)},0)}),[a]),D=p.useMemo(()=>v.filter(s=>s.connected).reduce((s,n)=>s+n.exposed,0),[v]),T=p.useMemo(()=>a.slice(0,6),[a]),d=((k=m==null?void 0:m.baseUrl)==null?void 0:k.replace(/\/+$/,""))||"",j="minmax(220px,1.9fr) minmax(110px,0.95fr) minmax(120px,0.95fr) 80px 80px 90px 72px",N=!E;return e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-end justify-between gap-4 mb-6",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"hub-h1",children:r("pages.dashboard.title")}),e.jsxs("p",{className:"hub-sub",children:[r("pages.dashboard.totalServers")," · ",e.jsx("span",{className:"hub-num",children:t.total})," · ",r("pages.dashboard.onlineServers")," · ",e.jsx("span",{className:"hub-num",children:t.online})]})]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsxs("button",{className:"hub-btn",onClick:()=>z(),children:[e.jsx(_,{size:13})," ",r("common.refresh")]}),e.jsxs("button",{className:"hub-btn primary",onClick:()=>l("/servers"),children:[e.jsx(B,{size:13})," ",r("server.add")]})]})]}),o&&e.jsxs("div",{className:"hub-card flex items-center justify-between gap-3 mb-5",style:{padding:"10px 14px",borderColor:"oklch(0.85 0.1 25)",background:"oklch(0.97 0.03 25)",color:"oklch(0.4 0.18 25)"},children:[e.jsxs("div",{className:"flex items-center gap-2 min-w-0",children:[e.jsx(C,{size:14,className:"flex-shrink-0"}),e.jsx("span",{className:"truncate text-[13px]",children:o})]}),e.jsx("button",{className:"hub-icon-btn sm",onClick:()=>R(null),"aria-label":r("app.closeButton"),children:"✕"})]}),N?e.jsx("div",{className:"grid grid-cols-2 md:grid-cols-6 gap-3 mb-6",children:Array.from({length:6}).map((s,n)=>e.jsx("div",{className:"hub-card animate-pulse",style:{padding:"14px 16px",height:78}},n))}):e.jsxs("div",{className:"grid grid-cols-2 md:grid-cols-6 gap-3 mb-6",children:[e.jsx(i,{label:r("pages.dashboard.totalServers"),value:t.total}),e.jsx(i,{label:r("pages.dashboard.onlineServers"),value:t.online,tone:"ok"}),e.jsx(i,{label:r("pages.dashboard.connectingServers"),value:t.connecting,tone:"warn"}),e.jsx(i,{label:r("pages.dashboard.offlineServers"),value:t.offline,tone:"err"}),e.jsx(i,{label:r("pages.dashboard.disabledServers"),value:t.disabled,tone:"muted"}),e.jsx(i,{label:r("cost.totalFootprint"),value:U(D)})]}),a.length>0&&!N&&e.jsxs("div",{className:"hub-card overflow-hidden mb-6",children:[e.jsxs("div",{className:"flex items-center justify-between px-4 py-3",style:{borderBottom:"1px solid var(--hub-line-2)"},children:[e.jsx("h3",{className:"hub-card-title",children:r("pages.dashboard.recentServers")}),e.jsxs("button",{className:"hub-btn ghost sm",style:{color:"var(--hub-ink-3)"},onClick:()=>l("/servers"),children:[r("common.viewAll")||"View all",e.jsx(G,{size:12})]})]}),e.jsxs("div",{className:"hub-row head hub-mono",style:{gridTemplateColumns:j},children:[e.jsx("div",{children:r("server.name")}),e.jsx("div",{children:r("server.status")}),e.jsx("div",{children:r("common.type")||"Transport"}),e.jsx("div",{children:r("server.tools")}),e.jsx("div",{children:r("server.prompts")}),e.jsx("div",{children:r("nav.resources")}),e.jsx("div",{children:r("server.enabled")})]}),T.map(s=>{var n,c,S,y;return e.jsxs("div",{className:"hub-row hover cursor-pointer",style:{gridTemplateColumns:j},onClick:()=>l("/servers"),children:[e.jsxs("div",{className:"flex items-center gap-2 min-w-0",children:[e.jsx("span",{className:"hub-mono truncate",style:{fontSize:13,color:s.enabled===!1?"var(--hub-ink-3)":"var(--hub-ink)"},children:s.name}),s.error&&e.jsx(C,{size:13,className:"text-[var(--hub-err)] flex-shrink-0"})]}),e.jsx("div",{className:"min-w-0",children:e.jsx(H,{status:s.status,enabled:s.enabled})}),e.jsx("div",{className:"min-w-0",children:(n=s.config)!=null&&n.type?e.jsx("span",{className:"hub-tag",title:w(r,s.config.type)??void 0,children:w(r,s.config.type)}):e.jsx("span",{style:{color:"var(--hub-ink-3)",fontSize:12},children:"—"})}),e.jsx("div",{className:"hub-num hub-mono",style:{fontSize:12.5},children:((c=s.tools)==null?void 0:c.length)||0}),e.jsx("div",{className:"hub-num hub-mono",style:{fontSize:12.5,color:"var(--hub-ink-2)"},children:((S=s.prompts)==null?void 0:S.length)||0}),e.jsx("div",{className:"hub-num hub-mono",style:{fontSize:12.5,color:"var(--hub-ink-2)"},children:((y=s.resources)==null?void 0:y.length)||0}),e.jsx("div",{className:"text-[12px]",style:{color:s.enabled!==!1?"var(--hub-ok)":"var(--hub-ink-3)"},children:s.enabled!==!1?"✓":"—"})]},s.name)})]}),e.jsxs("div",{className:"hub-card mb-5",style:{padding:16},children:[e.jsxs("div",{className:"flex justify-between items-start gap-3 mb-3",children:[e.jsxs("div",{children:[e.jsx("h3",{className:"hub-card-title",children:r("pages.dashboard.endpoints")||"MCP Endpoints"}),e.jsx("p",{className:"hub-sub",style:{marginTop:2},children:r("pages.dashboard.endpointsHint")||"Use these URLs in Claude Desktop, Cursor, or any MCP client"})]}),e.jsxs("a",{className:"hub-btn ghost",href:"https://docs.mcphub.app",target:"_blank",rel:"noopener noreferrer",style:{color:"var(--hub-ink-3)"},children:[r("common.docs")||"Docs"," →"]})]}),e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-2.5",children:[e.jsx(h,{label:"ALL",url:`${d}/mcp`}),e.jsx(h,{label:"SMART",url:`${d}/mcp/$smart`}),x.slice(0,2).map(s=>e.jsx(h,{label:"GROUP",url:`${d}/mcp/${s.name}`},s.id)),x.length<2&&a[0]&&e.jsx(h,{label:"SERVER",url:`${d}/mcp/${a[0].name}`})]})]})]})};export{Y as default};
2
- //# sourceMappingURL=Dashboard-CElNx820.js.map
@@ -1,2 +0,0 @@
1
- import{r as y,j as t}from"./framework-vendor-_YL27Pfc.js";import{j as x,m as r}from"./index-Bu4XuAH4.js";import{u as h}from"./i18n-vendor-BMaj5qV8.js";import{C,q as b}from"./icons-vendor-VW-UwEhw.js";const f=async e=>{try{if(navigator.clipboard&&window.isSecureContext)return await navigator.clipboard.writeText(e),!0}catch{}try{const o=document.createElement("textarea");o.value=e,o.style.position="fixed",o.style.left="-9999px",document.body.appendChild(o),o.focus(),o.select();const s=document.execCommand("copy");return document.body.removeChild(o),s}catch{return!1}},E=({url:e,label:o,prefix:s,className:p,copyValue:d,ariaLabel:l})=>{const{t:c}=h(),{showToast:n}=x(),[a,i]=y.useState(!1),m=async u=>{if(u.stopPropagation(),!await f(d??e)){n(c("common.copyFailed")||"Copy failed","error");return}i(!0),n(c("common.copySuccess")||"Copied to clipboard","success"),setTimeout(()=>i(!1),1200)};return t.jsxs("div",{className:r("hub-endpoint",p),role:"group","aria-label":l||e,children:[o&&t.jsx("div",{className:"hub-endpoint-label",children:o}),t.jsxs("div",{className:"hub-endpoint-url",title:e,children:[s&&t.jsx("span",{style:{color:"var(--hub-ink-3)"},children:s}),e]}),t.jsx("button",{type:"button",onClick:m,className:r("hub-endpoint-copy",a?"copied":""),title:c("common.copy")||"Copy","aria-label":c("common.copy")||"Copy",children:a?t.jsx(C,{size:13}):t.jsx(b,{size:13})})]})};export{E};
2
- //# sourceMappingURL=EndpointCopy-8jW5Xtka.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"EndpointCopy-8jW5Xtka.js","sources":["../../src/components/ui/EndpointCopy.tsx"],"sourcesContent":["import React, { useState } from 'react';\nimport { Copy, Check } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { useToast } from '@/contexts/ToastContext';\nimport { cn } from '@/utils/cn';\n\nconst copyText = async (value: string): Promise<boolean> => {\n try {\n if (navigator.clipboard && window.isSecureContext) {\n await navigator.clipboard.writeText(value);\n return true;\n }\n } catch {\n // fall through to fallback\n }\n try {\n const el = document.createElement('textarea');\n el.value = value;\n el.style.position = 'fixed';\n el.style.left = '-9999px';\n document.body.appendChild(el);\n el.focus();\n el.select();\n const ok = document.execCommand('copy');\n document.body.removeChild(el);\n return ok;\n } catch {\n return false;\n }\n};\n\ninterface EndpointCopyProps {\n url: string;\n label?: string;\n prefix?: string;\n className?: string;\n /** Optionally override the value placed on the clipboard. */\n copyValue?: string;\n ariaLabel?: string;\n}\n\nexport const EndpointCopy: React.FC<EndpointCopyProps> = ({\n url,\n label,\n prefix,\n className,\n copyValue,\n ariaLabel,\n}) => {\n const { t } = useTranslation();\n const { showToast } = useToast();\n const [copied, setCopied] = useState(false);\n\n const onCopy = async (e: React.MouseEvent) => {\n e.stopPropagation();\n const ok = await copyText(copyValue ?? url);\n if (!ok) {\n showToast(t('common.copyFailed') || 'Copy failed', 'error');\n return;\n }\n setCopied(true);\n showToast(t('common.copySuccess') || 'Copied to clipboard', 'success');\n setTimeout(() => setCopied(false), 1200);\n };\n\n return (\n <div className={cn('hub-endpoint', className)} role=\"group\" aria-label={ariaLabel || url}>\n {label && <div className=\"hub-endpoint-label\">{label}</div>}\n <div className=\"hub-endpoint-url\" title={url}>\n {prefix && <span style={{ color: 'var(--hub-ink-3)' }}>{prefix}</span>}\n {url}\n </div>\n <button\n type=\"button\"\n onClick={onCopy}\n className={cn('hub-endpoint-copy', copied ? 'copied' : '')}\n title={t('common.copy') || 'Copy'}\n aria-label={t('common.copy') || 'Copy'}\n >\n {copied ? <Check size={13} /> : <Copy size={13} />}\n </button>\n </div>\n );\n};\n\ninterface MonoCopyProps {\n text: string;\n className?: string;\n copyValue?: string;\n title?: string;\n}\n\n/** Inline monospace value with hover-to-copy icon. */\nexport const MonoCopy: React.FC<MonoCopyProps> = ({ text, className, copyValue, title }) => {\n const { t } = useTranslation();\n const { showToast } = useToast();\n const [copied, setCopied] = useState(false);\n\n const onCopy = async (e: React.MouseEvent) => {\n e.stopPropagation();\n const ok = await copyText(copyValue ?? text);\n if (!ok) {\n showToast(t('common.copyFailed') || 'Copy failed', 'error');\n return;\n }\n setCopied(true);\n showToast(t('common.copySuccess') || 'Copied to clipboard', 'success');\n setTimeout(() => setCopied(false), 1200);\n };\n\n return (\n <span\n className={cn(\n 'hub-mono inline-flex items-center gap-1.5 group cursor-pointer text-[12.5px]',\n className,\n )}\n onClick={onCopy}\n title={title || text}\n role=\"button\"\n >\n <span className=\"truncate\">{text}</span>\n {copied ? (\n <Check size={12} className=\"text-[var(--hub-ok)] flex-shrink-0\" />\n ) : (\n <Copy\n size={12}\n className=\"text-[var(--hub-ink-3)] opacity-0 group-hover:opacity-100 transition-opacity flex-shrink-0\"\n />\n )}\n </span>\n );\n};\n"],"names":["copyText","value","el","ok","EndpointCopy","url","label","prefix","className","copyValue","ariaLabel","t","useTranslation","showToast","useToast","copied","setCopied","useState","onCopy","e","jsxs","cn","jsx","Check","Copy"],"mappings":"wMAMA,MAAMA,EAAW,MAAOC,GAAoC,CAC1D,GAAI,CACF,GAAI,UAAU,WAAa,OAAO,gBAChC,aAAM,UAAU,UAAU,UAAUA,CAAK,EAClC,EAEX,MAAQ,CAER,CACA,GAAI,CACF,MAAMC,EAAK,SAAS,cAAc,UAAU,EAC5CA,EAAG,MAAQD,EACXC,EAAG,MAAM,SAAW,QACpBA,EAAG,MAAM,KAAO,UAChB,SAAS,KAAK,YAAYA,CAAE,EAC5BA,EAAG,MAAA,EACHA,EAAG,OAAA,EACH,MAAMC,EAAK,SAAS,YAAY,MAAM,EACtC,gBAAS,KAAK,YAAYD,CAAE,EACrBC,CACT,MAAQ,CACN,MAAO,EACT,CACF,EAYaC,EAA4C,CAAC,CACxD,IAAAC,EACA,MAAAC,EACA,OAAAC,EACA,UAAAC,EACA,UAAAC,EACA,UAAAC,CACF,IAAM,CACJ,KAAM,CAAE,EAAAC,CAAA,EAAMC,EAAA,EACR,CAAE,UAAAC,CAAA,EAAcC,EAAA,EAChB,CAACC,EAAQC,CAAS,EAAIC,EAAAA,SAAS,EAAK,EAEpCC,EAAS,MAAOC,GAAwB,CAG5C,GAFAA,EAAE,gBAAA,EAEE,CADO,MAAMnB,EAASS,GAAaJ,CAAG,EACjC,CACPQ,EAAUF,EAAE,mBAAmB,GAAK,cAAe,OAAO,EAC1D,MACF,CACAK,EAAU,EAAI,EACdH,EAAUF,EAAE,oBAAoB,GAAK,sBAAuB,SAAS,EACrE,WAAW,IAAMK,EAAU,EAAK,EAAG,IAAI,CACzC,EAEA,OACEI,EAAAA,KAAC,MAAA,CAAI,UAAWC,EAAG,eAAgBb,CAAS,EAAG,KAAK,QAAQ,aAAYE,GAAaL,EAClF,SAAA,CAAAC,GAASgB,EAAAA,IAAC,MAAA,CAAI,UAAU,qBAAsB,SAAAhB,EAAM,EACrDc,EAAAA,KAAC,MAAA,CAAI,UAAU,mBAAmB,MAAOf,EACtC,SAAA,CAAAE,SAAW,OAAA,CAAK,MAAO,CAAE,MAAO,kBAAA,EAAuB,SAAAA,EAAO,EAC9DF,CAAA,EACH,EACAiB,EAAAA,IAAC,SAAA,CACC,KAAK,SACL,QAASJ,EACT,UAAWG,EAAG,oBAAqBN,EAAS,SAAW,EAAE,EACzD,MAAOJ,EAAE,aAAa,GAAK,OAC3B,aAAYA,EAAE,aAAa,GAAK,OAE/B,SAAAI,QAAUQ,EAAA,CAAM,KAAM,GAAI,EAAKD,EAAAA,IAACE,EAAA,CAAK,KAAM,EAAA,CAAI,CAAA,CAAA,CAClD,EACF,CAEJ"}