@samanhappy/mcphub 1.1.14 → 1.2.0

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 (215) hide show
  1. package/README.fr.md +2 -1
  2. package/README.md +2 -1
  3. package/README.zh.md +2 -1
  4. package/dist/betterAuth.js +3 -3
  5. package/dist/betterAuth.js.map +1 -1
  6. package/dist/cli/commands/keys.js +22 -3
  7. package/dist/cli/commands/keys.js.map +1 -1
  8. package/dist/clients/mcpSdkClient.js +2667 -1448
  9. package/dist/clients/mcpSdkClient.js.map +4 -4
  10. package/dist/clients/openapi.js +3 -2
  11. package/dist/clients/openapi.js.map +1 -1
  12. package/dist/controllers/bearerKeyController.js +49 -3
  13. package/dist/controllers/bearerKeyController.js.map +1 -1
  14. package/dist/controllers/credentialBindingController.js +1 -1
  15. package/dist/controllers/credentialBindingController.js.map +1 -1
  16. package/dist/controllers/groupController.js +12 -5
  17. package/dist/controllers/groupController.js.map +1 -1
  18. package/dist/controllers/healthController.js +23 -1
  19. package/dist/controllers/healthController.js.map +1 -1
  20. package/dist/controllers/metricsController.js +9 -1
  21. package/dist/controllers/metricsController.js.map +1 -1
  22. package/dist/controllers/oauthDynamicRegistrationController.js +5 -5
  23. package/dist/controllers/oauthDynamicRegistrationController.js.map +1 -1
  24. package/dist/controllers/oauthRelayController.js +65 -0
  25. package/dist/controllers/oauthRelayController.js.map +1 -0
  26. package/dist/controllers/personalOAuthController.js +10 -1
  27. package/dist/controllers/personalOAuthController.js.map +1 -1
  28. package/dist/controllers/serverController.js +23 -14
  29. package/dist/controllers/serverController.js.map +1 -1
  30. package/dist/controllers/userController.js +11 -1
  31. package/dist/controllers/userController.js.map +1 -1
  32. package/dist/dao/BearerKeyDao.js +10 -5
  33. package/dist/dao/BearerKeyDao.js.map +1 -1
  34. package/dist/dao/BearerKeyDaoDbImpl.js +16 -5
  35. package/dist/dao/BearerKeyDaoDbImpl.js.map +1 -1
  36. package/dist/dao/GroupDaoDbImpl.js +11 -0
  37. package/dist/dao/GroupDaoDbImpl.js.map +1 -1
  38. package/dist/dao/ServerDao.js +5 -1
  39. package/dist/dao/ServerDao.js.map +1 -1
  40. package/dist/dao/ServerDaoDbImpl.js +3 -0
  41. package/dist/dao/ServerDaoDbImpl.js.map +1 -1
  42. package/dist/dao/UserDaoDbImpl.js +4 -0
  43. package/dist/dao/UserDaoDbImpl.js.map +1 -1
  44. package/dist/db/connection.js +6 -2
  45. package/dist/db/connection.js.map +1 -1
  46. package/dist/db/entities/BearerKey.js +8 -0
  47. package/dist/db/entities/BearerKey.js.map +1 -1
  48. package/dist/db/entities/Group.js +4 -0
  49. package/dist/db/entities/Group.js.map +1 -1
  50. package/dist/db/entities/OAuthState.js +43 -0
  51. package/dist/db/entities/OAuthState.js.map +1 -0
  52. package/dist/db/entities/Server.js +4 -0
  53. package/dist/db/entities/Server.js.map +1 -1
  54. package/dist/db/entities/User.js +4 -0
  55. package/dist/db/entities/User.js.map +1 -1
  56. package/dist/db/entities/index.js +3 -1
  57. package/dist/db/entities/index.js.map +1 -1
  58. package/dist/db/replicaSchema.js +40 -0
  59. package/dist/db/replicaSchema.js.map +1 -0
  60. package/dist/db/repositories/ServerRepository.js +1 -0
  61. package/dist/db/repositories/ServerRepository.js.map +1 -1
  62. package/dist/db/setup.js +25 -0
  63. package/dist/db/setup.js.map +1 -0
  64. package/dist/db/transactionContext.js +21 -0
  65. package/dist/db/transactionContext.js.map +1 -0
  66. package/dist/index.js +2 -0
  67. package/dist/index.js.map +1 -1
  68. package/dist/middlewares/auth.js +7 -1
  69. package/dist/middlewares/auth.js.map +1 -1
  70. package/dist/middlewares/replicaConfig.js +134 -0
  71. package/dist/middlewares/replicaConfig.js.map +1 -0
  72. package/dist/middlewares/userContext.js +1 -1
  73. package/dist/middlewares/userContext.js.map +1 -1
  74. package/dist/models/OAuth.js +57 -7
  75. package/dist/models/OAuth.js.map +1 -1
  76. package/dist/routes/index.js +16 -1
  77. package/dist/routes/index.js.map +1 -1
  78. package/dist/server.js +13 -4
  79. package/dist/server.js.map +1 -1
  80. package/dist/services/authorizationService.js.map +1 -1
  81. package/dist/services/capabilitySnapshotService.js +2 -1
  82. package/dist/services/capabilitySnapshotService.js.map +1 -1
  83. package/dist/services/credentialBindingService.js +13 -1
  84. package/dist/services/credentialBindingService.js.map +1 -1
  85. package/dist/services/dataService.js +4 -2
  86. package/dist/services/dataService.js.map +1 -1
  87. package/dist/services/groupService.js +15 -7
  88. package/dist/services/groupService.js.map +1 -1
  89. package/dist/services/mcpEventBus.js +6 -0
  90. package/dist/services/mcpEventBus.js.map +1 -0
  91. package/dist/services/mcpOAuthProvider.js +91 -5
  92. package/dist/services/mcpOAuthProvider.js.map +1 -1
  93. package/dist/services/mcpService.js +136 -9
  94. package/dist/services/mcpService.js.map +1 -1
  95. package/dist/services/metricsService.js +4 -0
  96. package/dist/services/metricsService.js.map +1 -1
  97. package/dist/services/oauthClientRegistration.js +21 -1
  98. package/dist/services/oauthClientRegistration.js.map +1 -1
  99. package/dist/services/oauthServerService.js +5 -6
  100. package/dist/services/oauthServerService.js.map +1 -1
  101. package/dist/services/oauthSettingsStore.js +21 -0
  102. package/dist/services/oauthSettingsStore.js.map +1 -1
  103. package/dist/services/personalOAuthService.js +42 -2
  104. package/dist/services/personalOAuthService.js.map +1 -1
  105. package/dist/services/replicaLock.js +30 -0
  106. package/dist/services/replicaLock.js.map +1 -0
  107. package/dist/services/replicaService.js +111 -0
  108. package/dist/services/replicaService.js.map +1 -0
  109. package/dist/services/requestContextService.js +15 -0
  110. package/dist/services/requestContextService.js.map +1 -1
  111. package/dist/services/serverConfigEnvironment.js +2 -1
  112. package/dist/services/serverConfigEnvironment.js.map +1 -1
  113. package/dist/services/sseService.js +61 -8
  114. package/dist/services/sseService.js.map +1 -1
  115. package/dist/services/templateService.js +11 -5
  116. package/dist/services/templateService.js.map +1 -1
  117. package/dist/services/userService.js +5 -1
  118. package/dist/services/userService.js.map +1 -1
  119. package/dist/utils/groupAccess.js +6 -4
  120. package/dist/utils/groupAccess.js.map +1 -1
  121. package/dist/utils/groupKeyScope.js +11 -5
  122. package/dist/utils/groupKeyScope.js.map +1 -1
  123. package/dist/utils/logger.js +7 -0
  124. package/dist/utils/logger.js.map +1 -1
  125. package/dist/utils/migration.js +8 -0
  126. package/dist/utils/migration.js.map +1 -1
  127. package/dist/utils/oauthBearer.js +1 -0
  128. package/dist/utils/oauthBearer.js.map +1 -1
  129. package/dist/utils/oauthServerMetadata.js +21 -0
  130. package/dist/utils/oauthServerMetadata.js.map +1 -1
  131. package/dist/utils/replicaLogContext.js +3 -0
  132. package/dist/utils/replicaLogContext.js.map +1 -0
  133. package/dist/utils/replicaMode.js +17 -0
  134. package/dist/utils/replicaMode.js.map +1 -0
  135. package/dist/utils/serverConfigPersistence.js +20 -1
  136. package/dist/utils/serverConfigPersistence.js.map +1 -1
  137. package/dist/utils/serverConfigValidation.js +1 -0
  138. package/dist/utils/serverConfigValidation.js.map +1 -1
  139. package/dist/utils/settingsSync.js +4 -0
  140. package/dist/utils/settingsSync.js.map +1 -1
  141. package/frontend/dist/assets/{ActivityPage-C8Zj4FeE.js → ActivityPage-CSXEpl6y.js} +2 -2
  142. package/frontend/dist/assets/{ActivityPage-C8Zj4FeE.js.map → ActivityPage-CSXEpl6y.js.map} +1 -1
  143. package/frontend/dist/assets/{ConfirmDialog-BYdfb115.js → ConfirmDialog-BJpzQmMw.js} +2 -2
  144. package/frontend/dist/assets/{ConfirmDialog-BYdfb115.js.map → ConfirmDialog-BJpzQmMw.js.map} +1 -1
  145. package/frontend/dist/assets/CredentialsPage-CPxOHQUZ.js +2 -0
  146. package/frontend/dist/assets/CredentialsPage-CPxOHQUZ.js.map +1 -0
  147. package/frontend/dist/assets/{Dashboard-CCiZcGi4.js → Dashboard-Da-YT_l_.js} +2 -2
  148. package/frontend/dist/assets/{Dashboard-CCiZcGi4.js.map → Dashboard-Da-YT_l_.js.map} +1 -1
  149. package/frontend/dist/assets/{DeleteDialog-BaCsEkJA.js → DeleteDialog-BoMYLx3J.js} +2 -2
  150. package/frontend/dist/assets/{DeleteDialog-BaCsEkJA.js.map → DeleteDialog-BoMYLx3J.js.map} +1 -1
  151. package/frontend/dist/assets/{EndpointCopy-CmKx4RVL.js → EndpointCopy-CZOjiFAH.js} +2 -2
  152. package/frontend/dist/assets/{EndpointCopy-CmKx4RVL.js.map → EndpointCopy-CZOjiFAH.js.map} +1 -1
  153. package/frontend/dist/assets/GroupsPage-CSA5G9_H.js +33 -0
  154. package/frontend/dist/assets/GroupsPage-CSA5G9_H.js.map +1 -0
  155. package/frontend/dist/assets/{LoginPage-Hn1uu0vB.js → LoginPage-7RswUPtG.js} +2 -2
  156. package/frontend/dist/assets/{LoginPage-Hn1uu0vB.js.map → LoginPage-7RswUPtG.js.map} +1 -1
  157. package/frontend/dist/assets/{LogsPage-JMCtTjCv.js → LogsPage-Dbef_68F.js} +2 -2
  158. package/frontend/dist/assets/{LogsPage-JMCtTjCv.js.map → LogsPage-Dbef_68F.js.map} +1 -1
  159. package/frontend/dist/assets/MarketPage-rSBdHZxo.js +2 -0
  160. package/frontend/dist/assets/{MarketPage-Bvi1KESo.js.map → MarketPage-rSBdHZxo.js.map} +1 -1
  161. package/frontend/dist/assets/{OAuthConsentPage-DofQEZAU.js → OAuthConsentPage-BH9O7bk3.js} +2 -2
  162. package/frontend/dist/assets/{OAuthConsentPage-DofQEZAU.js.map → OAuthConsentPage-BH9O7bk3.js.map} +1 -1
  163. package/frontend/dist/assets/{Pagination-D99WHhBx.js → Pagination-S-7lzy59.js} +2 -2
  164. package/frontend/dist/assets/{Pagination-D99WHhBx.js.map → Pagination-S-7lzy59.js.map} +1 -1
  165. package/frontend/dist/assets/{PromptsPage-B-8vczAR.js → PromptsPage-B558MhVU.js} +2 -2
  166. package/frontend/dist/assets/{PromptsPage-B-8vczAR.js.map → PromptsPage-B558MhVU.js.map} +1 -1
  167. package/frontend/dist/assets/{ResourcesPage-DLAIatoG.js → ResourcesPage-DQpy8B9L.js} +2 -2
  168. package/frontend/dist/assets/{ResourcesPage-DLAIatoG.js.map → ResourcesPage-DQpy8B9L.js.map} +1 -1
  169. package/frontend/dist/assets/{ServersPage-wVLsTL_f.js → ServersPage-DBcC8pG2.js} +5 -5
  170. package/frontend/dist/assets/ServersPage-DBcC8pG2.js.map +1 -0
  171. package/frontend/dist/assets/SettingsPage-BcpeHFR3.js +14 -0
  172. package/frontend/dist/assets/SettingsPage-BcpeHFR3.js.map +1 -0
  173. package/frontend/dist/assets/{StatusDot-00-sTQKv.js → StatusDot-CLxRrJ5l.js} +2 -2
  174. package/frontend/dist/assets/{StatusDot-00-sTQKv.js.map → StatusDot-CLxRrJ5l.js.map} +1 -1
  175. package/frontend/dist/assets/{ToggleGroup-CtWBng3r.js → ToggleGroup-DuWJZU41.js} +2 -2
  176. package/frontend/dist/assets/{ToggleGroup-CtWBng3r.js.map → ToggleGroup-DuWJZU41.js.map} +1 -1
  177. package/frontend/dist/assets/UserGroupSelection-CN0weGXJ.js +2 -0
  178. package/frontend/dist/assets/UserGroupSelection-CN0weGXJ.js.map +1 -0
  179. package/frontend/dist/assets/UsersPage-B158Bofs.js +2 -0
  180. package/frontend/dist/assets/UsersPage-B158Bofs.js.map +1 -0
  181. package/frontend/dist/assets/{clipboard-2RRFM-q8.js → clipboard-BLr_gbf8.js} +2 -2
  182. package/frontend/dist/assets/{clipboard-2RRFM-q8.js.map → clipboard-BLr_gbf8.js.map} +1 -1
  183. package/frontend/dist/assets/{costRevision-Ntl7VtWo.js → costRevision-Dzec2k_b.js} +2 -2
  184. package/frontend/dist/assets/{costRevision-Ntl7VtWo.js.map → costRevision-Dzec2k_b.js.map} +1 -1
  185. package/frontend/dist/assets/framework-vendor-D0S_ys6r.js +61 -0
  186. package/frontend/dist/assets/framework-vendor-D0S_ys6r.js.map +1 -0
  187. package/frontend/dist/assets/{i18n-vendor-DVmjrzgW.js → i18n-vendor-COTriSc6.js} +2 -2
  188. package/frontend/dist/assets/{i18n-vendor-DVmjrzgW.js.map → i18n-vendor-COTriSc6.js.map} +1 -1
  189. package/frontend/dist/assets/{icons-vendor-CyAS6fj0.js → icons-vendor-DZjjGrOu.js} +2 -2
  190. package/frontend/dist/assets/{icons-vendor-CyAS6fj0.js.map → icons-vendor-DZjjGrOu.js.map} +1 -1
  191. package/frontend/dist/assets/index-CGRjM_NC.js +3 -0
  192. package/frontend/dist/assets/{index-CkSmxNPW.js.map → index-CGRjM_NC.js.map} +1 -1
  193. package/frontend/dist/assets/{resourceService-BB4UM6IQ.js → resourceService-BNH7uNar.js} +2 -2
  194. package/frontend/dist/assets/{resourceService-BB4UM6IQ.js.map → resourceService-BNH7uNar.js.map} +1 -1
  195. package/frontend/dist/assets/{useCostData-C3XnQyUj.js → useCostData-B2d2eLCD.js} +2 -2
  196. package/frontend/dist/assets/{useCostData-C3XnQyUj.js.map → useCostData-B2d2eLCD.js.map} +1 -1
  197. package/frontend/dist/assets/variableDetection-DRdE941j.js +80 -0
  198. package/frontend/dist/assets/variableDetection-DRdE941j.js.map +1 -0
  199. package/frontend/dist/index.html +4 -4
  200. package/package.json +4 -2
  201. package/frontend/dist/assets/CredentialsPage-BnzqPYjg.js +0 -2
  202. package/frontend/dist/assets/CredentialsPage-BnzqPYjg.js.map +0 -1
  203. package/frontend/dist/assets/GroupsPage-DHgQeVHy.js +0 -33
  204. package/frontend/dist/assets/GroupsPage-DHgQeVHy.js.map +0 -1
  205. package/frontend/dist/assets/MarketPage-Bvi1KESo.js +0 -2
  206. package/frontend/dist/assets/ServersPage-wVLsTL_f.js.map +0 -1
  207. package/frontend/dist/assets/SettingsPage-DkfXDE5_.js +0 -14
  208. package/frontend/dist/assets/SettingsPage-DkfXDE5_.js.map +0 -1
  209. package/frontend/dist/assets/UsersPage-BtdFWcVD.js +0 -2
  210. package/frontend/dist/assets/UsersPage-BtdFWcVD.js.map +0 -1
  211. package/frontend/dist/assets/framework-vendor-CQFm9vKd.js +0 -61
  212. package/frontend/dist/assets/framework-vendor-CQFm9vKd.js.map +0 -1
  213. package/frontend/dist/assets/index-CkSmxNPW.js +0 -3
  214. package/frontend/dist/assets/variableDetection-BUXwrSop.js +0 -18
  215. package/frontend/dist/assets/variableDetection-BUXwrSop.js.map +0 -1
@@ -1,3 +0,0 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./LoginPage-Hn1uu0vB.js","./framework-vendor-CQFm9vKd.js","./i18n-vendor-DVmjrzgW.js","./icons-vendor-CyAS6fj0.js","./OAuthConsentPage-DofQEZAU.js","./Dashboard-CCiZcGi4.js","./useCostData-C3XnQyUj.js","./clipboard-2RRFM-q8.js","./contextCost-CilWqGWT.js","./EndpointCopy-CmKx4RVL.js","./StatusDot-00-sTQKv.js","./CredentialsPage-BnzqPYjg.js","./ServersPage-wVLsTL_f.js","./ToggleGroup-CtWBng3r.js","./costRevision-Ntl7VtWo.js","./DeleteDialog-BaCsEkJA.js","./ConfirmDialog-BYdfb115.js","./variableDetection-BUXwrSop.js","./Pagination-D99WHhBx.js","./GroupsPage-DHgQeVHy.js","./UsersPage-BtdFWcVD.js","./passwordValidation-DTLWgUy9.js","./SettingsPage-DkfXDE5_.js","./MarketPage-Bvi1KESo.js","./LogsPage-JMCtTjCv.js","./ActivityPage-C8Zj4FeE.js","./PromptsPage-B-8vczAR.js","./ResourcesPage-DLAIatoG.js"])))=>i.map(i=>d[i]);
2
- var ta=Object.defineProperty;var aa=(e,r,t)=>r in e?ta(e,r,{enumerable:!0,configurable:!0,writable:!0,value:t}):e[r]=t;var Ae=(e,r,t)=>aa(e,typeof r!="symbol"?r+"":r,t);import{c as na,r as d,j as a,R as ze,u as ia,b as Qr,d as oa,N as sa,O as Zr,e as Ue,B as la,f as ca,g as V,h as Er}from"./framework-vendor-CQFm9vKd.js";import{u as _,i as da,B as ua,a as ma}from"./i18n-vendor-DVmjrzgW.js";import{X as xe,C as pa,M as ha,S as ga,a as ba,B as va,R as Ir,b as ya,A as Nr,U as fa,c as et,I as ka,L as Sa,d as Ca,e as Pa,f as Aa,g as Ra,F as Ta,h as xa,i as wa,j as Da,k as Ea,K as Ia}from"./icons-vendor-CyAS6fj0.js";(function(){const r=document.createElement("link").relList;if(r&&r.supports&&r.supports("modulepreload"))return;for(const i of document.querySelectorAll('link[rel="modulepreload"]'))n(i);new MutationObserver(i=>{for(const l of i)if(l.type==="childList")for(const s of l.addedNodes)s.tagName==="LINK"&&s.rel==="modulepreload"&&n(s)}).observe(document,{childList:!0,subtree:!0});function t(i){const l={};return i.integrity&&(l.integrity=i.integrity),i.referrerPolicy&&(l.referrerPolicy=i.referrerPolicy),i.crossOrigin==="use-credentials"?l.credentials="include":i.crossOrigin==="anonymous"?l.credentials="omit":l.credentials="same-origin",l}function n(i){if(i.ep)return;i.ep=!0;const l=t(i);fetch(i.href,l)}})();const Na="modulepreload",Oa=function(e,r){return new URL(e,r).href},Or={},ee=function(r,t,n){let i=Promise.resolve();if(t&&t.length>0){let s=function(h){return Promise.all(h.map(g=>Promise.resolve(g).then(A=>({status:"fulfilled",value:A}),A=>({status:"rejected",reason:A}))))};const u=document.getElementsByTagName("link"),o=document.querySelector("meta[property=csp-nonce]"),m=(o==null?void 0:o.nonce)||(o==null?void 0:o.getAttribute("nonce"));i=s(t.map(h=>{if(h=Oa(h,n),h in Or)return;Or[h]=!0;const g=h.endsWith(".css"),A=g?'[rel="stylesheet"]':"";if(!!n)for(let x=u.length-1;x>=0;x--){const L=u[x];if(L.href===h&&(!g||L.rel==="stylesheet"))return}else if(document.querySelector(`link[href="${h}"]${A}`))return;const O=document.createElement("link");if(O.rel=g?"stylesheet":Na,g||(O.as="script"),O.crossOrigin="",O.href=h,m&&O.setAttribute("nonce",m),document.head.appendChild(O),g)return new Promise((x,L)=>{O.addEventListener("load",x),O.addEventListener("error",()=>L(new Error(`Unable to preload CSS for ${h}`)))})}))}function l(s){const u=new Event("vite:preloadError",{cancelable:!0});if(u.payload=s,window.dispatchEvent(u),!u.defaultPrevented)throw s}return i.then(s=>{for(const u of s||[])u.status==="rejected"&&l(u.reason);return r().catch(l)})},rt=()=>window.__MCPHUB_CONFIG__||{basePath:"",version:"dev",name:"mcphub"},Fe=()=>{const r=rt().basePath||"";return r&&!r.startsWith("/")?"/"+r:r},Ma=()=>Fe()+"/api",tt=e=>{const r=Ma(),t=e.startsWith("/")?e:"/"+e;return r+t},La=async()=>{try{const e=window.location.pathname,r=[e.replace(/\/[^/]*$/,"")+"/config","/config",...e.includes("/")?[e.split("/")[1]?`/${e.split("/")[1]}/config`:"/config"]:["/config"]];for(const t of r)try{const n=await fetch(t,{method:"GET",headers:{Accept:"application/json","Cache-Control":"no-cache"}});if(n.ok){const i=await n.json();if(i.success&&i.data)return i.data}}catch(n){console.debug(`Failed to load config from ${t}:`,n)}return console.warn("Could not load runtime config from server, using defaults"),{basePath:"",version:"dev",name:"mcphub"}}catch(e){return console.error("Error loading runtime config:",e),{basePath:"",version:"dev",name:"mcphub"}}},dd=()=>rt().smartRoutingPath||"$smart",Me=[];let $e=null,je=null;const Re=new WeakMap;typeof document<"u"&&document.addEventListener("click",e=>{const r=e.target,t=r==null?void 0:r.closest("button");t&&($e=t,je&&clearTimeout(je),je=setTimeout(()=>{$e=null},100))},!0);const za=e=>{Me.push(e)},at=async(e,r={})=>{let t=e.toString(),n={...r};const i=$e;if(i){const l=Re.get(i)||0;Re.set(i,l+1),i.classList.add("is-loading")}try{for(const s of Me)if(s.request){const u=await s.request(t,n);t=u.url,n=u.config}let l=await fetch(t,n);for(const s of Me)s.response&&(l=await s.response(l));return l}catch(l){let s=l;for(const u of Me)u.error&&(s=await u.error(s));throw s}finally{if(i){const l=Re.get(i)||0;l<=1?(Re.delete(i),i.classList.remove("is-loading")):Re.set(i,l-1)}}},Ke=async(e,r={})=>{try{const t=tt(e),n=await at(t,r);let i;try{i=await n.json()}catch{i={success:n.ok,message:n.ok?"Request successful":`HTTP ${n.status}: ${n.statusText}`}}if(!n.ok&&typeof i=="object"&&i!==null){const l=i;l.success!==!1&&(l.success=!1,l.message=l.message||`HTTP ${n.status}: ${n.statusText}`)}return i}catch(t){return console.error("API request error:",t),{success:!1,message:t instanceof Error?t.message:"An unknown error occurred"}}},Y=(e,r={})=>Ke(e,{...r,method:"GET"}),oe=(e,r,t={})=>Ke(e,{...t,method:"POST",headers:{"Content-Type":"application/json",...t.headers},body:r?JSON.stringify(r):void 0}),K=(e,r,t={})=>Ke(e,{...t,method:"PUT",headers:{"Content-Type":"application/json",...t.headers},body:r?JSON.stringify(r):void 0}),Se=(e,r={})=>Ke(e,{...r,method:"DELETE"}),We="mcphub_token",we=()=>localStorage.getItem(We),nt=e=>{localStorage.setItem(We,e)},qe=()=>{localStorage.removeItem(We)},Ua={request:async(e,r)=>{const t=new Headers(r.headers),n=localStorage.getItem("i18nextLng")||"en";t.set("Accept-Language",n);const i=we();return i&&t.set("x-auth-token",i),{url:e,config:{...r,headers:t,credentials:r.credentials??"include"}}},response:async e=>(e.status===401&&qe(),e),error:async e=>(console.error("Auth interceptor error:",e),e)},qa=()=>{za(Ua)},Ba=e=>e?e.startsWith("/")?e:`/${e}`:"/api/auth/better",it=e=>{if(typeof window>"u")return"";const r=Fe(),t=Ba(e||"/api/auth/better");return`${window.location.origin}${r}${t}`},Fa=e=>na({baseURL:it(e),fetchOptions:{credentials:"include"}}),ud=async({providerId:e,callbackURL:r,errorCallbackURL:t,basePathOverride:n})=>{const i=await fetch(`${it(n)}/sign-in/oauth2`,{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify({providerId:e,callbackURL:r,errorCallbackURL:t})});if(!i.ok)throw new Error("OIDC sign-in request failed.");const l=await i.json().catch(()=>({}));if(!l.redirect||!l.url)throw new Error("OIDC sign-in did not return a redirect URL.");window.location.assign(l.url)},Ka=Fa(),ja=async e=>{try{const r=await oe("/auth/login",e);return r.success&&r.token?(nt(r.token),r):{success:!1,message:r.message||"Login failed"}}catch(r){return console.error("Login error",{error:r}),{success:!1,message:r instanceof Error?r.message:"An error occurred during login"}}},Ga=async e=>{try{const r=await oe("/auth/register",e);return r.success&&r.token?(nt(r.token),r):{success:!1,message:r.message||"Registration failed"}}catch(r){return console.error("Register error",{error:r}),{success:!1,message:r instanceof Error?r.message:"An error occurred during registration"}}},Ha=async()=>{if(!we())return{success:!1,message:"No authentication token"};try{return await Y("/auth/user")}catch(r){return console.error("Get current user error",{error:r}),{success:!1,message:"An error occurred while fetching user data"}}},Ge=async()=>{try{return await Y("/better-auth/user")}catch(e){return console.error("Get Better Auth user error",{error:e}),{success:!1,message:"An error occurred while fetching user data"}}},md=async e=>{if(!we())return{success:!1,message:"No authentication token"};try{return await oe("/auth/change-password",e)}catch(t){return console.error("Change password error",{error:t}),{success:!1,message:"An error occurred while changing password"}}},_a=()=>{qe(),Ka.signOut().catch(e=>{console.debug("Better Auth sign out failed",{error:e})})},ot=async()=>{var e,r,t,n,i;try{const l=Fe(),s=await at(`${l}/public-config`,{method:"GET",headers:{"Content-Type":"application/json"}});if(s.ok){const u=await s.json();return{dashboardName:(e=u.data)==null?void 0:e.dashboardName,skipAuth:((r=u.data)==null?void 0:r.skipAuth)===!0,allowRegistration:((t=u.data)==null?void 0:t.allowRegistration)===!0,permissions:((n=u.data)==null?void 0:n.permissions)||{},betterAuth:(i=u.data)==null?void 0:i.betterAuth}}return{skipAuth:!1}}catch(l){return console.debug("Failed to get public config:",l),{skipAuth:!1}}},ie={isAuthenticated:!1,loading:!0,user:null,error:null},st=d.createContext({auth:ie,login:async()=>({success:!1}),register:async()=>!1,logout:()=>{}}),Va=({children:e})=>{const[r,t]=d.useState(ie);d.useEffect(()=>{(async()=>{const{skipAuth:u,permissions:o}=await ot();if(u){t({isAuthenticated:!0,loading:!1,user:{username:"guest",isAdmin:!0,permissions:o},error:null});return}if(!we()){const h=await Ge();if(h.success&&h.user){t({isAuthenticated:!0,loading:!1,user:h.user,error:null});return}t({...ie,loading:!1});return}try{const h=await Ha();if(h.success&&h.user)t({isAuthenticated:!0,loading:!1,user:h.user,error:null});else{qe();const g=await Ge();g.success&&g.user?t({isAuthenticated:!0,loading:!1,user:g.user,error:null}):t({...ie,loading:!1})}}catch{qe();const g=await Ge();g.success&&g.user?t({isAuthenticated:!0,loading:!1,user:g.user,error:null}):t({...ie,loading:!1})}})()},[]);const n=async(s,u)=>{try{const o=await ja({username:s,password:u});return o.success&&o.token&&o.user?(t({isAuthenticated:!0,loading:!1,user:o.user,error:null}),{success:!0,isUsingDefaultPassword:o.isUsingDefaultPassword}):(t({...ie,loading:!1,error:o.message||"Authentication failed"}),{success:!1,message:o.message})}catch(o){return t({...ie,loading:!1,error:"Authentication failed"}),{success:!1,message:o instanceof Error?o.message:void 0}}},i=async(s,u,o=!1)=>{try{const m=await Ga({username:s,password:u,isAdmin:o});return m.success&&m.token&&m.user?(t({isAuthenticated:!0,loading:!1,user:m.user,error:null}),!0):(t({...ie,loading:!1,error:m.message||"Registration failed"}),!1)}catch{return t({...ie,loading:!1,error:"Registration failed"}),!1}},l=()=>{_a(),t({...ie,loading:!1})};return a.jsx(st.Provider,{value:{auth:r,login:n,register:i,logout:l},children:e})},Ce=()=>d.useContext(st);function lt(e){var r,t,n="";if(typeof e=="string"||typeof e=="number")n+=e;else if(typeof e=="object")if(Array.isArray(e)){var i=e.length;for(r=0;r<i;r++)e[r]&&(t=lt(e[r]))&&(n&&(n+=" "),n+=t)}else for(t in e)e[t]&&(n&&(n+=" "),n+=t);return n}function $a(){for(var e,r,t=0,n="",i=arguments.length;t<i;t++)(e=arguments[t])&&(r=lt(e))&&(n&&(n+=" "),n+=r);return n}const Ja=(e,r)=>{const t=new Array(e.length+r.length);for(let n=0;n<e.length;n++)t[n]=e[n];for(let n=0;n<r.length;n++)t[e.length+n]=r[n];return t},Wa=(e,r)=>({classGroupId:e,validator:r}),ct=(e=new Map,r=null,t)=>({nextPart:e,validators:r,classGroupId:t}),Be="-",Mr=[],Ya="arbitrary..",Xa=e=>{const r=Za(e),{conflictingClassGroups:t,conflictingClassGroupModifiers:n}=e;return{getClassGroupId:s=>{if(s.startsWith("[")&&s.endsWith("]"))return Qa(s);const u=s.split(Be),o=u[0]===""&&u.length>1?1:0;return dt(u,o,r)},getConflictingClassGroupIds:(s,u)=>{if(u){const o=n[s],m=t[s];return o?m?Ja(m,o):o:m||Mr}return t[s]||Mr}}},dt=(e,r,t)=>{if(e.length-r===0)return t.classGroupId;const i=e[r],l=t.nextPart.get(i);if(l){const m=dt(e,r+1,l);if(m)return m}const s=t.validators;if(s===null)return;const u=r===0?e.join(Be):e.slice(r).join(Be),o=s.length;for(let m=0;m<o;m++){const h=s[m];if(h.validator(u))return h.classGroupId}},Qa=e=>e.slice(1,-1).indexOf(":")===-1?void 0:(()=>{const r=e.slice(1,-1),t=r.indexOf(":"),n=r.slice(0,t);return n?Ya+n:void 0})(),Za=e=>{const{theme:r,classGroups:t}=e;return en(t,r)},en=(e,r)=>{const t=ct();for(const n in e){const i=e[n];Ye(i,t,n,r)}return t},Ye=(e,r,t,n)=>{const i=e.length;for(let l=0;l<i;l++){const s=e[l];rn(s,r,t,n)}},rn=(e,r,t,n)=>{if(typeof e=="string"){tn(e,r,t);return}if(typeof e=="function"){an(e,r,t,n);return}nn(e,r,t,n)},tn=(e,r,t)=>{const n=e===""?r:ut(r,e);n.classGroupId=t},an=(e,r,t,n)=>{if(on(e)){Ye(e(n),r,t,n);return}r.validators===null&&(r.validators=[]),r.validators.push(Wa(t,e))},nn=(e,r,t,n)=>{const i=Object.entries(e),l=i.length;for(let s=0;s<l;s++){const[u,o]=i[s];Ye(o,ut(r,u),t,n)}},ut=(e,r)=>{let t=e;const n=r.split(Be),i=n.length;for(let l=0;l<i;l++){const s=n[l];let u=t.nextPart.get(s);u||(u=ct(),t.nextPart.set(s,u)),t=u}return t},on=e=>"isThemeGetter"in e&&e.isThemeGetter===!0,sn=e=>{if(e<1)return{get:()=>{},set:()=>{}};let r=0,t=Object.create(null),n=Object.create(null);const i=(l,s)=>{t[l]=s,r++,r>e&&(r=0,n=t,t=Object.create(null))};return{get(l){let s=t[l];if(s!==void 0)return s;if((s=n[l])!==void 0)return i(l,s),s},set(l,s){l in t?t[l]=s:i(l,s)}}},Je="!",Lr=":",ln=[],zr=(e,r,t,n,i)=>({modifiers:e,hasImportantModifier:r,baseClassName:t,maybePostfixModifierPosition:n,isExternal:i}),cn=e=>{const{prefix:r,experimentalParseClassName:t}=e;let n=i=>{const l=[];let s=0,u=0,o=0,m;const h=i.length;for(let x=0;x<h;x++){const L=i[x];if(s===0&&u===0){if(L===Lr){l.push(i.slice(o,x)),o=x+1;continue}if(L==="/"){m=x;continue}}L==="["?s++:L==="]"?s--:L==="("?u++:L===")"&&u--}const g=l.length===0?i:i.slice(o);let A=g,D=!1;g.endsWith(Je)?(A=g.slice(0,-1),D=!0):g.startsWith(Je)&&(A=g.slice(1),D=!0);const O=m&&m>o?m-o:void 0;return zr(l,D,A,O)};if(r){const i=r+Lr,l=n;n=s=>s.startsWith(i)?l(s.slice(i.length)):zr(ln,!1,s,void 0,!0)}if(t){const i=n;n=l=>t({className:l,parseClassName:i})}return n},dn=e=>{const r=new Map;return e.orderSensitiveModifiers.forEach((t,n)=>{r.set(t,1e6+n)}),t=>{const n=[];let i=[];for(let l=0;l<t.length;l++){const s=t[l],u=s[0]==="[",o=r.has(s);u||o?(i.length>0&&(i.sort(),n.push(...i),i=[]),n.push(s)):i.push(s)}return i.length>0&&(i.sort(),n.push(...i)),n}},un=e=>({cache:sn(e.cacheSize),parseClassName:cn(e),sortModifiers:dn(e),postfixLookupClassGroupIds:mn(e),...Xa(e)}),mn=e=>{const r=Object.create(null),t=e.postfixLookupClassGroups;if(t)for(let n=0;n<t.length;n++)r[t[n]]=!0;return r},pn=/\s+/,hn=(e,r)=>{const{parseClassName:t,getClassGroupId:n,getConflictingClassGroupIds:i,sortModifiers:l,postfixLookupClassGroupIds:s}=r,u=[],o=e.trim().split(pn);let m="";for(let h=o.length-1;h>=0;h-=1){const g=o[h],{isExternal:A,modifiers:D,hasImportantModifier:O,baseClassName:x,maybePostfixModifierPosition:L}=t(g);if(A){m=g+(m.length>0?" "+m:m);continue}let E=!!L,I;if(E){const J=x.substring(0,L);I=n(J);const C=I&&s[I]?n(x):void 0;C&&C!==I&&(I=C,E=!1)}else I=n(x);if(!I){if(!E){m=g+(m.length>0?" "+m:m);continue}if(I=n(x),!I){m=g+(m.length>0?" "+m:m);continue}E=!1}const k=D.length===0?"":D.length===1?D[0]:l(D).join(":"),B=O?k+Je:k,M=B+I;if(u.indexOf(M)>-1)continue;u.push(M);const W=i(I,E);for(let J=0;J<W.length;++J){const C=W[J];u.push(B+C)}m=g+(m.length>0?" "+m:m)}return m},gn=(...e)=>{let r=0,t,n,i="";for(;r<e.length;)(t=e[r++])&&(n=mt(t))&&(i&&(i+=" "),i+=n);return i},mt=e=>{if(typeof e=="string")return e;let r,t="";for(let n=0;n<e.length;n++)e[n]&&(r=mt(e[n]))&&(t&&(t+=" "),t+=r);return t},bn=(e,...r)=>{let t,n,i,l;const s=o=>{const m=r.reduce((h,g)=>g(h),e());return t=un(m),n=t.cache.get,i=t.cache.set,l=u,u(o)},u=o=>{const m=n(o);if(m)return m;const h=hn(o,t);return i(o,h),h};return l=s,(...o)=>l(gn(...o))},vn=[],$=e=>{const r=t=>t[e]||vn;return r.isThemeGetter=!0,r},pt=/^\[(?:(\w[\w-]*):)?(.+)\]$/i,ht=/^\((?:(\w[\w-]*):)?(.+)\)$/i,yn=/^\d+(?:\.\d+)?\/\d+(?:\.\d+)?$/,fn=/^(\d+(\.\d+)?)?(xs|sm|md|lg|xl)$/,kn=/\d+(%|px|r?em|[sdl]?v([hwib]|min|max)|pt|pc|in|cm|mm|cap|ch|ex|r?lh|cq(w|h|i|b|min|max))|\b(calc|min|max|clamp)\(.+\)|^0$/,Sn=/^(rgba?|hsla?|hwb|(ok)?(lab|lch)|color-mix)\(.+\)$/,Cn=/^(inset_)?-?((\d+)?\.?(\d+)[a-z]+|0)_-?((\d+)?\.?(\d+)[a-z]+|0)/,Pn=/^(url|image|image-set|cross-fade|element|(repeating-)?(linear|radial|conic)-gradient)\(.+\)$/,ce=e=>yn.test(e),z=e=>!!e&&!Number.isNaN(Number(e)),ne=e=>!!e&&Number.isInteger(Number(e)),He=e=>e.endsWith("%")&&z(e.slice(0,-1)),se=e=>fn.test(e),gt=()=>!0,An=e=>kn.test(e)&&!Sn.test(e),Xe=()=>!1,Rn=e=>Cn.test(e),Tn=e=>Pn.test(e),xn=e=>!y(e)&&!f(e),wn=e=>e.startsWith("@container")&&(e[10]==="/"&&e[11]!==void 0||e[11]==="s"&&e[16]!==void 0&&e.startsWith("-size/",10)||e[11]==="n"&&e[18]!==void 0&&e.startsWith("-normal/",10)),Dn=e=>de(e,yt,Xe),y=e=>pt.test(e),he=e=>de(e,ft,An),Ur=e=>de(e,Un,z),En=e=>de(e,St,gt),In=e=>de(e,kt,Xe),qr=e=>de(e,bt,Xe),Nn=e=>de(e,vt,Tn),Ie=e=>de(e,Ct,Rn),f=e=>ht.test(e),Te=e=>ge(e,ft),On=e=>ge(e,kt),Br=e=>ge(e,bt),Mn=e=>ge(e,yt),Ln=e=>ge(e,vt),Ne=e=>ge(e,Ct,!0),zn=e=>ge(e,St,!0),de=(e,r,t)=>{const n=pt.exec(e);return n?n[1]?r(n[1]):t(n[2]):!1},ge=(e,r,t=!1)=>{const n=ht.exec(e);return n?n[1]?r(n[1]):t:!1},bt=e=>e==="position"||e==="percentage",vt=e=>e==="image"||e==="url",yt=e=>e==="length"||e==="size"||e==="bg-size",ft=e=>e==="length",Un=e=>e==="number",kt=e=>e==="family-name",St=e=>e==="number"||e==="weight",Ct=e=>e==="shadow",qn=()=>{const e=$("color"),r=$("font"),t=$("text"),n=$("font-weight"),i=$("tracking"),l=$("leading"),s=$("breakpoint"),u=$("container"),o=$("spacing"),m=$("radius"),h=$("shadow"),g=$("inset-shadow"),A=$("text-shadow"),D=$("drop-shadow"),O=$("blur"),x=$("perspective"),L=$("aspect"),E=$("ease"),I=$("animate"),k=()=>["auto","avoid","all","avoid-page","page","left","right","column"],B=()=>["center","top","bottom","left","right","top-left","left-top","top-right","right-top","bottom-right","right-bottom","bottom-left","left-bottom"],M=()=>[...B(),f,y],W=()=>["auto","hidden","clip","visible","scroll"],J=()=>["auto","contain","none"],C=()=>[f,y,o],F=()=>[ce,"full","auto",...C()],j=()=>[ne,"none","subgrid",f,y],Q=()=>["auto",{span:["full",ne,f,y]},ne,f,y],le=()=>[ne,"auto",f,y],ue=()=>["auto","min","max","fr",f,y],me=()=>["start","end","center","between","around","evenly","stretch","baseline","center-safe","end-safe"],te=()=>["start","end","center","stretch","center-safe","end-safe"],X=()=>["auto",...C()],re=()=>[ce,"auto","full","dvw","dvh","lvw","lvh","svw","svh","min","max","fit",...C()],pe=()=>[ce,"screen","full","dvw","lvw","svw","min","max","fit",...C()],N=()=>[ce,"screen","full","lh","dvh","lvh","svh","min","max","fit",...C()],w=()=>[e,f,y],T=()=>[...B(),Br,qr,{position:[f,y]}],be=()=>["no-repeat",{repeat:["","x","y","space","round"]}],v=()=>["auto","cover","contain",Mn,Dn,{size:[f,y]}],S=()=>[He,Te,he],R=()=>["","none","full",m,f,y],q=()=>["",z,Te,he],G=()=>["solid","dashed","dotted","double"],Z=()=>["normal","multiply","screen","overlay","darken","lighten","color-dodge","color-burn","hard-light","soft-light","difference","exclusion","hue","saturation","color","luminosity"],U=()=>[z,He,Br,qr],ve=()=>["","none",O,f,y],ye=()=>["none",z,f,y],fe=()=>["none",z,f,y],Pe=()=>[z,f,y],ke=()=>[ce,"full",...C()];return{cacheSize:500,theme:{animate:["spin","ping","pulse","bounce"],aspect:["video"],blur:[se],breakpoint:[se],color:[gt],container:[se],"drop-shadow":[se],ease:["in","out","in-out"],font:[xn],"font-weight":["thin","extralight","light","normal","medium","semibold","bold","extrabold","black"],"inset-shadow":[se],leading:["none","tight","snug","normal","relaxed","loose"],perspective:["dramatic","near","normal","midrange","distant","none"],radius:[se],shadow:[se],spacing:["px",z],text:[se],"text-shadow":[se],tracking:["tighter","tight","normal","wide","wider","widest"]},classGroups:{aspect:[{aspect:["auto","square",ce,y,f,L]}],container:["container"],"container-type":[{"@container":["","normal","size",f,y]}],"container-named":[wn],columns:[{columns:[z,y,f,u]}],"break-after":[{"break-after":k()}],"break-before":[{"break-before":k()}],"break-inside":[{"break-inside":["auto","avoid","avoid-page","avoid-column"]}],"box-decoration":[{"box-decoration":["slice","clone"]}],box:[{box:["border","content"]}],display:["block","inline-block","inline","flex","inline-flex","table","inline-table","table-caption","table-cell","table-column","table-column-group","table-footer-group","table-header-group","table-row-group","table-row","flow-root","grid","inline-grid","contents","list-item","hidden"],sr:["sr-only","not-sr-only"],float:[{float:["right","left","none","start","end"]}],clear:[{clear:["left","right","both","none","start","end"]}],isolation:["isolate","isolation-auto"],"object-fit":[{object:["contain","cover","fill","none","scale-down"]}],"object-position":[{object:M()}],overflow:[{overflow:W()}],"overflow-x":[{"overflow-x":W()}],"overflow-y":[{"overflow-y":W()}],overscroll:[{overscroll:J()}],"overscroll-x":[{"overscroll-x":J()}],"overscroll-y":[{"overscroll-y":J()}],position:["static","fixed","absolute","relative","sticky"],inset:[{inset:F()}],"inset-x":[{"inset-x":F()}],"inset-y":[{"inset-y":F()}],start:[{"inset-s":F(),start:F()}],end:[{"inset-e":F(),end:F()}],"inset-bs":[{"inset-bs":F()}],"inset-be":[{"inset-be":F()}],top:[{top:F()}],right:[{right:F()}],bottom:[{bottom:F()}],left:[{left:F()}],visibility:["visible","invisible","collapse"],z:[{z:[ne,"auto",f,y]}],basis:[{basis:[ce,"full","auto",u,...C()]}],"flex-direction":[{flex:["row","row-reverse","col","col-reverse"]}],"flex-wrap":[{flex:["nowrap","wrap","wrap-reverse"]}],flex:[{flex:[z,ce,"auto","initial","none",y]}],grow:[{grow:["",z,f,y]}],shrink:[{shrink:["",z,f,y]}],order:[{order:[ne,"first","last","none",f,y]}],"grid-cols":[{"grid-cols":j()}],"col-start-end":[{col:Q()}],"col-start":[{"col-start":le()}],"col-end":[{"col-end":le()}],"grid-rows":[{"grid-rows":j()}],"row-start-end":[{row:Q()}],"row-start":[{"row-start":le()}],"row-end":[{"row-end":le()}],"grid-flow":[{"grid-flow":["row","col","dense","row-dense","col-dense"]}],"auto-cols":[{"auto-cols":ue()}],"auto-rows":[{"auto-rows":ue()}],gap:[{gap:C()}],"gap-x":[{"gap-x":C()}],"gap-y":[{"gap-y":C()}],"justify-content":[{justify:[...me(),"normal"]}],"justify-items":[{"justify-items":[...te(),"normal"]}],"justify-self":[{"justify-self":["auto",...te()]}],"align-content":[{content:["normal",...me()]}],"align-items":[{items:[...te(),{baseline:["","last"]}]}],"align-self":[{self:["auto",...te(),{baseline:["","last"]}]}],"place-content":[{"place-content":me()}],"place-items":[{"place-items":[...te(),"baseline"]}],"place-self":[{"place-self":["auto",...te()]}],p:[{p:C()}],px:[{px:C()}],py:[{py:C()}],ps:[{ps:C()}],pe:[{pe:C()}],pbs:[{pbs:C()}],pbe:[{pbe:C()}],pt:[{pt:C()}],pr:[{pr:C()}],pb:[{pb:C()}],pl:[{pl:C()}],m:[{m:X()}],mx:[{mx:X()}],my:[{my:X()}],ms:[{ms:X()}],me:[{me:X()}],mbs:[{mbs:X()}],mbe:[{mbe:X()}],mt:[{mt:X()}],mr:[{mr:X()}],mb:[{mb:X()}],ml:[{ml:X()}],"space-x":[{"space-x":C()}],"space-x-reverse":["space-x-reverse"],"space-y":[{"space-y":C()}],"space-y-reverse":["space-y-reverse"],size:[{size:re()}],"inline-size":[{inline:["auto",...pe()]}],"min-inline-size":[{"min-inline":["auto",...pe()]}],"max-inline-size":[{"max-inline":["none",...pe()]}],"block-size":[{block:["auto",...N()]}],"min-block-size":[{"min-block":["auto",...N()]}],"max-block-size":[{"max-block":["none",...N()]}],w:[{w:[u,"screen",...re()]}],"min-w":[{"min-w":[u,"screen","none",...re()]}],"max-w":[{"max-w":[u,"screen","none","prose",{screen:[s]},...re()]}],h:[{h:["screen","lh",...re()]}],"min-h":[{"min-h":["screen","lh","none",...re()]}],"max-h":[{"max-h":["screen","lh",...re()]}],"font-size":[{text:["base",t,Te,he]}],"font-smoothing":["antialiased","subpixel-antialiased"],"font-style":["italic","not-italic"],"font-weight":[{font:[n,zn,En]}],"font-stretch":[{"font-stretch":["ultra-condensed","extra-condensed","condensed","semi-condensed","normal","semi-expanded","expanded","extra-expanded","ultra-expanded",He,y]}],"font-family":[{font:[On,In,r]}],"font-features":[{"font-features":[y]}],"fvn-normal":["normal-nums"],"fvn-ordinal":["ordinal"],"fvn-slashed-zero":["slashed-zero"],"fvn-figure":["lining-nums","oldstyle-nums"],"fvn-spacing":["proportional-nums","tabular-nums"],"fvn-fraction":["diagonal-fractions","stacked-fractions"],tracking:[{tracking:[i,f,y]}],"line-clamp":[{"line-clamp":[z,"none",f,Ur]}],leading:[{leading:[l,...C()]}],"list-image":[{"list-image":["none",f,y]}],"list-style-position":[{list:["inside","outside"]}],"list-style-type":[{list:["disc","decimal","none",f,y]}],"text-alignment":[{text:["left","center","right","justify","start","end"]}],"placeholder-color":[{placeholder:w()}],"text-color":[{text:w()}],"text-decoration":["underline","overline","line-through","no-underline"],"text-decoration-style":[{decoration:[...G(),"wavy"]}],"text-decoration-thickness":[{decoration:[z,"from-font","auto",f,he]}],"text-decoration-color":[{decoration:w()}],"underline-offset":[{"underline-offset":[z,"auto",f,y]}],"text-transform":["uppercase","lowercase","capitalize","normal-case"],"text-overflow":["truncate","text-ellipsis","text-clip"],"text-wrap":[{text:["wrap","nowrap","balance","pretty"]}],indent:[{indent:C()}],"tab-size":[{tab:[ne,f,y]}],"vertical-align":[{align:["baseline","top","middle","bottom","text-top","text-bottom","sub","super",f,y]}],whitespace:[{whitespace:["normal","nowrap","pre","pre-line","pre-wrap","break-spaces"]}],break:[{break:["normal","words","all","keep"]}],wrap:[{wrap:["break-word","anywhere","normal"]}],hyphens:[{hyphens:["none","manual","auto"]}],content:[{content:["none",f,y]}],"bg-attachment":[{bg:["fixed","local","scroll"]}],"bg-clip":[{"bg-clip":["border","padding","content","text"]}],"bg-origin":[{"bg-origin":["border","padding","content"]}],"bg-position":[{bg:T()}],"bg-repeat":[{bg:be()}],"bg-size":[{bg:v()}],"bg-image":[{bg:["none",{linear:[{to:["t","tr","r","br","b","bl","l","tl"]},ne,f,y],radial:["",f,y],conic:[ne,f,y]},Ln,Nn]}],"bg-color":[{bg:w()}],"gradient-from-pos":[{from:S()}],"gradient-via-pos":[{via:S()}],"gradient-to-pos":[{to:S()}],"gradient-from":[{from:w()}],"gradient-via":[{via:w()}],"gradient-to":[{to:w()}],rounded:[{rounded:R()}],"rounded-s":[{"rounded-s":R()}],"rounded-e":[{"rounded-e":R()}],"rounded-t":[{"rounded-t":R()}],"rounded-r":[{"rounded-r":R()}],"rounded-b":[{"rounded-b":R()}],"rounded-l":[{"rounded-l":R()}],"rounded-ss":[{"rounded-ss":R()}],"rounded-se":[{"rounded-se":R()}],"rounded-ee":[{"rounded-ee":R()}],"rounded-es":[{"rounded-es":R()}],"rounded-tl":[{"rounded-tl":R()}],"rounded-tr":[{"rounded-tr":R()}],"rounded-br":[{"rounded-br":R()}],"rounded-bl":[{"rounded-bl":R()}],"border-w":[{border:q()}],"border-w-x":[{"border-x":q()}],"border-w-y":[{"border-y":q()}],"border-w-s":[{"border-s":q()}],"border-w-e":[{"border-e":q()}],"border-w-bs":[{"border-bs":q()}],"border-w-be":[{"border-be":q()}],"border-w-t":[{"border-t":q()}],"border-w-r":[{"border-r":q()}],"border-w-b":[{"border-b":q()}],"border-w-l":[{"border-l":q()}],"divide-x":[{"divide-x":q()}],"divide-x-reverse":["divide-x-reverse"],"divide-y":[{"divide-y":q()}],"divide-y-reverse":["divide-y-reverse"],"border-style":[{border:[...G(),"hidden","none"]}],"divide-style":[{divide:[...G(),"hidden","none"]}],"border-color":[{border:w()}],"border-color-x":[{"border-x":w()}],"border-color-y":[{"border-y":w()}],"border-color-s":[{"border-s":w()}],"border-color-e":[{"border-e":w()}],"border-color-bs":[{"border-bs":w()}],"border-color-be":[{"border-be":w()}],"border-color-t":[{"border-t":w()}],"border-color-r":[{"border-r":w()}],"border-color-b":[{"border-b":w()}],"border-color-l":[{"border-l":w()}],"divide-color":[{divide:w()}],"outline-style":[{outline:[...G(),"none","hidden"]}],"outline-offset":[{"outline-offset":[z,f,y]}],"outline-w":[{outline:["",z,Te,he]}],"outline-color":[{outline:w()}],shadow:[{shadow:["","none",h,Ne,Ie]}],"shadow-color":[{shadow:w()}],"inset-shadow":[{"inset-shadow":["none",g,Ne,Ie]}],"inset-shadow-color":[{"inset-shadow":w()}],"ring-w":[{ring:q()}],"ring-w-inset":["ring-inset"],"ring-color":[{ring:w()}],"ring-offset-w":[{"ring-offset":[z,he]}],"ring-offset-color":[{"ring-offset":w()}],"inset-ring-w":[{"inset-ring":q()}],"inset-ring-color":[{"inset-ring":w()}],"text-shadow":[{"text-shadow":["none",A,Ne,Ie]}],"text-shadow-color":[{"text-shadow":w()}],opacity:[{opacity:[z,f,y]}],"mix-blend":[{"mix-blend":[...Z(),"plus-darker","plus-lighter"]}],"bg-blend":[{"bg-blend":Z()}],"mask-clip":[{"mask-clip":["border","padding","content","fill","stroke","view"]},"mask-no-clip"],"mask-composite":[{mask:["add","subtract","intersect","exclude"]}],"mask-image-linear-pos":[{"mask-linear":[z]}],"mask-image-linear-from-pos":[{"mask-linear-from":U()}],"mask-image-linear-to-pos":[{"mask-linear-to":U()}],"mask-image-linear-from-color":[{"mask-linear-from":w()}],"mask-image-linear-to-color":[{"mask-linear-to":w()}],"mask-image-t-from-pos":[{"mask-t-from":U()}],"mask-image-t-to-pos":[{"mask-t-to":U()}],"mask-image-t-from-color":[{"mask-t-from":w()}],"mask-image-t-to-color":[{"mask-t-to":w()}],"mask-image-r-from-pos":[{"mask-r-from":U()}],"mask-image-r-to-pos":[{"mask-r-to":U()}],"mask-image-r-from-color":[{"mask-r-from":w()}],"mask-image-r-to-color":[{"mask-r-to":w()}],"mask-image-b-from-pos":[{"mask-b-from":U()}],"mask-image-b-to-pos":[{"mask-b-to":U()}],"mask-image-b-from-color":[{"mask-b-from":w()}],"mask-image-b-to-color":[{"mask-b-to":w()}],"mask-image-l-from-pos":[{"mask-l-from":U()}],"mask-image-l-to-pos":[{"mask-l-to":U()}],"mask-image-l-from-color":[{"mask-l-from":w()}],"mask-image-l-to-color":[{"mask-l-to":w()}],"mask-image-x-from-pos":[{"mask-x-from":U()}],"mask-image-x-to-pos":[{"mask-x-to":U()}],"mask-image-x-from-color":[{"mask-x-from":w()}],"mask-image-x-to-color":[{"mask-x-to":w()}],"mask-image-y-from-pos":[{"mask-y-from":U()}],"mask-image-y-to-pos":[{"mask-y-to":U()}],"mask-image-y-from-color":[{"mask-y-from":w()}],"mask-image-y-to-color":[{"mask-y-to":w()}],"mask-image-radial":[{"mask-radial":[f,y]}],"mask-image-radial-from-pos":[{"mask-radial-from":U()}],"mask-image-radial-to-pos":[{"mask-radial-to":U()}],"mask-image-radial-from-color":[{"mask-radial-from":w()}],"mask-image-radial-to-color":[{"mask-radial-to":w()}],"mask-image-radial-shape":[{"mask-radial":["circle","ellipse"]}],"mask-image-radial-size":[{"mask-radial":[{closest:["side","corner"],farthest:["side","corner"]}]}],"mask-image-radial-pos":[{"mask-radial-at":B()}],"mask-image-conic-pos":[{"mask-conic":[z]}],"mask-image-conic-from-pos":[{"mask-conic-from":U()}],"mask-image-conic-to-pos":[{"mask-conic-to":U()}],"mask-image-conic-from-color":[{"mask-conic-from":w()}],"mask-image-conic-to-color":[{"mask-conic-to":w()}],"mask-mode":[{mask:["alpha","luminance","match"]}],"mask-origin":[{"mask-origin":["border","padding","content","fill","stroke","view"]}],"mask-position":[{mask:T()}],"mask-repeat":[{mask:be()}],"mask-size":[{mask:v()}],"mask-type":[{"mask-type":["alpha","luminance"]}],"mask-image":[{mask:["none",f,y]}],filter:[{filter:["","none",f,y]}],blur:[{blur:ve()}],brightness:[{brightness:[z,f,y]}],contrast:[{contrast:[z,f,y]}],"drop-shadow":[{"drop-shadow":["","none",D,Ne,Ie]}],"drop-shadow-color":[{"drop-shadow":w()}],grayscale:[{grayscale:["",z,f,y]}],"hue-rotate":[{"hue-rotate":[z,f,y]}],invert:[{invert:["",z,f,y]}],saturate:[{saturate:[z,f,y]}],sepia:[{sepia:["",z,f,y]}],"backdrop-filter":[{"backdrop-filter":["","none",f,y]}],"backdrop-blur":[{"backdrop-blur":ve()}],"backdrop-brightness":[{"backdrop-brightness":[z,f,y]}],"backdrop-contrast":[{"backdrop-contrast":[z,f,y]}],"backdrop-grayscale":[{"backdrop-grayscale":["",z,f,y]}],"backdrop-hue-rotate":[{"backdrop-hue-rotate":[z,f,y]}],"backdrop-invert":[{"backdrop-invert":["",z,f,y]}],"backdrop-opacity":[{"backdrop-opacity":[z,f,y]}],"backdrop-saturate":[{"backdrop-saturate":[z,f,y]}],"backdrop-sepia":[{"backdrop-sepia":["",z,f,y]}],"border-collapse":[{border:["collapse","separate"]}],"border-spacing":[{"border-spacing":C()}],"border-spacing-x":[{"border-spacing-x":C()}],"border-spacing-y":[{"border-spacing-y":C()}],"table-layout":[{table:["auto","fixed"]}],caption:[{caption:["top","bottom"]}],transition:[{transition:["","all","colors","opacity","shadow","transform","none",f,y]}],"transition-behavior":[{transition:["normal","discrete"]}],duration:[{duration:[z,"initial",f,y]}],ease:[{ease:["linear","initial",E,f,y]}],delay:[{delay:[z,f,y]}],animate:[{animate:["none",I,f,y]}],backface:[{backface:["hidden","visible"]}],perspective:[{perspective:[x,f,y]}],"perspective-origin":[{"perspective-origin":M()}],rotate:[{rotate:ye()}],"rotate-x":[{"rotate-x":ye()}],"rotate-y":[{"rotate-y":ye()}],"rotate-z":[{"rotate-z":ye()}],scale:[{scale:fe()}],"scale-x":[{"scale-x":fe()}],"scale-y":[{"scale-y":fe()}],"scale-z":[{"scale-z":fe()}],"scale-3d":["scale-3d"],skew:[{skew:Pe()}],"skew-x":[{"skew-x":Pe()}],"skew-y":[{"skew-y":Pe()}],transform:[{transform:[f,y,"","none","gpu","cpu"]}],"transform-origin":[{origin:M()}],"transform-style":[{transform:["3d","flat"]}],translate:[{translate:ke()}],"translate-x":[{"translate-x":ke()}],"translate-y":[{"translate-y":ke()}],"translate-z":[{"translate-z":ke()}],"translate-none":["translate-none"],zoom:[{zoom:[ne,f,y]}],accent:[{accent:w()}],appearance:[{appearance:["none","auto"]}],"caret-color":[{caret:w()}],"color-scheme":[{scheme:["normal","dark","light","light-dark","only-dark","only-light"]}],cursor:[{cursor:["auto","default","pointer","wait","text","move","help","not-allowed","none","context-menu","progress","cell","crosshair","vertical-text","alias","copy","no-drop","grab","grabbing","all-scroll","col-resize","row-resize","n-resize","e-resize","s-resize","w-resize","ne-resize","nw-resize","se-resize","sw-resize","ew-resize","ns-resize","nesw-resize","nwse-resize","zoom-in","zoom-out",f,y]}],"field-sizing":[{"field-sizing":["fixed","content"]}],"pointer-events":[{"pointer-events":["auto","none"]}],resize:[{resize:["none","","y","x"]}],"scroll-behavior":[{scroll:["auto","smooth"]}],"scrollbar-thumb-color":[{"scrollbar-thumb":w()}],"scrollbar-track-color":[{"scrollbar-track":w()}],"scrollbar-gutter":[{"scrollbar-gutter":["auto","stable","both"]}],"scrollbar-w":[{scrollbar:["auto","thin","none"]}],"scroll-m":[{"scroll-m":C()}],"scroll-mx":[{"scroll-mx":C()}],"scroll-my":[{"scroll-my":C()}],"scroll-ms":[{"scroll-ms":C()}],"scroll-me":[{"scroll-me":C()}],"scroll-mbs":[{"scroll-mbs":C()}],"scroll-mbe":[{"scroll-mbe":C()}],"scroll-mt":[{"scroll-mt":C()}],"scroll-mr":[{"scroll-mr":C()}],"scroll-mb":[{"scroll-mb":C()}],"scroll-ml":[{"scroll-ml":C()}],"scroll-p":[{"scroll-p":C()}],"scroll-px":[{"scroll-px":C()}],"scroll-py":[{"scroll-py":C()}],"scroll-ps":[{"scroll-ps":C()}],"scroll-pe":[{"scroll-pe":C()}],"scroll-pbs":[{"scroll-pbs":C()}],"scroll-pbe":[{"scroll-pbe":C()}],"scroll-pt":[{"scroll-pt":C()}],"scroll-pr":[{"scroll-pr":C()}],"scroll-pb":[{"scroll-pb":C()}],"scroll-pl":[{"scroll-pl":C()}],"snap-align":[{snap:["start","end","center","align-none"]}],"snap-stop":[{snap:["normal","always"]}],"snap-type":[{snap:["none","x","y","both"]}],"snap-strictness":[{snap:["mandatory","proximity"]}],touch:[{touch:["auto","none","manipulation"]}],"touch-x":[{"touch-pan":["x","left","right"]}],"touch-y":[{"touch-pan":["y","up","down"]}],"touch-pz":["touch-pinch-zoom"],select:[{select:["none","text","all","auto"]}],"will-change":[{"will-change":["auto","scroll","contents","transform",f,y]}],fill:[{fill:["none",...w()]}],"stroke-w":[{stroke:[z,Te,he,Ur]}],stroke:[{stroke:["none",...w()]}],"forced-color-adjust":[{"forced-color-adjust":["auto","none"]}]},conflictingClassGroups:{"container-named":["container-type"],overflow:["overflow-x","overflow-y"],overscroll:["overscroll-x","overscroll-y"],inset:["inset-x","inset-y","inset-bs","inset-be","start","end","top","right","bottom","left"],"inset-x":["right","left"],"inset-y":["top","bottom"],flex:["basis","grow","shrink"],gap:["gap-x","gap-y"],p:["px","py","ps","pe","pbs","pbe","pt","pr","pb","pl"],px:["pr","pl"],py:["pt","pb"],m:["mx","my","ms","me","mbs","mbe","mt","mr","mb","ml"],mx:["mr","ml"],my:["mt","mb"],size:["w","h"],"font-size":["leading"],"fvn-normal":["fvn-ordinal","fvn-slashed-zero","fvn-figure","fvn-spacing","fvn-fraction"],"fvn-ordinal":["fvn-normal"],"fvn-slashed-zero":["fvn-normal"],"fvn-figure":["fvn-normal"],"fvn-spacing":["fvn-normal"],"fvn-fraction":["fvn-normal"],"line-clamp":["display","overflow"],rounded:["rounded-s","rounded-e","rounded-t","rounded-r","rounded-b","rounded-l","rounded-ss","rounded-se","rounded-ee","rounded-es","rounded-tl","rounded-tr","rounded-br","rounded-bl"],"rounded-s":["rounded-ss","rounded-es"],"rounded-e":["rounded-se","rounded-ee"],"rounded-t":["rounded-tl","rounded-tr"],"rounded-r":["rounded-tr","rounded-br"],"rounded-b":["rounded-br","rounded-bl"],"rounded-l":["rounded-tl","rounded-bl"],"border-spacing":["border-spacing-x","border-spacing-y"],"border-w":["border-w-x","border-w-y","border-w-s","border-w-e","border-w-bs","border-w-be","border-w-t","border-w-r","border-w-b","border-w-l"],"border-w-x":["border-w-r","border-w-l"],"border-w-y":["border-w-t","border-w-b"],"border-color":["border-color-x","border-color-y","border-color-s","border-color-e","border-color-bs","border-color-be","border-color-t","border-color-r","border-color-b","border-color-l"],"border-color-x":["border-color-r","border-color-l"],"border-color-y":["border-color-t","border-color-b"],translate:["translate-x","translate-y","translate-none"],"translate-none":["translate","translate-x","translate-y","translate-z"],"scroll-m":["scroll-mx","scroll-my","scroll-ms","scroll-me","scroll-mbs","scroll-mbe","scroll-mt","scroll-mr","scroll-mb","scroll-ml"],"scroll-mx":["scroll-mr","scroll-ml"],"scroll-my":["scroll-mt","scroll-mb"],"scroll-p":["scroll-px","scroll-py","scroll-ps","scroll-pe","scroll-pbs","scroll-pbe","scroll-pt","scroll-pr","scroll-pb","scroll-pl"],"scroll-px":["scroll-pr","scroll-pl"],"scroll-py":["scroll-pt","scroll-pb"],touch:["touch-x","touch-y","touch-pz"],"touch-x":["touch"],"touch-y":["touch"],"touch-pz":["touch"]},conflictingClassGroupModifiers:{"font-size":["leading"]},postfixLookupClassGroups:["container-type"],orderSensitiveModifiers:["*","**","after","backdrop","before","details-content","file","first-letter","first-line","marker","placeholder","selection"]}},Bn=bn(qn);function _e(...e){return Bn($a(e))}const Fn=({message:e,type:r="info",duration:t=3e3,onClose:n,visible:i})=>{const{t:l}=_();d.useEffect(()=>{if(i){const g=setTimeout(()=>{n()},t);return()=>clearTimeout(g)}},[i,t,n]);const s={success:a.jsx(pa,{className:"w-5 h-5 text-green-500"}),error:a.jsx(xe,{className:"w-5 h-5 text-red-500"}),info:a.jsx("svg",{className:"w-5 h-5 text-blue-500",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:a.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"})}),warning:a.jsx("svg",{className:"w-5 h-5 text-yellow-500",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:a.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"})})},u={success:"bg-green-50 border-green-200 dark:bg-green-950 dark:border-green-800",error:"bg-red-50 border-red-200 dark:bg-red-950 dark:border-red-800",info:"bg-blue-50 border-blue-200 dark:bg-blue-950 dark:border-blue-800",warning:"bg-yellow-50 border-yellow-200 dark:bg-yellow-950 dark:border-yellow-800"},o={success:"text-green-800 dark:text-green-200",error:"text-red-800 dark:text-red-200",info:"text-blue-800 dark:text-blue-200",warning:"text-yellow-800 dark:text-yellow-200"},m={success:"hover:bg-green-100 dark:hover:bg-green-900 focus:ring-green-500",error:"hover:bg-red-100 dark:hover:bg-red-900 focus:ring-red-500",info:"hover:bg-blue-100 dark:hover:bg-blue-900 focus:ring-blue-500",warning:"hover:bg-yellow-100 dark:hover:bg-yellow-900 focus:ring-yellow-500"},h={success:"border-l-4 border-l-green-500",error:"border-l-4 border-l-red-600",info:"border-l-4 border-l-blue-500",warning:"border-l-4 border-l-yellow-500"};return a.jsx("div",{className:_e("fixed top-4 right-4 z-50 max-w-sm p-4 rounded-md shadow-lg border",u[r],o[r],h[r],"transform transition-all duration-300 ease-in-out",i?"translate-x-0 opacity-100":"translate-x-full opacity-0"),children:a.jsxs("div",{className:"flex items-start",children:[a.jsx("div",{className:"flex-shrink-0",children:s[r]}),a.jsx("div",{className:"ml-3",children:a.jsx("p",{className:_e("text-sm font-medium",o[r]),children:e})}),a.jsx("div",{className:"ml-auto pl-3",children:a.jsx("div",{className:"-mx-1.5 -my-1.5",children:a.jsxs("button",{onClick:n,className:_e("inline-flex rounded-md p-1.5","focus:outline-none focus:ring-2 focus:ring-offset-2 dark:focus:ring-offset-gray-900",m[r]),children:[a.jsx("span",{className:"sr-only",children:l("common.dismiss")}),a.jsx(xe,{className:"h-5 w-5"})]})})})]})})},Pt=d.createContext(void 0),At=()=>{const e=d.useContext(Pt);if(!e)throw new Error("useToast must be used within a ToastProvider");return e},Kn=({children:e})=>{const[r,t]=d.useState({message:"",type:"info",visible:!1,duration:3e3}),n=d.useCallback((l,s="info",u=3e3)=>{t({message:l,type:s,visible:!0,duration:u})},[]),i=d.useCallback(()=>{t(l=>({...l,visible:!1}))},[]);return a.jsxs(Pt.Provider,{value:{showToast:n},children:[e,a.jsx(Fn,{message:r.message,type:r.type,duration:r.duration,onClose:i,visible:r.visible})]})},Rt=d.createContext(void 0),jn=()=>{const e=d.useContext(Rt);if(!e)throw new Error("useTheme must be used within a ThemeProvider");return e},Gn=({children:e})=>{const[r,t]=d.useState(()=>localStorage.getItem("theme")||"system"),[n,i]=d.useState("light"),l=s=>{t(s),localStorage.setItem("theme",s)};return d.useEffect(()=>{const s=()=>{const o=window.document.documentElement,m=window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light",h=r==="system"?m:r;i(h),h==="dark"?(console.log("Applying dark mode to HTML root element"),o.classList.add("dark")):(console.log("Removing dark mode from HTML root element"),o.classList.remove("dark"))},u=window.matchMedia("(prefers-color-scheme: dark)");return u.addEventListener("change",s),s(),()=>{u.removeEventListener("change",s)}},[r]),a.jsx(Rt.Provider,{value:{theme:r,setTheme:l,resolvedTheme:n},children:e})},Fr=2e3,Kr=3e4,jr=6e4,Hn=3,_n=(e=Date.now)=>{let r=e()+jr,t=!0,n,i=0,l=0;return{success(s){const u=JSON.stringify(s.map(({name:m,status:h})=>[m,h]).sort(([m],[h])=>m.localeCompare(h)));(l>0||!t&&n!==void 0&&n!==u)&&(r=e()+jr),i=u===n?i+1:1,n=u,l=0;const o=s.some(m=>m.status==="connecting");return t=e()<r&&(o||i<Hn),t?Fr:Kr},failure(){return i=0,l+=1,Math.min(Kr,Fr*2**Math.min(l-1,4))}}},Oe=(e,r,t)=>e.map(n=>n.name!==r?n:{...n,...t.enabled!==void 0?{enabled:t.enabled}:{},...t.visibility!==void 0?{visibility:t.visibility}:{},config:n.config?{...n.config,...t.enabled!==void 0?{enabled:t.enabled}:{},...t.visibility!==void 0?{visibility:t.visibility}:{}}:n.config}),Vn=(e,r="tokens")=>oe(`/servers/${encodeURIComponent(e)}/oauth/disconnect`,{scope:r}),Tt="mcphub_servers_per_page",Le=5,xt=new Set([5,10,20,50]),$n=()=>{if(typeof window>"u")return Le;const e=window.localStorage.getItem(Tt);if(!e)return Le;const r=Number(e);return xt.has(r)?r:Le},wt=d.createContext(void 0),Jn=({children:e})=>{const{t:r}=_(),{auth:t}=Ce(),[n,i]=d.useState([]),[l,s]=d.useState([]),[u,o]=d.useState(null),[m,h]=d.useState(0),[g,A]=d.useState(!0),[D,O]=d.useState(0),[x,L]=d.useState(null),[E,I]=d.useState(1),[k,B]=d.useState($n),M=d.useRef(null),W=d.useRef(0),J=3e3,C=()=>{M.current&&(clearTimeout(M.current),M.current=null)},F=d.useCallback(v=>{if(v&&!Array.isArray(v)&&v.success&&Array.isArray(v.data)){i(v.data),s(Array.isArray(v.allServers)?v.allServers:v.data),L(v.pagination??null);return}if(Array.isArray(v)){i(v),s(v),L(null);return}console.error("Invalid server data format",{serverData:v}),i([]),s([]),L(null)},[]);d.useEffect(()=>{if(!t.isAuthenticated){i([]),s([]),A(!1),o(null);return}let v=!0;const S=new AbortController,R=_n();O(0);const q=async()=>{let G;try{const Z=new URLSearchParams({page:E.toString(),limit:k.toString()}),U=await Y(`/servers?${Z}`,{signal:S.signal});if(!v)return;if(!Array.isArray(U)&&(!U.success||!Array.isArray(U.data)))throw new Error("Invalid server list response");const ve=Array.isArray(U)?U:Array.isArray(U.allServers)?U.allServers:U.data;G=R.success(ve),W.current=Date.now(),F(U),A(!1),O(0),o(null)}catch(Z){if(!v)return;G=R.failure(),O(U=>U+1),A(!1),console.error("Error fetching servers",{err:Z}),o(r(navigator.onLine?"errors.serverFetch":"errors.network"))}v&&(M.current=setTimeout(q,G))};return q(),()=>{v=!1,S.abort(),C()}},[t.isAuthenticated,F,m,r,E,k]),d.useEffect(()=>{if(!x)return;const v=Math.max(1,x.totalPages||1);E>v&&I(v)},[x,E]);const j=d.useCallback(()=>{C(),h(v=>v+1)},[]),Q=d.useCallback(()=>{const S=Date.now()-W.current;console.log("[ServerContext] refreshIfNeeded called",{timeSinceLastFetch:S}),S>=J?(console.log("[ServerContext] Triggering refresh after minimum interval",{minRefreshInterval:J}),j()):console.log("[ServerContext] Skipping refresh because minimum interval not reached",{minRefreshInterval:J,timeSinceLastFetch:S})},[j]),le=d.useCallback(()=>{h(v=>v+1)},[]),ue=d.useCallback(async v=>{try{const S=encodeURIComponent(v.name),R=await Y(`/servers/${S}`);return R&&R.success&&R.data?{name:R.data.name,status:R.data.status,tools:R.data.tools||[],config:R.data.config}:(console.error("Failed to get server config",{serverName:v.name,serverData:R}),o(r("server.invalidConfig",{serverName:v.name})),null)}catch(S){return console.error("Error fetching server config",{serverName:v.name,err:S}),o(S instanceof Error?S.message:String(S)),null}},[r]),me=d.useCallback(async v=>{try{const S=encodeURIComponent(v),R=await Se(`/servers/${S}`);return!R||!R.success?(o((R==null?void 0:R.message)||r("server.deleteError",{serverName:v})),!1):(h(q=>q+1),!0)}catch(S){return o(r("errors.general")+": "+(S instanceof Error?S.message:String(S))),!1}},[r]),te=d.useCallback(async(v,S)=>{try{const R=encodeURIComponent(v.name),q=await oe(`/servers/${R}/toggle`,{enabled:S});return!q||!q.success?(console.error("Failed to toggle server",{serverName:v.name,result:q}),o((q==null?void 0:q.message)||r("server.toggleError",{serverName:v.name})),!1):(i(G=>Oe(G,v.name,{enabled:S})),s(G=>Oe(G,v.name,{enabled:S})),h(G=>G+1),!0)}catch(R){return console.error("Error toggling server",{serverName:v.name,err:R}),o(R instanceof Error?R.message:String(R)),!1}},[r]),X=d.useCallback(async(v,S)=>{var R;try{const q=encodeURIComponent(v.name),G=await Y(`/servers/${q}`);if(!G||!G.success||!((R=G.data)!=null&&R.config))return o(r("server.invalidConfig",{serverName:v.name})),!1;const Z=await K(`/servers/${q}`,{config:{...G.data.config,visibility:S}});return!Z||!Z.success?(o((Z==null?void 0:Z.message)||r("server.updateError",{serverName:v.name})),!1):(i(U=>Oe(U,v.name,{visibility:S})),s(U=>Oe(U,v.name,{visibility:S})),h(U=>U+1),!0)}catch(q){return console.error("Error updating server visibility",{serverName:v.name,err:q}),o(q instanceof Error?q.message:String(q)),!1}},[r]),re=d.useCallback(async v=>{try{const S=encodeURIComponent(v.name),R=await oe(`/servers/${S}/reload`,{});return!R||!R.success?(console.error("Failed to reload server",{serverName:v.name,result:R}),o(r("server.reloadError",{serverName:v.name})),!1):(j(),!0)}catch(S){return console.error("Error reloading server",{serverName:v.name,err:S}),o(S instanceof Error?S.message:String(S)),!1}},[r,j]),pe=d.useCallback(async v=>{try{const S=encodeURIComponent(v.name),R=await oe(`/servers/${S}/reinstall`,{});return!R||!R.success?(console.error("Failed to reinstall server",{serverName:v.name,result:R}),o((R==null?void 0:R.message)||r("server.reinstallError",{serverName:v.name})),!1):(j(),!0)}catch(S){return console.error("Error reinstalling server",{serverName:v.name,err:S}),o(S instanceof Error?S.message:String(S)),!1}},[r,j]),N=d.useCallback(async v=>{try{const S=await Vn(v.name);return!S||!S.success?(console.error("Failed to disconnect server OAuth",{serverName:v.name,result:S}),o((S==null?void 0:S.message)||r("server.disconnectOAuthError",{serverName:v.name})),!1):(j(),!0)}catch(S){return console.error("Error disconnecting server OAuth",{serverName:v.name,err:S}),o(S instanceof Error?S.message:String(S)),!1}},[r,j]),w=d.useCallback(v=>{I(v)},[]),T=d.useCallback(v=>{const S=xt.has(v)?v:Le;typeof window<"u"&&window.localStorage.setItem(Tt,String(S)),B(S),I(1)},[]),be={servers:n,allServers:l,error:u,setError:o,isLoading:g,fetchAttempts:D,pagination:x,currentPage:E,serversPerPage:k,setCurrentPage:w,setServersPerPage:T,triggerRefresh:j,refreshIfNeeded:Q,handleServerAdd:le,handleServerEdit:ue,handleServerRemove:me,handleServerToggle:te,handleServerVisibilityChange:X,handleServerReload:re,handleServerReinstall:pe,handleServerOAuthDisconnect:N};return a.jsx(wt.Provider,{value:be,children:e})},Wn=()=>{const e=d.useContext(wt);if(e===void 0)throw new Error("useServerContext must be used within a ServerProvider");return e},Gr=["username","keyId","groupId","serverId","tool"],pd=(e,r)=>e.flatMap(t=>["serverId","keyId","groupId"].flatMap(n=>t[n]&&!r[n].includes(t[n])?[{policyId:t.id,selector:n,value:t[n]}]:[]));function Yn(e){if(!Array.isArray(e))throw new Error("toolPolicies must be an array");const r=new Set;for(const t of e){if(!t||typeof t!="object"||Array.isArray(t)||typeof t.id!="string"||!t.id.trim()||r.has(t.id)||!["allow","deny"].includes(t.effect)||Object.keys(t).some(n=>!["id","effect",...Gr].includes(n))||Gr.some(n=>t[n]!==void 0&&(typeof t[n]!="string"||!t[n].trim())))throw new Error("Invalid toolPolicies rule: use unique IDs, allow/deny and non-empty selectors");r.add(t.id)}}const Ve=()=>({enabled:!0,accessTokenLifetime:3600,refreshTokenLifetime:1209600,authorizationCodeLifetime:300,requireClientSecret:!1,allowedScopes:["read","write"],requireState:!1,dynamicRegistration:{enabled:!0,allowedGrantTypes:["authorization_code","refresh_token"],requiresAuthentication:!1,clientTtl:2592e3}}),Dt=["openid","profile","email"],Et=()=>({enabled:!0,baseUrl:"",basePath:"/api/auth/better",trustedOrigins:[],disablePasswordLogin:!1,providers:{google:{enabled:!0},github:{enabled:!0},oidc:{enabled:!1,providerId:"oidc",discoveryUrl:"",scopes:[...Dt],pkce:!0,prompt:""}}}),Hr=(e,r=[])=>{const t=Array.isArray(e)?e.filter(n=>typeof n=="string").map(n=>n.trim()).filter(n=>n.length>0):[];return t.length>0?t:[...r]},It=e=>{var t,n,i,l,s,u,o,m,h,g,A,D,O,x,L,E,I,k,B,M,W;const r=Et();return{enabled:(e==null?void 0:e.enabled)??r.enabled,baseUrl:((t=e==null?void 0:e.baseUrl)==null?void 0:t.trim())||r.baseUrl,basePath:((n=e==null?void 0:e.basePath)==null?void 0:n.trim())||r.basePath,trustedOrigins:Hr(e==null?void 0:e.trustedOrigins,r.trustedOrigins),disablePasswordLogin:(e==null?void 0:e.disablePasswordLogin)??r.disablePasswordLogin,providers:{google:{enabled:((l=(i=e==null?void 0:e.providers)==null?void 0:i.google)==null?void 0:l.enabled)??r.providers.google.enabled},github:{enabled:((u=(s=e==null?void 0:e.providers)==null?void 0:s.github)==null?void 0:u.enabled)??r.providers.github.enabled},oidc:{enabled:((m=(o=e==null?void 0:e.providers)==null?void 0:o.oidc)==null?void 0:m.enabled)??r.providers.oidc.enabled,providerId:((A=(g=(h=e==null?void 0:e.providers)==null?void 0:h.oidc)==null?void 0:g.providerId)==null?void 0:A.trim())||r.providers.oidc.providerId,discoveryUrl:((x=(O=(D=e==null?void 0:e.providers)==null?void 0:D.oidc)==null?void 0:O.discoveryUrl)==null?void 0:x.trim())||"",scopes:Hr((E=(L=e==null?void 0:e.providers)==null?void 0:L.oidc)==null?void 0:E.scopes,Dt),pkce:((k=(I=e==null?void 0:e.providers)==null?void 0:I.oidc)==null?void 0:k.pkce)??r.providers.oidc.pkce,prompt:((W=(M=(B=e==null?void 0:e.providers)==null?void 0:B.oidc)==null?void 0:M.prompt)==null?void 0:W.trim())||""}}}},Xn=(e,r)=>{var n,i,l,s,u;const t={...e,...r,baseUrl:r.baseUrl??e.baseUrl,trustedOrigins:r.trustedOrigins??e.trustedOrigins,providers:{...e.providers,...r.providers,google:{...e.providers.google,...(n=r.providers)==null?void 0:n.google},github:{...e.providers.github,...(i=r.providers)==null?void 0:i.github},oidc:{...e.providers.oidc,...(l=r.providers)==null?void 0:l.oidc,scopes:((u=(s=r.providers)==null?void 0:s.oidc)==null?void 0:u.scopes)??e.providers.oidc.scopes}}};return It(t)},Nt=d.createContext(void 0),hd=()=>{const e=d.useContext(Nt);if(!e)throw new Error("useSettings must be used within a SettingsProvider");return e},Qn=({children:e})=>{const{t:r}=_(),{showToast:t}=At(),{auth:n}=Ce(),[i,l]=d.useState({enableGlobalRoute:!0,enableGroupNameRoute:!0,enableBearerAuth:!0,bearerAuthKey:"",bearerAuthHeaderName:"Authorization",jsonBodyLimit:"1mb",skipAuth:!1}),[s,u]=d.useState({bearerAuthKey:"",bearerAuthHeaderName:"Authorization",jsonBodyLimit:"1mb"}),[o,m]=d.useState({pythonIndexUrl:"",npmRegistry:"",baseUrl:"http://localhost:3000"}),[h,g]=d.useState({enabled:!1,dbUrl:"",basePacingDelayMs:void 0,embeddingProvider:"openai",embeddingEncodingFormat:"auto",embeddingDimensions:void 0,embeddingDimensionsApiPassthrough:!1,llmProviderBaseUrl:"",llmProviderApiKey:"",embeddingModel:"",azureOpenaiEndpoint:"",azureOpenaiApiKey:"",azureOpenaiApiVersion:"",azureOpenaiEmbeddingDeployment:"",azureOpenaiEmbeddingModel:"",progressiveDisclosure:!1,embeddingMaxTokens:void 0,embeddingQueryPrefix:"",embeddingDocumentPrefix:"",similarityThreshold:void 0,fullSchemaTopN:void 0}),[A,D]=d.useState({enabled:!1,minTokens:2e3,maxOutputTokens:1200,strategy:"auto"}),[O,x]=d.useState({apiKey:"",referer:"https://www.mcphub.app",title:"MCPHub",baseUrl:"https://api.mcprouter.to/v1"}),[L,E]=d.useState(Ve()),[I,k]=d.useState(!1),[B,M]=d.useState(Et()),[W,J]=d.useState("-"),[C,F]=d.useState(!1),[j,Q]=d.useState([]),[le,ue]=d.useState(),[me,te]=d.useState(!0),[X,re]=d.useState([]),[pe,N]=d.useState(!1),[w,T]=d.useState(null),[be,v]=d.useState(0),S=d.useCallback(()=>{v(p=>p+1)},[]),R=d.useCallback(async()=>{var p,c,P,Ze,er,rr,tr,ar,nr,ir,or,sr,lr,cr,dr,ur,mr,pr,hr,gr,br,vr,yr,fr,kr,Sr,Cr,Pr,Ar,Rr,Tr,xr,wr,Dr;N(!0),T(null);try{const b=await Y("/settings");if(b.success&&((p=b.data)!=null&&p.systemConfig)){const H=b.data.systemConfig.toolPolicies===void 0?[]:b.data.systemConfig.toolPolicies;Yn(H),ue(H)}if(b.success&&((P=(c=b.data)==null?void 0:c.systemConfig)!=null&&P.routing)&&l({enableGlobalRoute:b.data.systemConfig.routing.enableGlobalRoute??!0,enableGroupNameRoute:b.data.systemConfig.routing.enableGroupNameRoute??!0,enableBearerAuth:b.data.systemConfig.routing.enableBearerAuth??!0,bearerAuthKey:b.data.systemConfig.routing.bearerAuthKey||"",bearerAuthHeaderName:b.data.systemConfig.routing.bearerAuthHeaderName||"Authorization",jsonBodyLimit:b.data.systemConfig.routing.jsonBodyLimit||"1mb",skipAuth:b.data.systemConfig.routing.skipAuth??!1}),b.success&&((er=(Ze=b.data)==null?void 0:Ze.systemConfig)!=null&&er.install)&&m({pythonIndexUrl:b.data.systemConfig.install.pythonIndexUrl||"",npmRegistry:b.data.systemConfig.install.npmRegistry||"",baseUrl:b.data.systemConfig.install.baseUrl||"http://localhost:3000"}),b.success&&((tr=(rr=b.data)==null?void 0:rr.systemConfig)!=null&&tr.smartRouting)&&g({enabled:b.data.systemConfig.smartRouting.enabled??!1,dbUrl:b.data.systemConfig.smartRouting.dbUrl||"",basePacingDelayMs:b.data.systemConfig.smartRouting.basePacingDelayMs,embeddingProvider:b.data.systemConfig.smartRouting.embeddingProvider==="azure_openai"?"azure_openai":"openai",embeddingEncodingFormat:b.data.systemConfig.smartRouting.embeddingEncodingFormat==="base64"?"base64":b.data.systemConfig.smartRouting.embeddingEncodingFormat==="float"?"float":"auto",embeddingDimensions:b.data.systemConfig.smartRouting.embeddingDimensions,embeddingDimensionsApiPassthrough:b.data.systemConfig.smartRouting.embeddingDimensionsApiPassthrough??!1,llmProviderBaseUrl:b.data.systemConfig.smartRouting.llmProviderBaseUrl||"",llmProviderApiKey:b.data.systemConfig.smartRouting.llmProviderApiKey||"",embeddingModel:b.data.systemConfig.smartRouting.embeddingModel||"",azureOpenaiEndpoint:b.data.systemConfig.smartRouting.azureOpenaiEndpoint||"",azureOpenaiApiKey:b.data.systemConfig.smartRouting.azureOpenaiApiKey||"",azureOpenaiApiVersion:b.data.systemConfig.smartRouting.azureOpenaiApiVersion||"",azureOpenaiEmbeddingDeployment:b.data.systemConfig.smartRouting.azureOpenaiEmbeddingDeployment||"",azureOpenaiEmbeddingModel:b.data.systemConfig.smartRouting.azureOpenaiEmbeddingModel||"",progressiveDisclosure:b.data.systemConfig.smartRouting.progressiveDisclosure??!1,embeddingMaxTokens:b.data.systemConfig.smartRouting.embeddingMaxTokens,embeddingQueryPrefix:b.data.systemConfig.smartRouting.embeddingQueryPrefix||"",embeddingDocumentPrefix:b.data.systemConfig.smartRouting.embeddingDocumentPrefix||"",similarityThreshold:b.data.systemConfig.smartRouting.similarityThreshold,fullSchemaTopN:b.data.systemConfig.smartRouting.fullSchemaTopN,toolDefinitionFields:b.data.systemConfig.smartRouting.toolDefinitionFields,envOverriddenFields:b.data.systemConfig.smartRouting.envOverriddenFields??[]}),b.success&&((nr=(ar=b.data)==null?void 0:ar.systemConfig)!=null&&nr.toolResultCompression)){const H=b.data.systemConfig.toolResultCompression,ae=H.strategy;D({enabled:H.enabled??!1,minTokens:H.minTokens||2e3,maxOutputTokens:H.maxOutputTokens||1200,strategy:["auto","json","log","search","diff","text"].includes(ae)?ae:"auto"})}if(b.success&&((or=(ir=b.data)==null?void 0:ir.systemConfig)!=null&&or.mcpRouter)&&x({apiKey:b.data.systemConfig.mcpRouter.apiKey||"",referer:b.data.systemConfig.mcpRouter.referer||"https://www.mcphub.app",title:b.data.systemConfig.mcpRouter.title||"MCPHub",baseUrl:b.data.systemConfig.mcpRouter.baseUrl||"https://api.mcprouter.to/v1"}),b.success){if((lr=(sr=b.data)==null?void 0:sr.systemConfig)!=null&&lr.oauthServer){const H=b.data.systemConfig.oauthServer,ae=Ve(),Ee=ae.dynamicRegistration,ea=Array.isArray(H.allowedScopes)?[...H.allowedScopes]:[...ae.allowedScopes],ra=Array.isArray((cr=H.dynamicRegistration)==null?void 0:cr.allowedGrantTypes)?[...H.dynamicRegistration.allowedGrantTypes]:[...Ee.allowedGrantTypes];E({enabled:H.enabled??ae.enabled,accessTokenLifetime:H.accessTokenLifetime??ae.accessTokenLifetime,refreshTokenLifetime:H.refreshTokenLifetime??ae.refreshTokenLifetime,authorizationCodeLifetime:H.authorizationCodeLifetime??ae.authorizationCodeLifetime,requireClientSecret:H.requireClientSecret??ae.requireClientSecret,requireState:H.requireState??ae.requireState,allowedScopes:ea,dynamicRegistration:{enabled:((dr=H.dynamicRegistration)==null?void 0:dr.enabled)??Ee.enabled,allowedGrantTypes:ra,requiresAuthentication:((ur=H.dynamicRegistration)==null?void 0:ur.requiresAuthentication)??Ee.requiresAuthentication,clientTtl:((mr=H.dynamicRegistration)==null?void 0:mr.clientTtl)??Ee.clientTtl}})}else E(Ve());k(((gr=(hr=(pr=b.data)==null?void 0:pr.systemConfig)==null?void 0:hr.auth)==null?void 0:gr.allowRegistration)===!0),M(It((yr=(vr=(br=b.data)==null?void 0:br.systemConfig)==null?void 0:vr.auth)==null?void 0:yr.betterAuth))}b.success&&Q(((Sr=(kr=(fr=b.data)==null?void 0:fr.systemConfig)==null?void 0:kr.network)==null?void 0:Sr.allowedCidrs)??[]),b.success&&((Pr=(Cr=b.data)==null?void 0:Cr.systemConfig)==null?void 0:Pr.nameSeparator)!==void 0&&J(b.data.systemConfig.nameSeparator),b.success&&((Rr=(Ar=b.data)==null?void 0:Ar.systemConfig)==null?void 0:Rr.enableSessionRebuild)!==void 0&&F(b.data.systemConfig.enableSessionRebuild),b.success&&((wr=(xr=(Tr=b.data)==null?void 0:Tr.systemConfig)==null?void 0:xr.activityLog)==null?void 0:wr.storeToolPayload)!==void 0&&te(b.data.systemConfig.activityLog.storeToolPayload),b.success&&Array.isArray((Dr=b.data)==null?void 0:Dr.bearerKeys)&&re(b.data.bearerKeys)}catch(b){console.error("Failed to fetch settings",{error:b}),T(b instanceof Error?b.message:"Failed to fetch settings"),t(r("errors.failedToFetchSettings"))}finally{N(!1)}},[r,t]),q=async(p,c)=>{N(!0),T(null);try{const P=await K("/system-config",{routing:{[p]:c}});return P.success?(l({...i,[p]:c}),t(r("settings.systemConfigUpdated")),!0):(T(P.error||"Failed to update routing config"),t(P.error||r("errors.failedToUpdateRoutingConfig")),!1)}catch(P){return console.error("Failed to update routing config",{key:p,value:c,error:P}),T(P instanceof Error?P.message:"Failed to update routing config"),t(r("errors.failedToUpdateRoutingConfig")),!1}finally{N(!1)}},G=async(p,c)=>{N(!0),T(null);try{const P=await K("/system-config",{install:{[p]:c}});return P.success?(m({...o,[p]:c}),t(r("settings.systemConfigUpdated")),!0):(T(P.error||"Failed to update install config"),t(P.error||r("errors.failedToUpdateInstallConfig")),!1)}catch(P){return console.error("Failed to update install config",{key:p,value:c,error:P}),T(P instanceof Error?P.message:"Failed to update install config"),t(r("errors.failedToUpdateInstallConfig")),!1}finally{N(!1)}},Z=async(p,c)=>{N(!0),T(null);try{const P=await K("/system-config",{smartRouting:{[p]:c}});return P.success?(g({...h,[p]:c}),t(r("settings.systemConfigUpdated")),!0):(T(P.error||"Failed to update smart routing config"),t(P.error||r("errors.failedToUpdateSmartRoutingConfig")),!1)}catch(P){return console.error("Failed to update smart routing config",{key:p,value:c,error:P}),T(P instanceof Error?P.message:"Failed to update smart routing config"),t(r("errors.failedToUpdateSmartRoutingConfig")),!1}finally{N(!1)}},U=async p=>{N(!0),T(null);try{const c=await K("/system-config",{smartRouting:p});return c.success?(g({...h,...p}),t(r("settings.systemConfigUpdated")),!0):(T(c.error||"Failed to update smart routing config"),t(c.error||r("errors.failedToUpdateSmartRoutingConfig")),!1)}catch(c){return console.error("Failed to batch update smart routing config",{updates:p,error:c}),T(c instanceof Error?c.message:"Failed to update smart routing config"),t(r("errors.failedToUpdateSmartRoutingConfig")),!1}finally{N(!1)}},ve=async(p,c)=>{N(!0),T(null);try{const P=await K("/system-config",{toolResultCompression:{[p]:c}});return P.success?(D({...A,[p]:c}),t(r("settings.systemConfigUpdated")),!0):(T(P.error||"Failed to update tool result compression config"),t(P.error||r("errors.failedToUpdateSettings")),!1)}catch(P){return console.error("Failed to update tool result compression config",{key:p,value:c,error:P}),T(P instanceof Error?P.message:"Failed to update tool result compression config"),t(r("errors.failedToUpdateSettings")),!1}finally{N(!1)}},ye=async p=>{N(!0),T(null);try{const c=await K("/system-config",{toolResultCompression:p});return c.success?(D({...A,...p}),t(r("settings.systemConfigUpdated")),!0):(T(c.error||"Failed to update tool result compression config"),t(c.error||r("errors.failedToUpdateSettings")),!1)}catch(c){return console.error("Failed to batch update tool result compression config",{updates:p,error:c}),T(c instanceof Error?c.message:"Failed to update tool result compression config"),t(r("errors.failedToUpdateSettings")),!1}finally{N(!1)}},fe=async p=>{N(!0),T(null);try{const c=await K("/system-config",{routing:p});return c.success?(l({...i,...p}),t(r("settings.systemConfigUpdated")),!0):(T(c.error||"Failed to update routing config"),t(c.error||r("errors.failedToUpdateRoutingConfig")),!1)}catch(c){return console.error("Failed to batch update routing config",{updates:p,error:c}),T(c instanceof Error?c.message:"Failed to update routing config"),t(r("errors.failedToUpdateRoutingConfig")),!1}finally{N(!1)}},Pe=async(p,c)=>{N(!0),T(null);try{const P=await K("/system-config",{mcpRouter:{[p]:c}});return P.success?(x({...O,[p]:c}),t(r("settings.systemConfigUpdated")),!0):(T(P.error||"Failed to update MCP Router config"),t(P.error||r("errors.failedToUpdateMCPRouterConfig")),!1)}catch(P){return console.error("Failed to update MCP Router config",{key:p,value:c,error:P}),T(P instanceof Error?P.message:"Failed to update MCP Router config"),t(r("errors.failedToUpdateMCPRouterConfig")),!1}finally{N(!1)}},ke=async p=>{N(!0),T(null);try{const c=await K("/system-config",{mcpRouter:p});return c.success?(x({...O,...p}),t(r("settings.systemConfigUpdated")),!0):(T(c.error||"Failed to update MCP Router config"),t(c.error||r("errors.failedToUpdateMCPRouterConfig")),!1)}catch(c){return console.error("Failed to batch update MCP Router config",{updates:p,error:c}),T(c instanceof Error?c.message:"Failed to update MCP Router config"),t(r("errors.failedToUpdateMCPRouterConfig")),!1}finally{N(!1)}},Ft=async(p,c)=>{N(!0),T(null);try{const P=await K("/system-config",{oauthServer:{[p]:c}});return P.success?(E({...L,[p]:c}),t(r("settings.systemConfigUpdated")),!0):(T(P.error||"Failed to update OAuth server config"),t(P.error||r("errors.failedToUpdateOAuthServerConfig")),!1)}catch(P){return console.error("Failed to update OAuth server config",{key:p,value:c,error:P}),T(P instanceof Error?P.message:"Failed to update OAuth server config"),t(r("errors.failedToUpdateOAuthServerConfig")),!1}finally{N(!1)}},Kt=async p=>{N(!0),T(null);try{const c=await K("/system-config",{oauthServer:p});return c.success?(E({...L,...p}),t(r("settings.systemConfigUpdated")),!0):(T(c.error||"Failed to update OAuth server config"),t(c.error||r("errors.failedToUpdateOAuthServerConfig")),!1)}catch(c){return console.error("Failed to batch update OAuth server config",{updates:p,error:c}),T(c instanceof Error?c.message:"Failed to update OAuth server config"),t(r("errors.failedToUpdateOAuthServerConfig")),!1}finally{N(!1)}},jt=async p=>{N(!0),T(null);try{(await K("/system-config",{auth:{allowRegistration:p}})).success?(k(p),t(r("settings.systemConfigUpdated"))):t(r("errors.failedToUpdateSettings"))}catch(c){T(c instanceof Error?c.message:"Failed to update registration setting")}finally{N(!1)}},Gt=async p=>{N(!0),T(null);try{const c=await K("/system-config",{auth:{betterAuth:p}});return c.success?(M(P=>Xn(P,p)),t(r("settings.systemConfigUpdated")),!0):(T(c.error||"Failed to update Better Auth config"),t(c.error||r("errors.failedToUpdateBetterAuthConfig")),!1)}catch(c){return console.error("Failed to batch update Better Auth config",{updates:p,error:c}),T(c instanceof Error?c.message:"Failed to update Better Auth config"),t(r("errors.failedToUpdateBetterAuthConfig")),!1}finally{N(!1)}},Ht=async p=>{N(!0),T(null);try{const c=await K("/system-config",{nameSeparator:p});return c.success?(J(p),t(r("settings.systemConfigUpdated")),!0):(T(c.error||"Failed to update name separator"),t(c.error||r("errors.failedToUpdateNameSeparator")),!1)}catch(c){return console.error("Failed to update name separator",{value:p,error:c}),T(c instanceof Error?c.message:"Failed to update name separator"),t(r("errors.failedToUpdateNameSeparator")),!1}finally{N(!1)}},_t=async p=>{N(!0),T(null);try{const c=await K("/system-config",{enableSessionRebuild:p});return c.success?(F(p),t(r("settings.systemConfigUpdated")),!0):(T(c.error||"Failed to update session rebuild setting"),t(c.error||r("errors.failedToUpdateSessionRebuild")),!1)}catch(c){return console.error("Failed to update session rebuild setting",{value:p,error:c}),T(c instanceof Error?c.message:"Failed to update session rebuild setting"),t(r("errors.failedToUpdateSessionRebuild")),!1}finally{N(!1)}},Vt=async p=>{N(!0);try{const c=await K("/system-config",{toolPolicies:p});return c.success?(ue(p),t(r("settings.systemConfigUpdated")),!0):(t(c.message||c.error||r("settings.toolPolicies.saveFailed"),"error"),!1)}catch(c){return t(c instanceof Error?c.message:r("settings.toolPolicies.saveFailed"),"error"),!1}finally{N(!1)}},$t=async p=>{N(!0);try{const c=await K("/system-config",{network:{allowedCidrs:p}});return c.success?(Q(c.data.network.allowedCidrs),t(r("settings.systemConfigUpdated")),!0):(t(c.message||c.error||r("settings.allowedCidrsUpdateFailed")),!1)}catch(c){return t(c instanceof Error?c.message:r("settings.allowedCidrsUpdateFailed")),!1}finally{N(!1)}},Jt=async p=>{N(!0),T(null);try{const c=await K("/system-config",{activityLog:{storeToolPayload:p}});return c.success?(te(p),t(r("settings.systemConfigUpdated")),!0):(T(c.error||"Failed to update activity log setting"),t(c.error||r("settings.storeToolPayloadUpdateFailed")),!1)}catch(c){return console.error("Failed to update activity log setting",{value:p,error:c}),T(c instanceof Error?c.message:"Failed to update activity log setting"),t(r("settings.storeToolPayloadUpdateFailed")),!1}finally{N(!1)}},Wt=async p=>{N(!0),T(null);try{return await Y(`/mcp-settings/export?serverName=${p||""}`)}catch(c){console.error("Failed to export MCP settings",{serverName:p,error:c});const P=c instanceof Error?c.message:"Failed to export MCP settings";T(P),t(P)}finally{N(!1)}},De=async()=>{try{const p=await Y("/auth/keys");p.success&&Array.isArray(p.data)&&re(p.data)}catch(p){console.error("Failed to refresh bearer keys",{error:p}),t(r("errors.failedToFetchSettings"))}},Yt=async p=>{try{const c=await oe("/auth/keys",p);return c.success&&c.data?(await De(),t(r("settings.systemConfigUpdated")),c.data):(t(c.message||r("errors.failedToUpdateRoutingConfig")),null)}catch(c){return console.error("Failed to create bearer key",{error:c}),t(r("errors.failedToUpdateRoutingConfig")),null}},Xt=async(p,c)=>{try{const P=await K(`/auth/keys/${p}`,c);return P.success&&P.data?(await De(),t(r("settings.systemConfigUpdated")),P.data):(t(P.message||r("errors.failedToUpdateRoutingConfig")),null)}catch(P){return console.error("Failed to update bearer key",{id:p,error:P}),t(r("errors.failedToUpdateRoutingConfig")),null}},Qt=async p=>{try{const c=await Se(`/auth/keys/${p}`);return c.success?(await De(),t(r("settings.systemConfigUpdated")),!0):(t(c.message||r("errors.failedToUpdateRoutingConfig")),!1)}catch(c){return console.error("Failed to delete bearer key",{id:p,error:c}),t(r("errors.failedToUpdateRoutingConfig")),!1}};d.useEffect(()=>{R()},[R,be]),d.useEffect(()=>{n.isAuthenticated&&(console.log("[SettingsContext] User authenticated, triggering settings refresh"),S())},[n.isAuthenticated,S]),d.useEffect(()=>{i&&u({bearerAuthKey:i.bearerAuthKey,bearerAuthHeaderName:i.bearerAuthHeaderName,jsonBodyLimit:i.jsonBodyLimit})},[i]);const Zt={toolPolicies:le,updateToolPolicies:Vt,routingConfig:i,tempRoutingConfig:s,setTempRoutingConfig:u,installConfig:o,smartRoutingConfig:h,toolResultCompressionConfig:A,mcpRouterConfig:O,oauthServerConfig:L,allowRegistration:I,updateAllowRegistration:jt,betterAuthConfig:B,nameSeparator:W,enableSessionRebuild:C,allowedCidrs:j,updateAllowedCidrs:$t,storeToolPayload:me,bearerKeys:X,loading:pe,error:w,setError:T,triggerRefresh:S,fetchSettings:R,updateRoutingConfig:q,updateInstallConfig:G,updateSmartRoutingConfig:Z,updateSmartRoutingConfigBatch:U,updateToolResultCompressionConfig:ve,updateToolResultCompressionConfigBatch:ye,updateRoutingConfigBatch:fe,updateMCPRouterConfig:Pe,updateMCPRouterConfigBatch:ke,updateOAuthServerConfig:Ft,updateOAuthServerConfigBatch:Kt,updateBetterAuthConfigBatch:Gt,updateNameSeparator:Ht,updateSessionRebuild:_t,updateStoreToolPayload:Jt,exportMCPSettings:Wt,refreshBearerKeys:De,createBearerKey:Yt,updateBearerKey:Xt,deleteBearerKey:Qt};return a.jsx(Nt.Provider,{value:Zt,children:e})},Ot=d.createContext(null),_r=({children:e})=>{const{t:r}=_(),[t,n]=d.useState(""),i=t||r("app.title");return d.useEffect(()=>{let l=!0;return ot().then(s=>{var u;l&&n(((u=s.dashboardName)==null?void 0:u.trim())||"")}),()=>{l=!1}},[]),d.useEffect(()=>{document.title=t||"MCPHub Dashboard"},[t]),a.jsx(Ot.Provider,{value:{dashboardName:t,dashboardTitle:i,setDashboardName:n},children:e})},Mt=()=>{const e=d.useContext(Ot);if(!e)throw new Error("useBranding must be used within a BrandingProvider");return e},Zn=()=>{const{t:e}=_(),{theme:r,setTheme:t}=jn(),n=()=>{t(r==="light"?"dark":"light")};return a.jsx("button",{onClick:n,className:"p-2 rounded-md text-gray-500 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-200 hover:bg-gray-100 dark:bg-gray-800 dark:hover:bg-gray-700 focus:outline-none",title:e(r==="light"?"theme.dark":"theme.light"),"aria-label":e(r==="light"?"theme.dark":"theme.light"),children:r==="light"?a.jsx(ha,{className:"h-5 w-5"}):a.jsx(ga,{className:"h-5 w-5"})})},ei=e=>{const{t:r}=_();return a.jsxs("svg",{role:"img",viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",fill:"none",stroke:"currentColor",strokeWidth:2,...e,children:[a.jsx("title",{children:r("common.language")}),a.jsx("circle",{cx:"12",cy:"12",r:"10"}),a.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M2 12h20"}),a.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M12 2a15.3 15.3 0 014 10 15.3 15.3 0 01-4 10 15.3 15.3 0 01-4-10 15.3 15.3 0 014-10z"})]})},ri=()=>{const{i18n:e}=_(),[r,t]=d.useState(!1),[n,i]=d.useState(e.language),l=[{code:"en",label:"English"},{code:"vi",label:"Tiếng Việt"},{code:"zh",label:"中文"},{code:"fr",label:"Français"},{code:"tr",label:"Türkçe"},{code:"es",label:"Español"}];d.useEffect(()=>{i(e.language)},[e.language]),d.useEffect(()=>{const o=m=>{m.target.closest(".language-dropdown")||t(!1)};return r&&document.addEventListener("mousedown",o),()=>{document.removeEventListener("mousedown",o)}},[r]);const s=o=>{localStorage.setItem("i18nextLng",o),t(!1),window.location.reload()},u=()=>{t(!r)};return a.jsxs("div",{className:"relative language-dropdown",children:[a.jsx("button",{onClick:u,className:"p-2 rounded-md text-gray-500 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-200 hover:bg-gray-100 dark:bg-gray-800 dark:hover:bg-gray-700 focus:outline-none","aria-label":"Language Switcher",children:a.jsx(ei,{className:"h-5 w-5"})}),r&&a.jsx("div",{className:"absolute right-0 mt-2 w-24 bg-white dark:bg-gray-800 rounded-md shadow-lg border border-gray-200 dark:border-gray-700 z-50",children:a.jsx("div",{children:l.map(o=>a.jsx("button",{onClick:()=>s(o.code),className:`flex items-center w-full px-4 py-2 text-sm hover:bg-gray-100 dark:hover:bg-gray-700 ${n.startsWith(o.code)?"bg-blue-50 text-blue-700":"text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-100"}`,children:o.label},o.code))})})]})},ti=e=>{const{t:r}=_();return a.jsxs("svg",{role:"img",viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",fill:"currentColor",...e,children:[a.jsx("title",{children:r("common.github")}),a.jsx("path",{d:"M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"})]})},ai=async()=>{try{const e=await Y("/logs");if(!e.success)throw new Error(e.error||"Failed to fetch logs");return e.data}catch(e){throw console.error("Error fetching logs",{error:e}),e}},ni=async()=>{try{const e=await Se("/logs");if(!e.success)throw new Error(e.error||"Failed to clear logs")}catch(e){throw console.error("Error clearing logs",{error:e}),e}};class ii{constructor(){Ae(this,"eventSource",null);Ae(this,"subscribers",new Set);Ae(this,"reconnectTimer",null);Ae(this,"openAttempts",0)}subscribe(r){return this.subscribers.add(r),this.subscribers.size===1&&(this.openAttempts=0,this.openEventSource()),()=>{this.subscribers.delete(r),this.subscribers.size===0&&this.close()}}openEventSource(){this.closeEventSource();const r=we();if(!r){console.warn("[LogStreamManager] No token available, scheduling reconnect..."),this.scheduleReconnect();return}try{const t=tt(`/logs/stream?token=${r}`);let n=t;try{const i=new URL(t);i.search="",n=i.toString()}catch{n=t.split("?")[0]||t}console.log("[LogStreamManager] Opening EventSource:",n),this.eventSource=new EventSource(t),this.eventSource.onmessage=i=>{this.subscribers.forEach(l=>l(i))},this.eventSource.onopen=()=>{this.openAttempts=0,console.log("[LogStreamManager] EventSource opened successfully")},this.eventSource.onerror=()=>{console.warn("[LogStreamManager] EventSource error, attempting reconnect..."),this.closeEventSource(),this.subscribers.size>0&&this.scheduleReconnect()}}catch(t){console.error("[LogStreamManager] Failed to open EventSource:",t),this.closeEventSource(),this.subscribers.size>0&&this.scheduleReconnect()}}closeEventSource(){this.eventSource&&(this.eventSource.close(),this.eventSource=null)}scheduleReconnect(){if(this.reconnectTimer!==null)return;const r=Math.min(1e3*Math.pow(2,this.openAttempts),8e3);this.openAttempts++,console.log(`[LogStreamManager] Scheduling reconnect in ${r}ms (attempt ${this.openAttempts})`),this.reconnectTimer=setTimeout(()=>{this.reconnectTimer=null,this.subscribers.size>0&&this.openEventSource()},r)}close(){this.closeEventSource(),this.reconnectTimer!==null&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=null)}}const Qe=new ii,gd=()=>{const[e,r]=d.useState([]),[t,n]=d.useState(!0),[i,l]=d.useState(null);return d.useEffect(()=>{let u=!0;(async()=>{try{const g=await ai();u&&(r(g),n(!1))}catch(g){u&&(l(g instanceof Error?g:new Error("Failed to fetch logs")),n(!1))}})();const m=g=>{if(u)try{const A=JSON.parse(g.data);if(A.type==="initial")return;A.type==="log"&&r(D=>[...D,A.log])}catch(A){console.error("Error parsing SSE message",{err:A})}},h=Qe.subscribe(m);return()=>{u=!1,h()}},[]),{logs:e,loading:t,error:i,clearLogs:async()=>{try{await ni(),r([])}catch(u){l(u instanceof Error?u:new Error("Failed to clear logs"))}}}},oi=5e3,Lt=d.createContext(void 0),si=e=>!!e&&typeof e.serverName=="string"&&typeof e.current=="number"&&typeof e.total=="number"&&e.total>0&&e.current>=0&&e.current<=e.total&&["started","in_progress","completed","error"].includes(String(e.status)),li=({children:e})=>{const[r,t]=d.useState([]),n=d.useRef(new Map);d.useEffect(()=>{const l=g=>{const A=n.current.get(g);A&&(clearTimeout(A),n.current.delete(g))},s=()=>{n.current.forEach(g=>clearTimeout(g)),n.current.clear()},u=g=>{t(A=>{const D=A.findIndex(x=>x.serverName===g.serverName);if(D===-1)return[...A,g];const O=[...A];return O[D]=g,O})},o=g=>{t(A=>A.filter(D=>D.serverName!==g))},m=g=>{try{const A=JSON.parse(g.data);if((A==null?void 0:A.type)!=="embedding-sync-progress"||!si(A.progress))return;const D=A.progress;if(l(D.serverName),D.status==="error"){o(D.serverName);return}const O={serverName:D.serverName,current:D.current,total:D.total,status:D.status};if(u(O),D.status==="completed"){const x=setTimeout(()=>{o(D.serverName),n.current.delete(D.serverName)},oi);n.current.set(D.serverName,x)}}catch{}},h=Qe.subscribe(m);return()=>{s(),h()}},[]);const i=d.useMemo(()=>({activeSyncs:r}),[r]);return a.jsx(Lt.Provider,{value:i,children:e})},ci=()=>{const e=d.useContext(Lt);if(!e)throw new Error("useEmbeddingSync must be used within an EmbeddingSyncProvider");return e},di=()=>{const{t:e}=_(),{dashboardTitle:r}=Mt(),t=ia(),n=Qr();return d.useMemo(()=>{const i=t.pathname,l=r;if(i==="/")return[l,e("nav.dashboard")];if(i.startsWith("/credentials"))return[l,e("credentials.title")];if(i.startsWith("/servers"))return[l,e("nav.servers")];if(i.startsWith("/groups"))return[l,e("nav.groups")];if(i.startsWith("/prompts"))return[l,e("nav.prompts")];if(i.startsWith("/resources"))return[l,e("nav.resources")];if(i.startsWith("/users"))return[l,e("nav.users")];if(i.startsWith("/market")){const s=n.serverName,u=[l,e("nav.market")];return s&&u.push(s),u}return i.startsWith("/logs")?[l,e("nav.logs")]:i.startsWith("/activity")?[l,e("nav.activity")]:i.startsWith("/settings")?[l,e("nav.settings")]:[l]},[t.pathname,n,e,r])},ui=({onToggleSidebar:e})=>{const{t:r}=_(),{activeSyncs:t}=ci(),n=di();return a.jsxs("header",{className:"hub-topbar shrink-0",children:[a.jsx("button",{onClick:e,className:"hub-icon-btn","aria-label":r("app.toggleSidebar"),children:a.jsx(ba,{size:16})}),a.jsx("div",{className:"hub-crumb flex items-center min-w-0",children:n.map((i,l)=>a.jsxs(ze.Fragment,{children:[l>0&&a.jsx("span",{className:"sep",children:"/"}),l===n.length-1?a.jsx("b",{className:"truncate",children:i}):a.jsx("span",{className:"truncate",children:i})]},l))}),a.jsx("div",{className:"flex-1 flex justify-center px-2 min-w-0",children:t.length>0&&a.jsx("div",{className:"flex max-w-full flex-wrap justify-center gap-2",children:t.map(i=>a.jsxs("div",{className:"hub-card flex min-w-0 w-56 max-w-full flex-col px-3 py-1.5 text-xs",style:{borderRadius:7},title:r("app.embeddingSyncProgressAriaLabel",{serverName:i.serverName,current:i.current,total:i.total}),children:[a.jsx("span",{className:"truncate hub-mono text-[var(--hub-ink-2)]",children:r("app.embeddingSyncProgress",{serverName:i.serverName})}),a.jsxs("div",{className:"mt-1 flex items-center gap-2",children:[a.jsx("progress",{className:"h-1.5 flex-1",value:i.current,max:i.total,"aria-label":r("app.embeddingSyncProgressAriaLabel",{serverName:i.serverName,current:i.current,total:i.total})}),a.jsxs("span",{className:"shrink-0 hub-mono hub-num text-[var(--hub-ink-3)]",children:[i.current,"/",i.total]})]})]},i.serverName))})}),a.jsxs("div",{className:"ml-auto flex items-center gap-1 shrink-0",children:[a.jsx("a",{href:"https://github.com/samanhappy/mcphub",target:"_blank",rel:"noopener noreferrer",className:"hub-icon-btn","aria-label":"GitHub Repository",children:a.jsx(ti,{className:"h-4 w-4"})}),a.jsx("a",{href:"https://docs.mcphub.app",target:"_blank",rel:"noopener noreferrer",className:"hub-icon-btn","aria-label":"Documentation",children:a.jsx(va,{className:"h-4 w-4"})}),a.jsx(Zn,{}),a.jsx(ri,{})]})]})},mi=()=>{const{t:e}=_(),[r,t]=d.useState([]),[n,i]=d.useState(!0),[l,s]=d.useState(null),[u,o]=d.useState(0),m=d.useCallback(async()=>{try{i(!0);const E=await Y("/groups");E&&E.success&&Array.isArray(E.data)?t(E.data):(console.error("Invalid group data format:",E),t([])),s(null)}catch(E){console.error("Error fetching groups:",E),s(E instanceof Error?E.message:"Failed to fetch groups"),t([])}finally{i(!1)}},[]),h=d.useCallback(()=>{o(E=>E+1)},[]),g=async(E,I,k=[],B={})=>{try{const M=await oe("/groups",{name:E,description:I,servers:k,...B});return console.log("Group created successfully:",M),!M||!M.success?(s((M==null?void 0:M.message)||e("groups.createError")),M):(h(),M||null)}catch(M){return s(M instanceof Error?M.message:"Failed to create group"),null}},A=async(E,I)=>{try{const k=await K(`/groups/${E}`,I);return!k||!k.success?(s((k==null?void 0:k.message)||e("groups.updateError")),k):(h(),k||null)}catch(k){return s(k instanceof Error?k.message:"Failed to update group"),null}},D=async(E,I)=>{try{const k=await K(`/groups/${E}/servers/batch`,{servers:I});return!k||!k.success?(s((k==null?void 0:k.message)||e("groups.updateError")),null):(h(),k.data||null)}catch(k){return s(k instanceof Error?k.message:"Failed to update group servers"),null}},O=async E=>{try{const I=await Se(`/groups/${E}`);return!I||!I.success?(s((I==null?void 0:I.message)||e("groups.deleteError")),I):(h(),I)}catch(I){return s(I instanceof Error?I.message:"Failed to delete group"),null}},x=async(E,I)=>{try{const k=await oe(`/groups/${E}/servers`,{serverName:I});return!k||!k.success?(s((k==null?void 0:k.message)||e("groups.serverAddError")),null):(h(),k.data||null)}catch(k){return s(k instanceof Error?k.message:"Failed to add server to group"),null}},L=async(E,I)=>{try{const k=await Se(`/groups/${E}/servers/${I}`);return!k||!k.success?(s((k==null?void 0:k.message)||e("groups.serverRemoveError")),null):(h(),k.data||null)}catch(k){return s(k instanceof Error?k.message:"Failed to remove server from group"),null}};return d.useEffect(()=>{m()},[m,u]),{groups:r,loading:n,error:l,setError:s,triggerRefresh:h,createGroup:g,updateGroup:A,updateGroupServers:D,deleteGroup:O,addServerToGroup:x,removeServerFromGroup:L}},pi=e=>!!(e!=null&&e.isAdmin),bd=({permissions:e,fallback:r=null,children:t})=>zt(e)?a.jsx(a.Fragment,{children:t}):a.jsx(a.Fragment,{children:r}),zt=e=>{const{auth:r}=Ce();if(!r.isAuthenticated||!r.user)return!1;const t=r.user.permissions||[];return e==="x"&&!t.includes("x")?!1:t.includes("*")||r.user.isAdmin?!0:(Array.isArray(e)?e:[e]).some(i=>t.includes(i))},Ut="mcphub.dismissedUpdateVersion";async function qt(e){const r=new URLSearchParams;r.set("currentVersion",e.currentVersion),r.set("locale",gi(e.locale)),e.force&&r.set("force","true");const t=await Y(`/changelog/update-info?${r.toString()}`);return!t.success||!t.data?null:t.data}function hi(e){localStorage.setItem(Ut,e)}function Bt(e){return e?localStorage.getItem(Ut)===e:!1}function Vr(e){return!!(e!=null&&e.hasUpdate&&e.latestVersion&&!Bt(e.latestVersion))}function gi(e){return e!=null&&e.toLowerCase().startsWith("zh")?"zh":"en"}const bi=({isOpen:e,onClose:r,version:t,initialUpdateInfo:n,onUpdateInfoChange:i,onDismissUpdate:l})=>{const{t:s,i18n:u}=_(),[o,m]=d.useState(n??null),[h,g]=d.useState(!1),[A,D]=d.useState(!1);d.useEffect(()=>{if(!e)return;const B=M=>{M.key==="Escape"&&r()};return document.addEventListener("keydown",B),()=>document.removeEventListener("keydown",B)},[e,r]),d.useEffect(()=>{m(n??null)},[n]),d.useEffect(()=>{D(!1)},[o==null?void 0:o.latestVersion]);const O=async(B=!1)=>{g(!0);try{const M=await qt({currentVersion:t,locale:u.language,force:B});m(M),i==null||i(M)}catch(M){console.error("Failed to check for updates:",M)}finally{g(!1)}};d.useEffect(()=>{e&&!o&&O(!1)},[e,o]);const x=(o==null?void 0:o.entries[0])??null,L=!!(o!=null&&o.hasUpdate&&o.latestVersion),E=d.useMemo(()=>A||Bt(o==null?void 0:o.latestVersion),[A,o==null?void 0:o.latestVersion]),I=Math.max(0,((o==null?void 0:o.totalUpdateCount)??0)-((o==null?void 0:o.entries.length)??0)),k=()=>{o!=null&&o.latestVersion&&(hi(o.latestVersion),D(!0),l==null||l(o.latestVersion))};return e?a.jsx("div",{className:"fixed inset-0 bg-black/50 z-50 flex items-center justify-center p-4",children:a.jsxs("div",{role:"dialog","aria-modal":"true","aria-labelledby":"about-dialog-title",className:"hub-card flex max-h-[calc(100dvh-2rem)] w-full max-w-[520px] flex-col overflow-hidden shadow-xl",children:[a.jsxs("div",{className:"p-5 relative shrink-0",children:[a.jsx("button",{onClick:r,className:"hub-icon-btn sm absolute top-4 right-4","aria-label":s("common.close"),children:a.jsx(xe,{className:"h-4 w-4"})}),a.jsxs("div",{className:"pr-8",children:[a.jsx("h3",{id:"about-dialog-title",className:"hub-h1",children:s("about.title")}),a.jsx("p",{className:"hub-sub",children:s("about.versionInfo",{version:t})})]})]}),a.jsx("div",{className:"min-h-0 overflow-y-auto overscroll-contain px-5 pb-5",children:a.jsxs("div",{className:"space-y-4",children:[h&&!o?a.jsxs("div",{className:"flex items-center gap-2 text-[13px]",style:{color:"var(--hub-ink-2)"},children:[a.jsx(Ir,{className:"h-4 w-4 animate-spin",style:{color:"var(--hub-accent)"}}),s("about.checking")]}):(o==null?void 0:o.source)==="disabled"?a.jsx("div",{className:"hub-card-pad rounded-md",style:{background:"var(--hub-bg-2)"},children:a.jsx("p",{className:"text-[13px]",style:{color:"var(--hub-ink-2)"},children:s("about.updateChecksDisabled")})}):L?a.jsxs("div",{className:"rounded-md border p-4",style:{borderColor:"var(--hub-line)",background:"var(--hub-bg-2)"},children:[a.jsxs("div",{className:"flex items-start justify-between gap-3",children:[a.jsxs("div",{children:[a.jsx("div",{className:"hub-mono text-[11px]",style:{color:"var(--hub-warn)"},children:s("about.newVersion")}),a.jsx("div",{className:"mt-1 text-[15px] font-medium",style:{color:"var(--hub-ink)"},children:s("about.newVersionAvailable",{version:o==null?void 0:o.latestVersion})})]}),E?a.jsx("span",{className:"hub-tag muted",children:s("about.dismissed")}):a.jsx("button",{className:"hub-btn ghost sm",onClick:k,children:s("about.dismissUpdate")})]}),x!=null&&x.summary?a.jsx("p",{className:"mt-3 text-[13px] leading-relaxed",style:{color:"var(--hub-ink-2)"},children:x.summary}):(o==null?void 0:o.source)==="npm-fallback"?a.jsx("p",{className:"mt-3 text-[13px]",style:{color:"var(--hub-ink-2)"},children:s("about.releaseNotesUnavailable")}):null]}):a.jsxs("div",{className:"flex items-center gap-2 text-[13px]",style:{color:"var(--hub-ink-2)"},children:[a.jsx(ya,{className:"h-4 w-4",style:{color:"var(--hub-ok)"}}),s("about.upToDate")]}),o!=null&&o.entries.length?a.jsxs("div",{className:"hub-card overflow-hidden",children:[a.jsx("div",{className:"px-4 py-3 hub-border-b",children:a.jsx("h4",{className:"hub-card-title",children:s("about.latestChanges")})}),a.jsx("div",{className:"hub-divider",children:o.entries.map(B=>a.jsxs("div",{className:"p-4",children:[a.jsxs("div",{className:"flex items-center justify-between gap-3",children:[a.jsxs("div",{children:[a.jsxs("div",{className:"hub-mono text-[12px]",style:{color:"var(--hub-accent)"},children:["v",B.version]}),a.jsx("div",{className:"mt-1 text-[13px] font-medium",style:{color:"var(--hub-ink)"},children:B.title})]}),a.jsx("a",{href:B.changelogUrl,target:"_blank",rel:"noopener noreferrer",className:"hub-icon-btn sm","aria-label":s("about.viewReleaseNotes"),children:a.jsx(Nr,{className:"h-3.5 w-3.5"})})]}),B.highlights.length>0&&a.jsx("ul",{className:"mt-2 space-y-1 list-none p-0",children:B.highlights.slice(0,3).map(M=>a.jsxs("li",{className:"text-[12.5px]",style:{color:"var(--hub-ink-2)"},children:[a.jsx("span",{style:{color:"var(--hub-accent)"},children:"•"})," ",M]},M))})]},B.version))}),I>0&&a.jsx("div",{className:"px-4 py-2 hub-border-t text-[12px]",style:{color:"var(--hub-ink-3)"},children:s("about.earlierReleases",{count:I})})]}):null,a.jsxs("div",{className:"flex flex-wrap items-center gap-2 pt-1",children:[a.jsxs("button",{onClick:()=>O(!0),disabled:h,className:`hub-btn ${h?"opacity-60 cursor-not-allowed":""}`,children:[a.jsx(Ir,{className:`h-4 w-4 ${h?"animate-spin":""}`}),s(h?"about.checking":"about.checkForUpdates")]}),a.jsxs("a",{href:(o==null?void 0:o.changelogUrl)||"https://www.mcphub.app/changelog",target:"_blank",rel:"noopener noreferrer",className:"hub-btn primary",children:[s(L?"about.viewReleaseNotes":"about.viewChangelog"),a.jsx(Nr,{className:"h-3.5 w-3.5"})]}),(x==null?void 0:x.url)&&a.jsx("a",{href:x.url,target:"_blank",rel:"noopener noreferrer",className:"hub-btn ghost",children:s("about.viewOnGitHub")})]})]})})]})}):null},vi=({open:e,onOpenChange:r})=>{const{i18n:t,t:n}=_();return e?a.jsx("div",{className:"fixed inset-0 bg-black/50 z-50 flex items-center justify-center p-4",children:a.jsx("div",{className:"bg-white dark:bg-gray-800 rounded-lg shadow-lg max-w-md w-full",children:a.jsxs("div",{className:"p-6 relative",children:[a.jsx("button",{onClick:()=>r(!1),className:"absolute top-4 right-4 text-gray-400 hover:text-gray-500 dark:text-gray-500 dark:hover:text-gray-400","aria-label":n("common.close"),children:a.jsx(xe,{className:"h-5 w-5"})}),a.jsx("h3",{className:"text-lg font-medium text-gray-900 dark:text-gray-100 mb-4",children:n("sponsor.title")}),a.jsx("div",{className:"flex flex-col items-center justify-center py-4",children:t.resolvedLanguage==="zh"?a.jsx("img",{src:"./assets/reward.png",alt:n("sponsor.rewardAlt"),className:"max-w-full h-auto",style:{maxHeight:"400px"}}):a.jsxs("div",{className:"text-center",children:[a.jsx("p",{className:"mb-4 text-gray-700 dark:text-gray-300",children:n("sponsor.supportMessage")}),a.jsx("a",{href:"https://ko-fi.com/samanhappy",target:"_blank",rel:"noopener noreferrer",className:"inline-flex items-center justify-center bg-[#13C3FF] text-white px-4 py-2 rounded-md hover:bg-[#00A5E5] transition-colors",children:n("sponsor.supportButton")})]})})]})})}):null},yi=({open:e,onOpenChange:r})=>{const{t}=_();return e?a.jsx("div",{className:"fixed inset-0 bg-black/50 z-50 flex items-center justify-center p-4",children:a.jsx("div",{className:"bg-white dark:bg-gray-800 rounded-lg shadow-lg max-w-md w-full",children:a.jsxs("div",{className:"p-6 relative",children:[a.jsx("button",{onClick:()=>r(!1),className:"absolute top-4 right-4 text-gray-400 hover:text-gray-500 dark:text-gray-500 dark:hover:text-gray-400","aria-label":t("common.close"),children:a.jsx(xe,{className:"h-5 w-5"})}),a.jsx("h3",{className:"text-lg font-medium text-gray-900 dark:text-gray-100 mb-4",children:t("wechat.title")}),a.jsxs("div",{className:"flex flex-col items-center justify-center py-4",children:[a.jsx("img",{src:"./assets/wexin.png",alt:t("wechat.qrCodeAlt"),className:"max-w-full h-auto",style:{maxHeight:"400px"}}),a.jsx("p",{className:"mt-4 text-center text-gray-700 dark:text-gray-300",children:t("wechat.scanMessage")})]})]})})}):null},fi=e=>{const{t:r}=_();return a.jsxs("svg",{role:"img",viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",fill:"currentColor",...e,children:[a.jsx("title",{children:r("common.wechat")}),a.jsx("path",{d:"M8.691 2.188C3.891 2.188 0 5.476 0 9.53c0 2.212 1.17 4.203 3.002 5.55a.59.59 0 0 1 .213.665l-.39 1.48c-.019.07-.048.141-.048.213 0 .163.13.295.29.295a.326.326 0 0 0 .167-.054l1.903-1.114a.864.864 0 0 1 .717-.098 10.16 10.16 0 0 0 2.837.403c.276 0 .543-.027.811-.05-.857-2.578.157-4.972 1.932-6.446 1.703-1.415 3.882-1.98 5.853-1.838-.576-3.583-4.196-6.348-8.596-6.348zM5.785 5.991c.642 0 1.162.529 1.162 1.18a1.17 1.17 0 0 1-1.162 1.178A1.17 1.17 0 0 1 4.623 7.17c0-.651.52-1.18 1.162-1.18zm5.813 0c.642 0 1.162.529 1.162 1.18a1.17 1.17 0 0 1-1.162 1.178 1.17 1.17 0 0 1-1.162-1.178c0-.651.52-1.18 1.162-1.18zm5.34 2.867c-1.797-.052-3.746.512-5.28 1.786-1.72 1.428-2.687 3.72-1.78 6.22.942 2.453 3.666 4.229 6.884 4.229.826 0 1.622-.12 2.361-.336a.722.722 0 0 1 .598.082l1.584.926a.272.272 0 0 0 .14.047c.134 0 .24-.111.24-.247 0-.06-.023-.12-.038-.177l-.327-1.233a.582.582 0 0 1-.023-.156.49.49 0 0 1 .201-.398C23.024 18.48 24 16.82 24 14.98c0-3.21-2.931-5.837-6.656-6.088V8.89c-.135-.01-.27-.027-.407-.03zm-2.53 3.274c.535 0 .969.44.969.982a.976.976 0 0 1-.969.983.976.976 0 0 1-.969-.983c0-.542.434-.982.97-.982zm4.844 0c.535 0 .969.44.969.982a.976.976 0 0 1-.969.983.976.976 0 0 1-.969-.983c0-.542.434-.982.969-.982z"})]})},ki=e=>{const{t:r}=_();return a.jsxs("svg",{role:"img",viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",fill:"currentColor",...e,children:[a.jsx("title",{children:r("common.discord")}),a.jsx("path",{d:"M20.317 4.3698a19.7913 19.7913 0 00-4.8851-1.5152.0741.0741 0 00-.0785.0371c-.211.3753-.4447.8648-.6083 1.2495-1.8447-.2762-3.68-.2762-5.4868 0-.1636-.3933-.4058-.8742-.6177-1.2495a.077.077 0 00-.0785-.037 19.7363 19.7363 0 00-4.8852 1.515.0699.0699 0 00-.0321.0277C.5334 9.0458-.319 13.5799.0992 18.0578a.0824.0824 0 00.0312.0561c2.0528 1.5076 4.0413 2.4228 5.9929 3.0294a.0777.0777 0 00.0842-.0276c.4616-.6304.8731-1.2952 1.226-1.9942a.076.076 0 00-.0416-.1057c-.6528-.2476-1.2743-.5495-1.8722-.8923a.077.077 0 01-.0076-.1277c.1258-.0943.2517-.1923.3718-.2914a.0743.0743 0 01.0776-.0105c3.9278 1.7933 8.18 1.7933 12.0614 0a.0739.0739 0 01.0785.0095c.1202.099.246.1981.3728.2924a.077.077 0 01-.0066.1276 12.2986 12.2986 0 01-1.873.8914.0766.0766 0 00-.0407.1067c.3604.698.7719 1.3628 1.225 1.9932a.076.076 0 00.0842.0286c1.961-.6067 3.9495-1.5219 6.0023-3.0294a.077.077 0 00.0313-.0552c.5004-5.177-.8382-9.6739-3.5485-13.6604a.061.061 0 00-.0312-.0286zM8.02 15.3312c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9555-2.4189 2.157-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.9555 2.4189-2.1569 2.4189zm7.9748 0c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9554-2.4189 2.1569-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.946 2.4189-2.1568 2.4189Z"})]})},Si=e=>{const{t:r}=_();return a.jsxs("svg",{role:"img",viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",fill:"currentColor",...e,children:[a.jsx("title",{children:r("sponsor.label")}),a.jsx("path",{d:"M17.625 1.499c-2.32 0-4.354 1.203-5.625 3.03-1.271-1.827-3.305-3.03-5.625-3.03C3.129 1.499 0 4.253 0 8.249c0 4.275 3.068 7.847 5.828 10.227a33.14 33.14 0 0 0 5.616 3.876l.028.017.008.003-.001.003c.163.085.342.126.521.125.179.001.358-.041.521-.125l-.001-.003.008-.003.028-.017a33.14 33.14 0 0 0 5.616-3.876C20.932 16.096 24 12.524 24 8.249c0-3.996-3.129-6.75-6.375-6.75zm-.919 15.275a30.766 30.766 0 0 1-4.703 3.316l-.004-.002-.004.002a30.955 30.955 0 0 1-4.703-3.316c-2.677-2.307-5.047-5.298-5.047-8.523 0-2.754 2.121-4.5 4.125-4.5 2.06 0 3.914 1.479 4.544 3.684.143.495.596.797 1.086.796.49.001.943-.302 1.085-.796.63-2.205 2.484-3.684 4.544-3.684 2.004 0 4.125 1.746 4.125 4.5 0 3.225-2.37 6.216-5.048 8.523z"})]})},Ci=({collapsed:e,version:r})=>{var F;const{t,i18n:n}=_(),i=oa(),{auth:l,logout:s}=Ce(),[u,o]=d.useState(!1),[m,h]=d.useState(!1),[g,A]=d.useState(!1),[D,O]=d.useState(!1),[x,L]=d.useState(!1),[E,I]=d.useState(null),k=d.useRef(null);d.useEffect(()=>{(async()=>{try{const Q=await qt({currentVersion:r,locale:n.language});I(Q),h(Vr(Q))}catch(Q){console.error("Error checking for new version:",Q)}})()},[r,n.language]),d.useEffect(()=>{const j=Q=>{k.current&&!k.current.contains(Q.target)&&o(!1)};return document.addEventListener("mousedown",j),()=>{document.removeEventListener("mousedown",j)}},[]);const B=()=>{i("/settings"),o(!1)},M=()=>{s(),i("/login")},W=()=>{A(!0),o(!1)},J=()=>{O(!0),o(!1)},C=()=>{L(!0),o(!1)};return a.jsxs("div",{ref:k,className:"relative",children:[a.jsxs("button",{onClick:()=>o(!u),className:`flex ${e?"justify-center":"items-center"} w-full p-2 hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors rounded-md ${u?"bg-gray-100 dark:bg-gray-700":""}`,children:[a.jsxs("div",{className:"flex-shrink-0 relative",children:[a.jsx("div",{className:"w-5 h-5 flex items-center justify-center rounded-full border border-gray-300 dark:border-gray-600 bg-gray-50 dark:bg-gray-700",children:a.jsx(fa,{className:"h-4 w-4 text-gray-700 dark:text-gray-300"})}),m&&a.jsx("span",{className:"absolute -top-1 -right-1 block w-2 h-2 bg-red-500 rounded-full"})]}),!e&&a.jsx("div",{className:"ml-3 flex flex-col items-start",children:a.jsx("span",{className:"text-sm font-medium text-gray-700 dark:text-gray-300",children:((F=l.user)==null?void 0:F.username)||t("auth.user")})})]}),u&&a.jsxs("div",{className:"absolute top-0 transform -translate-y-full left-0 w-full min-w-max bg-white border border-gray-200 dark:border-gray-700 dark:bg-gray-800 z-50",children:[a.jsxs("button",{onClick:J,className:"flex items-center w-full px-4 py-2 text-left text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:bg-gray-800 dark:hover:bg-gray-700",children:[a.jsx(Si,{className:"h-4 w-4 mr-2"}),t("sponsor.label")]}),n.resolvedLanguage==="zh"?a.jsxs("button",{onClick:C,className:"flex items-center w-full px-4 py-2 text-left text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:bg-gray-800 dark:hover:bg-gray-700",children:[a.jsx(fi,{className:"h-4 w-4 mr-2"}),t("wechat.label")]}):a.jsxs("a",{href:"https://discord.gg/2BJehJZVH5",target:"_blank",rel:"noopener noreferrer",className:"flex items-center w-full px-4 py-2 text-left text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:bg-gray-800 dark:hover:bg-gray-700",children:[a.jsx(ki,{className:"h-4 w-4 mr-2"}),t("discord.label")]}),a.jsxs("button",{onClick:B,className:"flex items-center w-full px-4 py-2 text-left text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:bg-gray-800 dark:hover:bg-gray-700",children:[a.jsx(et,{className:"h-4 w-4 mr-2"}),t("nav.settings")]}),a.jsxs("button",{onClick:W,className:"flex items-center w-full px-4 py-2 text-left text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:bg-gray-800 dark:hover:bg-gray-700 relative",children:[a.jsx(ka,{className:"h-4 w-4 mr-2"}),t("about.title"),m&&a.jsx("span",{className:"absolute top-2 right-4 block w-2 h-2 bg-red-500 rounded-full"})]}),a.jsx("div",{className:"border-t border-gray-200 dark:border-gray-600"}),a.jsxs("button",{onClick:M,className:"flex items-center w-full px-4 py-2 text-left text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:bg-gray-800 dark:hover:bg-gray-700",children:[a.jsx(Sa,{className:"h-4 w-4 mr-2"}),t("app.logout")]})]}),a.jsx(bi,{isOpen:g,onClose:()=>A(!1),version:r,initialUpdateInfo:E,onUpdateInfoChange:j=>{I(j),h(Vr(j))},onDismissUpdate:()=>{h(!1)}}),a.jsx(vi,{open:D,onOpenChange:O}),a.jsx(yi,{open:x,onOpenChange:L})]})},Pi=async()=>{var e;try{const r=await Y("/activities/available");return((e=r==null?void 0:r.data)==null?void 0:e.available)||!1}catch(r){return console.error("Error checking activity availability:",r),!1}},Ai=(e,r,t)=>{const n=new URLSearchParams;return n.append("page",e.toString()),n.append("limit",r.toString()),t!=null&&t.server&&n.append("server",t.server),t!=null&&t.tool&&n.append("tool",t.tool),t!=null&&t.status&&n.append("status",t.status),t!=null&&t.group&&n.append("group",t.group),t!=null&&t.username&&n.append("username",t.username),t!=null&&t.keyId&&n.append("keyId",t.keyId),t!=null&&t.keyName&&n.append("keyName",t.keyName),t!=null&&t.startDate&&n.append("startDate",t.startDate),t!=null&&t.endDate&&n.append("endDate",t.endDate),n.toString()},vd=async(e,r,t)=>{const n=Ai(e,r,t);return await Y(`/activities?${n}`)},yd=async e=>await Y(`/activities/${e}`),fd=async e=>{const r=new URLSearchParams;e!=null&&e.server&&r.append("server",e.server),e!=null&&e.tool&&r.append("tool",e.tool),e!=null&&e.status&&r.append("status",e.status),e!=null&&e.group&&r.append("group",e.group),e!=null&&e.username&&r.append("username",e.username),e!=null&&e.keyId&&r.append("keyId",e.keyId),e!=null&&e.keyName&&r.append("keyName",e.keyName),e!=null&&e.startDate&&r.append("startDate",e.startDate),e!=null&&e.endDate&&r.append("endDate",e.endDate);const t=r.toString();return await Y(`/activities/stats${t?`?${t}`:""}`)},kd=async()=>await Y("/activities/filters"),Sd=async(e=30)=>await Se(`/activities/cleanup?daysOld=${e}`),Ri=({collapsed:e})=>{var D,O;const{t:r}=_(),{dashboardTitle:t}=Mt(),{auth:n}=Ce(),{allServers:i}=Wn(),{groups:l}=mi(),[s,u]=d.useState(!1),o="1.1.14";d.useEffect(()=>{Pi().then(u).catch(()=>u(!1))},[]);const m=((D=n.user)==null?void 0:D.isAdmin)&&zt("x"),h=[{path:"/",label:r("nav.dashboard"),icon:a.jsx(Ca,{className:"h-4 w-4"}),end:!0},{path:"/servers",label:r("nav.servers"),icon:a.jsx(Pa,{className:"h-4 w-4"}),badge:i.length||void 0},{path:"/groups",label:r("nav.groups"),icon:a.jsx(Aa,{className:"h-4 w-4"}),badge:l.length||void 0},{path:"/prompts",label:r("nav.prompts"),icon:a.jsx(Ra,{className:"h-4 w-4"})},{path:"/resources",label:r("nav.resources"),icon:a.jsx(Ta,{className:"h-4 w-4"})},{path:"/market",label:r("nav.market"),icon:a.jsx(xa,{className:"h-4 w-4"})}],g=[...m?[{path:"/users",label:r("nav.users"),icon:a.jsx(wa,{className:"h-4 w-4"})}]:[],...s&&((O=n.user)!=null&&O.isAdmin)?[{path:"/activity",label:r("nav.activity"),icon:a.jsx(Da,{className:"h-4 w-4"})}]:[],...pi(n.user)?[{path:"/logs",label:r("nav.logs"),icon:a.jsx(Ea,{className:"h-4 w-4"})}]:[],{path:"/credentials",label:r("credentials.title"),icon:a.jsx(Ia,{className:"h-4 w-4"})},{path:"/settings",label:r("nav.settings"),icon:a.jsx(et,{className:"h-4 w-4"})}],A=x=>a.jsx(sa,{to:x.path,end:x.end,className:({isActive:L})=>["group flex items-center gap-2.5 rounded-md text-[13.5px] transition-colors",e?"justify-center px-2 py-2":"px-2.5 py-1.5",L?"bg-[var(--hub-surface)] text-[var(--hub-ink)] ring-1 ring-inset ring-[var(--hub-line)]":"text-[var(--hub-ink-2)] hover:bg-[var(--hub-surface-hover)] hover:text-[var(--hub-ink)]"].join(" "),children:({isActive:L})=>a.jsxs(a.Fragment,{children:[a.jsx("span",{className:L?"text-[var(--hub-ink)] flex-shrink-0":"text-[var(--hub-ink-3)] group-hover:text-[var(--hub-ink-2)] flex-shrink-0",children:x.icon}),!e&&a.jsxs(a.Fragment,{children:[a.jsx("span",{className:"truncate",children:x.label}),x.badge!=null&&a.jsx("span",{className:"ml-auto hub-mono hub-num text-[11px] text-[var(--hub-ink-3)]",children:x.badge})]})]})},x.path);return a.jsxs("aside",{className:"flex flex-col h-full relative shrink-0 transition-[width] duration-200 ease-out bg-[var(--hub-bg-2)] border-r border-[var(--hub-line)] "+(e?"w-14":"w-[232px]"),children:[a.jsxs("div",{className:"flex items-center gap-2.5 "+(e?"px-2 py-3 justify-center":"px-4 py-3"),children:[a.jsxs("div",{className:"relative grid shrink-0 h-7 w-7 place-items-center rounded-md text-white hub-mono text-[12px] font-semibold",style:{background:"linear-gradient(135deg, var(--hub-accent), oklch(0.62 0.18 285))",boxShadow:"inset 0 1px 0 rgba(255,255,255,0.14)"},children:[a.jsx("span",{children:"M"}),a.jsx("span",{className:"absolute -right-0.5 -bottom-0.5 w-[6px] h-[6px] rounded-full",style:{background:"var(--hub-ok)",boxShadow:"0 0 0 2px oklch(0.66 0.15 145 / 0.18)"}})]}),!e&&a.jsxs("div",{className:"flex flex-wrap items-baseline gap-x-1.5 min-w-0",children:[a.jsx("span",{className:"font-semibold tracking-tight text-[var(--hub-ink)] break-words min-w-0 max-w-full",children:t}),a.jsx("span",{className:"hub-mono text-[10.5px] text-[var(--hub-ink-3)] flex-shrink-0",children:`v${o}`})]})]}),a.jsxs("div",{className:"flex-1 overflow-y-auto pb-2",children:[!e&&a.jsx("div",{className:"hub-sect px-3 pt-2 pb-1.5",children:r("nav.workspace")}),a.jsx("nav",{className:"flex flex-col gap-px "+(e?"px-1.5":"px-2"),children:h.map(A)}),!e&&a.jsx("div",{className:"hub-sect px-3 pt-3 pb-1.5",children:r("nav.system")}),a.jsx("nav",{className:"flex flex-col gap-px "+(e?"px-1.5 mt-1":"px-2"),children:g.map(A)})]}),a.jsx("div",{className:"p-2.5 border-t border-[var(--hub-line)]",children:a.jsx(Ci,{collapsed:e,version:o})})]})},Ti=({children:e})=>a.jsx("main",{className:"flex-1 overflow-auto",style:{background:"var(--hub-bg)"},children:a.jsx("div",{className:"mx-auto w-full max-w-[1680px] px-6 pt-6 pb-16 lg:px-8 xl:px-10",children:e})}),xi=()=>a.jsx("div",{className:"flex h-full min-h-[240px] items-center justify-center text-sm",style:{color:"var(--hub-ink-3)"},children:"Loading..."}),wi=()=>{const[e,r]=ze.useState(!1),t=()=>{r(!e)};return a.jsx(li,{children:a.jsxs("div",{className:"flex h-screen",style:{background:"var(--hub-bg)",color:"var(--hub-ink)"},children:[a.jsx(Ri,{collapsed:e}),a.jsxs("div",{className:"flex flex-1 flex-col min-w-0 min-h-0",children:[a.jsx(ui,{onToggleSidebar:t}),a.jsx(Ti,{children:a.jsx(d.Suspense,{fallback:a.jsx(xi,{}),children:a.jsx(Zr,{})})})]})]})})},Di=({redirectPath:e="/login"})=>{const{t:r}=_(),{auth:t}=Ce();return t.loading?a.jsx("div",{className:"flex items-center justify-center h-screen",children:r("app.loading")}):t.isAuthenticated?a.jsx(Zr,{}):a.jsx(Ue,{to:e,replace:!0})},$r="[EMBED_SYNC_ERROR]",Ei=8e3,Jr=3e4,Ii=()=>{const{showToast:e}=At(),r=d.useRef(new Map);return d.useEffect(()=>{const t=u=>{const o=Date.now();r.current.forEach((h,g)=>{o-h>=Jr&&r.current.delete(g)});const m=r.current.get(u);return m&&o-m<Jr?!0:(r.current.set(u,o),!1)},n=u=>{const o=u.match(/server\s+"([^"]+)"/i);return(o==null?void 0:o[1])||null},i=(u,o)=>{t(u)||e(o,"error",Ei)},l=u=>{const o=u.replace($r,"").trim(),m=n(o);if(o.includes("Full embeddings resync failed")){i("embedding-resync-failed","Embedding resynchronization failed. Check smart routing logs and provider limits.");return}if(m){i(`embedding-sync-error:${m}`,`Embedding synchronization failed for server "${m}". Check logs for details.`);return}i(`embedding-sync-error:${o}`,o||"Embedding synchronization failed. Check smart routing logs and provider rate limits.")},s=u=>{var o,m,h;try{const g=JSON.parse(u.data);if((g==null?void 0:g.type)==="embedding-sync-progress"){const D=typeof((o=g.progress)==null?void 0:o.serverName)=="string"?g.progress.serverName:"";(typeof((m=g.progress)==null?void 0:m.status)=="string"?g.progress.status:"")==="error"&&D&&i(`embedding-sync-error:${D}`,`Embedding synchronization failed for server "${D}". Check logs for details.`);return}if((g==null?void 0:g.type)!=="log")return;const A=String(((h=g==null?void 0:g.log)==null?void 0:h.message)||"");if(!A.includes($r))return;l(A)}catch{}};return Qe.subscribe(s)},[e]),null},Ni=d.lazy(()=>ee(()=>import("./LoginPage-Hn1uu0vB.js"),__vite__mapDeps([0,1,2,3]),import.meta.url)),Oi=d.lazy(()=>ee(()=>import("./OAuthConsentPage-DofQEZAU.js"),__vite__mapDeps([4,1,2,3]),import.meta.url)),Mi=d.lazy(()=>ee(()=>import("./Dashboard-CCiZcGi4.js"),__vite__mapDeps([5,1,6,7,8,9,2,3,10]),import.meta.url)),Li=d.lazy(()=>ee(()=>import("./CredentialsPage-BnzqPYjg.js"),__vite__mapDeps([11,1,2,3]),import.meta.url)),zi=d.lazy(()=>ee(()=>import("./ServersPage-wVLsTL_f.js"),__vite__mapDeps([12,1,2,3,8,10,7,13,14,15,16,17,18,6]),import.meta.url)),Ui=d.lazy(()=>ee(()=>import("./GroupsPage-DHgQeVHy.js"),__vite__mapDeps([19,1,6,2,7,8,14,3,15]),import.meta.url)),qi=d.lazy(()=>ee(()=>import("./UsersPage-BtdFWcVD.js"),__vite__mapDeps([20,1,2,21,15,10,3]),import.meta.url)),Bi=d.lazy(()=>ee(()=>import("./SettingsPage-DkfXDE5_.js"),__vite__mapDeps([22,1,7,2,21,13,3,9,16]),import.meta.url)),Wr=d.lazy(()=>ee(()=>import("./MarketPage-Bvi1KESo.js"),__vite__mapDeps([23,1,2,17,8,3,18]),import.meta.url)),Fi=d.lazy(()=>ee(()=>import("./LogsPage-JMCtTjCv.js"),__vite__mapDeps([24,1,2,3]),import.meta.url)),Ki=d.lazy(()=>ee(()=>import("./ActivityPage-C8Zj4FeE.js"),__vite__mapDeps([25,1,18,2,3]),import.meta.url)),ji=d.lazy(()=>ee(()=>import("./PromptsPage-B-8vczAR.js"),__vite__mapDeps([26,1,2,16,10,3]),import.meta.url)),Gi=d.lazy(()=>ee(()=>import("./ResourcesPage-DLAIatoG.js"),__vite__mapDeps([27,1,2,16,10,3]),import.meta.url)),Hi=()=>{const{serverName:e}=Qr();return a.jsx(Ue,{to:`/market/${e}`,replace:!0})},Yr=()=>a.jsx("div",{className:"flex min-h-screen items-center justify-center text-sm text-gray-500",children:"Loading..."});function Xr(){const e=Fe();return a.jsx(Gn,{children:a.jsx(Va,{children:a.jsx(Jn,{children:a.jsx(Kn,{children:a.jsx(Qn,{children:a.jsxs(la,{basename:e,children:[a.jsx(Ii,{}),a.jsxs(ca,{children:[a.jsx(V,{path:"/login",element:a.jsx(d.Suspense,{fallback:a.jsx(Yr,{}),children:a.jsx(Ni,{})})}),a.jsx(V,{path:"/oauth/authorize",element:a.jsx(d.Suspense,{fallback:a.jsx(Yr,{}),children:a.jsx(Oi,{})})}),a.jsx(V,{element:a.jsx(Di,{}),children:a.jsxs(V,{element:a.jsx(wi,{}),children:[a.jsx(V,{path:"/",element:a.jsx(Mi,{})}),a.jsx(V,{path:"/credentials",element:a.jsx(Li,{})}),a.jsx(V,{path:"/servers",element:a.jsx(zi,{})}),a.jsx(V,{path:"/groups",element:a.jsx(Ui,{})}),a.jsx(V,{path:"/prompts",element:a.jsx(ji,{})}),a.jsx(V,{path:"/resources",element:a.jsx(Gi,{})}),a.jsx(V,{path:"/users",element:a.jsx(qi,{})}),a.jsx(V,{path:"/market",element:a.jsx(Wr,{})}),a.jsx(V,{path:"/market/:serverName",element:a.jsx(Wr,{})}),a.jsx(V,{path:"/cloud",element:a.jsx(Ue,{to:"/market",replace:!0})}),a.jsx(V,{path:"/cloud/:serverName",element:a.jsx(Hi,{})}),a.jsx(V,{path:"/logs",element:a.jsx(Fi,{})}),a.jsx(V,{path:"/activity",element:a.jsx(Ki,{})}),a.jsx(V,{path:"/settings",element:a.jsx(Bi,{})})]})}),a.jsx(V,{path:"*",element:a.jsx(Ue,{to:"/"})})]})]})})})})})})}const _i={title:"MCPHub Dashboard",error:"Error",closeButton:"Close",noServers:"No MCP servers available",loading:"Loading...",logout:"Logout",profile:"Profile",changePassword:"Change Password",toggleSidebar:"Toggle Sidebar",welcomeUser:"Welcome, {{username}}",name:"MCPHub",embeddingSyncProgress:"Embeddings for {{serverName}}",embeddingSyncProgressAriaLabel:"Creating embeddings for {{serverName}}: {{current}} of {{total}} completed"},Vi={title:"About",versionInfo:"MCPHub Version: {{version}}",newVersion:"New version available!",currentVersion:"Current version",newVersionAvailable:"New version {{version}} is available",viewOnGitHub:"View on GitHub",checkForUpdates:"Check for Updates",checking:"Checking for updates...",viewChangelog:"View changelog",viewReleaseNotes:"View release notes",viewAllChanges:"View all changes",latestChanges:"Latest changes",upToDate:"You are on the latest known version.",releaseNotesUnavailable:"A newer version is available, but structured release notes are not available yet.",updateChecksDisabled:"Update checks are disabled for this deployment.",dismissUpdate:"Dismiss",dismissed:"Dismissed",earlierReleases:"+ {{count}} earlier releases"},$i={viewProfile:"View profile",userCenter:"User Center"},Ji={label:"Sponsor",title:"Support the Project",rewardAlt:"Reward QR Code",supportMessage:"Support the development of MCPHub by buying me a coffee!",supportButton:"Support on Ko-fi"},Wi={label:"WeChat",title:"Connect via WeChat",qrCodeAlt:"WeChat QR Code",scanMessage:"Scan this QR code to connect with us on WeChat"},Yi={label:"Discord",title:"Join our Discord server",community:"Join our growing community on Discord for support, discussions, and updates!"},Xi={title:"Theme",light:"Light",dark:"Dark",system:"System"},Qi={createAccount:"Create account",backToLogin:"Back to sign in",userAlreadyExists:"Username already exists",login:"Login",loginTitle:"Login to MCPHub",slogan:"Open-source, self-hosted MCP gateway and control plane",subtitle:"Connect, organize, control, and operate Model Context Protocol servers through unified endpoints.",username:"Username",password:"Password",loggingIn:"Logging in...",orContinue:"Or continue with",loginWithGoogle:"Continue with Google",loginWithGithub:"Continue with GitHub",loginWithOIDC:"Continue with OIDC",socialLoginFailed:"Social login failed. Please try again.","error.account_not_linked":"Account not linked. Your email may not be verified by the identity provider. Please verify your email and try again.","error.email_doesn't_match":"The email from the identity provider does not match your existing account.","error.email_not_found":"No email was returned by the identity provider.","error.access_denied":"Access was denied by the identity provider.","error.account_already_linked_to_different_user":"This account is already linked to a different user.","error.unable_to_link_account":"Unable to link the account. Please try again.","error.signup_disabled":"Sign up is currently disabled.","error.oauth_provider_not_found":"OAuth provider not found.","error.invalid_code":"Invalid authorization code. Please try again.","error.unable_to_get_user_info":"Unable to get user information from the identity provider.",emptyFields:"Username and password cannot be empty",loginFailed:"Login failed, please check your username and password",loginError:"An error occurred during login",serverUnavailable:"Unable to connect to the server. Please check your network connection or try again later",currentPassword:"Current Password",newPassword:"New Password",confirmPassword:"Confirm Password",passwordsNotMatch:"New password and confirmation do not match",changePasswordSuccess:"Password changed successfully",changePasswordError:"Failed to change password",changePassword:"Change Password",passwordChanged:"Password changed successfully",passwordChangeError:"Failed to change password",defaultPasswordWarning:"Default Password Security Warning",defaultPasswordMessage:"You are using the default password (admin123), which poses a security risk. Please change your password immediately to protect your account.",goToSettings:"Go to Settings",passwordStrengthError:"Password does not meet security requirements",passwordMinLength:"Password must be at least 8 characters long",passwordRequireLetter:"Password must contain at least one letter",passwordRequireNumber:"Password must contain at least one number",passwordRequireSpecial:"Password must contain at least one special character",passwordStrengthHint:"Password must be at least 8 characters and contain letters, numbers, and special characters"},Zi=JSON.parse(`{"protocolVersion":"MCP protocol","protocolVersionUnknown":"Not available","localExecutionRequiresAdmin":"Local command execution requires an administrator.","httpOAuthRequiresAdmin":"Allowing HTTP OAuth token endpoints requires an administrator.","startOnDemand":"Start On Demand","startOnDemandDescription":"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.","idleTimeoutMs":"Idle shutdown timeout (ms)","idleTimeoutMsDescription":"Shut down the process after this many milliseconds with no tool calls. Default: 300000 (5 minutes).","addServer":"Add Server","add":"Add","edit":"Edit","copy":"Copy","duplicate":"Duplicate","delete":"Delete","confirmDelete":"Are you sure you want to delete this server?","deleteWarning":"Deleting server '{{name}}' will remove it and all its data. This action cannot be undone.","status":"Status","tools":"Tools","prompts":"Prompts","name":"Server Name","nameInvalid":"Server name can only contain letters, numbers, dots, underscores, and hyphens (no spaces or special characters)","description":"Server Note","descriptionPlaceholder":"Optional note to describe this server","url":"Server URL","apiKey":"API Key","save":"Save","cancel":"Cancel","invalidConfig":"Could not find configuration data for {{serverName}}","addError":"Failed to add server","editError":"Failed to edit server {{serverName}}","deleteError":"Failed to delete server {{serverName}}","updateError":"Failed to update server","editTitle":"Edit Server: {{serverName}}","duplicateTitle":"Duplicate Server: {{serverName}}","type":"Server Type","typeStdio":"STDIO","typeSse":"SSE","typeStreamableHttp":"Streamable HTTP","typeOpenapi":"OpenAPI","mcpApp":"MCP App — this server exposes interactive UI resources","visibility":"Visibility","visibilityPrivateShort":"Private","visibilityPrivate":"Private — only the owner and admins","visibilityGroupShort":"Shared","visibilityGroup":"Shared — selected users only","visibilityPublicShort":"Public","visibilityPublic":"Public — every authenticated user","visibilityDescription":"Controls which non-admin users can discover and call this server. Admins always have access.","shareWithUsers":"Share with users","shareWithUsersDescription":"Selected users can discover and call this server, but cannot manage its configuration.","shareCandidatesLoading":"Loading users...","shareCandidatesError":"Failed to load users.","shareAfterCreate":"Save the server before selecting users.","noShareCandidates":"No other users are available.","shareUserSearchLabel":"Search users","shareUserSearchPlaceholder":"Search usernames...","selectAllShareUsers":"Select all","deselectAllShareUsers":"Deselect all","noMatchingShareUsers":"No users match your search.","command":"Command","packageVersion":"Installed package version (last installed by the runner cache)","reportedVersion":"Version reported by the server","updateAvailable":"A newer version is available on the registry","arguments":"Arguments","addArgument":"Add argument","argumentsHint":"Each field is one argument. Spaces and quotes are preserved; an empty field passes an empty argument.","argumentLabel":"Argument {{index}}","removeArgument":"Remove argument {{index}}","envVars":"Environment Variables","headers":"HTTP Headers","key":"key","value":"value","enabled":"Enabled","enable":"Enable","disable":"Disable","reload":"Reload","reloadSuccess":"Server reloaded successfully","reloadError":"Failed to reload server {{serverName}}","reinstall":"Reinstall","reinstallConfirm":"This will clear the package cache and re-download dependencies. The server will restart.","reinstallSuccess":"Server reinstall initiated","reinstallError":"Failed to reinstall server {{serverName}}","disconnectOAuth":"Disconnect OAuth","disconnectOAuthConfirm":"This will revoke stored OAuth credentials where supported and require authorization again.","disconnectOAuthSuccess":"Server OAuth disconnected","disconnectOAuthError":"Failed to disconnect OAuth for server {{serverName}}","requestOptions":"Connection Configuration","maxBufferSize":"Stdio buffer limit (bytes)","maxBufferSizeDescription":"Maximum stdio read buffer size. Leave blank for the SDK default (10 MiB). Larger limits allow higher memory use.","timeout":"Request Timeout","timeoutDescription":"Timeout for requests to the MCP server (ms)","maxTotalTimeout":"Maximum Total Timeout","maxTotalTimeoutDescription":"Maximum total timeout for requests sent to the MCP server (ms) (Use with progress notifications)","resetTimeoutOnProgress":"Reset Timeout on Progress","resetTimeoutOnProgressDescription":"Reset timeout on progress notifications (enabled by default)","keepAlive":"Connection Health","retryScheduled":"Retry at {{time}}","reconnecting":"Reconnecting…","lastRetry":"Last retry: {{time}} ({{count}} attempts)","enableKeepAlive":"Enable Health Checks","keepAliveDescription":"Run periodic health checks. Disconnected remote servers always reconnect automatically with backoff.","keepAliveInterval":"Check interval (ms)","keepAliveIntervalDescription":"Time between health checks in milliseconds (default: 60000ms = 1 minute)","perSessionClient":"Per-Session Client Isolation","perSessionClientDescription":"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.","remove":"Remove","toggleError":"Failed to toggle server {{serverName}}","alreadyExists":"Server {{serverName}} already exists","invalidData":"Invalid server data provided","notFound":"Server {{serverName}} not found","namePlaceholder":"Enter server name","urlPlaceholder":"Enter server URL","commandPlaceholder":"Enter command","argumentsPlaceholder":"Enter arguments","errorDetails":"Error Details","viewErrorDetails":"View error details","copyConfig":"Copy Configuration","confirmVariables":"Confirm Variable Configuration","variablesDetected":"Variables detected in configuration. Please confirm these variables are properly configured:","detectedVariables":"Detected Variables","confirmVariablesMessage":"Please ensure these variables are properly defined in your runtime environment. Continue adding server?","confirmAndAdd":"Confirm and Add","openapi":{"inputMode":"Input Mode","inputModeUrl":"Specification URL","inputModeSchema":"JSON Schema","specUrl":"OpenAPI Specification URL","schema":"OpenAPI JSON Schema","schemaHelp":"Paste your complete OpenAPI JSON schema here","security":"Security Type","securityNone":"None","securityApiKey":"API Key","securityHttp":"HTTP Authentication","securityOAuth2":"OAuth 2.0","securityOpenIdConnect":"OpenID Connect","securityDetect":"Detect from spec","securityDetecting":"Detecting…","securityNotDeclared":"This spec does not declare a security scheme.","securityPrefillNotice":"This spec declares {{summary}}. Security settings were pre-filled — add your credential value before the first call.","securityMismatchWarning":"The spec declares {{summary}}, but this server is configured as {{configured}}. This can cause silent 401 responses.","securityUnsupportedNotice":"This spec declares {{summary}}, which MCPHub cannot represent ({{reason}}). Configure authentication manually.","apiKeyConfig":"API Key Configuration","apiKeyName":"Header/Parameter Name","apiKeyIn":"Location","apiKeyValue":"API Key Value","httpAuthConfig":"HTTP Authentication Configuration","httpScheme":"Authentication Scheme","httpCredentials":"Credentials","httpCredentialsBasicHint":"Enter user:password (encoded automatically) or pre-encoded Base64.","specSecurityToggle":"Specification URL requires separate authentication","specSecurityHelp":"Enable only when the spec document itself is protected differently from the API (e.g. Basic-protected /v3/api-docs behind a Bearer-protected API). When off, the security configuration above is used for both.","httpSchemeBasic":"Basic","httpSchemeBearer":"Bearer","httpSchemeDigest":"Digest","oauth2Config":"OAuth 2.0 Configuration","oauth2Token":"Access Token","openIdConnectConfig":"OpenID Connect Configuration","openIdConnectUrl":"Discovery URL","openIdConnectToken":"ID Token","apiKeyInHeader":"Header","apiKeyInQuery":"Query","apiKeyInCookie":"Cookie","passthroughHeaders":"Passthrough Headers","passthroughHeadersHelp":"Comma-separated list of header names to pass through from incoming MCP requests to upstream server requests (e.g., Authorization, X-API-Key)","cookieSession":"Cookie Session Handling","cookieSessionHelp":"Capture Set-Cookie from upstream login responses and replay them on later calls within the same downstream session. Isolated per MCP session; not persisted.","statsMeasuring":"Measuring the generated tool list…","statsSummary":"{{toolCount}} tools · ~{{bytes}} of definitions · ~{{tokens}} tokens","statsWarning":"This tool list alone may approach or exceed common model context windows. Consider exposing fewer tools — create a group or disable individual tools on the server.","statsUnavailable":"The specification could not be measured. You can still continue; the server will validate the import when it is submitted."},"oauth":{"sectionTitle":"OAuth Configuration","sectionDescription":"Configure client credentials for OAuth-protected servers (optional).","allowInsecureTokenEndpoint":"Allow HTTP OAuth token endpoints","allowInsecureTokenEndpointHelp":"Admin only. Disabled by default. Sends credentials and tokens without TLS for this upstream. Enable only on a trusted network; HTTPS is recommended. Once enabled, only administrators can edit this entire server configuration; a non-admin owner cannot edit it.","clientId":"Client ID","clientSecret":"Client Secret","authorizationEndpoint":"Authorization Endpoint","tokenEndpoint":"Token Endpoint","scopes":"Scopes","scopesPlaceholder":"scope1 scope2","resource":"Resource / Audience","accessToken":"Access Token","refreshToken":"Refresh Token","identityMode":"OAuth identity","sharedIdentity":"Shared account","personalIdentity":"Each user authorizes independently","personalIdentityHelp":"Personal mode requires dashboard authorization for each user. User-associated keys use their owner; shared/service keys are ineligible.","personalConnect":"Connect","personalReconnect":"Reconnect","personalDisconnect":"Disconnect","personalError":"Personal authorization failed","personalSuccess":"Personal authorization saved. Return to Dashboard → Servers."}}`),eo={sleeping:"Sleeping",sleepingDescription:"On-demand server - will start automatically when a tool is called",online:"Online",offline:"Offline",connecting:"Connecting",oauthRequired:"OAuth Required",clickToAuthorize:"Click to authorize with OAuth",oauthWindowOpened:"OAuth authorization window opened. Please complete the authorization.",oauthClientIdHint:'This server has a preconfigured OAuth client ID. If authorization fails with "invalid redirect_uri", remove the clientId so MCPHub can register its own OAuth client automatically.'},ro={general:"Something went wrong",network:"Network connection error. Please check your internet connection",serverConnection:"Unable to connect to the server. Please check if the server is running",serverAdd:"Failed to add server. Please check the server status",serverUpdate:"Failed to edit server {{serverName}}. Please check the server status",serverFetch:"Failed to retrieve server data. Please try again later",initialStartup:"The server might be starting up. Please wait a moment as this process can take some time on first launch...",serverInstall:"Failed to install server",failedToFetchSettings:"Failed to fetch settings",failedToUpdateRouteConfig:"Failed to update route configuration",failedToUpdateSmartRoutingConfig:"Failed to update smart routing configuration",failedToUpdateBetterAuthConfig:"Failed to update Better Auth configuration"},to={processing:"Processing...",save:"Save",cancel:"Cancel",back:"Back",refresh:"Refresh",search:"Search",clear:"Clear",view:"View",create:"Create",creating:"Creating...",update:"Update",updating:"Updating...",submitting:"Submitting...",delete:"Delete",remove:"Remove",copy:"Copy",copyId:"Copy ID",copyUrl:"Copy URL",copyOpenApiUrl:"Copy OpenAPI URL",copySuccess:"Copied to clipboard",copyFailed:"Copy failed",copied:"Copied",close:"Close",confirm:"Confirm",language:"Language",true:"True",false:"False",dismiss:"Dismiss",github:"GitHub",wechat:"WeChat",discord:"Discord",required:"Required",itemsPerPage:"Items per page",showing:"Showing {{start}}-{{end}} of {{total}}",previous:"Previous",next:"Next",secret:"Secret",default:"Default",value:"Value",type:"Type",repeated:"Repeated",valueHint:"Value Hint",choices:"Choices",actions:"Actions",saving:"Saving...",active:"Active",inactive:"Inactive",viewAll:"View all",docs:"Docs",all:"All"},ao={title:"Copy MCP configuration",description:"Pick your client to copy a ready-to-paste configuration for {{name}}.",menuItem:"Copy MCP config",tokenPrompt:"MCPHub access token",configBlock:"Configuration",commandBlock:"CLI command",copied:"Copied",noTransport:"This server has no client-side MCP transport (it is OpenAPI-backed). Use the hub or a group endpoint instead.",clients:{"generic-mcp-servers":{label:"Generic (mcpServers)",hint:"Widely accepted mcpServers block: Claude Desktop, Cline, Cherry Studio and most clients."},"generic-http":{label:"Generic HTTP",hint:`Escape hatch with the bare entry: remote endpoints give a raw HTTP entry (SSE upstreams carry a "type": "sse" marker), local servers a raw stdio entry (command/args/env). Paste it into your client's own server map; for most clients use Generic (mcpServers).`},"claude-code":{label:"Claude Code",hint:"Claude Code: `claude mcp add`, or the mcpServers block in ~/.claude.json."},cursor:{label:"Cursor",hint:"Cursor: .cursor/mcp.json in a project, or ~/.cursor/mcp.json globally."},vscode:{label:"VS Code / Copilot",hint:"VS Code / Copilot: .vscode/mcp.json in the workspace, or mcp.json in your user profile."},codex:{label:"Codex",hint:"Codex: ~/.codex/config.toml, or a project-level .codex/config.toml."},opencode:{label:"OpenCode",hint:"OpenCode: ~/.config/opencode/opencode.json globally, or opencode.json in the project."},windsurf:{label:"Windsurf",hint:"Windsurf: ~/.codeium/windsurf/mcp_config.json."},"cherry-studio":{label:"Cherry Studio",hint:"Cherry Studio: Settings > MCP Servers > Add Server > Import JSON."},codebuddy:{label:"CodeBuddy Code",hint:"CodeBuddy Code: ~/.codebuddy/.mcp.json globally, or .mcp.json in the project."},qoder:{label:"Qoder",hint:"Qoder: Settings > MCP > Add Manually, then paste the JSON."},trae:{label:"TRAE",hint:"TRAE: Settings > MCP > Add > Add Manually, then paste the JSON."},zcode:{label:"ZCode",hint:"ZCode: Settings > MCP Servers > New MCP Server > Full configuration."},workbuddy:{label:"WorkBuddy",hint:"WorkBuddy: Plugins > MCP Servers > Configure MCP, or ~/.workbuddy/mcp.json."}}},no={rowsPerPage:"Rows per page",showing:"Showing {{from}}-{{to}} of {{total}}"},io={dashboard:"Dashboard",servers:"Servers",groups:"Groups",prompts:"Prompts",resources:"Resources",users:"Users",settings:"Settings",changePassword:"Change Password",market:"Market",cloud:"Cloud Market",logs:"Logs",activity:"Activity",workspace:"Workspace",system:"System"},oo={dashboard:{title:"Dashboard",totalServers:"Total",onlineServers:"Online",disabledServers:"Disabled",offlineServers:"Offline",connectingServers:"Connecting",recentServers:"Recent Servers",endpoints:"MCP Endpoints",endpointsHint:"Use these URLs in Claude Desktop, Cursor or any MCP client"},servers:{title:"Server Management"},groups:{title:"Group Management"},prompts:{title:"Built-in Prompts"},resources:{title:"Built-in Resources"},users:{title:"User Management"},settings:{title:"Settings",language:"Language",account:"Account Settings",password:"Change Password",appearance:"Appearance",routeConfig:"Security",installConfig:"Installation",smartRouting:"Smart Routing",oauthServer:"OAuth Server"},market:{title:"Market Hub - Local and Cloud Markets"},logs:{title:"System Logs"}},so={filters:"Filters",search:"Search logs...",autoScroll:"Auto-scroll",clearLogs:"Clear logs",loading:"Loading logs...",noLogs:"No logs available.",noMatch:"No logs match the current filters.",mainProcess:"Main Process",childProcess:"Child Process",main:"Main",child:"Child"},lo={legacyVisibility:"Legacy — choose visibility",legacyVisibilityHint:"This group keeps its previous endpoint access until you explicitly choose visibility.",visibilityDescription:"Group access also requires access to each server. Sharing a group does not share private servers. Only the owner and admins can manage the group.",shareAfterCreate:"Save the group before selecting users.",add:"Add",addNew:"Add New Group",edit:"Edit Group",delete:"Delete",confirmDelete:"Are you sure you want to delete this group?",deleteWarning:"Deleting group '{{name}}' will remove it and all its server associations. This action cannot be undone.",name:"Group Name",namePlaceholder:"Enter group name",instructions:"Instructions",instructionsHelp:"Optional. Sent to MCP clients when they connect to this group (also as $smart/<group>); most clients add it to the model's system prompt.",instructionsPlaceholder:"e.g. Use fetch for web pages; if it fails, use firecrawl_scrape.",nameRequired:"Group name is required",description:"Description",descriptionPlaceholder:"Enter group description (optional)",createError:"Failed to create group",updateError:"Failed to update group",deleteError:"Failed to delete group",serverAddError:"Failed to add server to group",serverRemoveError:"Failed to remove server from group",addServer:"Add Server to Group",selectServer:"Select a server to add",servers:"Servers in Group",remove:"Remove",noGroups:"No groups available. Create a new group to get started.",noServers:"No servers in this group.",noServerOptions:"No servers available",serverCount:"{{count}} Servers",toolSelection:"Tool Selection",promptSelection:"Prompt Selection",resourceSelection:"Resource Selection",toolsSelected:"Selected",promptsSelected:"Selected",resourcesSelected:"Selected",allTools:"All",allPrompts:"All prompts",allResources:"All resources",selectedTools:"Selected tools",selectedPrompts:"Selected prompts",selectedResources:"Selected resources",selectAll:"Select All",selectNone:"Select None",configureTools:"Configure Tools",configureCapabilities:"Configure Tools, Prompts, and Resources",alias:"Exposed Name",preserveToolNames:"Keep original tool names",preserveToolNamesHint:"Expose tools without a server prefix. Tool names must be unique across the group. Exposed Name still applies to prompts.",pinTool:"Pin: always list this tool on the group's Smart Routing endpoint, next to search_tools",pinToolLabel:"Pin to the Smart Routing endpoint",unpinTool:"Unpin: reach this tool through search_tools only",previewPrompts:"[prompts: {{items}}]",previewResources:"[resources: {{items}}]",previewAllTools:"(all tools)",previewAllPrompts:"(all prompts)",previewAllResources:"(all resources)",bulkSearch:"Search by name or description…",bulkSearchLabel:"Search {{capability}}",annotationFilter:"Filter by annotation",allAnnotations:"All annotations",readOnlyHint:"Read-only hint",destructiveHint:"Destructive hint",idempotentHint:"Idempotent hint",flatList:"Flat list",riskGroups:"Risk groups",visibleCount:"{{count}} of {{total}} visible",selectVisible:"Select visible",deselectVisible:"Deselect visible",invertVisible:"Invert visible",riskHint:"Groups use upstream hints and name heuristics; they do not guarantee safety. Actions affect filtered items only.",noMatchingItems:"No matching items",risk_read:"Read",risk_create:"Create",risk_update:"Update",risk_delete:"Delete",risk_other:"Other / unclassified"},co={title:"Local Installation",official:"Official",by:"By",unknown:"Unknown",tools:"tools",search:"Search",searchPlaceholder:"Search for servers by name, category, or tags",clearFilters:"Clear",clearCategoryFilter:"",clearTagFilter:"",categories:"Categories",tags:"Tags",showTags:"Show tags",hideTags:"Hide tags",moreTags:"",noServers:"No servers found matching your search",backToList:"Back to list",install:"Install",installing:"Installing...",installed:"Installed",installServer:"Install Server: {{name}}",installSuccess:"Server {{serverName}} installed successfully",author:"Author",license:"License",repository:"Repository",examples:"Examples",arguments:"Arguments",argumentName:"Name",description:"Description",required:"Required",example:"Example",viewSchema:"View schema",fetchError:"Error fetching market servers",serverNotFound:"Server not found",searchError:"Error searching servers",filterError:"Error filtering servers by category",tagFilterError:"Error filtering servers by tag",noInstallationMethod:"No installation method available for this server",showing:"Showing {{from}}-{{to}} of {{total}} servers",perPage:"Per page",confirmVariablesMessage:"Please ensure these variables are properly defined in your runtime environment. Continue installing server?",confirmAndInstall:"Confirm and Install"},uo={authorizeTitle:"Authorize Application",authorizeSubtitle:"Allow this application to access your MCPHub account.",buttons:{approve:"Allow access",deny:"Deny",approveSubtitle:"Recommended if you trust this application.",denySubtitle:"You can always grant access later."},application:"Application",scopesTitle:"This application will be able to:",noScopes:"No permissions requested.",requestInvalidTitle:"Request invalid",requestInvalid:"This authorization request is invalid or has expired. Please go back and try again.",grantingAccessTo:"Granting access to:",resourceAll:"All MCP servers",resourceSmart:"Smart routing",resourceServer:"MCP server: {{name}}",resourceGroup:"MCP group: {{name}}",clientId:"Client ID",willRedirectTo:"Will redirect to:",policy:"Privacy policy",terms:"Terms",homepage:"Homepage"},mo={title:"Cloud Support",subtitle:"Powered by MCPRouter",by:"By",server:"Server",config:"Config",created:"Created",updated:"Updated",available:"Available",description:"Description",details:"Details",tools:"Tools",tool:"tool",toolsAvailable:"{{count}} tool available||{{count}} tools available",loadingTools:"Loading tools...",noTools:"No tools available for this server",noDescription:"No description available",viewDetails:"View Details",parameters:"Parameters",result:"Result",error:"Error",callTool:"Call",calling:"Calling...",toolCallSuccess:"Tool {{toolName}} executed successfully",toolCallError:"Failed to call tool {{toolName}}: {{error}}",viewSchema:"View Schema",backToList:"Back to Cloud Market",search:"Search",searchPlaceholder:"Search cloud servers by name, title, or author",clearFilters:"Clear Filters",clearCategoryFilter:"Clear",clearTagFilter:"Clear",categories:"Categories",tags:"Tags",noCategories:"No categories found",noTags:"No tags found",noServers:"No cloud servers found",fetchError:"Error fetching cloud servers",serverNotFound:"Cloud server not found",searchError:"Error searching cloud servers",filterError:"Error filtering cloud servers by category",tagFilterError:"Error filtering cloud servers by tag",showing:"Showing {{from}}-{{to}} of {{total}} cloud servers",perPage:"Per page",apiKeyNotConfigured:"MCPRouter API key not configured",apiKeyNotConfiguredDescription:"To use cloud servers, you need to configure your MCPRouter API key.",getApiKey:"Get API Key",configureInSettings:"Configure in Settings",installServer:"Install {{name}}",installSuccess:"Server {{name}} installed successfully",installError:"Failed to install server: {{error}}"},po={title:"Registry",official:"Official",latest:"Latest",description:"Description",website:"Website",repository:"Repository",packages:"Packages",package:"package",remotes:"Remotes",remote:"remote",published:"Published",updated:"Updated",install:"Install",installing:"Installing...",installed:"Installed",installServer:"Install {{name}}",installSuccess:"Server {{name}} installed successfully",installError:"Failed to install server: {{error}}",noDescription:"No description available",viewDetails:"View Details",backToList:"Back to Registry",search:"Search",searchPlaceholder:"Search registry servers by name",clearFilters:"Clear",noServers:"No registry servers found",fetchError:"Error fetching registry servers",serverNotFound:"Registry server not found",showing:"Showing {{from}}-{{to}} of {{total}} registry servers",perPage:"Per page",environmentVariables:"Environment Variables",packageArguments:"Package Arguments",runtimeArguments:"Runtime Arguments",headers:"Headers"},ho={run:"Run",running:"Running...",runTool:"Run Tool",cancel:"Cancel",noDescription:"No description available",inputSchema:"Input Schema:",runToolWithName:"Run Tool: {{name}}",execution:"Tool Execution",successful:"Successful",failed:"Failed",result:"Result:",error:"Error",errorDetails:"Error Details:",noContent:"Tool executed successfully but returned no content.",unknownError:"Unknown error occurred",jsonResponse:"JSON Response:",toolResult:"Tool result",noParameters:"This tool does not require any parameters.",selectOption:"Select an option",enterValue:"Enter {{type}} value",enabled:"Enabled",enableSuccess:"Tool {{name}} enabled successfully",disableSuccess:"Tool {{name}} disabled successfully",toggleFailed:"Failed to toggle tool status",descriptionUpdateSuccess:"Tool description updated successfully",descriptionUpdateFailed:"Failed to update tool description",descriptionModifiedBadge:"Modified",defaultDescriptionLabel:"Default description",visibleParams:"Parameters shown to models",visibleParamsHelp:"Unchecked parameters are removed from the schema models receive and dropped from their calls. Required parameters (*) cannot be hidden.",requiredParam:"Required parameters cannot be hidden",hiddenParamsFailed:"Failed to update hidden parameters",defaultDescriptionTooltip:"Default description: {{description}}",restoreDefault:"Restore default",restoreDefaultSuccess:"Tool description restored to default",restoreDefaultFailed:"Failed to restore the default tool description",parameters:"Tool Parameters",formMode:"Form Mode",jsonMode:"JSON Mode",jsonConfiguration:"JSON Configuration",invalidJsonFormat:"Invalid JSON format",fixJsonBeforeSwitching:"Please fix JSON format before switching to form mode",item:"Item {{index}}",addItem:"Add {{key}} item",enterKey:"Enter {{key}}"},go={run:"Get",running:"Getting...",result:"Prompt Result",error:"Prompt Error",execution:"Prompt Execution",successful:"Successful",failed:"Failed",errorDetails:"Error Details:",noContent:"Prompt executed successfully but returned no content.",unknownError:"Unknown error occurred",jsonResponse:"JSON Response:",description:"Description",messages:"Messages",noDescription:"No description available",runPromptWithName:"Get Prompt: {{name}}",descriptionUpdateSuccess:"Prompt description updated successfully",descriptionUpdateFailed:"Failed to update prompt description",restoreDefault:"Restore default",restoreDefaultSuccess:"Prompt description restored to default",restoreDefaultFailed:"Failed to restore the default prompt description"},bo=JSON.parse(`{"dashboardName":"Dashboard name","dashboardNameDescription":"Shown in the sidebar, header, login page and browser tab. Leave blank to restore the default name.","dashboardNameSaveFailed":"Failed to save dashboard name","resetBearerKey":"Reset Bearer key","resetBearerKeyConfirm":"Reset this Bearer key? The old token will stop working immediately. Permissions and enabled status will stay the same.","resetBearerKeySuccess":"Bearer key reset. Copy and save the new token before closing; it will not be shown again.","resetBearerKeyError":"Failed to reset Bearer key","allowRegistration":"Allow self-registration","allowRegistrationDescription":"Allow visitors to create regular accounts from the login page. Disabled by default; unavailable while password login is disabled.","allowedCidrs":"Allowed upstream CIDR ranges","allowedCidrsDescription":"One IPv4 or IPv6 CIDR per line. All users can connect upstream MCP, OpenAPI and OAuth endpoints in these ranges. Empty means no additional access. Admin-owned servers retain unrestricted internal access. Avoid broad ranges and metadata or loopback addresses unless required. Changes apply to new requests; existing connections are not closed.","allowedCidrsUpdateFailed":"Failed to update allowed CIDR ranges","subtitle":"Configure system settings, authentication, routing, and MCP server integrations.","enableGlobalRoute":"Enable Global Route","enableGlobalRouteDescription":"Allow connections to /sse endpoint without specifying a group ID","enableGroupNameRoute":"Enable Group Name Route","enableGroupNameRouteDescription":"Allow connections to /sse endpoint using group names instead of just group IDs","enableBearerAuth":"Enable Bearer Authentication","enableBearerAuthDescription":"Require bearer token authentication for MCP endpoints (default on)","bearerAuthKey":"Bearer Authentication Key","bearerAuthKeyDescription":"The authentication key that will be required in the Bearer token","bearerAuthKeyPlaceholder":"Enter bearer authentication key","bearerAuthHeaderName":"Bearer Auth Header Name","bearerAuthHeaderNameDescription":"Header name used to receive MCP bearer credentials. Change this when upstream passthrough headers also use Authorization.","bearerAuthHeaderNamePlaceholder":"e.g. Authorization or X-MCP-Authorization","bearerKeysSectionTitle":"Keys","bearerKeysSectionDescription":"Manage multiple keys with different access scopes.","bearerKeyScopeFilter":"Filter by scope","noBearerKeys":"No keys configured yet.","bearerKeyName":"Name","bearerKeyToken":"Token","bearerKeyEnabled":"Enabled","bearerKeyAccessType":"Access scope","bearerKeyAccessAll":"All","bearerKeyAccessGroups":"Groups","bearerKeyAccessServers":"Servers","bearerKeyAccessCustom":"Custom","bearerKeyAllowedGroups":"Allowed groups","bearerKeyAllowedServers":"Allowed servers","addBearerKey":"Add key","addBearerKeyButton":"Create","bearerKeyRequired":"Name and token are required","bearerKeyNameRequired":"Name is required","bearerKeyOwnerRequired":"Owner is required","bearerKeyKind":"Key type","bearerKeyKindSystem":"System-level","bearerKeyKindUser":"User-level","bearerKeyOwner":"Owner","bearerKeySelectOwner":"Select user...","bearerKeyAccessUserVisibility":"User visibility","bearerKeyShownOnce":"Copy this token now. It will not be shown again.","deleteBearerKeyConfirm":"Are you sure you want to delete this key?","generate":"Generate","selectGroups":"Select Groups","selectServers":"Select Servers","selectAtLeastOneGroup":"Please select at least one group","selectAtLeastOneServer":"Please select at least one server","skipAuth":"Skip Authentication","skipAuthDescription":"Allow dashboard access without login; unauthenticated users get guest admin access (does not affect MCP endpoint auth)","jsonBodyLimit":"JSON Body Size Limit","jsonBodyLimitDescription":"Express JSON request size limit. This affects large OpenAPI schema uploads as well.","jsonBodyLimitPlaceholder":"e.g. 1mb, 5mb, 1024kb","pythonIndexUrl":"Python Package Repository URL","pythonIndexUrlDescription":"Set UV_DEFAULT_INDEX environment variable for Python package installation","pythonIndexUrlPlaceholder":"e.g. https://pypi.org/simple","npmRegistry":"NPM Registry URL","npmRegistryDescription":"Set npm_config_registry environment variable for NPM package installation","npmRegistryPlaceholder":"e.g. https://registry.npmjs.org/","baseUrl":"Base URL","baseUrlDescription":"Base URL for MCP requests and OAuth callbacks","baseUrlPlaceholder":"e.g. http://localhost:3000","installConfig":"Installation","clearCache":"Clear package cache","clearCacheDescription":"Clear npm and uv package caches. Servers may need to re-download packages on next start.","clearCacheConfirm":"This will clear the npm and uv package caches. Servers may need to re-download packages on next start.","clearCacheSuccess":"Package cache cleared successfully","clearCacheError":"Failed to clear package cache","clearCacheSkipped":"not installed","clearingCache":"Clearing...","systemConfigUpdated":"System configuration updated successfully","noChanges":"No changes to save","betterAuthTitle":"Better Auth","betterAuthEnvNote":"Client IDs and secrets still come from environment variables. Changing Better Auth settings may require an application restart, and the install base URL origin is trusted automatically.","enableBetterAuth":"Enable Better Auth","enableBetterAuthDescription":"Enable social and OIDC login when the required environment variables are configured.","disablePasswordLogin":"Disable password login","disablePasswordLoginDescription":"Only allow sign-in through the SSO providers: the username/password form and POST /api/auth/login are turned off. Takes effect only while at least one provider is enabled and was already enabled when the application started. BETTER_AUTH_DISABLE_PASSWORD_LOGIN overrides this setting, and setting it to false is the way back in if the identity provider is unavailable.","betterAuthBaseUrl":"Base URL","betterAuthBaseUrlDescription":"Public base URL used to build Better Auth redirect URIs. Falls back to the install base URL when empty; the BETTER_AUTH_URL environment variable takes precedence.","betterAuthBasePath":"Auth base path","betterAuthBasePathDescription":"Relative API path used by the Better Auth routes.","betterAuthTrustedOrigins":"Trusted origins","betterAuthTrustedOriginsDescription":"Comma-separated origins allowed for Better Auth requests. The install base URL origin is added automatically.","betterAuthProviders":"Providers","betterAuthProvidersDescription":"Provider switches control which configured login methods are exposed on the sign-in page.","betterAuthGoogleDescription":"Requires GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET.","betterAuthGithubDescription":"Requires GITHUB_CLIENT_ID and GITHUB_CLIENT_SECRET.","betterAuthOidcDescription":"Requires OIDC client credentials plus a discovery URL.","betterAuthOidcProviderId":"OIDC provider ID","betterAuthOidcProviderIdDescription":"Provider identifier used when starting the OIDC login flow.","betterAuthOidcDiscoveryUrl":"OIDC discovery URL","betterAuthOidcDiscoveryUrlDescription":"Well-known OpenID configuration URL published by your identity provider.","betterAuthOidcScopes":"OIDC scopes","betterAuthOidcScopesDescription":"Comma-separated scopes requested during the OIDC sign-in flow.","betterAuthOidcPrompt":"OIDC prompt","betterAuthOidcPromptDescription":"Optional prompt value sent to the identity provider, such as login or consent.","betterAuthOidcPkce":"Enable PKCE","betterAuthOidcPkceDescription":"Use PKCE for the OIDC authorization flow.","enableSmartRouting":"Enable Smart Routing","enableSmartRoutingDescription":"Enable smart routing feature to search the most suitable tool based on input (using $smart group name)","dbUrl":"PostgreSQL URL (requires pgvector support)","dbUrlPlaceholder":"e.g. postgresql://user:password@localhost:5432/dbname","embeddingProvider":"Embedding Provider","embeddingProviderPreset":"Provider Preset","embeddingProviderPresetDescription":"Choose a provider to prefill its OpenAI-compatible endpoint and model.","embeddingProviderPresetOpenai":"OpenAI","embeddingProviderPresetOpenrouter":"OpenRouter","embeddingProviderPresetSiliconflow":"SiliconFlow · free tier (1000 RPM)","embeddingProviderPresetGemini":"Google Gemini · free tier (100 RPM)","embeddingProviderPresetCustom":"Other / OpenAI-compatible","llmProviderBaseUrl":"OpenAI-compatible Base URL","llmProviderBaseUrlPlaceholder":"https://api.openai.com/v1","llmProviderApiKey":"LLM Provider API Key","llmProviderApiKeyPlaceholder":"Enter LLM provider API key","smartRoutingEnvOverrideWarning":"Currently supplied by the environment variable {{envVar}} — the value saved here is ignored at runtime.","embeddingModel":"Embedding Model Name","embeddingModelPlaceholder":"text-embedding-3-small","basePacingDelayMs":"Base Pacing Delay (ms)","basePacingDelayMsDescription":"Baseline delay between embedding API requests. Defaults to 0 — the system manages rate limits automatically: it respects Retry-After headers, falls back to a 63-second cooldown, and increases the pacing delay after any 403/429 response. Set a non-zero value only if your provider enforces a fixed minimum interval between requests.","basePacingDelayMsPlaceholder":"Empty = default 0 ms","basePacingDelayMsAuto":"Default ({{value}} ms): rate limiting is managed automatically.","basePacingDelayMsZero":"0 ms (default): rate limiting is managed automatically via adaptive throttling and retry logic.","basePacingDelayMsOverride":"Custom value: overrides the default baseline pacing delay.","embeddingEncodingFormat":"Embedding Encoding Format","embeddingEncodingFormatDescription":"Encoding format for embedding vectors. Auto will detect based on provider support.","embeddingEncodingFormatAuto":"Auto (Recommended)","embeddingDimensions":"Embedding Dimensions","embeddingDimensionsDescription":"Optional output size for providers that support it. Leave empty to use the model's default.","embeddingDimensionsPlaceholder":"Empty = model default","embeddingDimensionsApiPassthrough":"Forward dimensions to API (MRL passthrough)","embeddingDimensionsApiPassthroughDescription":"Only models known to support Matryoshka (MRL) receive the dimensions parameter. Enable this to force it for other MRL-capable models. Non-MRL models (Qwen3-Embedding, BGE, vLLM/sglang) reject the parameter outright, so leave this off for them.","azureOpenaiEndpoint":"Azure OpenAI Endpoint","azureOpenaiEndpointPlaceholder":"https://YOUR_RESOURCE_NAME.openai.azure.com","azureOpenaiApiKey":"Azure OpenAI API Key","azureOpenaiApiKeyPlaceholder":"Enter Azure OpenAI API key","azureOpenaiApiVersion":"Azure OpenAI API Version","azureOpenaiApiVersionPlaceholder":"2024-02-15-preview","azureOpenaiEmbeddingDeployment":"Azure OpenAI Embedding Deployment","azureOpenaiEmbeddingDeploymentPlaceholder":"text-embedding-3-small","azureOpenaiEmbeddingModel":"Azure Embedding Model Name","azureOpenaiEmbeddingModelDescription":"The actual OpenAI model name deployed in Azure (e.g. text-embedding-3-small). Used for accurate token counting before sending text to the API.","azureOpenaiEmbeddingModelPlaceholder":"text-embedding-3-small","progressiveDisclosure":"Progressive Disclosure","progressiveDisclosureDescription":"When enabled, search_tools returns only tool names and descriptions. Use describe_tool to get full parameter schema, reducing token usage.","embeddingMaxTokens":"Max Embedding Tokens","embeddingMaxTokensDescription":"Maximum tokens for text truncation before generating embeddings. Leave empty to use the model default automatically. A custom value always overrides the model default. Manually setting this value is especially useful when using local LLM providers to prevent truncation errors.","embeddingMaxTokensPlaceholder":"Empty = auto by model","embeddingMaxTokensAuto":"Auto: {{limit}} tokens (model default for {{model}})","embeddingMaxTokensOverride":"This value overrides the model default.","embeddingPrefixes":"Embedding Task Prefixes","embeddingPrefixesDescription":"Text prepended before embedding, for asymmetric retrieval models trained with task prefixes (e.g. EmbeddingGemma, E5, Nomic). Leave both empty for models that expect raw text. Include the trailing space. Changing the document prefix re-embeds all tools.","embeddingQueryPrefix":"Query prefix","embeddingDocumentPrefix":"Document prefix","searchResults":"Search Results","searchResultsDescription":"How search_tools filters and returns matches. Every hit carries its similarity score. Leave both empty for the defaults.","similarityThreshold":"Similarity threshold (0-1)","similarityThresholdPlaceholder":"Empty = by query length (0.2 / 0.3 / 0.4)","fullSchemaTopN":"Full schemas for the top N results","fullSchemaTopNPlaceholder":"Empty = all results; lower ones get describe_tool","toolDefinitionFields":"Tool fields in results","toolDefinitionFieldsDescription":"Optional fields that search_tools and describe_tool results carry next to the name, description and inputSchema. Default: title and annotations. The others are mostly for clients and can be large (icons are base64 images).","invalidSearchSettings":"Invalid value for {{fields}}. The similarity threshold must be between 0 and 1, and top N a whole number of 0 or more.","smartRoutingConfigUpdated":"Smart routing configuration updated successfully","smartRoutingRequiredFields":"Database URL is required to enable smart routing. An LLM Provider API Key is required for cloud-based providers (local LLMs usually don't require an API key, enter any value to pass the form validation)","smartRoutingValidationError":"Please fill in the required fields before enabling Smart Routing: {{fields}}","smartRoutingWorkflow":"Workflow","smartRoutingWorkflowDescription":"Prompts are vectorized; top-k similar tools are fetched from pgvector and exposed to the upstream LLM.","toolResultCompressionTitle":"Tool Result Compression","toolResultCompressionEnable":"Enable compression","toolResultCompressionDescription":"Reduce large text tool outputs before they reach MCP clients. Changes apply to the next tool call.","toolResultCompressionStrategy":"Strategy","toolResultCompressionStrategyDescription":"Auto detects JSON, logs, search output, diffs, and plain text.","toolResultCompressionMinTokens":"Minimum tokens","toolResultCompressionMinTokensDescription":"Only compress text blocks at or above this size.","toolResultCompressionMaxOutputTokens":"Output token budget","toolResultCompressionMaxOutputTokensDescription":"Target maximum tokens for each compressed text block.","mcpRouterConfig":"Cloud Market","mcpRouterApiKey":"MCPRouter API Key","mcpRouterApiKeyDescription":"API key for accessing MCPRouter cloud market services","mcpRouterApiKeyPlaceholder":"Enter MCPRouter API key","mcpRouterReferer":"Referer","mcpRouterRefererDescription":"Referer header for MCPRouter API requests","mcpRouterRefererPlaceholder":"https://www.mcphub.app","mcpRouterTitle":"Title","mcpRouterTitleDescription":"Title header for MCPRouter API requests","mcpRouterTitlePlaceholder":"MCPHub","mcpRouterBaseUrl":"Base URL","mcpRouterBaseUrlDescription":"Base URL for MCPRouter API","mcpRouterBaseUrlPlaceholder":"https://api.mcprouter.to/v1","systemSettings":"System Settings","nameSeparatorLabel":"Name Separator","nameSeparatorDescription":"Character used to separate server name and tool/prompt name (default: -)","enableSessionRebuild":"Enable Server Session Rebuild","enableSessionRebuildDescription":"When enabled, applies the improved server session rebuild code for better session management experience","storeToolPayload":"Store Tool Call Payloads","storeToolPayloadDescription":"When enabled, the full input and output of each tool call is stored in activity logs. Tool payloads are saved verbatim without redaction; turn this off if tool arguments may contain sensitive data and should not be persisted.","storeToolPayloadUpdateFailed":"Failed to update tool payload storage setting","restartRequired":"Configuration saved. It is recommended to restart the application to ensure all services load the new settings correctly.","exportMcpSettings":"Export Settings","mcpSettingsJson":"MCP Settings JSON","mcpSettingsJsonDescription":"View, copy, or download your current mcp_settings.json configuration for backup or migration to other tools","copyToClipboard":"Copy to Clipboard","downloadJson":"Download JSON","exportSuccess":"Settings exported successfully","exportError":"Failed to fetch settings","enableOauthServer":"Enable OAuth Server","enableOauthServerDescription":"Allow MCPHub to issue OAuth tokens for external clients","requireClientSecret":"Require Client Secret","requireClientSecretDescription":"When enabled, confidential clients must present a client secret (disable for PKCE-only clients)","requireState":"Require State Parameter","requireStateDescription":"Reject authorization requests that omit the OAuth state parameter","accessTokenLifetime":"Access Token Lifetime (seconds)","accessTokenLifetimeDescription":"How long issued access tokens remain valid","accessTokenLifetimePlaceholder":"e.g. 3600","refreshTokenLifetime":"Refresh Token Lifetime (seconds)","refreshTokenLifetimeDescription":"How long refresh tokens remain valid","refreshTokenLifetimePlaceholder":"e.g. 1209600","authorizationCodeLifetime":"Authorization Code Lifetime (seconds)","authorizationCodeLifetimeDescription":"How long authorization codes remain valid before they can be exchanged","authorizationCodeLifetimePlaceholder":"e.g. 300","allowedScopes":"Allowed Scopes","allowedScopesDescription":"Comma-separated list of scopes users can approve during authorization","allowedScopesPlaceholder":"e.g. read, write","enableDynamicRegistration":"Enable Dynamic Client Registration","dynamicRegistrationDescription":"Allow RFC 7591 compliant clients to self-register using the public endpoint","dynamicRegistrationAllowedGrantTypes":"Allowed Grant Types","dynamicRegistrationAllowedGrantTypesDescription":"Comma-separated list of grants permitted for dynamically registered clients","dynamicRegistrationAllowedGrantTypesPlaceholder":"e.g. authorization_code, refresh_token","dynamicRegistrationAuth":"Require Authentication","dynamicRegistrationAuthDescription":"Protect the registration endpoint so only authenticated requests can register clients","invalidNumberInput":"Please enter a valid non-negative number","dynamicRegistrationClientTtl":"Idle Client Cleanup TTL (seconds)","dynamicRegistrationClientTtlDescription":"Reap dynamically-registered clients with no live tokens and no in-progress authorization flow older than this age. Set to 0 to disable cleanup.","dynamicRegistrationClientTtlPlaceholder":"e.g. 2592000","smartRoutingIndexTitle":"Vector Index & Diagnostics","smartRoutingIndexRefresh":"Refresh","smartRoutingIndexReindex":"Reindex","smartRoutingIndexReindexing":"Reindexing…","smartRoutingIndexLoading":"Loading…","smartRoutingIndexNoData":"No index data yet. Enable Smart Routing and click Reindex to build the vector store.","smartRoutingIndexStatsUnavailable":"Statistics unavailable","smartRoutingIndexDatabase":"Database","smartRoutingIndexConnected":"Connected","smartRoutingIndexDisconnected":"Disconnected","smartRoutingIndexUnhealthy":"Unhealthy","smartRoutingIndexModel":"Model","smartRoutingIndexDimensions":"Dimensions","smartRoutingIndexTotalRows":"Total rows","smartRoutingIndexToolRows":"Tool rows","smartRoutingIndexServerRows":"Server rows","smartRoutingIndexClusterLabel":"Indexed servers","smartRoutingIndexCoverage":"Coverage","smartRoutingIndexLastSynced":"Last synced","smartRoutingIndexPerServer":"Tools per server","smartRoutingIndexMissingIndex":"{{count}} enabled server(s) missing an index","smartRoutingIndexSyncedRange":"Sync range: {{oldest}} → {{newest}}","smartRoutingIndexReindexDone":"Reindex completed: {{synced}} server(s) synced, {{failed}} failed, {{skipped}} skipped, {{total}} tools in total","smartRoutingIndexReindexFailed":"Reindex failed: {{message}}","smartRoutingIndexReindexStarting":"Starting reindex…","smartRoutingIndexReindexingServer":"Reindexing \\"{{server}}\\"","smartRoutingIndexReindexSummary":"Reindex done · {{synced}} synced, {{failed}} failed, {{skipped}} skipped, {{total}} tools","smartRoutingIndexReindexConfirmTitle":"Rebuild vector index?","smartRoutingIndexReindexConfirmMessage":"All existing embeddings will be cleared and regenerated from scratch. This can take a while and consumes embedding API quota.","smartRoutingIndexPersonalCredentials":"Personal-credential servers","smartRoutingIndexSkippedReason":"Skipped","smartRoutingIndexIndexedAs":"indexed as {{principals}}","toolPolicies":{"missingReferences":"Some rule IDs were not found in the loaded servers, keys or groups. An unmatched deny provides no protection; an unmatched allow may block access. Verify these references before saving. You can still save rules for resources you plan to create.","missingReference":"Rule {{policyId}}: {{selector}} {{value}} was not found.","title":"Tool access policies","description":"Rules apply to tool discovery and invocation, including smart routing. Changes take effect after saving.","semantics":"Blank selectors match everyone or every target. Selectors in a rule must all match. Applicable allow rules form an allowlist for the subject; matching deny rules win. Policies never grant access beyond existing permissions.","empty":"No policies configured. Existing access permissions apply.","rule":"Rule {{number}}","id":"Rule ID (unique, required)","effect":"Effect","allow":"Allow","deny":"Deny","username":"Username","keyId":"Bearer key ID","groupId":"Endpoint group ID","serverId":"Server ID","tool":"Original upstream tool name","any":"Any","selectorsHint":"Choose a suggestion or enter an exact value. IDs survive renames. The group is the endpoint group, not server membership. Tool names are case-sensitive, without the gateway prefix; no wildcards.","add":"Add rule","save":"Save policies","unsaved":"Unsaved changes. Additions and deletions take effect only after saving.","invalid":"Each rule needs a unique, non-empty ID and a valid effect. Optional selectors must not contain only whitespace.","saveFailed":"Could not save policies. Your changes are retained.","confirm":"Apply the policy set immediately ({{count}} rules)? This may change which tools callers can discover and invoke.","confirmClear":"Remove all policies? Access will fall back to existing permissions.","deleteRule":"Delete rule {{number}}","retry":"Retry"}}`),vo={upload:"Upload",uploadTitle:"Upload MCPB Bundle",dropFileHere:"Drop your .mcpb file here",orClickToSelect:"or click to select from your computer",invalidFileType:"Please select a valid .mcpb file",noFileSelected:"Please select a .mcpb file to upload",uploading:"Uploading...",uploadFailed:"Failed to upload MCPB file",installServer:"Install MCP Server from MCPB",extensionInfo:"Extension Information",name:"Name",version:"Version",description:"Description",author:"Author",tools:"Tools",serverName:"Server Name",serverNamePlaceholder:"Enter a name for this server",install:"Install",installing:"Installing...",installFailed:"Failed to install server from MCPB",serverExistsTitle:"Server Already Exists",serverExistsConfirm:"Server '{{serverName}}' already exists. Do you want to override it with the new version?",override:"Override"},yo={button:"Import",title:"Import Servers from JSON",inputLabel:"Server Configuration JSON",inputHelp:"Paste your server configuration JSON. Supports STDIO, SSE, and HTTP (streamable-http) server types.",preview:"Preview",previewTitle:"Preview Servers to Import",import:"Import",importing:"Importing...",invalidFormat:"Invalid JSON format. The JSON must contain an 'mcpServers' object.",parseError:"Failed to parse JSON. Please check the format and try again.",addFailed:"Failed to add server",importFailed:"Failed to import servers",partialSuccess:"Imported {{count}} of {{total}} servers successfully. Some servers failed:",validationErrors:"Some servers could not be imported. Please fix the following and try again:"},fo={button:"Import",title:"Import Groups from JSON",inputLabel:"Group Configuration JSON",inputHelp:"Paste your group configuration JSON. Each group can contain a list of servers.",preview:"Preview",previewTitle:"Preview Groups to Import",import:"Import",importing:"Importing...",invalidFormat:"Invalid JSON format. The JSON must contain a 'groups' array.",missingName:"Each group must have a 'name' field.",parseError:"Failed to parse JSON. Please check the format and try again.",addFailed:"Failed to add group",importFailed:"Failed to import groups",partialSuccess:"Imported {{count}} of {{total}} groups successfully. Some groups failed:"},ko={add:"Add User",addNew:"Add New User",edit:"Edit User",delete:"Delete User",create:"Create User",update:"Update User",username:"Username",email:"Email",emailPlaceholder:"Enter email (optional)",password:"Password",newPassword:"New Password",confirmPassword:"Confirm Password",changePassword:"Change Password",adminRole:"Administrator",admin:"Admin",user:"User",role:"Role",actions:"Actions",addFirst:"Add your first user",permissions:"Permissions",adminPermissions:"Full system access",userPermissions:"Limited access",currentUser:"You",noUsers:"No users found",adminRequired:"Administrator access required to manage users",usernameRequired:"Username is required",passwordRequired:"Password is required",passwordTooShort:"Password must be at least 6 characters long",passwordMismatch:"Passwords do not match",usernamePlaceholder:"Enter username",passwordPlaceholder:"Enter password",newPasswordPlaceholder:"Leave empty to keep current password",confirmPasswordPlaceholder:"Confirm new password",createError:"Failed to create user",updateError:"Failed to update user",deleteError:"Failed to delete user",statsError:"Failed to fetch user statistics",deleteConfirmation:"Are you sure you want to delete user '{{username}}'? This action cannot be undone.",confirmDelete:"Delete User",deleteWarning:"Are you sure you want to delete user '{{username}}'? This action cannot be undone."},So={errors:{readonly:"Readonly for demo environment",invalid_credentials:"Invalid username or password",password_login_disabled:"Password login is disabled. Sign in with SSO, or use a bearer key for API access.",serverNameRequired:"Server name is required",serverConfigRequired:"Server configuration is required",serverConfigInvalid:"Server configuration must include either a URL, OpenAPI specification URL or schema, or command with arguments",serverTypeInvalid:"Server type must be one of: stdio, sse, streamable-http, openapi",urlRequiredForType:"URL is required for {{type}} server type",openapiSpecRequired:"OpenAPI specification URL or schema is required for openapi server type",headersInvalidFormat:"Headers must be an object",headersNotSupportedForStdio:"Headers are not supported for stdio server type",serverNotFound:"Server not found",failedToRemoveServer:"Server not found or failed to remove",internalServerError:"Internal server error",failedToGetServers:"Failed to get servers information",failedToReloadServer:"Failed to reload server",failedToGetServerSettings:"Failed to get server settings",failedToGetServerConfig:"Failed to get server configuration",failedToSaveSettings:"Failed to save settings",toolNameRequired:"Server name and tool name are required",descriptionMustBeString:"Description must be a string",groupIdRequired:"Group ID is required",groupNameRequired:"Group name is required",groupNotFound:"Group not found",groupIdAndServerNameRequired:"Group ID and server name are required",groupOrServerNotFound:"Group or server not found",toolsMustBeAllOrArray:'Tools must be "all" or an array of strings',serverNameAndToolNameRequired:"Server name and tool name are required",usernameRequired:"Username is required",userNotFound:"User not found",failedToGetUsers:"Failed to get users information",failedToGetUserInfo:"Failed to get user information",failedToGetUserStats:"Failed to get user statistics",marketServerNameRequired:"Server name is required",marketServerNotFound:"Market server not found",failedToGetMarketServers:"Failed to get market servers information",failedToGetMarketServer:"Failed to get market server information",failedToGetMarketCategories:"Failed to get market categories",failedToGetMarketTags:"Failed to get market tags",failedToSearchMarketServers:"Failed to search market servers",failedToFilterMarketServers:"Failed to filter market servers",failedToProcessMcpbFile:"Failed to process MCPB file"},success:{serverCreated:"Server created successfully",serverUpdated:"Server updated successfully",serverRemoved:"Server removed successfully",serverToggled:"Server status toggled successfully",toolToggled:"Tool {{name}} {{action}} successfully",toolDescriptionUpdated:"Tool {{name}} description updated successfully",systemConfigUpdated:"System configuration updated successfully",groupCreated:"Group created successfully",groupUpdated:"Group updated successfully",groupDeleted:"Group deleted successfully",serverAddedToGroup:"Server added to group successfully",serverRemovedFromGroup:"Server removed from group successfully",serverToolsUpdated:"Server tools updated successfully"}},Co={authorizationFailed:"Authorization Failed",authorizationFailedError:"Error",authorizationFailedDetails:"Details",invalidRequest:"Invalid Request",missingStateParameter:"Missing required OAuth state parameter.",missingCodeParameter:"Missing required authorization code parameter.",serverNotFound:"Server Not Found",serverNotFoundMessage:"Could not find server associated with this authorization request.",sessionExpiredMessage:"The authorization session may have expired. Please try authorizing again.",authorizationSuccessful:"Authorization Successful",server:"Server",status:"Status",connected:"Connected",successMessage:"The server has been successfully authorized and connected.",autoCloseMessage:"This window will close automatically in 3 seconds...",closeNow:"Close Now",connectionError:"Connection Error",connectionErrorMessage:"Authorization was successful, but failed to connect to the server.",reconnectMessage:"Please try reconnecting from the dashboard.",configurationError:"Configuration Error",configurationErrorMessage:"Server transport does not support OAuth finishAuth(). Please ensure the server is configured with streamable-http transport.",internalError:"Internal Error",internalErrorMessage:"An unexpected error occurred while processing the OAuth callback.",closeWindow:"Close Window"},Po={add:"Add Prompt",addNew:"Add New Prompt",edit:"Edit Prompt",delete:"Delete",noPrompts:"No built-in prompts configured",addFirst:"Add your first prompt",name:"Name",namePlaceholder:"e.g. code-review",title:"Title",titlePlaceholder:"e.g. Code Review Prompt",description:"Description",descriptionPlaceholder:"Brief description of the prompt",template:"Template",templatePlaceholder:"Enter template text with {{parameter}} placeholders...",templateHint:"Use {{paramName}} for template parameters",arguments:"Arguments",addArgument:"Add Argument",argName:"Name",argDescription:"Description",argRequired:"Required",enabled:"Enabled",active:"Active",inactive:"Inactive",nameRequired:"Name is required",templateRequired:"Template is required",fetchError:"Failed to load built-in prompts",createError:"Failed to create prompt",updateError:"Failed to update prompt",deleteError:"Failed to delete prompt",saveError:"Failed to save prompt",confirmDelete:"Delete Prompt",deleteWarning:'Are you sure you want to delete the prompt "{{name}}"? This action cannot be undone.'},Ao={add:"Add Resource",addNew:"Add New Resource",edit:"Edit Resource",delete:"Delete",noResources:"No built-in resources configured",addFirst:"Add your first resource",uri:"URI",uriPlaceholder:"e.g. resource://docs/guide",name:"Name",namePlaceholder:"e.g. User Guide",description:"Description",descriptionPlaceholder:"Brief description of the resource",mimeType:"MIME Type",content:"Content",contentPlaceholder:"Enter the resource content...",enabled:"Enabled",active:"Active",inactive:"Inactive",descriptionUpdateSuccess:"Resource description updated successfully",descriptionUpdateFailed:"Failed to update resource description",restoreDefault:"Restore default",restoreDefaultSuccess:"Resource description restored to default",restoreDefaultFailed:"Failed to restore the default resource description",uriRequired:"URI is required",contentRequired:"Content is required",fetchError:"Failed to load built-in resources",createError:"Failed to create resource",updateError:"Failed to update resource",deleteError:"Failed to delete resource",saveError:"Failed to save resource",confirmDelete:"Delete Resource",deleteWarning:'Are you sure you want to delete the resource "{{name}}"? This action cannot be undone.'},Ro={title:"Activity",totalCalls:"Total Calls",successCount:"Successful",errorCount:"Failed",avgDuration:"Avg Duration",timestamp:"Timestamp",server:"Server",tool:"Tool",duration:"Duration",status:"Status",group:"Group",user:"User",key:"API Key",sourceIp:"Source IP",input:"Input",output:"Output",details:"Activity Details",errorMessage:"Error Message",searchServer:"Server...",searchTool:"Tool...",searchStatus:"Status...",searchGroup:"Group...",searchUsername:"User...",searchKeyName:"API key...",keyName:"API Key Name",allStatus:"All Status",statusSuccess:"Success",statusError:"Error",noData:"No activity data available",fetchError:"Failed to load activity data",cleanup:"Cleanup",confirmCleanup:"Are you sure you want to delete activities older than 30 days?",cleanupSuccess:"Deleted {{count}} old activities",cleanupError:"Failed to cleanup old activities",notAvailable:"Activity tracking is only available in database mode"},To={exportButton:"Export Template",importButton:"Import Template",exportTitle:"Export Configuration Template",importTitle:"Import Configuration Template",name:"Template Name",nameRequired:"Template name is required",namePlaceholder:"e.g., Frontend Dev Tools",description:"Description",descriptionPlaceholder:"e.g., Standard MCP servers for frontend development",selectGroups:"Select Groups",selectGroupsHelp:"Leave empty to export all groups",selectAll:"Select All",deselectAll:"Deselect All",includeDisabled:"Include disabled servers",exportNote:"Secrets (API keys, tokens, passwords) will be replaced with ${PLACEHOLDER} references. Recipients must supply their own credentials.",export:"Export",exporting:"Exporting...",exportFailed:"Failed to export template",import:"Import",importing:"Importing...",importFailed:"Failed to import template",invalidFormat:"Invalid template format. Must contain version, name, servers, and groups fields.",parseError:"Failed to parse JSON. Please check the format and try again.",uploadFile:"Upload Template File",or:"or",pasteJson:"Paste Template JSON",pastePlaceholder:"Paste your .mcphub-template.json content here...",version:"Version",createdAt:"Created",servers:"Servers",groups:"Groups",serversInGroup:"server(s)",envVarsNeeded:"Required Environment Variables — set these before using the imported servers:",importResult:"Servers: {{serversCreated}} created, {{serversSkipped}} skipped. Groups: {{groupsCreated}} created, {{groupsSkipped}} skipped."},xo={exposed:"Exposed",gross:"Gross",estimate:"Estimated tokens (cl100k) — approximate",direct:"Direct",smartRouting:"Smart routing",smartRoutingPd:"Smart routing + progressive disclosure",smartRoutingPdHint:"Adds the describe_tool meta-tool — higher upfront cost, but smaller per-search responses",saved:"{{percent}}% less",notConnected:"Not connected",connectedOf:"{{connected}} of {{total}} servers connected",totalFootprint:"Context footprint"},wo={title:"Credentials",missing:"Personal credentials required for '{{serverName}}'. Bind all required slots in Dashboard → Credentials.",description:"Bind your own credentials to shared servers. Each server uses the credentials of the user making the request.",slots:"Per-user credential slots",slotsHint:"Declare field names only. Every slot requires a personal binding; organization credentials are never used as a fallback.",target:"Credential target",urlHint:"For URL slots, place {{placeholder}} as a complete host label or path segment and list allowed values below.",allowed:"Allowed values (one per line)",argsHint:"For argument slots, use {{placeholder}} in an argument, replacing API_KEY with the field name. Values are inserted literally without a shell.",fieldName:"Field name",label:"Label (optional)",addSlot:"Add slot",removeSlot:"Remove slot",personalBadge:"Personal credentials",manage:"Manage",configured:"Configured",required:"Binding required",writeOnly:"Saved values cannot be displayed. To replace a binding, enter new values for every slot.",replaceValue:"Enter replacement value",enterValue:"Enter credential",save:"Save binding",delete:"Delete binding",saved:"Binding saved",deleted:"Binding deleted",failed:"Unable to manage credentials",showAll:"Show all servers",loading:"Loading…",empty:"No shared servers require personal credentials.",targetUser:"Manage credentials for",myCredentials:"My credentials",updatedAt:"Last updated"},Do={app:_i,about:Vi,profile:$i,sponsor:Ji,wechat:Wi,discord:Yi,theme:Xi,auth:Qi,server:Zi,status:eo,errors:ro,common:to,clientConfig:ao,pagination:no,nav:io,pages:oo,logs:so,groups:lo,market:co,oauthServer:uo,cloud:mo,registry:po,tool:ho,prompt:go,settings:bo,mcpb:vo,jsonImport:yo,groupImport:fo,users:ko,api:So,oauthCallback:Co,builtinPrompts:Po,builtinResources:Ao,activity:Ro,template:To,cost:xo,credentials:wo},Eo={title:"Bảng điều khiển MCPHub",error:"Lỗi",closeButton:"Đóng",noServers:"Không có máy chủ MCP nào",loading:"Đang tải...",logout:"Đăng xuất",profile:"Hồ sơ",changePassword:"Đổi mật khẩu",toggleSidebar:"Bật/tắt thanh bên",welcomeUser:"Chào mừng, {{username}}",name:"MCPHub",embeddingSyncProgress:"Đang đồng bộ embedding cho {{serverName}}",embeddingSyncProgressAriaLabel:"Đang tạo embedding cho {{serverName}}: Đã hoàn thành {{current}} trên {{total}}"},Io={title:"Giới thiệu",versionInfo:"Phiên bản MCPHub: {{version}}",newVersion:"Đã có phiên bản mới!",currentVersion:"Phiên bản hiện tại",newVersionAvailable:"Đã có phiên bản mới {{version}}",viewOnGitHub:"Xem trên GitHub",checkForUpdates:"Kiểm tra bản cập nhật",checking:"Đang kiểm tra bản cập nhật...",viewChangelog:"Xem nhật ký thay đổi",viewReleaseNotes:"Xem ghi chú phát hành",viewAllChanges:"Xem tất cả thay đổi",latestChanges:"Những thay đổi mới nhất",upToDate:"Bạn đang sử dụng phiên bản mới nhất.",releaseNotesUnavailable:"Đã có phiên bản mới hơn, nhưng chưa có ghi chú phát hành chi tiết.",updateChecksDisabled:"Tính năng kiểm tra cập nhật bị vô hiệu hóa cho bản triển khai này.",dismissUpdate:"Bỏ qua",dismissed:"Đã bỏ qua",earlierReleases:"+ {{count}} bản phát hành trước đó"},No={viewProfile:"Xem hồ sơ",userCenter:"Trung tâm người dùng"},Oo={label:"Tài trợ",title:"Ủng hộ dự án",rewardAlt:"Mã QR ủng hộ",supportMessage:"Hỗ trợ quá trình phát triển MCPHub bằng cách mời tôi một ly cà phê!",supportButton:"Ủng hộ trên Ko-fi"},Mo={label:"WeChat",title:"Kết nối qua WeChat",qrCodeAlt:"Mã QR WeChat",scanMessage:"Quét mã QR này để kết nối với chúng tôi trên WeChat"},Lo={label:"Discord",title:"Tham gia máy chủ Discord của chúng tôi",community:"Tham gia cộng đồng ngày càng lớn mạnh trên Discord để được hỗ trợ, thảo luận và nhận thông tin cập nhật!"},zo={title:"Giao diện",light:"Sáng",dark:"Tối",system:"Hệ thống"},Uo={createAccount:"Tạo tài khoản",backToLogin:"Quay lại trang đăng nhập",userAlreadyExists:"Tên người dùng đã tồn tại",login:"Đăng nhập",loginTitle:"Đăng nhập vào MCPHub",slogan:"Cổng kết nối MCP nguồn mở, tự lưu trữ và bảng điều khiển",subtitle:"Kết nối, tổ chức, kiểm soát và vận hành các máy chủ Model Context Protocol thông qua các endpoint thống nhất.",username:"Tên người dùng",password:"Mật khẩu",loggingIn:"Đang đăng nhập...",orContinue:"Hoặc tiếp tục với",loginWithGoogle:"Tiếp tục với Google",loginWithGithub:"Tiếp tục với GitHub",loginWithOIDC:"Tiếp tục với OIDC",socialLoginFailed:"Đăng nhập qua mạng xã hội thất bại. Vui lòng thử lại.","error.account_not_linked":"Tài khoản chưa được liên kết. Email của bạn có thể chưa được xác minh bởi nhà cung cấp danh tính. Vui lòng xác minh email và thử lại.","error.email_doesn't_match":"Email từ nhà cung cấp danh tính không khớp với tài khoản hiện tại của bạn.","error.email_not_found":"Nhà cung cấp danh tính không trả về email nào.","error.access_denied":"Truy cập bị từ chối bởi nhà cung cấp danh tính.","error.account_already_linked_to_different_user":"Tài khoản này đã được liên kết với một người dùng khác.","error.unable_to_link_account":"Không thể liên kết tài khoản. Vui lòng thử lại.","error.signup_disabled":"Tính năng đăng ký hiện đang bị vô hiệu hóa.","error.oauth_provider_not_found":"Không tìm thấy nhà cung cấp OAuth.","error.invalid_code":"Mã xác thực không hợp lệ. Vui lòng thử lại.","error.unable_to_get_user_info":"Không thể lấy thông tin người dùng từ nhà cung cấp danh tính.",emptyFields:"Tên người dùng và mật khẩu không được để trống",loginFailed:"Đăng nhập thất bại, vui lòng kiểm tra tên người dùng và mật khẩu",loginError:"Đã xảy ra lỗi trong quá trình đăng nhập",serverUnavailable:"Không thể kết nối đến máy chủ. Vui lòng kiểm tra kết nối mạng hoặc thử lại sau",currentPassword:"Mật khẩu hiện tại",newPassword:"Mật khẩu mới",confirmPassword:"Xác nhận mật khẩu",passwordsNotMatch:"Mật khẩu mới và xác nhận không khớp",changePasswordSuccess:"Đổi mật khẩu thành công",changePasswordError:"Đổi mật khẩu thất bại",changePassword:"Đổi mật khẩu",passwordChanged:"Đổi mật khẩu thành công",passwordChangeError:"Đổi mật khẩu thất bại",defaultPasswordWarning:"Cảnh báo bảo mật mật khẩu mặc định",defaultPasswordMessage:"Bạn đang sử dụng mật khẩu mặc định (admin123), điều này tiềm ẩn rủi ro bảo mật. Vui lòng đổi mật khẩu ngay để bảo vệ tài khoản.",goToSettings:"Đi đến Cài đặt",passwordStrengthError:"Mật khẩu không đáp ứng yêu cầu bảo mật",passwordMinLength:"Mật khẩu phải dài ít nhất 8 ký tự",passwordRequireLetter:"Mật khẩu phải chứa ít nhất một chữ cái",passwordRequireNumber:"Mật khẩu phải chứa ít nhất một chữ số",passwordRequireSpecial:"Mật khẩu phải chứa ít nhất một ký tự đặc biệt",passwordStrengthHint:"Mật khẩu phải dài ít nhất 8 ký tự và chứa chữ cái, chữ số, và ký tự đặc biệt"},qo=JSON.parse(`{"protocolVersion":"Giao thức MCP","protocolVersionUnknown":"Chưa có","localExecutionRequiresAdmin":"Thực thi lệnh cục bộ yêu cầu quyền quản trị viên.","httpOAuthRequiresAdmin":"Cho phép các endpoint token HTTP OAuth yêu cầu quyền quản trị viên.","startOnDemand":"Khởi động theo yêu cầu","startOnDemandDescription":"Bỏ qua kết nối lúc khởi động và chỉ bật máy chủ này khi có yêu cầu gọi công cụ. Tiến trình sẽ tự động tắt sau thời gian chờ không hoạt động, và khởi động lại vào lần gọi tiếp theo. Giúp giảm sử dụng bộ nhớ cho các máy chủ ít dùng.","idleTimeoutMs":"Thời gian chờ tắt khi không hoạt động (ms)","idleTimeoutMsDescription":"Tắt tiến trình sau số mili-giây này nếu không có yêu cầu gọi công cụ nào. Mặc định: 300000 (5 phút).","addServer":"Thêm máy chủ","add":"Thêm","edit":"Sửa","copy":"Sao chép","duplicate":"Nhân bản","delete":"Xóa","confirmDelete":"Bạn có chắc chắn muốn xóa máy chủ này không?","deleteWarning":"Xóa máy chủ '{{name}}' sẽ gỡ bỏ nó và toàn bộ dữ liệu liên quan. Hành động này không thể hoàn tác.","status":"Trạng thái","tools":"Công cụ","prompts":"Lời nhắc","name":"Tên máy chủ","nameInvalid":"Tên máy chủ chỉ có thể chứa chữ cái, số, dấu chấm, dấu gạch dưới và dấu gạch ngang (không chứa khoảng trắng hoặc ký tự đặc biệt)","description":"Ghi chú máy chủ","descriptionPlaceholder":"Ghi chú tùy chọn để mô tả máy chủ này","url":"URL máy chủ","apiKey":"Khóa API","save":"Lưu","cancel":"Hủy","invalidConfig":"Không tìm thấy dữ liệu cấu hình cho {{serverName}}","addError":"Thêm máy chủ thất bại","editError":"Sửa máy chủ {{serverName}} thất bại","deleteError":"Xóa máy chủ {{serverName}} thất bại","updateError":"Cập nhật máy chủ thất bại","editTitle":"Sửa máy chủ: {{serverName}}","duplicateTitle":"Nhân bản máy chủ: {{serverName}}","type":"Loại máy chủ","typeStdio":"STDIO","typeSse":"SSE","typeStreamableHttp":"Streamable HTTP","typeOpenapi":"OpenAPI","mcpApp":"Ứng dụng MCP — máy chủ này cung cấp tài nguyên UI tương tác","visibility":"Hiển thị","visibilityPrivateShort":"Riêng tư","visibilityPrivate":"Riêng tư — chỉ chủ sở hữu và quản trị viên","visibilityGroupShort":"Chia sẻ","visibilityGroup":"Chia sẻ — chỉ người dùng được chọn","visibilityPublicShort":"Công khai","visibilityPublic":"Công khai — mọi người dùng đã xác thực","visibilityDescription":"Kiểm soát những người dùng (không phải quản trị viên) có thể khám phá và gọi máy chủ này. Quản trị viên luôn có quyền truy cập.","shareWithUsers":"Chia sẻ với người dùng","shareWithUsersDescription":"Người dùng được chọn có thể khám phá và gọi máy chủ này, nhưng không thể quản lý cấu hình của nó.","shareCandidatesLoading":"Đang tải người dùng...","shareCandidatesError":"Tải người dùng thất bại.","shareAfterCreate":"Lưu máy chủ trước khi chọn người dùng.","noShareCandidates":"Không có người dùng nào khác.","shareUserSearchLabel":"Tìm kiếm người dùng","shareUserSearchPlaceholder":"Tìm kiếm tên người dùng...","selectAllShareUsers":"Chọn tất cả","deselectAllShareUsers":"Bỏ chọn tất cả","noMatchingShareUsers":"Không có người dùng nào khớp với tìm kiếm của bạn.","command":"Lệnh","packageVersion":"Phiên bản gói đã cài (cài đặt lần cuối bởi bộ nhớ đệm runner)","reportedVersion":"Phiên bản từ máy chủ","updateAvailable":"Đã có phiên bản mới hơn trên registry","arguments":"Đối số","addArgument":"Thêm đối số","argumentsHint":"Mỗi trường là một đối số. Khoảng trắng và dấu ngoặc kép được giữ nguyên; trường trống sẽ truyền một đối số rỗng.","argumentLabel":"Đối số {{index}}","removeArgument":"Xóa đối số {{index}}","envVars":"Biến môi trường","headers":"Tiêu đề HTTP (Headers)","key":"khóa","value":"giá trị","enabled":"Đã bật","enable":"Bật","disable":"Tắt","reload":"Tải lại","reloadSuccess":"Tải lại máy chủ thành công","reloadError":"Tải lại máy chủ {{serverName}} thất bại","reinstall":"Cài đặt lại","reinstallConfirm":"Hành động này sẽ xóa bộ nhớ đệm gói và tải lại các phần phụ thuộc. Máy chủ sẽ khởi động lại.","reinstallSuccess":"Đã bắt đầu cài đặt lại máy chủ","reinstallError":"Cài đặt lại máy chủ {{serverName}} thất bại","disconnectOAuth":"Ngắt kết nối OAuth","disconnectOAuthConfirm":"Hành động này sẽ thu hồi các thông tin xác thực OAuth đã lưu nếu được hỗ trợ và yêu cầu cấp quyền lại.","disconnectOAuthSuccess":"Đã ngắt kết nối OAuth của máy chủ","disconnectOAuthError":"Ngắt kết nối OAuth cho máy chủ {{serverName}} thất bại","requestOptions":"Cấu hình kết nối","maxBufferSize":"Giới hạn bộ đệm Stdio (bytes)","maxBufferSizeDescription":"Kích thước tối đa của bộ đệm đọc stdio. Để trống để dùng mặc định của SDK (10 MiB). Giới hạn lớn hơn cho phép sử dụng nhiều bộ nhớ hơn.","timeout":"Thời gian chờ yêu cầu (Timeout)","timeoutDescription":"Thời gian chờ cho các yêu cầu gửi đến máy chủ MCP (ms)","maxTotalTimeout":"Thời gian chờ tổng tối đa","maxTotalTimeoutDescription":"Thời gian chờ tổng tối đa cho các yêu cầu gửi đến máy chủ MCP (ms) (Dùng với thông báo tiến trình)","resetTimeoutOnProgress":"Đặt lại Timeout khi có tiến trình","resetTimeoutOnProgressDescription":"Đặt lại thời gian chờ mỗi khi có thông báo tiến trình (mặc định được bật)","keepAlive":"Sức khỏe kết nối","retryScheduled":"Thử lại lúc {{time}}","reconnecting":"Đang kết nối lại…","lastRetry":"Lần thử gần nhất: {{time}} ({{count}} lần)","enableKeepAlive":"Bật kiểm tra sức khỏe","keepAliveDescription":"Kiểm tra kết nối định kỳ. Máy chủ từ xa bị ngắt luôn tự động kết nối lại với thời gian chờ tăng dần.","keepAliveInterval":"Chu kỳ kiểm tra (ms)","keepAliveIntervalDescription":"Thời gian giữa các lần kiểm tra tính bằng mili-giây (mặc định: 60000ms = 1 phút)","perSessionClient":"Cách ly Client theo phiên","perSessionClientDescription":"Tạo một kết nối upstream riêng biệt cho mỗi phiên thay vì dùng chung một kết nối cho tất cả các phiên. Bật cho các máy chủ lưu trạng thái như Playwright. Sẽ làm tăng số lượng kết nối upstream khi có nhiều phiên đồng thời.","remove":"Gỡ bỏ","toggleError":"Bật/tắt máy chủ {{serverName}} thất bại","alreadyExists":"Máy chủ {{serverName}} đã tồn tại","invalidData":"Dữ liệu máy chủ cung cấp không hợp lệ","notFound":"Không tìm thấy máy chủ {{serverName}}","namePlaceholder":"Nhập tên máy chủ","urlPlaceholder":"Nhập URL máy chủ","commandPlaceholder":"Nhập lệnh","argumentsPlaceholder":"Nhập đối số","errorDetails":"Chi tiết lỗi","viewErrorDetails":"Xem chi tiết lỗi","copyConfig":"Sao chép cấu hình","confirmVariables":"Xác nhận cấu hình Biến","variablesDetected":"Phát hiện biến trong cấu hình. Vui lòng xác nhận các biến này đã được cấu hình đúng:","detectedVariables":"Các biến được phát hiện","confirmVariablesMessage":"Vui lòng đảm bảo các biến này được định nghĩa chính xác trong môi trường chạy của bạn. Tiếp tục thêm máy chủ?","confirmAndAdd":"Xác nhận và Thêm","openapi":{"inputMode":"Chế độ đầu vào","inputModeUrl":"URL Thông số kỹ thuật (Specification URL)","inputModeSchema":"Lược đồ JSON (JSON Schema)","specUrl":"URL Thông số OpenAPI","schema":"Lược đồ OpenAPI JSON","schemaHelp":"Dán toàn bộ lược đồ OpenAPI JSON của bạn vào đây","security":"Loại bảo mật","securityNone":"Không có","securityApiKey":"Khóa API (API Key)","securityHttp":"Xác thực HTTP","securityOAuth2":"OAuth 2.0","securityOpenIdConnect":"OpenID Connect","securityDetect":"Phát hiện từ thông số (spec)","securityDetecting":"Đang phát hiện…","securityNotDeclared":"Thông số này không khai báo scheme bảo mật nào.","securityPrefillNotice":"Thông số này khai báo {{summary}}. Cài đặt bảo mật đã được điền sẵn — hãy thêm giá trị xác thực của bạn trước lần gọi đầu tiên.","securityMismatchWarning":"Thông số khai báo {{summary}}, nhưng máy chủ này được cấu hình là {{configured}}. Điều này có thể gây ra lỗi 401 ngầm.","securityUnsupportedNotice":"Thông số này khai báo {{summary}}, mà MCPHub không thể biểu diễn ({{reason}}). Vui lòng cấu hình xác thực thủ công.","apiKeyConfig":"Cấu hình khóa API","apiKeyName":"Tên Tiêu đề/Tham số (Header/Parameter Name)","apiKeyIn":"Vị trí","apiKeyValue":"Giá trị Khóa API","httpAuthConfig":"Cấu hình Xác thực HTTP","httpScheme":"Kiểu xác thực (Scheme)","httpCredentials":"Thông tin xác thực","httpCredentialsBasicHint":"Nhập user:password (được mã hóa tự động) hoặc chuỗi Base64 đã mã hóa sẵn.","specSecurityToggle":"URL thông số yêu cầu xác thực riêng biệt","specSecurityHelp":"Chỉ bật khi bản thân tài liệu spec được bảo vệ khác với API (ví dụ: /v3/api-docs được bảo vệ bằng Basic Auth nhưng API thì dùng Bearer). Khi tắt, cấu hình bảo mật ở trên sẽ dùng cho cả hai.","httpSchemeBasic":"Basic","httpSchemeBearer":"Bearer","httpSchemeDigest":"Digest","oauth2Config":"Cấu hình OAuth 2.0","oauth2Token":"Access Token","openIdConnectConfig":"Cấu hình OpenID Connect","openIdConnectUrl":"URL Khám phá (Discovery URL)","openIdConnectToken":"ID Token","apiKeyInHeader":"Header","apiKeyInQuery":"Query","apiKeyInCookie":"Cookie","passthroughHeaders":"Tiêu đề chuyển tiếp (Passthrough Headers)","passthroughHeadersHelp":"Danh sách các tên tiêu đề phân tách bằng dấu phẩy để chuyển tiếp từ yêu cầu MCP đến các yêu cầu máy chủ upstream (ví dụ: Authorization, X-API-Key)","cookieSession":"Xử lý phiên Cookie","cookieSessionHelp":"Bắt Set-Cookie từ phản hồi đăng nhập upstream và phát lại chúng trong các lệnh gọi sau thuộc cùng phiên downstream. Được cách ly theo phiên MCP; không lưu trữ bền vững.","statsMeasuring":"Đang đo lường danh sách công cụ được tạo…","statsSummary":"{{toolCount}} công cụ · ~{{bytes}} định nghĩa · ~{{tokens}} token","statsWarning":"Danh sách công cụ này có thể chạm mức hoặc vượt quá cửa sổ ngữ cảnh thông thường của mô hình. Hãy cân nhắc cung cấp ít công cụ hơn — tạo nhóm hoặc tắt bớt các công cụ lẻ trên máy chủ.","statsUnavailable":"Không thể đo lường thông số kỹ thuật. Bạn vẫn có thể tiếp tục; máy chủ sẽ xác thực quá trình nhập khi bạn gửi đi."},"oauth":{"sectionTitle":"Cấu hình OAuth","sectionDescription":"Cấu hình thông tin client cho các máy chủ được bảo vệ bằng OAuth (tùy chọn).","allowInsecureTokenEndpoint":"Cho phép các endpoint token HTTP OAuth","allowInsecureTokenEndpointHelp":"Chỉ dành cho quản trị viên. Bị tắt theo mặc định. Gửi thông tin xác thực và token mà không qua TLS cho upstream này. Chỉ bật trên mạng đáng tin cậy; khuyến cáo dùng HTTPS. Khi đã bật, chỉ quản trị viên mới có thể sửa đổi toàn bộ cấu hình máy chủ này; chủ sở hữu không phải admin không thể sửa nó.","clientId":"Client ID","clientSecret":"Client Secret","authorizationEndpoint":"Endpoint Ủy quyền (Authorization Endpoint)","tokenEndpoint":"Endpoint Token","scopes":"Phạm vi (Scopes)","scopesPlaceholder":"scope1 scope2","resource":"Tài nguyên / Khán giả (Resource / Audience)","accessToken":"Access Token","refreshToken":"Refresh Token","identityMode":"Danh tính OAuth","sharedIdentity":"Tài khoản dùng chung","personalIdentity":"Mỗi người dùng ủy quyền độc lập","personalIdentityHelp":"Chế độ cá nhân yêu cầu ủy quyền trên bảng điều khiển cho từng người dùng. Các khóa liên kết người dùng sử dụng chủ sở hữu của chúng; các khóa dịch vụ/dùng chung không hợp lệ.","personalConnect":"Kết nối","personalReconnect":"Kết nối lại","personalDisconnect":"Ngắt kết nối","personalError":"Ủy quyền cá nhân thất bại","personalSuccess":"Đã lưu ủy quyền cá nhân. Quay lại Bảng điều khiển → Máy chủ."}}`),Bo={sleeping:"Đang ngủ",sleepingDescription:"Máy chủ theo yêu cầu - sẽ tự động khởi động khi có lệnh gọi công cụ",online:"Trực tuyến",offline:"Ngoại tuyến",connecting:"Đang kết nối",oauthRequired:"Yêu cầu OAuth",clickToAuthorize:"Nhấp để ủy quyền qua OAuth",oauthWindowOpened:"Cửa sổ ủy quyền OAuth đã mở. Vui lòng hoàn thành ủy quyền.",oauthClientIdHint:'Máy chủ này có một ID ứng dụng khách OAuth được cấu hình sẵn. Nếu ủy quyền thất bại với lỗi "invalid redirect_uri", hãy xóa clientId để MCPHub có thể tự động đăng ký máy khách OAuth riêng.'},Fo={general:"Đã xảy ra lỗi",network:"Lỗi kết nối mạng. Vui lòng kiểm tra đường truyền Internet của bạn",serverConnection:"Không thể kết nối với máy chủ. Vui lòng kiểm tra xem máy chủ có đang chạy không",serverAdd:"Thêm máy chủ thất bại. Vui lòng kiểm tra trạng thái máy chủ",serverUpdate:"Sửa máy chủ {{serverName}} thất bại. Vui lòng kiểm tra trạng thái máy chủ",serverFetch:"Lấy dữ liệu máy chủ thất bại. Vui lòng thử lại sau",initialStartup:"Máy chủ có thể đang khởi động. Vui lòng đợi một chút vì quá trình này có thể mất thời gian trong lần chạy đầu tiên...",serverInstall:"Cài đặt máy chủ thất bại",failedToFetchSettings:"Lấy cài đặt thất bại",failedToUpdateRouteConfig:"Cập nhật cấu hình định tuyến thất bại",failedToUpdateSmartRoutingConfig:"Cập nhật cấu hình định tuyến thông minh thất bại",failedToUpdateBetterAuthConfig:"Cập nhật cấu hình Better Auth thất bại"},Ko={processing:"Đang xử lý...",save:"Lưu",cancel:"Hủy",back:"Quay lại",refresh:"Làm mới",search:"Tìm kiếm",clear:"Xóa",view:"Xem",create:"Tạo",creating:"Đang tạo...",update:"Cập nhật",updating:"Đang cập nhật...",submitting:"Đang gửi...",delete:"Xóa",remove:"Gỡ bỏ",copy:"Sao chép",copyId:"Sao chép ID",copyUrl:"Sao chép URL",copyOpenApiUrl:"Sao chép OpenAPI URL",copySuccess:"Đã sao chép vào khay nhớ tạm",copyFailed:"Sao chép thất bại",copied:"Đã sao chép",close:"Đóng",confirm:"Xác nhận",language:"Ngôn ngữ",true:"Đúng (True)",false:"Sai (False)",dismiss:"Bỏ qua",github:"GitHub",wechat:"WeChat",discord:"Discord",required:"Bắt buộc",itemsPerPage:"Mục mỗi trang",showing:"Đang hiển thị {{start}}-{{end}} trong tổng số {{total}}",previous:"Trước",next:"Tiếp",secret:"Bí mật (Secret)",default:"Mặc định",value:"Giá trị",type:"Loại",repeated:"Lặp lại",valueHint:"Gợi ý giá trị",choices:"Tùy chọn",actions:"Hành động",saving:"Đang lưu...",active:"Hoạt động",inactive:"Không hoạt động",viewAll:"Xem tất cả",docs:"Tài liệu",all:"Tất cả"},jo={title:"Sao chép cấu hình MCP",description:"Chọn client của bạn để sao chép cấu hình sẵn sàng dán cho {{name}}.",menuItem:"Sao chép cấu hình MCP",tokenPrompt:"Token truy cập MCPHub",configBlock:"Cấu hình",commandBlock:"Lệnh CLI",copied:"Đã sao chép",noTransport:"Máy chủ này không có transport MCP phía client (nó dựa trên OpenAPI). Vui lòng sử dụng hub hoặc endpoint của nhóm.",clients:{"generic-mcp-servers":{label:"Chung (mcpServers)",hint:"Khối mcpServers được chấp nhận rộng rãi: Claude Desktop, Cline, Cherry Studio và hầu hết các client khác."},"generic-http":{label:"HTTP Chung",hint:'Cửa thoát với entry thô: các endpoint từ xa cung cấp một entry HTTP thô (các upstream SSE mang dấu "type": "sse"), máy chủ cục bộ có entry stdio thô (command/args/env). Dán nó vào bản đồ máy chủ của riêng client; đối với hầu hết client, hãy dùng Chung (mcpServers).'},"claude-code":{label:"Claude Code",hint:"Claude Code: `claude mcp add`, hoặc khối mcpServers trong ~/.claude.json."},cursor:{label:"Cursor",hint:"Cursor: .cursor/mcp.json trong thư mục dự án, hoặc ~/.cursor/mcp.json trên toàn hệ thống."},vscode:{label:"VS Code / Copilot",hint:"VS Code / Copilot: .vscode/mcp.json trong workspace, hoặc mcp.json trong hồ sơ người dùng của bạn."},codex:{label:"Codex",hint:"Codex: ~/.codex/config.toml, hoặc .codex/config.toml ở cấp độ dự án."},opencode:{label:"OpenCode",hint:"OpenCode: ~/.config/opencode/opencode.json toàn hệ thống, hoặc opencode.json trong dự án."},windsurf:{label:"Windsurf",hint:"Windsurf: Đường dẫn tệp cấu hình tại ~/.codeium/windsurf/mcp_config.json."},"cherry-studio":{label:"Cherry Studio",hint:"Cherry Studio: Vào Cài đặt (Settings) > Máy chủ MCP (MCP Servers) > Thêm máy chủ (Add Server) > Nhập JSON (Import JSON)."},codebuddy:{label:"CodeBuddy Code",hint:"CodeBuddy Code: ~/.codebuddy/.mcp.json Toàn hệ thống, hoặc .mcp.json trong dự án."},qoder:{label:"Qoder",hint:"Qoder: Settings > MCP > Thêm thủ công, rồi dán chuỗi JSON."},trae:{label:"TRAE",hint:"TRAE: Settings > MCP > Add > Thêm thủ công, rồi dán chuỗi JSON vào."},zcode:{label:"ZCode",hint:"ZCode: Vào Cài đặt (Settings) > Máy chủ MCP (MCP Servers) > Máy chủ MCP mới (New MCP Server) > Cấu hình đầy đủ (Full configuration)."},workbuddy:{label:"WorkBuddy",hint:"WorkBuddy: Plugins > MCP Servers > Configure MCP, hoặc ~/.workbuddy/mcp.json."}}},Go={rowsPerPage:"Số hàng mỗi trang",showing:"Đang hiển thị {{from}}-{{to}} trong tổng số {{total}}"},Ho={dashboard:"Bảng điều khiển",servers:"Máy chủ",groups:"Nhóm",prompts:"Lời nhắc",resources:"Tài nguyên",users:"Người dùng",settings:"Cài đặt",changePassword:"Đổi mật khẩu",market:"Chợ ứng dụng",cloud:"Chợ đám mây (Cloud Market)",logs:"Nhật ký (Logs)",activity:"Hoạt động",workspace:"Không gian làm việc",system:"Hệ thống"},_o={dashboard:{title:"Bảng điều khiển",totalServers:"Tổng số",onlineServers:"Trực tuyến",disabledServers:"Đã tắt",offlineServers:"Ngoại tuyến",connectingServers:"Đang kết nối",recentServers:"Máy chủ gần đây",endpoints:"Endpoints MCP",endpointsHint:"Sử dụng các URL này trong Claude Desktop, Cursor hoặc bất kỳ MCP client nào"},servers:{title:"Quản lý Máy chủ"},groups:{title:"Quản lý Nhóm"},prompts:{title:"Lời nhắc tích hợp (Built-in)"},resources:{title:"Tài nguyên tích hợp (Built-in)"},users:{title:"Quản lý Người dùng"},settings:{title:"Cài đặt",language:"Ngôn ngữ",account:"Cài đặt tài khoản",password:"Đổi mật khẩu",appearance:"Giao diện",routeConfig:"Bảo mật",installConfig:"Cài đặt",smartRouting:"Định tuyến thông minh (Smart Routing)",oauthServer:"Máy chủ OAuth"},market:{title:"Trung tâm Ứng dụng - Cục bộ và Đám mây"},logs:{title:"Nhật ký hệ thống"}},Vo={filters:"Bộ lọc",search:"Tìm kiếm nhật ký...",autoScroll:"Tự động cuộn",clearLogs:"Xóa nhật ký",loading:"Đang tải nhật ký...",noLogs:"Không có nhật ký nào.",noMatch:"Không có nhật ký nào khớp với bộ lọc hiện tại.",mainProcess:"Tiến trình chính",childProcess:"Tiến trình con",main:"Chính",child:"Con"},$o={legacyVisibility:"Cũ — chọn quyền hiển thị",legacyVisibilityHint:"Nhóm này giữ nguyên quyền truy cập endpoint trước đó cho đến khi bạn chọn hiển thị rõ ràng.",visibilityDescription:"Truy cập nhóm cũng đòi hỏi quyền truy cập vào từng máy chủ. Chia sẻ nhóm không chia sẻ các máy chủ riêng tư. Chỉ chủ sở hữu và quản trị viên mới có thể quản lý nhóm.",shareAfterCreate:"Lưu nhóm trước khi chọn người dùng.",add:"Thêm",addNew:"Thêm nhóm mới",edit:"Sửa nhóm",delete:"Xóa",confirmDelete:"Bạn có chắc chắn muốn xóa nhóm này không?",deleteWarning:"Xóa nhóm '{{name}}' sẽ gỡ bỏ nó và tất cả các liên kết máy chủ trong nhóm. Hành động này không thể hoàn tác.",name:"Tên nhóm",namePlaceholder:"Nhập tên nhóm",instructions:"Hướng dẫn (Instructions)",instructionsHelp:"Tùy chọn. Sẽ được gửi cho MCP clients khi họ kết nối đến nhóm này (cũng có trong $smart/<group>); hầu hết clients đều thêm nó vào prompt hệ thống của mô hình.",instructionsPlaceholder:"Ví dụ: Dùng lệnh fetch cho các trang web; nếu thất bại, hãy dùng firecrawl_scrape.",nameRequired:"Bắt buộc phải nhập tên nhóm",description:"Mô tả",descriptionPlaceholder:"Nhập mô tả nhóm (tùy chọn)",createError:"Tạo nhóm thất bại",updateError:"Cập nhật nhóm thất bại",deleteError:"Xóa nhóm thất bại",serverAddError:"Thêm máy chủ vào nhóm thất bại",serverRemoveError:"Xóa máy chủ khỏi nhóm thất bại",addServer:"Thêm máy chủ vào nhóm",selectServer:"Chọn một máy chủ để thêm",servers:"Các máy chủ trong nhóm",remove:"Gỡ bỏ",noGroups:"Không có nhóm nào khả dụng. Hãy tạo một nhóm mới để bắt đầu.",noServers:"Không có máy chủ nào trong nhóm này.",noServerOptions:"Không có máy chủ khả dụng",serverCount:"{{count}} Máy chủ",toolSelection:"Lựa chọn công cụ",promptSelection:"Lựa chọn lời nhắc",resourceSelection:"Lựa chọn tài nguyên",toolsSelected:"Đã chọn",promptsSelected:"Đã chọn",resourcesSelected:"Đã chọn",allTools:"Tất cả",allPrompts:"Tất cả lời nhắc",allResources:"Tất cả tài nguyên",selectedTools:"Công cụ đã chọn",selectedPrompts:"Lời nhắc đã chọn",selectedResources:"Tài nguyên đã chọn",selectAll:"Chọn tất cả",selectNone:"Bỏ chọn tất cả",configureTools:"Cấu hình công cụ",configureCapabilities:"Cấu hình Công cụ, Lời nhắc, và Tài nguyên",alias:"Tên phơi bày (Exposed Name)",preserveToolNames:"Giữ tên công cụ gốc",preserveToolNamesHint:"Hiển thị công cụ không có tiền tố máy chủ. Tên phải duy nhất trong nhóm. Tên hiển thị vẫn áp dụng cho prompt.",pinTool:"Ghim: luôn liệt kê công cụ này trên endpoint Định tuyến Thông minh của nhóm, cạnh search_tools",pinToolLabel:"Ghim vào endpoint Định tuyến Thông minh",unpinTool:"Bỏ ghim: chỉ có thể tiếp cận công cụ này thông qua search_tools",previewPrompts:"[lời nhắc: {{items}}]",previewResources:"[tài nguyên: {{items}}]",previewAllTools:"(tất cả công cụ)",previewAllPrompts:"(tất cả lời nhắc)",previewAllResources:"(tất cả tài nguyên)",bulkSearch:"Tìm theo tên hoặc mô tả…",bulkSearchLabel:"Tìm {{capability}}",annotationFilter:"Lọc theo chú thích",allAnnotations:"Tất cả chú thích",readOnlyHint:"Gợi ý chỉ đọc",destructiveHint:"Gợi ý phá hủy",idempotentHint:"Gợi ý lũy đẳng",flatList:"Danh sách phẳng",riskGroups:"Nhóm rủi ro",visibleCount:"Hiển thị {{count}} / {{total}} mục",selectVisible:"Chọn mục hiển thị",deselectVisible:"Bỏ chọn mục hiển thị",invertVisible:"Đảo chọn mục hiển thị",riskHint:"Các nhóm dựa trên gợi ý của máy chủ và suy đoán theo tên; không đảm bảo an toàn. Thao tác chỉ áp dụng cho các mục đã lọc.",noMatchingItems:"Không có mục phù hợp",risk_read:"Đọc",risk_create:"Tạo",risk_update:"Cập nhật",risk_delete:"Xóa",risk_other:"Khác / chưa phân loại"},Jo={title:"Cài đặt Cục bộ",official:"Chính thức",by:"Bởi",unknown:"Không xác định",tools:"công cụ",search:"Tìm kiếm",searchPlaceholder:"Tìm kiếm máy chủ theo tên, danh mục, hoặc thẻ",clearFilters:"Xóa",clearCategoryFilter:"",clearTagFilter:"",categories:"Danh mục",tags:"Thẻ",showTags:"Hiển thị thẻ",hideTags:"Ẩn thẻ",moreTags:"",noServers:"Không tìm thấy máy chủ nào khớp với tìm kiếm của bạn",backToList:"Quay lại danh sách",install:"Cài đặt",installing:"Đang cài đặt...",installed:"Đã cài",installServer:"Cài đặt Máy chủ: {{name}}",installSuccess:"Cài đặt máy chủ {{serverName}} thành công",author:"Tác giả",license:"Giấy phép",repository:"Kho lưu trữ (Repository)",examples:"Ví dụ",arguments:"Đối số",argumentName:"Tên",description:"Mô tả",required:"Bắt buộc",example:"Ví dụ",viewSchema:"Xem schema",fetchError:"Lỗi lấy danh sách máy chủ chợ (market)",serverNotFound:"Không tìm thấy máy chủ",searchError:"Lỗi tìm kiếm máy chủ",filterError:"Lỗi lọc máy chủ theo danh mục",tagFilterError:"Lỗi lọc máy chủ theo thẻ",noInstallationMethod:"Không có phương thức cài đặt khả dụng cho máy chủ này",showing:"Đang hiển thị {{from}}-{{to}} trong tổng số {{total}} máy chủ",perPage:"Mỗi trang",confirmVariablesMessage:"Vui lòng đảm bảo các biến này được định nghĩa đúng trong môi trường chạy. Tiếp tục cài đặt máy chủ?",confirmAndInstall:"Xác nhận và Cài đặt"},Wo={authorizeTitle:"Ủy quyền ứng dụng",authorizeSubtitle:"Cho phép ứng dụng này truy cập tài khoản MCPHub của bạn.",buttons:{approve:"Cho phép truy cập",deny:"Từ chối",approveSubtitle:"Khuyến cáo nếu bạn tin tưởng ứng dụng này.",denySubtitle:"Bạn luôn có thể cấp quyền sau."},application:"Ứng dụng",scopesTitle:"Ứng dụng này sẽ có thể:",noScopes:"Không yêu cầu quyền nào.",requestInvalidTitle:"Yêu cầu không hợp lệ",requestInvalid:"Yêu cầu ủy quyền này không hợp lệ hoặc đã hết hạn. Vui lòng quay lại và thử lại.",grantingAccessTo:"Cấp quyền truy cập cho:",resourceAll:"Tất cả máy chủ MCP",resourceSmart:"Định tuyến thông minh",resourceServer:"Máy chủ MCP: {{name}}",resourceGroup:"Nhóm MCP: {{name}}",clientId:"Client ID",willRedirectTo:"Sẽ chuyển hướng tới:",policy:"Chính sách quyền riêng tư",terms:"Điều khoản",homepage:"Trang chủ"},Yo={title:"Hỗ trợ Đám mây",subtitle:"Được cung cấp bởi MCPRouter",by:"Bởi",server:"Máy chủ",config:"Cấu hình",created:"Đã tạo",updated:"Đã cập nhật",available:"Khả dụng",description:"Mô tả",details:"Chi tiết",tools:"Công cụ",tool:"công cụ",toolsAvailable:"Có {{count}} công cụ||Có {{count}} công cụ",loadingTools:"Đang tải công cụ...",noTools:"Không có công cụ nào cho máy chủ này",noDescription:"Không có mô tả nào",viewDetails:"Xem chi tiết",parameters:"Tham số",result:"Kết quả",error:"Lỗi",callTool:"Gọi (Call)",calling:"Đang gọi...",toolCallSuccess:"Công cụ {{toolName}} chạy thành công",toolCallError:"Gọi công cụ {{toolName}} thất bại: {{error}}",viewSchema:"Xem Schema",backToList:"Quay lại Chợ Đám mây",search:"Tìm kiếm",searchPlaceholder:"Tìm kiếm máy chủ đám mây theo tên, tiêu đề hoặc tác giả",clearFilters:"Xóa bộ lọc",clearCategoryFilter:"Xóa",clearTagFilter:"Xóa",categories:"Danh mục",tags:"Thẻ",noCategories:"Không tìm thấy danh mục nào",noTags:"Không tìm thấy thẻ nào",noServers:"Không tìm thấy máy chủ đám mây nào",fetchError:"Lỗi lấy danh sách máy chủ đám mây",serverNotFound:"Không tìm thấy máy chủ đám mây",searchError:"Lỗi tìm kiếm máy chủ đám mây",filterError:"Lỗi lọc máy chủ đám mây theo danh mục",tagFilterError:"Lỗi lọc máy chủ đám mây theo thẻ",showing:"Đang hiển thị {{from}}-{{to}} trong tổng số {{total}} máy chủ đám mây",perPage:"Mỗi trang",apiKeyNotConfigured:"Chưa cấu hình Khóa API MCPRouter",apiKeyNotConfiguredDescription:"Để sử dụng các máy chủ đám mây, bạn cần cấu hình khóa API MCPRouter.",getApiKey:"Lấy Khóa API",configureInSettings:"Cấu hình trong Cài đặt",installServer:"Cài đặt {{name}}",installSuccess:"Cài đặt máy chủ {{name}} thành công",installError:"Cài đặt máy chủ thất bại: {{error}}"},Xo={title:"Kho lưu trữ (Registry)",official:"Chính thức",latest:"Mới nhất",description:"Mô tả",website:"Trang web",repository:"Kho lưu trữ (Repository)",packages:"Gói (Packages)",package:"gói",remotes:"Nguồn từ xa (Remotes)",remote:"nguồn từ xa",published:"Đã xuất bản",updated:"Đã cập nhật",install:"Cài đặt",installing:"Đang cài đặt...",installed:"Đã cài",installServer:"Cài đặt {{name}}",installSuccess:"Cài đặt máy chủ {{name}} thành công",installError:"Cài đặt máy chủ thất bại: {{error}}",noDescription:"Không có mô tả nào",viewDetails:"Xem chi tiết",backToList:"Quay lại Kho lưu trữ",search:"Tìm kiếm",searchPlaceholder:"Tìm kiếm máy chủ kho lưu trữ theo tên",clearFilters:"Xóa",noServers:"Không tìm thấy máy chủ nào trong kho lưu trữ",fetchError:"Lỗi lấy danh sách máy chủ kho lưu trữ",serverNotFound:"Không tìm thấy máy chủ kho lưu trữ",showing:"Đang hiển thị {{from}}-{{to}} trong tổng số {{total}} máy chủ kho",perPage:"Mỗi trang",environmentVariables:"Biến môi trường",packageArguments:"Đối số Gói (Package Arguments)",runtimeArguments:"Đối số Runtime",headers:"Tiêu đề (Headers)"},Qo={run:"Chạy",running:"Đang chạy...",runTool:"Chạy công cụ",cancel:"Hủy",noDescription:"Không có mô tả nào",inputSchema:"Schema đầu vào (Input Schema):",runToolWithName:"Chạy công cụ: {{name}}",execution:"Thực thi công cụ",successful:"Thành công",failed:"Thất bại",result:"Kết quả:",error:"Lỗi",errorDetails:"Chi tiết lỗi:",noContent:"Công cụ thực thi thành công nhưng không trả về nội dung nào.",unknownError:"Đã xảy ra lỗi không xác định",jsonResponse:"Phản hồi JSON:",toolResult:"Kết quả công cụ",noParameters:"Công cụ này không yêu cầu bất kỳ tham số nào.",selectOption:"Chọn một tùy chọn",enterValue:"Nhập giá trị {{type}}",enabled:"Đã bật",enableSuccess:"Bật công cụ {{name}} thành công",disableSuccess:"Tắt công cụ {{name}} thành công",toggleFailed:"Bật/tắt trạng thái công cụ thất bại",descriptionUpdateSuccess:"Cập nhật mô tả công cụ thành công",descriptionUpdateFailed:"Cập nhật mô tả công cụ thất bại",descriptionModifiedBadge:"Đã chỉnh sửa",defaultDescriptionLabel:"Mô tả mặc định",visibleParams:"Các tham số hiển thị cho mô hình",visibleParamsHelp:"Các tham số không được chọn sẽ bị loại bỏ khỏi lược đồ mà các mô hình nhận được, đồng thời cũng bị lược bỏ khỏi các lệnh gọi của chúng. Các tham số bắt buộc (*) không thể ẩn đi.",requiredParam:"Các tham số bắt buộc không thể bị ẩn đi",hiddenParamsFailed:"Không thể cập nhật các tham số ẩn",defaultDescriptionTooltip:"Mô tả mặc định: {{description}}",restoreDefault:"Khôi phục mặc định",restoreDefaultSuccess:"Đã khôi phục mô tả công cụ về mặc định",restoreDefaultFailed:"Khôi phục mô tả mặc định của công cụ thất bại",parameters:"Tham số công cụ",formMode:"Chế độ Biểu mẫu",jsonMode:"Chế độ JSON",jsonConfiguration:"Cấu hình JSON",invalidJsonFormat:"Định dạng JSON không hợp lệ",fixJsonBeforeSwitching:"Vui lòng sửa định dạng JSON trước khi chuyển sang chế độ biểu mẫu",item:"Mục {{index}}",addItem:"Thêm mục {{key}}",enterKey:"Nhập {{key}}"},Zo={run:"Lấy",running:"Đang lấy...",result:"Kết quả lời nhắc",error:"Lỗi lời nhắc",execution:"Thực thi lời nhắc",successful:"Thành công",failed:"Thất bại",errorDetails:"Chi tiết lỗi:",noContent:"Lời nhắc thực thi thành công nhưng không trả về nội dung nào.",unknownError:"Đã xảy ra lỗi không xác định",jsonResponse:"Phản hồi JSON:",description:"Mô tả",messages:"Tin nhắn",noDescription:"Không có mô tả nào",runPromptWithName:"Lấy Lời nhắc: {{name}}",descriptionUpdateSuccess:"Cập nhật mô tả lời nhắc thành công",descriptionUpdateFailed:"Cập nhật mô tả lời nhắc thất bại",restoreDefault:"Khôi phục mặc định",restoreDefaultSuccess:"Đã khôi phục mô tả lời nhắc về mặc định",restoreDefaultFailed:"Khôi phục mô tả lời nhắc về mặc định thất bại"},es=JSON.parse(`{"dashboardName":"Tên bảng điều khiển","dashboardNameDescription":"Hiển thị ở thanh bên, tiêu đề, trang đăng nhập và thẻ trình duyệt. Để trống để khôi phục tên mặc định.","dashboardNameSaveFailed":"Không thể lưu tên bảng điều khiển","resetBearerKey":"Đặt lại khóa Bearer","resetBearerKeyConfirm":"Đặt lại khóa Bearer này? Token cũ sẽ mất hiệu lực ngay. Quyền và trạng thái kích hoạt không thay đổi.","resetBearerKeySuccess":"Đã đặt lại khóa. Sao chép và lưu token mới trước khi đóng; token sẽ không được hiển thị lại.","resetBearerKeyError":"Không thể đặt lại khóa Bearer","allowRegistration":"Cho phép tự đăng ký","allowRegistrationDescription":"Cho phép khách truy cập tạo tài khoản thông thường từ trang đăng nhập. Tắt theo mặc định; không khả dụng khi chức năng đăng nhập bằng mật khẩu bị vô hiệu hóa.","allowedCidrs":"Dải CIDR upstream cho phép","allowedCidrsDescription":"Một dải IPv4 hoặc IPv6 CIDR trên mỗi dòng. Tất cả người dùng có thể kết nối với các endpoint MCP, OpenAPI và OAuth upstream trong các dải này. Bỏ trống nghĩa là không cấp thêm quyền truy cập. Các máy chủ thuộc sở hữu admin giữ nguyên quyền truy cập nội bộ không hạn chế. Tránh dùng các dải quá rộng, địa chỉ metadata hoặc loopback trừ khi thật sự cần thiết. Thay đổi áp dụng cho các yêu cầu mới; các kết nối hiện tại không bị đóng.","allowedCidrsUpdateFailed":"Cập nhật các dải CIDR được phép thất bại","subtitle":"Cấu hình các cài đặt hệ thống, xác thực, định tuyến và tích hợp máy chủ MCP.","enableGlobalRoute":"Bật Tuyến đường toàn hệ thống (Global Route)","enableGlobalRouteDescription":"Cho phép kết nối đến endpoint /sse mà không cần chỉ định ID nhóm","enableGroupNameRoute":"Bật Tuyến đường theo Tên nhóm","enableGroupNameRouteDescription":"Cho phép kết nối đến endpoint /sse sử dụng tên nhóm thay vì chỉ dùng ID nhóm","enableBearerAuth":"Bật Xác thực Bearer (Bearer Authentication)","enableBearerAuthDescription":"Yêu cầu xác thực token bearer cho các endpoint MCP (mặc định bật)","bearerAuthKey":"Khóa Xác thực Bearer","bearerAuthKeyDescription":"Khóa xác thực sẽ được yêu cầu trong token Bearer","bearerAuthKeyPlaceholder":"Nhập khóa xác thực bearer","bearerAuthHeaderName":"Tên tiêu đề Xác thực Bearer","bearerAuthHeaderNameDescription":"Tên header được sử dụng để nhận thông tin xác thực bearer MCP. Đổi giá trị này khi các header passthrough upstream cũng sử dụng Authorization.","bearerAuthHeaderNamePlaceholder":"Ví dụ: Authorization hoặc X-MCP-Authorization","bearerKeysSectionTitle":"Các khóa (Keys)","bearerKeysSectionDescription":"Quản lý nhiều khóa với các phạm vi truy cập khác nhau.","bearerKeyScopeFilter":"Lọc theo phạm vi","noBearerKeys":"Chưa có khóa nào được cấu hình.","bearerKeyName":"Tên","bearerKeyToken":"Token","bearerKeyEnabled":"Đã bật","bearerKeyAccessType":"Phạm vi truy cập","bearerKeyAccessAll":"Tất cả","bearerKeyAccessGroups":"Nhóm","bearerKeyAccessServers":"Máy chủ","bearerKeyAccessCustom":"Tùy chỉnh","bearerKeyAllowedGroups":"Nhóm được phép","bearerKeyAllowedServers":"Máy chủ được phép","addBearerKey":"Thêm khóa","addBearerKeyButton":"Tạo","bearerKeyRequired":"Tên và token là bắt buộc","bearerKeyNameRequired":"Tên là bắt buộc","bearerKeyOwnerRequired":"Chủ sở hữu là bắt buộc","bearerKeyKind":"Loại khóa","bearerKeyKindSystem":"Cấp hệ thống","bearerKeyKindUser":"Cấp người dùng","bearerKeyOwner":"Chủ sở hữu","bearerKeySelectOwner":"Chọn người dùng...","bearerKeyAccessUserVisibility":"Khả năng hiển thị của người dùng","bearerKeyShownOnce":"Sao chép token này ngay bây giờ. Nó sẽ không được hiển thị lại.","deleteBearerKeyConfirm":"Bạn có chắc chắn muốn xóa khóa này không?","generate":"Tạo","selectGroups":"Chọn nhóm","selectServers":"Chọn máy chủ","selectAtLeastOneGroup":"Vui lòng chọn ít nhất một nhóm","selectAtLeastOneServer":"Vui lòng chọn ít nhất một máy chủ","skipAuth":"Bỏ qua xác thực","skipAuthDescription":"Cho phép truy cập bảng điều khiển mà không cần đăng nhập; người dùng chưa xác thực sẽ có quyền quản trị cấp khách (không ảnh hưởng đến xác thực của endpoint MCP)","jsonBodyLimit":"Giới hạn kích thước Body JSON","jsonBodyLimitDescription":"Giới hạn kích thước yêu cầu JSON của Express. Điều này cũng ảnh hưởng đến các lần tải lên lược đồ OpenAPI dung lượng lớn.","jsonBodyLimitPlaceholder":"Ví dụ: 1mb, 5mb, 1024kb","pythonIndexUrl":"URL Kho gói Python (Package Repository)","pythonIndexUrlDescription":"Đặt biến môi trường UV_DEFAULT_INDEX cho việc cài đặt gói Python","pythonIndexUrlPlaceholder":"Ví dụ: https://pypi.org/simple","npmRegistry":"URL NPM Registry","npmRegistryDescription":"Đặt biến môi trường npm_config_registry cho việc cài đặt gói NPM","npmRegistryPlaceholder":"Ví dụ: https://registry.npmjs.org/","baseUrl":"URL Cơ sở (Base URL)","baseUrlDescription":"URL cơ sở cho các yêu cầu MCP và callback OAuth","baseUrlPlaceholder":"Ví dụ: http://localhost:3000","installConfig":"Cài đặt","clearCache":"Xóa bộ nhớ đệm gói (cache)","clearCacheDescription":"Xóa bộ nhớ đệm gói của npm và uv. Máy chủ có thể cần tải lại các gói ở lần khởi động tới.","clearCacheConfirm":"Hành động này sẽ xóa bộ nhớ đệm gói npm và uv. Các máy chủ có thể phải tải lại các gói vào lần khởi động tiếp theo.","clearCacheSuccess":"Đã xóa bộ nhớ đệm gói thành công","clearCacheError":"Xóa bộ nhớ đệm gói thất bại","clearCacheSkipped":"chưa cài đặt","clearingCache":"Đang xóa...","systemConfigUpdated":"Cập nhật cấu hình hệ thống thành công","noChanges":"Không có thay đổi nào để lưu","betterAuthTitle":"Better Auth","betterAuthEnvNote":"Client IDs và secrets vẫn lấy từ biến môi trường. Thay đổi cài đặt Better Auth có thể yêu cầu khởi động lại ứng dụng, và nguồn origin của URL cài đặt cơ sở được tự động tin cậy.","enableBetterAuth":"Bật Better Auth","enableBetterAuthDescription":"Bật đăng nhập qua mạng xã hội và OIDC khi các biến môi trường bắt buộc được cấu hình.","disablePasswordLogin":"Tắt đăng nhập bằng mật khẩu","disablePasswordLoginDescription":"Chỉ cho phép đăng nhập qua các nhà cung cấp SSO: biểu mẫu tên người dùng/mật khẩu và POST /api/auth/login bị tắt. Chỉ có hiệu lực khi có ít nhất một nhà cung cấp được bật và đã được bật từ lúc ứng dụng khởi động. Biến môi trường BETTER_AUTH_DISABLE_PASSWORD_LOGIN sẽ ghi đè thiết lập này; đặt về false là cách quay lại nếu nhà cung cấp danh tính không khả dụng.","betterAuthBaseUrl":"URL Cơ sở","betterAuthBaseUrlDescription":"URL cơ sở công khai dùng để tạo các URI chuyển hướng của Better Auth. Dự phòng về URL cài đặt cơ sở nếu để trống; biến môi trường BETTER_AUTH_URL có mức ưu tiên cao nhất.","betterAuthBasePath":"Đường dẫn cơ sở Auth (Base path)","betterAuthBasePathDescription":"Đường dẫn API tương đối dùng cho các route của Better Auth.","betterAuthTrustedOrigins":"Các nguồn tin cậy (Trusted origins)","betterAuthTrustedOriginsDescription":"Các origin (phân tách bằng dấu phẩy) được phép thực hiện yêu cầu Better Auth. Origin của URL cài đặt cơ sở được tự động thêm vào.","betterAuthProviders":"Các nhà cung cấp (Providers)","betterAuthProvidersDescription":"Các công tắc nhà cung cấp điều khiển phương thức đăng nhập nào sẽ hiển thị trên trang đăng nhập.","betterAuthGoogleDescription":"Yêu cầu GOOGLE_CLIENT_ID và GOOGLE_CLIENT_SECRET.","betterAuthGithubDescription":"Yêu cầu GITHUB_CLIENT_ID và GITHUB_CLIENT_SECRET.","betterAuthOidcDescription":"Yêu cầu thông tin client OIDC cộng với URL khám phá (discovery URL).","betterAuthOidcProviderId":"ID nhà cung cấp OIDC","betterAuthOidcProviderIdDescription":"Định danh nhà cung cấp dùng khi bắt đầu luồng đăng nhập OIDC.","betterAuthOidcDiscoveryUrl":"URL Khám phá OIDC","betterAuthOidcDiscoveryUrlDescription":"URL cấu hình OpenID well-known được công bố bởi nhà cung cấp danh tính của bạn.","betterAuthOidcScopes":"Phạm vi OIDC (Scopes)","betterAuthOidcScopesDescription":"Các phạm vi yêu cầu (phân tách bằng dấu phẩy) trong luồng đăng nhập OIDC.","betterAuthOidcPrompt":"Prompt OIDC","betterAuthOidcPromptDescription":"Giá trị prompt tùy chọn gửi đến nhà cung cấp danh tính, chẳng hạn như login hoặc consent.","betterAuthOidcPkce":"Bật PKCE","betterAuthOidcPkceDescription":"Dùng PKCE cho luồng ủy quyền OIDC.","enableSmartRouting":"Bật Định tuyến thông minh","enableSmartRoutingDescription":"Bật tính năng định tuyến thông minh để tìm kiếm công cụ phù hợp nhất dựa trên đầu vào (dùng tên nhóm $smart)","dbUrl":"URL PostgreSQL (yêu cầu hỗ trợ pgvector)","dbUrlPlaceholder":"Ví dụ: postgresql://user:password@localhost:5432/dbname","embeddingProvider":"Nhà cung cấp Embedding","embeddingProviderPreset":"Preset Nhà cung cấp","embeddingProviderPresetDescription":"Chọn một nhà cung cấp để điền sẵn endpoint tương thích với OpenAI và model của họ.","embeddingProviderPresetOpenai":"OpenAI","embeddingProviderPresetOpenrouter":"OpenRouter","embeddingProviderPresetSiliconflow":"SiliconFlow · Gói miễn phí (1000 RPM)","embeddingProviderPresetGemini":"Google Gemini · Gói miễn phí (100 RPM)","embeddingProviderPresetCustom":"Khác / Tương thích OpenAI","llmProviderBaseUrl":"URL Cơ sở tương thích OpenAI","llmProviderBaseUrlPlaceholder":"https://api.openai.com/v1","llmProviderApiKey":"Khóa API của Nhà cung cấp LLM","llmProviderApiKeyPlaceholder":"Nhập Khóa API LLM","smartRoutingEnvOverrideWarning":"Hiện tại được cung cấp bởi biến môi trường {{envVar}} — giá trị lưu tại đây sẽ bị bỏ qua khi chạy.","embeddingModel":"Tên Mô hình Embedding","embeddingModelPlaceholder":"text-embedding-3-small","basePacingDelayMs":"Độ trễ cơ sở (Base Pacing Delay - ms)","basePacingDelayMsDescription":"Độ trễ tối thiểu giữa các yêu cầu API embedding. Mặc định là 0 — hệ thống tự động quản lý giới hạn tỷ lệ (rate limits): nó tôn trọng tiêu đề Retry-After, lùi thời gian (cooldown) 63 giây và tăng độ trễ sau bất kỳ phản hồi 403/429 nào. Chỉ đặt giá trị khác 0 nếu nhà cung cấp của bạn bắt buộc một khoảng thời gian chờ cố định tối thiểu giữa các yêu cầu.","basePacingDelayMsPlaceholder":"Trống = mặc định 0 ms","basePacingDelayMsAuto":"Mặc định ({{value}} ms): giới hạn tỷ lệ được quản lý tự động.","basePacingDelayMsZero":"0 ms (mặc định): giới hạn tỷ lệ được quản lý tự động thông qua throttling thích ứng và logic thử lại.","basePacingDelayMsOverride":"Giá trị tùy chỉnh: ghi đè độ trễ cơ sở mặc định.","embeddingEncodingFormat":"Định dạng mã hóa Embedding","embeddingEncodingFormatDescription":"Định dạng mã hóa cho các vector embedding. 'Tự động' sẽ phát hiện dựa trên sự hỗ trợ của nhà cung cấp.","embeddingEncodingFormatAuto":"Tự động (Khuyên dùng)","embeddingDimensions":"Số chiều Embedding (Dimensions)","embeddingDimensionsDescription":"Kích thước đầu ra tùy chọn đối với các nhà cung cấp có hỗ trợ. Để trống để dùng mặc định của mô hình.","embeddingDimensionsPlaceholder":"Trống = mặc định của mô hình","embeddingDimensionsApiPassthrough":"Chuyển tiếp số chiều lên API (passthrough MRL)","embeddingDimensionsApiPassthroughDescription":"Chỉ các mô hình được biết là hỗ trợ Matryoshka (MRL) mới nhận được tham số dimensions. Bật tính năng này để ép buộc cho các mô hình hỗ trợ MRL khác. Các mô hình không có MRL (Qwen3-Embedding, BGE, vLLM/sglang) sẽ từ chối tham số này hoàn toàn, vì vậy hãy tắt cài đặt này đối với chúng.","azureOpenaiEndpoint":"Endpoint Azure OpenAI","azureOpenaiEndpointPlaceholder":"https://TEN_TAI_NGUYEN_CUA_BAN.openai.azure.com","azureOpenaiApiKey":"Khóa API Azure OpenAI","azureOpenaiApiKeyPlaceholder":"Nhập khóa API Azure OpenAI","azureOpenaiApiVersion":"Phiên bản API Azure OpenAI","azureOpenaiApiVersionPlaceholder":"2024-02-15-preview","azureOpenaiEmbeddingDeployment":"Deployment Embedding Azure OpenAI","azureOpenaiEmbeddingDeploymentPlaceholder":"text-embedding-3-small","azureOpenaiEmbeddingModel":"Tên Mô hình Embedding Azure","azureOpenaiEmbeddingModelDescription":"Tên mô hình OpenAI thực tế được deploy trong Azure (vd: text-embedding-3-small). Dùng để đếm token chính xác trước khi gửi văn bản đến API.","azureOpenaiEmbeddingModelPlaceholder":"text-embedding-3-small","progressiveDisclosure":"Tiết lộ lũy tiến (Progressive Disclosure)","progressiveDisclosureDescription":"Khi được bật, search_tools chỉ trả về tên và mô tả công cụ. Sử dụng describe_tool để lấy schema tham số đầy đủ, giúp giảm lượng token tiêu thụ.","embeddingMaxTokens":"Max Token của Embedding","embeddingMaxTokensDescription":"Số lượng token tối đa dùng để cắt xén văn bản trước khi tạo embedding. Để trống để tự động dùng mặc định của mô hình. Giá trị tùy chỉnh luôn ghi đè mặc định của mô hình. Việc thiết lập thủ công giá trị này đặc biệt hữu ích khi sử dụng các nhà cung cấp LLM cục bộ để tránh lỗi vượt quá giới hạn.","embeddingMaxTokensPlaceholder":"Trống = tự động theo mô hình","embeddingMaxTokensAuto":"Tự động: {{limit}} token (mặc định của mô hình {{model}})","embeddingMaxTokensOverride":"Giá trị này ghi đè mặc định của mô hình.","embeddingPrefixes":"Tiền tố Tác vụ Embedding","embeddingPrefixesDescription":"Văn bản được nối vào phía trước trước khi embedding, dành cho các mô hình tìm kiếm bất đối xứng được huấn luyện với các tiền tố tác vụ (vd: EmbeddingGemma, E5, Nomic). Để trống cả hai cho các mô hình mong đợi văn bản thô. Hãy bao gồm khoảng trắng ở cuối. Việc thay đổi tiền tố tài liệu sẽ thực hiện re-embed lại tất cả các công cụ.","embeddingQueryPrefix":"Tiền tố truy vấn (Query prefix)","embeddingDocumentPrefix":"Tiền tố tài liệu (Document prefix)","searchResults":"Kết quả tìm kiếm","searchResultsDescription":"Cách search_tools lọc và trả về kết quả khớp. Mỗi kết quả sẽ có điểm số tương đồng (similarity score) kèm theo. Để trống cả hai để dùng các giá trị mặc định.","similarityThreshold":"Ngưỡng tương đồng (0-1)","similarityThresholdPlaceholder":"Trống = tính theo độ dài truy vấn (0.2 / 0.3 / 0.4)","fullSchemaTopN":"Lấy schema đầy đủ cho N kết quả đầu tiên","fullSchemaTopNPlaceholder":"Trống = tất cả kết quả; các kết quả thấp hơn sẽ nhận describe_tool","toolDefinitionFields":"Các trường công cụ trong kết quả","toolDefinitionFieldsDescription":"Các trường tùy chọn mà kết quả search_tools và describe_tool mang theo bên cạnh name, description và inputSchema. Mặc định: title và annotations. Các trường khác chủ yếu dành cho client và có thể khá lớn (icon thường là ảnh base64).","invalidSearchSettings":"Giá trị không hợp lệ cho {{fields}}. Ngưỡng độ tương đồng phải nằm trong khoảng từ 0 đến 1, và Top N phải là một số nguyên từ 0 trở lên.","smartRoutingConfigUpdated":"Cập nhật cấu hình định tuyến thông minh thành công","smartRoutingRequiredFields":"Yêu cầu có URL cơ sở dữ liệu để bật định tuyến thông minh. Yêu cầu có Khóa API LLM Provider đối với các nhà cung cấp dựa trên đám mây (các LLM cục bộ thường không yêu cầu khóa API, hãy nhập một giá trị bất kỳ để qua bước xác thực biểu mẫu)","smartRoutingValidationError":"Vui lòng điền vào các trường bắt buộc trước khi bật Định tuyến Thông minh: {{fields}}","smartRoutingWorkflow":"Quy trình làm việc (Workflow)","smartRoutingWorkflowDescription":"Các lời nhắc (prompts) được vector hóa; top-k công cụ tương đồng nhất sẽ được lấy từ pgvector và phơi bày cho LLM upstream.","toolResultCompressionTitle":"Nén Kết quả Công cụ","toolResultCompressionEnable":"Bật nén","toolResultCompressionDescription":"Giảm dung lượng đầu ra văn bản lớn của các công cụ trước khi chúng đến tay MCP clients. Những thay đổi sẽ áp dụng cho lệnh gọi công cụ tiếp theo.","toolResultCompressionStrategy":"Chiến lược","toolResultCompressionStrategyDescription":"Tự động phát hiện JSON, logs, đầu ra tìm kiếm, diffs, và văn bản thuần túy.","toolResultCompressionMinTokens":"Số token tối thiểu","toolResultCompressionMinTokensDescription":"Chỉ nén các khối văn bản đạt hoặc vượt quá kích thước này.","toolResultCompressionMaxOutputTokens":"Ngân sách token đầu ra","toolResultCompressionMaxOutputTokensDescription":"Số lượng token tối đa mục tiêu cho mỗi khối văn bản bị nén.","mcpRouterConfig":"Chợ Đám mây (Cloud Market)","mcpRouterApiKey":"Khóa API MCPRouter","mcpRouterApiKeyDescription":"Khóa API dùng để truy cập dịch vụ chợ đám mây MCPRouter","mcpRouterApiKeyPlaceholder":"Nhập khóa API MCPRouter","mcpRouterReferer":"Referer","mcpRouterRefererDescription":"Tiêu đề Referer dùng cho các yêu cầu API MCPRouter","mcpRouterRefererPlaceholder":"https://www.mcphub.app","mcpRouterTitle":"Tiêu đề (Title)","mcpRouterTitleDescription":"Tiêu đề Header dùng cho các yêu cầu API MCPRouter","mcpRouterTitlePlaceholder":"MCPHub","mcpRouterBaseUrl":"URL Cơ sở","mcpRouterBaseUrlDescription":"URL cơ sở cho API MCPRouter","mcpRouterBaseUrlPlaceholder":"https://api.mcprouter.to/v1","systemSettings":"Cài đặt Hệ thống","nameSeparatorLabel":"Ký tự Phân tách Tên","nameSeparatorDescription":"Ký tự dùng để phân tách tên máy chủ và tên công cụ/lời nhắc (mặc định: -)","enableSessionRebuild":"Bật tái thiết Phiên Máy chủ","enableSessionRebuildDescription":"Khi được bật, sẽ áp dụng mã tái thiết phiên (session rebuild) máy chủ cải tiến để quản lý phiên mượt mà hơn","storeToolPayload":"Lưu Trữ Payload gọi Công cụ","storeToolPayloadDescription":"Khi được bật, đầu vào và đầu ra đầy đủ của mỗi lần gọi công cụ sẽ được lưu trong nhật ký hoạt động. Các payload công cụ được lưu nguyên văn (verbatim) mà không bị che giấu (redaction); hãy tắt tính năng này nếu đối số công cụ có thể chứa dữ liệu nhạy cảm và không nên được lưu trữ lâu dài.","storeToolPayloadUpdateFailed":"Cập nhật thiết lập lưu trữ payload công cụ thất bại","restartRequired":"Đã lưu cấu hình. Khuyến cáo khởi động lại ứng dụng để đảm bảo toàn bộ dịch vụ tải cài đặt mới một cách chính xác.","exportMcpSettings":"Xuất Cài đặt","mcpSettingsJson":"MCP Settings JSON","mcpSettingsJsonDescription":"Xem, sao chép hoặc tải xuống cấu hình mcp_settings.json hiện tại của bạn để sao lưu hoặc di chuyển sang công cụ khác","copyToClipboard":"Sao chép vào khay nhớ tạm","downloadJson":"Tải xuống JSON","exportSuccess":"Xuất cài đặt thành công","exportError":"Lấy thông tin cài đặt thất bại","enableOauthServer":"Bật Máy chủ OAuth","enableOauthServerDescription":"Cho phép MCPHub cấp token OAuth cho các ứng dụng client bên ngoài","requireClientSecret":"Yêu cầu Client Secret","requireClientSecretDescription":"Khi được bật, các client mật phải cung cấp client secret (hãy tắt cho các client chỉ dùng PKCE)","requireState":"Yêu cầu Tham số State","requireStateDescription":"Từ chối các yêu cầu ủy quyền mà bỏ qua tham số trạng thái (state) OAuth","accessTokenLifetime":"Thời gian sống của Access Token (giây)","accessTokenLifetimeDescription":"Khoảng thời gian token truy cập được cấp giữ hiệu lực","accessTokenLifetimePlaceholder":"Ví dụ: 3600","refreshTokenLifetime":"Thời gian sống của Refresh Token (giây)","refreshTokenLifetimeDescription":"Khoảng thời gian refresh token giữ hiệu lực","refreshTokenLifetimePlaceholder":"Ví dụ: 1209600","authorizationCodeLifetime":"Thời gian sống của Authorization Code (giây)","authorizationCodeLifetimeDescription":"Thời gian mã ủy quyền giữ hiệu lực trước khi được đem đổi (exchange)","authorizationCodeLifetimePlaceholder":"Ví dụ: 300","allowedScopes":"Các phạm vi (Scopes) cho phép","allowedScopesDescription":"Danh sách các phạm vi (phân tách bằng dấu phẩy) người dùng có thể chấp thuận trong quá trình ủy quyền","allowedScopesPlaceholder":"Ví dụ: read, write","enableDynamicRegistration":"Bật Đăng ký Máy khách Động (Dynamic Client Registration)","dynamicRegistrationDescription":"Cho phép các client tuân thủ RFC 7591 tự đăng ký thông qua endpoint công khai","dynamicRegistrationAllowedGrantTypes":"Các Loại Grant Type cho phép","dynamicRegistrationAllowedGrantTypesDescription":"Danh sách (phân tách bằng dấu phẩy) các khoản cấp (grants) được phép cho các máy khách đăng ký động","dynamicRegistrationAllowedGrantTypesPlaceholder":"Ví dụ: authorization_code, refresh_token","dynamicRegistrationAuth":"Yêu cầu Xác thực","dynamicRegistrationAuthDescription":"Bảo vệ endpoint đăng ký để chỉ các yêu cầu đã được xác thực mới có thể đăng ký client","invalidNumberInput":"Vui lòng nhập một số không âm hợp lệ","dynamicRegistrationClientTtl":"TTL dọn dẹp Client (giây)","dynamicRegistrationClientTtlDescription":"Dọn dẹp các máy khách đăng ký động không có token nào đang sống hoặc luồng ủy quyền nào đang xử lý nếu chúng quá thời gian này. Đặt thành 0 để tắt dọn dẹp.","dynamicRegistrationClientTtlPlaceholder":"Ví dụ: 2592000","smartRoutingIndexTitle":"Chỉ mục Vector & Chẩn đoán","smartRoutingIndexRefresh":"Làm mới","smartRoutingIndexReindex":"Lập chỉ mục lại","smartRoutingIndexReindexing":"Đang lập chỉ mục lại…","smartRoutingIndexLoading":"Đang tải…","smartRoutingIndexNoData":"Chưa có dữ liệu chỉ mục. Hãy bật Định tuyến thông minh và nhấp Lập chỉ mục lại để xây dựng kho lưu trữ vector.","smartRoutingIndexStatsUnavailable":"Thống kê không khả dụng","smartRoutingIndexDatabase":"Cơ sở dữ liệu","smartRoutingIndexConnected":"Đã kết nối","smartRoutingIndexDisconnected":"Ngắt kết nối","smartRoutingIndexUnhealthy":"Không khỏe (Unhealthy)","smartRoutingIndexModel":"Mô hình","smartRoutingIndexDimensions":"Số chiều","smartRoutingIndexTotalRows":"Tổng số hàng","smartRoutingIndexToolRows":"Số hàng công cụ","smartRoutingIndexServerRows":"Số hàng máy chủ","smartRoutingIndexClusterLabel":"Máy chủ đã được lập chỉ mục","smartRoutingIndexCoverage":"Mức độ bao phủ","smartRoutingIndexLastSynced":"Đồng bộ lần cuối","smartRoutingIndexPerServer":"Số công cụ mỗi máy chủ","smartRoutingIndexMissingIndex":"{{count}} máy chủ đang bật bị thiếu chỉ mục","smartRoutingIndexSyncedRange":"Phạm vi đồng bộ: {{oldest}} → {{newest}}","smartRoutingIndexReindexDone":"Đã hoàn tất lập chỉ mục lại: {{synced}} máy chủ được đồng bộ, {{failed}} máy chủ lỗi, {{skipped}} máy chủ bị bỏ qua, tổng cộng {{total}} công cụ","smartRoutingIndexReindexFailed":"Lập chỉ mục lại thất bại: {{message}}","smartRoutingIndexReindexStarting":"Đang bắt đầu lập chỉ mục lại…","smartRoutingIndexReindexingServer":"Đang lập chỉ mục lại \\"{{server}}\\"","smartRoutingIndexReindexSummary":"Lập chỉ mục xong · {{synced}} đồng bộ, {{failed}} lỗi, {{skipped}} bỏ qua, {{total}} công cụ","smartRoutingIndexReindexConfirmTitle":"Xây dựng lại chỉ mục vector?","smartRoutingIndexReindexConfirmMessage":"Toàn bộ embedding hiện tại sẽ bị xóa sạch và tạo lại từ đầu. Quá trình này có thể tốn chút thời gian và tiêu tốn hạn mức sử dụng API embedding.","smartRoutingIndexPersonalCredentials":"Các máy chủ sử dụng thông tin xác thực cá nhân","smartRoutingIndexSkippedReason":"Bị bỏ qua","smartRoutingIndexIndexedAs":"được lập chỉ mục dưới tư cách {{principals}}","toolPolicies":{"missingReferences":"Không tìm thấy một số ID trong máy chủ, khóa hoặc nhóm đã tải. Quy tắc từ chối không khớp sẽ không bảo vệ; quy tắc cho phép không khớp có thể chặn truy cập. Kiểm tra trước khi lưu. Vẫn có thể lưu quy tắc cho tài nguyên sẽ tạo.","missingReference":"Quy tắc {{policyId}}: không tìm thấy {{selector}} {{value}}.","title":"Chính sách truy cập công cụ","description":"Quy tắc áp dụng cho việc khám phá và gọi công cụ, kể cả định tuyến thông minh. Có hiệu lực sau khi lưu.","semantics":"Bộ chọn trống khớp mọi chủ thể hoặc mục tiêu. Mọi bộ chọn trong một quy tắc phải khớp. Quy tắc cho phép phù hợp tạo danh sách cho phép; từ chối được ưu tiên. Chính sách không mở rộng quyền hiện có.","empty":"Chưa có chính sách. Áp dụng quyền truy cập hiện có.","rule":"Quy tắc {{number}}","id":"ID quy tắc (duy nhất, bắt buộc)","effect":"Hiệu lực","allow":"Cho phép","deny":"Từ chối","username":"Tên người dùng","keyId":"ID khóa Bearer","groupId":"ID nhóm điểm cuối","serverId":"ID máy chủ","tool":"Tên công cụ gốc","any":"Tất cả","selectorsHint":"Chọn gợi ý hoặc nhập giá trị chính xác. ID không đổi khi đổi tên. Nhóm là nhóm điểm cuối, không phải nhóm chứa máy chủ. Tên công cụ phân biệt hoa thường, không có tiền tố cổng hay ký tự đại diện.","add":"Thêm quy tắc","save":"Lưu chính sách","unsaved":"Thay đổi chưa lưu. Việc thêm và xóa chỉ có hiệu lực sau khi lưu.","invalid":"Mỗi quy tắc cần ID duy nhất không trống và hiệu lực hợp lệ. Bộ chọn không được chỉ chứa khoảng trắng.","saveFailed":"Không thể lưu chính sách. Thay đổi được giữ lại.","confirm":"Áp dụng ngay {{count}} chính sách này? Công cụ mà người dùng có thể truy cập có thể thay đổi.","confirmClear":"Xóa mọi chính sách? Quyền hiện có sẽ được áp dụng.","deleteRule":"Xóa quy tắc {{number}}","retry":"Thử lại"}}`),rs={upload:"Tải lên",uploadTitle:"Tải lên MCPB Bundle",dropFileHere:"Thả tệp .mcpb của bạn vào đây",orClickToSelect:"hoặc nhấp để chọn tệp từ máy tính",invalidFileType:"Vui lòng chọn một tệp .mcpb hợp lệ",noFileSelected:"Vui lòng chọn tệp .mcpb để tải lên",uploading:"Đang tải lên...",uploadFailed:"Tải lên tệp MCPB thất bại",installServer:"Cài đặt máy chủ MCP từ MCPB",extensionInfo:"Thông tin Tiện ích mở rộng",name:"Tên",version:"Phiên bản",description:"Mô tả",author:"Tác giả",tools:"Công cụ",serverName:"Tên máy chủ",serverNamePlaceholder:"Nhập tên cho máy chủ này",install:"Cài đặt",installing:"Đang cài đặt...",installFailed:"Cài đặt máy chủ từ MCPB thất bại",serverExistsTitle:"Máy chủ đã tồn tại",serverExistsConfirm:"Máy chủ '{{serverName}}' đã tồn tại. Bạn có muốn ghi đè nó bằng phiên bản mới không?",override:"Ghi đè"},ts={button:"Nhập (Import)",title:"Nhập Máy chủ từ file JSON",inputLabel:"JSON Cấu hình Máy chủ",inputHelp:"Dán file cấu hình máy chủ dạng JSON. Hỗ trợ các loại máy chủ STDIO, SSE và HTTP (streamable-http).",preview:"Xem trước",previewTitle:"Xem trước Máy chủ sắp Nhập",import:"Nhập (Import)",importing:"Đang nhập...",invalidFormat:"Định dạng JSON không hợp lệ. JSON phải chứa một đối tượng 'mcpServers'.",parseError:"Phân tích cú pháp JSON thất bại. Vui lòng kiểm tra định dạng và thử lại.",addFailed:"Thêm máy chủ thất bại",importFailed:"Nhập máy chủ thất bại",partialSuccess:"Nhập thành công {{count}} trong tổng số {{total}} máy chủ. Một vài máy chủ bị lỗi:",validationErrors:"Một số máy chủ không thể nhập được. Vui lòng sửa những lỗi sau và thử lại:"},as={button:"Nhập (Import)",title:"Nhập Nhóm từ file JSON",inputLabel:"JSON Cấu hình Nhóm",inputHelp:"Dán file cấu hình nhóm dạng JSON. Mỗi nhóm có thể bao gồm một danh sách máy chủ.",preview:"Xem trước",previewTitle:"Xem trước Nhóm sắp Nhập",import:"Nhập (Import)",importing:"Đang nhập...",invalidFormat:"Định dạng JSON không hợp lệ. JSON phải chứa một mảng 'groups'.",missingName:"Mỗi nhóm bắt buộc phải có một trường 'name'.",parseError:"Phân tích cú pháp JSON thất bại. Vui lòng kiểm tra định dạng và thử lại.",addFailed:"Thêm nhóm thất bại",importFailed:"Nhập nhóm thất bại",partialSuccess:"Nhập thành công {{count}} trong tổng số {{total}} nhóm. Một vài nhóm bị lỗi:"},ns={add:"Thêm Người dùng",addNew:"Thêm Người dùng mới",edit:"Sửa Người dùng",delete:"Xóa Người dùng",create:"Tạo Người dùng",update:"Cập nhật Người dùng",username:"Tên người dùng",email:"Email",emailPlaceholder:"Nhập email (tùy chọn)",password:"Mật khẩu",newPassword:"Mật khẩu mới",confirmPassword:"Xác nhận Mật khẩu",changePassword:"Đổi Mật khẩu",adminRole:"Quản trị viên (Administrator)",admin:"Admin",user:"Người dùng",role:"Vai trò",actions:"Hành động",addFirst:"Thêm người dùng đầu tiên của bạn",permissions:"Quyền hạn",adminPermissions:"Truy cập toàn bộ hệ thống",userPermissions:"Truy cập giới hạn",currentUser:"Bạn",noUsers:"Không tìm thấy người dùng nào",adminRequired:"Bắt buộc có quyền quản trị viên để quản lý người dùng",usernameRequired:"Tên người dùng là bắt buộc",passwordRequired:"Mật khẩu là bắt buộc",passwordTooShort:"Mật khẩu phải chứa ít nhất 6 ký tự",passwordMismatch:"Mật khẩu không khớp",usernamePlaceholder:"Nhập tên người dùng",passwordPlaceholder:"Nhập mật khẩu",newPasswordPlaceholder:"Để trống để giữ nguyên mật khẩu cũ",confirmPasswordPlaceholder:"Xác nhận mật khẩu mới",createError:"Tạo người dùng thất bại",updateError:"Cập nhật người dùng thất bại",deleteError:"Xóa người dùng thất bại",statsError:"Lấy số liệu thống kê người dùng thất bại",deleteConfirmation:"Bạn có chắc chắn muốn xóa người dùng '{{username}}'? Hành động này không thể hoàn tác.",confirmDelete:"Xóa Người dùng",deleteWarning:"Bạn có chắc chắn muốn xóa người dùng '{{username}}'? Hành động này không thể hoàn tác."},is={errors:{readonly:"Môi trường demo chỉ cho phép xem",invalid_credentials:"Tên người dùng hoặc mật khẩu không hợp lệ",password_login_disabled:"Chức năng đăng nhập bằng mật khẩu bị tắt. Vui lòng đăng nhập bằng SSO hoặc dùng bearer key để truy cập API.",serverNameRequired:"Tên máy chủ là bắt buộc",serverConfigRequired:"Cấu hình máy chủ là bắt buộc",serverConfigInvalid:"Cấu hình máy chủ phải bao gồm một URL, một OpenAPI specification URL/schema, hoặc lệnh kèm đối số",serverTypeInvalid:"Loại máy chủ phải thuộc một trong các giá trị sau: stdio, sse, streamable-http, openapi",urlRequiredForType:"URL là bắt buộc cho loại máy chủ {{type}}",openapiSpecRequired:"Bắt buộc phải có URL thông số OpenAPI hoặc lược đồ (schema) cho loại máy chủ openapi",headersInvalidFormat:"Headers phải là một object",headersNotSupportedForStdio:"Headers không được hỗ trợ đối với loại máy chủ stdio",serverNotFound:"Không tìm thấy máy chủ",failedToRemoveServer:"Không tìm thấy máy chủ hoặc xóa thất bại",internalServerError:"Lỗi máy chủ nội bộ",failedToGetServers:"Lấy thông tin máy chủ thất bại",failedToReloadServer:"Tải lại máy chủ thất bại",failedToGetServerSettings:"Lấy cài đặt máy chủ thất bại",failedToGetServerConfig:"Lấy cấu hình máy chủ thất bại",failedToSaveSettings:"Lưu cài đặt thất bại",toolNameRequired:"Bắt buộc phải có tên máy chủ và tên công cụ",descriptionMustBeString:"Mô tả phải là một chuỗi văn bản (string)",groupIdRequired:"ID nhóm là bắt buộc",groupNameRequired:"Tên nhóm là bắt buộc",groupNotFound:"Không tìm thấy nhóm",groupIdAndServerNameRequired:"ID nhóm và tên máy chủ là bắt buộc",groupOrServerNotFound:"Không tìm thấy nhóm hoặc máy chủ",toolsMustBeAllOrArray:'Công cụ (tools) phải là "all" hoặc một mảng các chuỗi (array of strings)',serverNameAndToolNameRequired:"Bắt buộc có tên máy chủ và tên công cụ",usernameRequired:"Tên người dùng là bắt buộc",userNotFound:"Không tìm thấy người dùng",failedToGetUsers:"Lấy thông tin người dùng thất bại",failedToGetUserInfo:"Lấy dữ liệu người dùng thất bại",failedToGetUserStats:"Lấy thống kê người dùng thất bại",marketServerNameRequired:"Tên máy chủ là bắt buộc",marketServerNotFound:"Không tìm thấy máy chủ chợ (market)",failedToGetMarketServers:"Lấy thông tin máy chủ chợ thất bại",failedToGetMarketServer:"Lấy thông tin một máy chủ chợ thất bại",failedToGetMarketCategories:"Lấy danh mục chợ thất bại",failedToGetMarketTags:"Lấy thẻ chợ thất bại",failedToSearchMarketServers:"Tìm kiếm máy chủ chợ thất bại",failedToFilterMarketServers:"Lọc máy chủ chợ thất bại",failedToProcessMcpbFile:"Xử lý file MCPB thất bại"},success:{serverCreated:"Tạo máy chủ thành công",serverUpdated:"Cập nhật máy chủ thành công",serverRemoved:"Gỡ bỏ máy chủ thành công",serverToggled:"Bật/tắt trạng thái máy chủ thành công",toolToggled:"Công cụ {{name}} đã được {{action}} thành công",toolDescriptionUpdated:"Cập nhật mô tả công cụ {{name}} thành công",systemConfigUpdated:"Cập nhật cấu hình hệ thống thành công",groupCreated:"Tạo nhóm thành công",groupUpdated:"Cập nhật nhóm thành công",groupDeleted:"Xóa nhóm thành công",serverAddedToGroup:"Thêm máy chủ vào nhóm thành công",serverRemovedFromGroup:"Xóa máy chủ khỏi nhóm thành công",serverToolsUpdated:"Cập nhật công cụ máy chủ thành công"}},os={authorizationFailed:"Ủy quyền Thất bại",authorizationFailedError:"Lỗi",authorizationFailedDetails:"Chi tiết",invalidRequest:"Yêu cầu Không hợp lệ",missingStateParameter:"Thiếu tham số 'state' bắt buộc của OAuth.",missingCodeParameter:"Thiếu tham số mã ủy quyền (authorization code) bắt buộc.",serverNotFound:"Không tìm thấy Máy chủ",serverNotFoundMessage:"Không tìm thấy máy chủ liên kết với yêu cầu ủy quyền này.",sessionExpiredMessage:"Phiên ủy quyền có thể đã hết hạn. Vui lòng thử ủy quyền lại.",authorizationSuccessful:"Ủy quyền Thành công",server:"Máy chủ",status:"Trạng thái",connected:"Đã kết nối",successMessage:"Máy chủ đã được ủy quyền và kết nối thành công.",autoCloseMessage:"Cửa sổ này sẽ tự động đóng sau 3 giây...",closeNow:"Đóng ngay",connectionError:"Lỗi kết nối",connectionErrorMessage:"Ủy quyền thành công, nhưng kết nối tới máy chủ thất bại.",reconnectMessage:"Vui lòng thử kết nối lại từ bảng điều khiển.",configurationError:"Lỗi cấu hình",configurationErrorMessage:"Transport máy chủ không hỗ trợ gọi OAuth finishAuth(). Vui lòng đảm bảo máy chủ được cấu hình với streamable-http transport.",internalError:"Lỗi Hệ thống nội bộ",internalErrorMessage:"Đã xảy ra lỗi không mong muốn trong quá trình xử lý callback OAuth.",closeWindow:"Đóng cửa sổ"},ss={add:"Thêm Lời nhắc",addNew:"Thêm Lời nhắc Mới",edit:"Sửa Lời nhắc",delete:"Xóa",noPrompts:"Không có lời nhắc tích hợp nào được cấu hình",addFirst:"Thêm lời nhắc đầu tiên của bạn",name:"Tên",namePlaceholder:"Ví dụ: code-review",title:"Tiêu đề",titlePlaceholder:"Ví dụ: Lời nhắc Đánh giá Mã nguồn (Code Review)",description:"Mô tả",descriptionPlaceholder:"Mô tả ngắn gọn về lời nhắc",template:"Mẫu (Template)",templatePlaceholder:"Nhập văn bản mẫu với các biến giữ chỗ (placeholder) {{parameter}}...",templateHint:"Sử dụng {{paramName}} cho các tham số trong mẫu",arguments:"Đối số",addArgument:"Thêm Đối số",argName:"Tên",argDescription:"Mô tả",argRequired:"Bắt buộc",enabled:"Đã bật",active:"Hoạt động",inactive:"Không hoạt động",nameRequired:"Tên là bắt buộc",templateRequired:"Mẫu (Template) là bắt buộc",fetchError:"Tải danh sách lời nhắc tích hợp thất bại",createError:"Tạo lời nhắc thất bại",updateError:"Cập nhật lời nhắc thất bại",deleteError:"Xóa lời nhắc thất bại",saveError:"Lưu lời nhắc thất bại",confirmDelete:"Xóa Lời nhắc",deleteWarning:'Bạn có chắc chắn muốn xóa lời nhắc "{{name}}"? Hành động này không thể hoàn tác.'},ls={add:"Thêm Tài nguyên",addNew:"Thêm Tài nguyên Mới",edit:"Sửa Tài nguyên",delete:"Xóa",noResources:"Không có tài nguyên tích hợp nào được cấu hình",addFirst:"Thêm tài nguyên đầu tiên của bạn",uri:"URI",uriPlaceholder:"Ví dụ: resource://docs/guide",name:"Tên",namePlaceholder:"Ví dụ: Hướng dẫn Người dùng",description:"Mô tả",descriptionPlaceholder:"Mô tả ngắn gọn về tài nguyên",mimeType:"Loại MIME",content:"Nội dung",contentPlaceholder:"Nhập nội dung tài nguyên...",enabled:"Đã bật",active:"Hoạt động",inactive:"Không hoạt động",descriptionUpdateSuccess:"Cập nhật mô tả tài nguyên thành công",descriptionUpdateFailed:"Cập nhật mô tả tài nguyên thất bại",restoreDefault:"Khôi phục mặc định",restoreDefaultSuccess:"Đã khôi phục mô tả tài nguyên về mặc định",restoreDefaultFailed:"Khôi phục mô tả tài nguyên về mặc định thất bại",uriRequired:"URI là bắt buộc",contentRequired:"Nội dung là bắt buộc",fetchError:"Tải danh sách tài nguyên tích hợp thất bại",createError:"Tạo tài nguyên thất bại",updateError:"Cập nhật tài nguyên thất bại",deleteError:"Xóa tài nguyên thất bại",saveError:"Lưu tài nguyên thất bại",confirmDelete:"Xóa Tài nguyên",deleteWarning:'Bạn có chắc chắn muốn xóa tài nguyên "{{name}}"? Hành động này không thể hoàn tác.'},cs={title:"Hoạt động",totalCalls:"Tổng số lệnh gọi",successCount:"Thành công",errorCount:"Thất bại",avgDuration:"Thời gian trung bình",timestamp:"Dấu thời gian",server:"Máy chủ",tool:"Công cụ",duration:"Thời lượng",status:"Trạng thái",group:"Nhóm",user:"Người dùng",key:"Khóa API",sourceIp:"IP Nguồn",input:"Đầu vào",output:"Đầu ra",details:"Chi tiết Hoạt động",errorMessage:"Thông báo Lỗi",searchServer:"Máy chủ...",searchTool:"Công cụ...",searchStatus:"Trạng thái...",searchGroup:"Nhóm...",searchUsername:"Người dùng...",searchKeyName:"Khóa API...",keyName:"Tên Khóa API",allStatus:"Tất cả Trạng thái",statusSuccess:"Thành công",statusError:"Lỗi",noData:"Không có dữ liệu hoạt động",fetchError:"Tải dữ liệu hoạt động thất bại",cleanup:"Dọn dẹp",confirmCleanup:"Bạn có chắc chắn muốn xóa các hoạt động đã lưu từ hơn 30 ngày trước?",cleanupSuccess:"Đã xóa {{count}} hoạt động cũ",cleanupError:"Dọn dẹp các hoạt động cũ thất bại",notAvailable:"Theo dõi hoạt động chỉ khả dụng ở chế độ sử dụng cơ sở dữ liệu"},ds={exportButton:"Xuất Mẫu (Template)",importButton:"Nhập Mẫu (Template)",exportTitle:"Xuất Mẫu Cấu hình",importTitle:"Nhập Mẫu Cấu hình",name:"Tên Mẫu",nameRequired:"Tên mẫu là bắt buộc",namePlaceholder:"Ví dụ: Frontend Dev Tools",description:"Mô tả",descriptionPlaceholder:"Ví dụ: Các máy chủ MCP tiêu chuẩn cho frontend dev",selectGroups:"Chọn Nhóm",selectGroupsHelp:"Để trống nếu muốn xuất tất cả các nhóm",selectAll:"Chọn Tất cả",deselectAll:"Bỏ chọn Tất cả",includeDisabled:"Bao gồm cả các máy chủ đang tắt",exportNote:"Những dữ liệu bí mật (API keys, tokens, mật khẩu) sẽ bị thay thế bằng ${PLACEHOLDER}. Người nhận phải cung cấp thông tin xác thực của riêng họ.",export:"Xuất",exporting:"Đang xuất...",exportFailed:"Xuất mẫu (template) thất bại",import:"Nhập",importing:"Đang nhập...",importFailed:"Nhập mẫu (template) thất bại",invalidFormat:"Định dạng mẫu không hợp lệ. Phải chứa các trường: version, name, servers và groups.",parseError:"Phân tích cú pháp JSON thất bại. Vui lòng kiểm tra định dạng và thử lại.",uploadFile:"Tải File Mẫu lên",or:"hoặc",pasteJson:"Dán Mẫu dưới dạng JSON",pastePlaceholder:"Dán nội dung .mcphub-template.json của bạn vào đây...",version:"Phiên bản",createdAt:"Ngày tạo",servers:"Máy chủ",groups:"Nhóm",serversInGroup:"máy chủ",envVarsNeeded:"Các Biến Môi trường cần thiết — hãy cấu hình chúng trước khi sử dụng các máy chủ vừa nhập:",importResult:"Máy chủ: {{serversCreated}} đã tạo, {{serversSkipped}} bỏ qua. Nhóm: {{groupsCreated}} đã tạo, {{groupsSkipped}} bỏ qua."},us={exposed:"Được cung cấp (Exposed)",gross:"Tổng (Gross)",estimate:"Số lượng token ước tính (cl100k) — mang tính tương đối",direct:"Trực tiếp",smartRouting:"Định tuyến thông minh",smartRoutingPd:"Định tuyến thông minh + Tiết lộ lũy tiến",smartRoutingPdHint:"Bao gồm công cụ siêu dữ liệu describe_tool — tăng chi phí khởi điểm nhưng giảm thiểu dung lượng phản hồi cho mỗi lần tìm kiếm",saved:"Giảm {{percent}}%",notConnected:"Chưa kết nối",connectedOf:"Đã kết nối {{connected}} trên tổng số {{total}} máy chủ",totalFootprint:"Mức tiêu thụ ngữ cảnh (Context footprint)"},ms={title:"Thông tin xác thực (Credentials)",missing:"Yêu cầu thông tin xác thực cá nhân đối với '{{serverName}}'. Hãy ràng buộc mọi khe cắm yêu cầu trong Bảng điều khiển → Thông tin xác thực.",description:"Ràng buộc thông tin xác thực của riêng bạn vào các máy chủ được chia sẻ. Mỗi máy chủ sẽ sử dụng thông tin xác thực của người dùng tạo yêu cầu.",slots:"Các khe cắm (slots) thông tin xác thực theo người dùng",slotsHint:"Chỉ khai báo tên trường. Mỗi khe cắm đều yêu cầu ràng buộc cá nhân; thông tin xác thực tổ chức không bao giờ được dùng làm phương án dự phòng.",target:"Mục tiêu xác thực",urlHint:"Với khe URL, đặt {{placeholder}} làm nhãn máy chủ hoặc đoạn đường dẫn hoàn chỉnh và liệt kê các giá trị được phép.",allowed:"Giá trị được phép (mỗi dòng một giá trị)",argsHint:"Đối với các khe cắm thuộc đối số, hãy dùng {{placeholder}} trong đối số đó, thay thế API_KEY bằng tên trường. Giá trị sẽ được chèn trực tiếp mà không qua shell.",fieldName:"Tên trường",label:"Nhãn (tùy chọn)",addSlot:"Thêm khe cắm (slot)",removeSlot:"Xóa khe cắm",personalBadge:"Thông tin xác thực cá nhân",manage:"Quản lý",configured:"Đã cấu hình",required:"Bắt buộc có ràng buộc (binding)",writeOnly:"Các giá trị đã lưu không thể được hiển thị. Để thay thế một ràng buộc, bạn phải nhập giá trị mới cho tất cả các khe cắm.",replaceValue:"Nhập giá trị thay thế",enterValue:"Nhập thông tin xác thực",save:"Lưu ràng buộc",delete:"Xóa ràng buộc",saved:"Đã lưu ràng buộc",deleted:"Đã xóa ràng buộc",failed:"Không thể quản lý thông tin xác thực",showAll:"Hiển thị tất cả các máy chủ",loading:"Đang tải…",empty:"Không có máy chủ dùng chung nào yêu cầu thông tin xác thực cá nhân.",targetUser:"Quản lý thông tin xác thực cho",myCredentials:"Thông tin xác thực của tôi",updatedAt:"Cập nhật lần cuối"},ps={app:Eo,about:Io,profile:No,sponsor:Oo,wechat:Mo,discord:Lo,theme:zo,auth:Uo,server:qo,status:Bo,errors:Fo,common:Ko,clientConfig:jo,pagination:Go,nav:Ho,pages:_o,logs:Vo,groups:$o,market:Jo,oauthServer:Wo,cloud:Yo,registry:Xo,tool:Qo,prompt:Zo,settings:es,mcpb:rs,jsonImport:ts,groupImport:as,users:ns,api:is,oauthCallback:os,builtinPrompts:ss,builtinResources:ls,activity:cs,template:ds,cost:us,credentials:ms},hs={title:"MCPHub 控制面板",error:"错误",closeButton:"关闭",noServers:"没有可用的 MCP 服务器",loading:"加载中...",logout:"退出登录",profile:"个人资料",changePassword:"修改密码",toggleSidebar:"切换侧边栏",welcomeUser:"欢迎, {{username}}",name:"MCPHub",embeddingSyncProgress:"正在为 {{serverName}} 创建嵌入",embeddingSyncProgressAriaLabel:"正在为 {{serverName}} 创建嵌入:已完成 {{current}}/{{total}}"},gs={title:"关于",versionInfo:"MCPHub 版本: {{version}}",newVersion:"有新版本可用!",currentVersion:"当前版本",newVersionAvailable:"新版本 {{version}} 已发布",viewOnGitHub:"在 GitHub 上查看",checkForUpdates:"检查更新",checking:"检查更新中...",viewChangelog:"查看更新日志",viewReleaseNotes:"查看版本说明",viewAllChanges:"查看全部更新",latestChanges:"最近更新",upToDate:"当前已是已知的最新版本。",releaseNotesUnavailable:"已有新版本,但暂时没有结构化版本说明。",updateChecksDisabled:"当前部署已禁用更新检查。",dismissUpdate:"忽略",dismissed:"已忽略",earlierReleases:"另有 {{count}} 个更早版本"},bs={viewProfile:"查看个人中心",userCenter:"个人中心"},vs={label:"赞助",title:"支持项目",rewardAlt:"赞赏码",supportMessage:"通过捐赠支持 MCPHub 的开发!",supportButton:"在 Ko-fi 上支持"},ys={label:"微信",title:"微信联系",qrCodeAlt:"微信二维码",scanMessage:"扫描二维码添加微信"},fs={label:"Discord",title:"加入我们的 Discord 服务器",community:"加入我们不断壮大的 Discord 社区,获取支持、参与讨论并了解最新动态!"},ks={title:"主题",light:"浅色",dark:"深色",system:"系统"},Ss={createAccount:"创建账号",backToLogin:"返回登录",userAlreadyExists:"用户名已存在",login:"登录",loginTitle:"登录 MCPHub",slogan:"开源、自托管的 MCP 网关与控制平面",subtitle:"通过统一端点连接、组织、控制和运行 Model Context Protocol 服务器。",username:"用户名",password:"密码",loggingIn:"登录中...",orContinue:"或使用以下方式继续",loginWithGoogle:"使用 Google 登录",loginWithGithub:"使用 GitHub 登录",loginWithOIDC:"使用 OIDC 登录",socialLoginFailed:"社交登录失败,请重试。","error.account_not_linked":"账户未关联。您的邮箱可能尚未通过身份提供方验证。请验证邮箱后重试。","error.email_doesn't_match":"身份提供方返回的邮箱与您现有账户不匹配。","error.email_not_found":"身份提供方未返回邮箱地址。","error.access_denied":"访问被身份提供方拒绝。","error.account_already_linked_to_different_user":"该账户已关联到其他用户。","error.unable_to_link_account":"无法关联账户,请重试。","error.signup_disabled":"注册当前已禁用。","error.oauth_provider_not_found":"未找到 OAuth 提供方。","error.invalid_code":"授权码无效,请重试。","error.unable_to_get_user_info":"无法从身份提供方获取用户信息。",emptyFields:"用户名和密码不能为空",loginFailed:"登录失败,请检查用户名和密码",loginError:"登录过程中出现错误",serverUnavailable:"无法连接到服务器,请检查网络连接或稍后再试",currentPassword:"当前密码",newPassword:"新密码",confirmPassword:"确认密码",passwordsNotMatch:"新密码与确认密码不一致",changePasswordSuccess:"密码修改成功",changePasswordError:"修改密码失败",changePassword:"修改密码",passwordChanged:"密码修改成功",passwordChangeError:"修改密码失败",defaultPasswordWarning:"默认密码安全警告",defaultPasswordMessage:"您正在使用默认密码(admin123),这存在安全风险。为了保护您的账户安全,请立即修改密码。",goToSettings:"前往修改",passwordStrengthError:"密码不符合安全要求",passwordMinLength:"密码长度至少为 8 个字符",passwordRequireLetter:"密码必须包含至少一个字母",passwordRequireNumber:"密码必须包含至少一个数字",passwordRequireSpecial:"密码必须包含至少一个特殊字符",passwordStrengthHint:"密码必须至少 8 个字符,且包含字母、数字和特殊字符"},Cs={protocolVersion:"MCP 协议",protocolVersionUnknown:"未获取",localExecutionRequiresAdmin:"本地命令执行需要管理员权限。",httpOAuthRequiresAdmin:"允许 HTTP OAuth 令牌端点需要管理员权限。",startOnDemand:"按需启动",startOnDemandDescription:"跳过启动时连接,仅在收到工具调用时才启动此服务器。进程在空闲超时后自动关闭,下次调用时再重新启动。可减少不常用服务器的常驻内存占用。",idleTimeoutMs:"空闲关闭超时(毫秒)",idleTimeoutMsDescription:"无工具调用达到此时长后关闭进程。默认:300000(5 分钟)。",addServer:"添加服务器",add:"添加",edit:"编辑",copy:"复制",duplicate:"创建副本",delete:"删除",confirmDelete:"您确定要删除此服务器吗?",deleteWarning:"删除服务器 '{{name}}' 将会移除该服务器及其所有数据。此操作无法撤销。",status:"状态",tools:"工具",prompts:"提示词",name:"服务器名称",nameInvalid:"服务器名称只能包含字母、数字、点、下划线和连字符(不能包含空格或特殊字符)",description:"服务器注释",descriptionPlaceholder:"可选:记录这个服务器的用途说明",url:"服务器 URL",apiKey:"API 密钥",save:"保存",cancel:"取消",addError:"添加服务器失败",editError:"编辑服务器 {{serverName}} 失败",invalidConfig:"无法找到 {{serverName}} 的配置数据",deleteError:"删除服务器 {{serverName}} 失败",updateError:"更新服务器失败",editTitle:"编辑服务器: {{serverName}}",duplicateTitle:"创建服务器副本: {{serverName}}",type:"服务器类型",typeStdio:"STDIO",typeSse:"SSE",typeStreamableHttp:"流式 HTTP",typeOpenapi:"OpenAPI",mcpApp:"MCP App — 此服务器暴露交互式 UI 资源",visibility:"可见性",visibilityPrivateShort:"私有",visibilityPrivate:"私有 — 仅所有者和管理员可见",visibilityGroupShort:"共享",visibilityGroup:"共享 — 仅选中的用户可见",visibilityPublicShort:"公开",visibilityPublic:"公开 — 所有已登录用户可见",visibilityDescription:"控制哪些非管理员用户可以发现并调用此服务器。管理员始终拥有访问权限。",shareWithUsers:"共享给用户",shareWithUsersDescription:"选中的用户可以发现并调用此服务器,但不能管理其配置。",shareCandidatesLoading:"正在加载用户...",shareCandidatesError:"加载用户失败。",shareAfterCreate:"请先保存服务器,再选择共享用户。",noShareCandidates:"没有其他可选用户。",shareUserSearchLabel:"搜索用户",shareUserSearchPlaceholder:"搜索用户名...",selectAllShareUsers:"全选",deselectAllShareUsers:"取消全选",noMatchingShareUsers:"没有匹配的用户。",command:"命令",packageVersion:"已安装的包版本(runner 缓存中最后安装的版本)",reportedVersion:"服务端报告的版本",updateAvailable:"源上有更新的版本可用",arguments:"参数",addArgument:"添加参数",argumentsHint:"每个输入框对应一个参数,保留空格和引号;空输入框会传递空字符串参数。",argumentLabel:"参数 {{index}}",removeArgument:"移除参数 {{index}}",envVars:"环境变量",headers:"HTTP 请求头",key:"键",value:"值",enabled:"已启用",enable:"启用",disable:"禁用",reload:"重载",reloadSuccess:"服务器重载成功",reloadError:"重载服务器 {{serverName}} 失败",reinstall:"重新安装",reinstallConfirm:"这将清除包缓存并重新下载依赖。服务器将会重启。",reinstallSuccess:"服务器重新安装已启动",reinstallError:"重新安装服务器 {{serverName}} 失败",disconnectOAuth:"断开 OAuth",disconnectOAuthConfirm:"这将尽可能撤销已保存的 OAuth 凭据,并需要重新授权。",disconnectOAuthSuccess:"服务器 OAuth 已断开",disconnectOAuthError:"断开服务器 {{serverName}} 的 OAuth 失败",requestOptions:"连接配置",maxBufferSize:"Stdio 缓冲区上限(字节)",maxBufferSizeDescription:"Stdio 读取缓冲区的最大大小。留空使用 SDK 默认值(10 MiB)。提高上限会允许使用更多内存。",timeout:"请求超时",timeoutDescription:"请求超时时间(毫秒)",maxTotalTimeout:"最大总超时",maxTotalTimeoutDescription:"无论是否有进度通知的最大总超时时间(毫秒)",resetTimeoutOnProgress:"收到进度通知时重置超时",resetTimeoutOnProgressDescription:"适用于发送周期性进度更新的长时间运行操作(默认开启)",keepAlive:"连接健康检查",retryScheduled:"{{time}} 重试",reconnecting:"正在重连…",lastRetry:"上次重试:{{time}}(已尝试 {{count}} 次)",enableKeepAlive:"启用健康检查",keepAliveDescription:"周期性检查连接健康状态。已断连的远端服务始终会按退避策略自动重连。",keepAliveInterval:"检查间隔(毫秒)",keepAliveIntervalDescription:"健康检查的时间间隔(默认:60000毫秒 = 1分钟)",perSessionClient:"会话级客户端隔离",perSessionClientDescription:"为每个会话创建独立的上游连接,而不是在所有会话间共享同一个连接。适用于 Playwright 等有状态服务器。并发会话越多,上游连接数越多。",remove:"移除",toggleError:"切换服务器 {{serverName}} 状态失败",alreadyExists:"服务器 {{serverName}} 已经存在",invalidData:"提供的服务器数据无效",notFound:"找不到服务器 {{serverName}}",namePlaceholder:"请输入服务器名称",urlPlaceholder:"请输入服务器URL",commandPlaceholder:"请输入命令",argumentsPlaceholder:"请输入参数",errorDetails:"错误详情",viewErrorDetails:"查看错误详情",copyConfig:"复制配置",confirmVariables:"确认变量配置",variablesDetected:"检测到配置中包含变量,请确认这些变量是否已正确配置:",detectedVariables:"检测到的变量",confirmVariablesMessage:"请确保这些变量在运行环境中已正确定义。是否继续添加服务器?",confirmAndAdd:"确认并添加",openapi:{inputMode:"输入模式",inputModeUrl:"规范 URL",inputModeSchema:"JSON 模式",specUrl:"OpenAPI 规范 URL",schema:"OpenAPI JSON 模式",schemaHelp:"请在此处粘贴完整的 OpenAPI JSON 模式",security:"安全类型",securityNone:"无",securityApiKey:"API 密钥",securityHttp:"HTTP 认证",securityOAuth2:"OAuth 2.0",securityOpenIdConnect:"OpenID Connect",securityDetect:"从规范检测",securityDetecting:"检测中…",securityNotDeclared:"该规范未声明任何安全方案。",securityPrefillNotice:"该规范声明了 {{summary}}。安全设置已自动预填——请在首次调用前填入你的凭据值。",securityMismatchWarning:"该规范声明的是 {{summary}},但当前服务器配置为 {{configured}}。这可能导致静默返回 401。",securityUnsupportedNotice:"该规范声明了 {{summary}},但 MCPHub 无法表示该方案({{reason}})。请手动配置认证。",apiKeyConfig:"API 密钥配置",apiKeyName:"请求头/参数名称",apiKeyIn:"位置",apiKeyValue:"API 密钥值",httpAuthConfig:"HTTP 认证配置",httpScheme:"认证方案",httpCredentials:"凭据",httpCredentialsBasicHint:"可输入 user:password(自动编码)或已编码的 Base64。",specSecurityToggle:"规范文档需要单独的认证",specSecurityHelp:"仅当规范文档本身与 API 使用不同的认证时启用(例如 /v3/api-docs 使用 Basic 保护,而 API 需要 Bearer)。关闭时,上方的安全配置同时用于两者。",httpSchemeBasic:"Basic",httpSchemeBearer:"Bearer",httpSchemeDigest:"Digest",oauth2Config:"OAuth 2.0 配置",oauth2Token:"访问令牌",openIdConnectConfig:"OpenID Connect 配置",openIdConnectUrl:"发现 URL",openIdConnectToken:"ID 令牌",apiKeyInHeader:"请求头",apiKeyInQuery:"查询",apiKeyInCookie:"Cookie",passthroughHeaders:"透传请求头",passthroughHeadersHelp:"要从传入的 MCP 请求透传到上游服务器请求的请求头名称列表,用逗号分隔(如:Authorization, X-API-Key)",cookieSession:"Cookie 会话处理",cookieSessionHelp:"捕获上游登录响应中的 Set-Cookie,并在同一下游会话的后续调用中自动携带。按 MCP 会话隔离,不持久化存储。",statsMeasuring:"正在测量生成的工具列表…",statsSummary:"{{toolCount}} 个工具 · 定义约 {{bytes}} · 约 {{tokens}} tokens",statsWarning:"仅此工具列表就可能接近或超过常见模型的上下文窗口。建议只暴露部分工具:创建分组,或在服务器上按工具禁用。",statsUnavailable:"暂时无法测量此规范。仍可继续,提交时服务器会再次校验导入。"},oauth:{sectionTitle:"OAuth 配置",sectionDescription:"为需要 OAuth 的服务器配置客户端凭据(可选)。",allowInsecureTokenEndpoint:"允许 HTTP OAuth 令牌端点",allowInsecureTokenEndpointHelp:"仅管理员可设置,默认关闭。此上游的凭据和令牌将通过未加密的 HTTP 传输。仅在可信网络中启用,建议使用 HTTPS。 启用后,整个服务器配置仅限管理员编辑,非管理员所有者也无法编辑。",clientId:"客户端 ID",clientSecret:"客户端密钥",authorizationEndpoint:"授权端点",tokenEndpoint:"令牌端点",scopes:"权限范围(Scopes)",scopesPlaceholder:"scope1 scope2",resource:"资源 / 受众",accessToken:"访问令牌",refreshToken:"刷新令牌",identityMode:"OAuth 身份",sharedIdentity:"共享账号",personalIdentity:"每位用户独立授权",personalIdentityHelp:"个人模式要求每位用户在 Dashboard 授权。用户密钥使用其拥有者身份;共享或服务密钥不支持。",personalConnect:"连接授权",personalReconnect:"重新授权",personalDisconnect:"断开授权",personalError:"个人授权失败",personalSuccess:"个人授权已保存,请返回 Dashboard → 服务器。"}},Ps={sleeping:"休眠",sleepingDescription:"按需启动服务器 - 调用工具时将自动启动",online:"在线",offline:"离线",connecting:"连接中",oauthRequired:"需要OAuth授权",clickToAuthorize:"点击进行OAuth授权",oauthWindowOpened:"OAuth授权窗口已打开,请完成授权。",oauthClientIdHint:"该服务器配置了预设的 OAuth 客户端 ID。如果授权因“invalid redirect_uri”失败,请删除 clientId,让 MCPHub 自动注册自己的 OAuth 客户端。"},As={general:"发生错误",network:"网络连接错误,请检查您的互联网连接",serverConnection:"无法连接到服务器,请检查服务器是否正在运行",serverAdd:"添加服务器失败,请检查服务器状态",serverUpdate:"编辑服务器 {{serverName}} 失败,请检查服务器状态",serverFetch:"获取服务器数据失败,请稍后重试",failedToReloadServer:"重载服务器失败",initialStartup:"服务器可能正在启动中。首次启动可能需要一些时间,请耐心等候...",serverInstall:"安装服务器失败",failedToFetchSettings:"获取设置失败",failedToUpdateSystemConfig:"更新系统配置失败",failedToUpdateRouteConfig:"更新路由配置失败",failedToUpdateSmartRoutingConfig:"更新智能路由配置失败",failedToUpdateBetterAuthConfig:"更新 Better Auth 配置失败"},Rs={processing:"处理中...",save:"保存",cancel:"取消",back:"返回",refresh:"刷新",search:"搜索",clear:"清除",view:"查看",create:"创建",creating:"创建中...",update:"更新",updating:"更新中...",submitting:"提交中...",delete:"删除",remove:"移除",copy:"复制",copyId:"复制ID",copyUrl:"复制URL",copyOpenApiUrl:"复制OpenAPI URL",copySuccess:"已复制到剪贴板",copyFailed:"复制失败",copied:"已复制",close:"关闭",confirm:"确认",language:"语言",true:"是",false:"否",dismiss:"忽略",github:"GitHub",wechat:"微信",itemsPerPage:"每页显示",showing:"显示第 {{start}}-{{end}} 条,共 {{total}} 条",previous:"上一页",next:"下一页",discord:"Discord",required:"必填",secret:"敏感",default:"默认值",value:"值",type:"类型",repeated:"可重复",valueHint:"值提示",choices:"可选值",actions:"操作",saving:"保存中...",active:"已激活",inactive:"未激活",viewAll:"查看全部",docs:"文档",all:"全部"},Ts={title:"复制 MCP 配置",description:"选择你的客户端,复制可直接粘贴的 {{name}} 配置。",menuItem:"复制 MCP 配置",tokenPrompt:"MCPHub 访问令牌",configBlock:"配置内容",commandBlock:"命令行",copied:"已复制",noTransport:"该服务器没有客户端侧的 MCP 传输方式(它由 OpenAPI 支撑)。请改用 hub 或分组端点。",clients:{"generic-mcp-servers":{label:"通用(mcpServers)",hint:"最通用的 mcpServers 结构:Claude Desktop、Cline、Cherry Studio 等大多数客户端都可用。"},"generic-http":{label:"通用 HTTP",hint:'输出裸条目的兜底出口:远程端点给出裸 HTTP 条目(SSE 上游会带上 "type": "sse" 标记),本地服务器给出裸 stdio 条目(command/args/env),粘进目标客户端自己的服务器表即可;大多数客户端请用「通用(mcpServers)」。'},"claude-code":{label:"Claude Code",hint:"Claude Code:`claude mcp add`,或写入 ~/.claude.json 的 mcpServers。"},cursor:{label:"Cursor",hint:"Cursor:项目内 .cursor/mcp.json,或全局 ~/.cursor/mcp.json。"},vscode:{label:"VS Code / Copilot",hint:"VS Code / Copilot:工作区 .vscode/mcp.json,或用户配置中的 mcp.json。"},codex:{label:"Codex",hint:"Codex:~/.codex/config.toml,或项目级 .codex/config.toml。"},opencode:{label:"OpenCode",hint:"OpenCode:全局 ~/.config/opencode/opencode.json,或项目内 opencode.json。"},windsurf:{label:"Windsurf",hint:"Windsurf:~/.codeium/windsurf/mcp_config.json。"},"cherry-studio":{label:"Cherry Studio",hint:"Cherry Studio:设置 > MCP 服务器 > 添加服务器 > 从 JSON 导入。"},codebuddy:{label:"CodeBuddy Code",hint:"CodeBuddy Code:全局 ~/.codebuddy/.mcp.json,或项目内 .mcp.json。"},qoder:{label:"Qoder",hint:"Qoder:设置 > MCP > 手动添加,粘贴 JSON。"},trae:{label:"TRAE",hint:"TRAE:设置 > MCP > 添加 > 手动添加,粘贴 JSON。"},zcode:{label:"ZCode",hint:"ZCode:设置 > MCP 服务器 > 新建 MCP 服务器 > 完整配置。"},workbuddy:{label:"WorkBuddy",hint:"WorkBuddy:侧边栏插件 > MCP 服务器 > 配置 MCP,或 ~/.workbuddy/mcp.json。"}}},xs={rowsPerPage:"每页行数",showing:"显示第 {{from}}-{{to}} 条,共 {{total}} 条"},ws={dashboard:"仪表盘",servers:"服务器",settings:"设置",changePassword:"修改密码",groups:"分组",prompts:"提示词",resources:"资源",users:"用户",market:"市场",cloud:"云端市场",logs:"日志",activity:"活动",workspace:"工作区",system:"系统"},Ds={dashboard:{title:"仪表盘",totalServers:"总数",onlineServers:"在线",disabledServers:"禁用",offlineServers:"离线",connectingServers:"连接中",recentServers:"最近的服务器",endpoints:"MCP 接入端点",endpointsHint:"把这些 URL 配到 Claude Desktop / Cursor 等 MCP 客户端即可使用"},servers:{title:"服务器管理"},settings:{title:"设置",language:"语言",account:"账户设置",password:"修改密码",appearance:"外观",routeConfig:"安全配置",installConfig:"安装",smartRouting:"智能路由",oauthServer:"OAuth"},groups:{title:"分组管理"},prompts:{title:"内置提示词"},resources:{title:"内置资源"},users:{title:"用户管理"},market:{title:"市场中心 - 本地市场和云端市场"},logs:{title:"系统日志"}},Es={filters:"筛选",search:"搜索日志...",autoScroll:"自动滚动",clearLogs:"清除日志",loading:"加载日志中...",noLogs:"暂无日志。",noMatch:"没有匹配当前筛选条件的日志。",mainProcess:"主进程",childProcess:"子进程",main:"主",child:"子"},Is={legacyVisibility:"历史组 — 请设置可见性",legacyVisibilityHint:"在您明确选择可见性之前,该组保留原有的端点访问规则。",visibilityDescription:"访问组内服务器还需具备对应服务器的权限。共享组不会共享私有服务器。仅所有者和管理员可管理此组。",shareAfterCreate:"请先保存组,再选择共享用户。",add:"添加",addNew:"添加新分组",edit:"编辑分组",delete:"删除",confirmDelete:"您确定要删除此分组吗?",deleteWarning:"删除分组 '{{name}}' 将会移除该分组及其所有服务器关联。此操作无法撤销。",name:"分组名称",namePlaceholder:"请输入分组名称",instructions:"说明",instructionsHelp:"可选。客户端连接此分组(包括 $smart/<group>)时作为 MCP instructions 发送;多数客户端会将其加入模型的系统提示。",instructionsPlaceholder:"例如:网页先用 fetch;失败时改用 firecrawl_scrape。",nameRequired:"分组名称不能为空",description:"描述",descriptionPlaceholder:"请输入分组描述(可选)",createError:"创建分组失败",updateError:"更新分组失败",deleteError:"删除分组失败",serverAddError:"向分组添加服务器失败",serverRemoveError:"从分组移除服务器失败",addServer:"添加服务器到分组",selectServer:"选择要添加的服务器",servers:"分组中的服务器",remove:"移除",noGroups:"暂无可用分组。创建一个新分组以开始使用。",noServers:"此分组中没有服务器。",noServerOptions:"没有可用的服务器",serverCount:"{{count}} 台服务器",toolSelection:"工具选择",promptSelection:"提示词选择",resourceSelection:"资源选择",toolsSelected:"选择",promptsSelected:"选择",resourcesSelected:"选择",allTools:"全部",allPrompts:"全部提示词",allResources:"全部资源",selectedTools:"选中的工具",selectedPrompts:"选中的提示词",selectedResources:"选中的资源",selectAll:"全选",selectNone:"全不选",configureTools:"配置工具",configureCapabilities:"配置工具、提示词和资源",alias:"对外名称",preserveToolNames:"保留原始工具名",preserveToolNamesHint:"工具名不添加服务器前缀,须在组内唯一。对外名称仍适用于提示词。",pinTool:"固定:始终在此分组的智能路由端点中与 search_tools 一同列出此工具",pinToolLabel:"固定到智能路由端点",unpinTool:"取消固定:仅通过 search_tools 访问此工具",previewPrompts:"[提示词: {{items}}]",previewResources:"[资源: {{items}}]",previewAllTools:"(全部工具)",previewAllPrompts:"(全部提示词)",previewAllResources:"(全部资源)",bulkSearch:"按名称或描述搜索…",bulkSearchLabel:"搜索{{capability}}",annotationFilter:"按注解筛选",allAnnotations:"所有注解",readOnlyHint:"只读提示",destructiveHint:"破坏性提示",idempotentHint:"幂等提示",flatList:"平铺列表",riskGroups:"风险分组",visibleCount:"显示 {{count}} / {{total}} 项",selectVisible:"选择可见项",deselectVisible:"取消可见项",invertVisible:"反选可见项",riskHint:"分组依据上游提示和名称推测,不保证安全性。操作仅影响筛选后的项目。",noMatchingItems:"没有匹配的项目",risk_read:"读取",risk_create:"创建",risk_update:"更新",risk_delete:"删除",risk_other:"其他 / 未分类"},Ns={title:"本地安装",official:"官方",by:"作者",unknown:"未知",tools:"工具",search:"搜索",searchPlaceholder:"搜索服务器名称、分类或标签",clearFilters:"清除",clearCategoryFilter:"",clearTagFilter:"",categories:"分类",tags:"标签",showTags:"显示标签",hideTags:"隐藏标签",moreTags:"",noServers:"未找到匹配的服务器",backToList:"返回列表",install:"安装",installing:"安装中...",installed:"已安装",installServer:"安装服务器: {{name}}",installSuccess:"服务器 {{serverName}} 安装成功",author:"作者",license:"许可证",repository:"代码仓库",examples:"示例",arguments:"参数",argumentName:"名称",description:"描述",required:"必填",example:"示例",viewSchema:"查看结构",fetchError:"获取本地市场服务器数据失败",serverNotFound:"未找到服务器",searchError:"搜索服务器失败",filterError:"按分类筛选服务器失败",tagFilterError:"按标签筛选服务器失败",noInstallationMethod:"该服务器没有可用的安装方法",showing:"显示 {{from}}-{{to}}/{{total}} 个服务器",perPage:"每页显示",confirmVariablesMessage:"请确保这些变量在运行环境中已正确定义。是否继续安装服务器?",confirmAndInstall:"确认并安装"},Os={authorizeTitle:"授权应用",authorizeSubtitle:"允许此应用访问您的 MCPHub 账号。",buttons:{approve:"允许访问",deny:"拒绝",approveSubtitle:"如果您信任此应用,建议选择允许。",denySubtitle:"您可以在之后随时再次授权。"},application:"应用程序",scopesTitle:"此应用程序将能够:",noScopes:"未请求任何权限。",requestInvalidTitle:"请求无效",requestInvalid:"此授权请求无效或已过期。请返回后重试。",grantingAccessTo:"将授予访问权限:",resourceAll:"所有 MCP 服务器",resourceSmart:"智能路由",resourceServer:"MCP 服务器:{{name}}",resourceGroup:"MCP 分组:{{name}}",clientId:"客户端 ID",willRedirectTo:"将重定向到:",policy:"隐私政策",terms:"服务条款",homepage:"主页"},Ms={title:"云端支持",subtitle:"由 MCPRouter 提供支持",by:"作者",server:"服务器",config:"配置",created:"创建时间",updated:"更新时间",available:"可用",description:"描述",details:"详细信息",tools:"工具",tool:"个工具",toolsAvailable:"{{count}} 个工具可用",loadingTools:"加载工具中...",noTools:"该服务器没有可用工具",noDescription:"无描述信息",viewDetails:"查看详情",parameters:"参数",result:"结果",error:"错误",callTool:"调用",calling:"调用中...",toolCallSuccess:"工具 {{toolName}} 执行成功",toolCallError:"调用工具 {{toolName}} 失败:{{error}}",viewSchema:"查看结构",backToList:"返回云端市场",search:"搜索",searchPlaceholder:"搜索云端服务器名称、标题或作者",clearFilters:"清除筛选",clearCategoryFilter:"清除",clearTagFilter:"清除",categories:"分类",tags:"标签",noCategories:"未找到分类",noTags:"未找到标签",noServers:"未找到云端服务器",fetchError:"获取云端服务器失败",serverNotFound:"未找到云端服务器",searchError:"搜索云端服务器失败",filterError:"按分类筛选云端服务器失败",tagFilterError:"按标签筛选云端服务器失败",showing:"显示 {{from}}-{{to}}/{{total}} 个云端服务器",perPage:"每页显示",apiKeyNotConfigured:"MCPRouter API 密钥未配置",apiKeyNotConfiguredDescription:"要使用云端服务器,您需要配置 MCPRouter API 密钥。",getApiKey:"获取 API 密钥",configureInSettings:"在设置中配置",installServer:"安装 {{name}}",installSuccess:"服务器 {{name}} 安装成功",installError:"安装服务器失败:{{error}}"},Ls={title:"注册中心",official:"官方",latest:"最新版本",description:"描述",website:"网站",repository:"代码仓库",packages:"安装包",package:"安装包",remotes:"远程服务",remote:"远程服务",published:"发布时间",updated:"更新时间",install:"安装",installing:"安装中...",installed:"已安装",installServer:"安装 {{name}}",installSuccess:"服务器 {{name}} 安装成功",installError:"安装服务器失败:{{error}}",noDescription:"无描述信息",viewDetails:"查看详情",backToList:"返回注册中心",search:"搜索",searchPlaceholder:"按名称搜索注册中心服务器",clearFilters:"清除",noServers:"未找到注册中心服务器",fetchError:"获取注册中心服务器失败",serverNotFound:"未找到注册中心服务器",showing:"显示 {{from}}-{{to}}/{{total}} 个注册中心服务器",perPage:"每页显示",environmentVariables:"环境变量",packageArguments:"安装包参数",runtimeArguments:"运行时参数",headers:"请求头"},zs={run:"运行",running:"运行中...",runTool:"运行",cancel:"取消",noDescription:"无描述信息",inputSchema:"输入模式:",runToolWithName:"运行工具:{{name}}",execution:"工具执行",successful:"成功",failed:"失败",result:"结果:",error:"错误",errorDetails:"错误详情:",noContent:"工具执行成功但未返回内容。",unknownError:"发生未知错误",jsonResponse:"JSON 响应:",toolResult:"工具结果",noParameters:"此工具不需要任何参数。",selectOption:"选择一个选项",enterValue:"输入{{type}}值",enabled:"已启用",enableSuccess:"工具 {{name}} 启用成功",disableSuccess:"工具 {{name}} 禁用成功",toggleFailed:"切换工具状态失败",descriptionUpdateSuccess:"工具描述更新成功",descriptionUpdateFailed:"更新工具描述失败",descriptionModifiedBadge:"已修改",defaultDescriptionLabel:"默认描述",visibleParams:"向模型展示的参数",visibleParamsHelp:"未勾选的参数会从模型收到的 schema 中移除,并从其调用参数中丢弃。必填参数(*)不能隐藏。",requiredParam:"必填参数不能隐藏",hiddenParamsFailed:"更新隐藏参数失败",defaultDescriptionTooltip:"默认描述:{{description}}",restoreDefault:"恢复默认值",restoreDefaultSuccess:"工具描述已恢复为默认值",restoreDefaultFailed:"恢复默认工具描述失败",parameters:"工具参数",formMode:"表单模式",jsonMode:"JSON 模式",jsonConfiguration:"JSON 配置",invalidJsonFormat:"无效的 JSON 格式",fixJsonBeforeSwitching:"请修复 JSON 格式后再切换到表单模式",item:"项目 {{index}}",addItem:"添加 {{key}} 项目",enterKey:"输入 {{key}}"},Us={run:"获取",running:"获取中...",result:"提示词结果",error:"提示词错误",execution:"提示词执行",successful:"成功",failed:"失败",errorDetails:"错误详情:",noContent:"提示词执行成功但未返回内容。",unknownError:"发生未知错误",jsonResponse:"JSON 响应:",description:"描述",messages:"消息",noDescription:"无描述信息",runPromptWithName:"获取提示词: {{name}}",descriptionUpdateSuccess:"提示词描述更新成功",descriptionUpdateFailed:"更新提示词描述失败",restoreDefault:"恢复默认值",restoreDefaultSuccess:"提示词描述已恢复为默认值",restoreDefaultFailed:"恢复默认提示词描述失败"},qs=JSON.parse('{"dashboardName":"控制台名称","dashboardNameDescription":"显示在侧栏、页头、登录页和浏览器标签中。留空恢复默认名称。","dashboardNameSaveFailed":"保存控制台名称失败","resetBearerKey":"重置 Bearer key","resetBearerKeyConfirm":"确认重置此 Bearer key?原 token 将立即失效,权限和启用状态保持不变。","resetBearerKeySuccess":"Bearer key 已重置。请在关闭前复制并保存新 token,之后将不再显示。","resetBearerKeyError":"重置 Bearer key 失败","allowRegistration":"允许自助注册","allowRegistrationDescription":"允许访客从登录页创建普通账号。默认关闭;禁用密码登录时不可用。","allowedCidrs":"允许访问的上游 CIDR 范围","allowedCidrsDescription":"每行一个 IPv4 或 IPv6 CIDR。所有用户均可连接这些范围内的上游 MCP、OpenAPI 和 OAuth 端点。留空表示不额外放行。管理员拥有的服务器仍可访问所有内网地址。请按需配置,避免过大的范围以及元数据或回环地址。修改对新请求生效,不会关闭已有连接。","allowedCidrsUpdateFailed":"更新 CIDR 白名单失败","subtitle":"配置系统设置、认证、路由及 MCP 服务器集成。","enableGlobalRoute":"启用全局路由","enableGlobalRouteDescription":"允许不指定组 ID 就连接到 /sse 端点","enableGroupNameRoute":"启用组名路由","enableGroupNameRouteDescription":"允许使用组名而不仅仅是组 ID 连接到 /sse 端点","enableBearerAuth":"启用 Bearer 认证","enableBearerAuthDescription":"对 MCP 端点启用 Bearer 令牌认证(默认开启)","bearerAuthKey":"Bearer 认证密钥","bearerAuthKeyDescription":"Bearer 令牌中需要携带的认证密钥","bearerAuthKeyPlaceholder":"请输入 Bearer 认证密钥","bearerAuthHeaderName":"Bearer 认证请求头名称","bearerAuthHeaderNameDescription":"用于接收 MCP Bearer 凭证的请求头名称。当上游透传头也使用 Authorization 时,可改成其它名称以避免冲突。","bearerAuthHeaderNamePlaceholder":"例如:Authorization 或 X-MCP-Authorization","bearerKeysSectionTitle":"密钥","bearerKeysSectionDescription":"管理多条密钥,并为不同密钥配置不同的访问范围。","bearerKeyScopeFilter":"访问范围筛选","noBearerKeys":"当前还没有配置任何密钥。","bearerKeyName":"名称","bearerKeyToken":"密钥值","bearerKeyEnabled":"启用","bearerKeyAccessType":"访问范围","bearerKeyAccessAll":"全部","bearerKeyAccessGroups":"指定分组","bearerKeyAccessServers":"指定服务器","bearerKeyAccessCustom":"自定义","bearerKeyAllowedGroups":"允许访问的分组","bearerKeyAllowedServers":"允许访问的服务器","addBearerKey":"新增密钥","addBearerKeyButton":"创建","bearerKeyRequired":"名称和密钥值为必填项","bearerKeyNameRequired":"名称为必填项","bearerKeyOwnerRequired":"请选择所属用户","bearerKeyKind":"密钥类型","bearerKeyKindSystem":"系统级","bearerKeyKindUser":"用户级","bearerKeyOwner":"所属用户","bearerKeySelectOwner":"请选择用户...","bearerKeyAccessUserVisibility":"继承用户可见性","bearerKeyShownOnce":"请立即复制此密钥,之后将不再显示。","deleteBearerKeyConfirm":"确定要删除这条密钥吗?","generate":"生成","selectGroups":"选择分组","selectServers":"选择服务器","selectAtLeastOneGroup":"请至少选择一个分组","selectAtLeastOneServer":"请至少选择一个服务器","skipAuth":"免登录开关","skipAuthDescription":"允许仪表盘免登录;未认证用户将获得 guest 管理员访问权限(不影响 MCP 端点认证)","jsonBodyLimit":"JSON 请求体大小限制","jsonBodyLimitDescription":"Express JSON 请求体大小限制,大型 OpenAPI schema 上传也会受此配置影响。","jsonBodyLimitPlaceholder":"例如:1mb、5mb、1024kb","pythonIndexUrl":"Python 包仓库地址","pythonIndexUrlDescription":"设置 UV_DEFAULT_INDEX 环境变量,用于 Python 包安装","pythonIndexUrlPlaceholder":"例如: https://pypi.org/simple","npmRegistry":"NPM 仓库地址","npmRegistryDescription":"设置 npm_config_registry 环境变量,用于 NPM 包安装","npmRegistryPlaceholder":"例如: https://registry.npmjs.org/","baseUrl":"基础地址","baseUrlDescription":"用于 MCP 请求与 OAuth 回调的基础地址","baseUrlPlaceholder":"例如: http://localhost:3000","installConfig":"安装配置","clearCache":"清除包缓存","clearCacheDescription":"清除 npm 和 uv 包缓存。服务器在下次启动时可能需要重新下载包。","clearCacheConfirm":"这将清除 npm 和 uv 包缓存。服务器在下次启动时可能需要重新下载包。","clearCacheSuccess":"包缓存清除成功","clearCacheError":"清除包缓存失败","clearCacheSkipped":"未安装","clearingCache":"清除中...","systemConfigUpdated":"系统配置更新成功","noChanges":"没有需要保存的更改","betterAuthTitle":"Better Auth","betterAuthEnvNote":"客户端 ID 和密钥仍然来自环境变量。修改 Better Auth 设置后可能需要重启应用;同时,安装配置中的基础地址来源会自动加入受信任来源。","enableBetterAuth":"启用 Better Auth","enableBetterAuthDescription":"当所需环境变量配置完成后,启用社交登录和 OIDC 登录。","disablePasswordLogin":"禁用密码登录","disablePasswordLoginDescription":"仅允许通过 SSO 提供商登录:用户名/密码表单和 POST /api/auth/login 将被关闭。仅在至少启用一个提供商且应用启动时已启用时生效。BETTER_AUTH_DISABLE_PASSWORD_LOGIN 优先于此设置;当身份提供商不可用时,将其设为 false 即可恢复登录。","betterAuthBaseUrl":"基础地址","betterAuthBaseUrlDescription":"用于生成 Better Auth 回调 URL 的公网访问地址。留空时回退到安装配置中的基础地址;BETTER_AUTH_URL 环境变量优先级更高。","betterAuthBasePath":"认证基础路径","betterAuthBasePathDescription":"Better Auth 路由使用的相对 API 路径。","betterAuthTrustedOrigins":"受信任来源","betterAuthTrustedOriginsDescription":"允许 Better Auth 请求使用的来源,多个值请用逗号分隔。安装配置中的基础地址来源会自动加入。","betterAuthProviders":"登录提供方","betterAuthProvidersDescription":"这些开关用于控制登录页上展示哪些已配置的登录方式。","betterAuthGoogleDescription":"需要配置 GOOGLE_CLIENT_ID 和 GOOGLE_CLIENT_SECRET。","betterAuthGithubDescription":"需要配置 GITHUB_CLIENT_ID 和 GITHUB_CLIENT_SECRET。","betterAuthOidcDescription":"需要配置 OIDC 客户端凭据以及 discovery URL。","betterAuthOidcProviderId":"OIDC 提供方 ID","betterAuthOidcProviderIdDescription":"启动 OIDC 登录流程时使用的提供方标识。","betterAuthOidcDiscoveryUrl":"OIDC Discovery URL","betterAuthOidcDiscoveryUrlDescription":"由身份提供方发布的 OpenID Connect 配置地址。","betterAuthOidcScopes":"OIDC Scopes","betterAuthOidcScopesDescription":"OIDC 登录流程中请求的作用域,多个值请用逗号分隔。","betterAuthOidcPrompt":"OIDC Prompt","betterAuthOidcPromptDescription":"可选的 prompt 参数,会发送给身份提供方,例如 login 或 consent。","betterAuthOidcPkce":"启用 PKCE","betterAuthOidcPkceDescription":"为 OIDC 授权流程启用 PKCE。","enableSmartRouting":"启用智能路由","enableSmartRoutingDescription":"开启智能路由功能,根据输入自动搜索最合适的工具(使用 $smart 分组)","dbUrl":"PostgreSQL 连接地址(必须支持 pgvector)","dbUrlPlaceholder":"例如: postgresql://user:password@localhost:5432/dbname","embeddingProvider":"嵌入提供方","embeddingProviderPreset":"提供方预设","embeddingProviderPresetDescription":"选择提供方后自动填充 OpenAI 兼容的接口地址和模型。","embeddingProviderPresetOpenai":"OpenAI","embeddingProviderPresetOpenrouter":"OpenRouter","embeddingProviderPresetSiliconflow":"SiliconFlow · 免费额度(1000 RPM)","embeddingProviderPresetGemini":"Google Gemini · 免费额度(100 RPM)","embeddingProviderPresetCustom":"其他 / OpenAI 兼容服务","llmProviderBaseUrl":"OpenAI 兼容基础地址","llmProviderBaseUrlPlaceholder":"https://api.openai.com/v1","llmProviderApiKey":"LLM 提供商 API 密钥","llmProviderApiKeyDescription":"用于访问嵌入服务的 API 密钥","llmProviderApiKeyPlaceholder":"请输入 LLM 提供商 API 密钥","smartRoutingEnvOverrideWarning":"当前实际使用的是环境变量 {{envVar}},此处保存的值在运行时不会生效。","embeddingModel":"嵌入模型名称","embeddingModelPlaceholder":"text-embedding-3-small","basePacingDelayMs":"基础节流延迟(毫秒)","basePacingDelayMsDescription":"向嵌入服务提供方发送请求之间的基础等待时间。默认为 0 — 系统自动管理限流:优先遵守 Retry-After 响应头,若无该头则等待 63 秒,并在每次 403/429 后自动提高节流延迟。仅当提供方要求固定最小请求间隔时才需设置非零值。","basePacingDelayMsPlaceholder":"留空 = 默认 0 毫秒","basePacingDelayMsAuto":"默认({{value}} 毫秒):限流由系统自动管理。","basePacingDelayMsZero":"0 毫秒(默认):限流通过自适应节流和重试逻辑自动管理。","basePacingDelayMsOverride":"自定义值:覆盖默认的基础节流延迟。","embeddingEncodingFormat":"嵌入编码格式","embeddingEncodingFormatDescription":"嵌入向量的编码格式。自动模式会根据服务商支持情况自动选择。","embeddingEncodingFormatAuto":"自动(推荐)","embeddingDimensions":"嵌入维度","embeddingDimensionsDescription":"支持该参数的提供方可自定义输出维度。留空则使用模型默认值。","embeddingDimensionsPlaceholder":"留空 = 模型默认值","embeddingDimensionsApiPassthrough":"向 API 转发 dimensions 参数(MRL 透传)","embeddingDimensionsApiPassthroughDescription":"仅已知支持 Matryoshka(MRL)的模型会收到 dimensions 参数。如使用其他支持 MRL 的模型,可开启此选项强制转发。非 MRL 模型(Qwen3-Embedding、BGE、vLLM/sglang 等)会直接拒绝该参数,请保持关闭。","azureOpenaiEndpoint":"Azure OpenAI 终端地址","azureOpenaiEndpointPlaceholder":"https://YOUR_RESOURCE_NAME.openai.azure.com","azureOpenaiApiKey":"Azure OpenAI API 密钥","azureOpenaiApiKeyPlaceholder":"请输入 Azure OpenAI API 密钥","azureOpenaiApiVersion":"Azure OpenAI API 版本","azureOpenaiApiVersionPlaceholder":"2024-02-15-preview","azureOpenaiEmbeddingDeployment":"Azure OpenAI 嵌入部署","azureOpenaiEmbeddingDeploymentPlaceholder":"text-embedding-3-small","azureOpenaiEmbeddingModel":"Azure 嵌入模型名称","azureOpenaiEmbeddingModelDescription":"在 Azure 中部署的实际 OpenAI 模型名称(例如 text-embedding-3-small),用于在发送请求前准确进行 Token 计数。","azureOpenaiEmbeddingModelPlaceholder":"text-embedding-3-small","progressiveDisclosure":"渐进式披露","progressiveDisclosureDescription":"开启后,search_tools 只返回工具名称和描述,通过 describe_tool 获取完整参数定义,可减少 Token 消耗","embeddingMaxTokens":"最大嵌入 Token 数","embeddingMaxTokensDescription":"生成嵌入前截断文本的最大 Token 数。留空将自动使用模型默认值。设置自定义值将始终覆盖模型默认值。当使用本地 LLM 提供商时,手动设置此值特别有用,可防止截断错误。","embeddingMaxTokensPlaceholder":"留空 = 自动(按模型)","embeddingMaxTokensAuto":"自动:{{limit}} tokens({{model}} 的模型默认值)","embeddingMaxTokensOverride":"此值将覆盖模型默认值。","embeddingPrefixes":"嵌入任务前缀","embeddingPrefixesDescription":"在生成嵌入前添加到文本开头,适用于使用任务前缀训练的非对称检索模型(如 EmbeddingGemma、E5、Nomic)。对于期望原始文本的模型,请将两者留空。请包含末尾的空格。修改文档前缀会重新生成所有工具的嵌入。","embeddingQueryPrefix":"查询前缀","embeddingDocumentPrefix":"文档前缀","searchResults":"搜索结果","searchResultsDescription":"search_tools 如何过滤和返回匹配结果。每个结果都附带相似度分数。两项均留空即使用默认值。","similarityThreshold":"相似度阈值(0-1)","similarityThresholdPlaceholder":"留空 = 按查询长度(0.2 / 0.3 / 0.4)","fullSchemaTopN":"前 N 个结果返回完整 schema","fullSchemaTopNPlaceholder":"留空 = 全部结果;其余结果通过 describe_tool 获取","toolDefinitionFields":"结果中的工具字段","toolDefinitionFieldsDescription":"search_tools 和 describe_tool 结果在名称、描述和 inputSchema 之外附带的可选字段。默认:title 和 annotations。其余字段主要供客户端使用,可能很大(图标是 base64 图片)。","invalidSearchSettings":"{{fields}} 的值无效。相似度阈值必须在 0 到 1 之间,N 必须是大于或等于 0 的整数。","smartRoutingConfigUpdated":"智能路由配置更新成功","smartRoutingRequiredFields":"启用智能路由需要填写数据库连接地址。LLM 提供商 API 密钥仅在使用云端提供商时才需要(本地 LLM 通常不需要 API 密钥,可输入任意值通过表单验证)","smartRoutingValidationError":"启用智能路由前请先填写必要字段:{{fields}}","smartRoutingWorkflow":"工作流","smartRoutingWorkflowDescription":"用户的 prompt 经向量化后,在 pgvector 中检索 top-k 相似工具,仅暴露给上游 LLM。","toolResultCompressionTitle":"工具结果压缩","toolResultCompressionEnable":"启用压缩","toolResultCompressionDescription":"在大型文本工具结果到达 MCP 客户端前进行压缩。改动会在下一次工具调用生效。","toolResultCompressionStrategy":"策略","toolResultCompressionStrategyDescription":"自动检测 JSON、日志、搜索结果、diff 和纯文本。","toolResultCompressionMinTokens":"最小 Token 数","toolResultCompressionMinTokensDescription":"仅压缩达到或超过此大小的文本块。","toolResultCompressionMaxOutputTokens":"输出 Token 预算","toolResultCompressionMaxOutputTokensDescription":"每个压缩后文本块的目标最大 Token 数。","mcpRouterConfig":"云端市场","mcpRouterApiKey":"MCPRouter API 密钥","mcpRouterApiKeyDescription":"用于访问 MCPRouter 云端市场服务的 API 密钥","mcpRouterApiKeyPlaceholder":"请输入 MCPRouter API 密钥","mcpRouterReferer":"引用地址","mcpRouterRefererDescription":"MCPRouter API 请求的引用地址头","mcpRouterRefererPlaceholder":"https://www.mcphub.app","mcpRouterTitle":"标题","mcpRouterTitleDescription":"MCPRouter API 请求的标题头","mcpRouterTitlePlaceholder":"MCPHub","mcpRouterBaseUrl":"基础地址","mcpRouterBaseUrlDescription":"MCPRouter API 的基础地址","mcpRouterBaseUrlPlaceholder":"https://api.mcprouter.to/v1","systemSettings":"系统设置","nameSeparatorLabel":"名称分隔符","nameSeparatorDescription":"用于分隔服务器名称和工具/提示名称(默认:-)","enableSessionRebuild":"启用服务端会话重建","enableSessionRebuildDescription":"开启后会应用服务端会话重建的改进代码,提供更好的会话管理体验","storeToolPayload":"存储工具调用内容","storeToolPayloadDescription":"开启后,每次工具调用的完整输入和输出都会记录到活动日志中。工具内容会原样存储、不做脱敏;如果工具参数可能包含敏感数据且不应持久化,请关闭此项。","storeToolPayloadUpdateFailed":"更新工具内容存储设置失败","restartRequired":"配置已保存。为确保所有服务正确加载新设置,建议重启应用。","exportMcpSettings":"导出配置","mcpSettingsJson":"MCP 配置 JSON","mcpSettingsJsonDescription":"查看、复制或下载当前的 mcp_settings.json 配置,可用于备份或迁移到其他工具","copyToClipboard":"复制到剪贴板","downloadJson":"下载 JSON","exportSuccess":"配置导出成功","exportError":"获取配置失败","enableOauthServer":"启用 OAuth 服务器","enableOauthServerDescription":"允许 MCPHub 作为 OAuth 2.0 授权服务器向外部客户端签发令牌","requireClientSecret":"需要客户端密钥","requireClientSecretDescription":"开启后,保密客户端必须携带 client secret(如需仅使用 PKCE 的公共客户端可关闭)","requireState":"要求 state 参数","requireStateDescription":"拒绝未携带 state 参数的授权请求","accessTokenLifetime":"访问令牌有效期(秒)","accessTokenLifetimeDescription":"控制访问令牌可使用的时长","accessTokenLifetimePlaceholder":"例如:3600","refreshTokenLifetime":"刷新令牌有效期(秒)","refreshTokenLifetimeDescription":"控制刷新令牌的过期时间","refreshTokenLifetimePlaceholder":"例如:1209600","authorizationCodeLifetime":"授权码有效期(秒)","authorizationCodeLifetimeDescription":"授权码在被兑换前可保持有效的时间","authorizationCodeLifetimePlaceholder":"例如:300","allowedScopes":"允许的作用域","allowedScopesDescription":"使用逗号分隔的作用域列表,在授权时展示给用户","allowedScopesPlaceholder":"例如:read, write","enableDynamicRegistration":"启用动态客户端注册","dynamicRegistrationDescription":"允许遵循 RFC 7591 的客户端通过公共端点自行注册","dynamicRegistrationAllowedGrantTypes":"允许的授权类型","dynamicRegistrationAllowedGrantTypesDescription":"使用逗号分隔动态注册客户端可以使用的授权类型","dynamicRegistrationAllowedGrantTypesPlaceholder":"例如:authorization_code, refresh_token","dynamicRegistrationAuth":"注册需要认证","dynamicRegistrationAuthDescription":"开启后,注册端点需要认证请求才能创建客户端","invalidNumberInput":"请输入合法的非负数字","dynamicRegistrationClientTtl":"空闲客户端清理 TTL(秒)","dynamicRegistrationClientTtlDescription":"回收超过此时长、且没有活跃令牌和进行中授权流程的动态注册客户端。设为 0 可禁用清理。","dynamicRegistrationClientTtlPlaceholder":"例如 2592000","smartRoutingIndexTitle":"向量索引与诊断","smartRoutingIndexRefresh":"刷新","smartRoutingIndexReindex":"重新索引","smartRoutingIndexReindexing":"重建中…","smartRoutingIndexLoading":"加载中…","smartRoutingIndexNoData":"暂无索引数据。请先启用智能路由,再点击“重新索引”构建向量库。","smartRoutingIndexStatsUnavailable":"统计数据不可用","smartRoutingIndexDatabase":"数据库","smartRoutingIndexConnected":"已连接","smartRoutingIndexDisconnected":"未连接","smartRoutingIndexUnhealthy":"不健康","smartRoutingIndexModel":"模型","smartRoutingIndexDimensions":"维度","smartRoutingIndexTotalRows":"总行数","smartRoutingIndexToolRows":"工具行数","smartRoutingIndexServerRows":"服务器行数","smartRoutingIndexClusterLabel":"已索引服务器","smartRoutingIndexCoverage":"覆盖率","smartRoutingIndexLastSynced":"最近同步","smartRoutingIndexPerServer":"每台服务器的工具数","smartRoutingIndexMissingIndex":"有 {{count}} 台已启用服务器缺少索引","smartRoutingIndexSyncedRange":"同步范围:{{oldest}} → {{newest}}","smartRoutingIndexReindexDone":"重新索引完成:同步 {{synced}} 台,失败 {{failed}} 台,跳过 {{skipped}} 台,共 {{total}} 个工具","smartRoutingIndexReindexFailed":"重新索引失败:{{message}}","smartRoutingIndexReindexStarting":"开始重建…","smartRoutingIndexReindexingServer":"正在重建“{{server}}”","smartRoutingIndexReindexSummary":"重建完成 · 同步 {{synced}} 台,失败 {{failed}} 台,跳过 {{skipped}} 台,共 {{total}} 个工具","smartRoutingIndexReindexConfirmTitle":"确认重建向量索引?","smartRoutingIndexReindexConfirmMessage":"将清空所有现有向量并从头重新生成。此操作可能需要较长时间,并会消耗 embedding API 额度。","smartRoutingIndexPersonalCredentials":"需个人凭据的服务器","smartRoutingIndexSkippedReason":"已跳过","smartRoutingIndexIndexedAs":"以 {{principals}} 的身份索引","toolPolicies":{"missingReferences":"部分规则引用的 ID 在已加载的服务器、密钥或分组中不存在。无法匹配的拒绝规则不能提供保护,无法匹配的允许规则可能阻止访问。保存前请核对;仍可保存用于预先配置资源的规则。","missingReference":"规则 {{policyId}}:未找到 {{selector}} {{value}}。","title":"工具访问策略","description":"规则用于工具发现和调用(包括智能路由),保存后立即生效。","semantics":"留空的选择器匹配所有主体或目标;同一规则的条件必须全部满足。适用于主体的允许规则构成允许列表,匹配的拒绝规则优先。策略不能扩大现有权限。","empty":"尚未配置策略,沿用现有访问权限。","rule":"规则 {{number}}","id":"规则 ID(必填且唯一)","effect":"效果","allow":"允许","deny":"拒绝","username":"用户名","keyId":"Bearer 密钥 ID","groupId":"端点分组 ID","serverId":"服务器 ID","tool":"上游原始工具名","any":"不限","selectorsHint":"可选择建议值或输入精确值。ID 不受重命名影响。分组指端点分组,而非服务器所属分组。工具名区分大小写,不含网关前缀,不支持通配符。","add":"新增规则","save":"保存策略","unsaved":"有未保存的变更。新增和删除仅在保存后生效。","invalid":"规则 ID 必须非空且唯一,效果必须有效;可选条件不能仅包含空白字符。","saveFailed":"保存策略失败,已保留你的修改。","confirm":"立即应用这 {{count}} 条策略?这可能改变调用者可发现和调用的工具。","confirmClear":"删除全部策略?访问将恢复为现有权限控制。","deleteRule":"删除规则 {{number}}","retry":"重试"}}'),Bs={upload:"上传",uploadTitle:"上传 MCPB 文件",dropFileHere:"将 .mcpb 文件拖拽到此处",orClickToSelect:"或点击从计算机选择",invalidFileType:"请选择有效的 .mcpb 文件",noFileSelected:"请选择要上传的 .mcpb 文件",uploading:"上传中...",uploadFailed:"上传 MCPB 文件失败",installServer:"从 MCPB 安装 MCP 服务器",extensionInfo:"扩展信息",name:"名称",version:"版本",description:"描述",author:"作者",tools:"工具",serverName:"服务器名称",serverNamePlaceholder:"为此服务器输入名称",install:"安装",installing:"安装中...",installFailed:"从 MCPB 安装服务器失败",serverExistsTitle:"服务器已存在",serverExistsConfirm:"服务器 '{{serverName}}' 已存在。是否要用新版本覆盖它?",override:"覆盖"},Fs={button:"导入",title:"从 JSON 导入服务器",inputLabel:"服务器配置 JSON",inputHelp:"粘贴您的服务器配置 JSON。支持 STDIO、SSE 和 HTTP (streamable-http) 服务器类型。",preview:"预览",previewTitle:"预览要导入的服务器",import:"导入",importing:"导入中...",invalidFormat:"无效的 JSON 格式。JSON 必须包含 'mcpServers' 对象。",parseError:"解析 JSON 失败。请检查格式后重试。",addFailed:"添加服务器失败",importFailed:"导入服务器失败",partialSuccess:"成功导入 {{count}} / {{total}} 个服务器。部分服务器失败:",validationErrors:"部分服务器无法导入。请修正以下问题后重试:"},Ks={button:"导入",title:"从 JSON 导入分组",inputLabel:"分组配置 JSON",inputHelp:"粘贴您的分组配置 JSON。每个分组可以包含一个服务器列表。",preview:"预览",previewTitle:"预览要导入的分组",import:"导入",importing:"导入中...",invalidFormat:"无效的 JSON 格式。JSON 必须包含 'groups' 数组。",missingName:"每个分组必须有 'name' 字段。",parseError:"解析 JSON 失败。请检查格式后重试。",addFailed:"添加分组失败",importFailed:"导入分组失败",partialSuccess:"成功导入 {{count}} / {{total}} 个分组。部分分组失败:"},js={add:"添加",addNew:"添加新用户",edit:"编辑用户",delete:"删除用户",create:"创建",update:"更新",username:"用户名",email:"邮箱",emailPlaceholder:"输入邮箱(可选)",password:"密码",newPassword:"新密码",confirmPassword:"确认密码",changePassword:"修改密码",adminRole:"管理员",admin:"管理员",user:"用户",role:"角色",actions:"操作",addFirst:"添加第一个用户",permissions:"权限",adminPermissions:"完全系统访问权限",userPermissions:"受限访问权限",currentUser:"当前用户",noUsers:"没有找到用户",adminRequired:"需要管理员权限才能管理用户",usernameRequired:"用户名是必需的",passwordRequired:"密码是必需的",passwordTooShort:"密码至少需要6个字符",passwordMismatch:"密码不匹配",usernamePlaceholder:"输入用户名",passwordPlaceholder:"输入密码",newPasswordPlaceholder:"留空保持当前密码",confirmPasswordPlaceholder:"确认新密码",createError:"创建用户失败",updateError:"更新用户失败",deleteError:"删除用户失败",statsError:"获取用户统计失败",deleteConfirmation:"您确定要删除用户 '{{username}}' 吗?此操作无法撤消。",confirmDelete:"删除用户",deleteWarning:"您确定要删除用户 '{{username}}' 吗?此操作无法撤消。"},Gs={errors:{readonly:"演示环境无法修改数据",invalid_credentials:"用户名或密码错误",password_login_disabled:"已禁用密码登录。请使用 SSO 登录,或使用 Bearer 密钥访问 API。",serverNameRequired:"服务器名称是必需的",serverConfigRequired:"服务器配置是必需的",serverConfigInvalid:"服务器配置必须包含 URL、OpenAPI 规范 URL 或模式,或者带参数的命令",serverTypeInvalid:"服务器类型必须是以下之一:stdio、sse、streamable-http、openapi",urlRequiredForType:"{{type}} 服务器类型需要 URL",openapiSpecRequired:"openapi 服务器类型需要 OpenAPI 规范 URL 或模式",headersInvalidFormat:"请求头必须是对象格式",headersNotSupportedForStdio:"stdio 服务器类型不支持请求头",serverNotFound:"找不到服务器",failedToRemoveServer:"找不到服务器或删除失败",internalServerError:"服务器内部错误",failedToGetServers:"获取服务器信息失败",failedToGetServerSettings:"获取服务器设置失败",failedToGetServerConfig:"获取服务器配置失败",failedToSaveSettings:"保存设置失败",toolNameRequired:"服务器名称和工具名称是必需的",descriptionMustBeString:"描述必须是字符串",groupIdRequired:"分组 ID 是必需的",groupNameRequired:"分组名称是必需的",groupNotFound:"找不到分组",groupIdAndServerNameRequired:"分组 ID 和服务器名称是必需的",groupOrServerNotFound:"找不到分组或服务器",toolsMustBeAllOrArray:'工具必须是 "all" 或字符串数组',serverNameAndToolNameRequired:"服务器名称和工具名称是必需的",usernameRequired:"用户名是必需的",userNotFound:"找不到用户",failedToGetUsers:"获取用户信息失败",failedToGetUserInfo:"获取用户信息失败",failedToGetUserStats:"获取用户统计信息失败",marketServerNameRequired:"服务器名称是必需的",marketServerNotFound:"找不到市场服务器",failedToGetMarketServers:"获取市场服务器信息失败",failedToGetMarketServer:"获取市场服务器信息失败",failedToGetMarketCategories:"获取市场类别失败",failedToGetMarketTags:"获取市场标签失败",failedToSearchMarketServers:"搜索市场服务器失败",failedToFilterMarketServers:"过滤市场服务器失败",failedToProcessMcpbFile:"处理 MCPB 文件失败"},success:{serverCreated:"服务器创建成功",serverUpdated:"服务器更新成功",serverRemoved:"服务器删除成功",serverToggled:"服务器状态切换成功",toolToggled:"工具 {{name}} {{action}} 成功",toolDescriptionUpdated:"工具 {{name}} 描述更新成功",systemConfigUpdated:"系统配置更新成功",groupCreated:"分组创建成功",groupUpdated:"分组更新成功",groupDeleted:"分组删除成功",serverAddedToGroup:"服务器添加到分组成功",serverRemovedFromGroup:"服务器从分组移除成功",serverToolsUpdated:"服务器工具更新成功"}},Hs={authorizationFailed:"授权失败",authorizationFailedError:"错误",authorizationFailedDetails:"详情",invalidRequest:"无效请求",missingStateParameter:"缺少必需的 OAuth 状态参数。",missingCodeParameter:"缺少必需的授权码参数。",serverNotFound:"服务器未找到",serverNotFoundMessage:"无法找到与此授权请求关联的服务器。",sessionExpiredMessage:"授权会话可能已过期。请重新进行授权。",authorizationSuccessful:"授权成功",server:"服务器",status:"状态",connected:"已连接",successMessage:"服务器已成功授权并连接。",autoCloseMessage:"此窗口将在 3 秒后自动关闭...",closeNow:"立即关闭",connectionError:"连接错误",connectionErrorMessage:"授权成功,但连接服务器失败。",reconnectMessage:"请尝试从控制面板重新连接。",configurationError:"配置错误",configurationErrorMessage:"服务器传输不支持 OAuth finishAuth()。请确保服务器配置为 streamable-http 传输。",internalError:"内部错误",internalErrorMessage:"处理 OAuth 回调时发生意外错误。",closeWindow:"关闭窗口"},_s={add:"添加提示词",addNew:"添加新提示词",edit:"编辑提示词",delete:"删除",noPrompts:"暂无内置提示词",addFirst:"添加第一个提示词",name:"名称",namePlaceholder:"例如 code-review",title:"标题",titlePlaceholder:"例如 代码审查提示词",description:"描述",descriptionPlaceholder:"提示词的简要描述",template:"模板",templatePlaceholder:"输入包含 {{parameter}} 占位符的模板文本...",templateHint:"使用 {{paramName}} 作为模板参数",arguments:"参数",addArgument:"添加参数",argName:"名称",argDescription:"描述",argRequired:"必填",enabled:"启用",active:"已启用",inactive:"已禁用",nameRequired:"名称为必填项",templateRequired:"模板为必填项",fetchError:"加载内置提示词失败",createError:"创建提示词失败",updateError:"更新提示词失败",deleteError:"删除提示词失败",saveError:"保存提示词失败",confirmDelete:"删除提示词",deleteWarning:'确定要删除提示词 "{{name}}" 吗?此操作无法撤销。'},Vs={add:"添加资源",addNew:"添加新资源",edit:"编辑资源",delete:"删除",noResources:"暂无内置资源",addFirst:"添加第一个资源",uri:"URI",uriPlaceholder:"例如 resource://docs/guide",name:"名称",namePlaceholder:"例如 用户指南",description:"描述",descriptionPlaceholder:"资源的简要描述",mimeType:"MIME 类型",content:"内容",contentPlaceholder:"输入资源内容...",enabled:"启用",active:"已启用",inactive:"已禁用",descriptionUpdateSuccess:"资源描述更新成功",descriptionUpdateFailed:"更新资源描述失败",restoreDefault:"恢复默认值",restoreDefaultSuccess:"资源描述已恢复为默认值",restoreDefaultFailed:"恢复默认资源描述失败",uriRequired:"URI 为必填项",contentRequired:"内容为必填项",fetchError:"加载内置资源失败",createError:"创建资源失败",updateError:"更新资源失败",deleteError:"删除资源失败",saveError:"保存资源失败",confirmDelete:"删除资源",deleteWarning:'确定要删除资源 "{{name}}" 吗?此操作无法撤销。'},$s={title:"活动",totalCalls:"总调用次数",successCount:"成功次数",errorCount:"失败次数",avgDuration:"平均耗时",timestamp:"时间",server:"服务器",tool:"工具",duration:"耗时",status:"状态",group:"分组",user:"用户",key:"API密钥",sourceIp:"来源IP",input:"输入",output:"输出",details:"活动详情",errorMessage:"错误信息",searchServer:"服务器...",searchTool:"工具...",searchStatus:"状态...",searchGroup:"分组...",searchUsername:"用户...",searchKeyName:"API密钥...",keyName:"API密钥名称",allStatus:"全部状态",statusSuccess:"成功",statusError:"失败",noData:"暂无活动数据",fetchError:"加载活动数据失败",cleanup:"清理",confirmCleanup:"确定要删除30天前的活动记录吗?",cleanupSuccess:"已删除 {{count}} 条旧记录",cleanupError:"清理旧记录失败",notAvailable:"活动跟踪功能仅在数据库模式下可用"},Js={exportButton:"导出模板",importButton:"导入模板",exportTitle:"导出配置模板",importTitle:"导入配置模板",name:"模板名称",nameRequired:"模板名称不能为空",namePlaceholder:"例如:前端开发工具",description:"描述",descriptionPlaceholder:"例如:前端开发标准 MCP 服务器集合",selectGroups:"选择分组",selectGroupsHelp:"留空则导出全部分组",selectAll:"全选",deselectAll:"取消全选",includeDisabled:"包含已禁用的服务器",exportNote:"密钥(API Key、Token、密码等)将被替换为 ${PLACEHOLDER} 占位符。接收者需要提供自己的凭据。",export:"导出",exporting:"导出中...",exportFailed:"导出模板失败",import:"导入",importing:"导入中...",importFailed:"导入模板失败",invalidFormat:"模板格式无效。必须包含 version、name、servers 和 groups 字段。",parseError:"JSON 解析失败,请检查格式后重试。",uploadFile:"上传模板文件",or:"或",pasteJson:"粘贴模板 JSON",pastePlaceholder:"在此粘贴 .mcphub-template.json 内容...",version:"版本",createdAt:"创建时间",servers:"服务器",groups:"分组",serversInGroup:"个服务器",envVarsNeeded:"所需环境变量 — 请在使用导入的服务器前设置这些变量:",importResult:"服务器:创建 {{serversCreated}} 个,跳过 {{serversSkipped}} 个。分组:创建 {{groupsCreated}} 个,跳过 {{groupsSkipped}} 个。"},Ws={exposed:"已暴露",gross:"总量",estimate:"预估 Token 数(cl100k)— 近似值",direct:"直接",smartRouting:"智能路由",smartRoutingPd:"智能路由 + 渐进式披露",smartRoutingPdHint:"添加 describe_tool 元工具 — 前期成本较高,但每次搜索的响应更小",saved:"减少 {{percent}}%",notConnected:"未连接",connectedOf:"{{total}} 个服务器中已连接 {{connected}} 个",totalFootprint:"上下文占用"},Ys={title:"凭据",missing:"服务器“{{serverName}}”需要个人凭据。请在控制台 → 凭据中绑定所有必需字段。",description:"为共享服务器绑定自己的凭据。每次请求使用当前调用用户的凭据。",slots:"个人凭据字段",slotsHint:"仅声明字段名。所有字段均需用户绑定,缺失时不会回退到组织凭据。",target:"凭据目标",urlHint:"URL 槽请将 {{placeholder}} 放在完整的主机标签或路径段位置,并在下方填写允许值。",allowed:"允许的值(每行一个)",argsHint:"参数字段请在参数中使用 {{placeholder}},将 API_KEY 替换为字段名。值按原样传入,无需 shell。",fieldName:"字段名",label:"显示名称(可选)",addSlot:"添加字段",removeSlot:"移除字段",personalBadge:"个人凭据",manage:"管理",configured:"已绑定",required:"需要绑定",writeOnly:"已保存的值无法查看。替换绑定时,请为所有字段填写新值。",replaceValue:"输入替换值",enterValue:"输入凭据",save:"保存绑定",delete:"删除绑定",saved:"绑定已保存",deleted:"绑定已删除",failed:"无法管理凭据",showAll:"显示所有服务器",loading:"加载中…",empty:"暂无需要个人凭据的共享服务器。",targetUser:"管理用户凭据",myCredentials:"我的凭据",updatedAt:"最后更新"},Xs={app:hs,about:gs,profile:bs,sponsor:vs,wechat:ys,discord:fs,theme:ks,auth:Ss,server:Cs,status:Ps,errors:As,common:Rs,clientConfig:Ts,pagination:xs,nav:ws,pages:Ds,logs:Es,groups:Is,market:Ns,oauthServer:Os,cloud:Ms,registry:Ls,tool:zs,prompt:Us,settings:qs,mcpb:Bs,jsonImport:Fs,groupImport:Ks,users:js,api:Gs,oauthCallback:Hs,builtinPrompts:_s,builtinResources:Vs,activity:$s,template:Js,cost:Ws,credentials:Ys},Qs={title:"Tableau de bord MCPHub",error:"Erreur",closeButton:"Fermer",noServers:"Aucun serveur MCP disponible",loading:"Chargement...",logout:"Déconnexion",profile:"Profil",changePassword:"Changer le mot de passe",toggleSidebar:"Basculer la barre latérale",welcomeUser:"Bienvenue, {{username}}",name:"MCPHub",embeddingSyncProgress:"Embeddings pour {{serverName}}",embeddingSyncProgressAriaLabel:"Création des embeddings pour {{serverName}} : {{current}} sur {{total}} terminés"},Zs={title:"À propos",versionInfo:"Version MCPHub : {{version}}",newVersion:"Nouvelle version disponible !",currentVersion:"Version actuelle",newVersionAvailable:"La nouvelle version {{version}} est disponible",viewOnGitHub:"Voir sur GitHub",checkForUpdates:"Vérifier les mises à jour",checking:"Vérification des mises à jour...",viewChangelog:"Voir le changelog",viewReleaseNotes:"Voir les notes de version",viewAllChanges:"Voir tous les changements",latestChanges:"Derniers changements",upToDate:"Vous utilisez la dernière version connue.",releaseNotesUnavailable:"Une nouvelle version est disponible, mais les notes structurées ne sont pas encore disponibles.",updateChecksDisabled:"La vérification des mises à jour est désactivée pour ce déploiement.",dismissUpdate:"Ignorer",dismissed:"Ignoré",earlierReleases:"+ {{count}} versions précédentes"},el={viewProfile:"Voir le profil",userCenter:"Centre utilisateur"},rl={label:"Sponsor",title:"Soutenir le projet",rewardAlt:"QR Code de récompense",supportMessage:"Soutenez le développement de MCPHub en m'offrant un café !",supportButton:"Soutenir sur Ko-fi"},tl={label:"WeChat",title:"Se connecter via WeChat",qrCodeAlt:"QR Code WeChat",scanMessage:"Scannez ce QR code pour nous contacter sur WeChat"},al={label:"Discord",title:"Rejoignez notre serveur Discord",community:"Rejoignez notre communauté grandissante sur Discord pour du support, des discussions et des mises à jour !"},nl={title:"Thème",light:"Clair",dark:"Sombre",system:"Système"},il={createAccount:"Créer un compte",backToLogin:"Retour à la connexion",userAlreadyExists:"Ce nom d’utilisateur existe déjà",login:"Connexion",loginTitle:"Se connecter à MCPHub",slogan:"Passerelle et plan de contrôle MCP open source et auto-hébergés",subtitle:"Connectez, organisez, contrôlez et exploitez vos serveurs Model Context Protocol via des points de terminaison unifiés.",username:"Nom d'utilisateur",password:"Mot de passe",loggingIn:"Connexion en cours...",orContinue:"Ou continuer avec",loginWithGoogle:"Continuer avec Google",loginWithGithub:"Continuer avec GitHub",loginWithOIDC:"Continuer avec OIDC",socialLoginFailed:"La connexion sociale a échoué. Veuillez réessayer.","error.account_not_linked":"Compte non lié. Votre e-mail n'est peut-être pas vérifié par le fournisseur d'identité. Veuillez vérifier votre e-mail et réessayer.","error.email_doesn't_match":"L'e-mail du fournisseur d'identité ne correspond pas à votre compte existant.","error.email_not_found":"Aucun e-mail n'a été renvoyé par le fournisseur d'identité.","error.access_denied":"L'accès a été refusé par le fournisseur d'identité.","error.account_already_linked_to_different_user":"Ce compte est déjà lié à un autre utilisateur.","error.unable_to_link_account":"Impossible de lier le compte. Veuillez réessayer.","error.signup_disabled":"L'inscription est actuellement désactivée.","error.oauth_provider_not_found":"Fournisseur OAuth introuvable.","error.invalid_code":"Code d'autorisation invalide. Veuillez réessayer.","error.unable_to_get_user_info":"Impossible d'obtenir les informations utilisateur du fournisseur d'identité.",emptyFields:"Le nom d'utilisateur et le mot de passe ne peuvent pas être vides",loginFailed:"Échec de la connexion, veuillez vérifier votre nom d'utilisateur et votre mot de passe",loginError:"Une erreur est survenue lors de la connexion",serverUnavailable:"Impossible de se connecter au serveur. Veuillez vérifier votre connexion réseau ou réessayer plus tard",currentPassword:"Mot de passe actuel",newPassword:"Nouveau mot de passe",confirmPassword:"Confirmer le mot de passe",passwordsNotMatch:"Le nouveau mot de passe et la confirmation ne correspondent pas",changePasswordSuccess:"Mot de passe changé avec succès",changePasswordError:"Échec du changement de mot de passe",changePassword:"Changer le mot de passe",passwordChanged:"Mot de passe changé avec succès",passwordChangeError:"Échec du changement de mot de passe",defaultPasswordWarning:"Avertissement de sécurité du mot de passe par défaut",defaultPasswordMessage:"Vous utilisez le mot de passe par défaut (admin123), ce qui présente un risque de sécurité. Veuillez changer votre mot de passe immédiatement pour protéger votre compte.",goToSettings:"Aller aux paramètres",passwordStrengthError:"Le mot de passe ne répond pas aux exigences de sécurité",passwordMinLength:"Le mot de passe doit contenir au moins 8 caractères",passwordRequireLetter:"Le mot de passe doit contenir au moins une lettre",passwordRequireNumber:"Le mot de passe doit contenir au moins un chiffre",passwordRequireSpecial:"Le mot de passe doit contenir au moins un caractère spécial",passwordStrengthHint:"Le mot de passe doit contenir au moins 8 caractères et inclure des lettres, des chiffres et des caractères spéciaux"},ol=JSON.parse(`{"protocolVersion":"Protocole MCP","protocolVersionUnknown":"Indisponible","localExecutionRequiresAdmin":"L’exécution de commandes locales nécessite un administrateur.","httpOAuthRequiresAdmin":"Autoriser les points de terminaison de jetons OAuth en HTTP nécessite un administrateur.","startOnDemand":"Démarrage à la demande","startOnDemandDescription":"Ignore la connexion au démarrage et lance ce serveur uniquement lorsqu'un appel d'outil se produit. Le processus est arrêté automatiquement après le délai d'inactivité, puis redémarré au prochain appel. Réduit l'utilisation de la mémoire pour les serveurs rarement utilisés.","idleTimeoutMs":"Délai d'arrêt en inactivité (ms)","idleTimeoutMsDescription":"Arrête le processus après ce nombre de millisecondes sans appel d'outil. Par défaut : 300000 (5 minutes).","addServer":"Ajouter un serveur","add":"Ajouter","edit":"Modifier","copy":"Copier","duplicate":"Dupliquer","delete":"Supprimer","confirmDelete":"Êtes-vous sûr de vouloir supprimer ce serveur ?","deleteWarning":"La suppression du serveur '{{name}}' le supprimera ainsi que toutes ses données. Cette action est irréversible.","status":"Statut","tools":"Outils","prompts":"Invites","name":"Nom du serveur","nameInvalid":"Le nom du serveur ne peut contenir que des lettres, chiffres, points, underscores et traits d'union (ni espaces ni caractères spéciaux)","description":"Note du serveur","descriptionPlaceholder":"Optionnel : décrivez l'utilité de ce serveur","url":"URL du serveur","apiKey":"Clé API","save":"Enregistrer","cancel":"Annuler","invalidConfig":"Impossible de trouver les données de configuration pour {{serverName}}","addError":"Échec de l'ajout du serveur","editError":"Échec de la modification du serveur {{serverName}}","deleteError":"Échec de la suppression du serveur {{serverName}}","updateError":"Échec de la mise à jour du serveur","editTitle":"Modifier le serveur : {{serverName}}","duplicateTitle":"Dupliquer le serveur : {{serverName}}","type":"Type de serveur","typeStdio":"STDIO","typeSse":"SSE","typeStreamableHttp":"HTTP diffusable","typeOpenapi":"OpenAPI","mcpApp":"MCP App — ce serveur expose des ressources d'interface interactives","visibility":"Visibilité","visibilityPrivateShort":"Privé","visibilityPrivate":"Privé — uniquement le propriétaire et les administrateurs","visibilityGroupShort":"Partagé","visibilityGroup":"Partagé — uniquement avec les utilisateurs sélectionnés","visibilityPublicShort":"Public","visibilityPublic":"Public — tous les utilisateurs authentifiés","visibilityDescription":"Contrôle quels utilisateurs non administrateurs peuvent découvrir et appeler ce serveur. Les administrateurs ont toujours accès.","shareWithUsers":"Partager avec des utilisateurs","shareWithUsersDescription":"Les utilisateurs sélectionnés peuvent découvrir et appeler ce serveur, mais ne peuvent pas gérer sa configuration.","shareCandidatesLoading":"Chargement des utilisateurs...","shareCandidatesError":"Échec du chargement des utilisateurs.","shareAfterCreate":"Enregistrez le serveur avant de sélectionner des utilisateurs.","noShareCandidates":"Aucun autre utilisateur n'est disponible.","shareUserSearchLabel":"Rechercher des utilisateurs","shareUserSearchPlaceholder":"Rechercher des noms d'utilisateur...","selectAllShareUsers":"Tout sélectionner","deselectAllShareUsers":"Tout désélectionner","noMatchingShareUsers":"Aucun utilisateur ne correspond à votre recherche.","command":"Commande","packageVersion":"Version du paquet installé (dernière installée dans le cache du runner)","reportedVersion":"Version déclarée par le serveur","updateAvailable":"Une version plus récente est disponible sur le registre","arguments":"Arguments","addArgument":"Ajouter un argument","argumentsHint":"Chaque champ correspond à un argument. Les espaces et guillemets sont conservés ; un champ vide transmet un argument vide.","argumentLabel":"Argument {{index}}","removeArgument":"Supprimer l’argument {{index}}","envVars":"Variables d'environnement","headers":"En-têtes HTTP","key":"clé","value":"valeur","enabled":"Activé","enable":"Activer","disable":"Désactiver","reload":"Recharger","reloadSuccess":"Serveur rechargé avec succès","reloadError":"Échec du rechargement du serveur {{serverName}}","reinstall":"Réinstaller","reinstallConfirm":"Cela videra le cache des paquets et retéléchargera les dépendances. Le serveur redémarrera.","reinstallSuccess":"Réinstallation du serveur lancée","reinstallError":"Échec de la réinstallation du serveur {{serverName}}","disconnectOAuth":"Déconnecter OAuth","disconnectOAuthConfirm":"Cela révoquera les identifiants OAuth stockés lorsque le fournisseur le prend en charge et exigera une nouvelle autorisation.","disconnectOAuthSuccess":"OAuth du serveur déconnecté","disconnectOAuthError":"Échec de la déconnexion OAuth du serveur {{serverName}}","requestOptions":"Configuration de la connexion","maxBufferSize":"Limite du tampon stdio (octets)","maxBufferSizeDescription":"Taille maximale du tampon de lecture stdio. Laissez vide pour la valeur par défaut du SDK (10 Mio). Une limite supérieure permet une utilisation mémoire plus élevée.","timeout":"Délai d'attente de la requête","timeoutDescription":"Délai d'attente pour les requêtes vers le serveur MCP (ms)","maxTotalTimeout":"Délai d'attente total maximum","maxTotalTimeoutDescription":"Délai d'attente total maximum pour les requêtes envoyées au serveur MCP (ms) (à utiliser avec les notifications de progression)","resetTimeoutOnProgress":"Réinitialiser le délai d'attente en cas de progression","resetTimeoutOnProgressDescription":"Réinitialiser le délai d'attente lors des notifications de progression (activé par défaut)","keepAlive":"Santé de la connexion","retryScheduled":"Nouvel essai à {{time}}","reconnecting":"Reconnexion…","lastRetry":"Dernier essai : {{time}} ({{count}} tentatives)","enableKeepAlive":"Activer les vérifications de santé","keepAliveDescription":"Vérifier périodiquement la connexion. Les serveurs distants déconnectés se reconnectent toujours automatiquement avec un délai progressif.","keepAliveInterval":"Intervalle de vérification (ms)","keepAliveIntervalDescription":"Temps entre les vérifications en millisecondes (par défaut : 60000ms = 1 minute)","perSessionClient":"Isolation du client par session","perSessionClientDescription":"Créer une connexion amont dédiée par session au lieu d'en partager une seule entre toutes les sessions. À activer pour les serveurs à état comme Playwright. Augmente le nombre de connexions amont avec les sessions simultanées.","remove":"Retirer","toggleError":"Échec du basculement du serveur {{serverName}}","alreadyExists":"Le serveur {{serverName}} existe déjà","invalidData":"Données de serveur invalides fournies","notFound":"Serveur {{serverName}} non trouvé","namePlaceholder":"Entrez le nom du serveur","urlPlaceholder":"Entrez l'URL du serveur","commandPlaceholder":"Entrez la commande","argumentsPlaceholder":"Entrez les arguments","errorDetails":"Détails de l'erreur","viewErrorDetails":"Voir les détails de l'erreur","copyConfig":"Copier la configuration","confirmVariables":"Confirmer la configuration des variables","variablesDetected":"Variables détectées dans la configuration. Veuillez confirmer que ces variables sont correctement configurées :","detectedVariables":"Variables détectées","confirmVariablesMessage":"Veuillez vous assurer que ces variables sont correctement définies dans votre environnement d'exécution. Continuer l'ajout du serveur ?","confirmAndAdd":"Confirmer et ajouter","openapi":{"inputMode":"Mode de saisie","inputModeUrl":"URL de la spécification","inputModeSchema":"Schéma JSON","specUrl":"URL de la spécification OpenAPI","schema":"Schéma JSON OpenAPI","schemaHelp":"Collez votre schéma JSON OpenAPI complet ici","security":"Type de sécurité","securityNone":"Aucun","securityApiKey":"Clé API","securityHttp":"Authentification HTTP","securityOAuth2":"OAuth 2.0","securityOpenIdConnect":"OpenID Connect","securityDetect":"Détecter depuis le spec","securityDetecting":"Détection…","securityNotDeclared":"Ce spec ne déclare aucun schéma de sécurité.","securityPrefillNotice":"Ce spec déclare {{summary}}. Les paramètres de sécurité ont été pré-remplis — ajoutez votre valeur d’identification avant le premier appel.","securityMismatchWarning":"Le spec déclare {{summary}}, mais ce serveur est configuré en {{configured}}. Cela peut provoquer des réponses 401 silencieuses.","securityUnsupportedNotice":"Ce spec déclare {{summary}}, que MCPHub ne peut pas représenter ({{reason}}). Configurez l’authentification manuellement.","apiKeyConfig":"Configuration de la clé API","apiKeyName":"Nom de l'en-tête/paramètre","apiKeyIn":"Emplacement","apiKeyValue":"Valeur de la clé API","httpAuthConfig":"Configuration de l'authentification HTTP","httpScheme":"Schéma d'authentification","httpCredentials":"Identifiants","httpCredentialsBasicHint":"Saisissez utilisateur:motdepasse (encodé automatiquement) ou un Base64 pré-encodé.","specSecurityToggle":"L'URL de la spécification nécessite une authentification distincte","specSecurityHelp":"Activez uniquement si le document de spécification est protégé différemment de l'API (ex. /v3/api-docs protégé par Basic derrière une API en Bearer). Sinon, la configuration de sécurité ci-dessus est utilisée pour les deux.","httpSchemeBasic":"Basic","httpSchemeBearer":"Bearer","httpSchemeDigest":"Digest","oauth2Config":"Configuration OAuth 2.0","oauth2Token":"Jeton d'accès","openIdConnectConfig":"Configuration OpenID Connect","openIdConnectUrl":"URL de découverte","openIdConnectToken":"Jeton d'identification","apiKeyInHeader":"En-tête","apiKeyInQuery":"Requête","apiKeyInCookie":"Cookie","passthroughHeaders":"En-têtes de transmission","passthroughHeadersHelp":"Liste séparée par des virgules des noms d’en-têtes à transmettre des requêtes MCP entrantes vers les requêtes du serveur en amont (par ex. : Authorization, X-API-Key)","cookieSession":"Gestion de session Cookie","cookieSessionHelp":"Capture les Set-Cookie des réponses de connexion en amont et les renvoie lors des appels ultérieurs dans la même session aval. Isolé par session MCP ; non persistant.","statsMeasuring":"Mesure de la liste d'outils générée…","statsSummary":"{{toolCount}} outils · ~{{bytes}} de définitions · ~{{tokens}} jetons","statsWarning":"Cette liste d'outils peut à elle seule approcher ou dépasser les fenêtres de contexte courantes des modèles. Envisagez d'exposer moins d'outils : créez un groupe ou désactivez des outils individuels sur le serveur.","statsUnavailable":"La spécification n'a pas pu être mesurée. Vous pouvez continuer ; le serveur la validera lors de l'envoi."},"oauth":{"sectionTitle":"Configuration OAuth","sectionDescription":"Configurez les identifiants client pour les serveurs protégés par OAuth (optionnel).","allowInsecureTokenEndpoint":"Autoriser les endpoints de jetons OAuth HTTP","allowInsecureTokenEndpointHelp":"Administrateurs uniquement. Désactivé par défaut. Les identifiants et jetons de ce serveur sont transmis sans TLS. Activez uniquement sur un réseau de confiance ; HTTPS est recommandé. Une fois activée, seuls les administrateurs peuvent modifier toute la configuration de ce serveur, même si son propriétaire n’est pas administrateur.","clientId":"Identifiant client","clientSecret":"Secret client","authorizationEndpoint":"Point de terminaison d'autorisation","tokenEndpoint":"Point de terminaison de jeton","scopes":"Scopes","scopesPlaceholder":"scope1 scope2","resource":"Ressource / Audience","accessToken":"Jeton d'accès","refreshToken":"Jeton d'actualisation","identityMode":"Identité OAuth","sharedIdentity":"Compte partagé","personalIdentity":"Autorisation individuelle","personalIdentityHelp":"Chaque utilisateur doit autoriser dans le tableau de bord. Les clés utilisateur utilisent leur propriétaire ; les clés partagées sont exclues.","personalConnect":"Autoriser","personalReconnect":"Réautoriser","personalDisconnect":"Déconnecter","personalError":"Échec de l’autorisation personnelle","personalSuccess":"Autorisation personnelle enregistrée. Retournez au tableau de bord → Serveurs."}}`),sl={sleeping:"En veille",sleepingDescription:"Serveur à la demande - démarrera automatiquement lorsqu'un outil est appelé",online:"En ligne",offline:"Hors ligne",connecting:"Connexion en cours",oauthRequired:"OAuth requis",clickToAuthorize:"Cliquez pour autoriser avec OAuth",oauthWindowOpened:"Fenêtre d'autorisation OAuth ouverte. Veuillez compléter l'autorisation.",oauthClientIdHint:"Ce serveur possède un ID client OAuth préconfiguré. Si l'autorisation échoue avec « invalid redirect_uri », supprimez le clientId pour que MCPHub puisse enregistrer automatiquement son propre client OAuth."},ll={general:"Une erreur est survenue",network:"Erreur de connexion réseau. Veuillez vérifier votre connexion Internet",serverConnection:"Impossible de se connecter au serveur. Veuillez vérifier si le serveur est en cours d'exécution",serverAdd:"Échec de l'ajout du serveur. Veuillez vérifier l'état du serveur",serverUpdate:"Échec de la modification du serveur {{serverName}}. Veuillez vérifier l'état du serveur",serverFetch:"Échec de la récupération des données du serveur. Veuillez réessayer plus tard",failedToReloadServer:"Échec du rechargement du serveur",initialStartup:"Le serveur est peut-être en cours de démarrage. Veuillez patienter un instant car ce processus peut prendre du temps au premier lancement...",serverInstall:"Échec de l'installation du serveur",failedToFetchSettings:"Échec de la récupération des paramètres",failedToUpdateRouteConfig:"Échec de la mise à jour de la configuration de routage",failedToUpdateSmartRoutingConfig:"Échec de la mise à jour de la configuration du routage intelligent",failedToUpdateBetterAuthConfig:"Échec de la mise à jour de la configuration Better Auth"},cl={processing:"En cours de traitement...",save:"Enregistrer",cancel:"Annuler",back:"Retour",refresh:"Actualiser",search:"Rechercher",clear:"Effacer",view:"Voir",create:"Créer",creating:"Création en cours...",update:"Mettre à jour",updating:"Mise à jour en cours...",submitting:"Envoi en cours...",delete:"Supprimer",remove:"Retirer",copy:"Copier",copyId:"Copier l'ID",copyUrl:"Copier l'URL",copyOpenApiUrl:"Copier l'URL OpenAPI",copySuccess:"Copié dans le presse-papiers",copyFailed:"Échec de la copie",copied:"Copié",close:"Fermer",confirm:"Confirmer",language:"Langue",true:"Vrai",false:"Faux",dismiss:"Rejeter",github:"GitHub",wechat:"WeChat",discord:"Discord",itemsPerPage:"Éléments par page",showing:"Affichage de {{start}}-{{end}} sur {{total}}",previous:"Précédent",next:"Suivant",required:"Requis",secret:"Secret",default:"Défaut",value:"Valeur",type:"Type",repeated:"Répété",valueHint:"Indice de valeur",choices:"Choix",actions:"Actions",saving:"Enregistrement...",active:"Actif",inactive:"Inactif",viewAll:"Voir tout",docs:"Docs",all:"Tout"},dl={title:"Copier la configuration MCP",description:"Choisissez votre client pour copier une configuration prête à coller pour {{name}}.",menuItem:"Copier la config MCP",tokenPrompt:"Jeton d'accès MCPHub",configBlock:"Configuration",commandBlock:"Commande CLI",copied:"Copié",noTransport:"Ce serveur n'a aucun transport MCP côté client (il est adossé à OpenAPI). Utilisez plutôt le hub ou un endpoint de groupe.",clients:{"generic-mcp-servers":{label:"Générique (mcpServers)",hint:"Bloc mcpServers largement accepté : Claude Desktop, Cline, Cherry Studio et la plupart des clients."},"generic-http":{label:"HTTP générique",hint:`Solution de repli avec l'entrée brute : un endpoint distant donne une entrée HTTP brute (un upstream SSE porte le marqueur "type": "sse"), un serveur local une entrée stdio brute (command/args/env). Collez-la dans la table de serveurs du client ; pour la plupart des clients, utilisez Générique (mcpServers).`},"claude-code":{label:"Claude Code",hint:"Claude Code : `claude mcp add`, ou le bloc mcpServers dans ~/.claude.json."},cursor:{label:"Cursor",hint:"Cursor : .cursor/mcp.json dans un projet, ou ~/.cursor/mcp.json en global."},vscode:{label:"VS Code / Copilot",hint:"VS Code / Copilot : .vscode/mcp.json dans l'espace de travail, ou mcp.json dans votre profil utilisateur."},codex:{label:"Codex",hint:"Codex : ~/.codex/config.toml, ou .codex/config.toml au niveau du projet."},opencode:{label:"OpenCode",hint:"OpenCode : ~/.config/opencode/opencode.json en global, ou opencode.json dans le projet."},windsurf:{label:"Windsurf",hint:"Windsurf : ~/.codeium/windsurf/mcp_config.json."},"cherry-studio":{label:"Cherry Studio",hint:"Cherry Studio : Paramètres > Serveurs MCP > Ajouter un serveur > Importer JSON."},codebuddy:{label:"CodeBuddy Code",hint:"CodeBuddy Code : ~/.codebuddy/.mcp.json en global, ou .mcp.json dans le projet."},qoder:{label:"Qoder",hint:"Qoder : Paramètres > MCP > Ajout manuel, puis collez le JSON."},trae:{label:"TRAE",hint:"TRAE : Paramètres > MCP > Ajouter > Ajout manuel, puis collez le JSON."},zcode:{label:"ZCode",hint:"ZCode : Paramètres > Serveurs MCP > Nouveau serveur MCP > Configuration complète."},workbuddy:{label:"WorkBuddy",hint:"WorkBuddy : Plugins > Serveurs MCP > Configurer MCP, ou ~/.workbuddy/mcp.json."}}},ul={rowsPerPage:"Lignes par page",showing:"Affichage de {{from}}-{{to}} sur {{total}}"},ml={dashboard:"Tableau de bord",servers:"Serveurs",groups:"Groupes",prompts:"Prompts",resources:"Ressources",users:"Utilisateurs",settings:"Paramètres",changePassword:"Changer le mot de passe",market:"Marché",cloud:"Marché Cloud",logs:"Journaux",activity:"Activité",workspace:"Espace de travail",system:"Système"},pl={dashboard:{title:"Tableau de bord",totalServers:"Total",onlineServers:"En ligne",disabledServers:"Désactivés",offlineServers:"Hors ligne",connectingServers:"En connexion",recentServers:"Serveurs récents"},servers:{title:"Gestion des serveurs"},groups:{title:"Gestion des groupes"},prompts:{title:"Prompts intégrés"},resources:{title:"Ressources intégrées"},users:{title:"Gestion des utilisateurs"},settings:{title:"Paramètres",language:"Langue",account:"Paramètres du compte",password:"Changer le mot de passe",appearance:"Apparence",routeConfig:"Sécurité",installConfig:"Installation",smartRouting:"Routage intelligent",oauthServer:"Serveur OAuth"},market:{title:"Marché Hub - Marchés locaux et Cloud"},logs:{title:"Journaux système"}},hl={filters:"Filtres",search:"Rechercher dans les journaux...",autoScroll:"Défilement automatique",clearLogs:"Effacer les journaux",loading:"Chargement des journaux...",noLogs:"Aucun journal disponible.",noMatch:"Aucun journal ne correspond aux filtres actuels.",mainProcess:"Processus principal",childProcess:"Processus enfant",main:"Principal",child:"Enfant"},gl={legacyVisibility:"Groupe existant — choisir la visibilité",legacyVisibilityHint:"Ce groupe conserve ses règles d’accès précédentes jusqu’au choix explicite de sa visibilité.",visibilityDescription:"L’accès au groupe nécessite aussi l’accès à chaque serveur. Partager un groupe ne partage pas ses serveurs privés. Seuls le propriétaire et les administrateurs peuvent le gérer.",shareAfterCreate:"Enregistrez le groupe avant de sélectionner des utilisateurs.",add:"Ajouter",addNew:"Ajouter un nouveau groupe",edit:"Modifier le groupe",delete:"Supprimer",confirmDelete:"Êtes-vous sûr de vouloir supprimer ce groupe ?",deleteWarning:"La suppression du groupe '{{name}}' le supprimera ainsi que toutes ses associations de serveurs. Cette action est irréversible.",name:"Nom du groupe",namePlaceholder:"Entrez le nom du groupe",instructions:"Instructions",instructionsHelp:"Facultatif. Envoyées aux clients MCP à la connexion à ce groupe (y compris $smart/<group>) ; la plupart les ajoutent au prompt système du modèle.",instructionsPlaceholder:"Ex. : Utilisez fetch pour les pages web ; en cas d'échec, firecrawl_scrape.",nameRequired:"Le nom du groupe est requis",description:"Description",descriptionPlaceholder:"Entrez la description du groupe (facultatif)",createError:"Échec de la création du groupe",updateError:"Échec de la mise à jour du groupe",deleteError:"Échec de la suppression du groupe",serverAddError:"Échec de l'ajout du serveur au groupe",serverRemoveError:"Échec de la suppression du serveur du groupe",addServer:"Ajouter un serveur au groupe",selectServer:"Sélectionnez un serveur à ajouter",servers:"Serveurs dans le groupe",remove:"Retirer",noGroups:"Aucun groupe disponible. Créez un nouveau groupe pour commencer.",noServers:"Aucun serveur dans ce groupe.",noServerOptions:"Aucun serveur disponible",serverCount:"{{count}} serveurs",toolSelection:"Sélection d'outils",promptSelection:"Sélection des prompts",resourceSelection:"Sélection des ressources",toolsSelected:"Sélectionné",promptsSelected:"Sélectionné",resourcesSelected:"Sélectionné",allTools:"Tous",allPrompts:"Tous les prompts",allResources:"Toutes les ressources",selectedTools:"Outils sélectionnés",selectedPrompts:"Prompts sélectionnés",selectedResources:"Ressources sélectionnées",selectAll:"Tout sélectionner",selectNone:"Ne rien sélectionner",configureTools:"Configurer les outils",configureCapabilities:"Configurer les outils, prompts et ressources",alias:"Nom exposé",preserveToolNames:"Conserver les noms d’origine des outils",preserveToolNamesHint:"Expose les outils sans préfixe de serveur. Les noms doivent être uniques dans le groupe. Le nom exposé reste applicable aux prompts.",pinTool:"Épingler : toujours lister cet outil sur le point d'accès du routage intelligent du groupe, à côté de search_tools",pinToolLabel:"Épingler sur le point d'accès du routage intelligent",unpinTool:"Désépingler : n'accéder à cet outil que via search_tools",previewPrompts:"[prompts : {{items}}]",previewResources:"[ressources : {{items}}]",previewAllTools:"(tous les outils)",previewAllPrompts:"(tous les prompts)",previewAllResources:"(toutes les ressources)",bulkSearch:"Rechercher par nom ou description…",bulkSearchLabel:"Rechercher {{capability}}",annotationFilter:"Filtrer par annotation",allAnnotations:"Toutes les annotations",readOnlyHint:"Indication de lecture seule",destructiveHint:"Indication destructive",idempotentHint:"Indication d’idempotence",flatList:"Liste simple",riskGroups:"Groupes de risque",visibleCount:"{{count}} sur {{total}} visibles",selectVisible:"Sélectionner les éléments visibles",deselectVisible:"Désélectionner les éléments visibles",invertVisible:"Inverser les éléments visibles",riskHint:"Les groupes utilisent les indications du serveur et les noms ; ils ne garantissent pas la sécurité. Les actions concernent uniquement les éléments filtrés.",noMatchingItems:"Aucun résultat",risk_read:"Lecture",risk_create:"Création",risk_update:"Mise à jour",risk_delete:"Suppression",risk_other:"Autres / non classés"},bl={title:"Installation locale",official:"Officiel",by:"Par",unknown:"Inconnu",tools:"outils",search:"Rechercher",searchPlaceholder:"Rechercher des serveurs par nom, catégorie ou tags",clearFilters:"Effacer",clearCategoryFilter:"",clearTagFilter:"",categories:"Catégories",tags:"Tags",showTags:"Afficher les tags",hideTags:"Masquer les tags",moreTags:"",noServers:"Aucun serveur trouvé correspondant à votre recherche",backToList:"Retour à la liste",install:"Installer",installing:"Installation en cours...",installed:"Installé",installServer:"Installer le serveur : {{name}}",installSuccess:"Serveur {{serverName}} installé avec succès",author:"Auteur",license:"Licence",repository:"Dépôt",examples:"Exemples",arguments:"Arguments",argumentName:"Nom",description:"Description",required:"Requis",example:"Exemple",viewSchema:"Voir le schéma",fetchError:"Erreur lors de la récupération des serveurs du marché",serverNotFound:"Serveur non trouvé",searchError:"Erreur lors de la recherche de serveurs",filterError:"Erreur lors du filtrage des serveurs par catégorie",tagFilterError:"Erreur lors du filtrage des serveurs par tag",noInstallationMethod:"Aucune méthode d'installation disponible pour ce serveur",showing:"Affichage de {{from}}-{{to}} sur {{total}} serveurs",perPage:"Par page",confirmVariablesMessage:"Veuillez vous assurer que ces variables sont correctement définies dans votre environnement d'exécution. Continuer l'installation du serveur ?",confirmAndInstall:"Confirmer et installer"},vl={authorizeTitle:"Autoriser l'application",authorizeSubtitle:"Autorisez cette application à accéder à votre compte MCPHub.",buttons:{approve:"Autoriser l'accès",deny:"Refuser",approveSubtitle:"Recommandé si vous faites confiance à cette application.",denySubtitle:"Vous pourrez toujours accorder l'accès plus tard."},application:"Application",scopesTitle:"Cette application pourra :",noScopes:"Aucune autorisation demandée.",requestInvalidTitle:"Demande invalide",requestInvalid:"Cette demande d'autorisation est invalide ou a expiré. Veuillez revenir en arrière et réessayer.",grantingAccessTo:"Accord de l'accès à :",resourceAll:"Tous les serveurs MCP",resourceSmart:"Routage intelligent",resourceServer:"Serveur MCP : {{name}}",resourceGroup:"Groupe MCP : {{name}}",clientId:"ID client",willRedirectTo:"Redirigera vers :",policy:"Politique de confidentialité",terms:"Conditions d'utilisation",homepage:"Page d'accueil"},yl={title:"Support Cloud",subtitle:"Propulsé par MCPRouter",by:"Par",server:"Serveur",config:"Config",created:"Créé",updated:"Mis à jour",available:"Disponible",description:"Description",details:"Détails",tools:"Outils",tool:"outil",toolsAvailable:"{{count}} outil disponible||{{count}} outils disponibles",loadingTools:"Chargement des outils...",noTools:"Aucun outil disponible pour ce serveur",noDescription:"Aucune description disponible",viewDetails:"Voir les détails",parameters:"Paramètres",result:"Résultat",error:"Erreur",callTool:"Appeler",calling:"Appel en cours...",toolCallSuccess:"L'outil {{toolName}} a été exécuté avec succès",toolCallError:"Échec de l'appel de l'outil {{toolName}} : {{error}}",viewSchema:"Voir le schéma",backToList:"Retour au marché Cloud",search:"Rechercher",searchPlaceholder:"Rechercher des serveurs cloud par nom, titre ou auteur",clearFilters:"Effacer les filtres",clearCategoryFilter:"Effacer",clearTagFilter:"Effacer",categories:"Catégories",tags:"Tags",noCategories:"Aucune catégorie trouvée",noTags:"Aucun tag trouvé",noServers:"Aucun serveur cloud trouvé",fetchError:"Erreur lors de la récupération des serveurs cloud",serverNotFound:"Serveur cloud non trouvé",searchError:"Erreur lors de la recherche de serveurs cloud",filterError:"Erreur lors du filtrage des serveurs cloud par catégorie",tagFilterError:"Erreur lors du filtrage des serveurs cloud par tag",showing:"Affichage de {{from}}-{{to}} sur {{total}} serveurs cloud",perPage:"Par page",apiKeyNotConfigured:"Clé API MCPRouter non configurée",apiKeyNotConfiguredDescription:"Pour utiliser les serveurs cloud, vous devez configurer votre clé API MCPRouter.",getApiKey:"Obtenir une clé API",configureInSettings:"Configurer dans les paramètres",installServer:"Installer {{name}}",installSuccess:"Serveur {{name}} installé avec succès",installError:"Échec de l'installation du serveur : {{error}}"},fl={title:"Registre",official:"Officiel",latest:"Dernière version",description:"Description",website:"Site web",repository:"Dépôt",packages:"Paquets",package:"paquet",remotes:"Services distants",remote:"service distant",published:"Publié",updated:"Mis à jour",install:"Installer",installing:"Installation...",installed:"Installé",installServer:"Installer {{name}}",installSuccess:"Serveur {{name}} installé avec succès",installError:"Échec de l'installation du serveur : {{error}}",noDescription:"Aucune description disponible",viewDetails:"Voir les détails",backToList:"Retour au registre",search:"Rechercher",searchPlaceholder:"Rechercher des serveurs par nom",clearFilters:"Effacer",noServers:"Aucun serveur trouvé dans le registre",fetchError:"Erreur lors de la récupération des serveurs du registre",serverNotFound:"Serveur du registre non trouvé",showing:"Affichage de {{from}}-{{to}} sur {{total}} serveurs du registre",perPage:"Par page",environmentVariables:"Variables d'environnement",packageArguments:"Arguments du paquet",runtimeArguments:"Arguments d'exécution",headers:"En-têtes"},kl={run:"Exécuter",running:"Exécution en cours...",runTool:"Exécuter l'outil",cancel:"Annuler",noDescription:"Aucune description disponible",inputSchema:"Schéma d'entrée :",runToolWithName:"Exécuter l'outil : {{name}}",execution:"Exécution de l'outil",successful:"Réussi",failed:"Échoué",result:"Résultat :",error:"Erreur",errorDetails:"Détails de l'erreur :",noContent:"L'outil a été exécuté avec succès mais n'a renvoyé aucun contenu.",unknownError:"Une erreur inconnue est survenue",jsonResponse:"Réponse JSON :",toolResult:"Résultat de l'outil",noParameters:"Cet outil ne nécessite aucun paramètre.",selectOption:"Sélectionnez une option",enterValue:"Entrez la valeur {{type}}",enabled:"Activé",enableSuccess:"Outil {{name}} activé avec succès",disableSuccess:"Outil {{name}} désactivé avec succès",toggleFailed:"Échec du basculement de l'état de l'outil",descriptionUpdateSuccess:"Description de l'outil mise à jour avec succès",descriptionUpdateFailed:"Échec de la mise à jour de la description de l'outil",descriptionModifiedBadge:"Modifiée",defaultDescriptionLabel:"Description par défaut",visibleParams:"Paramètres visibles par les modèles",visibleParamsHelp:"Les paramètres décochés sont retirés du schéma reçu par les modèles et ignorés dans leurs appels. Les paramètres obligatoires (*) ne peuvent pas être masqués.",requiredParam:"Les paramètres obligatoires ne peuvent pas être masqués",hiddenParamsFailed:"Échec de la mise à jour des paramètres masqués",defaultDescriptionTooltip:"Description par défaut : {{description}}",restoreDefault:"Restaurer par défaut",restoreDefaultSuccess:"La description de l'outil a été restaurée à sa valeur par défaut",restoreDefaultFailed:"Échec de la restauration de la description par défaut de l'outil",parameters:"Paramètres de l'outil",formMode:"Mode formulaire",jsonMode:"Mode JSON",jsonConfiguration:"Configuration JSON",invalidJsonFormat:"Format JSON invalide",fixJsonBeforeSwitching:"Veuillez corriger le format JSON avant de passer en mode formulaire",item:"Élément {{index}}",addItem:"Ajouter un élément {{key}}",enterKey:"Entrez {{key}}"},Sl={run:"Obtenir",running:"Obtention en cours...",result:"Résultat de l'invite",error:"Erreur de l'invite",execution:"Exécution de l'invite",successful:"Réussi",failed:"Échoué",errorDetails:"Détails de l'erreur :",noContent:"L'invite a été exécutée avec succès mais n'a renvoyé aucun contenu.",unknownError:"Une erreur inconnue est survenue",jsonResponse:"Réponse JSON :",description:"Description",messages:"Messages",noDescription:"Aucune description disponible",runPromptWithName:"Obtenir l'invite : {{name}}",descriptionUpdateSuccess:"Description de l'invite mise à jour avec succès",descriptionUpdateFailed:"Échec de la mise à jour de la description de l'invite",restoreDefault:"Restaurer par défaut",restoreDefaultSuccess:"La description de l'invite a été restaurée à sa valeur par défaut",restoreDefaultFailed:"Échec de la restauration de la description par défaut de l'invite"},Cl=JSON.parse(`{"dashboardName":"Nom du tableau de bord","dashboardNameDescription":"Affiché dans la barre latérale, l’en-tête, la connexion et l’onglet. Laissez vide pour rétablir le nom par défaut.","dashboardNameSaveFailed":"Échec de l’enregistrement du nom","resetBearerKey":"Réinitialiser la clé Bearer","resetBearerKeyConfirm":"Réinitialiser cette clé Bearer ? L’ancien jeton cessera immédiatement de fonctionner. Les autorisations et l’état resteront identiques.","resetBearerKeySuccess":"Clé réinitialisée. Copiez et conservez le nouveau jeton avant de fermer ; il ne sera plus affiché.","resetBearerKeyError":"Échec de la réinitialisation de la clé Bearer","allowRegistration":"Autoriser les inscriptions","allowRegistrationDescription":"Permet aux visiteurs de créer un compte standard depuis la page de connexion. Désactivé par défaut et indisponible si la connexion par mot de passe est désactivée.","allowedCidrs":"Plages CIDR autorisées pour les services en amont","allowedCidrsDescription":"Un CIDR IPv4 ou IPv6 par ligne. Tous les utilisateurs peuvent accéder aux services MCP, OpenAPI et OAuth de ces plages. Une liste vide ne donne aucun accès supplémentaire. Les serveurs appartenant aux administrateurs gardent leur accès interne. Évitez les plages larges et les adresses de métadonnées ou de boucle locale. Les changements concernent les nouvelles requêtes, sans fermer les connexions existantes.","allowedCidrsUpdateFailed":"Échec de la mise à jour des plages CIDR","subtitle":"Configurez les paramètres système, l'authentification, le routage et les intégrations de serveurs MCP.","enableGlobalRoute":"Activer la route globale","enableGlobalRouteDescription":"Autoriser les connexions au point de terminaison /sse sans spécifier d'ID de groupe","enableGroupNameRoute":"Activer la route par nom de groupe","enableGroupNameRouteDescription":"Autoriser les connexions au point de terminaison /sse en utilisant les noms de groupe au lieu des ID de groupe","enableBearerAuth":"Activer l'authentification Bearer","enableBearerAuthDescription":"Exiger une authentification par jeton Bearer pour les points de terminaison MCP (activé par défaut)","bearerAuthKey":"Clé d'authentification Bearer","bearerAuthKeyDescription":"La clé d'authentification qui sera requise dans le jeton Bearer","bearerAuthKeyPlaceholder":"Entrez la clé d'authentification Bearer","bearerAuthHeaderName":"Nom de l'en-tête Bearer","bearerAuthHeaderNameDescription":"Nom de l'en-tête utilisé pour recevoir les identifiants Bearer MCP. Modifiez-le si les en-têtes transmis en amont utilisent aussi Authorization.","bearerAuthHeaderNamePlaceholder":"ex. Authorization ou X-MCP-Authorization","bearerKeysSectionTitle":"Clés","bearerKeysSectionDescription":"Gérez plusieurs clés avec différentes portées d’accès.","bearerKeyScopeFilter":"Filtrer par portée","noBearerKeys":"Aucune clé configurée pour le moment.","bearerKeyName":"Nom","bearerKeyToken":"Jeton","bearerKeyEnabled":"Activée","bearerKeyAccessType":"Portée d’accès","bearerKeyAccessAll":"Toutes","bearerKeyAccessGroups":"Groupes","bearerKeyAccessServers":"Serveurs","bearerKeyAccessCustom":"Personnalisée","bearerKeyAllowedGroups":"Groupes autorisés","bearerKeyAllowedServers":"Serveurs autorisés","addBearerKey":"Ajouter une clé","addBearerKeyButton":"Créer","bearerKeyRequired":"Le nom et le jeton sont obligatoires","bearerKeyNameRequired":"Le nom est obligatoire","bearerKeyOwnerRequired":"Le propriétaire est obligatoire","bearerKeyKind":"Type de clé","bearerKeyKindSystem":"Système","bearerKeyKindUser":"Utilisateur","bearerKeyOwner":"Propriétaire","bearerKeySelectOwner":"Sélectionner un utilisateur...","bearerKeyAccessUserVisibility":"Visibilité de l’utilisateur","bearerKeyShownOnce":"Copiez ce jeton maintenant. Il ne sera plus affiché.","deleteBearerKeyConfirm":"Voulez-vous vraiment supprimer cette clé ?","generate":"Générer","selectGroups":"Sélectionner des groupes","selectServers":"Sélectionner des serveurs","selectAtLeastOneGroup":"Veuillez sélectionner au moins un groupe","selectAtLeastOneServer":"Veuillez sélectionner au moins un serveur","skipAuth":"Ignorer l'authentification","skipAuthDescription":"Autoriser l'accès au tableau de bord sans connexion ; les utilisateurs non authentifiés obtiennent un accès administrateur guest (n'affecte pas l'auth MCP)","jsonBodyLimit":"Limite de taille du corps JSON","jsonBodyLimitDescription":"Limite de taille des requêtes JSON Express. Les gros téléchargements de schémas OpenAPI utilisent aussi ce paramètre.","jsonBodyLimitPlaceholder":"ex. 1mb, 5mb, 1024kb","pythonIndexUrl":"URL du dépôt de paquets Python","pythonIndexUrlDescription":"Définir la variable d'environnement UV_DEFAULT_INDEX pour l'installation de paquets Python","pythonIndexUrlPlaceholder":"ex. https://pypi.org/simple","npmRegistry":"URL du registre NPM","npmRegistryDescription":"Définir la variable d'environnement npm_config_registry pour l'installation de paquets NPM","npmRegistryPlaceholder":"ex. https://registry.npmjs.org/","baseUrl":"URL de base","baseUrlDescription":"URL de base pour les requêtes MCP et les callbacks OAuth","baseUrlPlaceholder":"ex. http://localhost:3000","installConfig":"Installation","clearCache":"Vider le cache des paquets","clearCacheDescription":"Vider les caches npm et uv. Les serveurs pourraient devoir retélécharger les paquets au prochain démarrage.","clearCacheConfirm":"Cela videra les caches npm et uv. Les serveurs pourraient devoir retélécharger les paquets au prochain démarrage.","clearCacheSuccess":"Cache des paquets vidé avec succès","clearCacheError":"Échec du vidage du cache des paquets","clearCacheSkipped":"non installé","clearingCache":"Vidage...","systemConfigUpdated":"Configuration système mise à jour avec succès","noChanges":"Aucune modification à enregistrer","betterAuthTitle":"Better Auth","betterAuthEnvNote":"Les identifiants et secrets client proviennent toujours des variables d'environnement. Modifier les paramètres Better Auth peut nécessiter un redémarrage de l'application, et l'origine de l'URL de base d'installation est ajoutée automatiquement aux origines approuvées.","enableBetterAuth":"Activer Better Auth","enableBetterAuthDescription":"Activez la connexion sociale et OIDC lorsque les variables d'environnement requises sont configurées.","disablePasswordLogin":"Désactiver la connexion par mot de passe","disablePasswordLoginDescription":"N'autoriser la connexion que via les fournisseurs SSO : le formulaire nom d'utilisateur/mot de passe et POST /api/auth/login sont désactivés. Ne s'applique que si au moins un fournisseur est activé et l'était déjà au démarrage de l'application. BETTER_AUTH_DISABLE_PASSWORD_LOGIN prime sur ce réglage ; le mettre à false permet de se reconnecter si le fournisseur d'identité est indisponible.","betterAuthBaseUrl":"URL de base","betterAuthBaseUrlDescription":"URL de base publique utilisée pour construire les URI de redirection Better Auth. Si vide, l'URL de base d'installation est utilisée ; la variable d'environnement BETTER_AUTH_URL est prioritaire.","betterAuthBasePath":"Chemin de base d'authentification","betterAuthBasePathDescription":"Chemin API relatif utilisé par les routes Better Auth.","betterAuthTrustedOrigins":"Origines approuvées","betterAuthTrustedOriginsDescription":"Origines séparées par des virgules autorisées pour les requêtes Better Auth. L'origine de l'URL de base d'installation est ajoutée automatiquement.","betterAuthProviders":"Fournisseurs","betterAuthProvidersDescription":"Les interrupteurs des fournisseurs contrôlent les méthodes de connexion affichées sur la page de connexion.","betterAuthGoogleDescription":"Nécessite GOOGLE_CLIENT_ID et GOOGLE_CLIENT_SECRET.","betterAuthGithubDescription":"Nécessite GITHUB_CLIENT_ID et GITHUB_CLIENT_SECRET.","betterAuthOidcDescription":"Nécessite les identifiants client OIDC ainsi qu'une URL de découverte.","betterAuthOidcProviderId":"Identifiant du fournisseur OIDC","betterAuthOidcProviderIdDescription":"Identifiant du fournisseur utilisé pour démarrer le flux de connexion OIDC.","betterAuthOidcDiscoveryUrl":"URL de découverte OIDC","betterAuthOidcDiscoveryUrlDescription":"URL de configuration OpenID Connect publiée par votre fournisseur d'identité.","betterAuthOidcScopes":"Scopes OIDC","betterAuthOidcScopesDescription":"Scopes séparés par des virgules demandés pendant le flux de connexion OIDC.","betterAuthOidcPrompt":"Prompt OIDC","betterAuthOidcPromptDescription":"Valeur de prompt optionnelle envoyée au fournisseur d'identité, par exemple login ou consent.","betterAuthOidcPkce":"Activer PKCE","betterAuthOidcPkceDescription":"Utiliser PKCE pour le flux d'autorisation OIDC.","enableSmartRouting":"Activer le routage intelligent","enableSmartRoutingDescription":"Activer la fonctionnalité de routage intelligent pour rechercher l'outil le plus approprié en fonction de l'entrée (en utilisant le nom de groupe $smart)","dbUrl":"URL PostgreSQL (nécessite le support de pgvector)","dbUrlPlaceholder":"ex. postgresql://user:password@localhost:5432/dbname","embeddingProvider":"Fournisseur d'embeddings","embeddingProviderPreset":"Préréglage du fournisseur","embeddingProviderPresetDescription":"Choisissez un fournisseur pour préremplir son endpoint et son modèle compatibles OpenAI.","embeddingProviderPresetOpenai":"OpenAI","embeddingProviderPresetOpenrouter":"OpenRouter","embeddingProviderPresetSiliconflow":"SiliconFlow · offre gratuite (1000 RPM)","embeddingProviderPresetGemini":"Google Gemini · offre gratuite (100 RPM)","embeddingProviderPresetCustom":"Autre / compatible OpenAI","llmProviderBaseUrl":"URL de base compatible OpenAI","llmProviderBaseUrlPlaceholder":"https://api.openai.com/v1","llmProviderApiKey":"Clé API du fournisseur LLM","llmProviderApiKeyPlaceholder":"Entrez la clé API du fournisseur LLM","smartRoutingEnvOverrideWarning":"Actuellement fourni par la variable d'environnement {{envVar}} — la valeur enregistrée ici est ignorée à l'exécution.","embeddingModel":"Nom du modèle d'intégration","embeddingModelPlaceholder":"text-embedding-3-small","basePacingDelayMs":"Délai de pacing de base (ms)","basePacingDelayMsDescription":"Délai de base entre les requêtes d'embeddings envoyées au fournisseur. Par défaut 0 — le système gère les limites de débit automatiquement : il respecte les en-têtes Retry-After, applique un délai de 63 secondes en l'absence d'en-tête, et augmente le pacing après chaque réponse 403/429. Définissez une valeur non nulle uniquement si votre fournisseur impose un intervalle minimum fixe.","basePacingDelayMsPlaceholder":"Vide = valeur par défaut 0 ms","basePacingDelayMsAuto":"Par défaut ({{value}} ms) : la gestion des limites de débit est automatique.","basePacingDelayMsZero":"0 ms (par défaut) : la gestion des limites de débit est automatique via throttling adaptatif et logique de retry.","basePacingDelayMsOverride":"Valeur personnalisée : remplace le délai de pacing de base par défaut.","embeddingEncodingFormat":"Format d'encodage des embeddings","embeddingEncodingFormatDescription":"Format d'encodage pour les vecteurs d'embedding. Auto détectera en fonction du support du fournisseur.","embeddingEncodingFormatAuto":"Auto (Recommandé)","embeddingDimensions":"Dimensions des embeddings","embeddingDimensionsDescription":"Taille de sortie facultative pour les fournisseurs qui la prennent en charge. Laissez vide pour utiliser la valeur par défaut du modèle.","embeddingDimensionsPlaceholder":"Vide = valeur par défaut du modèle","embeddingDimensionsApiPassthrough":"Transmettre dimensions à l'API (passthrough MRL)","embeddingDimensionsApiPassthroughDescription":"Seuls les modèles connus pour supporter Matryoshka (MRL) reçoivent le paramètre dimensions. Activez cette option pour le forcer sur d'autres modèles compatibles MRL. Les modèles non-MRL (Qwen3-Embedding, BGE, vLLM/sglang) rejettent le paramètre, laissez donc désactivé pour eux.","azureOpenaiEndpoint":"Point de terminaison Azure OpenAI","azureOpenaiEndpointPlaceholder":"https://VOTRE_NOM_DE_RESSOURCE.openai.azure.com","azureOpenaiApiKey":"Clé API Azure OpenAI","azureOpenaiApiKeyPlaceholder":"Entrez la clé API Azure OpenAI","azureOpenaiApiVersion":"Version de l'API Azure OpenAI","azureOpenaiApiVersionPlaceholder":"2024-02-15-preview","azureOpenaiEmbeddingDeployment":"Déploiement d'embeddings Azure OpenAI","azureOpenaiEmbeddingDeploymentPlaceholder":"text-embedding-3-small","azureOpenaiEmbeddingModel":"Nom du modèle d'embedding Azure","azureOpenaiEmbeddingModelDescription":"Le nom réel du modèle OpenAI déployé dans Azure (ex. text-embedding-3-small). Utilisé pour le comptage précis des tokens avant l'envoi à l'API.","azureOpenaiEmbeddingModelPlaceholder":"text-embedding-3-small","smartRoutingConfigUpdated":"Configuration du routage intelligent mise à jour avec succès","progressiveDisclosure":"Divulgation progressive","progressiveDisclosureDescription":"Lorsqu'elle est activée, search_tools renvoie uniquement les noms et descriptions des outils. Utilisez describe_tool pour obtenir le schéma complet des paramètres, réduisant ainsi l'utilisation des tokens.","embeddingMaxTokens":"Tokens max pour les embeddings","embeddingMaxTokensDescription":"Nombre maximum de tokens pour la troncature du texte avant la génération des embeddings. Laissez vide pour utiliser automatiquement la valeur par défaut du modèle. Une valeur personnalisée remplace toujours la valeur par défaut du modèle. La configuration manuelle de cette valeur est particulièrement utile lors de l'utilisation de fournisseurs LLM locaux pour éviter les erreurs de troncature.","embeddingMaxTokensPlaceholder":"Vide = automatique selon le modèle","embeddingMaxTokensAuto":"Auto : {{limit}} tokens (valeur par défaut du modèle {{model}})","embeddingMaxTokensOverride":"Cette valeur remplace la valeur par défaut du modèle.","embeddingPrefixes":"Préfixes de tâche d'embedding","embeddingPrefixesDescription":"Texte ajouté avant l'embedding, pour les modèles de recherche asymétriques entraînés avec des préfixes de tâche (par ex. EmbeddingGemma, E5, Nomic). Laissez les deux vides pour les modèles qui attendent du texte brut. Incluez l'espace final. Modifier le préfixe de document recalcule les embeddings de tous les outils.","embeddingQueryPrefix":"Préfixe de requête","embeddingDocumentPrefix":"Préfixe de document","searchResults":"Résultats de recherche","searchResultsDescription":"Comment search_tools filtre et renvoie les correspondances. Chaque résultat porte son score de similarité. Laissez les deux champs vides pour les valeurs par défaut.","similarityThreshold":"Seuil de similarité (0-1)","similarityThresholdPlaceholder":"Vide = selon la longueur de la requête (0,2 / 0,3 / 0,4)","fullSchemaTopN":"Schémas complets pour les N premiers résultats","fullSchemaTopNPlaceholder":"Vide = tous les résultats ; les suivants passent par describe_tool","toolDefinitionFields":"Champs d'outil dans les résultats","toolDefinitionFieldsDescription":"Champs facultatifs que les résultats de search_tools et describe_tool incluent en plus du nom, de la description et de l'inputSchema. Par défaut : title et annotations. Les autres servent surtout aux clients et peuvent être volumineux (les icônes sont des images base64).","invalidSearchSettings":"Valeur invalide pour {{fields}}. Le seuil de similarité doit être compris entre 0 et 1, et N un nombre entier supérieur ou égal à 0.","smartRoutingRequiredFields":"L'URL de la base de données est requise pour activer le routage intelligent. Une clé API du fournisseur LLM est requise pour les fournisseurs cloud (les LLM locaux ne nécessitent généralement pas de clé API, entrez n'importe quelle valeur pour passer la validation du formulaire)","smartRoutingValidationError":"Veuillez remplir les champs obligatoires avant d'activer le routage intelligent : {{fields}}","smartRoutingWorkflow":"Flux de travail","smartRoutingWorkflowDescription":"Le prompt est vectorisé ; les top-k outils similaires sont récupérés depuis pgvector et exposés au LLM en amont.","toolResultCompressionTitle":"Compression des résultats d'outils","toolResultCompressionEnable":"Activer la compression","toolResultCompressionDescription":"Réduisez les grands résultats d'outils texte avant qu'ils n'atteignent les clients MCP. Les changements s'appliquent au prochain appel d'outil.","toolResultCompressionStrategy":"Stratégie","toolResultCompressionStrategyDescription":"Auto détecte JSON, journaux, résultats de recherche, diffs et texte brut.","toolResultCompressionMinTokens":"Tokens minimum","toolResultCompressionMinTokensDescription":"Compresser uniquement les blocs de texte à partir de cette taille.","toolResultCompressionMaxOutputTokens":"Budget de tokens en sortie","toolResultCompressionMaxOutputTokensDescription":"Nombre maximum cible de tokens pour chaque bloc de texte compressé.","mcpRouterConfig":"Marché Cloud","mcpRouterApiKey":"Clé API MCPRouter","mcpRouterApiKeyDescription":"Clé API pour accéder aux services du marché cloud MCPRouter","mcpRouterApiKeyPlaceholder":"Entrez la clé API MCPRouter","mcpRouterReferer":"Référent","mcpRouterRefererDescription":"En-tête Referer pour les requêtes API MCPRouter","mcpRouterRefererPlaceholder":"https://www.mcphub.app","mcpRouterTitle":"Titre","mcpRouterTitleDescription":"En-tête Title pour les requêtes API MCPRouter","mcpRouterTitlePlaceholder":"MCPHub","mcpRouterBaseUrl":"URL de base","mcpRouterBaseUrlDescription":"URL de base pour l'API MCPRouter","mcpRouterBaseUrlPlaceholder":"https://api.mcprouter.to/v1","systemSettings":"Paramètres système","nameSeparatorLabel":"Séparateur de noms","nameSeparatorDescription":"Caractère utilisé pour séparer le nom du serveur et le nom de l'outil/prompt (par défaut : -)","enableSessionRebuild":"Activer la reconstruction de session serveur","enableSessionRebuildDescription":"Lorsqu'il est activé, applique le code de reconstruction de session serveur amélioré pour une meilleure expérience de gestion de session","storeToolPayload":"Stocker le contenu des appels d'outils","storeToolPayloadDescription":"Lorsqu'il est activé, l'entrée et la sortie complètes de chaque appel d'outil sont stockées dans les journaux d'activité. Le contenu des outils est enregistré tel quel, sans masquage ; désactivez cette option si les arguments des outils peuvent contenir des données sensibles à ne pas conserver.","storeToolPayloadUpdateFailed":"Échec de la mise à jour du paramètre de stockage du contenu des outils","restartRequired":"Configuration enregistrée. Il est recommandé de redémarrer l'application pour s'assurer que tous les services chargent correctement les nouveaux paramètres.","exportMcpSettings":"Exporter les paramètres","mcpSettingsJson":"JSON des paramètres MCP","mcpSettingsJsonDescription":"Afficher, copier ou télécharger votre configuration mcp_settings.json actuelle pour la sauvegarde ou la migration vers d'autres outils","copyToClipboard":"Copier dans le presse-papiers","downloadJson":"Télécharger JSON","exportSuccess":"Paramètres exportés avec succès","exportError":"Échec de la récupération des paramètres","enableOauthServer":"Activer le serveur OAuth","enableOauthServerDescription":"Permet à MCPHub d'émettre des jetons OAuth pour les clients externes","requireClientSecret":"Exiger un secret client","requireClientSecretDescription":"Lorsque activé, les clients confidentiels doivent présenter un client secret (désactivez-le pour les clients PKCE publics)","requireState":"Exiger le paramètre state","requireStateDescription":"Refuser les demandes d'autorisation qui n'incluent pas le paramètre state","accessTokenLifetime":"Durée de vie du jeton d'accès (secondes)","accessTokenLifetimeDescription":"Durée pendant laquelle les jetons d'accès émis restent valides","accessTokenLifetimePlaceholder":"ex. 3600","refreshTokenLifetime":"Durée de vie du jeton d'actualisation (secondes)","refreshTokenLifetimeDescription":"Durée pendant laquelle les jetons d'actualisation restent valides","refreshTokenLifetimePlaceholder":"ex. 1209600","authorizationCodeLifetime":"Durée de vie du code d'autorisation (secondes)","authorizationCodeLifetimeDescription":"Temps pendant lequel les codes d'autorisation peuvent être échangés","authorizationCodeLifetimePlaceholder":"ex. 300","allowedScopes":"Scopes autorisés","allowedScopesDescription":"Liste séparée par des virgules des scopes que les utilisateurs peuvent approuver","allowedScopesPlaceholder":"ex. read, write","enableDynamicRegistration":"Activer l'enregistrement dynamique","dynamicRegistrationDescription":"Autoriser les clients conformes RFC 7591 à s'enregistrer via l'endpoint public","dynamicRegistrationAllowedGrantTypes":"Types de flux autorisés","dynamicRegistrationAllowedGrantTypesDescription":"Liste séparée par des virgules des types de flux disponibles pour les clients enregistrés dynamiquement","dynamicRegistrationAllowedGrantTypesPlaceholder":"ex. authorization_code, refresh_token","dynamicRegistrationAuth":"Exiger une authentification","dynamicRegistrationAuthDescription":"Protège l'endpoint d'enregistrement afin que seules les requêtes authentifiées puissent créer des clients","invalidNumberInput":"Veuillez saisir un nombre valide supérieur ou égal à zéro","dynamicRegistrationClientTtl":"TTL de nettoyage des clients inactifs (secondes)","dynamicRegistrationClientTtlDescription":"Réclame les clients enregistrés dynamiquement, sans jeton actif ni flux d'autorisation en cours, plus anciens que cette durée. Mettre à 0 pour désactiver.","dynamicRegistrationClientTtlPlaceholder":"ex. 2592000","smartRoutingIndexTitle":"Index vectoriel et diagnostic","smartRoutingIndexRefresh":"Actualiser","smartRoutingIndexReindex":"Réindexer","smartRoutingIndexReindexing":"Réindexation…","smartRoutingIndexLoading":"Chargement…","smartRoutingIndexNoData":"Aucune donnée d’index. Activez le routage intelligent puis cliquez sur Réindexer pour construire le magasin vectoriel.","smartRoutingIndexStatsUnavailable":"Statistiques indisponibles","smartRoutingIndexDatabase":"Base de données","smartRoutingIndexConnected":"Connectée","smartRoutingIndexDisconnected":"Déconnectée","smartRoutingIndexUnhealthy":"Malsaine","smartRoutingIndexModel":"Modèle","smartRoutingIndexDimensions":"Dimensions","smartRoutingIndexTotalRows":"Lignes totales","smartRoutingIndexToolRows":"Lignes d’outils","smartRoutingIndexServerRows":"Lignes de serveurs","smartRoutingIndexClusterLabel":"Serveurs indexés","smartRoutingIndexCoverage":"Couverture","smartRoutingIndexLastSynced":"Dernière synchro","smartRoutingIndexPerServer":"Outils par serveur","smartRoutingIndexMissingIndex":"{{count}} serveur(s) activé(s) sans index","smartRoutingIndexSyncedRange":"Plage de synchro : {{oldest}} → {{newest}}","smartRoutingIndexReindexDone":"Réindexation terminée : {{synced}} synchronisé(s), {{failed}} échec(s), {{skipped}} ignoré(s), {{total}} outils au total","smartRoutingIndexReindexFailed":"Échec de la réindexation : {{message}}","smartRoutingIndexReindexStarting":"Démarrage de la réindexation…","smartRoutingIndexReindexingServer":"Réindexation de « {{server}} »","smartRoutingIndexReindexSummary":"Réindexation effectuée · {{synced}} synchronisé(s), {{failed}} échec(s), {{skipped}} ignoré(s), {{total}} outils","smartRoutingIndexReindexConfirmTitle":"Reconstruire l’index vectoriel ?","smartRoutingIndexReindexConfirmMessage":"Tous les embeddings existants seront effacés puis régénérés depuis zéro. Cela peut prendre du temps et consommer du quota API d’embedding.","smartRoutingIndexPersonalCredentials":"Serveurs à identifiants personnels","smartRoutingIndexSkippedReason":"Ignoré","smartRoutingIndexIndexedAs":"indexé en tant que {{principals}}","toolPolicies":{"missingReferences":"Certains ID sont absents des serveurs, clés ou groupes chargés. Un refus sans correspondance ne protège pas ; une autorisation sans correspondance peut bloquer l’accès. Vérifiez avant d’enregistrer. Les règles pour de futures ressources restent autorisées.","missingReference":"Règle {{policyId}} : {{selector}} {{value}} introuvable.","title":"Politiques d’accès aux outils","description":"Les règles couvrent la découverte et les appels, y compris le routage intelligent. Elles prennent effet après enregistrement.","semantics":"Un sélecteur vide correspond à tous. Tous les sélecteurs d’une règle doivent correspondre. Les autorisations applicables forment une liste autorisée ; les refus sont prioritaires. Les politiques n’élargissent pas les permissions existantes.","empty":"Aucune politique. Les permissions existantes s’appliquent.","rule":"Règle {{number}}","id":"ID de règle (unique, obligatoire)","effect":"Effet","allow":"Autoriser","deny":"Refuser","username":"Utilisateur","keyId":"ID de clé Bearer","groupId":"ID du groupe du point d’accès","serverId":"ID du serveur","tool":"Nom original de l’outil amont","any":"Tous","selectorsHint":"Choisissez une suggestion ou saisissez une valeur exacte. Les ID résistent aux renommages. Le groupe désigne le point d’accès, pas l’appartenance du serveur. Les noms sont sensibles à la casse, sans préfixe de passerelle ni joker.","add":"Ajouter une règle","save":"Enregistrer les politiques","unsaved":"Modifications non enregistrées. Ajouts et suppressions prennent effet après enregistrement.","invalid":"Chaque règle nécessite un ID unique non vide et un effet valide. Les sélecteurs ne peuvent pas contenir uniquement des espaces.","saveFailed":"Échec de l’enregistrement. Vos modifications sont conservées.","confirm":"Appliquer ces {{count}} politiques immédiatement ? Les outils accessibles aux utilisateurs peuvent changer.","confirmClear":"Supprimer toutes les politiques ? Les permissions existantes s’appliqueront.","deleteRule":"Supprimer la règle {{number}}","retry":"Réessayer"}}`),Pl={upload:"Télécharger",uploadTitle:"Télécharger le bundle MCPB",dropFileHere:"Déposez votre fichier .mcpb ici",orClickToSelect:"ou cliquez pour sélectionner depuis votre ordinateur",invalidFileType:"Veuillez sélectionner un fichier .mcpb valide",noFileSelected:"Veuillez sélectionner un fichier .mcpb à télécharger",uploading:"Téléchargement en cours...",uploadFailed:"Échec du téléchargement du fichier MCPB",installServer:"Installer le serveur MCP depuis MCPB",extensionInfo:"Informations sur l'extension",name:"Nom",version:"Version",description:"Description",author:"Auteur",tools:"Outils",serverName:"Nom du serveur",serverNamePlaceholder:"Entrez un nom pour ce serveur",install:"Installer",installing:"Installation en cours...",installFailed:"Échec de l'installation du serveur depuis MCPB",serverExistsTitle:"Le serveur existe déjà",serverExistsConfirm:"Le serveur '{{serverName}}' existe déjà. Voulez-vous le remplacer par la nouvelle version ?",override:"Remplacer"},Al={button:"Importer",title:"Importer des serveurs depuis JSON",inputLabel:"Configuration JSON du serveur",inputHelp:"Collez votre configuration JSON de serveur. Prend en charge les types de serveurs STDIO, SSE et HTTP (streamable-http).",preview:"Aperçu",previewTitle:"Aperçu des serveurs à importer",import:"Importer",importing:"Importation en cours...",invalidFormat:"Format JSON invalide. Le JSON doit contenir un objet 'mcpServers'.",parseError:"Échec de l'analyse du JSON. Veuillez vérifier le format et réessayer.",addFailed:"Échec de l'ajout du serveur",importFailed:"Échec de l'importation des serveurs",partialSuccess:"{{count}} serveur(s) sur {{total}} importé(s) avec succès. Certains serveurs ont échoué :",validationErrors:"Certains serveurs n'ont pas pu être importés. Veuillez corriger les points suivants et réessayer :"},Rl={button:"Importer",title:"Importer des groupes depuis JSON",inputLabel:"Configuration JSON des groupes",inputHelp:"Collez votre configuration JSON de groupes. Chaque groupe peut contenir une liste de serveurs.",preview:"Aperçu",previewTitle:"Aperçu des groupes à importer",import:"Importer",importing:"Importation en cours...",invalidFormat:"Format JSON invalide. Le JSON doit contenir un tableau 'groups'.",missingName:"Chaque groupe doit avoir un champ 'name'.",parseError:"Échec de l'analyse du JSON. Veuillez vérifier le format et réessayer.",addFailed:"Échec de l'ajout du groupe",importFailed:"Échec de l'importation des groupes",partialSuccess:"{{count}} groupe(s) sur {{total}} importé(s) avec succès. Certains groupes ont échoué :"},Tl={add:"Ajouter un utilisateur",addNew:"Ajouter un nouvel utilisateur",edit:"Modifier l'utilisateur",delete:"Supprimer l'utilisateur",create:"Créer un utilisateur",update:"Mettre à jour l'utilisateur",username:"Nom d'utilisateur",email:"E-mail",emailPlaceholder:"Entrer l'e-mail (optionnel)",password:"Mot de passe",newPassword:"Nouveau mot de passe",confirmPassword:"Confirmer le mot de passe",changePassword:"Changer le mot de passe",adminRole:"Administrateur",admin:"Admin",user:"Utilisateur",role:"Rôle",actions:"Actions",addFirst:"Ajoutez votre premier utilisateur",permissions:"Permissions",adminPermissions:"Accès complet au système",userPermissions:"Accès limité",currentUser:"Vous",noUsers:"Aucun utilisateur trouvé",adminRequired:"Un accès administrateur est requis pour gérer les utilisateurs",usernameRequired:"Le nom d'utilisateur est requis",passwordRequired:"Le mot de passe est requis",passwordTooShort:"Le mot de passe doit comporter au moins 6 caractères",passwordMismatch:"Les mots de passe ne correspondent pas",usernamePlaceholder:"Entrez le nom d'utilisateur",passwordPlaceholder:"Entrez le mot de passe",newPasswordPlaceholder:"Laissez vide pour conserver le mot de passe actuel",confirmPasswordPlaceholder:"Confirmez le nouveau mot de passe",createError:"Échec de la création de l'utilisateur",updateError:"Échec de la mise à jour de l'utilisateur",deleteError:"Échec de la suppression de l'utilisateur",statsError:"Échec de la récupération des statistiques utilisateur",deleteConfirmation:"Êtes-vous sûr de vouloir supprimer l'utilisateur '{{username}}' ? Cette action est irréversible.",confirmDelete:"Supprimer l'utilisateur",deleteWarning:"Êtes-vous sûr de vouloir supprimer l'utilisateur '{{username}}' ? Cette action est irréversible."},xl={errors:{readonly:"Lecture seule pour l'environnement de démonstration",invalid_credentials:"Nom d'utilisateur ou mot de passe invalide",password_login_disabled:"La connexion par mot de passe est désactivée. Connectez-vous via SSO, ou utilisez une clé bearer pour l'accès API.",serverNameRequired:"Le nom du serveur est requis",serverConfigRequired:"La configuration du serveur est requise",serverConfigInvalid:"La configuration du serveur doit inclure une URL, une URL de spécification OpenAPI ou un schéma, ou une commande avec des arguments",serverTypeInvalid:"Le type de serveur doit être l'un des suivants : stdio, sse, streamable-http, openapi",urlRequiredForType:"L'URL est requise pour le type de serveur {{type}}",openapiSpecRequired:"L'URL de la spécification OpenAPI ou le schéma est requis pour le type de serveur openapi",headersInvalidFormat:"Les en-têtes doivent être un objet",headersNotSupportedForStdio:"Les en-têtes ne sont pas pris en charge pour le type de serveur stdio",serverNotFound:"Serveur non trouvé",failedToRemoveServer:"Serveur non trouvé ou échec de la suppression",internalServerError:"Erreur interne du serveur",failedToGetServers:"Échec de la récupération des informations sur les serveurs",failedToGetServerSettings:"Échec de la récupération des paramètres du serveur",failedToGetServerConfig:"Échec de la récupération de la configuration du serveur",failedToSaveSettings:"Échec de l'enregistrement des paramètres",toolNameRequired:"Le nom du serveur et le nom de l'outil sont requis",descriptionMustBeString:"La description doit être une chaîne de caractères",groupIdRequired:"L'ID de groupe est requis",groupNameRequired:"Le nom du groupe est requis",groupNotFound:"Groupe non trouvé",groupIdAndServerNameRequired:"L'ID de groupe和le nom du serveur sont requis",groupOrServerNotFound:"Groupe ou serveur non trouvé",toolsMustBeAllOrArray:'Les outils doivent être "all" ou un tableau de chaînes de caractères',serverNameAndToolNameRequired:"Le nom du serveur et le nom de l'outil sont requis",usernameRequired:"Le nom d'utilisateur est requis",userNotFound:"Utilisateur non trouvé",failedToGetUsers:"Échec de la récupération des informations sur les utilisateurs",failedToGetUserInfo:"Échec de la récupération des informations sur l'utilisateur",failedToGetUserStats:"Échec de la récupération des statistiques de l'utilisateur",marketServerNameRequired:"Le nom du serveur du marché est requis",marketServerNotFound:"Serveur du marché non trouvé",failedToGetMarketServers:"Échec de la récupération des informations sur les serveurs du marché",failedToGetMarketServer:"Échec de la récupération des informations sur le serveur du marché",failedToGetMarketCategories:"Échec de la récupération des catégories du marché",failedToGetMarketTags:"Échec de la récupération des tags du marché",failedToSearchMarketServers:"Échec de la recherche des serveurs du marché",failedToFilterMarketServers:"Échec du filtrage des serveurs du marché",failedToProcessMcpbFile:"Échec du traitement du fichier MCPB"},success:{serverCreated:"Serveur créé avec succès",serverUpdated:"Serveur mis à jour avec succès",serverRemoved:"Serveur supprimé avec succès",serverToggled:"État du serveur basculé avec succès",toolToggled:"Outil {{name}} {{action}} avec succès",toolDescriptionUpdated:"Description de l'outil {{name}} mise à jour avec succès",systemConfigUpdated:"Configuration système mise à jour avec succès",groupCreated:"Groupe créé avec succès",groupUpdated:"Groupe mis à jour avec succès",groupDeleted:"Groupe supprimé avec succès",serverAddedToGroup:"Serveur ajouté au groupe avec succès",serverRemovedFromGroup:"Serveur supprimé du groupe avec succès",serverToolsUpdated:"Outils du serveur mis à jour avec succès"}},wl={authorizationFailed:"Échec de l'autorisation",authorizationFailedError:"Erreur",authorizationFailedDetails:"Détails",invalidRequest:"Requête invalide",missingStateParameter:"Paramètre d'état OAuth requis manquant.",missingCodeParameter:"Paramètre de code d'autorisation requis manquant.",serverNotFound:"Serveur introuvable",serverNotFoundMessage:"Impossible de trouver le serveur associé à cette demande d'autorisation.",sessionExpiredMessage:"La session d'autorisation a peut-être expiré. Veuillez réessayer l'autorisation.",authorizationSuccessful:"Autorisation réussie",server:"Serveur",status:"État",connected:"Connecté",successMessage:"Le serveur a été autorisé et connecté avec succès.",autoCloseMessage:"Cette fenêtre se fermera automatiquement dans 3 secondes...",closeNow:"Fermer maintenant",connectionError:"Erreur de connexion",connectionErrorMessage:"L'autorisation a réussi, mais la connexion au serveur a échoué.",reconnectMessage:"Veuillez essayer de vous reconnecter à partir du tableau de bord.",configurationError:"Erreur de configuration",configurationErrorMessage:"Le transport du serveur ne prend pas en charge OAuth finishAuth(). Veuillez vous assurer que le serveur est configuré avec le transport streamable-http.",internalError:"Erreur interne",internalErrorMessage:"Une erreur inattendue s'est produite lors du traitement du callback OAuth.",closeWindow:"Fermer la fenêtre"},Dl={add:"Ajouter un prompt",addNew:"Ajouter un nouveau prompt",edit:"Modifier le prompt",delete:"Supprimer",noPrompts:"Aucun prompt intégré configuré",addFirst:"Ajoutez votre premier prompt",name:"Nom",namePlaceholder:"ex. code-review",title:"Titre",titlePlaceholder:"ex. Prompt de revue de code",description:"Description",descriptionPlaceholder:"Brève description du prompt",template:"Modèle",templatePlaceholder:"Entrez le texte du modèle avec des marqueurs {{paramètre}}...",templateHint:"Utilisez {{paramName}} pour les paramètres du modèle",arguments:"Arguments",addArgument:"Ajouter un argument",argName:"Nom",argDescription:"Description",argRequired:"Requis",enabled:"Activé",active:"Actif",inactive:"Inactif",nameRequired:"Le nom est requis",templateRequired:"Le modèle est requis",fetchError:"Échec du chargement des prompts intégrés",createError:"Échec de la création du prompt",updateError:"Échec de la mise à jour du prompt",deleteError:"Échec de la suppression du prompt",saveError:"Échec de l'enregistrement du prompt",confirmDelete:"Supprimer le prompt",deleteWarning:'Êtes-vous sûr de vouloir supprimer le prompt "{{name}}" ? Cette action est irréversible.'},El={add:"Ajouter une ressource",addNew:"Ajouter une nouvelle ressource",edit:"Modifier la ressource",delete:"Supprimer",noResources:"Aucune ressource intégrée configurée",addFirst:"Ajoutez votre première ressource",uri:"URI",uriPlaceholder:"ex. resource://docs/guide",name:"Nom",namePlaceholder:"ex. Guide utilisateur",description:"Description",descriptionPlaceholder:"Brève description de la ressource",mimeType:"Type MIME",content:"Contenu",contentPlaceholder:"Entrez le contenu de la ressource...",enabled:"Activé",active:"Actif",inactive:"Inactif",descriptionUpdateSuccess:"Description de la ressource mise à jour avec succès",descriptionUpdateFailed:"Échec de la mise à jour de la description de la ressource",restoreDefault:"Restaurer par défaut",restoreDefaultSuccess:"La description de la ressource a été restaurée à sa valeur par défaut",restoreDefaultFailed:"Échec de la restauration de la description par défaut de la ressource",uriRequired:"L'URI est requis",contentRequired:"Le contenu est requis",fetchError:"Échec du chargement des ressources intégrées",createError:"Échec de la création de la ressource",updateError:"Échec de la mise à jour de la ressource",deleteError:"Échec de la suppression de la ressource",saveError:"Échec de l'enregistrement de la ressource",confirmDelete:"Supprimer la ressource",deleteWarning:'Êtes-vous sûr de vouloir supprimer la ressource "{{name}}" ? Cette action est irréversible.'},Il={title:"Activité",totalCalls:"Total des appels",successCount:"Réussites",errorCount:"Échecs",avgDuration:"Durée moyenne",timestamp:"Horodatage",server:"Serveur",tool:"Outil",duration:"Durée",status:"Statut",group:"Groupe",user:"Utilisateur",key:"Clé API",sourceIp:"IP source",input:"Entrée",output:"Sortie",details:"Détails de l’activité",errorMessage:"Message d’erreur",searchServer:"Serveur...",searchTool:"Outil...",searchStatus:"Statut...",searchGroup:"Groupe...",searchUsername:"Utilisateur...",searchKeyName:"Clé API...",keyName:"Nom de la clé API",allStatus:"Tous les statuts",statusSuccess:"Succès",statusError:"Erreur",noData:"Aucune activité disponible",fetchError:"Impossible de charger les données d’activité",cleanup:"Nettoyer",confirmCleanup:"Voulez-vous vraiment supprimer les activités de plus de 30 jours ?",cleanupSuccess:"{{count}} anciennes activités supprimées",cleanupError:"Échec du nettoyage des anciennes activités",notAvailable:"Le suivi des activités est disponible uniquement en mode base de données"},Nl={exportButton:"Exporter le modèle",importButton:"Importer le modèle",exportTitle:"Exporter le modèle de configuration",importTitle:"Importer le modèle de configuration",name:"Nom du modèle",nameRequired:"Le nom du modèle est requis",namePlaceholder:"Ex. : Outils de développement frontend",description:"Description",descriptionPlaceholder:"Ex. : Serveurs MCP standards pour le développement frontend",selectGroups:"Sélectionner les groupes",selectGroupsHelp:"Laisser vide pour exporter tous les groupes",selectAll:"Tout sélectionner",deselectAll:"Tout désélectionner",includeDisabled:"Inclure les serveurs désactivés",exportNote:"Les secrets (clés API, tokens, mots de passe) seront remplacés par des références ${PLACEHOLDER}. Les destinataires devront fournir leurs propres identifiants.",export:"Exporter",exporting:"Exportation...",exportFailed:"Échec de l'exportation du modèle",import:"Importer",importing:"Importation...",importFailed:"Échec de l'importation du modèle",invalidFormat:"Format de modèle invalide. Doit contenir les champs version, name, servers et groups.",parseError:"Échec de l'analyse JSON. Veuillez vérifier le format et réessayer.",uploadFile:"Télécharger le fichier modèle",or:"ou",pasteJson:"Coller le JSON du modèle",pastePlaceholder:"Collez le contenu de votre fichier .mcphub-template.json ici...",version:"Version",createdAt:"Créé le",servers:"Serveurs",groups:"Groupes",serversInGroup:"serveur(s)",envVarsNeeded:"Variables d'environnement requises — définissez-les avant d'utiliser les serveurs importés :",importResult:"Serveurs : {{serversCreated}} créés, {{serversSkipped}} ignorés. Groupes : {{groupsCreated}} créés, {{groupsSkipped}} ignorés."},Ol={exposed:"Exposé",gross:"Brut",estimate:"Tokens estimés (cl100k) — approximatif",direct:"Direct",smartRouting:"Routage intelligent",smartRoutingPd:"Routage intelligent + divulgation progressive",smartRoutingPdHint:"Ajoute le méta-outil describe_tool — coût initial plus élevé, mais des réponses plus légères par recherche",saved:"{{percent}}% de moins",notConnected:"Non connecté",connectedOf:"{{connected}} sur {{total}} serveurs connectés",totalFootprint:"Empreinte contextuelle"},Ml={title:"Identifiants",missing:"Des identifiants personnels sont requis pour « {{serverName}} ». Associez tous les champs requis dans Tableau de bord → Identifiants.",description:"Associez vos identifiants aux serveurs partagés. Chaque requête utilise les identifiants de son utilisateur.",slots:"Champs d’identifiants personnels",slotsHint:"Déclarez uniquement les noms des champs. Chaque champ est obligatoire, sans repli sur les identifiants de l’organisation.",target:"Destination du champ",urlHint:"Pour les champs URL, utilisez {{placeholder}} comme étiquette d’hôte ou segment de chemin complet et listez les valeurs autorisées.",allowed:"Valeurs autorisées (une par ligne)",argsHint:"Pour les champs d’argument, utilisez {{placeholder}} dans un argument en remplaçant API_KEY par le nom du champ. Les valeurs sont insérées littéralement sans shell.",fieldName:"Nom du champ",label:"Libellé (facultatif)",addSlot:"Ajouter un champ",removeSlot:"Retirer le champ",personalBadge:"Identifiants personnels",manage:"Gérer",configured:"Configuré",required:"Association requise",writeOnly:"Les valeurs enregistrées ne sont jamais affichées. Pour remplacer une association, renseignez tous les champs.",replaceValue:"Nouvelle valeur",enterValue:"Saisir l’identifiant",save:"Enregistrer",delete:"Supprimer l’association",saved:"Association enregistrée",deleted:"Association supprimée",failed:"Impossible de gérer les identifiants",showAll:"Afficher tous les serveurs",loading:"Chargement…",empty:"Aucun serveur partagé ne nécessite d’identifiants personnels.",targetUser:"Gérer les identifiants de",myCredentials:"Mes identifiants",updatedAt:"Dernière mise à jour"},Ll={app:Qs,about:Zs,profile:el,sponsor:rl,wechat:tl,discord:al,theme:nl,auth:il,server:ol,status:sl,errors:ll,common:cl,clientConfig:dl,pagination:ul,nav:ml,pages:pl,logs:hl,groups:gl,market:bl,oauthServer:vl,cloud:yl,registry:fl,tool:kl,prompt:Sl,settings:Cl,mcpb:Pl,jsonImport:Al,groupImport:Rl,users:Tl,api:xl,oauthCallback:wl,builtinPrompts:Dl,builtinResources:El,activity:Il,template:Nl,cost:Ol,credentials:Ml},zl={title:"MCPHub Kontrol Paneli",error:"Hata",closeButton:"Kapat",noServers:"Kullanılabilir MCP sunucusu yok",loading:"Yükleniyor...",logout:"Çıkış Yap",profile:"Profil",changePassword:"Şifre Değiştir",toggleSidebar:"Kenar Çubuğunu Aç/Kapat",welcomeUser:"Hoş geldin, {{username}}",name:"MCPHub",embeddingSyncProgress:"{{serverName}} için gömme oluşturuluyor",embeddingSyncProgressAriaLabel:"{{serverName}} için gömme oluşturuluyor: {{total}} adımdan {{current}} tamamlandı"},Ul={title:"Hakkında",versionInfo:"MCPHub Sürümü: {{version}}",newVersion:"Yeni sürüm mevcut!",currentVersion:"Mevcut sürüm",newVersionAvailable:"Yeni sürüm {{version}} mevcut",viewOnGitHub:"GitHub'da Görüntüle",checkForUpdates:"Güncellemeleri Kontrol Et",checking:"Güncellemeler kontrol ediliyor...",viewChangelog:"Değişiklik günlüğünü görüntüle",viewReleaseNotes:"Sürüm notlarını görüntüle",viewAllChanges:"Tüm değişiklikleri görüntüle",latestChanges:"Son değişiklikler",upToDate:"Bilinen en son sürümü kullanıyorsunuz.",releaseNotesUnavailable:"Daha yeni bir sürüm var, ancak yapılandırılmış sürüm notları henüz yok.",updateChecksDisabled:"Bu dağıtımda güncelleme kontrolü devre dışı.",dismissUpdate:"Yoksay",dismissed:"Yoksayıldı",earlierReleases:"+ {{count}} önceki sürüm"},ql={viewProfile:"Profili görüntüle",userCenter:"Kullanıcı Merkezi"},Bl={label:"Sponsor",title:"Projeyi Destekle",rewardAlt:"Ödül QR Kodu",supportMessage:"Bana bir kahve ısmarlayarak MCPHub'ın geliştirilmesini destekleyin!",supportButton:"Ko-fi'de Destek Ol"},Fl={label:"WeChat",title:"WeChat ile Bağlan",qrCodeAlt:"WeChat QR Kodu",scanMessage:"WeChat'te bizimle bağlantı kurmak için bu QR kodunu tarayın"},Kl={label:"Discord",title:"Discord sunucumuza katılın",community:"Destek, tartışmalar ve güncellemeler için büyüyen Discord topluluğumuza katılın!"},jl={title:"Tema",light:"Açık",dark:"Koyu",system:"Sistem"},Gl={createAccount:"Hesap oluştur",backToLogin:"Girişe dön",userAlreadyExists:"Kullanıcı adı zaten mevcut",login:"Giriş Yap",loginTitle:"MCPHub'a Giriş Yap",slogan:"Açık kaynaklı, kendi kendine barındırılan MCP ağ geçidi ve kontrol düzlemi",subtitle:"Model Context Protocol sunucularını birleşik uç noktalar üzerinden bağlayın, düzenleyin, kontrol edin ve işletin.",username:"Kullanıcı Adı",password:"Şifre",loggingIn:"Giriş yapılıyor...",orContinue:"Veya şununla devam et",loginWithGoogle:"Google ile devam et",loginWithGithub:"GitHub ile devam et",loginWithOIDC:"OIDC ile devam et",socialLoginFailed:"Sosyal giriş başarısız oldu. Lütfen tekrar deneyin.","error.account_not_linked":"Hesap bağlanmadı. E-postanız kimlik sağlayıcı tarafından doğrulanmamış olabilir. Lütfen e-postanızı doğrulayın ve tekrar deneyin.","error.email_doesn't_match":"Kimlik sağlayıcıdan gelen e-posta mevcut hesabınızla eşleşmiyor.","error.email_not_found":"Kimlik sağlayıcıdan e-posta alınamadı.","error.access_denied":"Kimlik sağlayıcı tarafından erişim reddedildi.","error.account_already_linked_to_different_user":"Bu hesap zaten başka bir kullanıcıya bağlı.","error.unable_to_link_account":"Hesap bağlanamıyor. Lütfen tekrar deneyin.","error.signup_disabled":"Kayıt şu anda devre dışı.","error.oauth_provider_not_found":"OAuth sağlayıcı bulunamadı.","error.invalid_code":"Geçersiz yetkilendirme kodu. Lütfen tekrar deneyin.","error.unable_to_get_user_info":"Kimlik sağlayıcıdan kullanıcı bilgileri alınamıyor.",emptyFields:"Kullanıcı adı ve şifre boş olamaz",loginFailed:"Giriş başarısız, lütfen kullanıcı adınızı ve şifrenizi kontrol edin",loginError:"Giriş sırasında bir hata oluştu",serverUnavailable:"Sunucuya bağlanılamıyor. Lütfen ağ bağlantınızı kontrol edin veya daha sonra tekrar deneyin",currentPassword:"Mevcut Şifre",newPassword:"Yeni Şifre",confirmPassword:"Şifreyi Onayla",passwordsNotMatch:"Yeni şifre ve onay eşleşmiyor",changePasswordSuccess:"Şifre başarıyla değiştirildi",changePasswordError:"Şifre değişikliği başarısız oldu",changePassword:"Şifre Değiştir",passwordChanged:"Şifre başarıyla değiştirildi",passwordChangeError:"Şifre değişikliği başarısız oldu",defaultPasswordWarning:"Varsayılan Şifre Güvenlik Uyarısı",defaultPasswordMessage:"Varsayılan şifreyi (admin123) kullanıyorsunuz, bu bir güvenlik riski oluşturur. Hesabınızı korumak için lütfen şifrenizi hemen değiştirin.",goToSettings:"Ayarlara Git",passwordStrengthError:"Şifre güvenlik gereksinimlerini karşılamıyor",passwordMinLength:"Şifre en az 8 karakter uzunluğunda olmalıdır",passwordRequireLetter:"Şifre en az bir harf içermelidir",passwordRequireNumber:"Şifre en az bir rakam içermelidir",passwordRequireSpecial:"Şifre en az bir özel karakter içermelidir",passwordStrengthHint:"Şifre en az 8 karakter olmalı ve harf, rakam ve özel karakter içermelidir"},Hl=JSON.parse(`{"protocolVersion":"MCP protokolü","protocolVersionUnknown":"Mevcut değil","localExecutionRequiresAdmin":"Yerel komut çalıştırmak yönetici yetkisi gerektirir.","httpOAuthRequiresAdmin":"HTTP OAuth belirteç uç noktalarına izin vermek yönetici yetkisi gerektirir.","startOnDemand":"Talep üzerine başlat","startOnDemandDescription":"Başlangıçtaki bağlantıyı atla ve bu sunucuyu yalnızca bir araç çağrısı geldiğinde başlat. İşlem, boşta kalma zaman aşımından sonra otomatik olarak kapatılır ve bir sonraki çağrıda yeniden başlatılır. Seyrek kullanılan sunucularda kalıcı bellek kullanımını azaltır.","idleTimeoutMs":"Boşta kapatma zaman aşımı (ms)","idleTimeoutMsDescription":"Araç çağrısı olmadan bu kadar milisaniye geçtikten sonra işlemi kapat. Varsayılan: 300000 (5 dakika).","addServer":"Sunucu Ekle","add":"Ekle","edit":"Düzenle","copy":"Kopyala","duplicate":"Çoğalt","delete":"Sil","confirmDelete":"Bu sunucuyu silmek istediğinizden emin misiniz?","deleteWarning":"'{{name}}' sunucusunu silmek, onu ve tüm verilerini kaldıracaktır. Bu işlem geri alınamaz.","status":"Durum","tools":"Araçlar","prompts":"İstekler","name":"Sunucu Adı","nameInvalid":"Sunucu adı yalnızca harf, rakam, nokta, alt çizgi ve tire içerebilir (boşluk veya özel karakter içeremez)","description":"Sunucu Notu","descriptionPlaceholder":"İsteğe bağlı: Bu sunucunun ne işe yaradığını yazın","url":"Sunucu URL'si","apiKey":"API Anahtarı","save":"Kaydet","cancel":"İptal","invalidConfig":"{{serverName}} için yapılandırma verisi bulunamadı","addError":"Sunucu eklenemedi","editError":"{{serverName}} sunucusu düzenlenemedi","deleteError":"{{serverName}} sunucusu silinemedi","updateError":"Sunucu güncellenemedi","editTitle":"Sunucuyu Düzenle: {{serverName}}","duplicateTitle":"Sunucuyu Çoğalt: {{serverName}}","type":"Sunucu Türü","typeStdio":"STDIO","typeSse":"SSE","typeStreamableHttp":"Akış Yapılabilir HTTP","typeOpenapi":"OpenAPI","mcpApp":"MCP App — bu sunucu etkileşimli UI kaynakları sunar","visibility":"Görünürlük","visibilityPrivateShort":"Özel","visibilityPrivate":"Özel — yalnızca sahibi ve yöneticiler","visibilityGroupShort":"Paylaşılan","visibilityGroup":"Paylaşılan — yalnızca seçilen kullanıcılar","visibilityPublicShort":"Herkese açık","visibilityPublic":"Herkese açık — kimliği doğrulanmış tüm kullanıcılar","visibilityDescription":"Yönetici olmayan hangi kullanıcıların bu sunucuyu bulup çağırabileceğini denetler. Yöneticiler her zaman erişebilir.","shareWithUsers":"Kullanıcılarla paylaş","shareWithUsersDescription":"Seçilen kullanıcılar bu sunucuyu bulup çağırabilir, ancak yapılandırmasını yönetemez.","shareCandidatesLoading":"Kullanıcılar yükleniyor...","shareCandidatesError":"Kullanıcılar yüklenemedi.","shareAfterCreate":"Kullanıcı seçmeden önce sunucuyu kaydedin.","noShareCandidates":"Başka kullanılabilir kullanıcı yok.","shareUserSearchLabel":"Kullanıcıları ara","shareUserSearchPlaceholder":"Kullanıcı adlarını ara...","selectAllShareUsers":"Tümünü seç","deselectAllShareUsers":"Tümünün seçimini kaldır","noMatchingShareUsers":"Aramanızla eşleşen kullanıcı yok.","command":"Komut","packageVersion":"Kurulu paket sürümü (runner önbelleğindeki son kurulum)","reportedVersion":"Sunucu tarafından bildirilen sürüm","updateAvailable":"Kayıt defterinde daha yeni bir sürüm mevcut","arguments":"Argümanlar","addArgument":"Argüman ekle","argumentsHint":"Her alan bir argümandır. Boşluklar ve tırnaklar korunur; boş bir alan boş bir argüman iletir.","argumentLabel":"Argüman {{index}}","removeArgument":"Argüman {{index}} kaldır","envVars":"Ortam Değişkenleri","headers":"HTTP Başlıkları","key":"anahtar","value":"değer","enabled":"Etkin","enable":"Etkinleştir","disable":"Devre Dışı Bırak","reload":"Yeniden Yükle","reloadSuccess":"Sunucu başarıyla yeniden yüklendi","reloadError":"Sunucu {{serverName}} yeniden yüklenemedi","reinstall":"Yeniden Kur","reinstallConfirm":"Bu işlem paket önbelleğini temizleyecek ve bağımlılıkları yeniden indirecektir. Sunucu yeniden başlatılacaktır.","reinstallSuccess":"Sunucu yeniden kurulumu başlatıldı","reinstallError":"Sunucu {{serverName}} yeniden kurulamadı","disconnectOAuth":"OAuth Bağlantısını Kes","disconnectOAuthConfirm":"Bu işlem, desteklendiğinde saklanan OAuth kimlik bilgilerini iptal eder ve yeniden yetkilendirme gerektirir.","disconnectOAuthSuccess":"Sunucu OAuth bağlantısı kesildi","disconnectOAuthError":"{{serverName}} sunucusunun OAuth bağlantısı kesilemedi","requestOptions":"Bağlantı Yapılandırması","maxBufferSize":"Stdio arabellek sınırı (bayt)","maxBufferSizeDescription":"Stdio okuma arabelleğinin en büyük boyutu. SDK varsayılanı (10 MiB) için boş bırakın. Daha yüksek sınırlar daha fazla bellek kullanımına izin verir.","timeout":"İstek Zaman Aşımı","timeoutDescription":"MCP sunucusuna yapılan istekler için zaman aşımı (ms)","maxTotalTimeout":"Maksimum Toplam Zaman Aşımı","maxTotalTimeoutDescription":"MCP sunucusuna gönderilen istekler için maksimum toplam zaman aşımı (ms) (İlerleme bildirimleriyle kullanın)","resetTimeoutOnProgress":"İlerlemede Zaman Aşımını Sıfırla","resetTimeoutOnProgressDescription":"İlerleme bildirimlerinde zaman aşımını sıfırla (varsayılan olarak etkin)","keepAlive":"Bağlantı Sağlığı","retryScheduled":"{{time}} saatinde yeniden deneme","reconnecting":"Yeniden bağlanıyor…","lastRetry":"Son deneme: {{time}} ({{count}} deneme)","enableKeepAlive":"Sağlık Denetimlerini Etkinleştir","keepAliveDescription":"Bağlantıyı düzenli olarak denetleyin. Bağlantısı kesilen uzak sunucular artan bekleme süreleriyle otomatik olarak yeniden bağlanır.","keepAliveInterval":"Denetim aralığı (ms)","keepAliveIntervalDescription":"Sağlık denetimleri arasındaki süre (varsayılan: 60000ms = 1 dakika)","perSessionClient":"Oturum Başına İstemci Yalıtımı","perSessionClientDescription":"Tüm oturumlar arasında tek bir bağlantı paylaşmak yerine her oturum için ayrı bir yukarı akış bağlantısı oluşturun. Playwright gibi durum bilgili sunucular için etkinleştirin. Eşzamanlı oturumlarla birlikte yukarı akış bağlantı sayısını artırır.","remove":"Kaldır","toggleError":"{{serverName}} sunucusu açılamadı/kapatılamadı","alreadyExists":"{{serverName}} sunucusu zaten mevcut","invalidData":"Geçersiz sunucu verisi sağlandı","notFound":"{{serverName}} sunucusu bulunamadı","namePlaceholder":"Sunucu adını girin","urlPlaceholder":"Sunucu URL'sini girin","commandPlaceholder":"Komutu girin","argumentsPlaceholder":"Argümanları girin","errorDetails":"Hata Detayları","viewErrorDetails":"Hata detaylarını görüntüle","copyConfig":"Yapılandırmayı Kopyala","confirmVariables":"Değişken Yapılandırmasını Onayla","variablesDetected":"Yapılandırmada değişkenler algılandı. Lütfen bu değişkenlerin düzgün yapılandırıldığını onaylayın:","detectedVariables":"Algılanan Değişkenler","confirmVariablesMessage":"Lütfen bu değişkenlerin çalışma ortamınızda düzgün tanımlandığından emin olun. Sunucu eklemeye devam edilsin mi?","confirmAndAdd":"Onayla ve Ekle","openapi":{"inputMode":"Giriş Modu","inputModeUrl":"Şartname URL'si","inputModeSchema":"JSON Şeması","specUrl":"OpenAPI Şartname URL'si","schema":"OpenAPI JSON Şeması","schemaHelp":"Eksiksiz OpenAPI JSON şemanızı buraya yapıştırın","security":"Güvenlik Türü","securityNone":"Yok","securityApiKey":"API Anahtarı","securityHttp":"HTTP Kimlik Doğrulaması","securityOAuth2":"OAuth 2.0","securityOpenIdConnect":"OpenID Connect","securityDetect":"Spec'ten algıla","securityDetecting":"Algılanıyor…","securityNotDeclared":"Bu spec bir güvenlik şeması bildirmiyor.","securityPrefillNotice":"Bu spec {{summary}} bildiriyor. Güvenlik ayarları önceden dolduruldu — ilk çağrıdan önce kimlik bilginizi ekleyin.","securityMismatchWarning":"Spec {{summary}} bildiriyor, ancak bu sunucu {{configured}} olarak yapılandırılmış. Bu, sessiz 401 yanıtlarına neden olabilir.","securityUnsupportedNotice":"Bu spec {{summary}} bildiriyor; MCPHub bunu temsil edemiyor ({{reason}}). Kimlik doğrulamayı elle yapılandırın.","apiKeyConfig":"API Anahtarı Yapılandırması","apiKeyName":"Başlık/Parametre Adı","apiKeyIn":"Konum","apiKeyValue":"API Anahtarı Değeri","httpAuthConfig":"HTTP Kimlik Doğrulama Yapılandırması","httpScheme":"Kimlik Doğrulama Şeması","httpCredentials":"Kimlik Bilgileri","httpCredentialsBasicHint":"kullanıcı:şifre (otomatik kodlanır) veya önceden kodlanmış Base64 girin.","specSecurityToggle":"Şartname URL'si ayrı kimlik doğrulama gerektirir","specSecurityHelp":"Yalnızca şartname belgesi API'den farklı şekilde korunuyorsa etkinleştirin (örn. Bearer korumalı API arkasında Basic ile korunan /v3/api-docs). Kapalıyken yukarıdaki güvenlik yapılandırması her ikisi için de kullanılır.","httpSchemeBasic":"Basit","httpSchemeBearer":"Bearer","httpSchemeDigest":"Digest","oauth2Config":"OAuth 2.0 Yapılandırması","oauth2Token":"Erişim Anahtarı","openIdConnectConfig":"OpenID Connect Yapılandırması","openIdConnectUrl":"URL'yi Keşfet","openIdConnectToken":"ID Token","apiKeyInHeader":"Başlık","apiKeyInQuery":"Sorgu","apiKeyInCookie":"Çerez","passthroughHeaders":"Geçiş Başlıkları","passthroughHeadersHelp":"Gelen MCP isteklerinden yukarı akış sunucu isteklerine geçirilecek başlık adlarının virgülle ayrılmış listesi (örn. Authorization, X-API-Key)","cookieSession":"Cookie Oturum Yönetimi","cookieSessionHelp":"Yukarı akış oturum açma yanıtlarındaki Set-Cookie değerini yakalar ve aynı aşağı akış oturumundaki sonraki çağrılarda yeniden gönderir. MCP oturumu başına izole edilir; kalıcı değildir.","statsMeasuring":"Oluşturulan araç listesi ölçülüyor…","statsSummary":"{{toolCount}} araç · tanımlar ~{{bytes}} · ~{{tokens}} token","statsWarning":"Bu araç listesi tek başına yaygın model bağlam pencerelerine yaklaşabilir veya bunları aşabilir. Daha az araç göstermeyi düşünün: bir grup oluşturun veya sunucuda tek tek araçları devre dışı bırakın.","statsUnavailable":"Belirtim ölçülemedi. Devam edebilirsiniz; sunucu gönderim sırasında içe aktarmayı doğrular."},"oauth":{"sectionTitle":"OAuth Yapılandırması","sectionDescription":"OAuth korumalı sunucular için istemci kimlik bilgilerini yapılandırın (isteğe bağlı).","allowInsecureTokenEndpoint":"HTTP OAuth token uç noktalarına izin ver","allowInsecureTokenEndpointHelp":"Yalnızca yöneticiler. Varsayılan olarak kapalıdır. Bu sunucunun kimlik bilgileri ve tokenları TLS olmadan gönderilir. Yalnızca güvenilir bir ağda etkinleştirin; HTTPS önerilir. Etkinleştirildiğinde, yönetici olmayan sahibi dahil yalnızca yöneticiler bu sunucunun tüm yapılandırmasını düzenleyebilir.","clientId":"İstemci ID","clientSecret":"İstemci Gizli Anahtarı","authorizationEndpoint":"Yetkilendirme Uç Noktası","tokenEndpoint":"Token Uç Noktası","scopes":"Kapsamlar","scopesPlaceholder":"scope1 scope2","resource":"Kaynak / Hedef Kitle","accessToken":"Erişim Tokeni","refreshToken":"Yenileme Tokeni","identityMode":"OAuth kimliği","sharedIdentity":"Paylaşılan hesap","personalIdentity":"Her kullanıcı ayrı yetkilendirir","personalIdentityHelp":"Her kullanıcı panelde yetkilendirmelidir. Kullanıcı anahtarları sahibinin kimliğini kullanır; paylaşılan anahtarlar desteklenmez.","personalConnect":"Yetkilendir","personalReconnect":"Yeniden yetkilendir","personalDisconnect":"Bağlantıyı kes","personalError":"Kişisel yetkilendirme başarısız","personalSuccess":"Kişisel yetkilendirme kaydedildi. Panel → Sunucular bölümüne dönün."}}`),_l={sleeping:"Uykuda",sleepingDescription:"Talep üzerine sunucu - bir araç çağrıldığında otomatik olarak başlar",online:"Çevrimiçi",offline:"Çevrimdışı",connecting:"Bağlanıyor",oauthRequired:"OAuth Gerekli",clickToAuthorize:"OAuth ile yetkilendirmek için tıklayın",oauthWindowOpened:"OAuth yetkilendirme penceresi açıldı. Lütfen yetkilendirmeyi tamamlayın.",oauthClientIdHint:`Bu sunucuda önceden yapılandırılmış bir OAuth istemci kimliği var. Yetkilendirme "invalid redirect_uri" hatasıyla başarısız olursa, MCPHub'ın kendi OAuth istemcisini otomatik olarak kaydedebilmesi için clientId'yi kaldırın.`},Vl={general:"Bir şeyler yanlış gitti",network:"Ağ bağlantı hatası. Lütfen internet bağlantınızı kontrol edin",serverConnection:"Sunucuya bağlanılamıyor. Lütfen sunucunun çalışıp çalışmadığını kontrol edin",serverAdd:"Sunucu eklenemedi. Lütfen sunucu durumunu kontrol edin",serverUpdate:"{{serverName}} sunucusu düzenlenemedi. Lütfen sunucu durumunu kontrol edin",serverFetch:"Sunucu verileri alınamadı. Lütfen daha sonra tekrar deneyin",failedToReloadServer:"Sunucu yeniden yüklenemedi",initialStartup:"Sunucu başlatılıyor olabilir. İlk başlatmada bu işlem biraz zaman alabileceğinden lütfen bekleyin...",serverInstall:"Sunucu yüklenemedi",failedToFetchSettings:"Ayarlar getirilemedi",failedToUpdateRouteConfig:"Route yapılandırması güncellenemedi",failedToUpdateSmartRoutingConfig:"Akıllı yönlendirme yapılandırması güncellenemedi",failedToUpdateBetterAuthConfig:"Better Auth yapılandırması güncellenemedi"},$l={processing:"İşleniyor...",save:"Kaydet",cancel:"İptal",back:"Geri",refresh:"Yenile",search:"Ara",clear:"Temizle",view:"Görüntüle",create:"Oluştur",creating:"Oluşturuluyor...",update:"Güncelle",updating:"Güncelleniyor...",submitting:"Gönderiliyor...",delete:"Sil",remove:"Kaldır",copy:"Kopyala",copyId:"ID'yi Kopyala",copyUrl:"URL'yi Kopyala",copyOpenApiUrl:"OpenAPI URL'sini Kopyala",copySuccess:"Panoya kopyalandı",copyFailed:"Kopyalama başarısız",copied:"Kopyalandı",close:"Kapat",confirm:"Onayla",language:"Dil",true:"Doğru",false:"Yanlış",dismiss:"Anımsatma",github:"GitHub",wechat:"WeChat",discord:"Discord",itemsPerPage:"Sayfa başına öğe",showing:"{{total}} öğeden {{start}}-{{end}} gösteriliyor",previous:"Önceki",next:"Sonraki",required:"Gerekli",secret:"Gizli",default:"Varsayılan",value:"Değer",type:"Tür",repeated:"Tekrarlanan",valueHint:"Değer İpucu",choices:"Seçenekler",actions:"Eylemler",saving:"Kaydediliyor...",active:"Aktif",inactive:"Pasif",viewAll:"Tümünü gör",docs:"Belgeler",all:"Tümü"},Jl={title:"MCP yapılandırmasını kopyala",description:"{{name}} için doğrudan yapıştırılabilir yapılandırmayı kopyalamak üzere istemcinizi seçin.",menuItem:"MCP yapılandırmasını kopyala",tokenPrompt:"MCPHub erişim jetonu",configBlock:"Yapılandırma",commandBlock:"CLI komutu",copied:"Kopyalandı",noTransport:"Bu sunucunun istemci tarafı bir MCP taşıması yok (OpenAPI desteklidir). Bunun yerine hub'ı veya bir grup uç noktasını kullanın.",clients:{"generic-mcp-servers":{label:"Genel (mcpServers)",hint:"Yaygın kabul gören mcpServers bloğu: Claude Desktop, Cline, Cherry Studio ve çoğu istemci."},"generic-http":{label:"Genel HTTP",hint:'Ham girdiyle çıkış yolu: uzak uç nokta ham bir HTTP girdisi (SSE üzerinde "type": "sse" işaretini taşır), yerel sunucu ham bir stdio girdisi (command/args/env) verir. İstemcinin kendi sunucu tablosuna yapıştırın; çoğu istemci için Genel (mcpServers) sekmesini kullanın.'},"claude-code":{label:"Claude Code",hint:"Claude Code: `claude mcp add` veya ~/.claude.json içindeki mcpServers bloğu."},cursor:{label:"Cursor",hint:"Cursor: proje içinde .cursor/mcp.json veya genel olarak ~/.cursor/mcp.json."},vscode:{label:"VS Code / Copilot",hint:"VS Code / Copilot: çalışma alanında .vscode/mcp.json veya kullanıcı profilinizdeki mcp.json."},codex:{label:"Codex",hint:"Codex: ~/.codex/config.toml veya proje düzeyinde .codex/config.toml."},opencode:{label:"OpenCode",hint:"OpenCode: genel olarak ~/.config/opencode/opencode.json veya proje içinde opencode.json."},windsurf:{label:"Windsurf",hint:"Windsurf: ~/.codeium/windsurf/mcp_config.json."},"cherry-studio":{label:"Cherry Studio",hint:"Cherry Studio: Ayarlar > MCP Sunucuları > Sunucu Ekle > JSON İçe Aktar."},codebuddy:{label:"CodeBuddy Code",hint:"CodeBuddy Code: genel olarak ~/.codebuddy/.mcp.json veya proje içinde .mcp.json."},qoder:{label:"Qoder",hint:"Qoder: Ayarlar > MCP > Elle Ekle, ardından JSON'u yapıştırın."},trae:{label:"TRAE",hint:"TRAE: Ayarlar > MCP > Ekle > Elle Ekle, ardından JSON'u yapıştırın."},zcode:{label:"ZCode",hint:"ZCode: Ayarlar > MCP Sunucuları > Yeni MCP Sunucusu > Tam yapılandırma."},workbuddy:{label:"WorkBuddy",hint:"WorkBuddy: Eklentiler > MCP Sunucuları > MCP Yapılandır veya ~/.workbuddy/mcp.json."}}},Wl={rowsPerPage:"Sayfa başına satır",showing:"Toplam {{total}} öğeden {{from}}-{{to}} gösteriliyor"},Yl={dashboard:"Kontrol Paneli",servers:"Sunucular",groups:"Gruplar",prompts:"Promptlar",resources:"Kaynaklar",users:"Kullanıcılar",settings:"Ayarlar",changePassword:"Şifre Değiştir",market:"Market",cloud:"Bulut Market",logs:"Günlükler",activity:"Etkinlik",workspace:"Çalışma Alanı",system:"Sistem"},Xl={dashboard:{title:"Kontrol Paneli",totalServers:"Toplam",onlineServers:"Çevrimiçi",disabledServers:"Devre Dışı",offlineServers:"Çevrimdışı",connectingServers:"Bağlanıyor",recentServers:"Son Sunucular"},servers:{title:"Sunucu Yönetimi"},groups:{title:"Grup Yönetimi"},prompts:{title:"Yerleşik Promptlar"},resources:{title:"Yerleşik Kaynaklar"},users:{title:"Kullanıcı Yönetimi"},settings:{title:"Ayarlar",language:"Dil",account:"Hesap Ayarları",password:"Şifre Değiştir",appearance:"Görünüm",routeConfig:"Güvenlik",installConfig:"Kurulum",smartRouting:"Akıllı Yönlendirme",oauthServer:"OAuth Sunucusu"},market:{title:"Market Yönetimi - Yerel ve Bulut Marketler"},logs:{title:"Sistem Günlükleri"}},Ql={filters:"Filtreler",search:"Günlüklerde ara...",autoScroll:"Otomatik kaydır",clearLogs:"Günlükleri temizle",loading:"Günlükler yükleniyor...",noLogs:"Kullanılabilir günlük yok.",noMatch:"Mevcut filtrelerle eşleşen günlük yok.",mainProcess:"Ana İşlem",childProcess:"Alt İşlem",main:"Ana",child:"Alt"},Zl={legacyVisibility:"Eski grup — görünürlük seçin",legacyVisibilityHint:"Görünürlüğü açıkça seçene kadar bu grup önceki erişim kurallarını korur.",visibilityDescription:"Grup erişimi, her sunucuya erişim de gerektirir. Grubu paylaşmak özel sunucuları paylaşmaz. Grubu yalnızca sahibi ve yöneticiler yönetebilir.",shareAfterCreate:"Kullanıcıları seçmeden önce grubu kaydedin.",add:"Ekle",addNew:"Yeni Grup Ekle",edit:"Grubu Düzenle",delete:"Sil",confirmDelete:"Bu grubu silmek istediğinizden emin misiniz?",deleteWarning:"'{{name}}' grubunu silmek, onu ve tüm sunucu ilişkilerini kaldıracaktır. Bu işlem geri alınamaz.",name:"Grup Adı",namePlaceholder:"Grup adını girin",instructions:"Talimatlar",instructionsHelp:"İsteğe bağlı. MCP istemcileri bu gruba bağlandığında ($smart/<group> dahil) gönderilir; çoğu istemci bunu modelin sistem istemine ekler.",instructionsPlaceholder:"Ör: Web sayfaları için fetch kullanın; başarısız olursa firecrawl_scrape.",nameRequired:"Grup adı gereklidir",description:"Açıklama",descriptionPlaceholder:"Grup açıklamasını girin (isteğe bağlı)",createError:"Grup oluşturulamadı",updateError:"Grup güncellenemedi",deleteError:"Grup silinemedi",serverAddError:"Sunucu gruba eklenemedi",serverRemoveError:"Sunucu gruptan kaldırılamadı",addServer:"Gruba Sunucu Ekle",selectServer:"Eklenecek bir sunucu seçin",servers:"Gruptaki Sunucular",remove:"Kaldır",noGroups:"Kullanılabilir grup yok. Başlamak için yeni bir grup oluşturun.",noServers:"Bu grupta sunucu yok.",noServerOptions:"Kullanılabilir sunucu yok",serverCount:"{{count}} Sunucu",toolSelection:"Araç Seçimi",promptSelection:"İstem Seçimi",resourceSelection:"Kaynak Seçimi",toolsSelected:"Seçildi",promptsSelected:"Seçildi",resourcesSelected:"Seçildi",allTools:"Tümü",allPrompts:"Tüm istemler",allResources:"Tüm kaynaklar",selectedTools:"Seçili araçlar",selectedPrompts:"Seçili istemler",selectedResources:"Seçili kaynaklar",selectAll:"Tümünü Seç",selectNone:"Hiçbirini Seçme",configureTools:"Araçları Yapılandır",configureCapabilities:"Araçları, istemleri ve kaynakları yapılandır",alias:"Açık Ad",preserveToolNames:"Özgün araç adlarını koru",preserveToolNamesHint:"Araçları sunucu öneki olmadan sunar. Araç adları grupta benzersiz olmalıdır. Açık ad, istemler için geçerli kalır.",pinTool:"Sabitle: bu aracı grubun Akıllı Yönlendirme uç noktasında search_tools'un yanında her zaman listele",pinToolLabel:"Akıllı Yönlendirme uç noktasına sabitle",unpinTool:"Sabitlemeyi kaldır: bu araca yalnızca search_tools ile ulaş",previewPrompts:"[istemler: {{items}}]",previewResources:"[kaynaklar: {{items}}]",previewAllTools:"(tüm araçlar)",previewAllPrompts:"(tüm istemler)",previewAllResources:"(tüm kaynaklar)",bulkSearch:"Ada veya açıklamaya göre ara…",bulkSearchLabel:"{{capability}} içinde ara",annotationFilter:"Ek açıklamaya göre filtrele",allAnnotations:"Tüm ek açıklamalar",readOnlyHint:"Salt okunur ipucu",destructiveHint:"Yıkıcı işlem ipucu",idempotentHint:"İdempotent işlem ipucu",flatList:"Düz liste",riskGroups:"Risk grupları",visibleCount:"{{total}} öğeden {{count}} görünür",selectVisible:"Görünenleri seç",deselectVisible:"Görünenlerin seçimini kaldır",invertVisible:"Görünenleri tersine çevir",riskHint:"Gruplar sunucu ipuçlarına ve ad tahminlerine dayanır; güvenliği garanti etmez. İşlemler yalnızca filtrelenen öğeleri etkiler.",noMatchingItems:"Eşleşen öğe yok",risk_read:"Okuma",risk_create:"Oluşturma",risk_update:"Güncelleme",risk_delete:"Silme",risk_other:"Diğer / sınıflandırılmamış"},ec={title:"Yerel Kurulum",official:"Resmi",by:"Geliştirici",unknown:"Bilinmeyen",tools:"araçlar",search:"Ara",searchPlaceholder:"Sunucuları isme, kategoriye veya etiketlere göre ara",clearFilters:"Temizle",clearCategoryFilter:"",clearTagFilter:"",categories:"Kategoriler",tags:"Etiketler",showTags:"Etiketleri göster",hideTags:"Etiketleri gizle",moreTags:"",noServers:"Aramanızla eşleşen sunucu bulunamadı",backToList:"Listeye dön",install:"Yükle",installing:"Yükleniyor...",installed:"Yüklendi",installServer:"Sunucu Yükle: {{name}}",installSuccess:"{{serverName}} sunucusu başarıyla yüklendi",author:"Yazar",license:"Lisans",repository:"Depo",examples:"Örnekler",arguments:"Argümanlar",argumentName:"Ad",description:"Açıklama",required:"Gerekli",example:"Örnek",viewSchema:"Şemayı görüntüle",fetchError:"Market sunucuları getirilirken hata",serverNotFound:"Sunucu bulunamadı",searchError:"Sunucular aranırken hata",filterError:"Sunucular kategoriye göre filtrelenirken hata",tagFilterError:"Sunucular etikete göre filtrelenirken hata",noInstallationMethod:"Bu sunucu için kullanılabilir kurulum yöntemi yok",showing:"{{total}} sunucudan {{from}}-{{to}} arası gösteriliyor",perPage:"Sayfa başına",confirmVariablesMessage:"Lütfen bu değişkenlerin çalışma ortamınızda düzgün tanımlandığından emin olun. Sunucu yüklemeye devam edilsin mi?",confirmAndInstall:"Onayla ve Yükle"},rc={authorizeTitle:"Uygulamayı Yetkilendir",authorizeSubtitle:"Bu uygulamanın MCPHub hesabınıza erişmesine izin verin.",buttons:{approve:"Erişime izin ver",deny:"Reddet",approveSubtitle:"Bu uygulamaya güveniyorsanız izin vermeniz önerilir.",denySubtitle:"İstediğiniz zaman daha sonra erişim verebilirsiniz."},application:"Uygulama",scopesTitle:"Bu uygulama şunları yapabilecek:",noScopes:"İzin istenmedi.",requestInvalidTitle:"Geçersiz istek",requestInvalid:"Bu yetkilendirme isteği geçersiz veya süresi dolmuş. Lütfen geri dönüp tekrar deneyin.",grantingAccessTo:"Erişim verilecek hedef:",resourceAll:"Tüm MCP sunucuları",resourceSmart:"Akıllı yönlendirme",resourceServer:"MCP sunucusu: {{name}}",resourceGroup:"MCP grubu: {{name}}",clientId:"İstemci kimliği",willRedirectTo:"Şuraya yönlendirilecek:",policy:"Gizlilik politikası",terms:"Hizmet şartları",homepage:"Ana sayfa"},tc={title:"Bulut Desteği",subtitle:"MCPRouter tarafından desteklenmektedir",by:"Geliştirici",server:"Sunucu",config:"Yapılandırma",created:"Oluşturuldu",updated:"Güncellendi",available:"Kullanılabilir",description:"Açıklama",details:"Detaylar",tools:"Araçlar",tool:"araç",toolsAvailable:"{{count}} araç mevcut",loadingTools:"Araçlar yükleniyor...",noTools:"Bu sunucu için kullanılabilir araç yok",noDescription:"Kullanılabilir açıklama yok",viewDetails:"Detayları Görüntüle",parameters:"Parametreler",result:"Sonuç",error:"Hata",callTool:"Çalıştır",calling:"Çalıştırılıyor...",toolCallSuccess:"{{toolName}} aracı başarıyla çalıştırıldı",toolCallError:"{{toolName}} aracı çalıştırılamadı: {{error}}",viewSchema:"Şemayı Görüntüle",backToList:"Bulut Market'e Dön",search:"Ara",searchPlaceholder:"Bulut sunucularını isme, başlığa veya geliştiriciye göre ara",clearFilters:"Filtreleri Temizle",clearCategoryFilter:"Temizle",clearTagFilter:"Temizle",categories:"Kategoriler",tags:"Etiketler",noCategories:"Kategori bulunamadı",noTags:"Etiket bulunamadı",noServers:"Bulut sunucusu bulunamadı",fetchError:"Bulut sunucuları getirilirken hata",serverNotFound:"Bulut sunucusu bulunamadı",searchError:"Bulut sunucuları aranırken hata",filterError:"Bulut sunucuları kategoriye göre filtrelenirken hata",tagFilterError:"Bulut sunucuları etikete göre filtrelenirken hata",showing:"{{total}} bulut sunucusundan {{from}}-{{to}} arası gösteriliyor",perPage:"Sayfa başına",apiKeyNotConfigured:"MCPRouter API anahtarı yapılandırılmamış",apiKeyNotConfiguredDescription:"Bulut sunucularını kullanmak için MCPRouter API anahtarınızı yapılandırmanız gerekir.",getApiKey:"API Anahtarı Al",configureInSettings:"Ayarlarda Yapılandır",installServer:"{{name}} Yükle",installSuccess:"{{name}} sunucusu başarıyla yüklendi",installError:"Sunucu yüklenemedi: {{error}}"},ac={title:"Kayıt",official:"Resmi",latest:"En Son",description:"Açıklama",website:"Web Sitesi",repository:"Depo",packages:"Paketler",package:"paket",remotes:"Uzak Sunucular",remote:"uzak sunucu",published:"Yayınlandı",updated:"Güncellendi",install:"Yükle",installing:"Yükleniyor...",installed:"Yüklendi",installServer:"{{name}} Yükle",installSuccess:"{{name}} sunucusu başarıyla yüklendi",installError:"Sunucu yüklenemedi: {{error}}",noDescription:"Kullanılabilir açıklama yok",viewDetails:"Detayları Görüntüle",backToList:"Kayda Dön",search:"Ara",searchPlaceholder:"Kayıt sunucularını isme göre ara",clearFilters:"Temizle",noServers:"Kayıt sunucusu bulunamadı",fetchError:"Kayıt sunucuları getirilirken hata",serverNotFound:"Kayıt sunucusu bulunamadı",showing:"{{total}} kayıt sunucusundan {{from}}-{{to}} arası gösteriliyor",perPage:"Sayfa başına",environmentVariables:"Ortam Değişkenleri",packageArguments:"Paket Argümanları",runtimeArguments:"Çalışma Zamanı Argümanları",headers:"Başlıklar"},nc={run:"Çalıştır",running:"Çalıştırılıyor...",runTool:"Aracı Çalıştır",cancel:"İptal",noDescription:"Kullanılabilir açıklama yok",inputSchema:"Giriş Şeması:",runToolWithName:"Aracı Çalıştır: {{name}}",execution:"Araç Çalıştırma",successful:"Başarılı",failed:"Başarısız",result:"Sonuç:",error:"Hata",errorDetails:"Hata Detayları:",noContent:"Araç başarıyla çalıştırıldı ancak içerik döndürmedi.",unknownError:"Bilinmeyen hata oluştu",jsonResponse:"JSON Yanıtı:",toolResult:"Araç sonucu",noParameters:"Bu araç herhangi bir parametre gerektirmez.",selectOption:"Bir seçenek seçin",enterValue:"{{type}} değeri girin",enabled:"Etkin",enableSuccess:"{{name}} aracı başarıyla etkinleştirildi",disableSuccess:"{{name}} aracı başarıyla devre dışı bırakıldı",toggleFailed:"Araç durumu değiştirilemedi",descriptionUpdateSuccess:"Araç açıklaması başarıyla güncellendi",descriptionUpdateFailed:"Araç açıklaması güncellenemedi",descriptionModifiedBadge:"Değiştirildi",defaultDescriptionLabel:"Varsayılan açıklama",visibleParams:"Modellere gösterilen parametreler",visibleParamsHelp:"İşaretlenmemiş parametreler modellerin aldığı şemadan çıkarılır ve çağrılarından atılır. Zorunlu parametreler (*) gizlenemez.",requiredParam:"Zorunlu parametreler gizlenemez",hiddenParamsFailed:"Gizli parametreler güncellenemedi",defaultDescriptionTooltip:"Varsayılan açıklama: {{description}}",restoreDefault:"Varsayılana dön",restoreDefaultSuccess:"Araç açıklaması varsayılan değere döndürüldü",restoreDefaultFailed:"Varsayılan araç açıklamasına dönülemedi",parameters:"Araç Parametreleri",formMode:"Form Modu",jsonMode:"JSON Modu",jsonConfiguration:"JSON Yapılandırması",invalidJsonFormat:"Geçersiz JSON formatı",fixJsonBeforeSwitching:"Form moduna geçmeden önce lütfen JSON formatını düzeltin",item:"Öğe {{index}}",addItem:"{{key}} öğesi ekle",enterKey:"{{key}} girin"},ic={run:"Getir",running:"Getiriliyor...",result:"İstek Sonucu",error:"İstek Hatası",execution:"İstek Çalıştırma",successful:"Başarılı",failed:"Başarısız",errorDetails:"Hata Detayları:",noContent:"İstek başarıyla çalıştırıldı ancak içerik döndürmedi.",unknownError:"Bilinmeyen hata oluştu",jsonResponse:"JSON Yanıtı:",description:"Açıklama",messages:"Mesajlar",noDescription:"Kullanılabilir açıklama yok",runPromptWithName:"İsteği Getir: {{name}}",descriptionUpdateSuccess:"İstek açıklaması başarıyla güncellendi",descriptionUpdateFailed:"İstek açıklaması güncellenemedi",restoreDefault:"Varsayılana dön",restoreDefaultSuccess:"İstek açıklaması varsayılan değere döndürüldü",restoreDefaultFailed:"Varsayılan istek açıklamasına dönülemedi"},oc=JSON.parse(`{"dashboardName":"Pano adı","dashboardNameDescription":"Kenar çubuğu, başlık, giriş sayfası ve tarayıcı sekmesinde gösterilir. Varsayılan ad için boş bırakın.","dashboardNameSaveFailed":"Pano adı kaydedilemedi","resetBearerKey":"Bearer anahtarını sıfırla","resetBearerKeyConfirm":"Bu Bearer anahtarı sıfırlansın mı? Eski belirteç hemen geçersiz olacaktır. İzinler ve etkinlik durumu değişmeyecek.","resetBearerKeySuccess":"Anahtar sıfırlandı. Kapatmadan önce yeni belirteci kopyalayıp kaydedin; tekrar gösterilmeyecek.","resetBearerKeyError":"Bearer anahtarı sıfırlanamadı","allowRegistration":"Kendi kendine kayda izin ver","allowRegistrationDescription":"Ziyaretçilerin giriş sayfasından normal hesap oluşturmasına izin verir. Varsayılan olarak kapalıdır; parola ile giriş kapalıyken kullanılamaz.","allowedCidrs":"İzin verilen üst sunucu CIDR aralıkları","allowedCidrsDescription":"Her satıra bir IPv4 veya IPv6 CIDR girin. Tüm kullanıcılar bu aralıklardaki MCP, OpenAPI ve OAuth uç noktalarına erişebilir. Boş liste ek erişim sağlamaz. Yöneticiye ait sunucular iç ağ erişimini korur. Geniş aralıklardan, meta veri ve geri döngü adreslerinden kaçının. Değişiklikler yeni isteklere uygulanır; mevcut bağlantılar kapanmaz.","allowedCidrsUpdateFailed":"İzin verilen CIDR aralıkları güncellenemedi","subtitle":"Sistem ayarlarını, kimlik doğrulamayı, yönlendirmeyi ve MCP sunucu entegrasyonlarını yapılandırın.","enableGlobalRoute":"Global Yönlendirmeyi Etkinleştir","enableGlobalRouteDescription":"Grup ID'si belirtmeden /sse uç noktasına bağlantıya izin ver","enableGroupNameRoute":"Grup Adı Yönlendirmeyi Etkinleştir","enableGroupNameRouteDescription":"Sadece grup ID'leri yerine grup adları kullanarak /sse uç noktasına bağlantıya izin ver","enableBearerAuth":"Bearer Kimlik Doğrulamasını Etkinleştir","enableBearerAuthDescription":"MCP uç noktaları için bearer token kimlik doğrulaması gerektirir (varsayılan açık)","bearerAuthKey":"Bearer Kimlik Doğrulama Anahtarı","bearerAuthKeyDescription":"Bearer token'da gerekli olacak kimlik doğrulama anahtarı","bearerAuthKeyPlaceholder":"Bearer kimlik doğrulama anahtarını girin","bearerAuthHeaderName":"Bearer Kimlik Doğrulama Başlığı","bearerAuthHeaderNameDescription":"MCP bearer kimlik bilgilerinin alınacağı başlık adı. Yukarı akış passthrough başlıkları da Authorization kullanıyorsa bunu değiştirin.","bearerAuthHeaderNamePlaceholder":"örn. Authorization veya X-MCP-Authorization","bearerKeysSectionTitle":"Anahtarlar","bearerKeysSectionDescription":"Farklı erişim kapsamlarına sahip birden fazla anahtarı yönetin.","noBearerKeys":"Henüz yapılandırılmış herhangi bir anahtar yok.","bearerKeyName":"Ad","bearerKeyToken":"Token","bearerKeyEnabled":"Etkin","bearerKeyAccessType":"Erişim kapsamı","bearerKeyAccessAll":"Tümü","bearerKeyAccessGroups":"Gruplar","bearerKeyAccessServers":"Sunucular","bearerKeyAccessCustom":"Özel","bearerKeyAllowedGroups":"İzin verilen gruplar","bearerKeyAllowedServers":"İzin verilen sunucular","addBearerKey":"Anahtar ekle","addBearerKeyButton":"Oluştur","bearerKeyRequired":"Ad ve token zorunludur","bearerKeyNameRequired":"Ad zorunludur","bearerKeyOwnerRequired":"Sahip zorunludur","bearerKeyKind":"Anahtar türü","bearerKeyKindSystem":"Sistem düzeyi","bearerKeyKindUser":"Kullanıcı düzeyi","bearerKeyOwner":"Sahip","bearerKeySelectOwner":"Kullanıcı seçin...","bearerKeyAccessUserVisibility":"Kullanıcı görünürlüğü","bearerKeyShownOnce":"Bu tokenı şimdi kopyalayın. Tekrar gösterilmeyecek.","deleteBearerKeyConfirm":"Bu anahtarı silmek istediğinizden emin misiniz?","generate":"Oluştur","selectGroups":"Grupları Seç","selectServers":"Sunucuları Seç","selectAtLeastOneGroup":"Lütfen en az bir grup seçin","selectAtLeastOneServer":"Lütfen en az bir sunucu seçin","skipAuth":"Kimlik Doğrulamayı Atla","skipAuthDescription":"Kontrol paneline giriş olmadan erişime izin ver; kimliği doğrulanmamış kullanıcılar guest yönetici erişimi alır (MCP kimlik doğrulamasını etkilemez)","jsonBodyLimit":"JSON Gövde Boyutu Sınırı","jsonBodyLimitDescription":"Express JSON istek boyutu sınırı. Büyük OpenAPI şema yüklemeleri de bu ayardan etkilenir.","jsonBodyLimitPlaceholder":"örn. 1mb, 5mb, 1024kb","pythonIndexUrl":"Python Paket Deposu URL'si","pythonIndexUrlDescription":"Python paket kurulumu için UV_DEFAULT_INDEX ortam değişkenini ayarla","pythonIndexUrlPlaceholder":"örn. https://pypi.org/simple","npmRegistry":"NPM Kayıt URL'si","npmRegistryDescription":"NPM paket kurulumu için npm_config_registry ortam değişkenini ayarla","npmRegistryPlaceholder":"örn. https://registry.npmjs.org/","baseUrl":"Temel URL","baseUrlDescription":"MCP istekleri ve OAuth geri çağrıları için temel URL","baseUrlPlaceholder":"örn. http://localhost:3000","installConfig":"Kurulum","clearCache":"Paket önbelleğini temizle","clearCacheDescription":"npm ve uv paket önbelleklerini temizle. Sunucular bir sonraki başlatmada paketleri yeniden indirmek zorunda kalabilir.","clearCacheConfirm":"Bu işlem npm ve uv paket önbelleklerini temizleyecektir. Sunucular bir sonraki başlatmada paketleri yeniden indirmek zorunda kalabilir.","clearCacheSuccess":"Paket önbelleği başarıyla temizlendi","clearCacheError":"Paket önbelleği temizlenemedi","clearCacheSkipped":"kurulu değil","clearingCache":"Temizleniyor...","systemConfigUpdated":"Sistem yapılandırması başarıyla güncellendi","noChanges":"Kaydedilecek değişiklik yok","betterAuthTitle":"Better Auth","betterAuthEnvNote":"İstemci kimlikleri ve gizli anahtarlar hâlâ ortam değişkenlerinden gelir. Better Auth ayarlarını değiştirmek uygulamanın yeniden başlatılmasını gerektirebilir; kurulum temel URL kaynağı da güvenilen kaynaklara otomatik olarak eklenir.","enableBetterAuth":"Better Auth'u etkinleştir","enableBetterAuthDescription":"Gerekli ortam değişkenleri yapılandırıldığında sosyal giriş ve OIDC girişini etkinleştirin.","disablePasswordLogin":"Parola ile girişi devre dışı bırak","disablePasswordLoginDescription":"Yalnızca SSO sağlayıcıları üzerinden girişe izin verir: kullanıcı adı/parola formu ve POST /api/auth/login kapatılır. Yalnızca en az bir sağlayıcı etkinken ve uygulama başlatıldığında zaten etkinse geçerlidir. BETTER_AUTH_DISABLE_PASSWORD_LOGIN bu ayarı geçersiz kılar; kimlik sağlayıcı erişilemezse false yapmak yeniden giriş yolunu açar.","betterAuthBaseUrl":"Temel URL","betterAuthBaseUrlDescription":"Better Auth yönlendirme URI'lerini oluşturmak için kullanılan genel temel URL. Boş bırakılırsa kurulum temel URL'si kullanılır; BETTER_AUTH_URL ortam değişkeni önceliklidir.","betterAuthBasePath":"Kimlik doğrulama temel yolu","betterAuthBasePathDescription":"Better Auth rotaları tarafından kullanılan göreli API yolu.","betterAuthTrustedOrigins":"Güvenilen kaynaklar","betterAuthTrustedOriginsDescription":"Better Auth istekleri için izin verilen, virgülle ayrılmış kaynaklar. Kurulum temel URL kaynağı otomatik olarak eklenir.","betterAuthProviders":"Sağlayıcılar","betterAuthProvidersDescription":"Sağlayıcı anahtarları, giriş sayfasında hangi giriş yöntemlerinin gösterileceğini kontrol eder.","betterAuthGoogleDescription":"GOOGLE_CLIENT_ID ve GOOGLE_CLIENT_SECRET gerektirir.","betterAuthGithubDescription":"GITHUB_CLIENT_ID ve GITHUB_CLIENT_SECRET gerektirir.","betterAuthOidcDescription":"OIDC istemci kimlik bilgileri ve bir keşif URL'si gerektirir.","betterAuthOidcProviderId":"OIDC sağlayıcı kimliği","betterAuthOidcProviderIdDescription":"OIDC giriş akışı başlatılırken kullanılan sağlayıcı kimliği.","betterAuthOidcDiscoveryUrl":"OIDC keşif URL'si","betterAuthOidcDiscoveryUrlDescription":"Kimlik sağlayıcınız tarafından yayınlanan iyi bilinen OpenID yapılandırma URL'si.","betterAuthOidcScopes":"OIDC kapsamları","betterAuthOidcScopesDescription":"OIDC giriş akışı sırasında istenen, virgülle ayrılmış kapsamlar.","betterAuthOidcPrompt":"OIDC prompt","betterAuthOidcPromptDescription":"Kimlik sağlayıcısına gönderilen isteğe bağlı prompt değeri; örneğin login veya consent.","betterAuthOidcPkce":"PKCE'yi etkinleştir","betterAuthOidcPkceDescription":"OIDC yetkilendirme akışı için PKCE kullanın.","enableSmartRouting":"Akıllı Yönlendirmeyi Etkinleştir","enableSmartRoutingDescription":"Girdiye göre en uygun aracı aramak için akıllı yönlendirme özelliğini etkinleştir ($smart grup adını kullanarak)","dbUrl":"PostgreSQL URL'si (pgvector desteği gerektirir)","dbUrlPlaceholder":"örn. postgresql://kullanıcı:şifre@localhost:5432/veritabanıadı","embeddingProvider":"Embedding Sağlayıcısı","embeddingProviderPreset":"Sağlayıcı Ön Ayarı","embeddingProviderPresetDescription":"OpenAI uyumlu uç noktayı ve modeli doldurmak için bir sağlayıcı seçin.","embeddingProviderPresetOpenai":"OpenAI","embeddingProviderPresetOpenrouter":"OpenRouter","embeddingProviderPresetSiliconflow":"SiliconFlow · ücretsiz katman (1000 RPM)","embeddingProviderPresetGemini":"Google Gemini · ücretsiz katman (100 RPM)","embeddingProviderPresetCustom":"Diğer / OpenAI uyumlu","llmProviderBaseUrl":"OpenAI uyumlu Temel URL","llmProviderBaseUrlPlaceholder":"https://api.openai.com/v1","llmProviderApiKey":"LLM Sağlayıcı API Anahtarı","llmProviderApiKeyPlaceholder":"LLM sağlayıcı API anahtarını girin","smartRoutingEnvOverrideWarning":"Şu anda {{envVar}} ortam değişkeni tarafından sağlanıyor — burada kaydedilen değer çalışma zamanında kullanılmaz.","embeddingModel":"Entegrasyon Modeli Adı","embeddingModelPlaceholder":"text-embedding-3-small","basePacingDelayMs":"Temel pacing gecikmesi (ms)","basePacingDelayMsDescription":"Sağlayıcıya gönderilen embedding istekleri arasındaki temel bekleme süresi. Varsayılan 0 — sistem hız sınırlarını otomatik olarak yönetir: Retry-After başlıklarına uyar, başlık yoksa 63 saniyelik bekleme uygular ve her 403/429 yanıtından sonra pacing gecikmesini artırır. Yalnızca sağlayıcınız sabit bir minimum aralık gerektiriyorsa sıfırdan farklı bir değer ayarlayın.","basePacingDelayMsPlaceholder":"Boş = varsayılan 0 ms","basePacingDelayMsAuto":"Varsayılan ({{value}} ms): hız sınırı yönetimi otomatiktir.","basePacingDelayMsZero":"0 ms (varsayılan): hız sınırı yönetimi, uyarlanabilir pacing ve retry mantığı aracılığıyla otomatik olarak yapılır.","basePacingDelayMsOverride":"Özel değer: varsayılan temel pacing gecikmesini geçersiz kılar.","embeddingEncodingFormat":"Embedding Kodlama Formatı","embeddingEncodingFormatDescription":"Embedding vektörleri için kodlama formatı. Otomatik, sağlayıcı desteğine göre algılar.","embeddingEncodingFormatAuto":"Otomatik (Önerilen)","embeddingDimensions":"Embedding Boyutları","embeddingDimensionsDescription":"Destekleyen sağlayıcılar için isteğe bağlı çıktı boyutu. Model varsayılanını kullanmak için boş bırakın.","embeddingDimensionsPlaceholder":"Boş = model varsayılanı","embeddingDimensionsApiPassthrough":"dimensions'ı API'ye ilet (MRL passthrough)","embeddingDimensionsApiPassthroughDescription":"Yalnızca Matryoshka (MRL) desteklediği bilinen modeller dimensions parametresini alır. Diğer MRL uyumlu modeller için zorlamak üzere etkinleştirin. MRL olmayan modeller (Qwen3-Embedding, BGE, vLLM/sglang) parametreyi doğrudan reddeder, bu yüzden onlar için kapalı bırakın.","azureOpenaiEndpoint":"Azure OpenAI Uç Noktası","azureOpenaiEndpointPlaceholder":"https://KAYNAK_ADINIZ.openai.azure.com","azureOpenaiApiKey":"Azure OpenAI API Anahtarı","azureOpenaiApiKeyPlaceholder":"Azure OpenAI API anahtarını girin","azureOpenaiApiVersion":"Azure OpenAI API Sürümü","azureOpenaiApiVersionPlaceholder":"2024-02-15-preview","azureOpenaiEmbeddingDeployment":"Azure OpenAI Embedding Dağıtımı","azureOpenaiEmbeddingDeploymentPlaceholder":"text-embedding-3-small","azureOpenaiEmbeddingModel":"Azure Embedding Model Adı","azureOpenaiEmbeddingModelDescription":"Azure'da dağıtılan gerçek OpenAI model adı (örn. text-embedding-3-small). API'ye göndermeden önce doğru token sayımı için kullanılır.","azureOpenaiEmbeddingModelPlaceholder":"text-embedding-3-small","smartRoutingConfigUpdated":"Akıllı yönlendirme yapılandırması başarıyla güncellendi","progressiveDisclosure":"Aşamalı Açıklama","progressiveDisclosureDescription":"Etkinleştirildiğinde, search_tools yalnızca araç adlarını ve açıklamalarını döndürür. Tam parametre şemasını almak için describe_tool kullanın; bu da token kullanımını azaltır.","embeddingMaxTokens":"Maks. Embedding Token Sayısı","embeddingMaxTokensDescription":"Embedding oluşturmadan önce metin kesme için maksimum token sayısı. Model varsayılanını otomatik olarak kullanmak için boş bırakın. Özel bir değer her zaman model varsayılanını geçersiz kılar. Yerel LLM sağlayıcıları kullanırken bu değeri manuel olarak ayarlamak, kesme hatalarını önlemek için özellikle yararlıdır.","embeddingMaxTokensPlaceholder":"Boş = modele göre otomatik","embeddingMaxTokensAuto":"Otomatik: {{limit}} token ({{model}} model varsayılanı)","embeddingMaxTokensOverride":"Bu değer model varsayılanını geçersiz kılar.","embeddingPrefixes":"Embedding Görev Önekleri","embeddingPrefixesDescription":"Görev önekleriyle eğitilmiş asimetrik arama modelleri (ör. EmbeddingGemma, E5, Nomic) için embedding öncesinde metnin başına eklenir. Ham metin bekleyen modeller için ikisini de boş bırakın. Sondaki boşluğu da ekleyin. Belge önekini değiştirmek tüm araçların embedding'lerini yeniden oluşturur.","embeddingQueryPrefix":"Sorgu öneki","embeddingDocumentPrefix":"Belge öneki","searchResults":"Arama Sonuçları","searchResultsDescription":"search_tools eşleşmeleri nasıl filtreler ve döndürür. Her sonuç benzerlik puanını içerir. Varsayılanlar için iki alanı da boş bırakın.","similarityThreshold":"Benzerlik eşiği (0-1)","similarityThresholdPlaceholder":"Boş = sorgu uzunluğuna göre (0.2 / 0.3 / 0.4)","fullSchemaTopN":"İlk N sonuç için tam şemalar","fullSchemaTopNPlaceholder":"Boş = tüm sonuçlar; diğerleri describe_tool kullanır","toolDefinitionFields":"Sonuçlardaki araç alanları","toolDefinitionFieldsDescription":"search_tools ve describe_tool sonuçlarının ad, açıklama ve inputSchema dışında içerdiği isteğe bağlı alanlar. Varsayılan: title ve annotations. Diğerleri çoğunlukla istemciler içindir ve büyük olabilir (simgeler base64 görsellerdir).","invalidSearchSettings":"{{fields}} için geçersiz değer. Benzerlik eşiği 0 ile 1 arasında, N ise 0 veya daha büyük bir tam sayı olmalıdır.","smartRoutingRequiredFields":"Akıllı yönlendirmeyi etkinleştirmek için Veritabanı URL'si gereklidir. LLM Sağlayıcı API Anahtarı yalnızca bulut tabanlı sağlayıcılar için gereklidir (yerel LLM'ler genellikle API anahtarı gerektirmez, form doğrulamasını geçmek için herhangi bir değer girin)","smartRoutingValidationError":"Akıllı Yönlendirmeyi etkinleştirmeden önce lütfen gerekli alanları doldurun: {{fields}}","smartRoutingWorkflow":"İş Akışı","smartRoutingWorkflowDescription":"İstem vektörleştirilir; pgvector'dan en benzer top-k araç alınır ve üst LLM'e sunulur.","toolResultCompressionTitle":"Araç Sonucu Sıkıştırma","toolResultCompressionEnable":"Sıkıştırmayı etkinleştir","toolResultCompressionDescription":"Büyük metin araç çıktılarını MCP istemcilerine ulaşmadan önce küçültür. Değişiklikler bir sonraki araç çağrısında uygulanır.","toolResultCompressionStrategy":"Strateji","toolResultCompressionStrategyDescription":"JSON, günlük, arama çıktısı, diff ve düz metni otomatik algılar.","toolResultCompressionMinTokens":"Minimum token","toolResultCompressionMinTokensDescription":"Yalnızca bu boyuta eşit veya daha büyük metin bloklarını sıkıştırır.","toolResultCompressionMaxOutputTokens":"Çıkış token bütçesi","toolResultCompressionMaxOutputTokensDescription":"Her sıkıştırılmış metin bloğu için hedef maksimum token sayısı.","mcpRouterConfig":"Bulut Market","mcpRouterApiKey":"MCPRouter API Anahtarı","mcpRouterApiKeyDescription":"MCPRouter bulut market hizmetlerine erişim için API anahtarı","mcpRouterApiKeyPlaceholder":"MCPRouter API anahtarını girin","mcpRouterReferer":"Yönlendiren","mcpRouterRefererDescription":"MCPRouter API istekleri için Referer başlığı","mcpRouterRefererPlaceholder":"https://www.mcphub.app","mcpRouterTitle":"Başlık","mcpRouterTitleDescription":"MCPRouter API istekleri için Başlık başlığı","mcpRouterTitlePlaceholder":"MCPHub","mcpRouterBaseUrl":"Temel URL","mcpRouterBaseUrlDescription":"MCPRouter API için temel URL","mcpRouterBaseUrlPlaceholder":"https://api.mcprouter.to/v1","systemSettings":"Sistem Ayarları","nameSeparatorLabel":"İsim Ayırıcı","nameSeparatorDescription":"Sunucu adı ile araç/istek adını ayırmak için kullanılan karakter (varsayılan: -)","enableSessionRebuild":"Sunucu Oturum Yeniden Oluşturmayı Etkinleştir","enableSessionRebuildDescription":"Etkinleştirildiğinde, daha iyi oturum yönetimi deneyimi için geliştirilmiş sunucu oturum yeniden oluşturma kodunu uygular","storeToolPayload":"Araç Çağrısı İçeriğini Sakla","storeToolPayloadDescription":"Etkinleştirildiğinde, her araç çağrısının tam girdisi ve çıktısı etkinlik günlüklerinde saklanır. Araç içeriği maskelenmeden olduğu gibi kaydedilir; araç argümanları hassas veri içerebiliyorsa ve saklanmaması gerekiyorsa bunu kapatın.","storeToolPayloadUpdateFailed":"Araç içeriği saklama ayarı güncellenemedi","restartRequired":"Yapılandırma kaydedildi. Tüm hizmetlerin yeni ayarları doğru şekilde yüklemesini sağlamak için uygulamayı yeniden başlatmanız önerilir.","exportMcpSettings":"Ayarları Dışa Aktar","mcpSettingsJson":"MCP Ayarları JSON","mcpSettingsJsonDescription":"Yedekleme veya diğer araçlara taşıma için mevcut mcp_settings.json yapılandırmanızı görüntüleyin, kopyalayın veya indirin","copyToClipboard":"Panoya Kopyala","downloadJson":"JSON Olarak İndir","exportSuccess":"Ayarlar başarıyla dışa aktarıldı","exportError":"Ayarlar getirilemedi","enableOauthServer":"OAuth Sunucusunu Etkinleştir","enableOauthServerDescription":"MCPHub'ın harici istemciler için OAuth jetonları vermesine izin ver","requireClientSecret":"İstemci Sırrı Zorunlu","requireClientSecretDescription":"Etkin olduğunda gizli istemciler client secret sunmalıdır (yalnızca PKCE kullanan istemciler için kapatabilirsiniz)","requireState":"State parametresi zorunlu","requireStateDescription":"State parametresi olmayan yetkilendirme isteklerini reddeder","accessTokenLifetime":"Erişim jetonu süresi (saniye)","accessTokenLifetimeDescription":"Verilen erişim jetonlarının geçerli kalacağı süre","accessTokenLifetimePlaceholder":"örn. 3600","refreshTokenLifetime":"Yenileme jetonu süresi (saniye)","refreshTokenLifetimeDescription":"Yenileme jetonlarının geçerli kalacağı süre","refreshTokenLifetimePlaceholder":"örn. 1209600","authorizationCodeLifetime":"Yetkilendirme kodu süresi (saniye)","authorizationCodeLifetimeDescription":"Yetkilendirme kodlarının takas edilebileceği süre","authorizationCodeLifetimePlaceholder":"örn. 300","allowedScopes":"İzin verilen kapsamlar","allowedScopesDescription":"Kullanıcıların onaylayabileceği kapsamların virgülle ayrılmış listesi","allowedScopesPlaceholder":"örn. read, write","enableDynamicRegistration":"Dinamik istemci kaydını etkinleştir","dynamicRegistrationDescription":"RFC 7591 uyumlu istemcilerin herkese açık uç nokta üzerinden kayıt olmasına izin ver","dynamicRegistrationAllowedGrantTypes":"İzin verilen grant türleri","dynamicRegistrationAllowedGrantTypesDescription":"Dinamik olarak kaydedilen istemciler için kullanılabilecek grant türlerinin virgülle ayrılmış listesi","dynamicRegistrationAllowedGrantTypesPlaceholder":"örn. authorization_code, refresh_token","dynamicRegistrationAuth":"Kayıt için kimlik doğrulaması iste","dynamicRegistrationAuthDescription":"Kayıt uç noktasını korur, yalnızca kimliği doğrulanmış istekler yeni istemci oluşturabilir","invalidNumberInput":"Lütfen sıfırdan küçük olmayan geçerli bir sayı girin","dynamicRegistrationClientTtl":"Boşta İstemci Temizleme TTL'si (saniye)","dynamicRegistrationClientTtlDescription":"Aktif tokenı ve devam eden yetkilendirme akışı olmayan, bu süreden daha eski dinamik kayıtlı istemcileri temizler. Temizlemeyi devre dışı bırakmak için 0 yapın.","dynamicRegistrationClientTtlPlaceholder":"örn. 2592000","smartRoutingIndexTitle":"Vektör İndeksi ve Tanılama","smartRoutingIndexRefresh":"Yenile","smartRoutingIndexReindex":"Yeniden İndeksle","smartRoutingIndexReindexing":"Yeniden İndeksleniyor…","smartRoutingIndexLoading":"Yükleniyor…","smartRoutingIndexNoData":"Henüz indeks verisi yok. Akıllı yönlendirmeyi etkinleştirin ve vektör deposunu oluşturmak için Yeniden İndeksle’ye tıklayın.","smartRoutingIndexStatsUnavailable":"İstatistikler kullanılamıyor","smartRoutingIndexDatabase":"Veritabanı","smartRoutingIndexConnected":"Bağlı","smartRoutingIndexDisconnected":"Bağlı değil","smartRoutingIndexUnhealthy":"Sağlıksız","smartRoutingIndexModel":"Model","smartRoutingIndexDimensions":"Boyutlar","smartRoutingIndexTotalRows":"Toplam satır","smartRoutingIndexToolRows":"Araç satırı","smartRoutingIndexServerRows":"Sunucu satırı","smartRoutingIndexClusterLabel":"İndekslenen sunucular","smartRoutingIndexCoverage":"Kapsam","smartRoutingIndexLastSynced":"Son senkronizasyon","smartRoutingIndexPerServer":"Sunucu başına araçlar","smartRoutingIndexMissingIndex":"İndeksi olmayan {{count}} etkin sunucu","smartRoutingIndexSyncedRange":"Senkronizasyon aralığı: {{oldest}} → {{newest}}","smartRoutingIndexReindexDone":"Yeniden indeksleme tamamlandı: {{synced}} senkronize, {{failed}} hata, {{skipped}} atlandı, toplam {{total}} araç","smartRoutingIndexReindexFailed":"Yeniden indeksleme başarısız: {{message}}","smartRoutingIndexReindexStarting":"Yeniden indeksleme başlıyor…","smartRoutingIndexReindexingServer":"{{server}} yeniden indeksleniyor","smartRoutingIndexReindexSummary":"Yeniden indeksleme tamam · {{synced}} senkronize, {{failed}} hata, {{skipped}} atlandı, {{total}} araç","smartRoutingIndexReindexConfirmTitle":"Vektör indeksi yeniden oluşturulsun mu?","smartRoutingIndexReindexConfirmMessage":"Mevcut tüm embedding’ler temizlenecek ve sıfırdan yeniden üretilecek. Bu biraz zaman alabilir ve embedding API kotası harcar.","smartRoutingIndexPersonalCredentials":"Kişisel kimlik bilgisi gerektiren sunucular","smartRoutingIndexSkippedReason":"Atlandı","smartRoutingIndexIndexedAs":"{{principals}} olarak indekslendi","toolPolicies":{"missingReferences":"Bazı kimlikler yüklenen sunucu, anahtar veya gruplarda bulunamadı. Eşleşmeyen ret kuralı koruma sağlamaz; eşleşmeyen izin kuralı erişimi engelleyebilir. Kaydetmeden önce doğrulayın. Gelecekte oluşturulacak kaynaklar için kurallar kaydedilebilir.","missingReference":"{{policyId}} kuralı: {{selector}} {{value}} bulunamadı.","title":"Araç erişim politikaları","description":"Kurallar, akıllı yönlendirme dahil araç keşfi ve çağrılarına uygulanır. Kaydedildikten sonra etkinleşir.","semantics":"Boş seçiciler herkesi veya her hedefi eşleştirir. Bir kuralın tüm seçicileri eşleşmelidir. Geçerli izin kuralları bir izin listesi oluşturur; ret kuralları önceliklidir. Politikalar mevcut izinleri genişletmez.","empty":"Politika yok. Mevcut erişim izinleri geçerli.","rule":"Kural {{number}}","id":"Kural kimliği (benzersiz, zorunlu)","effect":"Etki","allow":"İzin ver","deny":"Reddet","username":"Kullanıcı adı","keyId":"Bearer anahtar kimliği","groupId":"Uç nokta grup kimliği","serverId":"Sunucu kimliği","tool":"Özgün araç adı","any":"Tümü","selectorsHint":"Öneri seçin veya tam değer girin. Kimlikler ad değişikliğinden etkilenmez. Grup, sunucu üyeliğini değil uç noktayı belirtir. Araç adları büyük/küçük harfe duyarlıdır; ağ geçidi öneki ve joker karakter kullanmayın.","add":"Kural ekle","save":"Politikaları kaydet","unsaved":"Kaydedilmemiş değişiklikler. Ekleme ve silmeler kaydedildikten sonra uygulanır.","invalid":"Her kural benzersiz, boş olmayan kimlik ve geçerli etki gerektirir. Seçiciler yalnızca boşluk içeremez.","saveFailed":"Politikalar kaydedilemedi. Değişiklikleriniz korundu.","confirm":"Bu {{count}} politika hemen uygulansın mı? Kullanıcıların erişebildiği araçlar değişebilir.","confirmClear":"Tüm politikalar silinsin mi? Mevcut izinler geçerli olacaktır.","deleteRule":"{{number}} numaralı kuralı sil","retry":"Yeniden dene"}}`),sc={upload:"Yükle",uploadTitle:"MCPB Paketi Yükle",dropFileHere:".mcpb dosyanızı buraya bırakın",orClickToSelect:"veya bilgisayarınızdan seçmek için tıklayın",invalidFileType:"Lütfen geçerli bir .mcpb dosyası seçin",noFileSelected:"Lütfen yüklemek için bir .mcpb dosyası seçin",uploading:"Yükleniyor...",uploadFailed:"MCPB dosyası yüklenemedi",installServer:"MCPB'den MCP Sunucusu Yükle",extensionInfo:"Uzantı Bilgisi",name:"Ad",version:"Sürüm",description:"Açıklama",author:"Geliştirici",tools:"Araçlar",serverName:"Sunucu Adı",serverNamePlaceholder:"Bu sunucu için bir ad girin",install:"Yükle",installing:"Yükleniyor...",installFailed:"MCPB'den sunucu yüklenemedi",serverExistsTitle:"Sunucu Zaten Mevcut",serverExistsConfirm:"'{{serverName}}' sunucusu zaten mevcut. Yeni sürümle geçersiz kılmak istiyor musunuz?",override:"Geçersiz Kıl"},lc={button:"İçe Aktar",title:"JSON'dan Sunucuları İçe Aktar",inputLabel:"Sunucu Yapılandırma JSON",inputHelp:"Sunucu yapılandırma JSON'unuzu yapıştırın. STDIO, SSE ve HTTP (streamable-http) sunucu türlerini destekler.",preview:"Önizle",previewTitle:"İçe Aktarılacak Sunucuları Önizle",import:"İçe Aktar",importing:"İçe aktarılıyor...",invalidFormat:"Geçersiz JSON formatı. JSON bir 'mcpServers' nesnesi içermelidir.",parseError:"JSON ayrıştırılamadı. Lütfen formatı kontrol edip tekrar deneyin.",addFailed:"Sunucu eklenemedi",importFailed:"Sunucular içe aktarılamadı",partialSuccess:"{{total}} sunucudan {{count}} tanesi başarıyla içe aktarıldı. Bazı sunucular başarısız oldu:",validationErrors:"Bazı sunucular içe aktarılamadı. Lütfen aşağıdakileri düzeltip tekrar deneyin:"},cc={button:"İçe Aktar",title:"JSON'dan Grupları İçe Aktar",inputLabel:"Grup Yapılandırma JSON",inputHelp:"Grup yapılandırma JSON'unuzu yapıştırın. Her grup bir sunucu listesi içerebilir.",preview:"Önizle",previewTitle:"İçe Aktarılacak Grupları Önizle",import:"İçe Aktar",importing:"İçe aktarılıyor...",invalidFormat:"Geçersiz JSON formatı. JSON bir 'groups' dizisi içermelidir.",missingName:"Her grubun bir 'name' alanı olmalıdır.",parseError:"JSON ayrıştırılamadı. Lütfen formatı kontrol edip tekrar deneyin.",addFailed:"Grup eklenemedi",importFailed:"Gruplar içe aktarılamadı",partialSuccess:"{{total}} gruptan {{count}} tanesi başarıyla içe aktarıldı. Bazı gruplar başarısız oldu:"},dc={add:"Kullanıcı Ekle",addNew:"Yeni Kullanıcı Ekle",edit:"Kullanıcıyı Düzenle",delete:"Kullanıcıyı Sil",create:"Kullanıcı Oluştur",update:"Kullanıcıyı Güncelle",username:"Kullanıcı Adı",email:"E-posta",emailPlaceholder:"E-posta girin (isteğe bağlı)",password:"Şifre",newPassword:"Yeni Şifre",confirmPassword:"Şifreyi Onayla",changePassword:"Şifre Değiştir",adminRole:"Yönetici",admin:"Yönetici",user:"Kullanıcı",role:"Rol",actions:"Eylemler",addFirst:"İlk kullanıcınızı ekleyin",permissions:"İzinler",adminPermissions:"Tam sistem erişimi",userPermissions:"Sınırlı erişim",currentUser:"Siz",noUsers:"Kullanıcı bulunamadı",adminRequired:"Kullanıcıları yönetmek için yönetici erişimi gereklidir",usernameRequired:"Kullanıcı adı gereklidir",passwordRequired:"Şifre gereklidir",passwordTooShort:"Şifre en az 6 karakter uzunluğunda olmalıdır",passwordMismatch:"Şifreler eşleşmiyor",usernamePlaceholder:"Kullanıcı adını girin",passwordPlaceholder:"Şifreyi girin",newPasswordPlaceholder:"Mevcut şifreyi korumak için boş bırakın",confirmPasswordPlaceholder:"Yeni şifreyi onaylayın",createError:"Kullanıcı oluşturulamadı",updateError:"Kullanıcı güncellenemedi",deleteError:"Kullanıcı silinemedi",statsError:"Kullanıcı istatistikleri getirilemedi",deleteConfirmation:"'{{username}}' kullanıcısını silmek istediğinizden emin misiniz? Bu işlem geri alınamaz.",confirmDelete:"Kullanıcıyı Sil",deleteWarning:"'{{username}}' kullanıcısını silmek istediğinizden emin misiniz? Bu işlem geri alınamaz."},uc={errors:{readonly:"Demo ortamı için salt okunur",invalid_credentials:"Geçersiz kullanıcı adı veya şifre",password_login_disabled:"Parola ile giriş devre dışı. SSO ile giriş yapın veya API erişimi için bir bearer anahtarı kullanın.",serverNameRequired:"Sunucu adı gereklidir",serverConfigRequired:"Sunucu yapılandırması gereklidir",serverConfigInvalid:"Sunucu yapılandırması bir URL, OpenAPI şartname URL'si veya şema, ya da argümanlı komut içermelidir",serverTypeInvalid:"Sunucu türü şunlardan biri olmalıdır: stdio, sse, streamable-http, openapi",urlRequiredForType:"{{type}} sunucu türü için URL gereklidir",openapiSpecRequired:"OpenAPI sunucu türü için OpenAPI şartname URL'si veya şema gereklidir",headersInvalidFormat:"Başlıklar bir nesne olmalıdır",headersNotSupportedForStdio:"Başlıklar stdio sunucu türü için desteklenmez",serverNotFound:"Sunucu bulunamadı",failedToRemoveServer:"Sunucu bulunamadı veya kaldırılamadı",internalServerError:"Dahili sunucu hatası",failedToGetServers:"Sunucu bilgileri alınamadı",failedToGetServerSettings:"Sunucu ayarları alınamadı",failedToGetServerConfig:"Sunucu yapılandırması alınamadı",failedToSaveSettings:"Ayarlar kaydedilemedi",toolNameRequired:"Sunucu adı ve araç adı gereklidir",descriptionMustBeString:"Açıklama bir string olmalıdır",groupIdRequired:"Grup ID gereklidir",groupNameRequired:"Grup adı gereklidir",groupNotFound:"Grup bulunamadı",groupIdAndServerNameRequired:"Grup ID ve sunucu adı gereklidir",groupOrServerNotFound:"Grup veya sunucu bulunamadı",toolsMustBeAllOrArray:'Araçlar "all" veya bir string dizisi olmalıdır',serverNameAndToolNameRequired:"Sunucu adı ve araç adı gereklidir",usernameRequired:"Kullanıcı adı gereklidir",userNotFound:"Kullanıcı bulunamadı",failedToGetUsers:"Kullanıcı bilgileri alınamadı",failedToGetUserInfo:"Kullanıcı bilgisi alınamadı",failedToGetUserStats:"Kullanıcı istatistikleri alınamadı",marketServerNameRequired:"Sunucu adı gereklidir",marketServerNotFound:"Market sunucusu bulunamadı",failedToGetMarketServers:"Market sunucuları bilgisi alınamadı",failedToGetMarketServer:"Market sunucusu bilgisi alınamadı",failedToGetMarketCategories:"Market kategorileri alınamadı",failedToGetMarketTags:"Market etiketleri alınamadı",failedToSearchMarketServers:"Market sunucuları aranamadı",failedToFilterMarketServers:"Market sunucuları filtrelenemedi",failedToProcessMcpbFile:"MCPB dosyası işlenemedi"},success:{serverCreated:"Sunucu başarıyla oluşturuldu",serverUpdated:"Sunucu başarıyla güncellendi",serverRemoved:"Sunucu başarıyla kaldırıldı",serverToggled:"Sunucu durumu başarıyla değiştirildi",toolToggled:"{{name}} aracı başarıyla {{action}}",toolDescriptionUpdated:"{{name}} aracının açıklaması başarıyla güncellendi",systemConfigUpdated:"Sistem yapılandırması başarıyla güncellendi",groupCreated:"Grup başarıyla oluşturuldu",groupUpdated:"Grup başarıyla güncellendi",groupDeleted:"Grup başarıyla silindi",serverAddedToGroup:"Sunucu başarıyla gruba eklendi",serverRemovedFromGroup:"Sunucu başarıyla gruptan kaldırıldı",serverToolsUpdated:"Sunucu araçları başarıyla güncellendi"}},mc={authorizationFailed:"Yetkilendirme Başarısız",authorizationFailedError:"Hata",authorizationFailedDetails:"Detaylar",invalidRequest:"Geçersiz İstek",missingStateParameter:"Gerekli OAuth durum parametresi eksik.",missingCodeParameter:"Gerekli yetkilendirme kodu parametresi eksik.",serverNotFound:"Sunucu Bulunamadı",serverNotFoundMessage:"Bu yetkilendirme isteğiyle ilişkili sunucu bulunamadı.",sessionExpiredMessage:"Yetkilendirme oturumunun süresi dolmuş olabilir. Lütfen tekrar yetkilendirmeyi deneyin.",authorizationSuccessful:"Yetkilendirme Başarılı",server:"Sunucu",status:"Durum",connected:"Bağlandı",successMessage:"Sunucu başarıyla yetkilendirildi ve bağlandı.",autoCloseMessage:"Bu pencere 3 saniye içinde otomatik olarak kapanacak...",closeNow:"Şimdi Kapat",connectionError:"Bağlantı Hatası",connectionErrorMessage:"Yetkilendirme başarılı oldu, ancak sunucuya bağlanılamadı.",reconnectMessage:"Lütfen kontrol panelinden yeniden bağlanmayı deneyin.",configurationError:"Yapılandırma Hatası",configurationErrorMessage:"Sunucu aktarımı OAuth finishAuth() desteklemiyor. Lütfen sunucunun streamable-http aktarımıyla yapılandırıldığından emin olun.",internalError:"İçsel Hata",internalErrorMessage:"OAuth geri araması işlenirken beklenmeyen bir hata oluştu.",closeWindow:"Pencereyi Kapat"},pc={add:"Prompt Ekle",addNew:"Yeni Prompt Ekle",edit:"Promptu Düzenle",delete:"Sil",noPrompts:"Yerleşik prompt yapılandırılmamış",addFirst:"İlk promptunuzu ekleyin",name:"Ad",namePlaceholder:"örn. code-review",title:"Başlık",titlePlaceholder:"örn. Kod İnceleme Promptu",description:"Açıklama",descriptionPlaceholder:"Promptun kısa açıklaması",template:"Şablon",templatePlaceholder:"{{parametre}} yer tutucularıyla şablon metni girin...",templateHint:"Şablon parametreleri için {{paramName}} kullanın",arguments:"Argümanlar",addArgument:"Argüman Ekle",argName:"Ad",argDescription:"Açıklama",argRequired:"Zorunlu",enabled:"Etkin",active:"Aktif",inactive:"İnaktif",nameRequired:"Ad zorunludur",templateRequired:"Şablon zorunludur",fetchError:"Yerleşik promptlar yüklenemedi",createError:"Prompt oluşturulamadı",updateError:"Prompt güncellenemedi",deleteError:"Prompt silinemedi",saveError:"Prompt kaydedilemedi",confirmDelete:"Promptu Sil",deleteWarning:'"{{name}}" promptunu silmek istediğinizden emin misiniz? Bu işlem geri alınamaz.'},hc={add:"Kaynak Ekle",addNew:"Yeni Kaynak Ekle",edit:"Kaynağı Düzenle",delete:"Sil",noResources:"Yerleşik kaynak yapılandırılmamış",addFirst:"İlk kaynağınızı ekleyin",uri:"URI",uriPlaceholder:"örn. resource://docs/guide",name:"Ad",namePlaceholder:"örn. Kullanıcı Kılavuzu",description:"Açıklama",descriptionPlaceholder:"Kaynağın kısa açıklaması",mimeType:"MIME Türü",content:"İçerik",contentPlaceholder:"Kaynak içeriğini girin...",enabled:"Etkin",active:"Aktif",inactive:"İnaktif",descriptionUpdateSuccess:"Kaynak açıklaması başarıyla güncellendi",descriptionUpdateFailed:"Kaynak açıklaması güncellenemedi",restoreDefault:"Varsayılana dön",restoreDefaultSuccess:"Kaynak açıklaması varsayılan değere döndürüldü",restoreDefaultFailed:"Varsayılan kaynak açıklamasına dönülemedi",uriRequired:"URI zorunludur",contentRequired:"İçerik zorunludur",fetchError:"Yerleşik kaynaklar yüklenemedi",createError:"Kaynak oluşturulamadı",updateError:"Kaynak güncellenemedi",deleteError:"Kaynak silinemedi",saveError:"Kaynak kaydedilemedi",confirmDelete:"Kaynağı Sil",deleteWarning:'"{{name}}" kaynağını silmek istediğinizden emin misiniz? Bu işlem geri alınamaz.'},gc={title:"Etkinlik",totalCalls:"Toplam çağrı",successCount:"Başarılı",errorCount:"Başarısız",avgDuration:"Ort. süre",timestamp:"Zaman damgası",server:"Sunucu",tool:"Araç",duration:"Süre",status:"Durum",group:"Grup",user:"Kullanıcı",key:"API Anahtarı",sourceIp:"Kaynak IP",input:"Girdi",output:"Çıktı",details:"Etkinlik detayları",errorMessage:"Hata mesajı",searchServer:"Sunucu...",searchTool:"Araç...",searchStatus:"Durum...",searchGroup:"Grup...",searchUsername:"Kullanıcı...",searchKeyName:"API anahtarı...",keyName:"API Anahtarı Adı",allStatus:"Tüm durumlar",statusSuccess:"Başarılı",statusError:"Hata",noData:"Kullanılabilir etkinlik verisi yok",fetchError:"Etkinlik verileri yüklenemedi",cleanup:"Temizle",confirmCleanup:"30 günden eski etkinlikleri silmek istediğinizden emin misiniz?",cleanupSuccess:"{{count}} eski etkinlik silindi",cleanupError:"Eski etkinlikler temizlenemedi",notAvailable:"Etkinlik takibi yalnızca veritabanı modunda kullanılabilir"},bc={exportButton:"Şablon Dışa Aktar",importButton:"Şablon İçe Aktar",exportTitle:"Yapılandırma Şablonunu Dışa Aktar",importTitle:"Yapılandırma Şablonunu İçe Aktar",name:"Şablon Adı",nameRequired:"Şablon adı gereklidir",namePlaceholder:"Ör: Frontend Geliştirme Araçları",description:"Açıklama",descriptionPlaceholder:"Ör: Frontend geliştirme için standart MCP sunucuları",selectGroups:"Grupları Seç",selectGroupsHelp:"Tüm grupları dışa aktarmak için boş bırakın",selectAll:"Tümünü Seç",deselectAll:"Tümünü Kaldır",includeDisabled:"Devre dışı sunucuları dahil et",exportNote:"Gizli bilgiler (API anahtarları, tokenlar, parolalar) ${PLACEHOLDER} referanslarıyla değiştirilecektir. Alıcıların kendi kimlik bilgilerini sağlaması gerekir.",export:"Dışa Aktar",exporting:"Dışa aktarılıyor...",exportFailed:"Şablon dışa aktarılamadı",import:"İçe Aktar",importing:"İçe aktarılıyor...",importFailed:"Şablon içe aktarılamadı",invalidFormat:"Geçersiz şablon formatı. version, name, servers ve groups alanlarını içermelidir.",parseError:"JSON ayrıştırılamadı. Lütfen formatı kontrol edip tekrar deneyin.",uploadFile:"Şablon Dosyası Yükle",or:"veya",pasteJson:"Şablon JSON Yapıştır",pastePlaceholder:".mcphub-template.json içeriğinizi buraya yapıştırın...",version:"Sürüm",createdAt:"Oluşturulma",servers:"Sunucular",groups:"Gruplar",serversInGroup:"sunucu",envVarsNeeded:"Gerekli Ortam Değişkenleri — içe aktarılan sunucuları kullanmadan önce bunları ayarlayın:",importResult:"Sunucular: {{serversCreated}} oluşturuldu, {{serversSkipped}} atlandı. Gruplar: {{groupsCreated}} oluşturuldu, {{groupsSkipped}} atlandı."},vc={exposed:"Gösterilen",gross:"Toplam",estimate:"Tahmini token sayısı (cl100k) — yaklaşık",direct:"Doğrudan",smartRouting:"Akıllı yönlendirme",smartRoutingPd:"Akıllı yönlendirme + aşamalı açıklama",smartRoutingPdHint:"describe_tool meta-aracını ekler — daha yüksek başlangıç maliyeti, ancak arama başına daha küçük yanıtlar",saved:"{{percent}}% daha az",notConnected:"Bağlı değil",connectedOf:"{{total}} sunucudan {{connected}} tanesi bağlı",totalFootprint:"Bağlam ayak izi"},yc={title:"Kimlik Bilgileri",missing:"{{serverName}} için kişisel kimlik bilgileri gerekli. Pano → Kimlik Bilgileri bölümünde gerekli tüm alanları bağlayın.",description:"Paylaşılan sunuculara kendi kimlik bilgilerinizi bağlayın. Her istek, çağrıyı yapan kullanıcının bilgilerini kullanır.",slots:"Kişisel kimlik bilgisi alanları",slotsHint:"Yalnızca alan adlarını tanımlayın. Tüm alanlar zorunludur; kuruluş bilgilerine otomatik dönüş yapılmaz.",target:"Kimlik bilgisi hedefi",urlHint:"URL alanları için {{placeholder}} ifadesini tam bir ana makine etiketi veya yol bölümü olarak kullanın ve izin verilen değerleri listeleyin.",allowed:"İzin verilen değerler (her satıra bir değer)",argsHint:"Argüman alanları için bir argümanda {{placeholder}} kullanın ve API_KEY yerine alan adını yazın. Değerler kabuk kullanılmadan olduğu gibi aktarılır.",fieldName:"Alan adı",label:"Etiket (isteğe bağlı)",addSlot:"Alan ekle",removeSlot:"Alanı kaldır",personalBadge:"Kişisel kimlik bilgileri",manage:"Yönet",configured:"Yapılandırıldı",required:"Bağlama gerekli",writeOnly:"Kaydedilen değerler görüntülenemez. Bağlamayı değiştirmek için tüm alanlara yeni değerler girin.",replaceValue:"Yeni değer girin",enterValue:"Kimlik bilgisi girin",save:"Bağlamayı kaydet",delete:"Bağlamayı sil",saved:"Bağlama kaydedildi",deleted:"Bağlama silindi",failed:"Kimlik bilgileri yönetilemiyor",showAll:"Tüm sunucuları göster",loading:"Yükleniyor…",empty:"Kişisel kimlik bilgisi gerektiren paylaşılan sunucu yok.",targetUser:"Kimlik bilgileri yönetilecek kullanıcı",myCredentials:"Kimlik bilgilerim",updatedAt:"Son güncelleme"},fc={app:zl,about:Ul,profile:ql,sponsor:Bl,wechat:Fl,discord:Kl,theme:jl,auth:Gl,server:Hl,status:_l,errors:Vl,common:$l,clientConfig:Jl,pagination:Wl,nav:Yl,pages:Xl,logs:Ql,groups:Zl,market:ec,oauthServer:rc,cloud:tc,registry:ac,tool:nc,prompt:ic,settings:oc,mcpb:sc,jsonImport:lc,groupImport:cc,users:dc,api:uc,oauthCallback:mc,builtinPrompts:pc,builtinResources:hc,activity:gc,template:bc,cost:vc,credentials:yc},kc={title:"Panel de MCPHub",error:"Error",closeButton:"Cerrar",noServers:"No hay servidores MCP disponibles",loading:"Cargando...",logout:"Cerrar sesión",profile:"Perfil",changePassword:"Cambiar contraseña",toggleSidebar:"Mostrar u ocultar la barra lateral",welcomeUser:"Bienvenido, {{username}}",name:"MCPHub",embeddingSyncProgress:"Embeddings para {{serverName}}",embeddingSyncProgressAriaLabel:"Creando embeddings para {{serverName}}: {{current}} de {{total}} completados"},Sc={title:"Acerca de",versionInfo:"Versión de MCPHub: {{version}}",newVersion:"¡Nueva versión disponible!",currentVersion:"Versión actual",newVersionAvailable:"La nueva versión {{version}} está disponible",viewOnGitHub:"Ver en GitHub",checkForUpdates:"Buscar actualizaciones",checking:"Buscando actualizaciones...",viewChangelog:"Ver registro de cambios",viewReleaseNotes:"Ver notas de la versión",viewAllChanges:"Ver todos los cambios",latestChanges:"Últimos cambios",upToDate:"Ya estás en la última versión conocida.",releaseNotesUnavailable:"Hay una versión más reciente disponible, pero las notas de la versión estructuradas aún no están disponibles.",updateChecksDisabled:"La comprobación de actualizaciones está deshabilitada en esta instalación.",dismissUpdate:"Descartar",dismissed:"Descartado",earlierReleases:"+ {{count}} versiones anteriores"},Cc={viewProfile:"Ver perfil",userCenter:"Centro de usuario"},Pc={label:"Patrocinar",title:"Apoya el proyecto",rewardAlt:"Código QR de recompensa",supportMessage:"¡Apoya el desarrollo de MCPHub invitándome a un café!",supportButton:"Apoyar en Ko-fi"},Ac={label:"WeChat",title:"Conectar por WeChat",qrCodeAlt:"Código QR de WeChat",scanMessage:"Escanea este código QR para conectar con nosotros en WeChat"},Rc={label:"Discord",title:"Únete a nuestro servidor de Discord",community:"¡Únete a nuestra creciente comunidad en Discord para soporte, debates y novedades!"},Tc={title:"Tema",light:"Claro",dark:"Oscuro",system:"Sistema"},xc={createAccount:"Crear cuenta",backToLogin:"Volver al inicio de sesión",userAlreadyExists:"El nombre de usuario ya existe",login:"Iniciar sesión",loginTitle:"Iniciar sesión en MCPHub",slogan:"Pasarela y plano de control MCP de código abierto y autoalojado",subtitle:"Conecta, organiza, controla y opera servidores Model Context Protocol a través de endpoints unificados.",username:"Nombre de usuario",password:"Contraseña",loggingIn:"Iniciando sesión...",orContinue:"O continuar con",loginWithGoogle:"Continuar con Google",loginWithGithub:"Continuar con GitHub",loginWithOIDC:"Continuar con OIDC",socialLoginFailed:"El inicio de sesión social ha fallado. Inténtalo de nuevo.","error.account_not_linked":"Cuenta no vinculada. Es posible que el proveedor de identidad no haya verificado tu correo electrónico. Verifica tu correo e inténtalo de nuevo.","error.email_doesn't_match":"El correo electrónico del proveedor de identidad no coincide con tu cuenta existente.","error.email_not_found":"El proveedor de identidad no ha devuelto ningún correo electrónico.","error.access_denied":"El proveedor de identidad ha denegado el acceso.","error.account_already_linked_to_different_user":"Esta cuenta ya está vinculada a otro usuario.","error.unable_to_link_account":"No se puede vincular la cuenta. Inténtalo de nuevo.","error.signup_disabled":"El registro está deshabilitado actualmente.","error.oauth_provider_not_found":"Proveedor OAuth no encontrado.","error.invalid_code":"Código de autorización no válido. Inténtalo de nuevo.","error.unable_to_get_user_info":"No se puede obtener la información del usuario del proveedor de identidad.",emptyFields:"El nombre de usuario y la contraseña no pueden estar vacíos",loginFailed:"Error al iniciar sesión, comprueba tu nombre de usuario y contraseña",loginError:"Se ha producido un error durante el inicio de sesión",serverUnavailable:"No se puede conectar con el servidor. Comprueba tu conexión de red o inténtalo más tarde",currentPassword:"Contraseña actual",newPassword:"Nueva contraseña",confirmPassword:"Confirmar contraseña",passwordsNotMatch:"La nueva contraseña y la confirmación no coinciden",changePasswordSuccess:"Contraseña cambiada correctamente",changePasswordError:"Error al cambiar la contraseña",changePassword:"Cambiar contraseña",passwordChanged:"Contraseña cambiada correctamente",passwordChangeError:"Error al cambiar la contraseña",defaultPasswordWarning:"Aviso de seguridad: contraseña predeterminada",defaultPasswordMessage:"Estás usando la contraseña predeterminada (admin123), lo que supone un riesgo de seguridad. Cambia tu contraseña inmediatamente para proteger tu cuenta.",goToSettings:"Ir a Ajustes",passwordStrengthError:"La contraseña no cumple los requisitos de seguridad",passwordMinLength:"La contraseña debe tener al menos 8 caracteres",passwordRequireLetter:"La contraseña debe contener al menos una letra",passwordRequireNumber:"La contraseña debe contener al menos un número",passwordRequireSpecial:"La contraseña debe contener al menos un carácter especial",passwordStrengthHint:"La contraseña debe tener al menos 8 caracteres y contener letras, números y caracteres especiales"},wc=JSON.parse(`{"protocolVersion":"Protocolo MCP","protocolVersionUnknown":"No disponible","localExecutionRequiresAdmin":"La ejecución de comandos locales requiere un administrador.","httpOAuthRequiresAdmin":"Permitir endpoints de tokens OAuth por HTTP requiere un administrador.","startOnDemand":"Inicio bajo demanda","startOnDemandDescription":"Omite la conexión al arrancar y lanza este servidor solo cuando llega una llamada de herramienta. El proceso se apaga automáticamente tras el tiempo de inactividad y se reinicia en la siguiente llamada. Reduce el uso persistente de memoria en servidores poco utilizados.","idleTimeoutMs":"Tiempo de inactividad antes del apagado (ms)","idleTimeoutMsDescription":"Apaga el proceso tras estos milisegundos sin llamadas de herramientas. Predeterminado: 300000 (5 minutos).","addServer":"Añadir servidor","add":"Añadir","edit":"Editar","copy":"Copiar","duplicate":"Duplicar","delete":"Eliminar","confirmDelete":"¿Seguro que quieres eliminar este servidor?","deleteWarning":"Eliminar el servidor '{{name}}' lo borrará junto con todos sus datos. Esta acción no se puede deshacer.","status":"Estado","tools":"Herramientas","prompts":"Prompts","name":"Nombre del servidor","nameInvalid":"El nombre del servidor solo puede contener letras, números, puntos, guiones bajos y guiones (sin espacios ni caracteres especiales)","description":"Nota del servidor","descriptionPlaceholder":"Nota opcional para describir este servidor","url":"URL del servidor","apiKey":"Clave de API","save":"Guardar","cancel":"Cancelar","invalidConfig":"No se han encontrado datos de configuración para {{serverName}}","addError":"Error al añadir el servidor","editError":"Error al editar el servidor {{serverName}}","deleteError":"Error al eliminar el servidor {{serverName}}","updateError":"Error al actualizar el servidor","editTitle":"Editar servidor: {{serverName}}","duplicateTitle":"Duplicar servidor: {{serverName}}","type":"Tipo de servidor","typeStdio":"STDIO","typeSse":"SSE","typeStreamableHttp":"Streamable HTTP","typeOpenapi":"OpenAPI","mcpApp":"MCP App — este servidor expone recursos de UI interactivos","visibility":"Visibilidad","visibilityPrivateShort":"Privado","visibilityPrivate":"Privado — solo el propietario y los administradores","visibilityGroupShort":"Compartido","visibilityGroup":"Compartido — solo usuarios seleccionados","visibilityPublicShort":"Público","visibilityPublic":"Público — todos los usuarios autenticados","visibilityDescription":"Controla qué usuarios no administradores pueden descubrir y llamar a este servidor. Los administradores siempre tienen acceso.","shareWithUsers":"Compartir con usuarios","shareWithUsersDescription":"Los usuarios seleccionados pueden descubrir y llamar a este servidor, pero no pueden gestionar su configuración.","shareCandidatesLoading":"Cargando usuarios...","shareCandidatesError":"Error al cargar los usuarios.","shareAfterCreate":"Guarda el servidor antes de seleccionar usuarios.","noShareCandidates":"No hay otros usuarios disponibles.","shareUserSearchLabel":"Buscar usuarios","shareUserSearchPlaceholder":"Buscar nombres de usuario...","selectAllShareUsers":"Seleccionar todos","deselectAllShareUsers":"Deseleccionar todos","noMatchingShareUsers":"Ningún usuario coincide con tu búsqueda.","command":"Comando","packageVersion":"Versión del paquete instalada (última instalada por la caché del runner)","reportedVersion":"Versión indicada por el servidor","updateAvailable":"Hay una versión más reciente disponible en el registro","arguments":"Argumentos","addArgument":"Añadir argumento","argumentsHint":"Cada campo es un argumento. Los espacios y las comillas se conservan; un campo vacío pasa un argumento vacío.","argumentLabel":"Argumento {{index}}","removeArgument":"Eliminar argumento {{index}}","envVars":"Variables de entorno","headers":"Cabeceras HTTP","key":"clave","value":"valor","enabled":"Habilitado","enable":"Habilitar","disable":"Deshabilitar","reload":"Recargar","reloadSuccess":"Servidor recargado correctamente","reloadError":"Error al recargar el servidor {{serverName}}","reinstall":"Reinstalar","reinstallConfirm":"Esto borrará la caché de paquetes y volverá a descargar las dependencias. El servidor se reiniciará.","reinstallSuccess":"Reinstalación del servidor iniciada","reinstallError":"Error al reinstalar el servidor {{serverName}}","disconnectOAuth":"Desconectar OAuth","disconnectOAuthConfirm":"Esto revocará las credenciales OAuth almacenadas cuando sea compatible y requerirá autorización de nuevo.","disconnectOAuthSuccess":"OAuth del servidor desconectado","disconnectOAuthError":"Error al desconectar OAuth del servidor {{serverName}}","requestOptions":"Configuración de conexión","maxBufferSize":"Límite del búfer stdio (bytes)","maxBufferSizeDescription":"Tamaño máximo del búfer de lectura stdio. Déjalo en blanco para usar el valor predeterminado del SDK (10 MiB). Límites mayores permiten un mayor uso de memoria.","timeout":"Tiempo de espera de la solicitud","timeoutDescription":"Tiempo de espera para las solicitudes al servidor MCP (ms)","maxTotalTimeout":"Tiempo de espera total máximo","maxTotalTimeoutDescription":"Tiempo de espera total máximo para las solicitudes enviadas al servidor MCP (ms) (usar con notificaciones de progreso)","resetTimeoutOnProgress":"Restablecer el tiempo de espera al progresar","resetTimeoutOnProgressDescription":"Restablece el tiempo de espera con las notificaciones de progreso (habilitado por defecto)","keepAlive":"Estado de la conexión","retryScheduled":"Reintento a las {{time}}","reconnecting":"Reconectando…","lastRetry":"Último reintento: {{time}} ({{count}} intentos)","enableKeepAlive":"Habilitar comprobaciones de estado","keepAliveDescription":"Comprobar el estado periódicamente. Los servidores remotos desconectados siempre se reconectan automáticamente con espera progresiva.","keepAliveInterval":"Intervalo de comprobación (ms)","keepAliveIntervalDescription":"Tiempo entre comprobaciones en milisegundos (predeterminado: 60000 ms = 1 minuto)","perSessionClient":"Aislamiento de cliente por sesión","perSessionClientDescription":"Crea una conexión ascendente dedicada por sesión en lugar de compartir una entre todas las sesiones. Habilítalo para servidores con estado como Playwright. Aumenta las conexiones ascendentes con sesiones concurrentes.","remove":"Quitar","toggleError":"Error al cambiar el estado del servidor {{serverName}}","alreadyExists":"El servidor {{serverName}} ya existe","invalidData":"Datos de servidor no válidos","notFound":"Servidor {{serverName}} no encontrado","namePlaceholder":"Introduce el nombre del servidor","urlPlaceholder":"Introduce la URL del servidor","commandPlaceholder":"Introduce el comando","argumentsPlaceholder":"Introduce los argumentos","errorDetails":"Detalles del error","viewErrorDetails":"Ver detalles del error","copyConfig":"Copiar configuración","confirmVariables":"Confirmar configuración de variables","variablesDetected":"Se han detectado variables en la configuración. Confirma que estas variables están correctamente configuradas:","detectedVariables":"Variables detectadas","confirmVariablesMessage":"Asegúrate de que estas variables están correctamente definidas en tu entorno de ejecución. ¿Continuar añadiendo el servidor?","confirmAndAdd":"Confirmar y añadir","openapi":{"inputMode":"Modo de entrada","inputModeUrl":"URL de la especificación","inputModeSchema":"Esquema JSON","specUrl":"URL de la especificación OpenAPI","schema":"Esquema JSON de OpenAPI","schemaHelp":"Pega aquí tu esquema JSON de OpenAPI completo","security":"Tipo de seguridad","securityNone":"Ninguna","securityApiKey":"Clave de API","securityHttp":"Autenticación HTTP","securityOAuth2":"OAuth 2.0","securityOpenIdConnect":"OpenID Connect","securityDetect":"Detectar desde la especificación","securityDetecting":"Detectando…","securityNotDeclared":"Esta especificación no declara ningún esquema de seguridad.","securityPrefillNotice":"Esta especificación declara {{summary}}. La configuración de seguridad se ha rellenado previamente: añade el valor de tu credencial antes de la primera llamada.","securityMismatchWarning":"La especificación declara {{summary}}, pero este servidor está configurado como {{configured}}. Esto puede provocar respuestas 401 silenciosas.","securityUnsupportedNotice":"Esta especificación declara {{summary}}, que MCPHub no puede representar ({{reason}}). Configura la autenticación manualmente.","apiKeyConfig":"Configuración de clave de API","apiKeyName":"Nombre de cabecera/parámetro","apiKeyIn":"Ubicación","apiKeyValue":"Valor de la clave de API","httpAuthConfig":"Configuración de autenticación HTTP","httpScheme":"Esquema de autenticación","httpCredentials":"Credenciales","httpCredentialsBasicHint":"Introduce usuario:contraseña (se codifica automáticamente) o Base64 precodificado.","specSecurityToggle":"La URL de la especificación requiere autenticación independiente","specSecurityHelp":"Habilítalo solo cuando el propio documento de la especificación esté protegido de forma distinta a la API (p. ej., /v3/api-docs protegido con Basic detrás de una API protegida con Bearer). Si está desactivado, la configuración de seguridad anterior se usa para ambos.","httpSchemeBasic":"Basic","httpSchemeBearer":"Bearer","httpSchemeDigest":"Digest","oauth2Config":"Configuración de OAuth 2.0","oauth2Token":"Token de acceso","openIdConnectConfig":"Configuración de OpenID Connect","openIdConnectUrl":"URL de descubrimiento","openIdConnectToken":"Token de ID","apiKeyInHeader":"Cabecera","apiKeyInQuery":"Query","apiKeyInCookie":"Cookie","passthroughHeaders":"Cabeceras de paso directo","passthroughHeadersHelp":"Lista separada por comas de nombres de cabecera que se pasan de las solicitudes MCP entrantes a las solicitudes del servidor ascendente (p. ej., Authorization, X-API-Key)","cookieSession":"Gestión de sesión con cookies","cookieSessionHelp":"Captura las Set-Cookie de las respuestas de inicio de sesión ascendentes y las reenvía en llamadas posteriores dentro de la misma sesión descendente. Aislada por sesión MCP; no se persiste.","statsMeasuring":"Midiendo la lista de herramientas generada…","statsSummary":"{{toolCount}} herramientas · ~{{bytes}} de definiciones · ~{{tokens}} tokens","statsWarning":"Esta lista de herramientas por sí sola puede acercarse o superar las ventanas de contexto habituales de los modelos. Considera exponer menos herramientas: crea un grupo o deshabilita herramientas individuales en el servidor.","statsUnavailable":"No se ha podido medir la especificación. Puedes continuar; el servidor validará la importación al enviarla."},"oauth":{"sectionTitle":"Configuración de OAuth","sectionDescription":"Configura las credenciales de cliente para servidores protegidos con OAuth (opcional).","allowInsecureTokenEndpoint":"Permitir endpoints de token OAuth por HTTP","allowInsecureTokenEndpointHelp":"Solo administradores. Deshabilitado por defecto. Envía credenciales y tokens sin TLS a este servidor ascendente. Habilítalo solo en una red de confianza; se recomienda HTTPS. Una vez habilitado, solo los administradores pueden editar toda la configuración de este servidor; un propietario no administrador no puede editarla.","clientId":"ID de cliente","clientSecret":"Secreto de cliente","authorizationEndpoint":"Endpoint de autorización","tokenEndpoint":"Endpoint de token","scopes":"Scopes","scopesPlaceholder":"scope1 scope2","resource":"Recurso / Audiencia","accessToken":"Token de acceso","refreshToken":"Token de actualización","identityMode":"Identidad OAuth","sharedIdentity":"Cuenta compartida","personalIdentity":"Cada usuario autoriza de forma independiente","personalIdentityHelp":"El modo personal requiere autorización desde el panel para cada usuario. Las claves asociadas a usuarios usan a su propietario; las claves compartidas o de servicio no son válidas.","personalConnect":"Conectar","personalReconnect":"Reconectar","personalDisconnect":"Desconectar","personalError":"Error en la autorización personal","personalSuccess":"Autorización personal guardada. Vuelve a Panel → Servidores."}}`),Dc={sleeping:"En suspensión",sleepingDescription:"Servidor bajo demanda: se iniciará automáticamente cuando se llame a una herramienta",online:"En línea",offline:"Sin conexión",connecting:"Conectando",oauthRequired:"Se requiere OAuth",clickToAuthorize:"Haz clic para autorizar con OAuth",oauthWindowOpened:"Se ha abierto la ventana de autorización OAuth. Completa la autorización.",oauthClientIdHint:'Este servidor tiene un ID de cliente OAuth preconfigurado. Si la autorización falla con "invalid redirect_uri", elimina el clientId para que MCPHub pueda registrar su propio cliente OAuth automáticamente.'},Ec={general:"Algo ha ido mal",network:"Error de conexión de red. Comprueba tu conexión a internet",serverConnection:"No se puede conectar con el servidor. Comprueba si el servidor está en ejecución",serverAdd:"Error al añadir el servidor. Comprueba el estado del servidor",serverUpdate:"Error al editar el servidor {{serverName}}. Comprueba el estado del servidor",serverFetch:"Error al obtener los datos del servidor. Inténtalo de nuevo más tarde",initialStartup:"Es posible que el servidor se esté iniciando. Espera un momento, este proceso puede tardar en el primer arranque...",serverInstall:"Error al instalar el servidor",failedToFetchSettings:"Error al obtener los ajustes",failedToUpdateRouteConfig:"Error al actualizar la configuración de rutas",failedToUpdateSmartRoutingConfig:"Error al actualizar la configuración de enrutamiento inteligente",failedToUpdateBetterAuthConfig:"Error al actualizar la configuración de Better Auth"},Ic={processing:"Procesando...",save:"Guardar",cancel:"Cancelar",back:"Volver",refresh:"Actualizar",search:"Buscar",clear:"Limpiar",view:"Ver",create:"Crear",creating:"Creando...",update:"Actualizar",updating:"Actualizando...",submitting:"Enviando...",delete:"Eliminar",remove:"Quitar",copy:"Copiar",copyId:"Copiar ID",copyUrl:"Copiar URL",copyOpenApiUrl:"Copiar URL de OpenAPI",copySuccess:"Copiado al portapapeles",copyFailed:"Error al copiar",copied:"Copiado",close:"Cerrar",confirm:"Confirmar",language:"Idioma",true:"Verdadero",false:"Falso",dismiss:"Descartar",github:"GitHub",wechat:"WeChat",discord:"Discord",required:"Obligatorio",itemsPerPage:"Elementos por página",showing:"Mostrando {{start}}-{{end}} de {{total}}",previous:"Anterior",next:"Siguiente",secret:"Secreto",default:"Predeterminado",value:"Valor",type:"Tipo",repeated:"Repetido",valueHint:"Sugerencia de valor",choices:"Opciones",actions:"Acciones",saving:"Guardando...",active:"Activo",inactive:"Inactivo",viewAll:"Ver todo",docs:"Documentación",all:"Todos"},Nc={title:"Copiar configuración MCP",description:"Elige tu cliente para copiar una configuración de {{name}} lista para pegar.",menuItem:"Copiar config. MCP",tokenPrompt:"Token de acceso de MCPHub",configBlock:"Configuración",commandBlock:"Comando CLI",copied:"Copiado",noTransport:"Este servidor no tiene transporte MCP de cliente (usa OpenAPI como base). Utiliza el hub o un endpoint de grupo en su lugar.",clients:{"generic-mcp-servers":{label:"Genérico (mcpServers)",hint:"Bloque mcpServers ampliamente aceptado: Claude Desktop, Cline, Cherry Studio y la mayoría de los clientes."},"generic-http":{label:"HTTP genérico",hint:'Opción alternativa con la entrada básica: los endpoints remotos generan una entrada HTTP sin procesar (los upstreams SSE incluyen un marcador "type": "sse"), los servidores locales una entrada stdio sin procesar (command/args/env). Pégala en el mapa de servidores de tu cliente; para la mayoría de los clientes usa Genérico (mcpServers).'},"claude-code":{label:"Claude Code",hint:"Claude Code: `claude mcp add`, o el bloque mcpServers en ~/.claude.json."},cursor:{label:"Cursor",hint:"Cursor: .cursor/mcp.json en un proyecto, o ~/.cursor/mcp.json de forma global."},vscode:{label:"VS Code / Copilot",hint:"VS Code / Copilot: .vscode/mcp.json en el espacio de trabajo, o mcp.json en tu perfil de usuario."},codex:{label:"Codex",hint:"Codex: ~/.codex/config.toml, o un .codex/config.toml a nivel de proyecto."},opencode:{label:"OpenCode",hint:"OpenCode: ~/.config/opencode/opencode.json de forma global, o opencode.json en el proyecto."},windsurf:{label:"Windsurf",hint:"Windsurf: ~/.codeium/windsurf/mcp_config.json."},"cherry-studio":{label:"Cherry Studio",hint:"Cherry Studio: Configuración > Servidores MCP > Añadir servidor > Importar JSON."},codebuddy:{label:"CodeBuddy Code",hint:"CodeBuddy Code: ~/.codebuddy/.mcp.json de forma global, o .mcp.json en el proyecto."},qoder:{label:"Qoder",hint:"Qoder: Configuración > MCP > Añadir manualmente, y luego pega el JSON."},trae:{label:"TRAE",hint:"TRAE: Configuración > MCP > Añadir > Añadir manualmente, y luego pega el JSON."},zcode:{label:"ZCode",hint:"ZCode: Configuración > Servidores MCP > Nuevo servidor MCP > Configuración completa."},workbuddy:{label:"WorkBuddy",hint:"WorkBuddy: Plugins > Servidores MCP > Configurar MCP, o ~/.workbuddy/mcp.json."}}},Oc={rowsPerPage:"Filas por página",showing:"Mostrando {{from}}-{{to}} de {{total}}"},Mc={dashboard:"Panel",servers:"Servidores",groups:"Grupos",prompts:"Prompts",resources:"Recursos",users:"Usuarios",settings:"Ajustes",changePassword:"Cambiar contraseña",market:"Mercado",cloud:"Mercado cloud",logs:"Registros",activity:"Actividad",workspace:"Espacio de trabajo",system:"Sistema"},Lc={dashboard:{title:"Panel",totalServers:"Total",onlineServers:"En línea",disabledServers:"Deshabilitados",offlineServers:"Sin conexión",connectingServers:"Conectando",recentServers:"Servidores recientes",endpoints:"Endpoints MCP",endpointsHint:"Usa estas URL en Claude Desktop, Cursor o cualquier cliente MCP"},servers:{title:"Gestión de servidores"},groups:{title:"Gestión de grupos"},prompts:{title:"Prompts integrados"},resources:{title:"Recursos integrados"},users:{title:"Gestión de usuarios"},settings:{title:"Ajustes",language:"Idioma",account:"Ajustes de cuenta",password:"Cambiar contraseña",appearance:"Apariencia",routeConfig:"Seguridad",installConfig:"Instalación",smartRouting:"Enrutamiento inteligente",oauthServer:"Servidor OAuth"},market:{title:"Market Hub - Mercados locales y en la nube"},logs:{title:"Registros del sistema"}},zc={filters:"Filtros",search:"Buscar en los registros...",autoScroll:"Desplazamiento automático",clearLogs:"Borrar registros",loading:"Cargando registros...",noLogs:"No hay registros disponibles.",noMatch:"Ningún registro coincide con los filtros actuales.",mainProcess:"Proceso principal",childProcess:"Proceso hijo",main:"Principal",child:"Hijo"},Uc={legacyVisibility:"Heredada — elige la visibilidad",legacyVisibilityHint:"Este grupo mantiene su acceso de endpoint anterior hasta que elijas explícitamente la visibilidad.",visibilityDescription:"El acceso al grupo también requiere acceso a cada servidor. Compartir un grupo no comparte servidores privados. Solo el propietario y los administradores pueden gestionar el grupo.",shareAfterCreate:"Guarda el grupo antes de seleccionar usuarios.",add:"Añadir",addNew:"Añadir nuevo grupo",edit:"Editar grupo",delete:"Eliminar",confirmDelete:"¿Seguro que quieres eliminar este grupo?",deleteWarning:"Eliminar el grupo '{{name}}' lo borrará junto con todas sus asociaciones de servidores. Esta acción no se puede deshacer.",name:"Nombre del grupo",namePlaceholder:"Introduce el nombre del grupo",instructions:"Instrucciones",instructionsHelp:"Opcional. Se envían a los clientes MCP al conectarse a este grupo (también como $smart/<group>); la mayoría los añade al prompt de sistema del modelo.",instructionsPlaceholder:"p. ej., Usa fetch para páginas web; si falla, usa firecrawl_scrape.",nameRequired:"El nombre del grupo es obligatorio",description:"Descripción",descriptionPlaceholder:"Introduce la descripción del grupo (opcional)",createError:"Error al crear el grupo",updateError:"Error al actualizar el grupo",deleteError:"Error al eliminar el grupo",serverAddError:"Error al añadir el servidor al grupo",serverRemoveError:"Error al quitar el servidor del grupo",addServer:"Añadir servidor al grupo",selectServer:"Selecciona un servidor para añadir",servers:"Servidores del grupo",remove:"Quitar",noGroups:"No hay grupos disponibles. Crea un nuevo grupo para empezar.",noServers:"No hay servidores en este grupo.",noServerOptions:"No hay servidores disponibles",serverCount:"{{count}} servidores",toolSelection:"Selección de herramientas",promptSelection:"Selección de prompts",resourceSelection:"Selección de recursos",toolsSelected:"Seleccionadas",promptsSelected:"Seleccionados",resourcesSelected:"Seleccionados",allTools:"Todas",allPrompts:"Todos los prompts",allResources:"Todos los recursos",selectedTools:"Herramientas seleccionadas",selectedPrompts:"Prompts seleccionados",selectedResources:"Recursos seleccionados",selectAll:"Seleccionar todo",selectNone:"No seleccionar ninguno",configureTools:"Configurar herramientas",configureCapabilities:"Configurar herramientas, prompts y recursos",alias:"Nombre expuesto",preserveToolNames:"Conservar los nombres originales de las herramientas",preserveToolNamesHint:"Expone herramientas sin prefijo del servidor. Los nombres deben ser únicos en el grupo. El nombre expuesto sigue aplicándose a los prompts.",pinTool:"Fijar: muestra siempre esta herramienta en el endpoint de enrutamiento inteligente del grupo, junto a search_tools",pinToolLabel:"Fijar en el endpoint de enrutamiento inteligente",unpinTool:"Desfijar: accede a esta herramienta solo a través de search_tools",previewPrompts:"[prompts: {{items}}]",previewResources:"[recursos: {{items}}]",previewAllTools:"(todas las herramientas)",previewAllPrompts:"(todos los prompts)",previewAllResources:"(todos los recursos)",bulkSearch:"Buscar por nombre o descripción…",bulkSearchLabel:"Buscar {{capability}}",annotationFilter:"Filtrar por anotación",allAnnotations:"Todas las anotaciones",readOnlyHint:"Indicación de solo lectura",destructiveHint:"Indicación destructiva",idempotentHint:"Indicación de idempotencia",flatList:"Lista plana",riskGroups:"Grupos de riesgo",visibleCount:"{{count}} de {{total}} visibles",selectVisible:"Seleccionar visibles",deselectVisible:"Deseleccionar visibles",invertVisible:"Invertir visibles",riskHint:"Los grupos usan indicaciones del servidor y heurísticas de nombres; no garantizan seguridad. Las acciones solo afectan a los elementos filtrados.",noMatchingItems:"No hay coincidencias",risk_read:"Lectura",risk_create:"Creación",risk_update:"Actualización",risk_delete:"Eliminación",risk_other:"Otros / sin clasificar"},qc={title:"Instalación local",official:"Oficial",by:"Por",unknown:"Desconocido",tools:"herramientas",search:"Buscar",searchPlaceholder:"Buscar servidores por nombre, categoría o etiquetas",clearFilters:"Limpiar",clearCategoryFilter:"",clearTagFilter:"",categories:"Categorías",tags:"Etiquetas",showTags:"Mostrar etiquetas",hideTags:"Ocultar etiquetas",moreTags:"",noServers:"No se han encontrado servidores que coincidan con tu búsqueda",backToList:"Volver a la lista",install:"Instalar",installing:"Instalando...",installed:"Instalado",installServer:"Instalar servidor: {{name}}",installSuccess:"Servidor {{serverName}} instalado correctamente",author:"Autor",license:"Licencia",repository:"Repositorio",examples:"Ejemplos",arguments:"Argumentos",argumentName:"Nombre",description:"Descripción",required:"Obligatorio",example:"Ejemplo",viewSchema:"Ver esquema",fetchError:"Error al obtener los servidores del mercado",serverNotFound:"Servidor no encontrado",searchError:"Error al buscar servidores",filterError:"Error al filtrar servidores por categoría",tagFilterError:"Error al filtrar servidores por etiqueta",noInstallationMethod:"No hay ningún método de instalación disponible para este servidor",showing:"Mostrando {{from}}-{{to}} de {{total}} servidores",perPage:"Por página",confirmVariablesMessage:"Asegúrate de que estas variables están correctamente definidas en tu entorno de ejecución. ¿Continuar instalando el servidor?",confirmAndInstall:"Confirmar e instalar"},Bc={authorizeTitle:"Autorizar aplicación",authorizeSubtitle:"Permitir que esta aplicación acceda a tu cuenta de MCPHub.",buttons:{approve:"Permitir acceso",deny:"Denegar",approveSubtitle:"Recomendado si confías en esta aplicación.",denySubtitle:"Siempre puedes conceder acceso más tarde."},application:"Aplicación",scopesTitle:"Esta aplicación podrá:",noScopes:"No se han solicitado permisos.",requestInvalidTitle:"Solicitud no válida",requestInvalid:"Esta solicitud de autorización no es válida o ha caducado. Vuelve atrás e inténtalo de nuevo.",grantingAccessTo:"Concediendo acceso a:",resourceAll:"Todos los servidores MCP",resourceSmart:"Enrutamiento inteligente",resourceServer:"Servidor MCP: {{name}}",resourceGroup:"Grupo MCP: {{name}}",clientId:"ID de cliente",willRedirectTo:"Redirigirá a:",policy:"Política de privacidad",terms:"Términos",homepage:"Página principal"},Fc={title:"Soporte en la nube",subtitle:"Con tecnología de MCPRouter",by:"Por",server:"Servidor",config:"Configuración",created:"Creado",updated:"Actualizado",available:"Disponible",description:"Descripción",details:"Detalles",tools:"Herramientas",tool:"herramienta",toolsAvailable:"{{count}} herramienta disponible||{{count}} herramientas disponibles",loadingTools:"Cargando herramientas...",noTools:"No hay herramientas disponibles para este servidor",noDescription:"No hay descripción disponible",viewDetails:"Ver detalles",parameters:"Parámetros",result:"Resultado",error:"Error",callTool:"Llamar",calling:"Llamando...",toolCallSuccess:"Herramienta {{toolName}} ejecutada correctamente",toolCallError:"Error al llamar a la herramienta {{toolName}}: {{error}}",viewSchema:"Ver esquema",backToList:"Volver al mercado cloud",search:"Buscar",searchPlaceholder:"Buscar servidores cloud por nombre, título o autor",clearFilters:"Limpiar filtros",clearCategoryFilter:"Limpiar",clearTagFilter:"Limpiar",categories:"Categorías",tags:"Etiquetas",noCategories:"No se han encontrado categorías",noTags:"No se han encontrado etiquetas",noServers:"No se han encontrado servidores cloud",fetchError:"Error al obtener los servidores cloud",serverNotFound:"Servidor cloud no encontrado",searchError:"Error al buscar servidores cloud",filterError:"Error al filtrar servidores cloud por categoría",tagFilterError:"Error al filtrar servidores cloud por etiqueta",showing:"Mostrando {{from}}-{{to}} de {{total}} servidores cloud",perPage:"Por página",apiKeyNotConfigured:"Clave de API de MCPRouter no configurada",apiKeyNotConfiguredDescription:"Para usar servidores cloud, debes configurar tu clave de API de MCPRouter.",getApiKey:"Obtener clave de API",configureInSettings:"Configurar en Ajustes",installServer:"Instalar {{name}}",installSuccess:"Servidor {{name}} instalado correctamente",installError:"Error al instalar el servidor: {{error}}"},Kc={title:"Registro",official:"Oficial",latest:"Última",description:"Descripción",website:"Sitio web",repository:"Repositorio",packages:"Paquetes",package:"paquete",remotes:"Remotos",remote:"remoto",published:"Publicado",updated:"Actualizado",install:"Instalar",installing:"Instalando...",installed:"Instalado",installServer:"Instalar {{name}}",installSuccess:"Servidor {{name}} instalado correctamente",installError:"Error al instalar el servidor: {{error}}",noDescription:"No hay descripción disponible",viewDetails:"Ver detalles",backToList:"Volver al registro",search:"Buscar",searchPlaceholder:"Buscar servidores del registro por nombre",clearFilters:"Limpiar",noServers:"No se han encontrado servidores en el registro",fetchError:"Error al obtener los servidores del registro",serverNotFound:"Servidor del registro no encontrado",showing:"Mostrando {{from}}-{{to}} de {{total}} servidores del registro",perPage:"Por página",environmentVariables:"Variables de entorno",packageArguments:"Argumentos del paquete",runtimeArguments:"Argumentos de ejecución",headers:"Cabeceras"},jc={run:"Ejecutar",running:"Ejecutando...",runTool:"Ejecutar herramienta",cancel:"Cancelar",noDescription:"No hay descripción disponible",inputSchema:"Esquema de entrada:",runToolWithName:"Ejecutar herramienta: {{name}}",execution:"Ejecución de herramienta",successful:"Correcta",failed:"Fallida",result:"Resultado:",error:"Error",errorDetails:"Detalles del error:",noContent:"La herramienta se ha ejecutado correctamente pero no ha devuelto contenido.",unknownError:"Se ha producido un error desconocido",jsonResponse:"Respuesta JSON:",toolResult:"Resultado de la herramienta",noParameters:"Esta herramienta no requiere parámetros.",selectOption:"Selecciona una opción",enterValue:"Introduce un valor de tipo {{type}}",enabled:"Habilitada",enableSuccess:"Herramienta {{name}} habilitada correctamente",disableSuccess:"Herramienta {{name}} deshabilitada correctamente",toggleFailed:"Error al cambiar el estado de la herramienta",descriptionUpdateSuccess:"Descripción de la herramienta actualizada correctamente",descriptionUpdateFailed:"Error al actualizar la descripción de la herramienta",descriptionModifiedBadge:"Modificada",defaultDescriptionLabel:"Descripción predeterminada",visibleParams:"Parámetros visibles para los modelos",visibleParamsHelp:"Los parámetros sin marcar se eliminan del esquema que reciben los modelos y se descartan de sus llamadas. Los parámetros obligatorios (*) no se pueden ocultar.",requiredParam:"Los parámetros obligatorios no se pueden ocultar",hiddenParamsFailed:"No se pudieron actualizar los parámetros ocultos",defaultDescriptionTooltip:"Descripción predeterminada: {{description}}",restoreDefault:"Restaurar predeterminada",restoreDefaultSuccess:"Descripción de la herramienta restaurada a la predeterminada",restoreDefaultFailed:"Error al restaurar la descripción predeterminada de la herramienta",parameters:"Parámetros de la herramienta",formMode:"Modo formulario",jsonMode:"Modo JSON",jsonConfiguration:"Configuración JSON",invalidJsonFormat:"Formato JSON no válido",fixJsonBeforeSwitching:"Corrige el formato JSON antes de cambiar al modo formulario",item:"Elemento {{index}}",addItem:"Añadir elemento {{key}}",enterKey:"Introduce {{key}}"},Gc={run:"Obtener",running:"Obteniendo...",result:"Resultado del prompt",error:"Error del prompt",execution:"Ejecución del prompt",successful:"Correcta",failed:"Fallida",errorDetails:"Detalles del error:",noContent:"El prompt se ha ejecutado correctamente pero no ha devuelto contenido.",unknownError:"Se ha producido un error desconocido",jsonResponse:"Respuesta JSON:",description:"Descripción",messages:"Mensajes",noDescription:"No hay descripción disponible",runPromptWithName:"Obtener prompt: {{name}}",descriptionUpdateSuccess:"Descripción del prompt actualizada correctamente",descriptionUpdateFailed:"Error al actualizar la descripción del prompt",restoreDefault:"Restaurar predeterminada",restoreDefaultSuccess:"Descripción del prompt restaurada a la predeterminada",restoreDefaultFailed:"Error al restaurar la descripción predeterminada del prompt"},Hc=JSON.parse('{"dashboardName":"Nombre del panel","dashboardNameDescription":"Se muestra en la barra lateral, la cabecera, el inicio de sesión y la pestaña. Déjelo vacío para restaurar el nombre predeterminado.","dashboardNameSaveFailed":"No se pudo guardar el nombre del panel","resetBearerKey":"Restablecer clave Bearer","resetBearerKeyConfirm":"¿Restablecer esta clave Bearer? El token anterior dejará de funcionar inmediatamente. Los permisos y el estado no cambiarán.","resetBearerKeySuccess":"Clave restablecida. Copia y guarda el nuevo token antes de cerrar; no volverá a mostrarse.","resetBearerKeyError":"No se pudo restablecer la clave Bearer","allowRegistration":"Permitir el registro público","allowRegistrationDescription":"Permite crear cuentas normales desde la página de inicio de sesión. Desactivado por defecto; no disponible si se desactiva el acceso con contraseña.","allowedCidrs":"Rangos CIDR ascendentes permitidos","allowedCidrsDescription":"Un CIDR IPv4 o IPv6 por línea. Todos los usuarios pueden conectar con endpoints MCP, OpenAPI y OAuth ascendentes en estos rangos. Vacío significa sin acceso adicional. Los servidores propiedad de administradores conservan acceso interno sin restricciones. Evita rangos amplios y direcciones de metadatos o loopback salvo que sean necesarias. Los cambios se aplican a las nuevas solicitudes; las conexiones existentes no se cierran.","allowedCidrsUpdateFailed":"Error al actualizar los rangos CIDR permitidos","subtitle":"Configura los ajustes del sistema, la autenticación, el enrutamiento y las integraciones de servidores MCP.","enableGlobalRoute":"Habilitar ruta global","enableGlobalRouteDescription":"Permitir conexiones al endpoint /sse sin especificar un ID de grupo","enableGroupNameRoute":"Habilitar ruta por nombre de grupo","enableGroupNameRouteDescription":"Permitir conexiones al endpoint /sse usando nombres de grupo en lugar de solo IDs de grupo","enableBearerAuth":"Habilitar autenticación Bearer","enableBearerAuthDescription":"Requerir autenticación mediante token Bearer para los endpoints MCP (activado por defecto)","bearerAuthKey":"Clave de autenticación Bearer","bearerAuthKeyDescription":"La clave de autenticación que se requerirá en el token Bearer","bearerAuthKeyPlaceholder":"Introduce la clave de autenticación Bearer","bearerAuthHeaderName":"Nombre de la cabecera de autenticación Bearer","bearerAuthHeaderNameDescription":"Nombre de cabecera usado para recibir las credenciales Bearer de MCP. Cámbialo cuando las cabeceras de paso directo ascendentes también usen Authorization.","bearerAuthHeaderNamePlaceholder":"p. ej., Authorization o X-MCP-Authorization","bearerKeysSectionTitle":"Claves","bearerKeysSectionDescription":"Gestiona varias claves con diferentes ámbitos de acceso.","bearerKeyScopeFilter":"Filtrar por ámbito","noBearerKeys":"Aún no hay claves configuradas.","bearerKeyName":"Nombre","bearerKeyToken":"Token","bearerKeyEnabled":"Habilitada","bearerKeyAccessType":"Ámbito de acceso","bearerKeyAccessAll":"Todas","bearerKeyAccessGroups":"Grupos","bearerKeyAccessServers":"Servidores","bearerKeyAccessCustom":"Personalizado","bearerKeyAllowedGroups":"Grupos permitidos","bearerKeyAllowedServers":"Servidores permitidos","addBearerKey":"Añadir clave","addBearerKeyButton":"Crear","bearerKeyRequired":"El nombre y el token son obligatorios","bearerKeyNameRequired":"El nombre es obligatorio","bearerKeyOwnerRequired":"El propietario es obligatorio","bearerKeyKind":"Tipo de clave","bearerKeyKindSystem":"A nivel de sistema","bearerKeyKindUser":"A nivel de usuario","bearerKeyOwner":"Propietario","bearerKeySelectOwner":"Seleccionar usuario...","bearerKeyAccessUserVisibility":"Visibilidad de usuario","bearerKeyShownOnce":"Copia este token ahora. No se volverá a mostrar.","deleteBearerKeyConfirm":"¿Seguro que quieres eliminar esta clave?","generate":"Generar","selectGroups":"Seleccionar grupos","selectServers":"Seleccionar servidores","selectAtLeastOneGroup":"Selecciona al menos un grupo","selectAtLeastOneServer":"Selecciona al menos un servidor","skipAuth":"Omitir autenticación","skipAuthDescription":"Permite el acceso al panel sin iniciar sesión; los usuarios no autenticados obtienen acceso de administrador invitado (no afecta a la autenticación de los endpoints MCP)","jsonBodyLimit":"Límite de tamaño del cuerpo JSON","jsonBodyLimitDescription":"Límite de tamaño de las solicitudes JSON de Express. También afecta a las subidas de esquemas OpenAPI grandes.","jsonBodyLimitPlaceholder":"p. ej., 1mb, 5mb, 1024kb","pythonIndexUrl":"URL del repositorio de paquetes de Python","pythonIndexUrlDescription":"Establece la variable de entorno UV_DEFAULT_INDEX para la instalación de paquetes Python","pythonIndexUrlPlaceholder":"p. ej., https://pypi.org/simple","npmRegistry":"URL del registro NPM","npmRegistryDescription":"Establece la variable de entorno npm_config_registry para la instalación de paquetes NPM","npmRegistryPlaceholder":"p. ej., https://registry.npmjs.org/","baseUrl":"URL base","baseUrlDescription":"URL base para las solicitudes MCP y los callbacks de OAuth","baseUrlPlaceholder":"p. ej., http://localhost:3000","installConfig":"Instalación","clearCache":"Borrar caché de paquetes","clearCacheDescription":"Borra las cachés de paquetes de npm y uv. Los servidores pueden necesitar volver a descargar paquetes en el próximo arranque.","clearCacheConfirm":"Esto borrará las cachés de paquetes de npm y uv. Los servidores pueden necesitar volver a descargar paquetes en el próximo arranque.","clearCacheSuccess":"Caché de paquetes borrada correctamente","clearCacheError":"Error al borrar la caché de paquetes","clearCacheSkipped":"no instalado","clearingCache":"Borrando...","systemConfigUpdated":"Configuración del sistema actualizada correctamente","noChanges":"No hay cambios que guardar","betterAuthTitle":"Better Auth","betterAuthEnvNote":"Los IDs de cliente y los secretos siguen procediendo de variables de entorno. Cambiar los ajustes de Better Auth puede requerir reiniciar la aplicación, y el origen de la URL base de instalación es de confianza automáticamente.","enableBetterAuth":"Habilitar Better Auth","enableBetterAuthDescription":"Habilita el inicio de sesión social y OIDC cuando las variables de entorno requeridas están configuradas.","disablePasswordLogin":"Deshabilitar inicio de sesión con contraseña","disablePasswordLoginDescription":"Permite el inicio de sesión solo a través de los proveedores SSO: el formulario de usuario/contraseña y POST /api/auth/login se desactivan. Solo tiene efecto mientras haya al menos un proveedor habilitado que ya lo estuviera al arrancar la aplicación. BETTER_AUTH_DISABLE_PASSWORD_LOGIN anula este ajuste, y establecerlo en false es la vía de recuperación si el proveedor de identidad no está disponible.","betterAuthBaseUrl":"URL base","betterAuthBaseUrlDescription":"URL base pública usada para construir las URI de redirección de Better Auth. Si está vacía, se usa la URL base de instalación; la variable de entorno BETTER_AUTH_URL tiene prioridad.","betterAuthBasePath":"Ruta base de autenticación","betterAuthBasePathDescription":"Ruta de API relativa usada por las rutas de Better Auth.","betterAuthTrustedOrigins":"Orígenes de confianza","betterAuthTrustedOriginsDescription":"Orígenes separados por comas permitidos para las solicitudes de Better Auth. El origen de la URL base de instalación se añade automáticamente.","betterAuthProviders":"Proveedores","betterAuthProvidersDescription":"Los conmutadores de proveedores controlan qué métodos de inicio de sesión configurados se muestran en la página de acceso.","betterAuthGoogleDescription":"Requiere GOOGLE_CLIENT_ID y GOOGLE_CLIENT_SECRET.","betterAuthGithubDescription":"Requiere GITHUB_CLIENT_ID y GITHUB_CLIENT_SECRET.","betterAuthOidcDescription":"Requiere credenciales de cliente OIDC más una URL de descubrimiento.","betterAuthOidcProviderId":"ID del proveedor OIDC","betterAuthOidcProviderIdDescription":"Identificador del proveedor usado al iniciar el flujo de inicio de sesión OIDC.","betterAuthOidcDiscoveryUrl":"URL de descubrimiento OIDC","betterAuthOidcDiscoveryUrlDescription":"URL well-known de configuración OpenID publicada por tu proveedor de identidad.","betterAuthOidcScopes":"Scopes OIDC","betterAuthOidcScopesDescription":"Scopes separados por comas solicitados durante el flujo de inicio de sesión OIDC.","betterAuthOidcPrompt":"Prompt OIDC","betterAuthOidcPromptDescription":"Valor de prompt opcional enviado al proveedor de identidad, como login o consent.","betterAuthOidcPkce":"Habilitar PKCE","betterAuthOidcPkceDescription":"Usa PKCE para el flujo de autorización OIDC.","enableSmartRouting":"Habilitar enrutamiento inteligente","enableSmartRoutingDescription":"Habilita la función de enrutamiento inteligente para buscar la herramienta más adecuada según la entrada (usando el nombre de grupo $smart)","dbUrl":"URL de PostgreSQL (requiere soporte pgvector)","dbUrlPlaceholder":"p. ej., postgresql://usuario:contraseña@localhost:5432/nombrebd","embeddingProvider":"Proveedor de embeddings","embeddingProviderPreset":"Preajuste de proveedor","embeddingProviderPresetDescription":"Elige un proveedor para rellenar su endpoint compatible con OpenAI y su modelo.","embeddingProviderPresetOpenai":"OpenAI","embeddingProviderPresetOpenrouter":"OpenRouter","embeddingProviderPresetSiliconflow":"SiliconFlow · nivel gratuito (1000 RPM)","embeddingProviderPresetGemini":"Google Gemini · nivel gratuito (100 RPM)","embeddingProviderPresetCustom":"Otro / compatible con OpenAI","llmProviderBaseUrl":"URL base compatible con OpenAI","llmProviderBaseUrlPlaceholder":"https://api.openai.com/v1","llmProviderApiKey":"Clave de API del proveedor LLM","llmProviderApiKeyPlaceholder":"Introduce la clave de API del proveedor LLM","smartRoutingEnvOverrideWarning":"Actualmente proporcionado por la variable de entorno {{envVar}}: el valor guardado aquí se ignora en tiempo de ejecución.","embeddingModel":"Nombre del modelo de embeddings","embeddingModelPlaceholder":"text-embedding-3-small","basePacingDelayMs":"Retraso base de ritmo (ms)","basePacingDelayMsDescription":"Retraso base entre solicitudes a la API de embeddings. Predeterminado: 0 — el sistema gestiona los límites de velocidad automáticamente: respeta las cabeceras Retry-After, recurre a un enfriamiento de 63 segundos y aumenta el retraso de ritmo tras cualquier respuesta 403/429. Establece un valor distinto de cero solo si tu proveedor impone un intervalo mínimo fijo entre solicitudes.","basePacingDelayMsPlaceholder":"Vacío = predeterminado 0 ms","basePacingDelayMsAuto":"Predeterminado ({{value}} ms): la limitación de velocidad se gestiona automáticamente.","basePacingDelayMsZero":"0 ms (predeterminado): la limitación de velocidad se gestiona automáticamente mediante regulación adaptativa y lógica de reintento.","basePacingDelayMsOverride":"Valor personalizado: anula el retraso de ritmo base predeterminado.","embeddingEncodingFormat":"Formato de codificación de embeddings","embeddingEncodingFormatDescription":"Formato de codificación para los vectores de embeddings. Auto detecta según el soporte del proveedor.","embeddingEncodingFormatAuto":"Auto (recomendado)","embeddingDimensions":"Dimensiones de embeddings","embeddingDimensionsDescription":"Tamaño de salida opcional para proveedores que lo soportan. Déjalo vacío para usar el valor predeterminado del modelo.","embeddingDimensionsPlaceholder":"Vacío = predeterminado del modelo","embeddingDimensionsApiPassthrough":"Reenviar dimensiones a la API (paso directo MRL)","embeddingDimensionsApiPassthroughDescription":"Solo los modelos conocidos por soportar Matryoshka (MRL) reciben el parámetro de dimensiones. Habilítalo para forzarlo en otros modelos compatibles con MRL. Los modelos no MRL (Qwen3-Embedding, BGE, vLLM/sglang) rechazan el parámetro directamente, así que déjalo desactivado para ellos.","azureOpenaiEndpoint":"Endpoint de Azure OpenAI","azureOpenaiEndpointPlaceholder":"https://YOUR_RESOURCE_NAME.openai.azure.com","azureOpenaiApiKey":"Clave de API de Azure OpenAI","azureOpenaiApiKeyPlaceholder":"Introduce la clave de API de Azure OpenAI","azureOpenaiApiVersion":"Versión de API de Azure OpenAI","azureOpenaiApiVersionPlaceholder":"2024-02-15-preview","azureOpenaiEmbeddingDeployment":"Despliegue de embeddings de Azure OpenAI","azureOpenaiEmbeddingDeploymentPlaceholder":"text-embedding-3-small","azureOpenaiEmbeddingModel":"Nombre del modelo de embeddings de Azure","azureOpenaiEmbeddingModelDescription":"El nombre real del modelo de OpenAI desplegado en Azure (p. ej., text-embedding-3-small). Se usa para un recuento de tokens preciso antes de enviar texto a la API.","azureOpenaiEmbeddingModelPlaceholder":"text-embedding-3-small","progressiveDisclosure":"Divulgación progresiva","progressiveDisclosureDescription":"Cuando está habilitada, search_tools solo devuelve nombres y descripciones de herramientas. Usa describe_tool para obtener el esquema de parámetros completo, reduciendo el uso de tokens.","embeddingMaxTokens":"Máximo de tokens de embeddings","embeddingMaxTokensDescription":"Máximo de tokens para el truncado de texto antes de generar embeddings. Déjalo vacío para usar automáticamente el predeterminado del modelo. Un valor personalizado siempre anula el predeterminado del modelo. Establecerlo manualmente es especialmente útil con proveedores LLM locales para evitar errores de truncado.","embeddingMaxTokensPlaceholder":"Vacío = automático según el modelo","embeddingMaxTokensAuto":"Auto: {{limit}} tokens (predeterminado del modelo para {{model}})","embeddingMaxTokensOverride":"Este valor anula el predeterminado del modelo.","embeddingPrefixes":"Prefijos de tarea de embeddings","embeddingPrefixesDescription":"Texto antepuesto antes del embedding, para modelos de recuperación asimétrica entrenados con prefijos de tarea (p. ej., EmbeddingGemma, E5, Nomic). Deja ambos vacíos para modelos que esperan texto sin procesar. Incluye el espacio final. Cambiar el prefijo de documento regenera los embeddings de todas las herramientas.","embeddingQueryPrefix":"Prefijo de consulta","embeddingDocumentPrefix":"Prefijo de documento","searchResults":"Resultados de búsqueda","searchResultsDescription":"Cómo search_tools filtra y devuelve coincidencias. Cada acierto lleva su puntuación de similitud. Deja ambos vacíos para los valores predeterminados.","similarityThreshold":"Umbral de similitud (0-1)","similarityThresholdPlaceholder":"Vacío = según longitud de la consulta (0.2 / 0.3 / 0.4)","fullSchemaTopN":"Esquemas completos para los N primeros resultados","fullSchemaTopNPlaceholder":"Vacío = todos los resultados; los inferiores usan describe_tool","toolDefinitionFields":"Campos de herramienta en los resultados","toolDefinitionFieldsDescription":"Campos opcionales que los resultados de search_tools y describe_tool llevan junto al nombre, la descripción y el inputSchema. Predeterminado: title y annotations. Los demás son sobre todo para clientes y pueden ser grandes (los iconos son imágenes base64).","invalidSearchSettings":"Valor no válido para {{fields}}. El umbral de similitud debe estar entre 0 y 1, y el top N debe ser un número entero igual o mayor que 0.","smartRoutingConfigUpdated":"Configuración de enrutamiento inteligente actualizada correctamente","smartRoutingRequiredFields":"La URL de la base de datos es obligatoria para habilitar el enrutamiento inteligente. Se requiere una clave de API de proveedor LLM para proveedores en la nube (los LLM locales normalmente no requieren clave de API; introduce cualquier valor para pasar la validación del formulario)","smartRoutingValidationError":"Rellena los campos obligatorios antes de habilitar el enrutamiento inteligente: {{fields}}","smartRoutingWorkflow":"Flujo de trabajo","smartRoutingWorkflowDescription":"Los prompts se vectorizan; las k herramientas más similares se obtienen de pgvector y se exponen al LLM ascendente.","toolResultCompressionTitle":"Compresión de resultados de herramientas","toolResultCompressionEnable":"Habilitar compresión","toolResultCompressionDescription":"Reduce las salidas de texto grandes de las herramientas antes de que lleguen a los clientes MCP. Los cambios se aplican en la siguiente llamada de herramienta.","toolResultCompressionStrategy":"Estrategia","toolResultCompressionStrategyDescription":"Auto detecta JSON, registros, salidas de búsqueda, diffs y texto plano.","toolResultCompressionMinTokens":"Mínimo de tokens","toolResultCompressionMinTokensDescription":"Solo comprime bloques de texto que alcancen o superen este tamaño.","toolResultCompressionMaxOutputTokens":"Presupuesto de tokens de salida","toolResultCompressionMaxOutputTokensDescription":"Máximo de tokens objetivo para cada bloque de texto comprimido.","mcpRouterConfig":"Mercado cloud","mcpRouterApiKey":"Clave de API de MCPRouter","mcpRouterApiKeyDescription":"Clave de API para acceder a los servicios del mercado cloud de MCPRouter","mcpRouterApiKeyPlaceholder":"Introduce la clave de API de MCPRouter","mcpRouterReferer":"Referer","mcpRouterRefererDescription":"Cabecera Referer para las solicitudes a la API de MCPRouter","mcpRouterRefererPlaceholder":"https://www.mcphub.app","mcpRouterTitle":"Título","mcpRouterTitleDescription":"Cabecera Title para las solicitudes a la API de MCPRouter","mcpRouterTitlePlaceholder":"MCPHub","mcpRouterBaseUrl":"URL base","mcpRouterBaseUrlDescription":"URL base para la API de MCPRouter","mcpRouterBaseUrlPlaceholder":"https://api.mcprouter.to/v1","systemSettings":"Ajustes del sistema","nameSeparatorLabel":"Separador de nombres","nameSeparatorDescription":"Carácter usado para separar el nombre del servidor y el nombre de la herramienta/prompt (predeterminado: -)","enableSessionRebuild":"Habilitar reconstrucción de sesiones de servidor","enableSessionRebuildDescription":"Cuando está habilitado, aplica el código mejorado de reconstrucción de sesiones de servidor para una mejor experiencia de gestión de sesiones","storeToolPayload":"Almacenar cargas de llamadas de herramientas","storeToolPayloadDescription":"Cuando está habilitado, la entrada y salida completa de cada llamada de herramienta se almacena en los registros de actividad. Las cargas de las herramientas se guardan literalmente sin redacción; desactívalo si los argumentos de las herramientas pueden contener datos sensibles que no deban persistirse.","storeToolPayloadUpdateFailed":"Error al actualizar el ajuste de almacenamiento de cargas de herramientas","restartRequired":"Configuración guardada. Se recomienda reiniciar la aplicación para asegurar que todos los servicios cargan correctamente los nuevos ajustes.","exportMcpSettings":"Exportar ajustes","mcpSettingsJson":"JSON de ajustes MCP","mcpSettingsJsonDescription":"Ver, copiar o descargar tu configuración actual de mcp_settings.json para copia de seguridad o migración a otras herramientas","copyToClipboard":"Copiar al portapapeles","downloadJson":"Descargar JSON","exportSuccess":"Ajustes exportados correctamente","exportError":"Error al obtener los ajustes","enableOauthServer":"Habilitar servidor OAuth","enableOauthServerDescription":"Permitir que MCPHub emita tokens OAuth para clientes externos","requireClientSecret":"Requerir secreto de cliente","requireClientSecretDescription":"Cuando está habilitado, los clientes confidenciales deben presentar un secreto de cliente (desactívalo para clientes solo PKCE)","requireState":"Requerir parámetro state","requireStateDescription":"Rechazar solicitudes de autorización que omitan el parámetro state de OAuth","accessTokenLifetime":"Vigencia del token de acceso (segundos)","accessTokenLifetimeDescription":"Cuánto tiempo permanecen válidos los tokens de acceso emitidos","accessTokenLifetimePlaceholder":"p. ej., 3600","refreshTokenLifetime":"Vigencia del token de actualización (segundos)","refreshTokenLifetimeDescription":"Cuánto tiempo permanecen válidos los tokens de actualización","refreshTokenLifetimePlaceholder":"p. ej., 1209600","authorizationCodeLifetime":"Vigencia del código de autorización (segundos)","authorizationCodeLifetimeDescription":"Cuánto tiempo permanecen válidos los códigos de autorización antes de poder canjearse","authorizationCodeLifetimePlaceholder":"p. ej., 300","allowedScopes":"Scopes permitidos","allowedScopesDescription":"Lista separada por comas de scopes que los usuarios pueden aprobar durante la autorización","allowedScopesPlaceholder":"p. ej., read, write","enableDynamicRegistration":"Habilitar registro dinámico de clientes","dynamicRegistrationDescription":"Permitir que clientes conformes con RFC 7591 se autorregistren usando el endpoint público","dynamicRegistrationAllowedGrantTypes":"Tipos de grant permitidos","dynamicRegistrationAllowedGrantTypesDescription":"Lista separada por comas de grants permitidos para clientes registrados dinámicamente","dynamicRegistrationAllowedGrantTypesPlaceholder":"p. ej., authorization_code, refresh_token","dynamicRegistrationAuth":"Requerir autenticación","dynamicRegistrationAuthDescription":"Proteger el endpoint de registro para que solo solicitudes autenticadas puedan registrar clientes","invalidNumberInput":"Introduce un número válido no negativo","dynamicRegistrationClientTtl":"TTL de limpieza de clientes inactivos (segundos)","dynamicRegistrationClientTtlDescription":"Elimina clientes registrados dinámicamente sin tokens activos y sin flujo de autorización en curso más antiguos que esta antigüedad. Establécelo en 0 para desactivar la limpieza.","dynamicRegistrationClientTtlPlaceholder":"p. ej., 2592000","smartRoutingIndexTitle":"Índice vectorial y diagnósticos","smartRoutingIndexRefresh":"Actualizar","smartRoutingIndexReindex":"Reindexar","smartRoutingIndexReindexing":"Reindexando…","smartRoutingIndexLoading":"Cargando…","smartRoutingIndexNoData":"Aún no hay datos de índice. Habilita el enrutamiento inteligente y haz clic en Reindexar para construir el almacén vectorial.","smartRoutingIndexStatsUnavailable":"Estadísticas no disponibles","smartRoutingIndexDatabase":"Base de datos","smartRoutingIndexConnected":"Conectada","smartRoutingIndexDisconnected":"Desconectada","smartRoutingIndexUnhealthy":"Con errores","smartRoutingIndexModel":"Modelo","smartRoutingIndexDimensions":"Dimensiones","smartRoutingIndexTotalRows":"Filas totales","smartRoutingIndexToolRows":"Filas de herramientas","smartRoutingIndexServerRows":"Filas de servidores","smartRoutingIndexClusterLabel":"Servidores indexados","smartRoutingIndexCoverage":"Cobertura","smartRoutingIndexLastSynced":"Última sincronización","smartRoutingIndexPerServer":"Herramientas por servidor","smartRoutingIndexMissingIndex":"{{count}} servidor(es) habilitado(s) sin índice","smartRoutingIndexSyncedRange":"Rango de sincronización: {{oldest}} → {{newest}}","smartRoutingIndexReindexDone":"Reindexación completada: {{synced}} servidor(es) sincronizado(s), {{failed}} fallido(s), {{skipped}} omitido(s), {{total}} herramientas en total","smartRoutingIndexReindexFailed":"Error en la reindexación: {{message}}","smartRoutingIndexReindexStarting":"Iniciando reindexación…","smartRoutingIndexReindexingServer":"Reindexando \\"{{server}}\\"","smartRoutingIndexReindexSummary":"Reindexación completada · {{synced}} sincronizado(s), {{failed}} fallido(s), {{skipped}} omitido(s), {{total}} herramientas","smartRoutingIndexReindexConfirmTitle":"¿Reconstruir el índice vectorial?","smartRoutingIndexReindexConfirmMessage":"Todos los embeddings existentes se borrarán y se regenerarán desde cero. Esto puede tardar y consume cuota de la API de embeddings.","smartRoutingIndexPersonalCredentials":"Servidores con credenciales personales","smartRoutingIndexSkippedReason":"Omitido","smartRoutingIndexIndexedAs":"indexado como {{principals}}","toolPolicies":{"missingReferences":"Algunos ID no se encontraron en los servidores, claves o grupos cargados. Una denegación sin coincidencias no protege; una autorización sin coincidencias puede bloquear el acceso. Verifica antes de guardar. Puedes guardar reglas para recursos futuros.","missingReference":"Regla {{policyId}}: no se encontró {{selector}} {{value}}.","title":"Políticas de acceso a herramientas","description":"Las reglas se aplican al descubrimiento y la ejecución, incluido el enrutamiento inteligente. Se activan al guardar.","semantics":"Los selectores vacíos coinciden con todos. Todos los selectores de una regla deben coincidir. Las reglas de permiso aplicables forman una lista de permitidos; las denegaciones prevalecen. Las políticas no amplían los permisos existentes.","empty":"Sin políticas. Se aplican los permisos existentes.","rule":"Regla {{number}}","id":"ID de regla (único, obligatorio)","effect":"Efecto","allow":"Permitir","deny":"Denegar","username":"Usuario","keyId":"ID de clave Bearer","groupId":"ID de grupo del endpoint","serverId":"ID del servidor","tool":"Nombre original de la herramienta","any":"Cualquiera","selectorsHint":"Elija una sugerencia o escriba un valor exacto. Los ID sobreviven a los cambios de nombre. El grupo corresponde al endpoint, no a la pertenencia del servidor. Los nombres distinguen mayúsculas, sin prefijo del gateway ni comodines.","add":"Añadir regla","save":"Guardar políticas","unsaved":"Cambios sin guardar. Las adiciones y eliminaciones se aplican al guardar.","invalid":"Cada regla necesita un ID único no vacío y un efecto válido. Los selectores opcionales no pueden contener solo espacios.","saveFailed":"No se pudieron guardar las políticas. Se conservan los cambios.","confirm":"¿Aplicar estas {{count}} políticas ahora? Puede cambiar las herramientas disponibles para los usuarios.","confirmClear":"¿Eliminar todas las políticas? Se aplicarán los permisos existentes.","deleteRule":"Eliminar regla {{number}}","retry":"Reintentar"}}'),_c={upload:"Subir",uploadTitle:"Subir paquete MCPB",dropFileHere:"Suelta tu archivo .mcpb aquí",orClickToSelect:"o haz clic para seleccionarlo desde tu ordenador",invalidFileType:"Selecciona un archivo .mcpb válido",noFileSelected:"Selecciona un archivo .mcpb para subir",uploading:"Subiendo...",uploadFailed:"Error al subir el archivo MCPB",installServer:"Instalar servidor MCP desde MCPB",extensionInfo:"Información de la extensión",name:"Nombre",version:"Versión",description:"Descripción",author:"Autor",tools:"Herramientas",serverName:"Nombre del servidor",serverNamePlaceholder:"Introduce un nombre para este servidor",install:"Instalar",installing:"Instalando...",installFailed:"Error al instalar el servidor desde MCPB",serverExistsTitle:"El servidor ya existe",serverExistsConfirm:"El servidor '{{serverName}}' ya existe. ¿Quieres sobrescribirlo con la nueva versión?",override:"Sobrescribir"},Vc={button:"Importar",title:"Importar servidores desde JSON",inputLabel:"JSON de configuración de servidores",inputHelp:"Pega tu JSON de configuración de servidores. Admite servidores de tipo STDIO, SSE y HTTP (streamable-http).",preview:"Vista previa",previewTitle:"Vista previa de servidores a importar",import:"Importar",importing:"Importando...",invalidFormat:"Formato JSON no válido. El JSON debe contener un objeto 'mcpServers'.",parseError:"Error al analizar el JSON. Comprueba el formato e inténtalo de nuevo.",addFailed:"Error al añadir el servidor",importFailed:"Error al importar los servidores",partialSuccess:"Se han importado {{count}} de {{total}} servidores correctamente. Algunos servidores han fallado:",validationErrors:"Algunos servidores no se han podido importar. Corrige lo siguiente e inténtalo de nuevo:"},$c={button:"Importar",title:"Importar grupos desde JSON",inputLabel:"JSON de configuración de grupos",inputHelp:"Pega tu JSON de configuración de grupos. Cada grupo puede contener una lista de servidores.",preview:"Vista previa",previewTitle:"Vista previa de grupos a importar",import:"Importar",importing:"Importando...",invalidFormat:"Formato JSON no válido. El JSON debe contener un array 'groups'.",missingName:"Cada grupo debe tener un campo 'name'.",parseError:"Error al analizar el JSON. Comprueba el formato e inténtalo de nuevo.",addFailed:"Error al añadir el grupo",importFailed:"Error al importar los grupos",partialSuccess:"Se han importado {{count}} de {{total}} grupos correctamente. Algunos grupos han fallado:"},Jc={add:"Añadir usuario",addNew:"Añadir nuevo usuario",edit:"Editar usuario",delete:"Eliminar usuario",create:"Crear usuario",update:"Actualizar usuario",username:"Nombre de usuario",email:"Correo electrónico",emailPlaceholder:"Introduce el correo electrónico (opcional)",password:"Contraseña",newPassword:"Nueva contraseña",confirmPassword:"Confirmar contraseña",changePassword:"Cambiar contraseña",adminRole:"Administrador",admin:"Admin",user:"Usuario",role:"Rol",actions:"Acciones",addFirst:"Añade tu primer usuario",permissions:"Permisos",adminPermissions:"Acceso completo al sistema",userPermissions:"Acceso limitado",currentUser:"Tú",noUsers:"No se han encontrado usuarios",adminRequired:"Se requiere acceso de administrador para gestionar usuarios",usernameRequired:"El nombre de usuario es obligatorio",passwordRequired:"La contraseña es obligatoria",passwordTooShort:"La contraseña debe tener al menos 6 caracteres",passwordMismatch:"Las contraseñas no coinciden",usernamePlaceholder:"Introduce el nombre de usuario",passwordPlaceholder:"Introduce la contraseña",newPasswordPlaceholder:"Déjalo vacío para mantener la contraseña actual",confirmPasswordPlaceholder:"Confirma la nueva contraseña",createError:"Error al crear el usuario",updateError:"Error al actualizar el usuario",deleteError:"Error al eliminar el usuario",statsError:"Error al obtener las estadísticas de usuarios",deleteConfirmation:"¿Seguro que quieres eliminar al usuario '{{username}}'? Esta acción no se puede deshacer.",confirmDelete:"Eliminar usuario",deleteWarning:"¿Seguro que quieres eliminar al usuario '{{username}}'? Esta acción no se puede deshacer."},Wc={errors:{readonly:"Solo lectura para el entorno de demostración",invalid_credentials:"Nombre de usuario o contraseña no válidos",password_login_disabled:"El inicio de sesión con contraseña está deshabilitado. Inicia sesión con SSO o usa una clave Bearer para acceso a la API.",serverNameRequired:"El nombre del servidor es obligatorio",serverConfigRequired:"La configuración del servidor es obligatoria",serverConfigInvalid:"La configuración del servidor debe incluir una URL, una URL o esquema de especificación OpenAPI, o un comando con argumentos",serverTypeInvalid:"El tipo de servidor debe ser uno de: stdio, sse, streamable-http, openapi",urlRequiredForType:"La URL es obligatoria para el tipo de servidor {{type}}",openapiSpecRequired:"La URL o el esquema de la especificación OpenAPI es obligatorio para el tipo de servidor openapi",headersInvalidFormat:"Las cabeceras deben ser un objeto",headersNotSupportedForStdio:"Las cabeceras no son compatibles con el tipo de servidor stdio",serverNotFound:"Servidor no encontrado",failedToRemoveServer:"Servidor no encontrado o error al eliminarlo",internalServerError:"Error interno del servidor",failedToGetServers:"Error al obtener la información de los servidores",failedToReloadServer:"Error al recargar el servidor",failedToGetServerSettings:"Error al obtener los ajustes del servidor",failedToGetServerConfig:"Error al obtener la configuración del servidor",failedToSaveSettings:"Error al guardar los ajustes",toolNameRequired:"El nombre del servidor y el nombre de la herramienta son obligatorios",descriptionMustBeString:"La descripción debe ser una cadena de texto",groupIdRequired:"El ID del grupo es obligatorio",groupNameRequired:"El nombre del grupo es obligatorio",groupNotFound:"Grupo no encontrado",groupIdAndServerNameRequired:"El ID del grupo y el nombre del servidor son obligatorios",groupOrServerNotFound:"Grupo o servidor no encontrado",toolsMustBeAllOrArray:'Las herramientas deben ser "all" o un array de cadenas',serverNameAndToolNameRequired:"El nombre del servidor y el nombre de la herramienta son obligatorios",usernameRequired:"El nombre de usuario es obligatorio",userNotFound:"Usuario no encontrado",failedToGetUsers:"Error al obtener la información de los usuarios",failedToGetUserInfo:"Error al obtener la información del usuario",failedToGetUserStats:"Error al obtener las estadísticas del usuario",marketServerNameRequired:"El nombre del servidor es obligatorio",marketServerNotFound:"Servidor del mercado no encontrado",failedToGetMarketServers:"Error al obtener la información de los servidores del mercado",failedToGetMarketServer:"Error al obtener la información del servidor del mercado",failedToGetMarketCategories:"Error al obtener las categorías del mercado",failedToGetMarketTags:"Error al obtener las etiquetas del mercado",failedToSearchMarketServers:"Error al buscar servidores del mercado",failedToFilterMarketServers:"Error al filtrar servidores del mercado",failedToProcessMcpbFile:"Error al procesar el archivo MCPB"},success:{serverCreated:"Servidor creado correctamente",serverUpdated:"Servidor actualizado correctamente",serverRemoved:"Servidor eliminado correctamente",serverToggled:"Estado del servidor cambiado correctamente",toolToggled:"Herramienta {{name}} {{action}} correctamente",toolDescriptionUpdated:"Descripción de la herramienta {{name}} actualizada correctamente",systemConfigUpdated:"Configuración del sistema actualizada correctamente",groupCreated:"Grupo creado correctamente",groupUpdated:"Grupo actualizado correctamente",groupDeleted:"Grupo eliminado correctamente",serverAddedToGroup:"Servidor añadido al grupo correctamente",serverRemovedFromGroup:"Servidor quitado del grupo correctamente",serverToolsUpdated:"Herramientas del servidor actualizadas correctamente"}},Yc={authorizationFailed:"Autorización fallida",authorizationFailedError:"Error",authorizationFailedDetails:"Detalles",invalidRequest:"Solicitud no válida",missingStateParameter:"Falta el parámetro state de OAuth obligatorio.",missingCodeParameter:"Falta el parámetro de código de autorización obligatorio.",serverNotFound:"Servidor no encontrado",serverNotFoundMessage:"No se ha podido encontrar el servidor asociado a esta solicitud de autorización.",sessionExpiredMessage:"La sesión de autorización puede haber caducado. Intenta autorizar de nuevo.",authorizationSuccessful:"Autorización correcta",server:"Servidor",status:"Estado",connected:"Conectado",successMessage:"El servidor se ha autorizado y conectado correctamente.",autoCloseMessage:"Esta ventana se cerrará automáticamente en 3 segundos...",closeNow:"Cerrar ahora",connectionError:"Error de conexión",connectionErrorMessage:"La autorización se ha realizado correctamente, pero ha fallado la conexión con el servidor.",reconnectMessage:"Intenta reconectar desde el panel.",configurationError:"Error de configuración",configurationErrorMessage:"El transporte del servidor no admite finishAuth() de OAuth. Asegúrate de que el servidor está configurado con transporte streamable-http.",internalError:"Error interno",internalErrorMessage:"Se ha producido un error inesperado al procesar el callback de OAuth.",closeWindow:"Cerrar ventana"},Xc={add:"Añadir prompt",addNew:"Añadir nuevo prompt",edit:"Editar prompt",delete:"Eliminar",noPrompts:"No hay prompts integrados configurados",addFirst:"Añade tu primer prompt",name:"Nombre",namePlaceholder:"p. ej., revision-codigo",title:"Título",titlePlaceholder:"p. ej., Prompt de revisión de código",description:"Descripción",descriptionPlaceholder:"Breve descripción del prompt",template:"Plantilla",templatePlaceholder:"Introduce el texto de la plantilla con marcadores {{parámetro}}...",templateHint:"Usa {{paramName}} para los parámetros de la plantilla",arguments:"Argumentos",addArgument:"Añadir argumento",argName:"Nombre",argDescription:"Descripción",argRequired:"Obligatorio",enabled:"Habilitado",active:"Activo",inactive:"Inactivo",nameRequired:"El nombre es obligatorio",templateRequired:"La plantilla es obligatoria",fetchError:"Error al cargar los prompts integrados",createError:"Error al crear el prompt",updateError:"Error al actualizar el prompt",deleteError:"Error al eliminar el prompt",saveError:"Error al guardar el prompt",confirmDelete:"Eliminar prompt",deleteWarning:'¿Seguro que quieres eliminar el prompt "{{name}}"? Esta acción no se puede deshacer.'},Qc={add:"Añadir recurso",addNew:"Añadir nuevo recurso",edit:"Editar recurso",delete:"Eliminar",noResources:"No hay recursos integrados configurados",addFirst:"Añade tu primer recurso",uri:"URI",uriPlaceholder:"p. ej., resource://docs/guia",name:"Nombre",namePlaceholder:"p. ej., Guía de usuario",description:"Descripción",descriptionPlaceholder:"Breve descripción del recurso",mimeType:"Tipo MIME",content:"Contenido",contentPlaceholder:"Introduce el contenido del recurso...",enabled:"Habilitado",active:"Activo",inactive:"Inactivo",descriptionUpdateSuccess:"Descripción del recurso actualizada correctamente",descriptionUpdateFailed:"Error al actualizar la descripción del recurso",restoreDefault:"Restaurar predeterminada",restoreDefaultSuccess:"Descripción del recurso restaurada a la predeterminada",restoreDefaultFailed:"Error al restaurar la descripción predeterminada del recurso",uriRequired:"La URI es obligatoria",contentRequired:"El contenido es obligatorio",fetchError:"Error al cargar los recursos integrados",createError:"Error al crear el recurso",updateError:"Error al actualizar el recurso",deleteError:"Error al eliminar el recurso",saveError:"Error al guardar el recurso",confirmDelete:"Eliminar recurso",deleteWarning:'¿Seguro que quieres eliminar el recurso "{{name}}"? Esta acción no se puede deshacer.'},Zc={title:"Actividad",totalCalls:"Llamadas totales",successCount:"Correctas",errorCount:"Fallidas",avgDuration:"Duración media",timestamp:"Marca de tiempo",server:"Servidor",tool:"Herramienta",duration:"Duración",status:"Estado",group:"Grupo",user:"Usuario",key:"Clave de API",sourceIp:"IP de origen",input:"Entrada",output:"Salida",details:"Detalles de la actividad",errorMessage:"Mensaje de error",searchServer:"Servidor...",searchTool:"Herramienta...",searchStatus:"Estado...",searchGroup:"Grupo...",searchUsername:"Usuario...",searchKeyName:"Clave de API...",keyName:"Nombre de la clave de API",allStatus:"Todos los estados",statusSuccess:"Éxito",statusError:"Error",noData:"No hay datos de actividad disponibles",fetchError:"Error al cargar los datos de actividad",cleanup:"Limpieza",confirmCleanup:"¿Seguro que quieres eliminar las actividades con más de 30 días?",cleanupSuccess:"Se han eliminado {{count}} actividades antiguas",cleanupError:"Error al limpiar las actividades antiguas",notAvailable:"El seguimiento de actividad solo está disponible en modo base de datos"},ed={exportButton:"Exportar plantilla",importButton:"Importar plantilla",exportTitle:"Exportar plantilla de configuración",importTitle:"Importar plantilla de configuración",name:"Nombre de la plantilla",nameRequired:"El nombre de la plantilla es obligatorio",namePlaceholder:"p. ej., Herramientas de desarrollo frontend",description:"Descripción",descriptionPlaceholder:"p. ej., Servidores MCP estándar para desarrollo frontend",selectGroups:"Seleccionar grupos",selectGroupsHelp:"Déjalo vacío para exportar todos los grupos",selectAll:"Seleccionar todo",deselectAll:"Deseleccionar todo",includeDisabled:"Incluir servidores deshabilitados",exportNote:"Los secretos (claves de API, tokens, contraseñas) se reemplazarán con referencias ${PLACEHOLDER}. Los destinatarios deben proporcionar sus propias credenciales.",export:"Exportar",exporting:"Exportando...",exportFailed:"Error al exportar la plantilla",import:"Importar",importing:"Importando...",importFailed:"Error al importar la plantilla",invalidFormat:"Formato de plantilla no válido. Debe contener los campos version, name, servers y groups.",parseError:"Error al analizar el JSON. Comprueba el formato e inténtalo de nuevo.",uploadFile:"Subir archivo de plantilla",or:"o",pasteJson:"Pegar JSON de plantilla",pastePlaceholder:"Pega aquí el contenido de tu .mcphub-template.json...",version:"Versión",createdAt:"Creada",servers:"Servidores",groups:"Grupos",serversInGroup:"servidor(es)",envVarsNeeded:"Variables de entorno requeridas: establécelas antes de usar los servidores importados:",importResult:"Servidores: {{serversCreated}} creados, {{serversSkipped}} omitidos. Grupos: {{groupsCreated}} creados, {{groupsSkipped}} omitidos."},rd={exposed:"Expuestos",gross:"Bruto",estimate:"Tokens estimados (cl100k) — aproximado",direct:"Directo",smartRouting:"Enrutamiento inteligente",smartRoutingPd:"Enrutamiento inteligente + divulgación progresiva",smartRoutingPdHint:"Añade la metaherramienta describe_tool: mayor coste inicial, pero respuestas por búsqueda más pequeñas",saved:"{{percent}}% menos",notConnected:"No conectado",connectedOf:"{{connected}} de {{total}} servidores conectados",totalFootprint:"Huella de contexto"},td={title:"Credenciales",missing:"Se requieren credenciales personales para '{{serverName}}'. Vincula todos los campos obligatorios en Panel → Credenciales.",description:"Vincula tus propias credenciales a servidores compartidos. Cada servidor usa las credenciales del usuario que realiza la solicitud.",slots:"Campos de credenciales por usuario",slotsHint:"Declara solo nombres de campos. Cada campo requiere una vinculación personal; las credenciales de la organización nunca se usan como alternativa.",target:"Destino de la credencial",urlHint:"Para campos URL, use {{placeholder}} como etiqueta de host o segmento de ruta completo e indique los valores permitidos.",allowed:"Valores permitidos (uno por línea)",argsHint:"Para campos de argumento, usa {{placeholder}} en un argumento, sustituyendo API_KEY por el nombre del campo. Los valores se insertan literalmente sin shell.",fieldName:"Nombre del campo",label:"Etiqueta (opcional)",addSlot:"Añadir campo",removeSlot:"Quitar campo",personalBadge:"Credenciales personales",manage:"Gestionar",configured:"Configurado",required:"Vinculación obligatoria",writeOnly:"Los valores guardados no se pueden mostrar. Para reemplazar una vinculación, introduce nuevos valores para cada campo.",replaceValue:"Introduce el valor de reemplazo",enterValue:"Introduce la credencial",save:"Guardar vinculación",delete:"Eliminar vinculación",saved:"Vinculación guardada",deleted:"Vinculación eliminada",failed:"No se pueden gestionar las credenciales",showAll:"Mostrar todos los servidores",loading:"Cargando…",empty:"Ningún servidor compartido requiere credenciales personales.",targetUser:"Gestionar credenciales de",myCredentials:"Mis credenciales",updatedAt:"Última actualización"},ad={app:kc,about:Sc,profile:Cc,sponsor:Pc,wechat:Ac,discord:Rc,theme:Tc,auth:xc,server:wc,status:Dc,errors:Ec,common:Ic,clientConfig:Nc,pagination:Oc,nav:Mc,pages:Lc,logs:zc,groups:Uc,market:qc,oauthServer:Bc,cloud:Fc,registry:Kc,tool:jc,prompt:Gc,settings:Hc,mcpb:_c,jsonImport:Vc,groupImport:$c,users:Jc,api:Wc,oauthCallback:Yc,builtinPrompts:Xc,builtinResources:Qc,activity:Zc,template:ed,cost:rd,credentials:td};da.use(ua).use(ma).init({resources:{en:{translation:Do},vi:{translation:ps},zh:{translation:Xs},fr:{translation:Ll},tr:{translation:fc},es:{translation:ad}},fallbackLng:"en",debug:!1,defaultNS:"translation",interpolation:{escapeValue:!1},detection:{order:["localStorage","cookie","navigator","htmlTag"],caches:["localStorage","cookie"]}});const nd=()=>{qa()};nd();async function id(){try{console.log("Loading runtime configuration...");const e=await La();console.log("Runtime configuration loaded:",e),window.__MCPHUB_CONFIG__=e,Er.createRoot(document.getElementById("root")).render(a.jsx(ze.StrictMode,{children:a.jsx(_r,{children:a.jsx(Xr,{})})}))}catch(e){console.error("Failed to initialize app:",e),console.log("Starting app with default configuration..."),window.__MCPHUB_CONFIG__={basePath:"",version:"dev",name:"mcphub"},Er.createRoot(document.getElementById("root")).render(a.jsx(ze.StrictMode,{children:a.jsx(_r,{children:a.jsx(Xr,{})})}))}}id();export{kd as A,Sd as B,yd as C,ti as G,ri as L,bd as P,Zn as T,ee as _,Ce as a,ot as b,Fe as c,Fa as d,mi as e,dd as f,we as g,Y as h,Se as i,K as j,At as k,oe as l,at as m,tt as n,_e as o,Wn as p,md as q,pd as r,ud as s,Qe as t,Mt as u,Yn as v,hd as w,gd as x,vd as y,fd as z};
3
- //# sourceMappingURL=index-CkSmxNPW.js.map