Skip to content

MCP editor redesign (Kevin's UI) + roles/keys, health, tool grid, server-backed counts - #529

Merged
nicdavidson merged 16 commits into
developfrom
feat/mcp-ui
Sep 22, 2026
Merged

nicdavidson merged 16 commits into
developfrom
feat/mcp-ui

Conversation

@nicdavidson

Copy link
Copy Markdown
Contributor

Kevin's MCP editor redesign (feat/mcp-config-redesign, src/app/adf-mcp/) as the base, plus the pieces ported from the competing implementation and the fixes found in review.

What's in it

  • Kevin's editor: Create, Connect, Tools and Settings tabs, preview drawer, exposure picker, custom tools, housekeeping. The route shim sends mcp / system_mcp services to it.
  • feat(mcp): create/add role and API key from the MCP page (#525) #528 Access section (Tools tab rail): lists the roles that can use the server (from /_internal/ai/mcp-access). An inline editor creates or adds roles or edits a role's grants, with table-level grants and a summary of the changes before save. It can optionally create an API key; the key is shown once and filled into the Connect snippets.
  • MCP UI: allow_writes / require_role_access, health + APP_URL, server-backed tool/context numbers (#526) #527 backend wiring:
    • Settings gets the Allow writes (allow_writes) and Require role access (require_role_access) switches.
    • A health chip reads /_internal/ai/mcp-health.
    • The endpoint URL is built from APP_URL.
    • Tool and token counts come from the server (/_internal/ai/mcp-catalog, falling back to rpc tools/list, then to the client-side estimate).
  • Tool grid on the Tools tab:
    • One cell per tool, in columns aligned under a header per kind of service.
    • Switches per column and per group (Read / Schema / Write / Procs).
    • Cell states: served read, served write/execute, off, and blocked by allow_writes.
  • Header: health problems show as df-alert banners (APP_URL copy rewritten). The tabs are now mat-tab-nav-bar.
  • Theme tokens: every hard-coded colour in adf-mcp now uses a DF token, so dark and phosphor themes work. Before, cards were white-on-white in dark mode.
  • e2e: mcp-service and mcp-redesign-flows create their own fixture services, so they run on any instance. workers: 1.

Fixes found in review

  • all_list_files was counted with 2+ databases; the daemon only registers it with 2+ file services. The UI showed one tool more than served.
  • The access editor reset an existing grant's requestor_mask to 3 (API+script) whenever it changed that grant's level.

Backend

Needs df-mcp-server develop (#77, #80, #81): the /_internal/ai/mcp-* endpoints and the allow_writes / require_role_access fields. Against an older backend those calls degrade to null and the client-side numbers.

Verified

  • Jest src/app/adf-mcp: 201/201. Other src/app/shared failures are the same 44 that fail on develop.
  • Playwright MCP suites: 13/13 on df-dev, run twice. They create and delete their own e2e_fx* services.
  • Manual in a browser on df-dev:
    • Connect / Tools / Settings in light and dark themes.
    • Cell, column and group toggles followed by discard.
    • Health banner showing an APP_URL mismatch.

Kevin McGahey and others added 16 commits September 21, 2026 21:02
Shared tool catalog (daemon-exact verbs), effective-access model with
camelCase-aware config parse/serialize, editor store with migration-safe
mutations, shell component (endpoint header, Connect/Tools/Settings tabs,
dirty bar with tool-count delta, save pipeline with auto cache flush),
route shim so mcp/system_mcp services get the new editor, and the
create-save redirect fix: a new MCP server lands on its own Connect tab
(?created=1) instead of API Docs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Connect: first-run checklist (?created=1), endpoint card with reachability
probe (401 renders as healthy auth), OAuth/API-key cards, six auth-aware
client setup panels with one-click Claude redirect-URI add.
Tools: unified exposure+curation surface — exposed-service rows with
tri-state capability drill-ins, derived access chips, orphan
needs-attention flow (keep-curation remove + rename successor with key
rewrite), filter strip + bulk bar at scale, global/aggregator and custom
tool sections, the what-an-agent-gets rail with derived read-only and
make-read-only, expose-services picker (read-only default, simulated
consequence footer), what-an-agent-sees preview drawer with named
exclusion reasons; system_mcp renders the fixed catalog with the same
grammar.
Settings: identity with rename warning, redirect URIs, API-key toggle,
honest tool-naming radio (null renders as server default, never rewritten
on load), catalog delivery, itemized orphan housekeeping, masked full
config viewer, danger zone.
Create: one-decision page — type cards, live URL preview, exposure picker
with read-only default and simulated consequence line, merged tool style
written at create, lands on Connect ?created=1.
Store: totalTools()/savedTotalTools() so system_mcp headers count the
fixed catalog.

122 jest tests across 6 suites.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
13 Playwright tests against a live instance (curation and exposure
round-trips verified via API, create flow landing on ?created=1, preview
exclusions, settings honesty, system_mcp variant, legacy-editor guard),
with snapshot/restore discipline that leaves the instance byte-identical.

Fixes found by testing: the route shim and editor shell now re-initialize
on every resolver emission (Angular reuses routed components on
/ai/mcp/9 -> /ai/mcp/21, which previously kept showing the prior
service's editor); tabs drop per-service UI state via ngOnChanges; the
breadcrumb builder strips query strings so ?created=1 no longer corrupts
the page title; create-page URL-preview spacing; rail hint clipping.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Model: registered_redirect_uris survives saves verbatim (no fallback into
redirect_uris); lazy_mode uses the real auto|on|off daemon contract with
legacy-value tolerance; write-tool counts follow Appendix A per style and
include write-capable custom tools (readOnly is false while any is
enabled; Make read-only disables them); disabled_tools ownership resolves
by exact {service}_{verb} so sibling names (db / db_backup) never claim
each other's keys; system_mcp bare tool names are never 'orphans'; store
derivations memoized behind a version counter.

Tools: trackBy + identity-stable row arrays (mat-menus no longer torn
down by the next change-detection pass — regression spec included);
access chips recolored so Read-only reads as the safe state; bulk
'Copy curation from…'; rail gains Copy tool list, Manage roles link and
the lazy Why explainer; custom-tool dialog guards dismissal.

Connect/Settings/Create: probe claims 'auth enforced' only on a real
401/403 challenge; zero-tools warning on Connect; single checklist
grammar; redirect-URI jump prompt; catalog-delivery options store
on/off; style-switch reassurance ('Your tool selections are preserved');
clone preserves a null tool_style as prefixed.

Shared: indeterminate checkboxes take the DF purple; custom-tool header
blobs exempt from case transforms; unsaved-changes canDeactivate guard
across editor and create; endpoint header deduplicated against the
Connect hero card.

165 jest tests, 13/13 live e2e green. Also fixes the instance-side
root-owned Laravel cache file that made rapid admin logins 401/500.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… server-backed catalog size

Settings: "Require role access" (Authentication) and "Allow writes"
(Serving, hidden for system_mcp) switches, saved through the existing
whole-service PUT. allow_writes=false now drops the daemon's write verbs
and write-capable custom tools from every count, the rail, preview and
copy-tool-list; the rail reads "writes are off" instead of offering
Make read-only. New services are created with require_role_access=true
and allow_writes=true (read-only stays compiled into disabled_tools).

Header: /_internal/ai/mcp-health chip (ok / warn / error) with the first
non-ok check's message; the endpoint URL uses APP_URL from the app_url
check, with a note when it differs from the page origin.

Catalog size: the flat 81 tokens/tool + 8k-token model is replaced by
the daemon's byte model (32 KiB LAZY_THRESHOLD_BYTES, bytes/4 tokens,
5-tool facade incl. fetch_more). Numbers come from the server for the
saved config (admin: tools/list over JSON-RPC; role/app:
mcp-catalog via store.setPreviewIdentity), and fall back to the
calibrated client simulation while the form is dirty or the call fails.

Refs #526
…nd API keys (#525)

Ports the inline access editor from feat/mcp-exposure onto the redesigned
MCP editor: roles that can use the server (from /_internal/ai/mcp-access),
one-click Grant, an access editor dialog (create / add / edit; per-service
none / read / read-write; Read on all; filter above 6; limit to tables;
live summary of the role changes), optional API key creation whose key the
Connect snippets then fill instead of YOUR_API_KEY. Respects allow_writes.
…he daemon

The UI treated all six all_* tools as database aggregators. The daemon
registers the five database ones at 2+ databases and all_list_files only at
2+ file services, so a databases-only server showed one tool more than it
serves (logistics_mcp: 25 vs server 24).
…tor changes its level

A row restricted to API callers (requestor_mask 1) was silently widened to
API+script (3) on any level change. Also pin the writes switch as
connection-affecting in the store spec.
mcp-service and mcp-redesign-flows no longer depend on service ids 9/21/6 or
names mcp_full/sysmcp_demo/db/db2/files/logs. Each file creates two SQLite
databases, a local file service, an mcp server (API-key auth, custom tool
env_info) and a system_mcp server under its own prefix in beforeAll and
deletes them in afterAll.

- Endpoint URLs are expected from APP_URL (mcp-health) like the editor,
  falling back to the page origin.
- Restore check ignores custom tools' created_at/updated_at (re-stamped on
  every save).
- workers: 1, as the config comment already intended: suites create/delete
  services and assert against the instance-wide service list.

Verified: 13/13 twice in a row on df-dev (APP_URL differs from the page
origin there), no e2e_* services left behind.
- Tools tab: each exposed service row now carries one cell per tool, in
  columns aligned under a per-kind header with rotated tool names, a switch
  per column (that tool in every exposed database) and per group (Read,
  Schema, Write, Procs). Green = served read, orange = served write/execute,
  hollow = off, hatched = blocked by allow_writes. Legend below. Drill-in,
  access chip and menus unchanged.
- Header: APP_URL and other health problems render as df-alert banners like
  the rest of the admin; the APP_URL copy explains which address clients
  must use instead of the raw health string.
- Tabs: mat-tab-nav-bar with bolder labels and an active tint.
- Every hard-coded colour in adf-mcp now uses the DF theme tokens (rgba
  alphas via color-mix), so the editor works in dark and phosphor themes;
  cards were white-on-white in dark mode before.
@nicdavidson
nicdavidson merged commit 4082550 into develop Sep 22, 2026
1 check passed
@nicdavidson
nicdavidson deleted the feat/mcp-ui branch September 22, 2026 20:20
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.

1 participant