Skip to content

feat(mcp): add approval attention controls and localized notifications#311

Open
Stiwar0098 wants to merge 4 commits into
TabularisDB:mainfrom
Stiwar0098:feat/mcp-approval-attention
Open

feat(mcp): add approval attention controls and localized notifications#311
Stiwar0098 wants to merge 4 commits into
TabularisDB:mainfrom
Stiwar0098:feat/mcp-approval-attention

Conversation

@Stiwar0098

@Stiwar0098 Stiwar0098 commented Jun 9, 2026

Copy link
Copy Markdown

Summary

Adds attention-grabbing controls for MCP approval gates so users never miss a pending approval, with fully localized notification text.

Closes #307

What's new

Attention Flow (src/utils/mcpApprovalAttention.ts)

  • Window snapshot/restore: captures and restores window position, size, and visibility
  • Focus request: brings window to front with
    equestUserAttention(Informational)
  • System notification: sends OS notification with localized title + body
  • Alert sound: optional sound on notification

Settings (McpSafetySection)

  • mcpApprovalAlwaysOnTop — keep approval window on top while pending
  • mcpApprovalNotifySound — play alert sound on notification
  • Labels localized in 8 languages (en, es, de, fr, it, ja, ru, zh)

Trigger (AiApprovalGate)

  • Calls attention flow when a pending approval appears
  • Respects both opt-out toggles

Infrastructure

  • Added Tauri capabilities:
    otification:default, is-visible, is-minimized,
    equest-user-attention, is-always-on-top, set-always-on-top
  • Rust config structs for the two new settings
  • isLanguageApplied() helper avoids spurious changeLanguage() on startup
  • Unit + component test coverage for attention flow, opt-out paths, and language-settlement edge cases

Test plan

  • 23 targeted tests pass (pnpm test)
  • Production build succeeds (pnpm build && pnpm tauri build)
  • Manual: approval gate appears on top when setting enabled
  • Manual: notification fires with localized text in each locale
  • Manual: sound plays/disabled per setting
  • Manual: window restores to original state after approval

- Add mcpApprovalAttention utility: window snapshot/restore, focus request,
  system notification with localized title/body, and alert sound
- Add mcpApprovalAlwaysOnTop and mcpApprovalNotifySound settings in
  McpSafetySection with i18n labels (en, es, de, fr, it, ja, ru, zh)
- Trigger attention flow from AiApprovalGate on pending approvals
- Add isLanguageApplied() helper to avoid unnecessary changeLanguage() calls
- Add Tauri capabilities: notification:default, is-visible, is-minimized,
  request-user-attention, is-always-on-top, set-always-on-top
- Add Rust config structs for new approval settings
- Add unit and component tests for attention flow and opt-out paths
- Update .gitignore to exclude .atl/

Closes TabularisDB#307
Comment thread src/contexts/SettingsProvider.tsx Outdated
Comment thread src/utils/mcpApprovalAttention.ts Outdated
@kilo-code-bot

kilo-code-bot Bot commented Jun 9, 2026

Copy link
Copy Markdown

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Resolved Issues
File Line Issue Status
src/contexts/SettingsProvider.tsx 237 Mount effect re-runs when language changes due to isLanguageApplied / queueLanguageApplication in dependency array Fixed — dependency array changed to [] in prior commit; this diff further refactors language state into derived LanguageState to eliminate synchronous setState in effects
src/utils/mcpApprovalAttention.ts 80 Stale window snapshot on consecutive approvals when previous restore partially failed Fixed — added windowAttentionSnapshotApprovalId !== approvalId check in prior commit; unchanged in this diff
src/components/modals/AiApprovalGate.tsx N/A Decouple modal and attention effect from isLanguageSettled FixedisLanguageSettled removed from render gate and effect dependencies
Files Reviewed (2 files)
  • src/utils/mcpApprovalAttention.ts — adds Linux-specific OS notification sound routing to work around WebKitGTK autoplay policy; skips in-page Web Audio tone on Linux to avoid double alert; macOS/Windows unchanged |
  • tests/utils/mcpApprovalAttention.test.ts — adds test verifying Linux behavior: OS notification sound is used and AudioContext is not instantiated |
Previous Review Summaries (2 snapshots, latest commit 8601478)

Current summary above is authoritative. Previous snapshots are kept for context only.

Previous review (commit 8601478)

Status: No Issues Found | Recommendation: Merge

All previously identified issues remain resolved, and no new issues were introduced in the latest commits.

Resolved Issues
File Line Issue Status
src/contexts/SettingsProvider.tsx 237 Mount effect re-runs when language changes due to isLanguageApplied / queueLanguageApplication in dependency array Fixed — dependency array changed to [] in prior commit; this diff further refactors language state into derived LanguageState to eliminate synchronous setState in effects
src/utils/mcpApprovalAttention.ts 80 Stale window snapshot on consecutive approvals when previous restore partially failed Fixed — added windowAttentionSnapshotApprovalId !== approvalId check in prior commit; unchanged in this diff
src/components/modals/AiApprovalGate.tsx N/A Decouple modal and attention effect from isLanguageSettled FixedisLanguageSettled removed from render gate and effect dependencies
Files Reviewed (3 files)
  • src/contexts/SettingsProvider.tsx — language state refactored to derived LanguageState; no synchronous setState in effects; previous mount-effect fix preserved
  • src/components/modals/AiApprovalGate.tsxisLanguageSettled decoupled from render and attention effect; dependencies correct
  • tests/components/modals/AiApprovalGate.test.tsx — test expectations updated for immediate render behavior

Previous review (commit 941629b)

Status: No Issues Found | Recommendation: Merge

All previously identified issues have been resolved in the latest commits.

Resolved Issues
File Line Issue Status
src/contexts/SettingsProvider.tsx 237 Mount effect re-runs when language changes due to isLanguageApplied / queueLanguageApplication in dependency array Fixed — dependency array changed to []
src/utils/mcpApprovalAttention.ts 80 Stale window snapshot on consecutive approvals when previous restore partially failed Fixed — added windowAttentionSnapshotApprovalId !== approvalId check
Files Reviewed (3 files)
  • src/contexts/SettingsProvider.tsx — previous issue fixed
  • src/utils/mcpApprovalAttention.ts — previous issue fixed
  • tests/utils/mcpApprovalAttention.test.ts — new test added for stale snapshot fix

Reviewed by kimi-k2.6-20260420 · 201,821 tokens

- SettingsProvider: remove isLanguageApplied/queueLanguageApplication from
  mount effect dependency array to prevent re-running loadSettings on
  language change (WARNING per kilo-review)
- mcpApprovalAttention: capture fresh snapshot when approval ID changes
  instead of reusing stale state from a partially-failed restore
- Add test coverage for fresh snapshot capture on different approval ID
@debba debba requested a review from NewtTheWolf June 12, 2026 12:59
@NewtTheWolf

Copy link
Copy Markdown
Collaborator

hey @Stiwar0098 thanks for your work!

didnt had time to review it yet but it is still on my todo! will do it tomorrow ASAP

@NewtTheWolf NewtTheWolf left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review — MCP approval attention controls

Nice work @Stiwar0098 — clean watcher→event→gate architecture and solid config tests. Tested locally on Linux; the core flow works when a language is set. Findings:

🔴 Blocking — no approval shows without a configured language. Fresh config (language: null, the default on first launch) → modal and notification never appear, the MCP call just times out. Backend emit is fine — it's the isLanguageSettled gate (L47, L79). i18next has fallbackLng: 'en', so decouple from the gate and translate with the fallback instead of suppressing.

🟡 Alert sound — couldn't validate. On my machine the sound never played (the notification did). I'm fairly sure that's my own OS notification-sound settings, so I can't confirm whether the code is fine or whether it's hitting the Web Audio autoplay policy (programmatic open → no user gesture → AudioContext stays suspended, L252-266). @debba — could you validate the sound on a setup where notification sounds are known to work?

🟡 React rule #2 — sync setState in useEffect (L245-246, L253-254).

ℹ️ Window not raising on Linux is not a bug — the WM blocks focus-stealing; the code calls the right APIs.

Left two inline suggestions on the gate decoupling.

Comment thread src/components/modals/AiApprovalGate.tsx Outdated
Comment thread src/components/modals/AiApprovalGate.tsx Outdated
@Stiwar0098

Copy link
Copy Markdown
Author

On the sound point, I tested the approval flow on Windows and the notification sound does play correctly on my side. That suggests the implementation is working at least on Windows, and the earlier no-sound result may have been environment-specific on Linux.

@Stiwar0098

Copy link
Copy Markdown
Author

On the setState note, this is now addressed in 8601478 as well. The language effect no longer does synchronous flag resets inside useEffect; isLanguageReady and isLanguageSettled are derived from the current i18n state plus the tracked result of the async language application for the active language, which preserves the same behavior without the extra post-render setState pattern.

@Stiwar0098 Stiwar0098 requested a review from NewtTheWolf June 17, 2026 03:38
The in-page Web Audio alert tone never plays on Linux: WebKitGTK's
autoplay policy keeps the programmatically-started AudioContext suspended
(no user gesture), so the synthesized beep is silent there.

Route the alert through the OS notification's XDG theme sound
(message-new-instant) on Linux instead, and skip the in-page tone to avoid
a double alert. macOS/Windows keep using the Web Audio tone, which their
webviews allow without a user gesture.
@NewtTheWolf

Copy link
Copy Markdown
Collaborator

Followed up on the alert sound, @Stiwar0098. Confirmed it's not a bug in your code — on Linux the synthesized Web Audio tone can't play because WebKitGTK's autoplay policy keeps the programmatically-started AudioContext suspended (no user gesture). Your Windows result was correct; WebView2 doesn't have that restriction. Verified end-to-end on KDE: system audio is fine, but the in-page tone never reaches the sink.

To avoid a review ping-pong round I pushed a fix straight to the branch (ed9c12f): on Linux the alert now rides the OS notification's XDG theme sound (message-new-instant) instead, and the in-page tone is skipped there to avoid a double alert. macOS/Windows keep using the Web Audio tone, so your platform is unchanged. Added a unit test; full suite green (2530).

Could you give it a quick check on Windows to confirm the tone still plays there as before? 🙏

@NewtTheWolf NewtTheWolf left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-reviewed 941629b..ed9c12f — both blocking points resolved, nicely done @Stiwar0098.

Language gateisLanguageSettled fully decoupled from the effect, deps, and render gate. Verified end-to-end on a fresh language: null config (staged a pending approval): modal and notification now appear with English fallback text, where before nothing showed. The inverted test locks it in.

React rule #2isLanguageReady/isLanguageSettled are derived during render; the i18n effect only sets state post-await with a language guard.

🔊 Sound — addressed in the follow-up commit I pushed (Linux now uses the OS notification sound; see comment above). Works end-to-end on KDE.

Branch tests green, typecheck + lint clean (the exhaustive-deps warning on the loadSettings mount effect is the intentional run-once pattern). LGTM 🚀

@Stiwar0098

Copy link
Copy Markdown
Author

Sorry for the delay on this. I rechecked the approval flow on Windows, and the tone still plays as before after the Linux-specific follow-up, so Windows behavior looks unchanged on my side.

@Stiwar0098 Stiwar0098 requested a review from NewtTheWolf June 20, 2026 06:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feat]: MCP approval attention controls and localized notifications

2 participants