🐛 Fix MCP notifications when there is only one tab

This commit is contained in:
Luis de Dios
2026-03-18 15:06:06 +01:00
committed by Alonso Torres
parent 93de83c427
commit 9e9c28fe3c
7 changed files with 62 additions and 40 deletions

View File

@@ -53,21 +53,28 @@
(rx/take 1)
(rx/map #(ptk/data-event ::connect))))))
(defn manage-notification
[mcp-enabled? mcp-connected?]
(if mcp-enabled?
(if mcp-connected?
(rx/of (ntf/hide))
(rx/of (ntf/dialog :content (tr "notifications.mcp.active-tab-switching.text")
:cancel {:label (tr "labels.dismiss")
:callback #(st/emit! (ntf/hide)
(ptk/event ::ev/event {::ev/name "confirm-mcp-tab-switch"
::ev/origin "workspace-notification"}))}
:accept {:label (tr "labels.switch")
:callback #(st/emit! (connect-mcp)
(ptk/event ::ev/event {::ev/name "dismiss-mcp-tab-switch"
::ev/origin "workspace-notification"}))})))
(rx/of (ntf/hide))))
(defn manage-mcp-notification
[]
(ptk/reify ::manage-mcp-notification
ptk/WatchEvent
(watch [_ state _]
(let [mcp-connected? (true? (-> state :workspace-local :mcp :connection))
mcp-enabled? (true? (-> state :profile :props :mcp-enabled))
num-sessions (-> state :workspace-presence vals count)
multi-session? (> num-sessions 1)]
(if (and mcp-enabled? multi-session?)
(if mcp-connected?
(rx/of (ntf/hide))
(rx/of (ntf/dialog :content (tr "notifications.mcp.active-in-another-tab")
:cancel {:label (tr "labels.dismiss")
:callback #(st/emit! (ntf/hide)
(ptk/event ::ev/event {::ev/name "confirm-mcp-tab-switch"
::ev/origin "workspace-notification"}))}
:accept {:label (tr "labels.switch")
:callback #(st/emit! (connect-mcp)
(ptk/event ::ev/event {::ev/name "dismiss-mcp-tab-switch"
::ev/origin "workspace-notification"}))})))
(rx/of (ntf/hide)))))))
(defn update-mcp-status
[value]
@@ -77,26 +84,24 @@
(update-in state [:profile :props] assoc :mcp-enabled value))
ptk/WatchEvent
(watch [_ state _]
(watch [_ _ _]
(rx/merge
(let [mcp-connected? (-> state :workspace-local :mcp :connected)]
(manage-notification value mcp-connected?))
(case value
true (rx/of (ptk/data-event ::connect))
false (rx/of (ptk/data-event ::disconnect))
nil)))))
(rx/of (manage-mcp-notification)))
(case value
true (rx/of (ptk/data-event ::connect))
false (rx/of (ptk/data-event ::disconnect))
nil))))
(defn update-mcp-connection
[value]
(ptk/reify ::update-mcp-plugin-connection
ptk/UpdateEvent
(update [_ state]
(update-in state [:workspace-local :mcp] assoc :connected value))
(update-in state [:workspace-local :mcp] assoc :connection value))
ptk/WatchEvent
(watch [_ state _]
(let [mcp-enabled? (-> state :profile :props :mcp-enabled)]
(manage-notification mcp-enabled? value)))))
(watch [_ _ _]
(rx/of (manage-mcp-notification)))))
(defn init-mcp!
[stream]
@@ -116,11 +121,12 @@
:getServerUrl #(str cf/mcp-ws-uri)
:setMcpStatus
(fn [status]
(let [mcp-connected? (case status
(let [mcp-connection (case status
"connected" true
"disconnected" false
nil)]
(st/emit! (update-mcp-connection mcp-connected?))
"error" nil
"")]
(st/emit! (update-mcp-connection mcp-connection))
(log/info :hint "MCP STATUS" :status status)))
:on

View File

@@ -23,6 +23,7 @@
[app.main.data.workspace.edition :as dwe]
[app.main.data.workspace.layout :as dwly]
[app.main.data.workspace.libraries :as dwl]
[app.main.data.workspace.mcp :as mcp]
[app.main.data.workspace.texts :as dwt]
[app.main.router :as rt]
[app.util.globals :refer [global]]
@@ -212,7 +213,11 @@
(update [_ state]
(if (or (= :disconnect type) (= :leave-file type))
(update state :workspace-presence dissoc session-id)
(update state :workspace-presence update-presence))))))
(update state :workspace-presence update-presence)))
ptk/WatchEvent
(watch [_ _ _]
(rx/of (mcp/manage-mcp-notification))))))
(defn handle-pointer-update
[{:keys [page-id session-id position zoom zoom-inverse vbox vport] :as msg}]

View File

@@ -7,7 +7,6 @@
(ns app.main.ui.settings.integrations
(:require-macros [app.main.style :as stl])
(:require
[app.common.data :as d]
[app.common.data.macros :as dm]
[app.common.schema :as sm]
[app.common.time :as ct]
@@ -410,7 +409,7 @@
profile (mf/deref refs/profile)
mcp-key (some #(when (= (:type %) "mcp") %) tokens)
mcp-enabled? (d/nilv (-> profile :props :mcp-enabled) false)
mcp-enabled? (true? (-> profile :props :mcp-enabled))
expires-at (:expires-at mcp-key)
expired? (and (some? expires-at) (> (ct/now) expires-at))

View File

@@ -749,8 +749,8 @@
profile (mf/deref refs/profile)
workspace-local (mf/deref refs/workspace-local)
mcp-enabled? (-> profile :props :mcp-enabled)
mcp-connected? (-> workspace-local :mcp :connected)
mcp-enabled? (true? (-> profile :props :mcp-enabled))
mcp-connected? (true? (-> workspace-local :mcp :connection))
on-nav-to-integrations
(mf/use-fn
@@ -978,9 +978,10 @@
:class (stl/css :item-arrow)}]])
(when (contains? cf/flags :mcp)
(let [mcp-enabled? (-> profile :props :mcp-enabled)
mcp-connected? (-> workspace-local :mcp :connected)
mcp-active? (and mcp-enabled? mcp-connected?)]
(let [mcp-enabled? (true? (-> profile :props :mcp-enabled))
mcp-connection (-> workspace-local :mcp :connection)
mcp-connected? (true? mcp-connection)
mcp-error? (nil? mcp-connection)]
[:> dropdown-menu-item* {:class (stl/css :base-menu-item :menu-item)
:on-click on-menu-click
:on-key-down (fn [event]
@@ -992,7 +993,8 @@
[:span {:class (stl/css :item-name)}
(tr "workspace.header.menu.option.mcp")]
[:span {:class (stl/css-case :item-indicator true
:active mcp-active?)}]
:active (and mcp-enabled? mcp-connected?)
:failed (and mcp-enabled? mcp-error?))}]
[:> icon* {:icon-id i/arrow-right
:class (stl/css :item-arrow)}]]))

View File

@@ -134,6 +134,10 @@
&.active {
--menu-indicator-color: var(--color-accent-primary);
}
&.failed {
--menu-indicator-color: var(--color-foreground-error);
}
}
.item-arrow {

View File

@@ -3833,9 +3833,12 @@ msgstr "Invitation sent successfully"
msgid "notifications.invitation-link-copied"
msgstr "Invitation link copied"
msgid "notifications.mcp.active-tab-switching.text"
msgid "notifications.mcp.active-in-another-tab"
msgstr "MCP is active in another tab. Switch here?"
msgid "notifications.mcp.active-in-this-tab"
msgstr "MCP is now active in this tab."
#: src/app/main/ui/settings/delete_account.cljs:24
msgid "notifications.profile-deletion-not-allowed"
msgstr "You can't delete your profile. Reassign your teams before proceed."

View File

@@ -3790,9 +3790,12 @@ msgstr "Invitación enviada con éxito"
msgid "notifications.invitation-link-copied"
msgstr "Enlace de invitacion copiado"
msgid "notifications.mcp.active-tab-switching.text"
msgid "notifications.mcp.active-in-another-tab"
msgstr "MCP está activo en otra pestaña. ¿Cambiar a esta?"
msgid "notifications.mcp.active-in-this-tab"
msgstr "MCP está ahora activo en esta pestaña."
#: src/app/main/ui/settings/delete_account.cljs:24
msgid "notifications.profile-deletion-not-allowed"
msgstr "No puedes borrar tu perfil. Reasigna tus equipos antes de seguir."