@openhands/agent-canvas 1.0.0-beta.4 → 1.0.0-beta.6

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 (97) hide show
  1. package/README.md +2 -2
  2. package/build/assets/{automations-list-rMki-8au.js → automations-list-6FDbI5dc.js} +1 -1
  3. package/build/assets/{home-XxBpNOVq.js → home-e-egNUXZ.js} +1 -1
  4. package/build/assets/install-server-modal-DHlbgqVH.js +1 -0
  5. package/build/assets/{manifest-a1d22045.js → manifest-3bf30d69.js} +1 -1
  6. package/build/assets/{mcp-D2onbwVk.js → mcp-ByeBfdfU.js} +1 -1
  7. package/build/assets/{recommended-automations-launcher-BQChv2rc.js → recommended-automations-launcher-CgV8FyPK.js} +1 -1
  8. package/build/assets/{root-35yk2E_M.js → root-dNntxffj.js} +1 -1
  9. package/build/assets/vendor~home~mcp~automations-list-Cs-TO3fK.js +1 -0
  10. package/build/index.html +3 -3
  11. package/dist/components/features/mcp-page/install-server-modal.cjs +1 -1
  12. package/dist/components/features/mcp-page/install-server-modal.cjs.map +1 -1
  13. package/dist/components/features/mcp-page/install-server-modal.js +92 -81
  14. package/dist/components/features/mcp-page/install-server-modal.js.map +1 -1
  15. package/dist/node_modules/@openhands/extensions/integrations/catalog/airtable.cjs +1 -1
  16. package/dist/node_modules/@openhands/extensions/integrations/catalog/airtable.cjs.map +1 -1
  17. package/dist/node_modules/@openhands/extensions/integrations/catalog/airtable.js +3 -1
  18. package/dist/node_modules/@openhands/extensions/integrations/catalog/airtable.js.map +1 -1
  19. package/dist/node_modules/@openhands/extensions/integrations/catalog/apify.cjs +1 -1
  20. package/dist/node_modules/@openhands/extensions/integrations/catalog/apify.cjs.map +1 -1
  21. package/dist/node_modules/@openhands/extensions/integrations/catalog/apify.js +3 -1
  22. package/dist/node_modules/@openhands/extensions/integrations/catalog/apify.js.map +1 -1
  23. package/dist/node_modules/@openhands/extensions/integrations/catalog/brave-search.cjs +1 -1
  24. package/dist/node_modules/@openhands/extensions/integrations/catalog/brave-search.cjs.map +1 -1
  25. package/dist/node_modules/@openhands/extensions/integrations/catalog/brave-search.js +3 -1
  26. package/dist/node_modules/@openhands/extensions/integrations/catalog/brave-search.js.map +1 -1
  27. package/dist/node_modules/@openhands/extensions/integrations/catalog/clickhouse.cjs +1 -1
  28. package/dist/node_modules/@openhands/extensions/integrations/catalog/clickhouse.cjs.map +1 -1
  29. package/dist/node_modules/@openhands/extensions/integrations/catalog/clickhouse.js +3 -1
  30. package/dist/node_modules/@openhands/extensions/integrations/catalog/clickhouse.js.map +1 -1
  31. package/dist/node_modules/@openhands/extensions/integrations/catalog/elevenlabs.cjs +1 -1
  32. package/dist/node_modules/@openhands/extensions/integrations/catalog/elevenlabs.cjs.map +1 -1
  33. package/dist/node_modules/@openhands/extensions/integrations/catalog/elevenlabs.js +3 -1
  34. package/dist/node_modules/@openhands/extensions/integrations/catalog/elevenlabs.js.map +1 -1
  35. package/dist/node_modules/@openhands/extensions/integrations/catalog/exa.cjs +1 -1
  36. package/dist/node_modules/@openhands/extensions/integrations/catalog/exa.cjs.map +1 -1
  37. package/dist/node_modules/@openhands/extensions/integrations/catalog/exa.js +3 -1
  38. package/dist/node_modules/@openhands/extensions/integrations/catalog/exa.js.map +1 -1
  39. package/dist/node_modules/@openhands/extensions/integrations/catalog/figma.cjs +1 -1
  40. package/dist/node_modules/@openhands/extensions/integrations/catalog/figma.cjs.map +1 -1
  41. package/dist/node_modules/@openhands/extensions/integrations/catalog/figma.js +3 -1
  42. package/dist/node_modules/@openhands/extensions/integrations/catalog/figma.js.map +1 -1
  43. package/dist/node_modules/@openhands/extensions/integrations/catalog/firecrawl.cjs +1 -1
  44. package/dist/node_modules/@openhands/extensions/integrations/catalog/firecrawl.cjs.map +1 -1
  45. package/dist/node_modules/@openhands/extensions/integrations/catalog/firecrawl.js +3 -1
  46. package/dist/node_modules/@openhands/extensions/integrations/catalog/firecrawl.js.map +1 -1
  47. package/dist/node_modules/@openhands/extensions/integrations/catalog/github.cjs +1 -1
  48. package/dist/node_modules/@openhands/extensions/integrations/catalog/github.cjs.map +1 -1
  49. package/dist/node_modules/@openhands/extensions/integrations/catalog/github.js +3 -1
  50. package/dist/node_modules/@openhands/extensions/integrations/catalog/github.js.map +1 -1
  51. package/dist/node_modules/@openhands/extensions/integrations/catalog/kagi.cjs +1 -1
  52. package/dist/node_modules/@openhands/extensions/integrations/catalog/kagi.cjs.map +1 -1
  53. package/dist/node_modules/@openhands/extensions/integrations/catalog/kagi.js +3 -1
  54. package/dist/node_modules/@openhands/extensions/integrations/catalog/kagi.js.map +1 -1
  55. package/dist/node_modules/@openhands/extensions/integrations/catalog/mongodb.cjs +1 -1
  56. package/dist/node_modules/@openhands/extensions/integrations/catalog/mongodb.cjs.map +1 -1
  57. package/dist/node_modules/@openhands/extensions/integrations/catalog/mongodb.js +3 -1
  58. package/dist/node_modules/@openhands/extensions/integrations/catalog/mongodb.js.map +1 -1
  59. package/dist/node_modules/@openhands/extensions/integrations/catalog/neon.cjs +1 -1
  60. package/dist/node_modules/@openhands/extensions/integrations/catalog/neon.cjs.map +1 -1
  61. package/dist/node_modules/@openhands/extensions/integrations/catalog/neon.js +3 -1
  62. package/dist/node_modules/@openhands/extensions/integrations/catalog/neon.js.map +1 -1
  63. package/dist/node_modules/@openhands/extensions/integrations/catalog/notion.cjs +1 -1
  64. package/dist/node_modules/@openhands/extensions/integrations/catalog/notion.cjs.map +1 -1
  65. package/dist/node_modules/@openhands/extensions/integrations/catalog/notion.js +3 -1
  66. package/dist/node_modules/@openhands/extensions/integrations/catalog/notion.js.map +1 -1
  67. package/dist/node_modules/@openhands/extensions/integrations/catalog/obsidian.cjs +1 -1
  68. package/dist/node_modules/@openhands/extensions/integrations/catalog/obsidian.cjs.map +1 -1
  69. package/dist/node_modules/@openhands/extensions/integrations/catalog/obsidian.js +2 -1
  70. package/dist/node_modules/@openhands/extensions/integrations/catalog/obsidian.js.map +1 -1
  71. package/dist/node_modules/@openhands/extensions/integrations/catalog/redis.cjs +1 -1
  72. package/dist/node_modules/@openhands/extensions/integrations/catalog/redis.cjs.map +1 -1
  73. package/dist/node_modules/@openhands/extensions/integrations/catalog/redis.js +2 -1
  74. package/dist/node_modules/@openhands/extensions/integrations/catalog/redis.js.map +1 -1
  75. package/dist/node_modules/@openhands/extensions/integrations/catalog/resend.cjs +1 -1
  76. package/dist/node_modules/@openhands/extensions/integrations/catalog/resend.cjs.map +1 -1
  77. package/dist/node_modules/@openhands/extensions/integrations/catalog/resend.js +3 -1
  78. package/dist/node_modules/@openhands/extensions/integrations/catalog/resend.js.map +1 -1
  79. package/dist/node_modules/@openhands/extensions/integrations/catalog/slack.cjs +1 -1
  80. package/dist/node_modules/@openhands/extensions/integrations/catalog/slack.cjs.map +1 -1
  81. package/dist/node_modules/@openhands/extensions/integrations/catalog/slack.js +8 -7
  82. package/dist/node_modules/@openhands/extensions/integrations/catalog/slack.js.map +1 -1
  83. package/dist/node_modules/@openhands/extensions/integrations/catalog/supabase.cjs +1 -1
  84. package/dist/node_modules/@openhands/extensions/integrations/catalog/supabase.cjs.map +1 -1
  85. package/dist/node_modules/@openhands/extensions/integrations/catalog/supabase.js +2 -1
  86. package/dist/node_modules/@openhands/extensions/integrations/catalog/supabase.js.map +1 -1
  87. package/dist/node_modules/@openhands/extensions/integrations/catalog/tavily.cjs +1 -1
  88. package/dist/node_modules/@openhands/extensions/integrations/catalog/tavily.cjs.map +1 -1
  89. package/dist/node_modules/@openhands/extensions/integrations/catalog/tavily.js +4 -2
  90. package/dist/node_modules/@openhands/extensions/integrations/catalog/tavily.js.map +1 -1
  91. package/dist/package.cjs +1 -1
  92. package/dist/package.cjs.map +1 -1
  93. package/dist/package.js +2 -2
  94. package/dist/package.js.map +1 -1
  95. package/package.json +2 -2
  96. package/build/assets/install-server-modal-f31_CLrW.js +0 -1
  97. package/build/assets/vendor~home~mcp~automations-list-Ccy2I0KU.js +0 -1
@@ -1,4 +1,4 @@
1
- import{a as e}from"./rolldown-runtime-BFRubm34.js";import{t}from"./react-CM_dJw1Z.js";import{L as n}from"./vendor~entry.client~root~root-layout~index-redirect~home~conversation-panel~conversation~la~cnj3raoq-DTEXlLSB.js";import{t as r}from"./useMutation-DqrumCWD.js";import{o as i,t as a}from"./declaration-BNMqORFE.js";import{n as o}from"./QueryClientProvider-CkGuhXg-.js";import{t as s}from"./useTranslation-DCOdSSMl.js";import{t as c}from"./retrieve-axios-error-message-BY-yIkIq.js";import{t as l}from"./createLucideIcon-Ddu8jDOQ.js";import{r as u}from"./vendor~home~mcp~automations-list-Ccy2I0KU.js";import{n as d,r as f}from"./custom-toast-handlers-C-SZFmto.js";import{a as p,c as m,i as h,l as g,n as _,r as v,s as y}from"./circle-plus-check-toggle-P7ZZToV4.js";import{t as b}from"./trash-2-CbVljPko.js";import{t as x}from"./x-JOBEVLW0.js";import{t as S}from"./utils-i18rdUj2.js";import{n as C}from"./active-backend-context-cCM1vYYZ.js";import{a as w}from"./query-keys-tAsQcc_9.js";import{t as T}from"./modal-backdrop-BAbgYsqB.js";import{a as E,t as D}from"./brand-button-Br7f0kZJ.js";import{t as O}from"./modal-close-button-t1Gh3qmL.js";import{n as k,t as A}from"./settings-input-Bn7F5C75.js";import{t as j}from"./confirmation-modal-Dau3w_sa.js";import{t as M}from"./settings-service.api-CZ3uWx4v.js";import{a as N,i as P,r as F}from"./use-settings-DQIZmIov.js";import{t as ee}from"./settings-dropdown-input-BJYvGdg-.js";import{a as I,c as L,d as R,f as te,i as z,m as ne,n as re,p as B,r as V,s as H,t as U,u as W}from"./install-server-modal-f31_CLrW.js";import{n as G}from"./extensions-navigation-BYR8Giqq.js";import{t as K}from"./enum-filter-dropdown-CEgCdu4A.js";import{n as q}from"./settings-like-page-layout-classes-I0BDBEoq.js";import{t as J}from"./acp-route-guard-B2yoBZ_4.js";var Y=l(`puzzle`,[[`path`,{d:`M15.39 4.39a1 1 0 0 0 1.68-.474 2.5 2.5 0 1 1 3.014 3.015 1 1 0 0 0-.474 1.68l1.683 1.682a2.414 2.414 0 0 1 0 3.414L19.61 15.39a1 1 0 0 1-1.68-.474 2.5 2.5 0 1 0-3.014 3.015 1 1 0 0 1 .474 1.68l-1.683 1.682a2.414 2.414 0 0 1-3.414 0L8.61 19.61a1 1 0 0 0-1.68.474 2.5 2.5 0 1 1-3.014-3.015 1 1 0 0 0 .474-1.68l-1.683-1.682a2.414 2.414 0 0 1 0-3.414L4.39 8.61a1 1 0 0 1 1.68.474 2.5 2.5 0 1 0 3.014-3.015 1 1 0 0 1-.474-1.68l1.683-1.682a2.414 2.414 0 0 1 3.414 0z`,key:`w46dr5`}]]),X=e(t(),1);function Z(){let e=o(),{data:t}=F();return r({mutationFn:async e=>{let n=P(t?.agent_settings?.mcp_config),r={sse_servers:[...n.sse_servers],stdio_servers:[...n.stdio_servers],shttp_servers:[...n.shttp_servers]},i=e=>{if(typeof e==`string`)return e;if(e&&typeof e==`object`&&`url`in e){let t=e.url;return typeof t==`string`?t:void 0}};if(e.type===`sse`){if(!e.url)return;let t=r.sse_servers.findIndex(t=>i(t)===e.url);t>=0&&r.sse_servers.splice(t,1)}else if(e.type===`shttp`){if(!e.url)return;let t=r.shttp_servers.findIndex(t=>i(t)===e.url);t>=0&&r.shttp_servers.splice(t,1)}else if(e.type===`stdio`){if(!e.name||!e.command)return;let t=r.stdio_servers.findIndex(t=>t.name===e.name&&t.command===e.command&&JSON.stringify(t.args??[])===JSON.stringify(e.args??[]));t>=0&&r.stdio_servers.splice(t,1)}else return;await M.saveSettings({agent_settings_diff:{mcp_config:N(r)}})},onSuccess:()=>{e.invalidateQueries({queryKey:w.personal()})}})}var Q=i();function ie(e){switch(e){case`sse`:return`SSE`;case`shttp`:return`HTTP`;case`stdio`:return`STDIO`;default:return e}}function ae(e){return e.type===`stdio`?e.name??e.command??``:e.url??``}function oe(e){if(e.type===`stdio`){let t=e.args&&e.args.length>0?` ${e.args.join(` `)}`:``;return`${e.command??``}${t}`.trim()}return e.url??``}function se({server:e,onEdit:t,onDelete:n}){let{t:r}=s(`openhands`),i=I(e,W(u)),o=i?.name??ae(e),c=oe(e),l=ie(e.type);return(0,Q.jsx)(`div`,{"data-testid":`mcp-server-item`,"data-server-id":e.id,role:`button`,tabIndex:0,onClick:t,onKeyDown:e=>{(e.key===`Enter`||e.key===` `)&&(e.preventDefault(),t())},"aria-label":r(a.MCP$EDIT_SERVER_ARIA,{name:o}),className:S(`flex min-h-[132px] flex-col overflow-hidden p-4 text-left`,y,p),children:(0,Q.jsxs)(`div`,{className:`flex items-start gap-3`,children:[(0,Q.jsx)(z,{entry:i,fallback:(0,Q.jsx)(Y,{strokeWidth:2.25})}),(0,Q.jsxs)(`div`,{className:`flex min-w-0 flex-1 flex-col gap-3`,children:[(0,Q.jsxs)(`header`,{className:`flex items-start justify-between gap-3`,children:[(0,Q.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,Q.jsx)(`h3`,{className:`truncate text-sm font-semibold`,title:o,children:o}),(0,Q.jsx)(`p`,{className:`mt-0.5 text-xs text-tertiary-alt`,children:l})]}),(0,Q.jsx)(_,{testId:`mcp-installed-toggle-${e.id}`,isSelected:!0,onToggle:e=>{e||n()},enableLabelKey:a.MCP$TOGGLE_ADD_SERVER,disableLabelKey:a.MCP$TOGGLE_REMOVE_SERVER})]}),i?.description?(0,Q.jsx)(`p`,{"data-testid":`mcp-server-description-${e.id}`,className:`line-clamp-2 break-words text-xs leading-relaxed text-tertiary-light`,children:i.description}):null,c?(0,Q.jsx)(`p`,{"data-testid":`mcp-server-detail-${e.id}`,className:`truncate text-xs text-tertiary-alt`,title:c,children:c}):null]})]})})}function ce({servers:e,hasAnyInstalled:t,query:n=``,onEdit:r,onDelete:i}){let{t:o}=s(`openhands`);return e.length===0?t&&n.trim().length>0?(0,Q.jsx)(`div`,{"data-testid":`mcp-installed-empty-search`,className:`rounded-xl border border-[var(--oh-border)] p-6 text-center`,children:(0,Q.jsx)(`p`,{className:`text-xs text-tertiary-light`,children:o(a.MCP$SEARCH_EMPTY)})}):(0,Q.jsxs)(`div`,{"data-testid":`mcp-installed-empty`,className:m,children:[(0,Q.jsx)(`p`,{className:`text-sm text-white`,children:o(a.MCP$INSTALLED_EMPTY_TITLE)}),(0,Q.jsx)(`p`,{className:`text-xs text-tertiary-light mt-1`,children:o(a.MCP$INSTALLED_EMPTY_HINT)})]}):(0,Q.jsx)(`div`,{className:h,children:(0,Q.jsx)(`div`,{"data-testid":`mcp-installed-list`,className:v,children:e.map(e=>(0,Q.jsx)(se,{server:e,onEdit:()=>r(e),onDelete:()=>i(e.id)},e.id))})})}function le({entry:e,onClick:t,onAdd:n}){let r=H(e),i=(()=>{switch(r?.kind){case`stdio`:return`STDIO`;case`shttp`:return`HTTP`;case`sse`:return`SSE`;default:return``}})();return(0,Q.jsx)(`button`,{type:`button`,onClick:t,"data-testid":`mcp-marketplace-card-${e.id}`,className:S(`flex min-h-[132px] flex-col overflow-hidden p-4 text-left`,y,p),children:(0,Q.jsxs)(`div`,{className:`flex items-start gap-3`,children:[(0,Q.jsx)(z,{entry:e}),(0,Q.jsxs)(`div`,{className:`flex min-w-0 flex-1 flex-col gap-3`,children:[(0,Q.jsxs)(`header`,{className:`flex items-start justify-between gap-3`,children:[(0,Q.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,Q.jsx)(`h3`,{className:`truncate text-sm font-semibold`,children:e.name}),(0,Q.jsx)(`p`,{className:`mt-0.5 text-xs text-tertiary-alt`,children:i})]}),(0,Q.jsx)(_,{testId:`mcp-marketplace-toggle-${e.id}`,isSelected:!1,onToggle:e=>{e&&n()},enableLabelKey:a.MCP$TOGGLE_ADD_SERVER,disableLabelKey:a.MCP$TOGGLE_ADD_SERVER})]}),(0,Q.jsx)(`p`,{className:`line-clamp-3 text-xs leading-relaxed text-tertiary-light`,children:e.description})]})]})})}function ue({backendKind:e,onSelect:t,onAdd:n,query:r=``}){let{t:i}=s(`openhands`),o=L(W(u)).filter(t=>te(t,e)&&B(t,r));return(0,Q.jsxs)(`section`,{"data-testid":`mcp-marketplace-section`,className:`flex flex-col gap-3`,children:[(0,Q.jsx)(`h2`,{className:`text-base font-medium text-foreground`,children:i(a.MCP$LIBRARY_TITLE)}),o.length===0?(0,Q.jsx)(`div`,{"data-testid":`mcp-marketplace-empty`,className:`rounded-xl border border-dashed border-[var(--oh-border)] p-6 text-center`,children:(0,Q.jsx)(`p`,{className:`text-xs text-tertiary-light`,children:i(a.MCP$SEARCH_EMPTY)})}):(0,Q.jsx)(`div`,{className:h,children:(0,Q.jsx)(`div`,{"data-testid":`mcp-marketplace-grid`,className:v,children:o.map(e=>(0,Q.jsx)(le,{entry:e,onClick:()=>t(e),onAdd:()=>n(e)},e.id))})})]})}function de({mode:e,server:t,existingServers:n,onSubmit:r,onCancel:i,onDelete:o,isActionDisabled:c=!1,onTest:l,isTestPending:u=!1,testMessage:d=null}){let{t:f}=s(`openhands`),[p,m]=X.useState(t?.type||`sse`),[h,g]=X.useState(null),_=X.useRef(null),v=[{key:`sse`,label:f(a.SETTINGS$MCP_SERVER_TYPE_SSE)},{key:`stdio`,label:f(a.SETTINGS$MCP_SERVER_TYPE_STDIO)},{key:`shttp`,label:f(a.SETTINGS$MCP_SERVER_TYPE_SHTTP)}],y=e=>{if(!e)return f(a.SETTINGS$MCP_ERROR_URL_REQUIRED);try{let t=new URL(e);if(![`http:`,`https:`].includes(t.protocol))return f(a.SETTINGS$MCP_ERROR_URL_INVALID_PROTOCOL)}catch{return f(a.SETTINGS$MCP_ERROR_URL_INVALID)}return null},x=e=>e?/^[a-zA-Z0-9_-]+$/.test(e)?null:f(a.SETTINGS$MCP_ERROR_NAME_INVALID):f(a.SETTINGS$MCP_ERROR_NAME_REQUIRED),C=r=>!n||!(e===`add`||e===`edit`&&t?.name!==r)?null:n.filter(e=>e.type===`stdio`).map(e=>e.name).filter(Boolean).includes(r)?f(a.SETTINGS$MCP_ERROR_NAME_DUPLICATE):null,w=e=>e?e.includes(` `)?f(a.SETTINGS$MCP_ERROR_COMMAND_NO_SPACES):null:f(a.SETTINGS$MCP_ERROR_COMMAND_REQUIRED),T=r=>{if(!n)return null;let i=t?.url;return(e===`add`||e===`edit`&&i!==r)&&n.some(e=>(e.type===`sse`||e.type===`shttp`)&&e.url===r)?f(a.SETTINGS$MCP_ERROR_URL_DUPLICATE):null},O=e=>{if(!e.trim())return null;let t=e.split(`
1
+ import{a as e}from"./rolldown-runtime-BFRubm34.js";import{t}from"./react-CM_dJw1Z.js";import{L as n}from"./vendor~entry.client~root~root-layout~index-redirect~home~conversation-panel~conversation~la~cnj3raoq-DTEXlLSB.js";import{t as r}from"./useMutation-DqrumCWD.js";import{o as i,t as a}from"./declaration-BNMqORFE.js";import{n as o}from"./QueryClientProvider-CkGuhXg-.js";import{t as s}from"./useTranslation-DCOdSSMl.js";import{t as c}from"./retrieve-axios-error-message-BY-yIkIq.js";import{t as l}from"./createLucideIcon-Ddu8jDOQ.js";import{r as u}from"./vendor~home~mcp~automations-list-Cs-TO3fK.js";import{n as d,r as f}from"./custom-toast-handlers-C-SZFmto.js";import{a as p,c as m,i as h,l as g,n as _,r as v,s as y}from"./circle-plus-check-toggle-P7ZZToV4.js";import{t as b}from"./trash-2-CbVljPko.js";import{t as x}from"./x-JOBEVLW0.js";import{t as S}from"./utils-i18rdUj2.js";import{n as C}from"./active-backend-context-cCM1vYYZ.js";import{a as w}from"./query-keys-tAsQcc_9.js";import{t as T}from"./modal-backdrop-BAbgYsqB.js";import{a as E,t as D}from"./brand-button-Br7f0kZJ.js";import{t as O}from"./modal-close-button-t1Gh3qmL.js";import{n as k,t as A}from"./settings-input-Bn7F5C75.js";import{t as j}from"./confirmation-modal-Dau3w_sa.js";import{t as M}from"./settings-service.api-CZ3uWx4v.js";import{a as N,i as P,r as F}from"./use-settings-DQIZmIov.js";import{t as ee}from"./settings-dropdown-input-BJYvGdg-.js";import{a as I,c as L,d as R,f as te,i as z,m as ne,n as re,p as B,r as V,s as H,t as U,u as W}from"./install-server-modal-DHlbgqVH.js";import{n as G}from"./extensions-navigation-BYR8Giqq.js";import{t as K}from"./enum-filter-dropdown-CEgCdu4A.js";import{n as q}from"./settings-like-page-layout-classes-I0BDBEoq.js";import{t as J}from"./acp-route-guard-B2yoBZ_4.js";var Y=l(`puzzle`,[[`path`,{d:`M15.39 4.39a1 1 0 0 0 1.68-.474 2.5 2.5 0 1 1 3.014 3.015 1 1 0 0 0-.474 1.68l1.683 1.682a2.414 2.414 0 0 1 0 3.414L19.61 15.39a1 1 0 0 1-1.68-.474 2.5 2.5 0 1 0-3.014 3.015 1 1 0 0 1 .474 1.68l-1.683 1.682a2.414 2.414 0 0 1-3.414 0L8.61 19.61a1 1 0 0 0-1.68.474 2.5 2.5 0 1 1-3.014-3.015 1 1 0 0 0 .474-1.68l-1.683-1.682a2.414 2.414 0 0 1 0-3.414L4.39 8.61a1 1 0 0 1 1.68.474 2.5 2.5 0 1 0 3.014-3.015 1 1 0 0 1-.474-1.68l1.683-1.682a2.414 2.414 0 0 1 3.414 0z`,key:`w46dr5`}]]),X=e(t(),1);function Z(){let e=o(),{data:t}=F();return r({mutationFn:async e=>{let n=P(t?.agent_settings?.mcp_config),r={sse_servers:[...n.sse_servers],stdio_servers:[...n.stdio_servers],shttp_servers:[...n.shttp_servers]},i=e=>{if(typeof e==`string`)return e;if(e&&typeof e==`object`&&`url`in e){let t=e.url;return typeof t==`string`?t:void 0}};if(e.type===`sse`){if(!e.url)return;let t=r.sse_servers.findIndex(t=>i(t)===e.url);t>=0&&r.sse_servers.splice(t,1)}else if(e.type===`shttp`){if(!e.url)return;let t=r.shttp_servers.findIndex(t=>i(t)===e.url);t>=0&&r.shttp_servers.splice(t,1)}else if(e.type===`stdio`){if(!e.name||!e.command)return;let t=r.stdio_servers.findIndex(t=>t.name===e.name&&t.command===e.command&&JSON.stringify(t.args??[])===JSON.stringify(e.args??[]));t>=0&&r.stdio_servers.splice(t,1)}else return;await M.saveSettings({agent_settings_diff:{mcp_config:N(r)}})},onSuccess:()=>{e.invalidateQueries({queryKey:w.personal()})}})}var Q=i();function ie(e){switch(e){case`sse`:return`SSE`;case`shttp`:return`HTTP`;case`stdio`:return`STDIO`;default:return e}}function ae(e){return e.type===`stdio`?e.name??e.command??``:e.url??``}function oe(e){if(e.type===`stdio`){let t=e.args&&e.args.length>0?` ${e.args.join(` `)}`:``;return`${e.command??``}${t}`.trim()}return e.url??``}function se({server:e,onEdit:t,onDelete:n}){let{t:r}=s(`openhands`),i=I(e,W(u)),o=i?.name??ae(e),c=oe(e),l=ie(e.type);return(0,Q.jsx)(`div`,{"data-testid":`mcp-server-item`,"data-server-id":e.id,role:`button`,tabIndex:0,onClick:t,onKeyDown:e=>{(e.key===`Enter`||e.key===` `)&&(e.preventDefault(),t())},"aria-label":r(a.MCP$EDIT_SERVER_ARIA,{name:o}),className:S(`flex min-h-[132px] flex-col overflow-hidden p-4 text-left`,y,p),children:(0,Q.jsxs)(`div`,{className:`flex items-start gap-3`,children:[(0,Q.jsx)(z,{entry:i,fallback:(0,Q.jsx)(Y,{strokeWidth:2.25})}),(0,Q.jsxs)(`div`,{className:`flex min-w-0 flex-1 flex-col gap-3`,children:[(0,Q.jsxs)(`header`,{className:`flex items-start justify-between gap-3`,children:[(0,Q.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,Q.jsx)(`h3`,{className:`truncate text-sm font-semibold`,title:o,children:o}),(0,Q.jsx)(`p`,{className:`mt-0.5 text-xs text-tertiary-alt`,children:l})]}),(0,Q.jsx)(_,{testId:`mcp-installed-toggle-${e.id}`,isSelected:!0,onToggle:e=>{e||n()},enableLabelKey:a.MCP$TOGGLE_ADD_SERVER,disableLabelKey:a.MCP$TOGGLE_REMOVE_SERVER})]}),i?.description?(0,Q.jsx)(`p`,{"data-testid":`mcp-server-description-${e.id}`,className:`line-clamp-2 break-words text-xs leading-relaxed text-tertiary-light`,children:i.description}):null,c?(0,Q.jsx)(`p`,{"data-testid":`mcp-server-detail-${e.id}`,className:`truncate text-xs text-tertiary-alt`,title:c,children:c}):null]})]})})}function ce({servers:e,hasAnyInstalled:t,query:n=``,onEdit:r,onDelete:i}){let{t:o}=s(`openhands`);return e.length===0?t&&n.trim().length>0?(0,Q.jsx)(`div`,{"data-testid":`mcp-installed-empty-search`,className:`rounded-xl border border-[var(--oh-border)] p-6 text-center`,children:(0,Q.jsx)(`p`,{className:`text-xs text-tertiary-light`,children:o(a.MCP$SEARCH_EMPTY)})}):(0,Q.jsxs)(`div`,{"data-testid":`mcp-installed-empty`,className:m,children:[(0,Q.jsx)(`p`,{className:`text-sm text-white`,children:o(a.MCP$INSTALLED_EMPTY_TITLE)}),(0,Q.jsx)(`p`,{className:`text-xs text-tertiary-light mt-1`,children:o(a.MCP$INSTALLED_EMPTY_HINT)})]}):(0,Q.jsx)(`div`,{className:h,children:(0,Q.jsx)(`div`,{"data-testid":`mcp-installed-list`,className:v,children:e.map(e=>(0,Q.jsx)(se,{server:e,onEdit:()=>r(e),onDelete:()=>i(e.id)},e.id))})})}function le({entry:e,onClick:t,onAdd:n}){let r=H(e),i=(()=>{switch(r?.kind){case`stdio`:return`STDIO`;case`shttp`:return`HTTP`;case`sse`:return`SSE`;default:return``}})();return(0,Q.jsx)(`button`,{type:`button`,onClick:t,"data-testid":`mcp-marketplace-card-${e.id}`,className:S(`flex min-h-[132px] flex-col overflow-hidden p-4 text-left`,y,p),children:(0,Q.jsxs)(`div`,{className:`flex items-start gap-3`,children:[(0,Q.jsx)(z,{entry:e}),(0,Q.jsxs)(`div`,{className:`flex min-w-0 flex-1 flex-col gap-3`,children:[(0,Q.jsxs)(`header`,{className:`flex items-start justify-between gap-3`,children:[(0,Q.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,Q.jsx)(`h3`,{className:`truncate text-sm font-semibold`,children:e.name}),(0,Q.jsx)(`p`,{className:`mt-0.5 text-xs text-tertiary-alt`,children:i})]}),(0,Q.jsx)(_,{testId:`mcp-marketplace-toggle-${e.id}`,isSelected:!1,onToggle:e=>{e&&n()},enableLabelKey:a.MCP$TOGGLE_ADD_SERVER,disableLabelKey:a.MCP$TOGGLE_ADD_SERVER})]}),(0,Q.jsx)(`p`,{className:`line-clamp-3 text-xs leading-relaxed text-tertiary-light`,children:e.description})]})]})})}function ue({backendKind:e,onSelect:t,onAdd:n,query:r=``}){let{t:i}=s(`openhands`),o=L(W(u)).filter(t=>te(t,e)&&B(t,r));return(0,Q.jsxs)(`section`,{"data-testid":`mcp-marketplace-section`,className:`flex flex-col gap-3`,children:[(0,Q.jsx)(`h2`,{className:`text-base font-medium text-foreground`,children:i(a.MCP$LIBRARY_TITLE)}),o.length===0?(0,Q.jsx)(`div`,{"data-testid":`mcp-marketplace-empty`,className:`rounded-xl border border-dashed border-[var(--oh-border)] p-6 text-center`,children:(0,Q.jsx)(`p`,{className:`text-xs text-tertiary-light`,children:i(a.MCP$SEARCH_EMPTY)})}):(0,Q.jsx)(`div`,{className:h,children:(0,Q.jsx)(`div`,{"data-testid":`mcp-marketplace-grid`,className:v,children:o.map(e=>(0,Q.jsx)(le,{entry:e,onClick:()=>t(e),onAdd:()=>n(e)},e.id))})})]})}function de({mode:e,server:t,existingServers:n,onSubmit:r,onCancel:i,onDelete:o,isActionDisabled:c=!1,onTest:l,isTestPending:u=!1,testMessage:d=null}){let{t:f}=s(`openhands`),[p,m]=X.useState(t?.type||`sse`),[h,g]=X.useState(null),_=X.useRef(null),v=[{key:`sse`,label:f(a.SETTINGS$MCP_SERVER_TYPE_SSE)},{key:`stdio`,label:f(a.SETTINGS$MCP_SERVER_TYPE_STDIO)},{key:`shttp`,label:f(a.SETTINGS$MCP_SERVER_TYPE_SHTTP)}],y=e=>{if(!e)return f(a.SETTINGS$MCP_ERROR_URL_REQUIRED);try{let t=new URL(e);if(![`http:`,`https:`].includes(t.protocol))return f(a.SETTINGS$MCP_ERROR_URL_INVALID_PROTOCOL)}catch{return f(a.SETTINGS$MCP_ERROR_URL_INVALID)}return null},x=e=>e?/^[a-zA-Z0-9_-]+$/.test(e)?null:f(a.SETTINGS$MCP_ERROR_NAME_INVALID):f(a.SETTINGS$MCP_ERROR_NAME_REQUIRED),C=r=>!n||!(e===`add`||e===`edit`&&t?.name!==r)?null:n.filter(e=>e.type===`stdio`).map(e=>e.name).filter(Boolean).includes(r)?f(a.SETTINGS$MCP_ERROR_NAME_DUPLICATE):null,w=e=>e?e.includes(` `)?f(a.SETTINGS$MCP_ERROR_COMMAND_NO_SPACES):null:f(a.SETTINGS$MCP_ERROR_COMMAND_REQUIRED),T=r=>{if(!n)return null;let i=t?.url;return(e===`add`||e===`edit`&&i!==r)&&n.some(e=>(e.type===`sse`||e.type===`shttp`)&&e.url===r)?f(a.SETTINGS$MCP_ERROR_URL_DUPLICATE):null},O=e=>{if(!e.trim())return null;let t=e.split(`
2
2
  `);for(let e=0;e<t.length;e+=1){let n=t[e].trim();if(n){let e=n.indexOf(`=`);if(e===-1||!n.substring(0,e).trim())return f(a.SETTINGS$MCP_ERROR_ENV_INVALID_FORMAT)}}return null},j=e=>{if(!e.trim())return null;let t=parseInt(e.trim(),10);return Number.isNaN(t)?f(a.SETTINGS$MCP_ERROR_TIMEOUT_INVALID_NUMBER):t<=0?f(a.SETTINGS$MCP_ERROR_TIMEOUT_POSITIVE):t>3600?f(a.SETTINGS$MCP_ERROR_TIMEOUT_MAX_EXCEEDED):null},M=e=>{let t=e.get(`name`)?.toString().trim()||``,n=e.get(`command`)?.toString().trim()||``,r=e.get(`env`)?.toString()||``;return x(t)||C(t)||w(n)||O(r)||null},N=e=>{if(p===`sse`||p===`shttp`){let t=e.get(`url`)?.toString().trim()||``,n=y(t);if(n)return n;let r=T(t);if(r)return r;if(p===`shttp`){let t=j(e.get(`timeout`)?.toString()||``);if(t)return t}return null}return p===`stdio`?M(e):null},P=e=>{let t={},n=e.trim();if(!n)return t;for(let e of n.split(`
3
3
  `)){let n=e.trim(),r=n.indexOf(`=`),i=r>=0?n.substring(0,r).trim():``;n&&r!==-1&&i&&(t[i]=n.substring(r+1).trim())}return t},F=e=>e?Object.entries(e).map(([e,t])=>`${e}=${t}`).join(`
4
4
  `):``,I=e=>{let n={id:t?.id||`${p}-${Date.now()}`,type:p};if(p===`sse`||p===`shttp`){let t=e.get(`url`)?.toString().trim(),r=e.get(`api_key`)?.toString().trim(),i=e.get(`timeout`)?.toString().trim(),a={...n,url:t,...r&&{api_key:r}};if(p===`shttp`&&i){let e=parseInt(i,10);Number.isNaN(e)||(a.timeout=e)}return a}let r=e.get(`name`)?.toString().trim(),i=e.get(`command`)?.toString().trim(),a=e.get(`args`)?.toString().trim(),o=e.get(`env`)?.toString().trim(),s=a?a.split(`
@@ -1,4 +1,4 @@
1
- import{a as e}from"./rolldown-runtime-BFRubm34.js";import{t}from"./react-CM_dJw1Z.js";import{o as n,t as r}from"./declaration-BNMqORFE.js";import{t as i}from"./use-is-creating-conversation-BZ5hB_Bg.js";import{t as a}from"./useTranslation-DCOdSSMl.js";import{r as o}from"./vendor~home~mcp~automations-list-Ccy2I0KU.js";import{a as s,i as c,o as l,r as u,s as d,t as f}from"./circle-plus-check-toggle-P7ZZToV4.js";import{t as p}from"./utils-i18rdUj2.js";import{n as m}from"./active-backend-context-cCM1vYYZ.js";import{n as h}from"./navigation-context-D0YWpT8d.js";import{a as g,o as _}from"./conversation-local-storage-UYl-SX-r.js";import{t as v}from"./conversation-store-Z5iMCRpc.js";import{i as y,r as b}from"./use-settings-DQIZmIov.js";import{t as x}from"./use-create-conversation-CEgXpkfH.js";import{f as S,i as C,l as w,m as T,o as E,t as D,u as O}from"./install-server-modal-f31_CLrW.js";import{n as k}from"./skill-card-pill-row-DF1axQCG.js";import{t as A}from"./clock-BRjCgHTc.js";var j=e(t(),1),M=[{id:`github-pr-reviewer`,name:`GitHub PR review copilot`,category:`Code review`,description:`Watch pull requests, inspect the diff, and leave a concise review with risks and suggested follow-ups.`,requiredIntegrationIds:[`github`],popularityRank:100,estimatedSetupMinutes:4,prompt:`Create an automation that reviews GitHub pull requests when they are opened or updated. Use the GitHub MCP to inspect the PR diff, changed files, tests, and existing discussion. Post a short review that highlights correctness risks, security issues, missing tests, and concrete next steps. Ask me for the repositories, filters, review tone, and whether comments should be posted automatically or drafted first.`,exampleImplementation:`Trigger: github.pull_request.opened and github.pull_request.synchronize
1
+ import{a as e}from"./rolldown-runtime-BFRubm34.js";import{t}from"./react-CM_dJw1Z.js";import{o as n,t as r}from"./declaration-BNMqORFE.js";import{t as i}from"./use-is-creating-conversation-BZ5hB_Bg.js";import{t as a}from"./useTranslation-DCOdSSMl.js";import{r as o}from"./vendor~home~mcp~automations-list-Cs-TO3fK.js";import{a as s,i as c,o as l,r as u,s as d,t as f}from"./circle-plus-check-toggle-P7ZZToV4.js";import{t as p}from"./utils-i18rdUj2.js";import{n as m}from"./active-backend-context-cCM1vYYZ.js";import{n as h}from"./navigation-context-D0YWpT8d.js";import{a as g,o as _}from"./conversation-local-storage-UYl-SX-r.js";import{t as v}from"./conversation-store-Z5iMCRpc.js";import{i as y,r as b}from"./use-settings-DQIZmIov.js";import{t as x}from"./use-create-conversation-CEgXpkfH.js";import{f as S,i as C,l as w,m as T,o as E,t as D,u as O}from"./install-server-modal-DHlbgqVH.js";import{n as k}from"./skill-card-pill-row-DF1axQCG.js";import{t as A}from"./clock-BRjCgHTc.js";var j=e(t(),1),M=[{id:`github-pr-reviewer`,name:`GitHub PR review copilot`,category:`Code review`,description:`Watch pull requests, inspect the diff, and leave a concise review with risks and suggested follow-ups.`,requiredIntegrationIds:[`github`],popularityRank:100,estimatedSetupMinutes:4,prompt:`Create an automation that reviews GitHub pull requests when they are opened or updated. Use the GitHub MCP to inspect the PR diff, changed files, tests, and existing discussion. Post a short review that highlights correctness risks, security issues, missing tests, and concrete next steps. Ask me for the repositories, filters, review tone, and whether comments should be posted automatically or drafted first.`,exampleImplementation:`Trigger: github.pull_request.opened and github.pull_request.synchronize
2
2
  Required MCP: GitHub
3
3
 
4
4
  1. Read repository, pull_request, and sender from the event payload.
@@ -1,2 +1,2 @@
1
1
  const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/vendor~entry.client~root~root-layout~home~conversation-panel~conversation~launch~skills-set~zm51vy4j-iOsylxCS.js","assets/rolldown-runtime-BFRubm34.js","assets/manage-backends-modal-l7RkKfwX.js","assets/agent-server-client-options-Bc5ZorQZ.js","assets/server-client-DyAQ3NZ_.js","assets/vendor~root~root-layout~home~conversation-panel~conversation~launch~extensions-hub~skills-s~f2l2lr17-CDXvdvb2.js","assets/vendor~entry.client~root~root-layout~home~conversation-panel~conversation~launch~extensions~g56ukk6u-DsSvIDZQ.js","assets/QueryClientProvider-CkGuhXg-.js","assets/declaration-BNMqORFE.js","assets/react-CM_dJw1Z.js","assets/pencil-Dr0b2jL1.js","assets/createLucideIcon-Ddu8jDOQ.js","assets/plus-DT-M0FA1.js","assets/trash-2-CbVljPko.js","assets/useTranslation-DCOdSSMl.js","assets/context-CEQZwATj.js","assets/backend-form-modal-Dnk33xA_.js","assets/organization-service.api-DzYTHTYC.js","assets/vendor~root-layout~home~conversation-panel~conversation~launch~extensions-hub~skills-settin~ninslayh-D9P8e98a.js","assets/proxy-CxydCnis.js","assets/health-store-BDC2rM-X.js","assets/brand-button-Br7f0kZJ.js","assets/utils-i18rdUj2.js","assets/vendor~entry.client~root~root-layout~home~conversation-panel~conversation~launch~extensions~hkqzh1hb-BZ0HXuHD.js","assets/settings-input-Bn7F5C75.js","assets/modal-backdrop-BAbgYsqB.js","assets/react-dom-hVBnwgwZ.js","assets/modal-body-BI6Ru2Qr.js","assets/modal-close-button-t1Gh3qmL.js","assets/navigation-context-D0YWpT8d.js","assets/active-backend-context-cCM1vYYZ.js","assets/confirmation-modal-Dau3w_sa.js","assets/api-key-entry-screen-B2gynaCp.js","assets/settings-client-C73C7IgV.js","assets/agent-server-compatibility-BlkUsrX2.js"])))=>i.map(i=>d[i]);
2
- import{a as e}from"./rolldown-runtime-BFRubm34.js";import{t}from"./react-CM_dJw1Z.js";import{t as n}from"./preload-helper-CT1Z6Pdu.js";import{L as r,a as i,c as a,d as o,f as s,i as c}from"./vendor~entry.client~root~root-layout~index-redirect~home~conversation-panel~conversation~la~cnj3raoq-DTEXlLSB.js";import{o as l,t as u}from"./declaration-BNMqORFE.js";import{t as d}from"./useTranslation-DCOdSSMl.js";import{r as f}from"./providers-Bx6EfrzZ.js";import{i as p,t as m}from"./custom-toast-handlers-C-SZFmto.js";import{w as h}from"./agent-server-client-options-Bc5ZorQZ.js";import{r as g,t as _}from"./agent-server-compatibility-BlkUsrX2.js";import{t as v}from"./modal-backdrop-BAbgYsqB.js";import{n as y}from"./modal-body-BI6Ru2Qr.js";import{n as b,r as x}from"./base-modal-_dYTw1ri.js";import{t as S}from"./brand-button-Br7f0kZJ.js";import{t as ee}from"./loading-spinner-BPtYORNK.js";import{t as C}from"./use-config-Co1O8-Ey.js";import{i as w,n as te}from"./color-themes-DSaoIL6A.js";var T=e(t(),1),E={name:`@openhands/agent-canvas`,version:`1.0.0-beta.4`,description:`Agent Canvas UI for OpenHands - run AI coding agents with a visual interface`,license:`MIT`,private:!1,type:`module`,repository:{type:`git`,url:`https://github.com/OpenHands/agent-canvas`},homepage:`https://github.com/OpenHands/agent-canvas#readme`,bugs:{url:`https://github.com/OpenHands/agent-canvas/issues`},bin:{"agent-canvas":`bin/agent-canvas.mjs`},engines:{node:`>=22.12.0`},dependencies:{"@heroui/react":`2.8.10`,"@microlink/react-json-view":`1.31.20`,"@monaco-editor/react":`4.7.0`,"@openhands/extensions":`git+https://github.com/OpenHands/extensions.git#e14f740c59b4bfd7369d4bb6aea5eeb33dd05909`,"@openhands/typescript-client":`1.24.3`,"@react-router/node":`7.14.2`,"@react-router/serve":`7.14.2`,"@tailwindcss/vite":`4.2.4`,"@tanstack/react-query":`5.100.9`,"@types/shell-quote":`^1.7.5`,"@uidotdev/usehooks":`2.4.1`,"@xterm/addon-fit":`0.11.0`,"@xterm/xterm":`6.0.0`,axios:`1.16.0`,"class-variance-authority":`0.7.1`,clsx:`2.1.1`,downshift:`9.3.2`,"framer-motion":`12.38.0`,i18next:`26.0.8`,"i18next-browser-languagedetector":`8.2.1`,"i18next-http-backend":`4.0.0`,isbot:`5.1.39`,"lucide-react":`1.14.0`,"monaco-editor":`0.55.1`,"posthog-js":`1.372.6`,react:`19.2.5`,"react-dom":`19.2.5`,"react-hot-toast":`2.6.0`,"react-i18next":`17.0.6`,"react-icons":`5.6.0`,"react-markdown":`10.1.0`,"react-router":`7.14.2`,"react-syntax-highlighter":`16.1.1`,"rehype-raw":`7.0.0`,"rehype-sanitize":`6.0.0`,"remark-breaks":`4.0.0`,"remark-gfm":`4.0.1`,"shell-quote":`^1.8.3`,"sirv-cli":`3.0.1`,"socket.io-client":`4.8.3`,"tailwind-merge":`3.5.0`,"tailwind-scrollbar":`4.0.2`,"unist-util-visit":`5.1.0`,uuid:`14.0.0`,vite:`8.0.10`,zustand:`5.0.12`},scripts:{dev:`node --env-file-if-exists=.env scripts/dev-with-automation.mjs`,"dev:static":`node --env-file-if-exists=.env scripts/dev-static.mjs`,"dev:extra-backend":`node --env-file-if-exists=.env scripts/dev-extra-backend.mjs`,"dev:minimal":`node --env-file-if-exists=.env scripts/dev-safe.mjs`,"dev:frontend":`npm run make-i18n && cross-env VITE_MOCK_API=false react-router dev`,"dev:mock":`npm run make-i18n && cross-env VITE_MOCK_API=true react-router dev`,build:`npm run build:app`,"build:mock":`npm run make-i18n && cross-env VITE_MOCK_API=true react-router build`,start:`npx sirv-cli build/ --single`,test:`npm run make-i18n && vitest run`,"test:e2e":`playwright test --pass-with-no-tests`,"test:e2e:live":`node --env-file-if-exists=.env tests/e2e/live/scripts/run-live-e2e.mjs`,"test:e2e:mock-llm":`playwright test --config=playwright.mock-llm.config.ts`,"test:e2e:mock-llm:docker":`playwright test --config=playwright.mock-llm-docker.config.ts`,"test:e2e:snapshots":`playwright test tests/e2e/snapshots --project=chromium --retries=0`,"test:e2e:snapshots:update":`playwright test tests/e2e/snapshots --project=chromium --update-snapshots`,"test:coverage":`npm run make-i18n && vitest run --coverage`,dev_wsl:`VITE_WATCH_USE_POLLING=true vite`,preview:`vite preview`,"make-i18n":`node scripts/make-i18n-translations.cjs`,prelint:`npm run make-i18n`,lint:`npm run typecheck && eslint src && prettier --check src/**/*.{ts,tsx}`,"lint:fix":`eslint src --fix && prettier --write src/**/*.{ts,tsx}`,prepare:`husky`,typecheck:`react-router typegen && tsc`,"typecheck:staged":`react-router typegen && npx tsc --noEmit --skipLibCheck`,"check-translation-completeness":`node scripts/check-translation-completeness.cjs`,"build:app":`npm run make-i18n && react-router build`,"build:lib":`npm run make-i18n && react-router typegen && cross-env BUILD_LIB=true VITE_APP_ENV=production vite build && tsc -p tsconfig.lib.json`,"build:docker":`node scripts/docker-build.mjs`},"lint-staged":{"src/**/*.{ts,tsx,js}":[`eslint --fix`,`prettier --write`],"src/**/*.{ts,tsx}":[`bash -c 'npm run typecheck:staged'`],"src/**/*":[`npm run check-translation-completeness`]},devDependencies:{"@eslint/eslintrc":`3.3.1`,"@eslint/js":`9.39.4`,"@mswjs/socket.io-binding":`0.2.0`,"@playwright/test":`1.59.1`,"@react-router/dev":`7.14.2`,"@tailwindcss/typography":`0.5.19`,"@tanstack/eslint-plugin-query":`5.100.9`,"@testing-library/dom":`10.4.1`,"@testing-library/jest-dom":`6.9.1`,"@testing-library/react":`16.3.2`,"@testing-library/user-event":`14.6.1`,"@types/mdast":`4.0.4`,"@types/node":`25.6.0`,"@types/react":`19.2.14`,"@types/react-dom":`19.2.3`,"@types/react-syntax-highlighter":`15.5.13`,"@typescript-eslint/eslint-plugin":`8.59.2`,"@typescript-eslint/parser":`8.59.2`,"@vercel/react-router":`1.3.0`,"@vitest/coverage-v8":`4.1.5`,"cross-env":`10.1.0`,eslint:`9.39.4`,"eslint-config-prettier":`10.1.8`,"eslint-import-resolver-typescript":`4.4.4`,"eslint-plugin-i18next":`6.1.4`,"eslint-plugin-import-x":`4.16.2`,"eslint-plugin-jsx-a11y":`6.10.2`,"eslint-plugin-prettier":`5.5.5`,"eslint-plugin-react":`7.37.5`,"eslint-plugin-react-hooks":`7.1.1`,"eslint-plugin-unused-imports":`4.4.1`,globals:`16.5.0`,husky:`9.1.7`,jsdom:`29.1.1`,"lint-staged":`16.4.0`,msw:`2.14.2`,"postcss-prefix-selector":`2.1.1`,prettier:`3.8.3`,tailwindcss:`4.2.4`,typescript:`6.0.3`,"vite-plugin-svgr":`5.2.0`,vitest:`4.1.5`},packageManager:`npm@10.5.0`,volta:{node:`22.12.0`},msw:{workerDirectory:[`public`]},overrides:{dompurify:`3.3.2`},main:`./dist/index.cjs`,module:`./dist/index.js`,types:`./dist/index.d.ts`,files:[`dist`,`bin`,`build`,`config`,`scripts`,`tools`],exports:{".":{types:`./dist/index.d.ts`,import:`./dist/index.js`,require:`./dist/index.cjs`},"./browser":{types:`./dist/components/browser/index.d.ts`,import:`./dist/components/browser/index.js`,require:`./dist/components/browser/index.cjs`},"./conversation":{types:`./dist/components/conversation/index.d.ts`,import:`./dist/components/conversation/index.js`,require:`./dist/components/conversation/index.cjs`},"./files":{types:`./dist/components/files/index.d.ts`,import:`./dist/components/files/index.js`,require:`./dist/components/files/index.cjs`},"./settings":{types:`./dist/components/settings/index.d.ts`,import:`./dist/components/settings/index.js`,require:`./dist/components/settings/index.cjs`},"./sidebar":{types:`./dist/components/sidebar/index.d.ts`,import:`./dist/components/sidebar/index.js`,require:`./dist/components/sidebar/index.cjs`},"./terminal":{types:`./dist/components/terminal/index.d.ts`,import:`./dist/components/terminal/index.js`,require:`./dist/components/terminal/index.cjs`},"./i18n":{types:`./dist/i18n/index.d.ts`,import:`./dist/i18n/index.js`,require:`./dist/i18n/index.cjs`},"./package.json":`./package.json`},peerDependencies:{react:`19.2.5`,"react-dom":`19.2.5`,"react-router":`7.14.2`}},D=`openhands-telemetry-consent`,O=`openhands-telemetry-first-use`,k=`openhands-telemetry-session`,A=`phc_kBtz5nKmxVRRQ7HtPwr2QX9eMC5j65zE86QKocVNwb4U`,j=`https://z.openhands.dev`,M=`https://us.posthog.com`,N=!1,P=null;function F(){return typeof window<`u`&&typeof localStorage<`u`}async function I(){if(!F())return null;if(P)return P;try{let{default:e}=await n(async()=>{let{default:e}=await import(`./vendor~entry.client~root~root-layout~home~conversation-panel~conversation~launch~skills-set~zm51vy4j-iOsylxCS.js`).then(e=>e.n);return{default:e}},__vite__mapDeps([0,1]));return P=e,e}catch{return null}}function L(){return typeof process<`u`&&{}?.DO_NOT_TRACK===`1`||typeof navigator<`u`&&(navigator.doNotTrack===`1`||typeof window<`u`&&window.doNotTrack===`1`)}async function R(e=!1){if(N)return P;let t=await I();return t?(t.init(A,{api_host:j,ui_host:M,opt_out_capturing_by_default:!e,capture_pageview:!1,autocapture:!1,persistence:`localStorage`,disable_session_recording:!0,loaded:e=>{e.register({package_name:E.name,package_version:E.version})}}),N=!0,t):null}function z(){if(!F())return`pending`;if(L())return`denied`;try{let e=localStorage.getItem(D);if(e===`granted`||e===`denied`)return e}catch{}return`pending`}async function B(e){if(F())try{localStorage.setItem(D,e);let t=await R();if(!t)return;e===`granted`?t.opt_in_capturing():t.opt_out_capturing()}catch{}}function V(){return z()===`granted`}function H(){if(!F())return!1;try{return localStorage.getItem(O)===`true`}catch{return!1}}function U(){if(F())try{localStorage.setItem(O,`true`)}catch{}}async function W(){if(L()||H())return;let e=await R(!0);e&&((e.has_opted_out_capturing?.()??!1)&&e.opt_in_capturing(),e.capture(`canvas_install`,{platform:typeof navigator<`u`?navigator.platform:`unknown`,user_agent:typeof navigator<`u`?navigator.userAgent:`unknown`,referrer:typeof document<`u`?document.referrer:``,url_origin:typeof window<`u`?window.location.origin:``,embedded:typeof window<`u`&&window.self!==window.top}),U(),z()!==`granted`&&e.opt_out_capturing())}function G(){if(!F())return!1;try{return sessionStorage.getItem(k)===`true`}catch{return!1}}function K(){if(F())try{sessionStorage.setItem(k,`true`)}catch{}}async function q(){if(!V()||G())return;let e=await R();e&&(e.capture(`canvas_new_session`,{is_first_use:!H()}),K())}async function J(e,t={}){if(!V())return;let n=await R();n&&n.capture(e,t)}async function Y(){if(F())try{localStorage.removeItem(D),localStorage.removeItem(O),sessionStorage.removeItem(k),N&&P&&P.reset()}catch{}}function X(){let[e,t]=(0,T.useState)(()=>z()),n=(0,T.useRef)(!1);(0,T.useEffect)(()=>{n.current||(n.current=!0,W())},[]),(0,T.useEffect)(()=>{e===`granted`&&q()},[e]);let r=(0,T.useCallback)(async()=>{await B(`granted`),t(`granted`)},[]),i=(0,T.useCallback)(async()=>{await B(`denied`),t(`denied`)},[]),a=(0,T.useCallback)((t,n)=>{e===`granted`&&J(t,n)},[e]),o=(0,T.useCallback)(()=>{Y(),t(`pending`)},[]);return{consent:e,isEnabled:e===`granted`,showConsentPrompt:e===`pending`,grantConsent:r,denyConsent:i,track:a,clearData:o}}var Z=l();function Q({onChoice:e}){let{t,ready:n}=d(`openhands`),{showConsentPrompt:r,grantConsent:i,denyConsent:a}=X(),[o,s]=(0,T.useState)(!1);return(0,T.useEffect)(()=>{if(n&&r){let e=setTimeout(()=>s(!0),50);return()=>clearTimeout(e)}s(!1)},[n,r]),o?(0,Z.jsx)(v,{"aria-label":t(u.TELEMETRY$CONSENT_TITLE),children:(0,Z.jsx)(`form`,{"data-testid":`telemetry-consent-form`,onSubmit:t=>{t.preventDefault();let n=new FormData(t.currentTarget).get(`analytics`)===`on`;n?i():a(),e?.(n)},className:`flex flex-col gap-2`,children:(0,Z.jsxs)(y,{className:`border border-[var(--oh-border)]`,children:[(0,Z.jsx)(x,{title:t(u.TELEMETRY$CONSENT_TITLE)}),(0,Z.jsx)(b,{children:t(u.TELEMETRY$CONSENT_DESCRIPTION)}),(0,Z.jsxs)(`label`,{className:`flex gap-2 items-center self-start text-sm cursor-pointer`,children:[(0,Z.jsx)(`input`,{name:`analytics`,type:`checkbox`,defaultChecked:!0,className:`w-4 h-4 cursor-pointer`}),t(u.TELEMETRY$SEND_ANONYMOUS_DATA)]}),(0,Z.jsx)(S,{testId:`confirm-telemetry-preferences`,type:`submit`,variant:`primary`,className:`w-full`,children:t(u.TELEMETRY$CONFIRM_PREFERENCES)})]})})}):null}function ne(){return T.useEffect(()=>{te(w())},[]),null}var re=T.lazy(()=>n(()=>import(`./manage-backends-modal-l7RkKfwX.js`).then(e=>e.n).then(e=>({default:e.ManageBackendsModal})),__vite__mapDeps([2,1,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31]))),ie=T.lazy(()=>n(()=>import(`./api-key-entry-screen-B2gynaCp.js`),__vite__mapDeps([32,1,3,33,8,14,15,9,34,4,16,17,6,5,7,18,19,20,21,22,23,24,25,26,27,28,29,30])));function ae({children:e}){return(0,Z.jsxs)(`html`,{lang:`en`,children:[(0,Z.jsxs)(`head`,{children:[(0,Z.jsx)(`meta`,{charSet:`utf-8`}),(0,Z.jsx)(`meta`,{name:`viewport`,content:`width=device-width, initial-scale=1`}),(0,Z.jsx)(i,{}),(0,Z.jsx)(c,{})]}),(0,Z.jsxs)(`body`,{"data-agent-server-ui":``,className:`m-0`,children:[(0,Z.jsxs)(f,{contentClassName:`min-h-screen`,children:[(0,Z.jsx)(ne,{}),e,(0,Z.jsx)(p,{toastOptions:m}),(0,Z.jsx)(Q,{}),(0,Z.jsx)(`div`,{id:`modal-portal-exit`})]}),(0,Z.jsx)(s,{}),(0,Z.jsx)(o,{})]})]})}function $(){return(0,Z.jsx)(`main`,{className:`min-h-screen bg-base px-6 py-10 text-white`,children:(0,Z.jsx)(`div`,{className:`mx-auto flex min-h-screen max-w-6xl items-center justify-center`,children:(0,Z.jsx)(`div`,{className:`rounded-3xl border border-white/10 bg-base/80 px-8 py-10 shadow-2xl`,children:(0,Z.jsx)(ee,{size:`large`})})})})}function oe(){let e=T.useCallback(()=>{},[]);return(0,Z.jsx)(`main`,{"data-testid":`agent-server-onboarding-screen`,className:`min-h-screen bg-base`,children:(0,Z.jsx)(T.Suspense,{fallback:null,children:(0,Z.jsx)(re,{onClose:e})})})}var se=()=>[{rel:`icon`,type:`image/svg+xml`,href:`/favicon.svg`}],ce=()=>[{title:`OpenHands`},{name:`description`,content:`Let's Start Building!`}],le=r(function(){let e=h(),t=C({enabled:!e});return e||_(t.error)?(0,Z.jsx)(T.Suspense,{fallback:(0,Z.jsx)($,{}),children:(0,Z.jsx)(ie,{})}):t.isPending||t.isLoading?(0,Z.jsx)($,{}):g(t.error)?(0,Z.jsx)(oe,{}):(0,Z.jsx)(a,{})});export{ae as Layout,le as default,se as links,ce as meta};
2
+ import{a as e}from"./rolldown-runtime-BFRubm34.js";import{t}from"./react-CM_dJw1Z.js";import{t as n}from"./preload-helper-CT1Z6Pdu.js";import{L as r,a as i,c as a,d as o,f as s,i as c}from"./vendor~entry.client~root~root-layout~index-redirect~home~conversation-panel~conversation~la~cnj3raoq-DTEXlLSB.js";import{o as l,t as u}from"./declaration-BNMqORFE.js";import{t as d}from"./useTranslation-DCOdSSMl.js";import{r as f}from"./providers-Bx6EfrzZ.js";import{i as p,t as m}from"./custom-toast-handlers-C-SZFmto.js";import{w as h}from"./agent-server-client-options-Bc5ZorQZ.js";import{r as g,t as _}from"./agent-server-compatibility-BlkUsrX2.js";import{t as v}from"./modal-backdrop-BAbgYsqB.js";import{n as y}from"./modal-body-BI6Ru2Qr.js";import{n as b,r as x}from"./base-modal-_dYTw1ri.js";import{t as S}from"./brand-button-Br7f0kZJ.js";import{t as ee}from"./loading-spinner-BPtYORNK.js";import{t as C}from"./use-config-Co1O8-Ey.js";import{i as w,n as te}from"./color-themes-DSaoIL6A.js";var T=e(t(),1),E={name:`@openhands/agent-canvas`,version:`1.0.0-beta.6`,description:`Agent Canvas UI for OpenHands - run AI coding agents with a visual interface`,license:`MIT`,private:!1,type:`module`,repository:{type:`git`,url:`https://github.com/OpenHands/agent-canvas`},homepage:`https://github.com/OpenHands/agent-canvas#readme`,bugs:{url:`https://github.com/OpenHands/agent-canvas/issues`},bin:{"agent-canvas":`bin/agent-canvas.mjs`},engines:{node:`>=22.12.0`},dependencies:{"@heroui/react":`2.8.10`,"@microlink/react-json-view":`1.31.20`,"@monaco-editor/react":`4.7.0`,"@openhands/extensions":`git+https://github.com/OpenHands/extensions.git#62594156a187722344736bc2ff5edfb12c0cc75c`,"@openhands/typescript-client":`1.24.3`,"@react-router/node":`7.14.2`,"@react-router/serve":`7.14.2`,"@tailwindcss/vite":`4.2.4`,"@tanstack/react-query":`5.100.9`,"@types/shell-quote":`^1.7.5`,"@uidotdev/usehooks":`2.4.1`,"@xterm/addon-fit":`0.11.0`,"@xterm/xterm":`6.0.0`,axios:`1.16.0`,"class-variance-authority":`0.7.1`,clsx:`2.1.1`,downshift:`9.3.2`,"framer-motion":`12.38.0`,i18next:`26.0.8`,"i18next-browser-languagedetector":`8.2.1`,"i18next-http-backend":`4.0.0`,isbot:`5.1.39`,"lucide-react":`1.14.0`,"monaco-editor":`0.55.1`,"posthog-js":`1.372.6`,react:`19.2.5`,"react-dom":`19.2.5`,"react-hot-toast":`2.6.0`,"react-i18next":`17.0.6`,"react-icons":`5.6.0`,"react-markdown":`10.1.0`,"react-router":`7.14.2`,"react-syntax-highlighter":`16.1.1`,"rehype-raw":`7.0.0`,"rehype-sanitize":`6.0.0`,"remark-breaks":`4.0.0`,"remark-gfm":`4.0.1`,"shell-quote":`^1.8.3`,"sirv-cli":`3.0.1`,"socket.io-client":`4.8.3`,"tailwind-merge":`3.5.0`,"tailwind-scrollbar":`4.0.2`,"unist-util-visit":`5.1.0`,uuid:`14.0.0`,vite:`8.0.10`,zustand:`5.0.12`},scripts:{dev:`node --env-file-if-exists=.env scripts/dev-with-automation.mjs`,"dev:static":`node --env-file-if-exists=.env scripts/dev-static.mjs`,"dev:extra-backend":`node --env-file-if-exists=.env scripts/dev-extra-backend.mjs`,"dev:minimal":`node --env-file-if-exists=.env scripts/dev-safe.mjs`,"dev:frontend":`npm run make-i18n && cross-env VITE_MOCK_API=false react-router dev`,"dev:mock":`npm run make-i18n && cross-env VITE_MOCK_API=true react-router dev`,build:`npm run build:app`,"build:mock":`npm run make-i18n && cross-env VITE_MOCK_API=true react-router build`,start:`npx sirv-cli build/ --single`,test:`npm run make-i18n && vitest run`,"test:e2e":`playwright test --pass-with-no-tests`,"test:e2e:live":`node --env-file-if-exists=.env tests/e2e/live/scripts/run-live-e2e.mjs`,"test:e2e:mock-llm":`playwright test --config=playwright.mock-llm.config.ts`,"test:e2e:mock-llm:docker":`playwright test --config=playwright.mock-llm-docker.config.ts`,"test:e2e:snapshots":`playwright test tests/e2e/snapshots --project=chromium --retries=0`,"test:e2e:snapshots:update":`playwright test tests/e2e/snapshots --project=chromium --update-snapshots`,"test:coverage":`npm run make-i18n && vitest run --coverage`,dev_wsl:`VITE_WATCH_USE_POLLING=true vite`,preview:`vite preview`,"make-i18n":`node scripts/make-i18n-translations.cjs`,prelint:`npm run make-i18n`,lint:`npm run typecheck && eslint src && prettier --check src/**/*.{ts,tsx}`,"lint:fix":`eslint src --fix && prettier --write src/**/*.{ts,tsx}`,prepare:`husky`,typecheck:`react-router typegen && tsc`,"typecheck:staged":`react-router typegen && npx tsc --noEmit --skipLibCheck`,"check-translation-completeness":`node scripts/check-translation-completeness.cjs`,"build:app":`npm run make-i18n && react-router build`,"build:lib":`npm run make-i18n && react-router typegen && cross-env BUILD_LIB=true VITE_APP_ENV=production vite build && tsc -p tsconfig.lib.json`,"build:docker":`node scripts/docker-build.mjs`},"lint-staged":{"src/**/*.{ts,tsx,js}":[`eslint --fix`,`prettier --write`],"src/**/*.{ts,tsx}":[`bash -c 'npm run typecheck:staged'`],"src/**/*":[`npm run check-translation-completeness`]},devDependencies:{"@eslint/eslintrc":`3.3.1`,"@eslint/js":`9.39.4`,"@mswjs/socket.io-binding":`0.2.0`,"@playwright/test":`1.59.1`,"@react-router/dev":`7.14.2`,"@tailwindcss/typography":`0.5.19`,"@tanstack/eslint-plugin-query":`5.100.9`,"@testing-library/dom":`10.4.1`,"@testing-library/jest-dom":`6.9.1`,"@testing-library/react":`16.3.2`,"@testing-library/user-event":`14.6.1`,"@types/mdast":`4.0.4`,"@types/node":`25.6.0`,"@types/react":`19.2.14`,"@types/react-dom":`19.2.3`,"@types/react-syntax-highlighter":`15.5.13`,"@typescript-eslint/eslint-plugin":`8.59.2`,"@typescript-eslint/parser":`8.59.2`,"@vercel/react-router":`1.3.0`,"@vitest/coverage-v8":`4.1.5`,"cross-env":`10.1.0`,eslint:`9.39.4`,"eslint-config-prettier":`10.1.8`,"eslint-import-resolver-typescript":`4.4.4`,"eslint-plugin-i18next":`6.1.4`,"eslint-plugin-import-x":`4.16.2`,"eslint-plugin-jsx-a11y":`6.10.2`,"eslint-plugin-prettier":`5.5.5`,"eslint-plugin-react":`7.37.5`,"eslint-plugin-react-hooks":`7.1.1`,"eslint-plugin-unused-imports":`4.4.1`,globals:`16.5.0`,husky:`9.1.7`,jsdom:`29.1.1`,"lint-staged":`16.4.0`,msw:`2.14.2`,"postcss-prefix-selector":`2.1.1`,prettier:`3.8.3`,tailwindcss:`4.2.4`,typescript:`6.0.3`,"vite-plugin-svgr":`5.2.0`,vitest:`4.1.5`},packageManager:`npm@10.5.0`,volta:{node:`22.12.0`},msw:{workerDirectory:[`public`]},overrides:{dompurify:`3.3.2`},main:`./dist/index.cjs`,module:`./dist/index.js`,types:`./dist/index.d.ts`,files:[`dist`,`bin`,`build`,`config`,`scripts`,`tools`],exports:{".":{types:`./dist/index.d.ts`,import:`./dist/index.js`,require:`./dist/index.cjs`},"./browser":{types:`./dist/components/browser/index.d.ts`,import:`./dist/components/browser/index.js`,require:`./dist/components/browser/index.cjs`},"./conversation":{types:`./dist/components/conversation/index.d.ts`,import:`./dist/components/conversation/index.js`,require:`./dist/components/conversation/index.cjs`},"./files":{types:`./dist/components/files/index.d.ts`,import:`./dist/components/files/index.js`,require:`./dist/components/files/index.cjs`},"./settings":{types:`./dist/components/settings/index.d.ts`,import:`./dist/components/settings/index.js`,require:`./dist/components/settings/index.cjs`},"./sidebar":{types:`./dist/components/sidebar/index.d.ts`,import:`./dist/components/sidebar/index.js`,require:`./dist/components/sidebar/index.cjs`},"./terminal":{types:`./dist/components/terminal/index.d.ts`,import:`./dist/components/terminal/index.js`,require:`./dist/components/terminal/index.cjs`},"./i18n":{types:`./dist/i18n/index.d.ts`,import:`./dist/i18n/index.js`,require:`./dist/i18n/index.cjs`},"./package.json":`./package.json`},peerDependencies:{react:`19.2.5`,"react-dom":`19.2.5`,"react-router":`7.14.2`}},D=`openhands-telemetry-consent`,O=`openhands-telemetry-first-use`,k=`openhands-telemetry-session`,A=`phc_kBtz5nKmxVRRQ7HtPwr2QX9eMC5j65zE86QKocVNwb4U`,j=`https://z.openhands.dev`,M=`https://us.posthog.com`,N=!1,P=null;function F(){return typeof window<`u`&&typeof localStorage<`u`}async function I(){if(!F())return null;if(P)return P;try{let{default:e}=await n(async()=>{let{default:e}=await import(`./vendor~entry.client~root~root-layout~home~conversation-panel~conversation~launch~skills-set~zm51vy4j-iOsylxCS.js`).then(e=>e.n);return{default:e}},__vite__mapDeps([0,1]));return P=e,e}catch{return null}}function L(){return typeof process<`u`&&{}?.DO_NOT_TRACK===`1`||typeof navigator<`u`&&(navigator.doNotTrack===`1`||typeof window<`u`&&window.doNotTrack===`1`)}async function R(e=!1){if(N)return P;let t=await I();return t?(t.init(A,{api_host:j,ui_host:M,opt_out_capturing_by_default:!e,capture_pageview:!1,autocapture:!1,persistence:`localStorage`,disable_session_recording:!0,loaded:e=>{e.register({package_name:E.name,package_version:E.version})}}),N=!0,t):null}function z(){if(!F())return`pending`;if(L())return`denied`;try{let e=localStorage.getItem(D);if(e===`granted`||e===`denied`)return e}catch{}return`pending`}async function B(e){if(F())try{localStorage.setItem(D,e);let t=await R();if(!t)return;e===`granted`?t.opt_in_capturing():t.opt_out_capturing()}catch{}}function V(){return z()===`granted`}function H(){if(!F())return!1;try{return localStorage.getItem(O)===`true`}catch{return!1}}function U(){if(F())try{localStorage.setItem(O,`true`)}catch{}}async function W(){if(L()||H())return;let e=await R(!0);e&&((e.has_opted_out_capturing?.()??!1)&&e.opt_in_capturing(),e.capture(`canvas_install`,{platform:typeof navigator<`u`?navigator.platform:`unknown`,user_agent:typeof navigator<`u`?navigator.userAgent:`unknown`,referrer:typeof document<`u`?document.referrer:``,url_origin:typeof window<`u`?window.location.origin:``,embedded:typeof window<`u`&&window.self!==window.top}),U(),z()!==`granted`&&e.opt_out_capturing())}function G(){if(!F())return!1;try{return sessionStorage.getItem(k)===`true`}catch{return!1}}function K(){if(F())try{sessionStorage.setItem(k,`true`)}catch{}}async function q(){if(!V()||G())return;let e=await R();e&&(e.capture(`canvas_new_session`,{is_first_use:!H()}),K())}async function J(e,t={}){if(!V())return;let n=await R();n&&n.capture(e,t)}async function Y(){if(F())try{localStorage.removeItem(D),localStorage.removeItem(O),sessionStorage.removeItem(k),N&&P&&P.reset()}catch{}}function X(){let[e,t]=(0,T.useState)(()=>z()),n=(0,T.useRef)(!1);(0,T.useEffect)(()=>{n.current||(n.current=!0,W())},[]),(0,T.useEffect)(()=>{e===`granted`&&q()},[e]);let r=(0,T.useCallback)(async()=>{await B(`granted`),t(`granted`)},[]),i=(0,T.useCallback)(async()=>{await B(`denied`),t(`denied`)},[]),a=(0,T.useCallback)((t,n)=>{e===`granted`&&J(t,n)},[e]),o=(0,T.useCallback)(()=>{Y(),t(`pending`)},[]);return{consent:e,isEnabled:e===`granted`,showConsentPrompt:e===`pending`,grantConsent:r,denyConsent:i,track:a,clearData:o}}var Z=l();function Q({onChoice:e}){let{t,ready:n}=d(`openhands`),{showConsentPrompt:r,grantConsent:i,denyConsent:a}=X(),[o,s]=(0,T.useState)(!1);return(0,T.useEffect)(()=>{if(n&&r){let e=setTimeout(()=>s(!0),50);return()=>clearTimeout(e)}s(!1)},[n,r]),o?(0,Z.jsx)(v,{"aria-label":t(u.TELEMETRY$CONSENT_TITLE),children:(0,Z.jsx)(`form`,{"data-testid":`telemetry-consent-form`,onSubmit:t=>{t.preventDefault();let n=new FormData(t.currentTarget).get(`analytics`)===`on`;n?i():a(),e?.(n)},className:`flex flex-col gap-2`,children:(0,Z.jsxs)(y,{className:`border border-[var(--oh-border)]`,children:[(0,Z.jsx)(x,{title:t(u.TELEMETRY$CONSENT_TITLE)}),(0,Z.jsx)(b,{children:t(u.TELEMETRY$CONSENT_DESCRIPTION)}),(0,Z.jsxs)(`label`,{className:`flex gap-2 items-center self-start text-sm cursor-pointer`,children:[(0,Z.jsx)(`input`,{name:`analytics`,type:`checkbox`,defaultChecked:!0,className:`w-4 h-4 cursor-pointer`}),t(u.TELEMETRY$SEND_ANONYMOUS_DATA)]}),(0,Z.jsx)(S,{testId:`confirm-telemetry-preferences`,type:`submit`,variant:`primary`,className:`w-full`,children:t(u.TELEMETRY$CONFIRM_PREFERENCES)})]})})}):null}function ne(){return T.useEffect(()=>{te(w())},[]),null}var re=T.lazy(()=>n(()=>import(`./manage-backends-modal-l7RkKfwX.js`).then(e=>e.n).then(e=>({default:e.ManageBackendsModal})),__vite__mapDeps([2,1,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31]))),ie=T.lazy(()=>n(()=>import(`./api-key-entry-screen-B2gynaCp.js`),__vite__mapDeps([32,1,3,33,8,14,15,9,34,4,16,17,6,5,7,18,19,20,21,22,23,24,25,26,27,28,29,30])));function ae({children:e}){return(0,Z.jsxs)(`html`,{lang:`en`,children:[(0,Z.jsxs)(`head`,{children:[(0,Z.jsx)(`meta`,{charSet:`utf-8`}),(0,Z.jsx)(`meta`,{name:`viewport`,content:`width=device-width, initial-scale=1`}),(0,Z.jsx)(i,{}),(0,Z.jsx)(c,{})]}),(0,Z.jsxs)(`body`,{"data-agent-server-ui":``,className:`m-0`,children:[(0,Z.jsxs)(f,{contentClassName:`min-h-screen`,children:[(0,Z.jsx)(ne,{}),e,(0,Z.jsx)(p,{toastOptions:m}),(0,Z.jsx)(Q,{}),(0,Z.jsx)(`div`,{id:`modal-portal-exit`})]}),(0,Z.jsx)(s,{}),(0,Z.jsx)(o,{})]})]})}function $(){return(0,Z.jsx)(`main`,{className:`min-h-screen bg-base px-6 py-10 text-white`,children:(0,Z.jsx)(`div`,{className:`mx-auto flex min-h-screen max-w-6xl items-center justify-center`,children:(0,Z.jsx)(`div`,{className:`rounded-3xl border border-white/10 bg-base/80 px-8 py-10 shadow-2xl`,children:(0,Z.jsx)(ee,{size:`large`})})})})}function oe(){let e=T.useCallback(()=>{},[]);return(0,Z.jsx)(`main`,{"data-testid":`agent-server-onboarding-screen`,className:`min-h-screen bg-base`,children:(0,Z.jsx)(T.Suspense,{fallback:null,children:(0,Z.jsx)(re,{onClose:e})})})}var se=()=>[{rel:`icon`,type:`image/svg+xml`,href:`/favicon.svg`}],ce=()=>[{title:`OpenHands`},{name:`description`,content:`Let's Start Building!`}],le=r(function(){let e=h(),t=C({enabled:!e});return e||_(t.error)?(0,Z.jsx)(T.Suspense,{fallback:(0,Z.jsx)($,{}),children:(0,Z.jsx)(ie,{})}):t.isPending||t.isLoading?(0,Z.jsx)($,{}):g(t.error)?(0,Z.jsx)(oe,{}):(0,Z.jsx)(a,{})});export{ae as Layout,le as default,se as links,ce as meta};
@@ -0,0 +1 @@
1
+ import{a as e}from"./rolldown-runtime-BFRubm34.js";import{t}from"./react-CM_dJw1Z.js";import{t as n}from"./createLucideIcon-Ddu8jDOQ.js";import{n as r,r as i,t as a}from"./git-branch-DQS2nMK4.js";import{l as ee}from"./circle-plus-check-toggle-P7ZZToV4.js";import{_ as te,a as o,b as ne,c as re,d as ie,f as ae,g as oe,h as se,i as ce,l as le,m as ue,n as de,o as fe,p as s,r as c,s as l,t as u,u as d,v as f,x as p,y as m}from"./vendor~home~mcp~automations-list-DoPfwaXj.js";var h=n(`book-open`,[[`path`,{d:`M12 7v14`,key:`1akyts`}],[`path`,{d:`M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z`,key:`ruj8y`}]]),g=n(`brain`,[[`path`,{d:`M12 18V5`,key:`adv99a`}],[`path`,{d:`M15 13a4.17 4.17 0 0 1-3-4 4.17 4.17 0 0 1-3 4`,key:`1e3is1`}],[`path`,{d:`M17.598 6.5A3 3 0 1 0 12 5a3 3 0 1 0-5.598 1.5`,key:`1gqd8o`}],[`path`,{d:`M17.997 5.125a4 4 0 0 1 2.526 5.77`,key:`iwvgf7`}],[`path`,{d:`M18 18a4 4 0 0 0 2-7.464`,key:`efp6ie`}],[`path`,{d:`M19.967 17.483A4 4 0 1 1 12 18a4 4 0 1 1-7.967-.517`,key:`1gq6am`}],[`path`,{d:`M6 18a4 4 0 0 1-2-7.464`,key:`k1g0md`}],[`path`,{d:`M6.003 5.125a4 4 0 0 0-2.526 5.77`,key:`q97ue3`}]]),_=n(`clock`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`path`,{d:`M12 6v6l4 2`,key:`mmk7yg`}]]),v=n(`database`,[[`ellipse`,{cx:`12`,cy:`5`,rx:`9`,ry:`3`,key:`msslwz`}],[`path`,{d:`M3 5V19A9 3 0 0 0 21 19V5`,key:`1wlel7`}],[`path`,{d:`M3 12A9 3 0 0 0 21 12`,key:`mv7ke4`}]]),y=n(`flame`,[[`path`,{d:`M12 3q1 4 4 6.5t3 5.5a1 1 0 0 1-14 0 5 5 0 0 1 1-3 1 1 0 0 0 5 0c0-2-1.5-3-1.5-5q0-2 2.5-4`,key:`1slcih`}]]),b=n(`globe`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`path`,{d:`M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20`,key:`13o1zl`}],[`path`,{d:`M2 12h20`,key:`9i4pu4`}]]),x=n(`list-tree`,[[`path`,{d:`M8 5h13`,key:`1pao27`}],[`path`,{d:`M13 12h8`,key:`h98zly`}],[`path`,{d:`M13 19h8`,key:`c3s6r1`}],[`path`,{d:`M3 10a2 2 0 0 0 2 2h3`,key:`1npucw`}],[`path`,{d:`M3 5v12a2 2 0 0 0 2 2h3`,key:`x1gjn2`}]]),S=n(`mouse-pointer-click`,[[`path`,{d:`M14 4.1 12 6`,key:`ita8i4`}],[`path`,{d:`m5.1 8-2.9-.8`,key:`1go3kf`}],[`path`,{d:`m6 12-1.9 2`,key:`mnht97`}],[`path`,{d:`M7.2 2.2 8 5.1`,key:`1cfko1`}],[`path`,{d:`M9.037 9.69a.498.498 0 0 1 .653-.653l11 4.5a.5.5 0 0 1-.074.949l-4.349 1.041a1 1 0 0 0-.74.739l-1.04 4.35a.5.5 0 0 1-.95.074z`,key:`s0h3yz`}]]),C=n(`sparkles`,[[`path`,{d:`M11.017 2.814a1 1 0 0 1 1.966 0l1.051 5.558a2 2 0 0 0 1.594 1.594l5.558 1.051a1 1 0 0 1 0 1.966l-5.558 1.051a2 2 0 0 0-1.594 1.594l-1.051 5.558a1 1 0 0 1-1.966 0l-1.051-5.558a2 2 0 0 0-1.594-1.594l-5.558-1.051a1 1 0 0 1 0-1.966l5.558-1.051a2 2 0 0 0 1.594-1.594z`,key:`1s2grr`}],[`path`,{d:`M20 2v4`,key:`1rf3ol`}],[`path`,{d:`M22 4h-4`,key:`gwowj6`}],[`circle`,{cx:`4`,cy:`20`,r:`2`,key:`6kqj1y`}]]),w=n(`telescope`,[[`path`,{d:`m10.065 12.493-6.18 1.318a.934.934 0 0 1-1.108-.702l-.537-2.15a1.07 1.07 0 0 1 .691-1.265l13.504-4.44`,key:`k4qptu`}],[`path`,{d:`m13.56 11.747 4.332-.924`,key:`19l80z`}],[`path`,{d:`m16 21-3.105-6.21`,key:`7oh9d`}],[`path`,{d:`M16.485 5.94a2 2 0 0 1 1.455-2.425l1.09-.272a1 1 0 0 1 1.212.727l1.515 6.06a1 1 0 0 1-.727 1.213l-1.09.272a2 2 0 0 1-2.425-1.455z`,key:`m7xp4m`}],[`path`,{d:`m6.158 8.633 1.114 4.456`,key:`74o979`}],[`path`,{d:`m8 21 3.105-6.21`,key:`1fvxut`}],[`circle`,{cx:`12`,cy:`13`,r:`2`,key:`1c1ljs`}]]),T=n(`test-tube`,[[`path`,{d:`M14.5 2v17.5c0 1.4-1.1 2.5-2.5 2.5c-1.4 0-2.5-1.1-2.5-2.5V2`,key:`125lnx`}],[`path`,{d:`M8.5 2h7`,key:`csnxdl`}],[`path`,{d:`M14.5 16h-5`,key:`1ox875`}]]),E={id:`airtable`,name:`Airtable`,description:`List bases, query records, and update fields across your Airtable workspace.`,docsUrl:`https://github.com/domdomegg/airtable-mcp-server`,iconBg:`#FCB400`,iconColor:`var(--oh-surface-deep)`,keywords:[`spreadsheet`,`database`,`records`,`bases`],kind:`mcp`,defaultConnectionOptionId:`api`,connectionOptions:[{id:`api`,provider:`mcp`,transport:{kind:`stdio`,serverName:`airtable`,command:`npx`,args:[`-y`,`airtable-mcp-server`],envFields:[{key:`AIRTABLE_API_KEY`,label:`Airtable personal access token`,type:`password`,required:!0,helperText:`Personal access token from your Airtable account.`,helperLink:`https://airtable.com/create/tokens`}]},auth:{strategy:`api_key`}}]},D={id:`apify`,name:`Apify Actors`,description:`Run any of Apify's 5,000+ Actors (scrapers, automations) from the agent.`,docsUrl:`https://docs.apify.com/platform/integrations/mcp`,iconBg:`#10b981`,keywords:[`scraping`,`automation`,`crawl`,`actors`],kind:`mcp`,defaultConnectionOptionId:`api`,connectionOptions:[{id:`api`,provider:`mcp`,transport:{kind:`stdio`,serverName:`apify`,command:`npx`,args:[`-y`,`@apify/actors-mcp-server`],envFields:[{key:`APIFY_TOKEN`,label:`Apify token`,type:`password`,required:!0,helperText:`API token from your Apify account settings.`,helperLink:`https://console.apify.com/account/integrations`}]},auth:{strategy:`api_key`}}]},O={id:`atlassian`,name:`Atlassian (Jira & Confluence)`,description:`Search Jira issues and Confluence pages via Atlassian's hosted MCP server.`,docsUrl:`https://www.atlassian.com/platform/remote-mcp-server`,iconBg:`#0052CC`,keywords:[`jira`,`confluence`,`tickets`,`wiki`,`issues`],kind:`mcp`,defaultConnectionOptionId:`none`,connectionOptions:[{id:`none`,provider:`mcp`,transport:{kind:`sse`,url:`https://mcp.atlassian.com/v1/sse`,apiKeyOptional:!0},auth:{strategy:`none`,apiKeyOptional:!0}}]},k={id:`brave-search`,name:`Brave Search`,description:`Privacy-first web and local search using the Brave Search API.`,docsUrl:`https://github.com/brave/brave-search-mcp-server`,iconBg:`#FB542B`,keywords:[`search`,`web`],kind:`mcp`,defaultConnectionOptionId:`api`,connectionOptions:[{id:`api`,provider:`mcp`,transport:{kind:`stdio`,serverName:`brave_search`,command:`npx`,args:[`-y`,`@brave/brave-search-mcp-server`,`--transport`,`stdio`],envFields:[{key:`BRAVE_API_KEY`,label:`Brave API key`,type:`password`,required:!0,helperText:`API key from the Brave Search API portal.`,helperLink:`https://api-dashboard.search.brave.com/app/keys`}]},auth:{strategy:`api_key`}}]},A={id:`browser-mcp`,name:`Browser MCP`,description:`Control your local browser tab — navigate, click, type, and read DOM contents.`,docsUrl:`https://browsermcp.io/`,iconBg:`#0EA5E9`,keywords:[`browser`,`automation`,`chrome`,`playwright`],kind:`mcp`,runtimeAvailability:`local`,defaultConnectionOptionId:`none`,connectionOptions:[{id:`none`,provider:`mcp`,transport:{kind:`stdio`,serverName:`browser_mcp`,command:`npx`,args:[`-y`,`@browsermcp/mcp`]},auth:{strategy:`none`}}]},j={id:`clickhouse`,name:`ClickHouse`,description:`Run analytical SQL queries against a ClickHouse cluster.`,docsUrl:`https://github.com/ClickHouse/mcp-clickhouse`,iconBg:`#FFFF00`,iconColor:`var(--oh-surface-deep)`,keywords:[`analytics`,`olap`,`database`,`sql`],kind:`mcp`,defaultConnectionOptionId:`api`,connectionOptions:[{id:`api`,provider:`mcp`,transport:{kind:`stdio`,serverName:`clickhouse`,command:`uvx`,args:[`mcp-clickhouse`],envFields:[{key:`CLICKHOUSE_HOST`,label:`Host`,type:`text`,placeholder:`clickhouse.example.com`,required:!0},{key:`CLICKHOUSE_USER`,label:`Username`,type:`text`,required:!0},{key:`CLICKHOUSE_PASSWORD`,label:`Password`,type:`password`,required:!0,helperText:`Password for your ClickHouse user.`,helperLink:`https://clickhouse.com/docs/operations/access-rights`}]},auth:{strategy:`api_key`}}]},M={id:`cloudflare-bindings`,name:`Cloudflare Workers Bindings`,description:`Inspect and manage KV, D1, R2, and Durable Object bindings on your Cloudflare account.`,docsUrl:`https://developers.cloudflare.com/agents/model-context-protocol/`,iconBg:`#F38020`,keywords:[`cloudflare`,`workers`,`kv`,`d1`,`r2`,`durable objects`],kind:`mcp`,defaultConnectionOptionId:`none`,connectionOptions:[{id:`none`,provider:`mcp`,transport:{kind:`sse`,url:`https://bindings.mcp.cloudflare.com/sse`,apiKeyOptional:!0},auth:{strategy:`none`,apiKeyOptional:!0}}]},N={id:`cloudflare-browser-rendering`,name:`Cloudflare Browser Rendering`,description:`Fetch and screenshot pages using Cloudflare's hosted browser rendering.`,docsUrl:`https://developers.cloudflare.com/agents/model-context-protocol/`,iconBg:`#F38020`,keywords:[`cloudflare`,`browser`,`rendering`,`screenshots`],kind:`mcp`,defaultConnectionOptionId:`none`,connectionOptions:[{id:`none`,provider:`mcp`,transport:{kind:`sse`,url:`https://browser.mcp.cloudflare.com/sse`,apiKeyOptional:!0},auth:{strategy:`none`,apiKeyOptional:!0}}]},P={id:`cloudflare-builds`,name:`Cloudflare Builds`,description:`Inspect Workers Builds — logs, statuses, and rerun failed deploys.`,docsUrl:`https://developers.cloudflare.com/agents/model-context-protocol/`,iconBg:`#F38020`,keywords:[`cloudflare`,`workers`,`ci`,`builds`,`deploys`],kind:`mcp`,defaultConnectionOptionId:`none`,connectionOptions:[{id:`none`,provider:`mcp`,transport:{kind:`sse`,url:`https://builds.mcp.cloudflare.com/sse`,apiKeyOptional:!0},auth:{strategy:`none`,apiKeyOptional:!0}}]},F={id:`cloudflare-docs`,name:`Cloudflare Docs`,description:`Search and reference Cloudflare's developer documentation directly from the agent.`,docsUrl:`https://developers.cloudflare.com/agents/model-context-protocol/`,iconBg:`#F38020`,keywords:[`cloudflare`,`docs`,`reference`,`workers`],kind:`mcp`,defaultConnectionOptionId:`none`,connectionOptions:[{id:`none`,provider:`mcp`,transport:{kind:`sse`,url:`https://docs.mcp.cloudflare.com/sse`,apiKeyOptional:!0},auth:{strategy:`none`,apiKeyOptional:!0}}]},I={id:`cloudflare-observability`,name:`Cloudflare Observability`,description:`Tail Workers logs and query observability data from your Cloudflare account.`,docsUrl:`https://developers.cloudflare.com/agents/model-context-protocol/`,iconBg:`#F38020`,keywords:[`cloudflare`,`logs`,`tail`,`observability`,`workers`],kind:`mcp`,defaultConnectionOptionId:`none`,connectionOptions:[{id:`none`,provider:`mcp`,transport:{kind:`sse`,url:`https://observability.mcp.cloudflare.com/sse`,apiKeyOptional:!0},auth:{strategy:`none`,apiKeyOptional:!0}}]},L={id:`deepwiki`,name:`DeepWiki`,description:`Ask grounded questions about any public GitHub repository via Devin's DeepWiki MCP.`,docsUrl:`https://docs.devin.ai/work-with-devin/deepwiki-mcp`,iconBg:`var(--oh-color-base)`,keywords:[`devin`,`code`,`wiki`,`github`,`docs`,`qa`],kind:`mcp`,defaultConnectionOptionId:`none`,connectionOptions:[{id:`none`,provider:`mcp`,transport:{kind:`sse`,url:`https://mcp.deepwiki.com/sse`,apiKeyOptional:!0},auth:{strategy:`none`,apiKeyOptional:!0}}]},R={id:`elevenlabs`,name:`ElevenLabs`,description:`Generate speech, clone voices, and transcribe audio via ElevenLabs.`,docsUrl:`https://elevenlabs.io/docs/api-reference/mcp`,iconBg:`var(--oh-color-base)`,keywords:[`tts`,`speech`,`voice`,`audio`],kind:`mcp`,defaultConnectionOptionId:`api`,connectionOptions:[{id:`api`,provider:`mcp`,transport:{kind:`stdio`,serverName:`elevenlabs`,command:`uvx`,args:[`elevenlabs-mcp`],envFields:[{key:`ELEVENLABS_API_KEY`,label:`ElevenLabs API key`,type:`password`,required:!0,helperText:`API key from your ElevenLabs account settings.`,helperLink:`https://elevenlabs.io/app/settings/api-keys`}]},auth:{strategy:`api_key`}}]},z={id:`everything`,name:`Everything (demo)`,description:`Reference server exercising every MCP capability — useful for testing.`,docsUrl:`https://github.com/modelcontextprotocol/servers/tree/main/src/everything`,iconBg:`#6366F1`,keywords:[`demo`,`test`,`reference`],kind:`mcp`,defaultConnectionOptionId:`none`,connectionOptions:[{id:`none`,provider:`mcp`,transport:{kind:`stdio`,serverName:`everything`,command:`npx`,args:[`-y`,`@modelcontextprotocol/server-everything`]},auth:{strategy:`none`}}]},B={id:`exa`,name:`Exa`,description:`Neural web search with semantic ranking, content extraction, and similar-page lookup.`,docsUrl:`https://docs.exa.ai/reference/exa-mcp`,iconBg:`var(--oh-surface)`,keywords:[`search`,`web`,`research`,`neural`],kind:`mcp`,defaultConnectionOptionId:`api`,connectionOptions:[{id:`api`,provider:`mcp`,transport:{kind:`stdio`,serverName:`exa`,command:`npx`,args:[`-y`,`exa-mcp-server`],envFields:[{key:`EXA_API_KEY`,label:`Exa API key`,type:`password`,required:!0,helperText:`API key from your Exa account.`,helperLink:`https://exa.ai/docs/reference/getting-started`}]},auth:{strategy:`api_key`}}]},V={id:`fetch`,name:`Fetch`,description:`Plain HTTP fetcher: download a URL and convert HTML to readable markdown.`,docsUrl:`https://github.com/modelcontextprotocol/servers/tree/main/src/fetch`,iconBg:`var(--oh-interactive-hover)`,keywords:[`http`,`web`,`url`,`scrape`],kind:`mcp`,defaultConnectionOptionId:`none`,connectionOptions:[{id:`none`,provider:`mcp`,transport:{kind:`stdio`,serverName:`fetch`,command:`uvx`,args:[`mcp-server-fetch`]},auth:{strategy:`none`}}]},pe={id:`figma`,name:`Figma`,description:`Read Figma frames, components, and styles to ground UI work in your designs.`,docsUrl:`https://github.com/GLips/Figma-Context-MCP`,iconBg:`var(--oh-surface)`,keywords:[`design`,`ui`,`frames`,`components`],kind:`mcp`,defaultConnectionOptionId:`api`,connectionOptions:[{id:`api`,provider:`mcp`,transport:{kind:`stdio`,serverName:`figma`,command:`npx`,args:[`-y`,`figma-developer-mcp`,`--stdio`],envFields:[{key:`FIGMA_API_KEY`,label:`Figma personal access token`,type:`password`,required:!0,helperText:`Personal access token from your Figma account settings.`,helperLink:`https://developers.figma.com/docs/rest-api/authentication/#personal-access-tokens`}]},auth:{strategy:`api_key`}}]},me={id:`filesystem`,name:`Filesystem`,description:`Give the agent secure, scoped filesystem access outside the workspace.`,docsUrl:`https://github.com/modelcontextprotocol/servers/tree/main/src/filesystem`,iconBg:`var(--oh-interactive-hover)`,keywords:[`files`,`local`,`disk`],installHint:`Each path is exposed read/write. Add as many as you need, separated by spaces.`,kind:`mcp`,runtimeAvailability:`local`,defaultConnectionOptionId:`api`,connectionOptions:[{id:`api`,provider:`mcp`,transport:{kind:`stdio`,serverName:`filesystem`,command:`npx`,args:[`-y`,`@modelcontextprotocol/server-filesystem`],argFields:[{key:`paths`,label:`Paths (space separated)`,type:`text`,placeholder:`/Users/me/Documents /Users/me/Projects`,required:!0,helperText:`Each whitespace-separated token is appended as its own argument.`}]},auth:{strategy:`api_key`}}]},he={id:`firecrawl`,name:`Firecrawl`,description:`Crawl any site and return clean markdown, structured data, or screenshots.`,docsUrl:`https://docs.firecrawl.dev/mcp`,iconBg:`#F97316`,keywords:[`scraping`,`crawl`,`web`,`markdown`],kind:`mcp`,defaultConnectionOptionId:`api`,connectionOptions:[{id:`api`,provider:`mcp`,transport:{kind:`stdio`,serverName:`firecrawl`,command:`npx`,args:[`-y`,`firecrawl-mcp`],envFields:[{key:`FIRECRAWL_API_KEY`,label:`Firecrawl API key`,type:`password`,required:!0,helperText:`API key from your Firecrawl dashboard.`,helperLink:`https://www.firecrawl.dev/app/api-keys`}]},auth:{strategy:`api_key`}}]},ge={id:`git`,name:`Git`,description:`Local git repository operations: log, diff, blame, status, and more.`,docsUrl:`https://github.com/modelcontextprotocol/servers/tree/main/src/git`,iconBg:`#F1502F`,keywords:[`version control`,`log`,`diff`,`blame`],installHint:`Runs the official Python server via uvx — no setup beyond the path.`,kind:`mcp`,runtimeAvailability:`local`,defaultConnectionOptionId:`api`,connectionOptions:[{id:`api`,provider:`mcp`,transport:{kind:`stdio`,serverName:`git`,command:`uvx`,args:[`mcp-server-git`,`--repository`],argFields:[{key:`repo_path`,label:`Repository path`,type:`text`,placeholder:`/Users/me/code/my-repo`,required:!0,helperText:`Appended as --repository <path>.`}]},auth:{strategy:`api_key`}}]},_e={id:`github`,name:`GitHub`,description:`Search code, manage issues and pull requests, and inspect repos via the GitHub API.`,docsUrl:`https://github.com/github/github-mcp-server`,iconBg:`var(--oh-surface)`,keywords:[`git`,`pr`,`repo`,`issues`,`code`],popularityRank:100,installHint:`Requires Docker because the legacy npm package was deprecated upstream.`,kind:`mcp`,defaultConnectionOptionId:`api`,connectionOptions:[{id:`api`,provider:`mcp`,transport:{kind:`stdio`,serverName:`github`,command:`docker`,args:[`run`,`-i`,`--rm`,`-e`,`GITHUB_PERSONAL_ACCESS_TOKEN`,`ghcr.io/github/github-mcp-server`],envFields:[{key:`GITHUB_PERSONAL_ACCESS_TOKEN`,label:`Personal access token`,type:`password`,placeholder:`github_pat_...`,required:!0,helperText:`Classic or fine-grained personal access token from GitHub settings.`,helperLink:`https://github.com/settings/tokens`}]},auth:{strategy:`api_key`}}]},ve={id:`huggingface`,name:`Hugging Face`,description:`Search models, datasets, and Spaces on the Hugging Face Hub from your agent.`,docsUrl:`https://huggingface.co/docs/huggingface_hub/en/guides/mcp`,iconBg:`#FFD21E`,iconColor:`#000000`,keywords:[`ml`,`models`,`datasets`,`ai`,`hub`],kind:`mcp`,defaultConnectionOptionId:`none`,connectionOptions:[{id:`none`,provider:`mcp`,transport:{kind:`shttp`,url:`https://huggingface.co/mcp`,apiKeyOptional:!0},auth:{strategy:`none`,apiKeyOptional:!0}}]},ye={id:`kagi`,name:`Kagi Search`,description:`Paid, privacy-first search with high signal-to-noise — great for research.`,docsUrl:`https://github.com/kagisearch/kagimcp`,iconBg:`#FFB319`,iconColor:`var(--oh-surface-deep)`,keywords:[`search`,`web`,`privacy`],kind:`mcp`,defaultConnectionOptionId:`api`,connectionOptions:[{id:`api`,provider:`mcp`,transport:{kind:`stdio`,serverName:`kagi`,command:`uvx`,args:[`kagimcp`],envFields:[{key:`KAGI_API_KEY`,label:`Kagi API key`,type:`password`,required:!0,helperText:`API key from your Kagi account settings.`,helperLink:`https://kagi.com/settings?p=api`}]},auth:{strategy:`api_key`}}]},be={id:`linear`,name:`Linear`,description:`Browse and update Linear issues, cycles, and projects from the agent.`,docsUrl:`https://linear.app/changelog/2025-05-01-mcp`,iconBg:`#5E6AD2`,keywords:[`issues`,`project management`,`tasks`,`tickets`],popularityRank:86,installHint:`Linear's hosted MCP server uses your Linear OAuth login — no key required.`,kind:`mcp`,defaultConnectionOptionId:`none`,connectionOptions:[{id:`none`,provider:`mcp`,transport:{kind:`sse`,url:`https://mcp.linear.app/sse`,apiKeyOptional:!0},auth:{strategy:`none`,apiKeyOptional:!0}}]},xe={id:`memory`,name:`Memory`,description:`Persistent key-value memory for the agent across conversations.`,docsUrl:`https://github.com/modelcontextprotocol/servers/tree/main/src/memory`,iconBg:`#7C3AED`,keywords:[`memory`,`kv`,`state`,`persistence`],kind:`mcp`,defaultConnectionOptionId:`none`,connectionOptions:[{id:`none`,provider:`mcp`,transport:{kind:`stdio`,serverName:`memory`,command:`npx`,args:[`-y`,`@modelcontextprotocol/server-memory`]},auth:{strategy:`none`}}]},Se={id:`mongodb`,name:`MongoDB`,description:`Query MongoDB collections, inspect schemas, and run aggregation pipelines.`,docsUrl:`https://www.mongodb.com/docs/mcp-server/`,iconBg:`#00684A`,keywords:[`database`,`nosql`,`atlas`],kind:`mcp`,defaultConnectionOptionId:`api`,connectionOptions:[{id:`api`,provider:`mcp`,transport:{kind:`stdio`,serverName:`mongodb`,command:`npx`,args:[`-y`,`mongodb-mcp-server`],envFields:[{key:`MDB_MCP_CONNECTION_STRING`,label:`MongoDB connection string`,type:`password`,placeholder:`mongodb+srv://user:pass@cluster.mongodb.net`,required:!0,helperText:`Connection string from your MongoDB Atlas cluster.`,helperLink:`https://www.mongodb.com/docs/atlas/connect-to-database-deployment/#connect-with-a-connection-string`}]},auth:{strategy:`api_key`}}]},Ce={id:`neon`,name:`Neon`,description:`Serverless Postgres: list projects, run queries, manage branches.`,docsUrl:`https://neon.com/docs/ai/neon-mcp-server`,iconBg:`#00E599`,iconColor:`var(--oh-surface-deep)`,keywords:[`database`,`postgres`,`serverless`],kind:`mcp`,defaultConnectionOptionId:`api`,connectionOptions:[{id:`api`,provider:`mcp`,transport:{kind:`stdio`,serverName:`neon`,command:`npx`,args:[`-y`,`@neondatabase/mcp-server-neon`,`start`],envFields:[{key:`NEON_API_KEY`,label:`Neon API key`,type:`password`,required:!0,helperText:`API key from your Neon account settings.`,helperLink:`https://neon.tech/docs/manage/api-keys`}]},auth:{strategy:`api_key`}}]},we={id:`notion`,name:`Notion`,description:`Read and edit Notion pages, databases, and blocks via Notion's MCP server.`,docsUrl:`https://developers.notion.com/docs/mcp`,iconBg:`#FFFFFF`,iconColor:`#000000`,keywords:[`docs`,`notes`,`wiki`,`knowledge base`],popularityRank:82,kind:`mcp`,defaultConnectionOptionId:`api`,connectionOptions:[{id:`api`,provider:`mcp`,transport:{kind:`stdio`,serverName:`notion`,command:`npx`,args:[`-y`,`@notionhq/notion-mcp-server`],envFields:[{key:`NOTION_API_KEY`,label:`Internal integration token`,type:`password`,placeholder:`ntn_...`,required:!0,helperText:`Internal integration token from your Notion integrations page.`,helperLink:`https://www.notion.so/profile/integrations`}]},auth:{strategy:`api_key`}}]},Te={id:`obsidian`,name:`Obsidian`,description:`Read and edit Markdown notes inside an Obsidian vault on the local disk.`,docsUrl:`https://github.com/MarkusPfundstein/mcp-obsidian`,iconBg:`#7C3AED`,keywords:[`notes`,`knowledge`,`markdown`,`vault`],kind:`mcp`,runtimeAvailability:`local`,defaultConnectionOptionId:`api`,connectionOptions:[{id:`api`,provider:`mcp`,transport:{kind:`stdio`,serverName:`obsidian`,command:`uvx`,args:[`mcp-obsidian`],envFields:[{key:`OBSIDIAN_API_KEY`,label:`Local REST API key`,type:`password`,required:!0,helperText:`From the Obsidian 'Local REST API' community plugin.`,helperLink:`https://github.com/coddingtonbear/obsidian-local-rest-api`}]},auth:{strategy:`api_key`}}]},Ee={id:`paypal`,name:`PayPal`,description:`Manage transactions and merchant data via PayPal's MCP server.`,docsUrl:`https://developer.paypal.com/tools/mcp-server/`,iconBg:`#003087`,keywords:[`payments`,`billing`,`finance`],kind:`mcp`,defaultConnectionOptionId:`none`,connectionOptions:[{id:`none`,provider:`mcp`,transport:{kind:`sse`,url:`https://mcp.paypal.com/sse`,apiKeyOptional:!0},auth:{strategy:`none`,apiKeyOptional:!0}}]},De={id:`playwright`,name:`Playwright`,description:`Headless-browser automation backed by Microsoft Playwright.`,docsUrl:`https://github.com/microsoft/playwright-mcp`,iconBg:`#2EAD33`,keywords:[`browser`,`automation`,`e2e`,`testing`,`scrape`],kind:`mcp`,defaultConnectionOptionId:`none`,connectionOptions:[{id:`none`,provider:`mcp`,transport:{kind:`stdio`,serverName:`playwright`,command:`npx`,args:[`-y`,`@playwright/mcp`]},auth:{strategy:`none`}}]},Oe={id:`redis`,name:`Redis`,description:`Get, set, scan, and inspect data on a Redis or Redis-compatible instance.`,docsUrl:`https://github.com/redis/mcp-redis`,iconBg:`#DC382D`,keywords:[`cache`,`kv`,`database`],kind:`mcp`,runtimeAvailability:`local`,defaultConnectionOptionId:`api`,connectionOptions:[{id:`api`,provider:`mcp`,transport:{kind:`stdio`,serverName:`redis`,command:`uvx`,args:[`--from`,`redis-mcp-server@latest`,`redis-mcp-server`,`--url`],argFields:[{key:`redis_url`,label:`Redis URL`,type:`password`,placeholder:`redis://localhost:6379`,required:!0,helperText:`Connection URL for your Redis instance. Appended as --url <redis_url>.`,helperLink:`https://redis.io/docs/latest/operate/rc/databases/connect/`}]},auth:{strategy:`api_key`}}]},ke={id:`resend`,name:`Resend`,description:`Send transactional and marketing emails via the Resend API.`,docsUrl:`https://resend.com/docs/mcp`,iconBg:`var(--oh-surface-deep)`,keywords:[`email`,`transactional`,`smtp`],kind:`mcp`,defaultConnectionOptionId:`api`,connectionOptions:[{id:`api`,provider:`mcp`,transport:{kind:`stdio`,serverName:`resend`,command:`npx`,args:[`-y`,`mcp-send-email`],envFields:[{key:`RESEND_API_KEY`,label:`Resend API key`,type:`password`,required:!0,helperText:`API key from your Resend dashboard.`,helperLink:`https://resend.com/api-keys`},{key:`SENDER_EMAIL_ADDRESS`,label:`From address`,type:`text`,placeholder:`you@example.com`,required:!0}]},auth:{strategy:`api_key`}}]},Ae={id:`sentry`,name:`Sentry`,description:`Triage issues, inspect events, and run Seer fixes against your Sentry org.`,docsUrl:`https://docs.sentry.io/product/sentry-mcp/`,iconBg:`#362D59`,keywords:[`errors`,`observability`,`monitoring`,`crash`],kind:`mcp`,defaultConnectionOptionId:`none`,connectionOptions:[{id:`none`,provider:`mcp`,transport:{kind:`shttp`,url:`https://mcp.sentry.dev/mcp`,apiKeyOptional:!0},auth:{strategy:`none`,apiKeyOptional:!0}}]},je={id:`sequential-thinking`,name:`Sequential Thinking`,description:`Lets the agent emit and revise a chain of structured thoughts.`,docsUrl:`https://github.com/modelcontextprotocol/servers/tree/main/src/sequentialthinking`,iconBg:`var(--oh-color-base)`,keywords:[`reasoning`,`planning`,`thoughts`],kind:`mcp`,defaultConnectionOptionId:`none`,connectionOptions:[{id:`none`,provider:`mcp`,transport:{kind:`stdio`,serverName:`sequential_thinking`,command:`npx`,args:[`-y`,`@modelcontextprotocol/server-sequential-thinking`]},auth:{strategy:`none`}}]},Me={id:`slack`,name:`Slack`,description:`Read channels, post messages, and search workspace history from your agent.`,docsUrl:`https://github.com/zencoderai/slack-mcp-server`,iconBg:`#4A154B`,keywords:[`chat`,`messaging`,`team`],popularityRank:95,installHint:`Create a Slack app with the required scopes, then paste its bot token below.`,kind:`mcp`,defaultConnectionOptionId:`api`,connectionOptions:[{id:`api`,provider:`mcp`,transport:{kind:`stdio`,serverName:`slack`,command:`npx`,args:[`-y`,`@zencoderai/slack-mcp-server`],envFields:[{key:`SLACK_TEAM_ID`,label:`Team / Workspace ID`,type:`text`,placeholder:`T01234567`,helperText:`First get your [Slack URL](https://slack.com/help/articles/221769328-Locate-your-Slack-URL-or-ID#find-your-url). Then use that to get your [Workspace ID](https://slack.com/help/articles/221769328-Locate-your-Slack-URL-or-ID#find-your-workspace-or-org-id).`,required:!0},{key:`SLACK_BOT_TOKEN`,label:`Bot token`,type:`password`,placeholder:`xoxb-...`,required:!0,helperText:`You'll need to create or have access to a [Slack App](https://github.com/zencoderai/slack-mcp-server#slack-bot-setup) to get a Bot token.`}]},auth:{strategy:`api_key`}}]},Ne={id:`stripe`,name:`Stripe`,description:`Query customers, payments, subscriptions, and invoices via Stripe's hosted MCP server.`,docsUrl:`https://stripe.com/docs/mcp`,iconBg:`#635BFF`,keywords:[`payments`,`billing`,`subscriptions`,`finance`],kind:`mcp`,defaultConnectionOptionId:`none`,connectionOptions:[{id:`none`,provider:`mcp`,transport:{kind:`shttp`,url:`https://mcp.stripe.com/`,apiKeyOptional:!0},auth:{strategy:`none`,apiKeyOptional:!0}}]},Pe={id:`supabase`,name:`Supabase`,description:`Query and manage your Supabase project, including database, auth, and storage.`,docsUrl:`https://supabase.com/docs/guides/getting-started/mcp`,iconBg:`#3ECF8E`,keywords:[`database`,`auth`,`storage`,`postgres`],kind:`mcp`,defaultConnectionOptionId:`api`,connectionOptions:[{id:`api`,provider:`mcp`,transport:{kind:`stdio`,serverName:`supabase`,command:`npx`,args:[`-y`,`@supabase/mcp-server-supabase@latest`],envFields:[{key:`SUPABASE_ACCESS_TOKEN`,label:`Supabase access token`,type:`password`,required:!0,helperText:`Personal access token from your Supabase dashboard.`,helperLink:`https://supabase.com/dashboard/account/tokens`}]},auth:{strategy:`api_key`}}]},Fe={id:`tavily`,name:`Tavily`,description:`Production-grade web search optimized for LLM agents. Free tier available.`,docsUrl:`https://github.com/tavily-ai/tavily-mcp`,iconBg:`#2563EB`,keywords:[`search`,`web`,`browsing`,`research`],popularityRank:90,installHint:`Paste your Tavily API key - the official tavily-mcp package runs via npx.`,kind:`mcp`,defaultConnectionOptionId:`api`,connectionOptions:[{id:`api`,provider:`mcp`,transport:{kind:`stdio`,serverName:`tavily`,command:`npx`,args:[`-y`,`tavily-mcp`],envFields:[{key:`TAVILY_API_KEY`,label:`Tavily API key`,type:`password`,placeholder:`tvly-...`,required:!0,helperText:`API key from your Tavily dashboard.`,helperLink:`https://app.tavily.com/home?tab=keys`}]},auth:{strategy:`api_key`}}]},Ie={id:`time`,name:`Time`,description:`Timezone-aware current time, conversions, and timestamp formatting.`,docsUrl:`https://github.com/modelcontextprotocol/servers/tree/main/src/time`,iconBg:`var(--oh-surface)`,keywords:[`clock`,`timezone`,`date`],kind:`mcp`,defaultConnectionOptionId:`none`,connectionOptions:[{id:`none`,provider:`mcp`,transport:{kind:`stdio`,serverName:`time`,command:`uvx`,args:[`mcp-server-time`]},auth:{strategy:`none`}}]},Le=`https://accounts.google.com/o/oauth2/v2/auth`,Re=`https://oauth2.googleapis.com/token`,ze=`https://login.microsoftonline.com/common/oauth2/v2.0/authorize`,Be=`https://login.microsoftonline.com/common/oauth2/v2.0/token`,Ve=`https://auth.atlassian.com/authorize`,He=`https://auth.atlassian.com/oauth/token`,H=(e,t,n,r,i,a=`GET`)=>({apiBaseUrl:e,authorizationUrl:Le,tokenUrl:Re,scopes:t,toolName:n,toolDescription:r,requestMethod:a,requestPath:i}),U=(e,t,n,r)=>({apiBaseUrl:`https://graph.microsoft.com/v1.0`,authorizationUrl:ze,tokenUrl:Be,scopes:e,toolName:t,toolDescription:n,requestMethod:`GET`,requestPath:r}),W=(e,t,n,r,i)=>({apiBaseUrl:e,authorizationUrl:Ve,tokenUrl:He,scopes:t,toolName:n,toolDescription:r,requestMethod:`GET`,requestPath:i}),G=`https://mcp.hubspot.com`,Ue=`${G}/oauth/authorize/user`,We=`${G}/oauth/v3/token`,Ge={github:`https://api.githubcopilot.com/mcp/`,hubspot:G,slack:`https://mcp.slack.com/mcp`,webflow:`https://mcp.webflow.com/mcp`,datadog:`https://mcp.datadoghq.com/api/unstable/mcp-server/mcp`,ordinal:`https://app.tryordinal.com/api/mcp`},Ke={github:{apiBaseUrl:`https://api.github.com`,authorizationUrl:`https://github.com/login/oauth/authorize`,tokenUrl:`https://github.com/login/oauth/access_token`,scopes:[`read:user`,`repo`],toolName:`get_authenticated_user`,toolDescription:`Fetch the authenticated GitHub user profile.`,requestMethod:`GET`,requestPath:`/user`},"google-docs":H(`https://docs.googleapis.com`,[`https://www.googleapis.com/auth/documents.readonly`],`get_document`,`Fetch a Google Docs document by ID.`,`/v1/documents/{documentId}`),slack:{provider:`mcp`,authorizationUrl:`https://slack.com/oauth/v2_user/authorize`,tokenUrl:`https://slack.com/api/oauth.v2.user.access`,scopes:[`search:read.public`,`search:read.private`,`search:read.mpim`,`search:read.im`,`search:read.files`,`search:read.users`,`chat:write`,`channels:history`,`groups:history`,`mpim:history`,`im:history`,`canvases:read`,`canvases:write`,`users:read`,`users:read.email`],pkce:!0,clientAuthentication:`body`},notion:{provider:`http`,apiBaseUrl:`https://api.notion.com`,openApiUrl:`https://developers.notion.com/openapi.json`,authorizationUrl:`https://api.notion.com/v1/oauth/authorize`,tokenUrl:`https://api.notion.com/v1/oauth/token`,scopes:[],toolName:`post_search`,toolDescription:`Search pages and databases in the connected Notion workspace.`,requestMethod:`POST`,requestPath:`/v1/search`},figma:{apiBaseUrl:`https://api.figma.com`,authorizationUrl:`https://www.figma.com/oauth`,tokenUrl:`https://api.figma.com/v1/oauth/token`,scopes:[`current_user:read`,`file_content:read`,`file_metadata:read`,`projects:read`],toolName:`get_file`,toolDescription:`Fetch a Figma file by key.`,requestMethod:`GET`,requestPath:`/v1/files/{fileKey}`},elevenlabs:{provider:`http`,authModes:[`api_key`],authStrategy:`api_key`,credentialLabel:`ElevenLabs API key`,credentialPlaceholder:`Paste your ElevenLabs API key`,credentialHelp:`Personal or workspace ElevenLabs API key sent in the xi-api-key header.`,apiKeyHeaderName:`xi-api-key`,apiBaseUrl:`https://api.elevenlabs.io`,openApiUrl:`https://api.elevenlabs.io/openapi.json`},"google-drive":H(`https://www.googleapis.com/drive/v3`,[`https://www.googleapis.com/auth/drive.metadata.readonly`],`list_files`,`List Drive files visible to the connected user.`,`/files`),"google-sheets":H(`https://sheets.googleapis.com`,[`https://www.googleapis.com/auth/spreadsheets.readonly`],`get_spreadsheet`,`Fetch spreadsheet metadata and sheets by ID.`,`/v4/spreadsheets/{spreadsheetId}`),gmail:H(`https://gmail.googleapis.com`,[`https://www.googleapis.com/auth/gmail.readonly`],`list_messages`,`List Gmail messages for the authenticated user.`,`/gmail/v1/users/me/messages`),"google-calendar":H(`https://www.googleapis.com/calendar/v3`,[`https://www.googleapis.com/auth/calendar.readonly`],`list_events`,`List events from the user's primary Google Calendar.`,`/calendars/primary/events`),jira:W(`https://api.atlassian.com/ex/jira/{cloudId}`,[`read:jira-work`],`list_projects`,`List Jira projects available to the connected user.`,`/rest/api/3/project/search`),confluence:W(`https://api.atlassian.com/ex/confluence/{cloudId}`,[`read:page:confluence`],`list_spaces`,`List Confluence spaces available to the connected user.`,`/wiki/api/v2/spaces`),linear:{apiBaseUrl:`https://api.linear.app`,authorizationUrl:`https://linear.app/oauth/authorize`,tokenUrl:`https://api.linear.app/oauth/token`,scopes:[`read`],toolName:`list_issues`,toolDescription:`Query issues from Linear via GraphQL.`,requestMethod:`POST`,requestPath:`/graphql`},asana:{apiBaseUrl:`https://app.asana.com/api/1.0`,authorizationUrl:`https://app.asana.com/-/oauth_authorize`,tokenUrl:`https://app.asana.com/-/oauth_token`,scopes:[`tasks:read`],toolName:`list_tasks`,toolDescription:`List tasks visible to the connected Asana user.`,requestMethod:`GET`,requestPath:`/tasks`},trello:{apiBaseUrl:`https://api.trello.com/1`,toolName:`list_boards`,toolDescription:`List Trello boards visible to the authenticated member.`,requestMethod:`GET`,requestPath:`/members/me/boards`},clickup:{apiBaseUrl:`https://api.clickup.com/api/v2`,authorizationUrl:`https://app.clickup.com/api`,tokenUrl:`https://api.clickup.com/api/v2/oauth/token`,scopes:[],toolName:`list_workspaces`,toolDescription:`List ClickUp workspaces available to the connected user.`,requestMethod:`GET`,requestPath:`/team`},monday:{apiBaseUrl:`https://api.monday.com/v2`,authorizationUrl:`https://auth.monday.com/oauth2/authorize`,tokenUrl:`https://auth.monday.com/oauth2/token`,scopes:[`boards:read`],toolName:`list_boards`,toolDescription:`Query boards from Monday.com.`,requestMethod:`POST`,requestPath:`/`},airtable:{apiBaseUrl:`https://api.airtable.com/v0`,authorizationUrl:`https://airtable.com/oauth2/v1/authorize`,tokenUrl:`https://airtable.com/oauth2/v1/token`,scopes:[`schema.bases:read`,`data.records:read`],toolName:`list_bases`,toolDescription:`List Airtable bases the connected user granted access to.`,requestMethod:`GET`,requestPath:`/meta/bases`},dropbox:{apiBaseUrl:`https://api.dropboxapi.com/2`,authorizationUrl:`https://www.dropbox.com/oauth2/authorize`,tokenUrl:`https://api.dropboxapi.com/oauth2/token`,scopes:[`files.metadata.read`],toolName:`list_root_folder`,toolDescription:`List entries in the root Dropbox folder.`,requestMethod:`POST`,requestPath:`/files/list_folder`},box:{apiBaseUrl:`https://api.box.com/2.0`,authorizationUrl:`https://account.box.com/api/oauth2/authorize`,tokenUrl:`https://api.box.com/oauth2/token`,scopes:[`root_readonly`,`item_read`],toolName:`list_root_items`,toolDescription:`List files and folders in the Box root folder.`,requestMethod:`GET`,requestPath:`/folders/0/items`},"microsoft-outlook":U([`Mail.Read`],`list_messages`,`List Outlook messages for the signed-in user.`,`/me/messages`),"microsoft-teams":U([`Team.ReadBasic.All`],`list_teams`,`List Microsoft Teams joined by the signed-in user.`,`/me/joinedTeams`),onedrive:U([`Files.Read`],`list_drive_items`,`List OneDrive items in the root folder.`,`/me/drive/root/children`),sharepoint:U([`Sites.Read.All`],`get_root_site`,`Fetch the SharePoint root site through Microsoft Graph.`,`/sites/root`),salesforce:{apiBaseUrl:`https://{instance}.salesforce.com/services/data/v60.0`,authorizationUrl:`https://login.salesforce.com/services/oauth2/authorize`,tokenUrl:`https://login.salesforce.com/services/oauth2/token`,scopes:[`api`],toolName:`list_accounts`,toolDescription:`List Salesforce accounts from the connected org.`,requestMethod:`GET`,requestPath:`/sobjects/Account`},hubspot:{provider:`mcp`,authorizationUrl:Ue,tokenUrl:We,clientAuthentication:`body`,pkce:!0,scopes:[],credentialHelp:`Use the client ID and secret from a HubSpot MCP auth app (Development → MCP Auth Apps). Standard HubSpot OAuth apps and private apps will not authenticate with mcp.hubspot.com.`},zendesk:{apiBaseUrl:`https://{subdomain}.zendesk.com/api/v2`,authorizationUrl:`https://{subdomain}.zendesk.com/oauth2/authorize`,tokenUrl:`https://{subdomain}.zendesk.com/oauth2/token`,scopes:[`tickets:read`],toolName:`list_tickets`,toolDescription:`List Zendesk tickets for the connected account.`,requestMethod:`GET`,requestPath:`/tickets`},intercom:{apiBaseUrl:`https://api.intercom.io`,authorizationUrl:`https://app.intercom.com/oauth`,tokenUrl:`https://api.intercom.io/auth/eagle/token`,scopes:[`read_users`,`read_conversations`],toolName:`list_contacts`,toolDescription:`List Intercom contacts for the connected workspace.`,requestMethod:`GET`,requestPath:`/contacts`},stripe:{apiBaseUrl:`https://api.stripe.com/v1`,authorizationUrl:`https://connect.stripe.com/oauth/authorize`,tokenUrl:`https://connect.stripe.com/oauth/token`,scopes:[`read_only`],toolName:`list_customers`,toolDescription:`List Stripe customers from the connected account.`,requestMethod:`GET`,requestPath:`/customers`},shopify:{apiBaseUrl:`https://{shop}.myshopify.com/admin/api/2025-01`,authorizationUrl:`https://{shop}.myshopify.com/admin/oauth/authorize`,tokenUrl:`https://{shop}.myshopify.com/admin/oauth/access_token`,scopes:[`read_products`],toolName:`list_products`,toolDescription:`List Shopify products for the connected store.`,requestMethod:`GET`,requestPath:`/products.json`},discord:{apiBaseUrl:`https://discord.com/api/v10`,authorizationUrl:`https://discord.com/oauth2/authorize`,tokenUrl:`https://discord.com/api/oauth2/token`,scopes:[`identify`,`guilds`],toolName:`list_guilds`,toolDescription:`List Discord guilds available to the connected user.`,requestMethod:`GET`,requestPath:`/users/@me/guilds`},zoom:{apiBaseUrl:`https://api.zoom.us/v2`,authorizationUrl:`https://zoom.us/oauth/authorize`,tokenUrl:`https://zoom.us/oauth/token`,scopes:[`meeting:read:user`],toolName:`list_meetings`,toolDescription:`List Zoom meetings for the connected user.`,requestMethod:`GET`,requestPath:`/users/me/meetings`},webflow:{provider:`mcp`,authorizationUrl:`https://mcp.webflow.com/oauth/authorize`,tokenUrl:`https://mcp.webflow.com/oauth/token`,registrationUrl:`https://mcp.webflow.com/oauth/register`,clientAuthentication:`none`,pkce:!0,scopes:[]},miro:{apiBaseUrl:`https://api.miro.com/v2`,authorizationUrl:`https://miro.com/oauth/authorize`,tokenUrl:`https://api.miro.com/v1/oauth/token`,scopes:[`boards:read`],toolName:`list_boards`,toolDescription:`List Miro boards available to the connected user.`,requestMethod:`GET`,requestPath:`/boards`},canva:{apiBaseUrl:`https://api.canva.com/rest/v1`,tokenUrl:`https://api.canva.com/rest/v1/oauth/token`,scopes:[],toolName:`list_designs`,toolDescription:`List Canva designs available to the connected user.`,requestMethod:`GET`,requestPath:`/designs`},datadog:{provider:`mcp`,authorizationUrl:`https://app.datadoghq.com/oauth2/v1/authorize`,tokenUrl:`https://api.datadoghq.com/oauth2/v1/token`,scopes:[`dashboards_read`,`monitors_read`]},sentry:{apiBaseUrl:`https://sentry.io/api/0`,authorizationUrl:`https://sentry.io/oauth/authorize`,tokenUrl:`https://sentry.io/oauth/token`,scopes:[`project:read`,`event:read`,`org:read`],toolName:`list_organizations`,toolDescription:`List Sentry organizations available to the connected user.`,requestMethod:`GET`,requestPath:`/organizations/`},posthog:{apiBaseUrl:`https://us.posthog.com/api`,authorizationUrl:`https://us.posthog.com/oauth/authorize`,tokenUrl:`https://us.posthog.com/oauth/token`,scopes:[`project:read`],toolName:`list_projects`,toolDescription:`List PostHog projects available to the connected user.`,requestMethod:`GET`,requestPath:`/projects/`},supabase:{apiBaseUrl:`https://api.supabase.com/v1`,authorizationUrl:`https://api.supabase.com/v1/oauth/authorize`,tokenUrl:`https://api.supabase.com/v1/oauth/token`,scopes:[],toolName:`list_projects`,toolDescription:`List Supabase projects available to the connected user.`,requestMethod:`GET`,requestPath:`/projects`},vercel:{apiBaseUrl:`https://api.vercel.com`,authorizationUrl:`https://vercel.com/oauth/authorize`,tokenUrl:`https://api.vercel.com/v2/oauth/access_token`,scopes:[`project:read`],toolName:`list_projects`,toolDescription:`List Vercel projects available to the connected user.`,requestMethod:`GET`,requestPath:`/v9/projects`},netlify:{apiBaseUrl:`https://api.netlify.com/api/v1`,authorizationUrl:`https://app.netlify.com/authorize`,tokenUrl:`https://api.netlify.com/oauth/token`,scopes:[`sites:read`],toolName:`list_sites`,toolDescription:`List Netlify sites available to the connected user.`,requestMethod:`GET`,requestPath:`/sites`},plaid:{apiBaseUrl:`https://production.plaid.com`,toolName:`get_accounts`,toolDescription:`Fetch accounts for a connected Plaid item.`,requestMethod:`POST`,requestPath:`/accounts/get`},okta:{apiBaseUrl:`https://{yourOktaDomain}/api/v1`,authorizationUrl:`https://{yourOktaDomain}/oauth2/v1/authorize`,tokenUrl:`https://{yourOktaDomain}/oauth2/v1/token`,scopes:[`okta.users.read`],toolName:`list_users`,toolDescription:`List Okta users for the connected org.`,requestMethod:`GET`,requestPath:`/users`},servicenow:{apiBaseUrl:`https://{instance}.service-now.com/api/now/v1`,authorizationUrl:`https://{instance}.service-now.com/oauth_auth.do`,tokenUrl:`https://{instance}.service-now.com/oauth_token.do`,scopes:[`useraccount`,`table.read`],toolName:`list_incidents`,toolDescription:`List ServiceNow incidents for the connected instance.`,requestMethod:`GET`,requestPath:`/table/incident`},freshdesk:{apiBaseUrl:`https://{domain}.freshdesk.com/api/v2`,authorizationUrl:`https://{domain}.freshdesk.com/oauth/authorize`,tokenUrl:`https://{domain}.freshdesk.com/oauth/token`,scopes:[`tickets_view`],toolName:`list_tickets`,toolDescription:`List Freshdesk tickets for the connected account.`,requestMethod:`GET`,requestPath:`/tickets`},pipedrive:{apiBaseUrl:`https://api.pipedrive.com/v1`,authorizationUrl:`https://oauth.pipedrive.com/oauth/authorize`,tokenUrl:`https://oauth.pipedrive.com/oauth/token`,scopes:[`deals:read`,`contacts:read`],toolName:`list_persons`,toolDescription:`List Pipedrive people visible to the connected user.`,requestMethod:`GET`,requestPath:`/persons`},mailchimp:{apiBaseUrl:`https://{dc}.api.mailchimp.com/3.0`,authorizationUrl:`https://login.mailchimp.com/oauth2/authorize`,tokenUrl:`https://login.mailchimp.com/oauth2/token`,scopes:[`audiences:read`],toolName:`list_audiences`,toolDescription:`List Mailchimp audiences for the connected account.`,requestMethod:`GET`,requestPath:`/lists`},quickbooks:{apiBaseUrl:`https://sandbox-quickbooks.api.intuit.com/v3/company/{companyId}`,authorizationUrl:`https://appcenter.intuit.com/connect/oauth2`,tokenUrl:`https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer`,scopes:[`com.intuit.quickbooks.accounting`],toolName:`list_customers`,toolDescription:`Query QuickBooks customers for the connected company.`,requestMethod:`GET`,requestPath:`/query?query=SELECT%20*%20FROM%20Customer%20MAXRESULTS%2010`},xero:{apiBaseUrl:`https://api.xero.com/api.xro/2.0`,authorizationUrl:`https://login.xero.com/identity/connect/authorize`,tokenUrl:`https://identity.xero.com/connect/token`,scopes:[`accounting.contacts.read`],toolName:`list_contacts`,toolDescription:`List Xero contacts for the connected tenant.`,requestMethod:`GET`,requestPath:`/Contacts`},gitlab:{apiBaseUrl:`https://gitlab.com/api/v4`,authorizationUrl:`https://gitlab.com/oauth/authorize`,tokenUrl:`https://gitlab.com/oauth/token`,scopes:[`read_api`],toolName:`get_current_user`,toolDescription:`Fetch the authenticated GitLab user profile.`,requestMethod:`GET`,requestPath:`/user`},bitbucket:{apiBaseUrl:`https://api.bitbucket.org/2.0`,authorizationUrl:`https://bitbucket.org/site/oauth2/authorize`,tokenUrl:`https://bitbucket.org/site/oauth2/access_token`,scopes:[`account`,`repository`],toolName:`get_current_user`,toolDescription:`Fetch the authenticated Bitbucket user profile.`,requestMethod:`GET`,requestPath:`/user`},ordinal:{provider:`mcp`,authModes:[`bearer`],authStrategy:`bearer`,credentialLabel:`Ordinal API key`,credentialPlaceholder:`Paste your Ordinal API key`,credentialHelp:`API key from your Ordinal workspace settings, sent as a Bearer token in the Authorization header.`}},qe=e=>{let t=Ke[e];if(!t)return;let n=Ge[e],r=t.provider??(n?`mcp`:t.apiBaseUrl||t.openApiUrl?`http`:void 0);return{...t,provider:r,serverUrl:r===`mcp`?t.serverUrl??n:t.serverUrl}},K=(e,t)=>{let n=qe(t.slug);return{...t,authStrategy:t.authStrategy??n?.authStrategy??`oauth2`,popularityRank:e,registrationDefaults:n}},q=[K(1,{slug:`github`,name:`GitHub`,description:`Source control, issues, pull requests, and developer workflows.`,categories:[`Engineering`,`Source control`],availability:`manual_token`,managedConnectorSlug:`github`,appUrl:`https://github.com`,docsUrl:`https://docs.github.com/apps/oauth-apps/building-oauth-apps`,notes:`Current managed connector works with bearer tokens today; GitHub OAuth is a strong candidate for a future one-click connect flow.`}),K(2,{slug:`google-docs`,name:`Google Docs`,description:`Docs authoring and Google Workspace document automation.`,categories:[`Documents`,`Knowledge base`],availability:`manual_token`,managedConnectorSlug:`google-docs`,appUrl:`https://workspace.google.com/products/docs/`,docsUrl:`https://developers.google.com/identity/protocols/oauth2`,notes:`Current managed connector accepts a Google access token manually; a full OAuth connect flow can remove token copy/paste.`}),K(3,{slug:`slack`,name:`Slack`,description:`Channels, messaging, workflows, canvases, and operational collaboration.`,categories:[`Communication`,`Operations`],availability:`oauth_ready`,managedConnectorSlug:`slack`,appUrl:`https://slack.com`,docsUrl:`https://docs.slack.dev/ai/slack-mcp-server`,notes:`Uses Slack's official hosted MCP server with confidential OAuth user-token auth.`}),K(4,{slug:`notion`,name:`Notion`,description:`Workspace search, pages, databases, and knowledge management.`,categories:[`Knowledge base`,`Documentation`],availability:`oauth_ready`,managedConnectorSlug:`notion`,appUrl:`https://www.notion.so`,docsUrl:`https://developers.notion.com/docs/authorization`,notes:``}),K(5,{slug:`figma`,name:`Figma`,description:`Design files, nodes, and developer handoff automation.`,categories:[`Design`,`Frontend`],availability:`oauth_ready`,managedConnectorSlug:`figma`,appUrl:`https://www.figma.com`,docsUrl:`https://www.figma.com/developers/api#oauth2`,notes:``}),K(6,{slug:`google-drive`,name:`Google Drive`,description:`File search, metadata, folders, and document discovery.`,categories:[`Storage`,`Documents`],availability:`planned`,appUrl:`https://workspace.google.com/products/drive/`,docsUrl:`https://developers.google.com/identity/protocols/oauth2`,notes:`Natural expansion of the Google Workspace surface beyond Google Docs.`}),K(7,{slug:`google-sheets`,name:`Google Sheets`,description:`Spreadsheet reads, writes, formulas, and reporting workflows.`,categories:[`Spreadsheets`,`Analytics`],availability:`planned`,appUrl:`https://workspace.google.com/products/sheets/`,docsUrl:`https://developers.google.com/identity/protocols/oauth2`,notes:`High-value automation surface for agent-driven reporting and structured edits.`}),K(8,{slug:`gmail`,name:`Gmail`,description:`Mailbox search, drafting, sending, and thread triage.`,categories:[`Communication`,`Email`],availability:`planned`,appUrl:`https://workspace.google.com/products/gmail/`,docsUrl:`https://developers.google.com/identity/protocols/oauth2`,notes:`Popular agent workflow target for inbox triage and drafting.`}),K(9,{slug:`google-calendar`,name:`Google Calendar`,description:`Calendar search, event scheduling, and meeting coordination.`,categories:[`Calendar`,`Scheduling`],availability:`planned`,appUrl:`https://workspace.google.com/products/calendar/`,docsUrl:`https://developers.google.com/identity/protocols/oauth2`,notes:`Strong personal productivity use case with mature OAuth flows.`}),K(10,{slug:`jira`,name:`Jira`,description:`Issue tracking, sprint workflows, and engineering program management.`,categories:[`Project management`,`Engineering`],availability:`planned`,appUrl:`https://www.atlassian.com/software/jira`,docsUrl:`https://developer.atlassian.com/cloud/jira/platform/oauth-2-3lo-apps/`,notes:`Very common MCP target for software teams and ticket automation.`}),K(11,{slug:`confluence`,name:`Confluence`,description:`Wiki pages, spaces, and internal documentation search.`,categories:[`Documentation`,`Knowledge base`],availability:`planned`,appUrl:`https://www.atlassian.com/software/confluence`,docsUrl:`https://developer.atlassian.com/cloud/confluence/oauth-2-3lo-apps/`,notes:`Natural companion to Jira for software teams.`}),K(12,{slug:`linear`,name:`Linear`,description:`Issue tracking, roadmap planning, and product engineering workflows.`,categories:[`Project management`,`Engineering`],availability:`planned`,appUrl:`https://linear.app`,docsUrl:`https://linear.app/developers/oauth-authentication`,notes:`Popular among modern product engineering teams and already useful to this repo's users.`}),K(13,{slug:`asana`,name:`Asana`,description:`Task management, projects, and work tracking.`,categories:[`Project management`,`Operations`],availability:`planned`,appUrl:`https://asana.com`,docsUrl:`https://developers.asana.com/docs/oauth`,notes:`Broad business adoption and straightforward OAuth app model.`}),K(14,{slug:`trello`,name:`Trello`,description:`Boards, cards, checklists, and lightweight project planning.`,categories:[`Project management`,`Operations`],availability:`planned`,appUrl:`https://trello.com`,docsUrl:`https://developer.atlassian.com/cloud/trello/guides/rest-api/authorization/`,notes:`Useful for SMB and cross-functional task boards, but Trello's public API auth is a special-case flow rather than a straightforward generic OAuth2 connector.`}),K(15,{slug:`clickup`,name:`ClickUp`,description:`Tasks, docs, goals, and workflow automation.`,categories:[`Project management`,`Operations`],availability:`planned`,appUrl:`https://clickup.com`,docsUrl:`https://clickup.com/api/developer-portal/authentication`,notes:`Large install base and broad operations coverage.`}),K(16,{slug:`monday`,name:`Monday.com`,description:`Boards, automations, and work management across teams.`,categories:[`Project management`,`Operations`],availability:`planned`,appUrl:`https://monday.com`,docsUrl:`https://developer.monday.com/apps/docs/oauth`,notes:`High-demand operations platform with rich board APIs.`}),K(17,{slug:`airtable`,name:`Airtable`,description:`Bases, records, linked data, and workflow automation.`,categories:[`Database`,`Operations`],availability:`planned`,appUrl:`https://airtable.com`,docsUrl:`https://airtable.com/developers/web/api/oauth-reference`,notes:`Very common internal-tools and operations automation surface.`}),K(18,{slug:`dropbox`,name:`Dropbox`,description:`Cloud files, folders, content access, and sharing.`,categories:[`Storage`,`Documents`],availability:`planned`,appUrl:`https://www.dropbox.com`,docsUrl:`https://developers.dropbox.com/oauth-guide`,notes:`Popular file automation target with mature OAuth support.`}),K(19,{slug:`box`,name:`Box`,description:`Enterprise file storage, metadata, and collaboration.`,categories:[`Storage`,`Enterprise`],availability:`planned`,appUrl:`https://www.box.com`,docsUrl:`https://developer.box.com/guides/authentication/oauth2/`,notes:`Strong enterprise document-management footprint.`}),K(20,{slug:`microsoft-outlook`,name:`Microsoft Outlook`,description:`Mail, calendar, contacts, and meeting workflows through Microsoft Graph.`,categories:[`Email`,`Calendar`],availability:`planned`,appUrl:`https://www.microsoft.com/microsoft-365/outlook/email-and-calendar-software-microsoft-outlook`,docsUrl:`https://learn.microsoft.com/graph/auth-v2-user`,notes:`High-value Microsoft Graph integration surface for enterprise users.`}),K(21,{slug:`microsoft-teams`,name:`Microsoft Teams`,description:`Chats, channels, meetings, and collaboration via Microsoft Graph.`,categories:[`Communication`,`Enterprise`],availability:`planned`,appUrl:`https://www.microsoft.com/microsoft-teams/group-chat-software`,docsUrl:`https://learn.microsoft.com/graph/auth-v2-user`,notes:`Common enterprise chat target alongside Outlook.`}),K(22,{slug:`onedrive`,name:`OneDrive`,description:`Cloud file access and document workflows through Microsoft Graph.`,categories:[`Storage`,`Documents`],availability:`planned`,appUrl:`https://www.microsoft.com/microsoft-365/onedrive/online-cloud-storage`,docsUrl:`https://learn.microsoft.com/graph/auth-v2-user`,notes:`Useful for enterprise file automation and search.`}),K(23,{slug:`sharepoint`,name:`SharePoint`,description:`Sites, document libraries, lists, and intranet content.`,categories:[`Knowledge base`,`Enterprise`],availability:`planned`,appUrl:`https://www.microsoft.com/microsoft-365/sharepoint/collaboration`,docsUrl:`https://learn.microsoft.com/graph/auth-v2-user`,notes:`Frequently requested for enterprise knowledge retrieval.`}),K(24,{slug:`salesforce`,name:`Salesforce`,description:`CRM records, accounts, opportunities, and sales operations.`,categories:[`CRM`,`Sales`],availability:`planned`,appUrl:`https://www.salesforce.com`,docsUrl:`https://help.salesforce.com/s/articleView?id=sf.remoteaccess_oauth_web_server_flow.htm&type=5`,notes:`Very common enterprise CRM and agent-assist target.`}),K(25,{slug:`hubspot`,name:`HubSpot`,description:`CRM, marketing, tickets, and customer lifecycle workflows.`,categories:[`CRM`,`Marketing`],availability:`oauth_ready`,managedConnectorSlug:`hubspot`,appUrl:`https://www.hubspot.com`,docsUrl:`https://developers.hubspot.com/docs/apps/developer-platform/build-apps/integrate-with-the-remote-hubspot-mcp-server`,notes:`Uses HubSpot's official remote MCP server plus MCP auth apps with PKCE.`}),K(26,{slug:`zendesk`,name:`Zendesk`,description:`Support tickets, customers, agents, and help desk operations.`,categories:[`Support`,`Operations`],availability:`planned`,appUrl:`https://www.zendesk.com`,docsUrl:`https://developer.zendesk.com/documentation/apps/getting-started/oauth/`,notes:`Strong support automation use case for agents.`}),K(27,{slug:`intercom`,name:`Intercom`,description:`Customer support, conversations, inboxes, and CRM context.`,categories:[`Support`,`CRM`],availability:`planned`,appUrl:`https://www.intercom.com`,docsUrl:`https://developers.intercom.com/building-apps/docs/authentication-types`,notes:`Useful for customer-facing assistant workflows.`}),K(28,{slug:`stripe`,name:`Stripe`,description:`Payments, customers, invoices, and subscription operations.`,categories:[`Payments`,`Finance`],availability:`planned`,appUrl:`https://stripe.com`,docsUrl:`https://docs.stripe.com/connect/oauth-reference`,notes:`High-value fintech automation target with mature OAuth patterns.`}),K(29,{slug:`shopify`,name:`Shopify`,description:`Storefronts, products, orders, and ecommerce operations.`,categories:[`Ecommerce`,`Operations`],availability:`planned`,appUrl:`https://www.shopify.com`,docsUrl:`https://shopify.dev/docs/apps/build/authentication-authorization/access-tokens/authorization-code-grant`,notes:`A top ecommerce platform and strong MCP candidate.`}),K(30,{slug:`discord`,name:`Discord`,description:`Guilds, channels, messages, and community operations.`,categories:[`Communication`,`Community`],availability:`planned`,appUrl:`https://discord.com`,docsUrl:`https://discord.com/developers/docs/topics/oauth2`,notes:`Useful for community automation and bot-assisted workflows.`}),K(31,{slug:`zoom`,name:`Zoom`,description:`Meetings, recordings, webinars, and scheduling operations.`,categories:[`Meetings`,`Calendar`],availability:`planned`,appUrl:`https://zoom.us`,docsUrl:`https://developers.zoom.us/docs/integrations/oauth/`,notes:`Frequently requested for scheduling and meeting summaries.`}),K(32,{slug:`webflow`,name:`Webflow`,description:`CMS items, sites, and web publishing workflows.`,categories:[`CMS`,`Marketing`],availability:`oauth_ready`,managedConnectorSlug:`webflow`,appUrl:`https://webflow.com`,docsUrl:`https://developers.webflow.com/mcp/reference/getting-started`,notes:`Uses Webflow's official hosted MCP server and deployment-scoped MCP OAuth registration so each user can authorize their own sites and workspaces.`}),K(33,{slug:`miro`,name:`Miro`,description:`Whiteboards, diagrams, notes, and workshop collaboration.`,categories:[`Whiteboard`,`Collaboration`],availability:`planned`,appUrl:`https://miro.com`,docsUrl:`https://developers.miro.com/docs/rest-api-build-your-first-oauth-app`,notes:`Strong visual collaboration target for design and product teams.`}),K(34,{slug:`canva`,name:`Canva`,description:`Design content, brand assets, and marketing collateral workflows.`,categories:[`Design`,`Marketing`],availability:`planned`,appUrl:`https://www.canva.com`,docsUrl:`https://www.canva.dev/docs/connect/oauth/`,notes:`Broad creator and marketing adoption with OAuth-based apps.`}),K(35,{slug:`datadog`,name:`Datadog`,description:`Logs, metrics, monitors, incidents, and observability workflows.`,categories:[`Observability`,`Operations`],availability:`oauth_ready`,managedConnectorSlug:`datadog`,appUrl:`https://www.datadoghq.com`,docsUrl:`https://docs.datadoghq.com/bits_ai/mcp_server/setup/`,notes:`Uses Datadog's official hosted MCP server. The default registration targets the US1 endpoint and can be edited for other Datadog sites.`}),K(36,{slug:`sentry`,name:`Sentry`,description:`Errors, releases, issue ownership, and incident investigation.`,categories:[`Observability`,`Engineering`],availability:`planned`,appUrl:`https://sentry.io`,docsUrl:`https://docs.sentry.io/api/guides/oauth/`,notes:`Natural target for engineering support agents.`}),K(37,{slug:`posthog`,name:`PostHog`,description:`Product analytics, feature flags, and session insights.`,categories:[`Analytics`,`Product`],availability:`planned`,appUrl:`https://posthog.com`,docsUrl:`https://posthog.com/docs/apps/build/oauth`,notes:`Relevant for product analytics and experimentation workflows.`}),K(38,{slug:`supabase`,name:`Supabase`,description:`Projects, databases, auth, and storage administration.`,categories:[`Database`,`Developer tools`],availability:`planned`,appUrl:`https://supabase.com`,docsUrl:`https://supabase.com/docs/guides/integrations/build-a-supabase-oauth-integration`,notes:`Popular developer platform with broad automation value and a documented management-API OAuth integration flow.`}),K(39,{slug:`vercel`,name:`Vercel`,description:`Deployments, projects, domains, and preview environment workflows.`,categories:[`Developer tools`,`Deployment`],availability:`planned`,appUrl:`https://vercel.com`,docsUrl:`https://vercel.com/docs/rest-api#oauth-apps`,notes:`Especially relevant to this repo's deployment model.`}),K(40,{slug:`netlify`,name:`Netlify`,description:`Sites, builds, deploy previews, and web operations.`,categories:[`Deployment`,`Developer tools`],availability:`planned`,appUrl:`https://www.netlify.com`,docsUrl:`https://docs.netlify.com/api/get-started/#oauth-applications`,notes:`Common alternative hosting/deployment automation target.`}),K(41,{slug:`plaid`,name:`Plaid`,description:`Financial account connectivity and transaction data flows.`,categories:[`Finance`,`Payments`],availability:`planned`,appUrl:`https://plaid.com`,docsUrl:`https://plaid.com/docs/auth/oauth/`,notes:`Strong fintech workflow candidate, although much of Plaid's OAuth guidance is a special-case token exchange rather than a generic end-user SaaS OAuth connector.`}),K(42,{slug:`okta`,name:`Okta`,description:`Identity, users, applications, and access administration.`,categories:[`Identity`,`Enterprise`],availability:`planned`,appUrl:`https://www.okta.com`,docsUrl:`https://developer.okta.com/docs/guides/implement-oauth-for-okta/main/`,notes:`High-value admin and security automation surface.`}),K(43,{slug:`servicenow`,name:`ServiceNow`,description:`Tickets, incidents, service catalogs, and enterprise workflows.`,categories:[`ITSM`,`Enterprise`],availability:`planned`,appUrl:`https://www.servicenow.com`,docsUrl:`https://www.servicenow.com/docs/bundle/xanadu-platform-security/page/administer/security/concept/oauth-concept.html`,notes:`Strong enterprise IT operations use case.`}),K(44,{slug:`freshdesk`,name:`Freshdesk`,description:`Support tickets, customer records, and help desk workflows.`,categories:[`Support`,`Operations`],availability:`planned`,appUrl:`https://www.freshworks.com/freshdesk/`,docsUrl:`https://developers.freshdesk.com/api/#authentication`,notes:`Popular support platform for SMB and mid-market teams.`}),K(45,{slug:`pipedrive`,name:`Pipedrive`,description:`Deals, contacts, and sales pipeline management.`,categories:[`CRM`,`Sales`],availability:`planned`,appUrl:`https://www.pipedrive.com`,docsUrl:`https://pipedrive.readme.io/docs/marketplace-oauth-authorization`,notes:`Common CRM choice with solid OAuth story.`}),K(46,{slug:`mailchimp`,name:`Mailchimp`,description:`Campaigns, audiences, automations, and email marketing.`,categories:[`Marketing`,`Email`],availability:`planned`,appUrl:`https://mailchimp.com`,docsUrl:`https://mailchimp.com/developer/marketing/guides/access-user-data-oauth-2/`,notes:`Popular marketing automation target.`}),K(47,{slug:`quickbooks`,name:`QuickBooks`,description:`Accounting, invoices, customers, and financial operations.`,categories:[`Finance`,`Accounting`],availability:`planned`,appUrl:`https://quickbooks.intuit.com`,docsUrl:`https://developer.intuit.com/app/developer/qbo/docs/develop/authentication-and-authorization/oauth-2.0`,notes:`Frequent finance automation request with OAuth-based apps.`}),K(48,{slug:`xero`,name:`Xero`,description:`Accounting, contacts, invoices, and bookkeeping workflows.`,categories:[`Finance`,`Accounting`],availability:`planned`,appUrl:`https://www.xero.com`,docsUrl:`https://developer.xero.com/documentation/guides/oauth2/overview/`,notes:`Important accounting platform in many regions.`}),K(49,{slug:`gitlab`,name:`GitLab`,description:`Repositories, issues, merge requests, pipelines, and DevSecOps.`,categories:[`Engineering`,`Source control`],availability:`planned`,appUrl:`https://about.gitlab.com`,docsUrl:`https://docs.gitlab.com/integration/oauth_provider/`,notes:`Major Git hosting platform and natural expansion beyond GitHub.`}),K(50,{slug:`bitbucket`,name:`Bitbucket`,description:`Repositories, pull requests, and Atlassian engineering workflows.`,categories:[`Engineering`,`Source control`],availability:`planned`,appUrl:`https://bitbucket.org`,docsUrl:`https://developer.atlassian.com/cloud/bitbucket/oauth-2/`,notes:`Popular in Atlassian-centric teams and complements Jira/Confluence.`}),K(51,{slug:`elevenlabs`,name:`ElevenLabs`,description:`Text to speech, voices, transcription, audio generation, and agents.`,categories:[`Audio`,`AI`],authStrategy:`api_key`,availability:`manual_token`,managedConnectorSlug:`elevenlabs`,appUrl:`https://elevenlabs.io`,docsUrl:`https://elevenlabs.io/docs/api-reference/introduction`,notes:`Official API-key connector backed by ElevenLabs' published OpenAPI spec.`}),K(52,{slug:`ordinal`,name:`Ordinal`,description:`Social media posts, profiles, analytics, labels, approvals, and engagements.`,categories:[`Social media`,`Marketing`],authStrategy:`bearer`,availability:`manual_token`,managedConnectorSlug:`ordinal`,appUrl:`https://app.tryordinal.com`,docsUrl:`https://docs.tryordinal.com/api/mcp`,notes:`Official MCP server backed by Ordinal's API with API-key (Bearer) auth.`})],Je=()=>q,Ye=[E,D,O,k,A,j,M,N,P,F,I,L,R,z,B,V,pe,me,he,ge,_e,ve,ye,be,xe,Se,Ce,we,Te,Ee,De,Oe,ke,Ae,je,Me,Ne,Pe,Fe,Ie],Xe=e=>{let t=e?.authStrategy??(e?.authorizationUrl||e?.tokenUrl,`oauth2`);return t===`oauth2`?`oauth`:t===`none`?`none`:`api`},Ze=e=>{let t=e.registrationDefaults;if(!t)return null;let n={id:Xe(t),provider:t.provider??(t.serverUrl?`mcp`:`http`),auth:{strategy:t.authStrategy??e.authStrategy??`oauth2`,authModes:t.authModes,credentialLabel:t.credentialLabel,credentialPlaceholder:t.credentialPlaceholder,credentialHelp:t.credentialHelp,apiKeyHeaderName:t.apiKeyHeaderName,oauth:t.authorizationUrl||t.tokenUrl?{authorizationUrl:t.authorizationUrl,tokenUrl:t.tokenUrl,scopes:t.scopes??[],optionalScopes:t.optionalScopes,toolScopes:t.toolScopes,scopeSeparator:t.scopeSeparator,pkce:t.pkce,clientAuthentication:t.clientAuthentication,registrationUrl:t.registrationUrl,additionalAuthorizationParams:t.additionalAuthorizationParams,additionalTokenParams:t.additionalTokenParams}:void 0}};return n.provider===`mcp`?n.transport={kind:`shttp`,url:t.serverUrl}:n.http={apiBaseUrl:t.apiBaseUrl,openApiUrl:t.openApiUrl,defaultTool:t.toolName?{name:t.toolName,description:t.toolDescription,method:t.requestMethod,path:t.requestPath,scopes:t.toolScopes}:void 0},n},Qe=e=>{let t=Ze(e);return{id:e.slug,kind:t?.provider??`http`,name:e.name,description:e.description,categories:e.categories,appUrl:e.appUrl,docsUrl:e.docsUrl,notes:e.notes,catalogStatus:e.availability,managedConnectorSlug:e.managedConnectorSlug,authStrategy:e.authStrategy,popularityRank:e.popularityRank,registrationDefaults:e.registrationDefaults,...t?{defaultConnectionOptionId:t.id,connectionOptions:[t]}:{connectionOptions:[]}}},$e=(e=[],t=[])=>{let n=new Map;for(let t of e)n.set(t.id,t);for(let e of t)n.has(e.id)||n.set(e.id,e);return[...n.values()]},et=(e,t)=>{let n=$e(e.connectionOptions,t.connectionOptions);return{...e,...t,catalogStatus:e.catalogStatus??t.catalogStatus,managedConnectorSlug:e.managedConnectorSlug??t.managedConnectorSlug,authStrategy:e.authStrategy??t.authStrategy,registrationDefaults:e.registrationDefaults??t.registrationDefaults,connectionOptions:n,defaultConnectionOptionId:e.defaultConnectionOptionId??t.defaultConnectionOptionId??n[0]?.id}},J=new Map;for(let e of Je().map(Qe))J.set(e.id,e);for(let e of Ye)J.set(e.id,J.has(e.id)?et(J.get(e.id),e):e);var tt=[...J.values()].sort((e,t)=>(t.popularityRank??0)-(e.popularityRank??0)||e.name.localeCompare(t.name)),Y=e(t(),1),X=`h-5 w-5`,Z=e=>(0,Y.createElement)(e,{className:X}),Q=e=>(0,Y.createElement)(e,{className:X,strokeWidth:2.25}),nt=Q(i),$={github:Z(re),slack:Z(m),tavily:(0,Y.createElement)(ee,{className:X,strokeWidth:2.5}),linear:Z(ie),notion:Z(s),atlassian:Z(de),sentry:Z(f),stripe:Z(ne),paypal:Z(se),"cloudflare-docs":Z(o),"cloudflare-bindings":Z(o),"cloudflare-observability":Z(o),huggingface:Z(le),deepwiki:Z(h),git:Q(a),"brave-search":Z(c),exa:Q(w),firecrawl:Q(y),apify:Q(i),fetch:Q(b),"browser-mcp":Q(S),playwright:Q(T),supabase:Z(p),neon:Q(v),mongodb:Z(ae),redis:Z(oe),filesystem:Q(r),memory:Q(g),"sequential-thinking":Q(x),time:Q(_),everything:Q(C),figma:Z(l),airtable:Z(u),obsidian:Z(ue),elevenlabs:Z(fe),resend:Z(te),"cloudflare-builds":Z(o),"cloudflare-browser-rendering":Z(o),kagi:Z(d),clickhouse:Z(ce)};new Set(Object.keys($));export{$ as n,tt as r,nt as t};
package/build/index.html CHANGED
@@ -1,12 +1,12 @@
1
- <!DOCTYPE html><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><title>OpenHands</title><meta name="description" content="Let&#x27;s Start Building!"/><link rel="icon" type="image/svg+xml" href="/favicon.svg"/><link rel="modulepreload" href="/assets/manifest-a1d22045.js"/><link rel="modulepreload" href="/assets/entry.client-1VMHpktY.js"/><link rel="modulepreload" href="/assets/rolldown-runtime-BFRubm34.js"/><link rel="modulepreload" href="/assets/preload-helper-CT1Z6Pdu.js"/><link rel="modulepreload" href="/assets/vendor~entry.client-CySJvEhK.js"/><link rel="modulepreload" href="/assets/providers-Bx6EfrzZ.js"/><link rel="modulepreload" href="/assets/declaration-BNMqORFE.js"/><link rel="modulepreload" href="/assets/vendor~entry.client-Du9GpFmX.js"/><link rel="modulepreload" href="/assets/react-CM_dJw1Z.js"/><link rel="modulepreload" href="/assets/i18n-CTohRuoO.js"/><link rel="modulepreload" href="/assets/react-dom-hVBnwgwZ.js"/><link rel="modulepreload" href="/assets/vendor~entry.client~root~root-layout~index-redirect~home~conversation-panel~conversation~la~cnj3raoq-DTEXlLSB.js"/><link rel="modulepreload" href="/assets/query-client-config-B7u9asM0.js"/><link rel="modulepreload" href="/assets/QueryClientProvider-CkGuhXg-.js"/><link rel="modulepreload" href="/assets/vendor~entry.client~root~root-layout~home~conversation-panel~conversation~launch~skills-set~jfc6hidu-VnmIZrq3.js"/><link rel="modulepreload" href="/assets/context-CEQZwATj.js"/><link rel="modulepreload" href="/assets/option-service.api-KvY_mZMY.js"/><link rel="modulepreload" href="/assets/utils-i18rdUj2.js"/><link rel="modulepreload" href="/assets/active-backend-context-cCM1vYYZ.js"/><link rel="modulepreload" href="/assets/query-keys-tAsQcc_9.js"/><link rel="modulepreload" href="/assets/agent-server-ui-style-scope-BwIZYdC1.js"/><link rel="modulepreload" href="/assets/vendor~entry.client~root~root-layout~home~conversation-panel~conversation~launch~extensions~g56ukk6u-DsSvIDZQ.js"/><link rel="modulepreload" href="/assets/mutation-D0OogFCz.js"/><link rel="modulepreload" href="/assets/custom-toast-handlers-C-SZFmto.js"/><link rel="modulepreload" href="/assets/health-store-BDC2rM-X.js"/><link rel="modulepreload" href="/assets/retrieve-axios-error-message-BY-yIkIq.js"/><link rel="modulepreload" href="/assets/createLucideIcon-Ddu8jDOQ.js"/><link rel="modulepreload" href="/assets/vendor~entry.client~root~root-layout~home~conversation-panel~conversation~launch~extensions~hkqzh1hb-BZ0HXuHD.js"/><link rel="modulepreload" href="/assets/vendor~entry.client~root~root-layout~home~conversation-panel~conversation~skills-settings~m~o9nrx3fm-D44TR8hL.js"/><link rel="modulepreload" href="/assets/vendor~entry.client~root~root-layout~home~conversation-panel~conversation~launch~skills-set~zm51vy4j-iOsylxCS.js"/><link rel="modulepreload" href="/assets/agent-server-client-options-Bc5ZorQZ.js"/><link rel="modulepreload" href="/assets/llm-client-DaH1TuyR.js"/><link rel="modulepreload" href="/assets/agent-server-compatibility-BlkUsrX2.js"/><link rel="modulepreload" href="/assets/server-client-DyAQ3NZ_.js"/><link rel="modulepreload" href="/assets/settings-client-C73C7IgV.js"/><link rel="modulepreload" href="/assets/root-35yk2E_M.js"/><link rel="modulepreload" href="/assets/useTranslation-DCOdSSMl.js"/><link rel="modulepreload" href="/assets/brand-button-Br7f0kZJ.js"/><link rel="modulepreload" href="/assets/base-modal-_dYTw1ri.js"/><link rel="modulepreload" href="/assets/loading-spinner-BPtYORNK.js"/><link rel="modulepreload" href="/assets/modal-backdrop-BAbgYsqB.js"/><link rel="modulepreload" href="/assets/modal-body-BI6Ru2Qr.js"/><link rel="modulepreload" href="/assets/use-config-Co1O8-Ey.js"/><link rel="modulepreload" href="/assets/color-themes-DSaoIL6A.js"/><link rel="modulepreload" href="/assets/vendor~root~root-layout~home~conversation-panel~conversation~launch~extensions-hub~skills-s~f2l2lr17-CDXvdvb2.js"/><link rel="stylesheet" href="/assets/root-DHeCXo9N.css"/></head><body data-agent-server-ui="" class="m-0"><div data-agent-server-ui="" style="--oh-color-logo:#cfb755;--oh-color-base:var(--cool-grey-950);--oh-color-base-secondary:var(--cool-grey-925);--oh-color-danger:#e76a5e;--oh-color-success:#a5e75e;--oh-color-basic:var(--cool-grey-400);--oh-color-tertiary:var(--cool-grey-800);--oh-color-tertiary-light:var(--cool-grey-300);--oh-color-content:var(--cool-grey-100);--oh-color-content-2:var(--cool-grey-50);--oh-background:var(--cool-grey-950);--oh-foreground:var(--cool-grey-100);--oh-surface:var(--cool-grey-925);--oh-surface-foreground:var(--cool-grey-100);--oh-surface-raised:var(--cool-grey-900);--oh-surface-deep:var(--cool-grey-975);--oh-overlay:var(--cool-grey-925);--oh-overlay-foreground:var(--cool-grey-100);--oh-muted:var(--cool-grey-400);--oh-text-secondary:var(--cool-grey-300);--oh-text-tertiary:var(--cool-grey-200);--oh-text-dim:var(--cool-grey-500);--oh-text-subtle:var(--cool-grey-600);--oh-interactive-hover:var(--cool-grey-700);--oh-interactive-hover-low:var(--cool-grey-900);--oh-interactive-active:var(--cool-grey-800);--oh-interactive-selected:var(--cool-grey-600);--oh-scrollbar:color-mix(in srgb, var(--cool-grey-400) 30%, transparent);--oh-scrollbar-hover:color-mix(in srgb, var(--cool-grey-400) 50%, transparent);--oh-default:var(--cool-grey-800);--oh-default-foreground:var(--cool-grey-100);--oh-accent-foreground:var(--cool-grey-950);--oh-success:#a5e75e;--oh-success-foreground:var(--cool-grey-950);--oh-warning-foreground:var(--cool-grey-950);--oh-danger:#e76a5e;--oh-danger-foreground:var(--cool-grey-50);--oh-segment:var(--cool-grey-925);--oh-segment-foreground:var(--cool-grey-100);--oh-border-width:1px;--oh-field-border-width:1px;--oh-border:var(--cool-grey-700);--oh-border-input:var(--cool-grey-600);--oh-border-subtle:var(--cool-grey-800);--oh-separator:rgba(113, 120, 136, 0.5);--oh-focus:#ffffff;--oh-status-success:#1FBD53;--oh-status-error:#FF684E;--oh-link:var(--cool-grey-100);--oh-radius:8px;--oh-field-radius:8px;--oh-surface-shadow:none;--oh-overlay-shadow:none;--oh-field-shadow:none;--oh-bg-dark:var(--cool-grey-950);--oh-bg-light:var(--cool-grey-900);--oh-bg-input:var(--cool-grey-800);--oh-bg-workspace:var(--cool-grey-925);--oh-text-editor-base:var(--cool-grey-400);--oh-text-editor-active:var(--cool-grey-300);--oh-bg-editor-sidebar:var(--cool-grey-925);--oh-bg-editor-active:var(--cool-grey-900);--oh-border-editor-sidebar:var(--cool-grey-800);--oh-bg-neutral-muted:color-mix(in srgb, var(--cool-grey-300) 20%, transparent)"><div class="dark min-h-screen text-foreground" data-theme="dark"><script>
1
+ <!DOCTYPE html><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><title>OpenHands</title><meta name="description" content="Let&#x27;s Start Building!"/><link rel="icon" type="image/svg+xml" href="/favicon.svg"/><link rel="modulepreload" href="/assets/manifest-3bf30d69.js"/><link rel="modulepreload" href="/assets/entry.client-1VMHpktY.js"/><link rel="modulepreload" href="/assets/rolldown-runtime-BFRubm34.js"/><link rel="modulepreload" href="/assets/preload-helper-CT1Z6Pdu.js"/><link rel="modulepreload" href="/assets/vendor~entry.client-CySJvEhK.js"/><link rel="modulepreload" href="/assets/providers-Bx6EfrzZ.js"/><link rel="modulepreload" href="/assets/declaration-BNMqORFE.js"/><link rel="modulepreload" href="/assets/vendor~entry.client-Du9GpFmX.js"/><link rel="modulepreload" href="/assets/react-CM_dJw1Z.js"/><link rel="modulepreload" href="/assets/i18n-CTohRuoO.js"/><link rel="modulepreload" href="/assets/react-dom-hVBnwgwZ.js"/><link rel="modulepreload" href="/assets/vendor~entry.client~root~root-layout~index-redirect~home~conversation-panel~conversation~la~cnj3raoq-DTEXlLSB.js"/><link rel="modulepreload" href="/assets/query-client-config-B7u9asM0.js"/><link rel="modulepreload" href="/assets/QueryClientProvider-CkGuhXg-.js"/><link rel="modulepreload" href="/assets/vendor~entry.client~root~root-layout~home~conversation-panel~conversation~launch~skills-set~jfc6hidu-VnmIZrq3.js"/><link rel="modulepreload" href="/assets/context-CEQZwATj.js"/><link rel="modulepreload" href="/assets/option-service.api-KvY_mZMY.js"/><link rel="modulepreload" href="/assets/utils-i18rdUj2.js"/><link rel="modulepreload" href="/assets/active-backend-context-cCM1vYYZ.js"/><link rel="modulepreload" href="/assets/query-keys-tAsQcc_9.js"/><link rel="modulepreload" href="/assets/agent-server-ui-style-scope-BwIZYdC1.js"/><link rel="modulepreload" href="/assets/vendor~entry.client~root~root-layout~home~conversation-panel~conversation~launch~extensions~g56ukk6u-DsSvIDZQ.js"/><link rel="modulepreload" href="/assets/mutation-D0OogFCz.js"/><link rel="modulepreload" href="/assets/custom-toast-handlers-C-SZFmto.js"/><link rel="modulepreload" href="/assets/health-store-BDC2rM-X.js"/><link rel="modulepreload" href="/assets/retrieve-axios-error-message-BY-yIkIq.js"/><link rel="modulepreload" href="/assets/createLucideIcon-Ddu8jDOQ.js"/><link rel="modulepreload" href="/assets/vendor~entry.client~root~root-layout~home~conversation-panel~conversation~launch~extensions~hkqzh1hb-BZ0HXuHD.js"/><link rel="modulepreload" href="/assets/vendor~entry.client~root~root-layout~home~conversation-panel~conversation~skills-settings~m~o9nrx3fm-D44TR8hL.js"/><link rel="modulepreload" href="/assets/vendor~entry.client~root~root-layout~home~conversation-panel~conversation~launch~skills-set~zm51vy4j-iOsylxCS.js"/><link rel="modulepreload" href="/assets/agent-server-client-options-Bc5ZorQZ.js"/><link rel="modulepreload" href="/assets/llm-client-DaH1TuyR.js"/><link rel="modulepreload" href="/assets/agent-server-compatibility-BlkUsrX2.js"/><link rel="modulepreload" href="/assets/server-client-DyAQ3NZ_.js"/><link rel="modulepreload" href="/assets/settings-client-C73C7IgV.js"/><link rel="modulepreload" href="/assets/root-dNntxffj.js"/><link rel="modulepreload" href="/assets/useTranslation-DCOdSSMl.js"/><link rel="modulepreload" href="/assets/brand-button-Br7f0kZJ.js"/><link rel="modulepreload" href="/assets/base-modal-_dYTw1ri.js"/><link rel="modulepreload" href="/assets/loading-spinner-BPtYORNK.js"/><link rel="modulepreload" href="/assets/modal-backdrop-BAbgYsqB.js"/><link rel="modulepreload" href="/assets/modal-body-BI6Ru2Qr.js"/><link rel="modulepreload" href="/assets/use-config-Co1O8-Ey.js"/><link rel="modulepreload" href="/assets/color-themes-DSaoIL6A.js"/><link rel="modulepreload" href="/assets/vendor~root~root-layout~home~conversation-panel~conversation~launch~extensions-hub~skills-s~f2l2lr17-CDXvdvb2.js"/><link rel="stylesheet" href="/assets/root-DHeCXo9N.css"/></head><body data-agent-server-ui="" class="m-0"><div data-agent-server-ui="" style="--oh-color-logo:#cfb755;--oh-color-base:var(--cool-grey-950);--oh-color-base-secondary:var(--cool-grey-925);--oh-color-danger:#e76a5e;--oh-color-success:#a5e75e;--oh-color-basic:var(--cool-grey-400);--oh-color-tertiary:var(--cool-grey-800);--oh-color-tertiary-light:var(--cool-grey-300);--oh-color-content:var(--cool-grey-100);--oh-color-content-2:var(--cool-grey-50);--oh-background:var(--cool-grey-950);--oh-foreground:var(--cool-grey-100);--oh-surface:var(--cool-grey-925);--oh-surface-foreground:var(--cool-grey-100);--oh-surface-raised:var(--cool-grey-900);--oh-surface-deep:var(--cool-grey-975);--oh-overlay:var(--cool-grey-925);--oh-overlay-foreground:var(--cool-grey-100);--oh-muted:var(--cool-grey-400);--oh-text-secondary:var(--cool-grey-300);--oh-text-tertiary:var(--cool-grey-200);--oh-text-dim:var(--cool-grey-500);--oh-text-subtle:var(--cool-grey-600);--oh-interactive-hover:var(--cool-grey-700);--oh-interactive-hover-low:var(--cool-grey-900);--oh-interactive-active:var(--cool-grey-800);--oh-interactive-selected:var(--cool-grey-600);--oh-scrollbar:color-mix(in srgb, var(--cool-grey-400) 30%, transparent);--oh-scrollbar-hover:color-mix(in srgb, var(--cool-grey-400) 50%, transparent);--oh-default:var(--cool-grey-800);--oh-default-foreground:var(--cool-grey-100);--oh-accent-foreground:var(--cool-grey-950);--oh-success:#a5e75e;--oh-success-foreground:var(--cool-grey-950);--oh-warning-foreground:var(--cool-grey-950);--oh-danger:#e76a5e;--oh-danger-foreground:var(--cool-grey-50);--oh-segment:var(--cool-grey-925);--oh-segment-foreground:var(--cool-grey-100);--oh-border-width:1px;--oh-field-border-width:1px;--oh-border:var(--cool-grey-700);--oh-border-input:var(--cool-grey-600);--oh-border-subtle:var(--cool-grey-800);--oh-separator:rgba(113, 120, 136, 0.5);--oh-focus:#ffffff;--oh-status-success:#1FBD53;--oh-status-error:#FF684E;--oh-link:var(--cool-grey-100);--oh-radius:8px;--oh-field-radius:8px;--oh-surface-shadow:none;--oh-overlay-shadow:none;--oh-field-shadow:none;--oh-bg-dark:var(--cool-grey-950);--oh-bg-light:var(--cool-grey-900);--oh-bg-input:var(--cool-grey-800);--oh-bg-workspace:var(--cool-grey-925);--oh-text-editor-base:var(--cool-grey-400);--oh-text-editor-active:var(--cool-grey-300);--oh-bg-editor-sidebar:var(--cool-grey-925);--oh-bg-editor-active:var(--cool-grey-900);--oh-border-editor-sidebar:var(--cool-grey-800);--oh-bg-neutral-muted:color-mix(in srgb, var(--cool-grey-300) 20%, transparent)"><div class="dark min-h-screen text-foreground" data-theme="dark"><script>
2
2
  console.log(
3
3
  "💿 Hey developer 👋. You can provide a way better UX than this " +
4
4
  "when your app is loading JS modules and/or running `clientLoader` " +
5
5
  "functions. Check out https://reactrouter.com/start/framework/route-module#hydratefallback " +
6
6
  "for more information."
7
7
  );
8
- </script><div data-rht-toaster="" style="position:fixed;z-index:9999;top:16px;left:16px;right:16px;bottom:16px;pointer-events:none"></div><div id="modal-portal-exit"></div></div></div><script>window.__reactRouterContext = {"basename":"/","future":{"unstable_optimizeDeps":false,"unstable_passThroughRequests":false,"unstable_subResourceIntegrity":false,"unstable_trailingSlashAwareDataRequests":false,"unstable_previewServerPrerendering":false,"v8_middleware":false,"v8_splitRouteModules":false,"v8_viteEnvironmentApi":false},"routeDiscovery":{"mode":"initial"},"ssr":false,"isSpaMode":true};window.__reactRouterContext.stream = new ReadableStream({start(controller){window.__reactRouterContext.streamController = controller;}}).pipeThrough(new TextEncoderStream());</script><script type="module" async="">import "/assets/manifest-a1d22045.js";
9
- import * as route0 from "/assets/root-35yk2E_M.js";
8
+ </script><div data-rht-toaster="" style="position:fixed;z-index:9999;top:16px;left:16px;right:16px;bottom:16px;pointer-events:none"></div><div id="modal-portal-exit"></div></div></div><script>window.__reactRouterContext = {"basename":"/","future":{"unstable_optimizeDeps":false,"unstable_passThroughRequests":false,"unstable_subResourceIntegrity":false,"unstable_trailingSlashAwareDataRequests":false,"unstable_previewServerPrerendering":false,"v8_middleware":false,"v8_splitRouteModules":false,"v8_viteEnvironmentApi":false},"routeDiscovery":{"mode":"initial"},"ssr":false,"isSpaMode":true};window.__reactRouterContext.stream = new ReadableStream({start(controller){window.__reactRouterContext.streamController = controller;}}).pipeThrough(new TextEncoderStream());</script><script type="module" async="">import "/assets/manifest-3bf30d69.js";
9
+ import * as route0 from "/assets/root-dNntxffj.js";
10
10
 
11
11
  window.__reactRouterRouteModules = {"root":route0};
12
12
 
@@ -1,2 +1,2 @@
1
- const e=require(`../../../_virtual/_rolldown/runtime.cjs`),t=require(`../../../node_modules/react-i18next/dist/es/useTranslation.cjs`),n=require(`../../../i18n/declaration.cjs`),r=require(`../../../utils/custom-toast-handlers.cjs`),i=require(`../../../node_modules/uuid/dist/v4.cjs`),a=require(`../../shared/modals/modal-backdrop.cjs`),o=require(`../../shared/modals/modal-close-button.cjs`),s=require(`../settings/brand-button.cjs`),c=require(`../settings/settings-input.cjs`),l=require(`../../../utils/retrieve-axios-error-message.cjs`),u=require(`../../../utils/mcp-marketplace-utils.cjs`),d=require(`../mcp-logo-badge.cjs`),f=require(`../../../hooks/mutation/use-add-mcp-server.cjs`),p=require(`../../../hooks/mutation/use-test-mcp-server.cjs`);let m=require(`react`);m=e.__toESM(m,1);let h=require(`react/jsx-runtime`);function g(e){return e?.transport.kind!==`shttp`&&e?.transport.kind!==`sse`?!1:[`api_key`,`bearer`,`basic`].includes(e.auth.strategy)}function _(e){return e.transport.kind===`stdio`?e.auth.apiKeyOptional??!1:e.auth.apiKeyOptional??e.transport.apiKeyOptional??!1}function v(e){let t={},n=u.getInstallableMcpConnectionOption(e),r=n?.transport;if(r?.kind===`stdio`){for(let e of r.envFields??[])t[e.key]=``;for(let e of r.argFields??[])t[e.key]=``}else g(n)&&(t.api_key=``);return{values:t,errors:{}}}function y({entry:e,onClose:y,onSuccess:b}){let{t:x}=t.useTranslation(`openhands`),{mutate:S,isPending:C}=f.useAddMcpServer(),{mutate:w,isPending:T}=p.useTestMcpServer(),[E,D]=m.default.useState(()=>v(e)),[O,k]=m.default.useState(null),A=u.getInstallableMcpConnectionOption(e),j=A?.transport,M=T||C,N=(e,t)=>{D(n=>({values:{...n.values,[e]:t},errors:{...n.errors,[e]:null}})),k(null)},P=e=>{switch(e.error_kind){case`timeout`:return x(n.I18nKey.MCP$TEST_ERROR_TIMEOUT);case`connection`:return x(n.I18nKey.MCP$TEST_ERROR_CONNECTION);default:return x(n.I18nKey.MCP$TEST_ERROR_UNKNOWN,{error:e.error})}},F=t=>{w(t,{onSuccess:i=>{if(!i.ok){k(P(i));return}S(t,{onSuccess:()=>{r.displaySuccessToast(x(n.I18nKey.MCP$INSTALL_SUCCESS)),b?.(e),y()},onError:e=>{k(l.retrieveAxiosErrorMessage(e)||x(n.I18nKey.ERROR$GENERIC))}})},onError:e=>{k(l.retrieveAxiosErrorMessage(e)||x(n.I18nKey.ERROR$GENERIC))}})},I=()=>{if(j?.kind!==`shttp`&&j?.kind!==`sse`||!A)return;let e=E.values.api_key?.trim()??``,t=g(A);if(t&&!_(A)&&!e){D(e=>({...e,errors:{api_key:x(n.I18nKey.MCP$ERROR_FIELD_REQUIRED)}}));return}F({id:`${j.kind}-${i.default()}`,type:j.kind,url:j.url,...t&&e&&{api_key:e}})},L=()=>{if(j?.kind!==`stdio`)return;let e=j,t={};for(let r of e.envFields??[])r.required&&!(E.values[r.key]??``).trim()&&(t[r.key]=x(n.I18nKey.MCP$ERROR_FIELD_REQUIRED));for(let r of e.argFields??[])r.required&&!(E.values[r.key]??``).trim()&&(t[r.key]=x(n.I18nKey.MCP$ERROR_FIELD_REQUIRED));if(Object.values(t).some(Boolean)){D(e=>({...e,errors:t}));return}let r={};for(let t of e.envFields??[]){let e=E.values[t.key]?.trim();e&&(r[t.key]=e)}let a=[];for(let t of e.argFields??[]){let e=E.values[t.key]?.trim();if(e)for(let t of e.split(/\s+/))t&&a.push(t)}F({id:`stdio-${i.default()}`,type:`stdio`,name:e.serverName,command:e.command,args:[...e.args,...a],...Object.keys(r).length>0&&{env:r}})};return(0,h.jsx)(a.ModalBackdrop,{onClose:y,"aria-label":e.name,children:(0,h.jsxs)(`form`,{"data-testid":`mcp-install-modal`,"data-marketplace-id":e.id,onSubmit:e=>(e.preventDefault(),k(null),j?.kind===`shttp`||j?.kind===`sse`?I():L()),className:`relative bg-base-secondary p-6 rounded-xl flex flex-col gap-4 border border-[var(--oh-border)] w-[520px] max-w-[90vw] max-h-[85vh] overflow-y-auto custom-scrollbar`,children:[(0,h.jsx)(o.ModalCloseButton,{onClose:y,testId:`mcp-install-modal-close`,disabled:M}),(0,h.jsxs)(`div`,{className:`flex items-start gap-3 pr-6`,children:[(0,h.jsx)(d.McpLogoBadge,{entry:e}),(0,h.jsxs)(`div`,{className:`flex flex-col flex-1`,children:[(0,h.jsx)(`h2`,{className:`text-lg font-semibold`,children:e.name}),(0,h.jsx)(`p`,{className:`text-xs text-tertiary-light`,children:e.description})]})]}),e.installHint&&(0,h.jsx)(`p`,{className:`text-xs text-tertiary-light`,children:e.installHint}),e.docsUrl&&(0,h.jsx)(`a`,{href:e.docsUrl,target:`_blank`,rel:`noreferrer`,className:`text-xs text-[var(--oh-muted)] hover:text-white hover:underline self-start transition-colors`,children:x(n.I18nKey.MCP$VIEW_DOCS)}),(0,h.jsx)(`div`,{className:`flex flex-col gap-3`,children:(()=>{if(j?.kind===`shttp`||j?.kind===`sse`){let e=g(A),t=A?_(A):!1;return(0,h.jsxs)(h.Fragment,{children:[(0,h.jsx)(c.SettingsInput,{testId:`mcp-install-field-url`,name:`url`,type:`url`,label:x(n.I18nKey.SETTINGS$MCP_URL),value:j.url,onChange:()=>{},isDisabled:!0,className:`w-full`}),e?(0,h.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[(0,h.jsx)(c.SettingsInput,{testId:`mcp-install-field-api_key`,name:`api_key`,type:`password`,label:x(n.I18nKey.SETTINGS$MCP_API_KEY),value:E.values.api_key??``,onChange:e=>N(`api_key`,e),placeholder:x(n.I18nKey.SETTINGS$MCP_API_KEY_PLACEHOLDER),showOptionalTag:t,required:!t,className:`w-full`}),E.errors.api_key&&(0,h.jsx)(`p`,{className:`text-xs text-red-500`,children:E.errors.api_key})]}):null]})}if(j?.kind!==`stdio`)return null;let e=j;return(0,h.jsxs)(h.Fragment,{children:[(0,h.jsx)(c.SettingsInput,{testId:`mcp-install-field-command-readonly`,name:`command-readonly`,type:`text`,label:x(n.I18nKey.MCP$COMMAND_LABEL),value:`${e.command} ${e.args.join(` `)}`.trim(),onChange:()=>{},isDisabled:!0,className:`w-full`}),(e.envFields??[]).map(e=>(0,h.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[(0,h.jsx)(c.SettingsInput,{testId:`mcp-install-field-${e.key}`,name:e.key,type:e.type===`password`?`password`:`text`,label:e.label,value:E.values[e.key]??``,onChange:t=>N(e.key,t),placeholder:e.placeholder,required:e.required,showOptionalTag:!e.required,className:`w-full`}),e.helperText&&(0,h.jsx)(`p`,{className:`text-xs text-tertiary-alt`,children:e.helperText}),E.errors[e.key]&&(0,h.jsx)(`p`,{className:`text-xs text-red-500`,children:E.errors[e.key]})]},e.key)),(e.argFields??[]).map(e=>(0,h.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[(0,h.jsx)(c.SettingsInput,{testId:`mcp-install-field-${e.key}`,name:e.key,type:e.type===`password`?`password`:`text`,label:e.label,value:E.values[e.key]??``,onChange:t=>N(e.key,t),placeholder:e.placeholder,required:e.required,showOptionalTag:!e.required,className:`w-full`}),e.helperText&&(0,h.jsx)(`p`,{className:`text-xs text-tertiary-alt`,children:e.helperText}),E.errors[e.key]&&(0,h.jsx)(`p`,{className:`text-xs text-red-500`,children:E.errors[e.key]})]},e.key))]})})()}),O&&(0,h.jsx)(`p`,{"data-testid":`mcp-install-modal-error`,className:`text-sm text-red-500 whitespace-pre-wrap`,children:O}),(0,h.jsxs)(`div`,{className:`flex justify-end gap-2 mt-2`,children:[(0,h.jsx)(s.BrandButton,{type:`button`,variant:`secondary`,onClick:y,testId:`mcp-install-cancel`,children:x(n.I18nKey.BUTTON$CANCEL)}),(0,h.jsx)(s.BrandButton,{type:`submit`,variant:`primary`,isDisabled:M,testId:`mcp-install-submit`,children:x(T?n.I18nKey.MCP$VERIFYING:C?n.I18nKey.SETTINGS$SAVING:n.I18nKey.MCP$INSTALL_BUTTON)})]})]})})}exports.InstallServerModal=y;
1
+ const e=require(`../../../_virtual/_rolldown/runtime.cjs`),t=require(`../../../node_modules/react-i18next/dist/es/useTranslation.cjs`),n=require(`../../../i18n/declaration.cjs`),r=require(`../../../utils/custom-toast-handlers.cjs`),i=require(`../../../node_modules/uuid/dist/v4.cjs`),a=require(`../../shared/modals/modal-backdrop.cjs`),o=require(`../../shared/modals/modal-close-button.cjs`),s=require(`../settings/brand-button.cjs`),c=require(`../settings/settings-input.cjs`),l=require(`../../../utils/retrieve-axios-error-message.cjs`),u=require(`../../../utils/mcp-marketplace-utils.cjs`),d=require(`../mcp-logo-badge.cjs`),f=require(`../../../hooks/mutation/use-add-mcp-server.cjs`),p=require(`../../../hooks/mutation/use-test-mcp-server.cjs`);let m=require(`react`);m=e.__toESM(m,1);let h=require(`react/jsx-runtime`);function g(e){let t=/\[([^\]]+)\]\(([^)]+)\)/g,n=[],r=0;for(let i of e.matchAll(t))i.index>r&&n.push(e.slice(r,i.index)),n.push((0,h.jsx)(`a`,{href:/^https?:\/\//i.test(i[2])?i[2]:`#`,target:`_blank`,rel:`noreferrer`,className:`underline hover:text-white transition-colors`,children:i[1]},i.index)),r=i.index+i[0].length;return r<e.length&&n.push(e.slice(r)),n}function _(e){return e?.transport.kind!==`shttp`&&e?.transport.kind!==`sse`?!1:[`api_key`,`bearer`,`basic`].includes(e.auth.strategy)}function v(e){return e.transport.kind===`stdio`?e.auth.apiKeyOptional??!1:e.auth.apiKeyOptional??e.transport.apiKeyOptional??!1}function y(e){let t={},n=u.getInstallableMcpConnectionOption(e),r=n?.transport;if(r?.kind===`stdio`){for(let e of r.envFields??[])t[e.key]=``;for(let e of r.argFields??[])t[e.key]=``}else _(n)&&(t.api_key=``);return{values:t,errors:{}}}function b({entry:e,onClose:b,onSuccess:x}){let{t:S}=t.useTranslation(`openhands`),{mutate:C,isPending:w}=f.useAddMcpServer(),{mutate:T,isPending:E}=p.useTestMcpServer(),[D,O]=m.default.useState(()=>y(e)),[k,A]=m.default.useState(null),j=u.getInstallableMcpConnectionOption(e),M=j?.transport,N=E||w,P=(e,t)=>{O(n=>({values:{...n.values,[e]:t},errors:{...n.errors,[e]:null}})),A(null)},F=e=>{switch(e.error_kind){case`timeout`:return S(n.I18nKey.MCP$TEST_ERROR_TIMEOUT);case`connection`:return S(n.I18nKey.MCP$TEST_ERROR_CONNECTION);default:return S(n.I18nKey.MCP$TEST_ERROR_UNKNOWN,{error:e.error})}},I=t=>{T(t,{onSuccess:i=>{if(!i.ok){A(F(i));return}C(t,{onSuccess:()=>{r.displaySuccessToast(S(n.I18nKey.MCP$INSTALL_SUCCESS)),x?.(e),b()},onError:e=>{A(l.retrieveAxiosErrorMessage(e)||S(n.I18nKey.ERROR$GENERIC))}})},onError:e=>{A(l.retrieveAxiosErrorMessage(e)||S(n.I18nKey.ERROR$GENERIC))}})},L=()=>{if(M?.kind!==`shttp`&&M?.kind!==`sse`||!j)return;let e=D.values.api_key?.trim()??``,t=_(j);if(t&&!v(j)&&!e){O(e=>({...e,errors:{api_key:S(n.I18nKey.MCP$ERROR_FIELD_REQUIRED)}}));return}I({id:`${M.kind}-${i.default()}`,type:M.kind,url:M.url,...t&&e&&{api_key:e}})},R=()=>{if(M?.kind!==`stdio`)return;let e=M,t={};for(let r of e.envFields??[])r.required&&!(D.values[r.key]??``).trim()&&(t[r.key]=S(n.I18nKey.MCP$ERROR_FIELD_REQUIRED));for(let r of e.argFields??[])r.required&&!(D.values[r.key]??``).trim()&&(t[r.key]=S(n.I18nKey.MCP$ERROR_FIELD_REQUIRED));if(Object.values(t).some(Boolean)){O(e=>({...e,errors:t}));return}let r={};for(let t of e.envFields??[]){let e=D.values[t.key]?.trim();e&&(r[t.key]=e)}let a=[];for(let t of e.argFields??[]){let e=D.values[t.key]?.trim();if(e)for(let t of e.split(/\s+/))t&&a.push(t)}I({id:`stdio-${i.default()}`,type:`stdio`,name:e.serverName,command:e.command,args:[...e.args,...a],...Object.keys(r).length>0&&{env:r}})};return(0,h.jsx)(a.ModalBackdrop,{onClose:b,"aria-label":e.name,children:(0,h.jsxs)(`form`,{"data-testid":`mcp-install-modal`,"data-marketplace-id":e.id,onSubmit:e=>(e.preventDefault(),A(null),M?.kind===`shttp`||M?.kind===`sse`?L():R()),className:`relative bg-base-secondary p-6 rounded-xl flex flex-col gap-4 border border-[var(--oh-border)] w-[520px] max-w-[90vw] max-h-[85vh] overflow-y-auto custom-scrollbar`,children:[(0,h.jsx)(o.ModalCloseButton,{onClose:b,testId:`mcp-install-modal-close`,disabled:N}),(0,h.jsxs)(`div`,{className:`flex items-start gap-3 pr-6`,children:[(0,h.jsx)(d.McpLogoBadge,{entry:e}),(0,h.jsxs)(`div`,{className:`flex flex-col flex-1`,children:[(0,h.jsx)(`h2`,{className:`text-lg font-semibold`,children:e.name}),(0,h.jsx)(`p`,{className:`text-xs text-tertiary-light`,children:e.description})]})]}),e.installHint&&(0,h.jsx)(`p`,{className:`text-xs text-tertiary-light`,children:e.installHint}),e.docsUrl&&(0,h.jsx)(`a`,{href:e.docsUrl,target:`_blank`,rel:`noreferrer`,className:`text-xs text-[var(--oh-muted)] hover:text-white hover:underline self-start transition-colors`,children:S(n.I18nKey.MCP$VIEW_DOCS)}),(0,h.jsx)(`div`,{className:`flex flex-col gap-3`,children:(()=>{if(M?.kind===`shttp`||M?.kind===`sse`){let e=_(j),t=j?v(j):!1;return(0,h.jsxs)(h.Fragment,{children:[(0,h.jsx)(c.SettingsInput,{testId:`mcp-install-field-url`,name:`url`,type:`url`,label:S(n.I18nKey.SETTINGS$MCP_URL),value:M.url,onChange:()=>{},isDisabled:!0,className:`w-full`}),e?(0,h.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[(0,h.jsx)(c.SettingsInput,{testId:`mcp-install-field-api_key`,name:`api_key`,type:`password`,label:S(n.I18nKey.SETTINGS$MCP_API_KEY),value:D.values.api_key??``,onChange:e=>P(`api_key`,e),placeholder:S(n.I18nKey.SETTINGS$MCP_API_KEY_PLACEHOLDER),showOptionalTag:t,required:!t,className:`w-full`}),D.errors.api_key&&(0,h.jsx)(`p`,{className:`text-xs text-red-500`,children:D.errors.api_key})]}):null]})}if(M?.kind!==`stdio`)return null;let e=M;return(0,h.jsxs)(h.Fragment,{children:[(0,h.jsx)(c.SettingsInput,{testId:`mcp-install-field-command-readonly`,name:`command-readonly`,type:`text`,label:S(n.I18nKey.MCP$COMMAND_LABEL),value:`${e.command} ${e.args.join(` `)}`.trim(),onChange:()=>{},isDisabled:!0,className:`w-full`}),(e.envFields??[]).map(e=>(0,h.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[(0,h.jsx)(c.SettingsInput,{testId:`mcp-install-field-${e.key}`,name:e.key,type:e.type===`password`?`password`:`text`,label:e.label,value:D.values[e.key]??``,onChange:t=>P(e.key,t),placeholder:e.placeholder,required:e.required,showOptionalTag:!e.required,className:`w-full`}),e.helperText&&(0,h.jsx)(`p`,{className:`text-xs text-tertiary-alt`,children:g(e.helperText)}),D.errors[e.key]&&(0,h.jsx)(`p`,{className:`text-xs text-red-500`,children:D.errors[e.key]})]},e.key)),(e.argFields??[]).map(e=>(0,h.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[(0,h.jsx)(c.SettingsInput,{testId:`mcp-install-field-${e.key}`,name:e.key,type:e.type===`password`?`password`:`text`,label:e.label,value:D.values[e.key]??``,onChange:t=>P(e.key,t),placeholder:e.placeholder,required:e.required,showOptionalTag:!e.required,className:`w-full`}),e.helperText&&(0,h.jsx)(`p`,{className:`text-xs text-tertiary-alt`,children:g(e.helperText)}),D.errors[e.key]&&(0,h.jsx)(`p`,{className:`text-xs text-red-500`,children:D.errors[e.key]})]},e.key))]})})()}),k&&(0,h.jsx)(`p`,{"data-testid":`mcp-install-modal-error`,className:`text-sm text-red-500 whitespace-pre-wrap`,children:k}),(0,h.jsxs)(`div`,{className:`flex justify-end gap-2 mt-2`,children:[(0,h.jsx)(s.BrandButton,{type:`button`,variant:`secondary`,onClick:b,testId:`mcp-install-cancel`,children:S(n.I18nKey.BUTTON$CANCEL)}),(0,h.jsx)(s.BrandButton,{type:`submit`,variant:`primary`,isDisabled:N,testId:`mcp-install-submit`,children:S(E?n.I18nKey.MCP$VERIFYING:w?n.I18nKey.SETTINGS$SAVING:n.I18nKey.MCP$INSTALL_BUTTON)})]})]})})}exports.InstallServerModal=b;
2
2
  //# sourceMappingURL=install-server-modal.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"install-server-modal.cjs","names":[],"sources":["../../../../src/components/features/mcp-page/install-server-modal.tsx"],"sourcesContent":["import React from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { AxiosError } from \"axios\";\nimport { v4 as uuidv4 } from \"uuid\";\nimport type { MCPTestFailure } from \"@openhands/typescript-client\";\nimport { ModalBackdrop } from \"#/components/shared/modals/modal-backdrop\";\nimport { ModalCloseButton } from \"#/components/shared/modals/modal-close-button\";\nimport { BrandButton } from \"#/components/features/settings/brand-button\";\nimport { SettingsInput } from \"#/components/features/settings/settings-input\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport type { IntegrationCatalogEntry as MarketplaceEntry } from \"@openhands/extensions/integrations\";\nimport { McpLogoBadge } from \"#/components/features/mcp-logo-badge\";\nimport { MCPServerConfig } from \"#/types/mcp-server\";\nimport { useAddMcpServer } from \"#/hooks/mutation/use-add-mcp-server\";\nimport { useTestMcpServer } from \"#/hooks/mutation/use-test-mcp-server\";\nimport { displaySuccessToast } from \"#/utils/custom-toast-handlers\";\nimport {\n getInstallableMcpConnectionOption,\n type McpMarketplaceConnectionOption,\n} from \"#/utils/mcp-marketplace-utils\";\nimport { retrieveAxiosErrorMessage } from \"#/utils/retrieve-axios-error-message\";\n\ninterface InstallServerModalProps {\n entry: MarketplaceEntry;\n onClose: () => void;\n onSuccess?: (entry: MarketplaceEntry) => void;\n}\n\ninterface FieldState {\n values: Record<string, string>;\n errors: Record<string, string | null>;\n}\n\nfunction optionNeedsCredentialField(\n option: McpMarketplaceConnectionOption | undefined,\n): boolean {\n if (option?.transport.kind !== \"shttp\" && option?.transport.kind !== \"sse\") {\n return false;\n }\n return [\"api_key\", \"bearer\", \"basic\"].includes(option.auth.strategy);\n}\n\nfunction isCredentialOptional(option: McpMarketplaceConnectionOption): boolean {\n if (option.transport.kind === \"stdio\") {\n return option.auth.apiKeyOptional ?? false;\n }\n return option.auth.apiKeyOptional ?? option.transport.apiKeyOptional ?? false;\n}\n\nfunction makeInitialState(entry: MarketplaceEntry): FieldState {\n const values: Record<string, string> = {};\n const option = getInstallableMcpConnectionOption(entry);\n const template = option?.transport;\n if (template?.kind === \"stdio\") {\n for (const field of template.envFields ?? []) {\n values[field.key] = \"\";\n }\n for (const field of template.argFields ?? []) {\n values[field.key] = \"\";\n }\n } else if (optionNeedsCredentialField(option)) {\n values.api_key = \"\";\n }\n return { values, errors: {} };\n}\n\n// The marketplace install modal is intentionally add-only: clicking\n// a catalog tile always appends a new server (the user might want\n// two Slack workspaces, two Postgres connections, etc.) even when\n// one of the same template kind is already installed. Editing an\n// existing server is reached via the installed-server-card's edit\n// button, which opens `CustomServerEditor` instead.\nexport function InstallServerModal({\n entry,\n onClose,\n onSuccess,\n}: InstallServerModalProps) {\n const { t } = useTranslation(\"openhands\");\n const { mutate: addMcpServer, isPending: isAdding } = useAddMcpServer();\n const { mutate: testMcpServer, isPending: isTesting } = useTestMcpServer();\n\n const [state, setState] = React.useState<FieldState>(() =>\n makeInitialState(entry),\n );\n const [globalError, setGlobalError] = React.useState<string | null>(null);\n const option = getInstallableMcpConnectionOption(entry);\n const template = option?.transport;\n\n const isPending = isTesting || isAdding;\n\n const setValue = (key: string, value: string) => {\n setState((prev) => ({\n values: { ...prev.values, [key]: value },\n errors: { ...prev.errors, [key]: null },\n }));\n setGlobalError(null);\n };\n\n const makeTestErrorMessage = (failure: MCPTestFailure): string => {\n switch (failure.error_kind) {\n case \"timeout\":\n return t(I18nKey.MCP$TEST_ERROR_TIMEOUT);\n case \"connection\":\n return t(I18nKey.MCP$TEST_ERROR_CONNECTION);\n default:\n return t(I18nKey.MCP$TEST_ERROR_UNKNOWN, { error: failure.error });\n }\n };\n\n const submitServer = (payload: MCPServerConfig) => {\n testMcpServer(payload, {\n onSuccess: (result) => {\n if (!result.ok) {\n setGlobalError(makeTestErrorMessage(result));\n // Modal stays open — do NOT call onClose.\n return;\n }\n addMcpServer(payload, {\n onSuccess: () => {\n displaySuccessToast(t(I18nKey.MCP$INSTALL_SUCCESS));\n onSuccess?.(entry);\n onClose();\n },\n onError: (err: unknown) => {\n const message = retrieveAxiosErrorMessage(err as AxiosError);\n setGlobalError(message || t(I18nKey.ERROR$GENERIC));\n },\n });\n },\n onError: (err: unknown) => {\n const message = retrieveAxiosErrorMessage(err as AxiosError);\n setGlobalError(message || t(I18nKey.ERROR$GENERIC));\n },\n });\n };\n\n // ------------------------------------------------------------------\n // Per-template submit handlers. Each is small and self-contained:\n // validate user input, build the payload, then hand off to\n // submitServer.\n // ------------------------------------------------------------------\n const handleHttpServerSubmit = () => {\n // TS narrows this branch to shttp|sse; the equality guard is a\n // runtime/defensive belt to make the helper safe in isolation.\n if (template?.kind !== \"shttp\" && template?.kind !== \"sse\") {\n return;\n }\n if (!option) return;\n const apiKey = state.values.api_key?.trim() ?? \"\";\n const needsCredential = optionNeedsCredentialField(option);\n if (needsCredential && !isCredentialOptional(option) && !apiKey) {\n setState((prev) => ({\n ...prev,\n errors: { api_key: t(I18nKey.MCP$ERROR_FIELD_REQUIRED) },\n }));\n return;\n }\n const payload: MCPServerConfig = {\n id: `${template.kind}-${uuidv4()}`,\n type: template.kind,\n url: template.url,\n ...(needsCredential && apiKey && { api_key: apiKey }),\n };\n submitServer(payload);\n };\n\n const handleStdioSubmit = () => {\n if (template?.kind !== \"stdio\") return;\n const stdio = template;\n const errors: Record<string, string | null> = {};\n\n for (const field of stdio.envFields ?? []) {\n if (field.required && !(state.values[field.key] ?? \"\").trim()) {\n errors[field.key] = t(I18nKey.MCP$ERROR_FIELD_REQUIRED);\n }\n }\n for (const field of stdio.argFields ?? []) {\n if (field.required && !(state.values[field.key] ?? \"\").trim()) {\n errors[field.key] = t(I18nKey.MCP$ERROR_FIELD_REQUIRED);\n }\n }\n if (Object.values(errors).some(Boolean)) {\n setState((prev) => ({ ...prev, errors }));\n return;\n }\n\n const env: Record<string, string> = {};\n for (const field of stdio.envFields ?? []) {\n const v = state.values[field.key]?.trim();\n if (v) env[field.key] = v;\n }\n const extraArgs: string[] = [];\n for (const field of stdio.argFields ?? []) {\n const v = state.values[field.key]?.trim();\n if (v) {\n // Filesystem-style multi-token input: split on whitespace.\n for (const token of v.split(/\\s+/)) {\n if (token) extraArgs.push(token);\n }\n }\n }\n\n const payload: MCPServerConfig = {\n id: `stdio-${uuidv4()}`,\n type: \"stdio\",\n name: stdio.serverName,\n command: stdio.command,\n args: [...stdio.args, ...extraArgs],\n ...(Object.keys(env).length > 0 && { env }),\n };\n submitServer(payload);\n };\n\n const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n setGlobalError(null);\n if (template?.kind === \"shttp\" || template?.kind === \"sse\") {\n return handleHttpServerSubmit();\n }\n return handleStdioSubmit();\n };\n\n const renderFields = () => {\n if (template?.kind === \"shttp\" || template?.kind === \"sse\") {\n const shouldRenderCredential = optionNeedsCredentialField(option);\n const apiKeyOptional = option ? isCredentialOptional(option) : false;\n return (\n <>\n <SettingsInput\n testId=\"mcp-install-field-url\"\n name=\"url\"\n type=\"url\"\n label={t(I18nKey.SETTINGS$MCP_URL)}\n value={template.url}\n onChange={() => {}}\n isDisabled\n className=\"w-full\"\n />\n {shouldRenderCredential ? (\n <div className=\"flex flex-col gap-1\">\n <SettingsInput\n testId=\"mcp-install-field-api_key\"\n name=\"api_key\"\n type=\"password\"\n label={t(I18nKey.SETTINGS$MCP_API_KEY)}\n value={state.values.api_key ?? \"\"}\n onChange={(v) => setValue(\"api_key\", v)}\n placeholder={t(I18nKey.SETTINGS$MCP_API_KEY_PLACEHOLDER)}\n showOptionalTag={apiKeyOptional}\n required={!apiKeyOptional}\n className=\"w-full\"\n />\n {state.errors.api_key && (\n <p className=\"text-xs text-red-500\">{state.errors.api_key}</p>\n )}\n </div>\n ) : null}\n </>\n );\n }\n\n if (template?.kind !== \"stdio\") return null;\n const stdio = template;\n return (\n <>\n <SettingsInput\n testId=\"mcp-install-field-command-readonly\"\n name=\"command-readonly\"\n type=\"text\"\n label={t(I18nKey.MCP$COMMAND_LABEL)}\n value={`${stdio.command} ${stdio.args.join(\" \")}`.trim()}\n onChange={() => {}}\n isDisabled\n className=\"w-full\"\n />\n {(stdio.envFields ?? []).map((field) => (\n <div key={field.key} className=\"flex flex-col gap-1\">\n <SettingsInput\n testId={`mcp-install-field-${field.key}`}\n name={field.key}\n type={field.type === \"password\" ? \"password\" : \"text\"}\n label={field.label}\n value={state.values[field.key] ?? \"\"}\n onChange={(v) => setValue(field.key, v)}\n placeholder={field.placeholder}\n required={field.required}\n showOptionalTag={!field.required}\n className=\"w-full\"\n />\n {field.helperText && (\n <p className=\"text-xs text-tertiary-alt\">{field.helperText}</p>\n )}\n {state.errors[field.key] && (\n <p className=\"text-xs text-red-500\">{state.errors[field.key]}</p>\n )}\n </div>\n ))}\n {(stdio.argFields ?? []).map((field) => (\n <div key={field.key} className=\"flex flex-col gap-1\">\n <SettingsInput\n testId={`mcp-install-field-${field.key}`}\n name={field.key}\n type={field.type === \"password\" ? \"password\" : \"text\"}\n label={field.label}\n value={state.values[field.key] ?? \"\"}\n onChange={(v) => setValue(field.key, v)}\n placeholder={field.placeholder}\n required={field.required}\n showOptionalTag={!field.required}\n className=\"w-full\"\n />\n {field.helperText && (\n <p className=\"text-xs text-tertiary-alt\">{field.helperText}</p>\n )}\n {state.errors[field.key] && (\n <p className=\"text-xs text-red-500\">{state.errors[field.key]}</p>\n )}\n </div>\n ))}\n </>\n );\n };\n\n return (\n <ModalBackdrop onClose={onClose} aria-label={entry.name}>\n <form\n data-testid=\"mcp-install-modal\"\n data-marketplace-id={entry.id}\n onSubmit={handleSubmit}\n className=\"relative bg-base-secondary p-6 rounded-xl flex flex-col gap-4 border border-[var(--oh-border)] w-[520px] max-w-[90vw] max-h-[85vh] overflow-y-auto custom-scrollbar\"\n >\n <ModalCloseButton\n onClose={onClose}\n testId=\"mcp-install-modal-close\"\n disabled={isPending}\n />\n <div className=\"flex items-start gap-3 pr-6\">\n <McpLogoBadge entry={entry} />\n <div className=\"flex flex-col flex-1\">\n <h2 className=\"text-lg font-semibold\">{entry.name}</h2>\n <p className=\"text-xs text-tertiary-light\">{entry.description}</p>\n </div>\n </div>\n\n {entry.installHint && (\n <p className=\"text-xs text-tertiary-light\">{entry.installHint}</p>\n )}\n\n {entry.docsUrl && (\n <a\n href={entry.docsUrl}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"text-xs text-[var(--oh-muted)] hover:text-white hover:underline self-start transition-colors\"\n >\n {t(I18nKey.MCP$VIEW_DOCS)}\n </a>\n )}\n\n <div className=\"flex flex-col gap-3\">{renderFields()}</div>\n\n {globalError && (\n <p\n data-testid=\"mcp-install-modal-error\"\n className=\"text-sm text-red-500 whitespace-pre-wrap\"\n >\n {globalError}\n </p>\n )}\n\n <div className=\"flex justify-end gap-2 mt-2\">\n <BrandButton\n type=\"button\"\n variant=\"secondary\"\n onClick={onClose}\n testId=\"mcp-install-cancel\"\n >\n {t(I18nKey.BUTTON$CANCEL)}\n </BrandButton>\n <BrandButton\n type=\"submit\"\n variant=\"primary\"\n isDisabled={isPending}\n testId=\"mcp-install-submit\"\n >\n {isTesting\n ? t(I18nKey.MCP$VERIFYING)\n : isAdding\n ? t(I18nKey.SETTINGS$SAVING)\n : t(I18nKey.MCP$INSTALL_BUTTON)}\n </BrandButton>\n </div>\n </form>\n </ModalBackdrop>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"install-server-modal.cjs","names":[],"sources":["../../../../src/components/features/mcp-page/install-server-modal.tsx"],"sourcesContent":["import React from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { AxiosError } from \"axios\";\nimport { v4 as uuidv4 } from \"uuid\";\nimport type { MCPTestFailure } from \"@openhands/typescript-client\";\nimport { ModalBackdrop } from \"#/components/shared/modals/modal-backdrop\";\nimport { ModalCloseButton } from \"#/components/shared/modals/modal-close-button\";\nimport { BrandButton } from \"#/components/features/settings/brand-button\";\nimport { SettingsInput } from \"#/components/features/settings/settings-input\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport type { IntegrationCatalogEntry as MarketplaceEntry } from \"@openhands/extensions/integrations\";\nimport { McpLogoBadge } from \"#/components/features/mcp-logo-badge\";\nimport { MCPServerConfig } from \"#/types/mcp-server\";\nimport { useAddMcpServer } from \"#/hooks/mutation/use-add-mcp-server\";\nimport { useTestMcpServer } from \"#/hooks/mutation/use-test-mcp-server\";\nimport { displaySuccessToast } from \"#/utils/custom-toast-handlers\";\nimport {\n getInstallableMcpConnectionOption,\n type McpMarketplaceConnectionOption,\n} from \"#/utils/mcp-marketplace-utils\";\nimport { retrieveAxiosErrorMessage } from \"#/utils/retrieve-axios-error-message\";\n\n/**\n * Renders a helperText string as React nodes, converting any `[text](url)`\n * markdown links into real `<a>` elements. Plain text segments are left as-is.\n * Only `http:` and `https:` URLs are rendered as links; anything else falls\n * back to `#` to guard against `javascript:` / `data:` XSS vectors.\n */\nfunction renderHelperText(text: string): React.ReactNode {\n const linkPattern = /\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\n const parts: React.ReactNode[] = [];\n let lastIndex = 0;\n for (const match of text.matchAll(linkPattern)) {\n if (match.index > lastIndex) {\n parts.push(text.slice(lastIndex, match.index));\n }\n parts.push(\n <a\n key={match.index}\n href={/^https?:\\/\\//i.test(match[2]) ? match[2] : \"#\"}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"underline hover:text-white transition-colors\"\n >\n {match[1]}\n </a>,\n );\n lastIndex = match.index + match[0].length;\n }\n if (lastIndex < text.length) {\n parts.push(text.slice(lastIndex));\n }\n return parts;\n}\n\ninterface InstallServerModalProps {\n entry: MarketplaceEntry;\n onClose: () => void;\n onSuccess?: (entry: MarketplaceEntry) => void;\n}\n\ninterface FieldState {\n values: Record<string, string>;\n errors: Record<string, string | null>;\n}\n\nfunction optionNeedsCredentialField(\n option: McpMarketplaceConnectionOption | undefined,\n): boolean {\n if (option?.transport.kind !== \"shttp\" && option?.transport.kind !== \"sse\") {\n return false;\n }\n return [\"api_key\", \"bearer\", \"basic\"].includes(option.auth.strategy);\n}\n\nfunction isCredentialOptional(option: McpMarketplaceConnectionOption): boolean {\n if (option.transport.kind === \"stdio\") {\n return option.auth.apiKeyOptional ?? false;\n }\n return option.auth.apiKeyOptional ?? option.transport.apiKeyOptional ?? false;\n}\n\nfunction makeInitialState(entry: MarketplaceEntry): FieldState {\n const values: Record<string, string> = {};\n const option = getInstallableMcpConnectionOption(entry);\n const template = option?.transport;\n if (template?.kind === \"stdio\") {\n for (const field of template.envFields ?? []) {\n values[field.key] = \"\";\n }\n for (const field of template.argFields ?? []) {\n values[field.key] = \"\";\n }\n } else if (optionNeedsCredentialField(option)) {\n values.api_key = \"\";\n }\n return { values, errors: {} };\n}\n\n// The marketplace install modal is intentionally add-only: clicking\n// a catalog tile always appends a new server (the user might want\n// two Slack workspaces, two Postgres connections, etc.) even when\n// one of the same template kind is already installed. Editing an\n// existing server is reached via the installed-server-card's edit\n// button, which opens `CustomServerEditor` instead.\nexport function InstallServerModal({\n entry,\n onClose,\n onSuccess,\n}: InstallServerModalProps) {\n const { t } = useTranslation(\"openhands\");\n const { mutate: addMcpServer, isPending: isAdding } = useAddMcpServer();\n const { mutate: testMcpServer, isPending: isTesting } = useTestMcpServer();\n\n const [state, setState] = React.useState<FieldState>(() =>\n makeInitialState(entry),\n );\n const [globalError, setGlobalError] = React.useState<string | null>(null);\n const option = getInstallableMcpConnectionOption(entry);\n const template = option?.transport;\n\n const isPending = isTesting || isAdding;\n\n const setValue = (key: string, value: string) => {\n setState((prev) => ({\n values: { ...prev.values, [key]: value },\n errors: { ...prev.errors, [key]: null },\n }));\n setGlobalError(null);\n };\n\n const makeTestErrorMessage = (failure: MCPTestFailure): string => {\n switch (failure.error_kind) {\n case \"timeout\":\n return t(I18nKey.MCP$TEST_ERROR_TIMEOUT);\n case \"connection\":\n return t(I18nKey.MCP$TEST_ERROR_CONNECTION);\n default:\n return t(I18nKey.MCP$TEST_ERROR_UNKNOWN, { error: failure.error });\n }\n };\n\n const submitServer = (payload: MCPServerConfig) => {\n testMcpServer(payload, {\n onSuccess: (result) => {\n if (!result.ok) {\n setGlobalError(makeTestErrorMessage(result));\n // Modal stays open — do NOT call onClose.\n return;\n }\n addMcpServer(payload, {\n onSuccess: () => {\n displaySuccessToast(t(I18nKey.MCP$INSTALL_SUCCESS));\n onSuccess?.(entry);\n onClose();\n },\n onError: (err: unknown) => {\n const message = retrieveAxiosErrorMessage(err as AxiosError);\n setGlobalError(message || t(I18nKey.ERROR$GENERIC));\n },\n });\n },\n onError: (err: unknown) => {\n const message = retrieveAxiosErrorMessage(err as AxiosError);\n setGlobalError(message || t(I18nKey.ERROR$GENERIC));\n },\n });\n };\n\n // ------------------------------------------------------------------\n // Per-template submit handlers. Each is small and self-contained:\n // validate user input, build the payload, then hand off to\n // submitServer.\n // ------------------------------------------------------------------\n const handleHttpServerSubmit = () => {\n // TS narrows this branch to shttp|sse; the equality guard is a\n // runtime/defensive belt to make the helper safe in isolation.\n if (template?.kind !== \"shttp\" && template?.kind !== \"sse\") {\n return;\n }\n if (!option) return;\n const apiKey = state.values.api_key?.trim() ?? \"\";\n const needsCredential = optionNeedsCredentialField(option);\n if (needsCredential && !isCredentialOptional(option) && !apiKey) {\n setState((prev) => ({\n ...prev,\n errors: { api_key: t(I18nKey.MCP$ERROR_FIELD_REQUIRED) },\n }));\n return;\n }\n const payload: MCPServerConfig = {\n id: `${template.kind}-${uuidv4()}`,\n type: template.kind,\n url: template.url,\n ...(needsCredential && apiKey && { api_key: apiKey }),\n };\n submitServer(payload);\n };\n\n const handleStdioSubmit = () => {\n if (template?.kind !== \"stdio\") return;\n const stdio = template;\n const errors: Record<string, string | null> = {};\n\n for (const field of stdio.envFields ?? []) {\n if (field.required && !(state.values[field.key] ?? \"\").trim()) {\n errors[field.key] = t(I18nKey.MCP$ERROR_FIELD_REQUIRED);\n }\n }\n for (const field of stdio.argFields ?? []) {\n if (field.required && !(state.values[field.key] ?? \"\").trim()) {\n errors[field.key] = t(I18nKey.MCP$ERROR_FIELD_REQUIRED);\n }\n }\n if (Object.values(errors).some(Boolean)) {\n setState((prev) => ({ ...prev, errors }));\n return;\n }\n\n const env: Record<string, string> = {};\n for (const field of stdio.envFields ?? []) {\n const v = state.values[field.key]?.trim();\n if (v) env[field.key] = v;\n }\n const extraArgs: string[] = [];\n for (const field of stdio.argFields ?? []) {\n const v = state.values[field.key]?.trim();\n if (v) {\n // Filesystem-style multi-token input: split on whitespace.\n for (const token of v.split(/\\s+/)) {\n if (token) extraArgs.push(token);\n }\n }\n }\n\n const payload: MCPServerConfig = {\n id: `stdio-${uuidv4()}`,\n type: \"stdio\",\n name: stdio.serverName,\n command: stdio.command,\n args: [...stdio.args, ...extraArgs],\n ...(Object.keys(env).length > 0 && { env }),\n };\n submitServer(payload);\n };\n\n const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n setGlobalError(null);\n if (template?.kind === \"shttp\" || template?.kind === \"sse\") {\n return handleHttpServerSubmit();\n }\n return handleStdioSubmit();\n };\n\n const renderFields = () => {\n if (template?.kind === \"shttp\" || template?.kind === \"sse\") {\n const shouldRenderCredential = optionNeedsCredentialField(option);\n const apiKeyOptional = option ? isCredentialOptional(option) : false;\n return (\n <>\n <SettingsInput\n testId=\"mcp-install-field-url\"\n name=\"url\"\n type=\"url\"\n label={t(I18nKey.SETTINGS$MCP_URL)}\n value={template.url}\n onChange={() => {}}\n isDisabled\n className=\"w-full\"\n />\n {shouldRenderCredential ? (\n <div className=\"flex flex-col gap-1\">\n <SettingsInput\n testId=\"mcp-install-field-api_key\"\n name=\"api_key\"\n type=\"password\"\n label={t(I18nKey.SETTINGS$MCP_API_KEY)}\n value={state.values.api_key ?? \"\"}\n onChange={(v) => setValue(\"api_key\", v)}\n placeholder={t(I18nKey.SETTINGS$MCP_API_KEY_PLACEHOLDER)}\n showOptionalTag={apiKeyOptional}\n required={!apiKeyOptional}\n className=\"w-full\"\n />\n {state.errors.api_key && (\n <p className=\"text-xs text-red-500\">{state.errors.api_key}</p>\n )}\n </div>\n ) : null}\n </>\n );\n }\n\n if (template?.kind !== \"stdio\") return null;\n const stdio = template;\n return (\n <>\n <SettingsInput\n testId=\"mcp-install-field-command-readonly\"\n name=\"command-readonly\"\n type=\"text\"\n label={t(I18nKey.MCP$COMMAND_LABEL)}\n value={`${stdio.command} ${stdio.args.join(\" \")}`.trim()}\n onChange={() => {}}\n isDisabled\n className=\"w-full\"\n />\n {(stdio.envFields ?? []).map((field) => (\n <div key={field.key} className=\"flex flex-col gap-1\">\n <SettingsInput\n testId={`mcp-install-field-${field.key}`}\n name={field.key}\n type={field.type === \"password\" ? \"password\" : \"text\"}\n label={field.label}\n value={state.values[field.key] ?? \"\"}\n onChange={(v) => setValue(field.key, v)}\n placeholder={field.placeholder}\n required={field.required}\n showOptionalTag={!field.required}\n className=\"w-full\"\n />\n {field.helperText && (\n <p className=\"text-xs text-tertiary-alt\">\n {renderHelperText(field.helperText)}\n </p>\n )}\n {state.errors[field.key] && (\n <p className=\"text-xs text-red-500\">{state.errors[field.key]}</p>\n )}\n </div>\n ))}\n {(stdio.argFields ?? []).map((field) => (\n <div key={field.key} className=\"flex flex-col gap-1\">\n <SettingsInput\n testId={`mcp-install-field-${field.key}`}\n name={field.key}\n type={field.type === \"password\" ? \"password\" : \"text\"}\n label={field.label}\n value={state.values[field.key] ?? \"\"}\n onChange={(v) => setValue(field.key, v)}\n placeholder={field.placeholder}\n required={field.required}\n showOptionalTag={!field.required}\n className=\"w-full\"\n />\n {field.helperText && (\n <p className=\"text-xs text-tertiary-alt\">\n {renderHelperText(field.helperText)}\n </p>\n )}\n {state.errors[field.key] && (\n <p className=\"text-xs text-red-500\">{state.errors[field.key]}</p>\n )}\n </div>\n ))}\n </>\n );\n };\n\n return (\n <ModalBackdrop onClose={onClose} aria-label={entry.name}>\n <form\n data-testid=\"mcp-install-modal\"\n data-marketplace-id={entry.id}\n onSubmit={handleSubmit}\n className=\"relative bg-base-secondary p-6 rounded-xl flex flex-col gap-4 border border-[var(--oh-border)] w-[520px] max-w-[90vw] max-h-[85vh] overflow-y-auto custom-scrollbar\"\n >\n <ModalCloseButton\n onClose={onClose}\n testId=\"mcp-install-modal-close\"\n disabled={isPending}\n />\n <div className=\"flex items-start gap-3 pr-6\">\n <McpLogoBadge entry={entry} />\n <div className=\"flex flex-col flex-1\">\n <h2 className=\"text-lg font-semibold\">{entry.name}</h2>\n <p className=\"text-xs text-tertiary-light\">{entry.description}</p>\n </div>\n </div>\n\n {entry.installHint && (\n <p className=\"text-xs text-tertiary-light\">{entry.installHint}</p>\n )}\n\n {entry.docsUrl && (\n <a\n href={entry.docsUrl}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"text-xs text-[var(--oh-muted)] hover:text-white hover:underline self-start transition-colors\"\n >\n {t(I18nKey.MCP$VIEW_DOCS)}\n </a>\n )}\n\n <div className=\"flex flex-col gap-3\">{renderFields()}</div>\n\n {globalError && (\n <p\n data-testid=\"mcp-install-modal-error\"\n className=\"text-sm text-red-500 whitespace-pre-wrap\"\n >\n {globalError}\n </p>\n )}\n\n <div className=\"flex justify-end gap-2 mt-2\">\n <BrandButton\n type=\"button\"\n variant=\"secondary\"\n onClick={onClose}\n testId=\"mcp-install-cancel\"\n >\n {t(I18nKey.BUTTON$CANCEL)}\n </BrandButton>\n <BrandButton\n type=\"submit\"\n variant=\"primary\"\n isDisabled={isPending}\n testId=\"mcp-install-submit\"\n >\n {isTesting\n ? t(I18nKey.MCP$VERIFYING)\n : isAdding\n ? t(I18nKey.SETTINGS$SAVING)\n : t(I18nKey.MCP$INSTALL_BUTTON)}\n </BrandButton>\n </div>\n </form>\n </ModalBackdrop>\n );\n}\n"],"mappings":"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"}