diff --git a/docs/mcp/index.md b/docs/mcp/index.md index cce812b516..fb9c927106 100644 --- a/docs/mcp/index.md +++ b/docs/mcp/index.md @@ -81,7 +81,7 @@ Some important concepts for users: Connect the tabs you want to use: -* **Remote MCP**: choose **MCP → Connect** in the dashboard sidebar or a file's toolbar. Use **Disconnect** in the same place to disconnect that tab. +* **Remote MCP**: choose **MCP → Connect** in the dashboard header or a file's toolbar. Use **Disconnect** in the same place to disconnect that tab. * **Local MCP**: run the plugin in each file and connect it to your local server. Each plugin connection has its own session ID. * Connecting or disconnecting one tab does not disconnect the others. * A connected tab stays connected while navigating between the dashboard and files. Its session ID stays the same; requests operate on the currently open file. diff --git a/frontend/src/app/main/ui/components/mcp_menu.cljs b/frontend/src/app/main/ui/components/mcp_menu.cljs index f38e4f377b..8e5091bfd3 100644 --- a/frontend/src/app/main/ui/components/mcp_menu.cljs +++ b/frontend/src/app/main/ui/components/mcp_menu.cljs @@ -7,9 +7,11 @@ (ns app.main.ui.components.mcp-menu (:require-macros [app.main.style :as stl]) (:require + [app.config :as cf] [app.main.data.event :as ev] [app.main.data.notifications :as ntf] [app.main.data.workspace.mcp :as mcp] + [app.main.refs :as refs] [app.main.store :as st] [app.main.ui.components.dropdown-menu :refer [dropdown-menu* dropdown-menu-item*]] [app.main.ui.ds.buttons.button :refer [button*]] @@ -36,13 +38,13 @@ open-timer* (mf/use-ref nil) close-timer* (mf/use-ref nil) - on-open-menu + on-toggle-menu (mf/use-fn (fn [event] (dom/stop-propagation event) (cancel-timer! open-timer*) (cancel-timer! close-timer*) - (reset! menu-open* true))) + (swap! menu-open* not))) on-close-menu (mf/use-fn @@ -80,7 +82,7 @@ (mf/deps dashboard) #(st/emit! (mcp/connect-mcp) (ev/event {::ev/name "connect-mcp-plugin" - ::ev/origin (if dashboard "dashboard:sidebar" "workspace:toolbar")}))) + ::ev/origin (if dashboard "dashboard:header" "workspace:toolbar")}))) on-disconnect (mf/use-fn @@ -102,8 +104,8 @@ [:div {:class (stl/css-case :mcp-tool true :dashboard dashboard) :on-pointer-enter on-display-menu :on-pointer-leave on-hide-menu} - [:> button* {:variant "ghost" - :on-click on-open-menu + [:> button* {:variant (if dashboard "secondary" "ghost") + :on-click on-toggle-menu :aria-haspopup true :aria-expanded menu-open? :aria-pressed menu-open? @@ -115,9 +117,7 @@ :connected is-mcp-connected)}] [:span {:class (stl/css-case :toolbar-mcp-button-label true :connected is-mcp-connected)} - (if (and dashboard is-mcp-connected) - (tr "workspace.toolbar.mcp-connected") - (tr "workspace.toolbar.mcp"))]]] + (tr "workspace.toolbar.mcp")]]] [:div {:class (stl/css :toolbar-mcp-menu)} [:> dropdown-menu* {:show menu-open? @@ -139,3 +139,14 @@ (if is-connection-requested (tr "workspace.header.menu.mcp.plugin.status.disconnect") (tr "workspace.header.menu.mcp.plugin.status.connect"))]]]])) + +(mf/defc dashboard-mcp-menu* + [] + (let [mcp-state (mf/deref refs/mcp)] + (when (and (contains? cf/flags :mcp) + (:enabled mcp-state) + (:token-valid mcp-state)) + [:> mcp-menu* {:dashboard true + :is-mcp-connected (= "connected" (:connection-status mcp-state)) + :is-connection-requested (:connection-requested mcp-state) + :session-id (:session-id mcp-state)}]))) diff --git a/frontend/src/app/main/ui/components/mcp_menu.scss b/frontend/src/app/main/ui/components/mcp_menu.scss index f4c69ba4c8..fd466d4206 100644 --- a/frontend/src/app/main/ui/components/mcp_menu.scss +++ b/frontend/src/app/main/ui/components/mcp_menu.scss @@ -13,10 +13,10 @@ .mcp-tool { position: relative; -} -.dashboard { - margin-inline: var(--sp-l); + &.dashboard { + --mcp-disconnected-dot-color: var(--color-foreground-secondary); + } } .toolbar-mcp-button { @@ -38,7 +38,7 @@ inline-size: px2rem(6); block-size: px2rem(6); border-radius: 50%; - background-color: var(--color-background-disabled); + background-color: var(--mcp-disconnected-dot-color, var(--color-background-disabled)); &.connected { background-color: var(--color-accent-primary); @@ -72,6 +72,7 @@ .toolbar-mcp-menu { position: absolute; + z-index: var(--z-index-dropdown); left: 0; top: $sz-36; } @@ -85,7 +86,6 @@ display: flex; flex-direction: column; gap: var(--sp-xs); - z-index: var(--z-index-dropdown); margin: 0; padding: var(--sp-xs); border: $b-2 solid var(--panel-border-color); diff --git a/frontend/src/app/main/ui/dashboard/deleted.cljs b/frontend/src/app/main/ui/dashboard/deleted.cljs index 2f41c028e6..6bef519d98 100644 --- a/frontend/src/app/main/ui/dashboard/deleted.cljs +++ b/frontend/src/app/main/ui/dashboard/deleted.cljs @@ -16,6 +16,7 @@ [app.main.refs :as refs] [app.main.store :as st] [app.main.ui.components.context-menu-a11y :refer [context-menu*]] + [app.main.ui.components.mcp-menu :refer [dashboard-mcp-menu*]] [app.main.ui.dashboard.grid :refer [grid*]] [app.main.ui.dashboard.layout-toggle :as lt :refer [layout-toggle*]] [app.main.ui.dashboard.subscription :refer [get-subscription-type]] @@ -64,6 +65,7 @@ [:div#dashboard-deleted-title {:class (stl/css :dashboard-title)} [:h1 (tr "dashboard.projects-title")]] [:div {:class (stl/css :dashboard-header-actions)} + [:> dashboard-mcp-menu*] [:> layout-toggle* {:layout layout :on-change on-change}]]]) (mf/defc project-context-menu* diff --git a/frontend/src/app/main/ui/dashboard/files.cljs b/frontend/src/app/main/ui/dashboard/files.cljs index b3318fc6f8..2d6a98f519 100644 --- a/frontend/src/app/main/ui/dashboard/files.cljs +++ b/frontend/src/app/main/ui/dashboard/files.cljs @@ -14,6 +14,7 @@ [app.main.data.project :as dpj] [app.main.refs :as refs] [app.main.store :as st] + [app.main.ui.components.mcp-menu :refer [dashboard-mcp-menu*]] [app.main.ui.dashboard.grid :refer [grid*]] [app.main.ui.dashboard.import :as udi] [app.main.ui.dashboard.inline-edition :refer [inline-edition]] @@ -102,6 +103,7 @@ (:name project)]])) [:div {:class (stl/css :dashboard-header-actions)} + [:> dashboard-mcp-menu*] [:> layout-toggle* {:layout layout :on-change on-change}] diff --git a/frontend/src/app/main/ui/dashboard/projects.cljs b/frontend/src/app/main/ui/dashboard/projects.cljs index fef26f5b9b..2efbbefd21 100644 --- a/frontend/src/app/main/ui/dashboard/projects.cljs +++ b/frontend/src/app/main/ui/dashboard/projects.cljs @@ -17,6 +17,7 @@ [app.main.data.team :as dtm] [app.main.refs :as refs] [app.main.store :as st] + [app.main.ui.components.mcp-menu :refer [dashboard-mcp-menu*]] [app.main.ui.dashboard.deleted :as deleted] [app.main.ui.dashboard.grid :refer [line-grid*]] [app.main.ui.dashboard.import :as udi] @@ -50,6 +51,7 @@ (tr "dashboard.personal-projects") (tr "dashboard.projects-title"))]] [:div {:class (stl/css :dashboard-header-actions)} + [:> dashboard-mcp-menu*] [:> layout-toggle* {:layout layout :on-change on-change}] (when can-edit diff --git a/frontend/src/app/main/ui/dashboard/sidebar.cljs b/frontend/src/app/main/ui/dashboard/sidebar.cljs index 8787c290ca..2f37187244 100644 --- a/frontend/src/app/main/ui/dashboard/sidebar.cljs +++ b/frontend/src/app/main/ui/dashboard/sidebar.cljs @@ -23,7 +23,6 @@ [app.main.ui.components.dropdown-menu :refer [dropdown-menu* dropdown-menu-item*]] [app.main.ui.components.link :refer [link*]] - [app.main.ui.components.mcp-menu :refer [mcp-menu*]] [app.main.ui.dashboard.check-updates :as dcu] [app.main.ui.dashboard.comments :refer [comments-icon* comments-section]] [app.main.ui.dashboard.inline-edition :refer [inline-edition]] @@ -256,7 +255,6 @@ (get default-project :id) team-id (get team :id) - mcp-state (mf/deref refs/mcp) projects? (= section :dashboard-recent) fonts? (= section :dashboard-fonts) @@ -384,15 +382,6 @@ [:span {:class (stl/css :element-title)} (tr "labels.shared-libraries")]]]]] - (when (and (contains? cf/flags :mcp) - (:enabled mcp-state) - (:token-valid mcp-state)) - [:div {:class (stl/css :sidebar-content-section)} - [:> mcp-menu* {:dashboard true - :is-mcp-connected (= "connected" (:connection-status mcp-state)) - :is-connection-requested (:connection-requested mcp-state) - :session-id (:session-id mcp-state)}]]) - [:div {:class (stl/css :sidebar-content-section) :data-testid "pinned-projects"} [:div {:class (stl/css :sidebar-section-title)}