Conversation
Add isSystemMcp, derived from the selected (create) or loaded (edit) service type name === 'system_mcp'. For such services the details page shows a single "System API · 17 tools" panel driven by a fixed tool catalogue (system-mcp-tools.ts, mirroring df-system-mcp-server TOOL_NAMES) with the same enable/disable toggles bound to disabledTools, skips loadMcpServices(), hides the per-service panels and the Custom Tools section, and omits customTools from the save payload. MCP endpoint and OAuth fields are unchanged. Claude-Session: https://claude.ai/code/session_01PSYuns4gquVBXZc9STN6wa
The login card was height: 100% plus margin-top: 20vh, which made mat-sidenav-content ~20vh taller than the viewport. Center with min-height instead, and constrain the logo on narrow screens. Fixes #517. Dist is not in this PR — rebuild on develop after merge.
…service-ui feat(services): System API MCP Server (system_mcp) service details UI
…ger UI The backend emits servers[0].url as '/api/v2/<service>' (valid, portable). Swagger UI receives the spec inline, so it has no document URL to resolve that against and prints host-less curl examples and Request URLs. Prefix relative server URLs with window.location.origin at render time only; the downloaded api-spec.json keeps the relative URL. Fixes #519
The operations view passed '/api/v2/<service>' into df-try-it as baseUrl, which it uses verbatim for the resolved-URL line and the curl / Python / JS snippets, bypassing its own origin fallback. Prefix with the page origin so the snippets are copy-pasteable. Includes rebuilt dist. Refs #519
…les-and-request-url-show-rela API Docs: show full instance URL in Swagger curl examples and Request URL
…ogue Read-only tool that reports last-used / never-used / stale API keys, roles and users from system/access_usage. Catalogue and spec go from 17 to 18 tools; df-system-mcp-server TOOL_NAMES must list it after list_admins.
…, roles, users, admins Join GET system/access_usage client-side (like the apps table's AI usage join) through a new DfAccessUsageService, and opt the apps, roles, users and admins tables into it via DfManageTableComponent.enableAccessUsage(): - "Last used" (apps, roles) / "Last active" (users, admins) column with relative time or "Never"; tooltip carries the exact time, the service and status of the last use, the last denial, stale window, last login and 30-day volume when present, and "no use recorded since" tracking start for never-used subjects - muted text for stale / never-used subjects, a warning icon for inactive keys that clients still send, an "Unreferenced" badge on roles - "Not used in" selector (Any / 30 / 90 / 180 days / Never used), filtering the loaded rows client-side; the column sorts by last use The request is silent: on 404 (older DreamFactory), 401/403, 400 or any error the column and filter stay hidden and the tables render as before.
…ess-usage-ui feat: access-usage last-used column and filter; get_access_audit in System MCP tool catalogue
With tool_style=merged the daemon registers each database verb once and selects the backend with a `service` argument, so the per-service panels - which list dvdstore_delete_records, db_delete_records and so on - no longer describe the tools a client actually sees. In merged mode the database panels are replaced by one "Database Tools (merged)" panel: 16 bare verbs down the side, one column per database, and a toggle per cell. Columns are labelled with the API name rather than the display label, because the name is what the `service` argument takes. Disable keys stay prefixed (<service>_<verb>) in both modes. The daemon reads those entries and enforces them per service, dropping the database from the merged tool's `service` enum and refusing it at call time, so the same checkbox means the same thing whichever style is selected. Writing bare verbs here would instead disable the verb for every database. File services keep their own panels; merged mode merges database tools only.
…ls-ui Feat/mcp merged tools UI
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.
MCP editor redesign (Kevin's UI) + roles/keys, health, tool grid, server-backed counts
The MCP editor assumed merged tool_style applied to databases only, which was
true of the daemon until file services gained merged registration. With that
support in place the editor disagrees with the server: on a service exposing
three databases and three file services it reports 47 tools while the daemon
advertises 35, and the tool grid still labels the file rows logs_list_files
when a client is served a bare list_files.
Five places carried the assumption:
- effectiveTools() summed file verbs per service unconditionally, so the
Tools tab over-counted by (services - 1) x 6. It now branches on style the
way the database count already does.
- the write math counted file write verbs as per-service instances in both
styles; merged now counts the distinct verb set, matching databases.
- the tool grid resolved the emitted name with style for databases and a
hardcoded 'prefixed' for file services.
- the merged caption, which explains that turning a verb off narrows the
tool's allowed services rather than removing it, was gated to databases.
- the preview pane listed file tools under per-service names always, and the
custom-tool dialog reserved only prefixed file names, so a custom tool
could collide with a merged file verb without being flagged.
disabled_tools keys stay in the prefixed {service}_{verb} form in both styles,
so the store's write path is unchanged; this is presentation and arithmetic.
Note for review: the Appendix A write-tool test asserted file services were
per-service instances in BOTH styles. That invariant is what changed, so the
test now asserts 3 merged and 6 prefixed for two file services.
"list -> open the MCP server lands on Connect with URL, probe and live count" fails on develop with Expected: 22, Received: 6. The header chip renders as soon as the editor does, showing the count the store can compute before the backend-services fetch has landed — globals and custom tools only. The test read it once, with textContent(), and compared that first paint against the settled model, so it raced the fetch and lost. The Tools tab tests do not hit this because openToolsTab() waits for .mcp-tools-loading to clear first. Read the chip through expect.poll so the assertion retries until the catalog arrives, and assert the model is non-trivial separately rather than inferring it from the racing read. numberFrom() is left alone for the callers that read values which are settled by the time they run.
…unt-race fix(e2e): poll the live tool count instead of reading it once
…e-tools-ui Feat/mcp merged file tools UI
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.