Skip to content

feat(060): form-based settings page + partial-update PATCH /config#536

Merged
Dumbris merged 10 commits into
mainfrom
060-settings-page
May 29, 2026
Merged

feat(060): form-based settings page + partial-update PATCH /config#536
Dumbris merged 10 commits into
mainfrom
060-settings-page

Conversation

@Dumbris

@Dumbris Dumbris commented May 29, 2026

Copy link
Copy Markdown
Member

Summary

Turns mcpproxy's large config surface into a friendly, prioritized Web UI Settings page, replacing the raw-JSON-only editor (kept as an escape hatch). Sections: Security & Access → General → Advanced (subsystem accordions) → Raw JSON (Monaco) → Teams (server edition only).

Backend

PATCH /api/v1/config deep-merges only the fields the client sends onto the live config and routes through the existing ApplyConfig pipeline. Starting from the real in-memory config means a section save never clobbers untouched fields or masked secrets (api_key, secret headers). Modeled on handlePatchDockerIsolation; TDD secret-preservation + nested-merge tests.

Frontend

Declarative field catalogue (fields.ts) drives SettingField + SettingsSection (per-section partial save, toast, restart/sensitive badges, danger-confirm dialogs). Settings.vue is the tab shell; Monaco kept as Raw JSON tab. Masked api_key with show/regenerate. data-test ids on all controls.

Verification (Chrome ext unavailable → Playwright + live API)

All sections render (Teams hidden in personal edition); partial save persisted require_mcp_auth=true while api_key was preserved (auth 200); danger-confirm cancel prevented reveal_secret_headers; restart/sensitive badges shown. Backend unit tests + frontend build green. QA report generated locally, not committed (project policy).

Known minor: ConfigApplyResult.changed_fields sometimes mislabels the changed key (pre-existing ApplyConfig diff quirk); values persist correctly.

Relates to Spec 060.

Redesign the Web UI Configuration page from a raw Monaco JSON editor into
prioritized, form-based sections: Security & Access / General / Advanced
(subsystem accordions) / Raw JSON (Monaco kept) / Teams (server edition).

Backend: new generic PATCH /api/v1/config that deep-merges only the fields
the client sends onto the live config and routes through ApplyConfig. Starting
from the real in-memory config means a section save never clobbers untouched
fields or masked secrets (api_key, secret headers). Modeled on
handlePatchDockerIsolation.

Frontend: declarative field catalogue (fields.ts) drives SettingField +
SettingsSection (per-section partial save, toast, restart/sensitive badges,
danger-confirm dialogs). Settings.vue becomes the tab shell. data-test ids on
all controls.

Verified end-to-end (Playwright; Chrome ext unavailable): all sections render,
partial save persists require_mcp_auth while preserving api_key, danger-confirm
cancel prevents reveal_secret_headers, restart badges shown. Backend
secret-preservation unit tests green.

Relates to Spec 060.
Comment thread frontend/src/views/settings/fields.ts Fixed
@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: a95f1c3
Status: ✅  Deploy successful!
Preview URL: https://b20deadf.mcpproxy-docs.pages.dev
Branch Preview URL: https://060-settings-page.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

❌ Patch coverage is 55.17241% with 26 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
internal/httpapi/server.go 55.17% 19 Missing and 7 partials ⚠️

📢 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: 060-settings-page

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 26646771079 --repo smart-mcp-proxy/mcpproxy-go

Note: Artifacts expire in 14 days.

Dumbris added 9 commits May 29, 2026 14:34
…dirty/discard

Make the settings page genuinely useful for finding and reviewing options:
- Cross-section search box: type to surface matching settings from every
  section (Security/General/Advanced/Teams) in one editable list.
- Security posture summary: at-a-glance colour-coded chips (quarantine, MCP
  auth, Docker isolation, secret scan, code exec, read-only, reveal headers),
  flagging anything that warrants review.
- Per-field dirty highlight (left accent + ● badge) and a per-section Discard
  button to revert unsaved changes.

Relates to Spec 060.
…ed verification spec

- Rewrote every setting's label and help text from the user's point of view:
  explain what each option does, how to use it, and the consequence (e.g.
  "Require API key for MCP clients" now explains clients send it as a Bearer
  token and points to the connect helper).
- Added a "Connect a client" helper to the Security section that opens the
  shared ConnectModal, so users can register mcpproxy in their AI client's
  config right where they configure auth.
- Committed the reproducible Playwright verification spec + config under
  specs/060/verification (spec only — screenshots/report stay local per policy).

Relates to Spec 060.
setPath walked dot-path keys and assigned recursively without rejecting
__proto__/prototype/constructor. Settings keys come from the static
catalogue, but guard the generic helper so a crafted path can never
pollute Object.prototype. Resolves CodeQL js/prototype-polluting-assignment.

Relates to Spec 060.
Add an optional `docs` path to settings fields/accordions and render links:
- per-field "docs ↗" on the options with a dedicated doc page (quarantine,
  Docker isolation, code execution, secret detection, routing mode, telemetry),
- "Learn more ↗" on each Advanced subsystem accordion (incl. output
  validation/sanitisation, activity log),
- "Full configuration reference ↗" in the page header.

All target URLs verified to return 200 on docs.mcpproxy.app (served at root via
the Docusaurus site). Verification spec asserts the field + reference links.

Relates to Spec 060.
…date duration, name prompts

API key field:
- add a copy-to-clipboard button (with a transient ✓ + clipboard fallback);
- regenerating the key now opens a confirmation dialog first (the value only
  changes after you confirm, and nothing persists until Save).

Confirmations:
- turning OFF "Anonymous usage telemetry" now asks for confirmation with an
  informational (non-alarming) tone explaining telemetry helps improve
  mcpproxy — new DangerSpec.tone:'info' (neutral styling, no "sensitive" badge).

Validation:
- duration fields (e.g. Tool call timeout) are validated against Go duration
  syntax; invalid input shows an inline error and blocks Save. Shared
  validateField() now gates both number and duration fields.

Clarity:
- "Expose MCP prompts" now names the built-in prompts (setup-new-mcp-server,
  troubleshoot-mcp-server).

Verification spec extended to cover copy button, regen confirm, telemetry
opt-out confirm, and duration validation.

Relates to Spec 060.
Add format validation so users can't save values that break mcpproxy:
- Listen address: must be a valid host:port (IPv4/hostname/[IPv6]:port,
  port 1–65535) — the critical field that previously accepted any string.
- Docker memory_limit (bytesize), cpu_limit (positive number), registry
  (hostname) — validated, blank falls back to the Docker default.
- API key: a non-empty key must be ≥16 chars (empty still = keep current).

Shared validateField() drives a new `valueKind` (hostport/bytesize/cpu/
hostname/url/secretkey). Errors only surface — and only block Save — for
fields the user has actually edited, so a pre-existing value never blocks
saving unrelated changes. Verification spec covers the listen + duration cases.

Relates to Spec 060.
The overview table listed `/mcp` as each mode's "Default MCP Endpoint",
implying the mode maps to a distinct default path. All modes default to
`/mcp`; the per-mode dedicated endpoints (/mcp/call, /mcp/all, /mcp/code)
are documented in the Dedicated Endpoints section. Remove the confusing
column and add a one-line pointer to that section.
Linked ../configuration.md (nonexistent) which failed the Docusaurus
broken-links build gate. Point to the real configuration reference
(../configuration/config-file.md).
CodeQL's js/prototype-pollution-utility didn't recognise the top-level
Set.has(...) check as a barrier. Guard each traversal key (and the final key)
with an explicit __proto__/prototype/constructor comparison, which CodeQL
treats as a sanitising guard for the recursive property assignment.
@Dumbris Dumbris merged commit 49a18fa into main May 29, 2026
39 checks passed
@Dumbris Dumbris deleted the 060-settings-page branch May 29, 2026 15:56
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.

3 participants