Skip to content

feat(macos): full native settings (REST config editor) in the tray app#537

Merged
Dumbris merged 6 commits into
mainfrom
061-macos-settings-tray
May 29, 2026
Merged

feat(macos): full native settings (REST config editor) in the tray app#537
Dumbris merged 6 commits into
mainfrom
061-macos-settings-tray

Conversation

@Dumbris

@Dumbris Dumbris commented May 29, 2026

Copy link
Copy Markdown
Member

Summary

Makes the macOS tray a full alternative client to the core: every backend setting is edited natively over REST, mirroring the web UI Configuration page. The tray never reads or writes the config JSON file directly — it loads via GET /api/v1/config and saves only the changed fields via the deep-merge PATCH /api/v1/config (Spec 060, now on main), so unrelated settings and redacted secrets are never clobbered (Constitution III).

Settings window — tabs (⌘1–⌘4)

  • App — OS-level prefs the app legitimately owns: launch-at-login (SMAppService), interface text size, version, live core-connection status.
  • Security — API key (masked + restart badge), MCP auth, quarantine, Docker isolation, code execution, read-only, secret detection, reveal-headers, listen.
  • General — routing mode, limits, response cap, call timeout, log level, telemetry, prompts.
  • Advanced — collapsible subsystem sections (code execution, Docker, secret detection, output validation/sanitisation, activity retention, logging, TLS, other).

Opened from a tray "Settings…" (⌘,) item using the activation-policy-flip pattern for .accessory apps. Per-section dirty-tracking + Save, inline validation (host:port, byte-size, durations, etc.), danger confirms (telemetry opt-out = gentle info tone), restart badges, and docs links — ported from the web UI.

Implementation

  • SettingsCatalog.swift — Swift port of the web UI field catalogue + validation + dot-path helpers.
  • ConfigSettingsView.swiftConfigStore (REST load/save) + reusable field rows & per-section save.
  • APIClient.getConfig() / patchConfig().
  • Also: self-building run.sh launcher repairing the mcpproxy-ui-test MCP server.

Verification (mcpproxy-ui-test)

Built a PATCH-capable core, attached the tray via the unix socket (Core: Connected), and captured all four tabs via screenshot_window (⌘1–⌘4 to navigate). The General tab shows a value set via PATCH (search limit 17), confirming live REST reads. Save calls PATCH /config (confirmed at the API layer + the Spec 060 web-UI suite). QA report kept local per policy.

Depends on #536 (merged).

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented May 29, 2026

Copy link
Copy Markdown

Deploying mcpproxy-docs with  Cloudflare Pages  Cloudflare Pages

Latest commit: 7d8fa80
Status: ✅  Deploy successful!
Preview URL: https://76e108f2.mcpproxy-docs.pages.dev
Branch Preview URL: https://061-macos-settings-tray.mcpproxy-docs.pages.dev

View logs

@codecov-commenter

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@github-actions

github-actions Bot commented May 29, 2026

Copy link
Copy Markdown

📦 Build Artifacts

Workflow Run: View Run
Branch: 061-macos-settings-tray

Available Artifacts

  • archive-darwin-amd64 (28 MB)
  • archive-darwin-arm64 (25 MB)
  • archive-linux-amd64 (16 MB)
  • archive-linux-arm64 (14 MB)
  • archive-windows-amd64 (27 MB)
  • archive-windows-arm64 (24 MB)
  • frontend-dist-pr (0 MB)
  • installer-dmg-darwin-amd64 (21 MB)
  • installer-dmg-darwin-arm64 (19 MB)

How to Download

Option 1: GitHub Web UI (easiest)

  1. Go to the workflow run page linked above
  2. Scroll to the bottom "Artifacts" section
  3. Click on the artifact you want to download

Option 2: GitHub CLI

gh run download 26655181691 --repo smart-mcp-proxy/mcpproxy-go

Note: Artifacts expire in 14 days.

Dumbris added 3 commits May 29, 2026 18:56
The MCP config pointed at /tmp/mcpproxy-ui-test, which gets wiped → the
server failed to start with ENOENT. Add run.sh: it builds the binary from
source (kept in this project) into .bin/ if missing or stale (module cache
under .build/, build logs to stderr so they don't corrupt the stdio JSON-RPC
stream), then execs it. Point the MCP config at run.sh so the tool self-heals
after a clean checkout or /tmp wipe. .bin/ is gitignored.
Add a HIG-idiomatic Settings window opened from a new tray "Settings…" item
(⌘,). Tabbed layout (General / Connection) hosted in a content-sized NSWindow,
using the app's proven activation-policy-flip pattern so it shows reliably from
an .accessory menu-bar app.

- General: launch-at-login (SMAppService via AutoStartService), interface text
  size (appState.fontScale), "Open full configuration in browser…" (web UI),
  version.
- Connection: endpoint + live connection status, Open Web UI.

Per Constitution III the tray stays a stateless controller — only OS-level
prefs (launch-at-login, text size) live here; all backend config defers to the
web UI. Verified end-to-end with the mcpproxy-ui-test tools (menu item present,
opens the window, renders all controls).

Relates to native macOS tray UX.
Replace the thin Settings (launch-at-login + browser shortcut) with a full
alternative-client config editor. The tray now edits all backend settings over
REST — GET /api/v1/config to load, PATCH /api/v1/config (deep-merge, only
changed fields) to save — never reading/writing the config JSON file directly.

- SettingsCatalog.swift: Swift port of the web UI field catalogue
  (Security / General / Advanced sections) + validation + dot-path helpers.
- ConfigSettingsView.swift: ConfigStore (load/save via REST) + reusable field
  rows and per-section save with dirty-tracking, validation, danger confirms
  (incl. telemetry info-tone), restart badges, and doc links.
- SettingsView tabs: App (OS prefs: launch-at-login, text size) + Security +
  General + Advanced. Window made resizable.
- APIClient: getConfig() + patchConfig(partial).

Depends on PATCH /api/v1/config (Spec 060). Relates to native macOS tray UX.
@Dumbris Dumbris force-pushed the 061-macos-settings-tray branch from dba3f7c to e74dd39 Compare May 29, 2026 16:06
@Dumbris Dumbris changed the title feat(macos): native Settings window in the tray app feat(macos): full native settings (REST config editor) in the tray app May 29, 2026
Dumbris added 3 commits May 29, 2026 19:54
DisclosureGroup only toggled when the chevron itself was clicked. Replace it
with a custom collapsible whose entire header row is a plain Button with
contentShape(Rectangle()), so clicking anywhere on the section title (or
chevron) expands/collapses it.

Relates to #537.
The app menu's 'Settings…' / ⌘, was wired to a leftover SwiftUI
`Settings {}` placeholder scene ('Use the MCPProxy tray menu to access
settings.'), a separate window from the real config window the tray
opens. Driving the SwiftUI Settings scene programmatically from a
menu-bar (.accessory) app proved unreliable (sendAction no-ops; even the
native ⌘, was flaky), so route every entry point to the one AppKit
config window instead:

- ⌘, is intercepted in the existing local key monitor.
- A click on the app-menu 'Settings…' item is repointed to
  showSettingsWindow() in setupMainMenu().
- The SwiftUI Settings scene is reduced to a 1x1 bridge that, if ever
  opened, hands off to the config window and dismisses itself — so the
  stub can never reappear.
- Activation-policy restore is now driven by a global window-close
  observer (the scene window isn't ours), replacing the delegate-only
  check.

Verified ⌘, opens the real Settings window; final on-device screenshot
pending (screen was locked during the run).
…ab in Settings

The main-window 'Configuration' sidebar item duplicated the new Settings
window AND violated the REST-only contract: ConfigView read/wrote
~/.mcpproxy/mcp_config.json directly (Data(contentsOf:) / write(to:)),
which bypasses the core's deep-merge (can clobber redacted secret
headers), races the file watcher, and breaks entirely against a remote
core.

- Remove the 'Configuration' sidebar item and delete ConfigView.swift.
- Add a read-only 'Raw' tab to the Settings window, sourced over REST
  (GET /api/v1/config via ConfigStore.prettyJSON) with a Copy button.
  Editing stays in the App/Security/General/Advanced forms; the Raw tab
  only mirrors the effective config the core is running.
- Wire ⌘5 for the new tab.

Main window is now operational-only (Dashboard/Servers/Activity/Secrets);
all configuration lives in Settings.
@Dumbris Dumbris merged commit b5e12da into main May 29, 2026
37 checks passed
@Dumbris Dumbris deleted the 061-macos-settings-tray branch May 29, 2026 19:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants