Skip to content

mcp-data-platform-v0.36.0

Choose a tag to compare

@github-actions github-actions released this 08 Mar 06:32
· 292 commits to main since this release
e18eab9

Portal UX Enhancements — User Activity, Knowledge, Tool Titles, Help Rewrite (#200)

This release adds two new user-facing portal sections (Activity and My Knowledge), surfaces human-readable tool display names across the entire UI, fixes a sidebar navigation bug, and rewrites all admin help content for non-technical users.


New: User Activity Page

Portal users now have a personal Activity dashboard at /portal/activity showing their own usage metrics:

  • Summary cards — Total Calls, Avg Duration, Tools Used
  • Activity Timeline — Interactive time-series chart of tool calls over time (reuses the admin TimeseriesChart component)
  • Top Tools — Horizontal bar chart showing most-used tools with human-readable names (reuses BreakdownBarChart)
  • Time range selector — 1h, 6h, 24h, 7d presets

Design decision: Success Rate is intentionally excluded from the user view. In AI-assisted workflows, "errors" are typically the agent self-correcting — trying a table name, getting a not-found, then adjusting. This is normal agent behavior, not something users should worry about. Success rate remains available in the admin dashboard where it's useful for platform tuning.

Backend

New portal endpoints auto-filtered to the authenticated user's user_id:

Endpoint Description
GET /api/v1/portal/activity/overview Aggregate stats (total calls, avg duration, unique tools)
GET /api/v1/portal/activity/timeseries Time-bucketed call counts with resolution parameter
GET /api/v1/portal/activity/breakdown Top tools/connections grouped by dimension

All three accept start_time, end_time query parameters (RFC 3339). The timeseries endpoint also accepts resolution (minute, hour, day) and the breakdown endpoint accepts group_by and limit.

Implementation: Added UserID string field to audit.TimeseriesFilter, audit.BreakdownFilter, and a new audit.MetricsFilter struct (replacing the previous startTime, endTime *time.Time parameters on Overview() and Performance()). The PostgreSQL metrics queries add WHERE user_id = $N when UserID is set. This is a breaking change to the AuditMetricsQuerier interface — all callers updated.


New: My Knowledge Page

Users whose persona includes the capture_insight tool now see a My Knowledge section in the portal sidebar, showing their own captured insights:

  • Summary cards — Total Insights, Pending, Approved, Applied
  • Status filter buttons — All, Pending, Approved, Applied, Rejected
  • Insights list — Each insight shows status badge, category label, insight text, entity URN chips, review notes, and creation date
  • Pagination — 20 items per page with previous/next navigation
  • Conditional visibility — The sidebar item only appears when the user's resolved persona includes capture_insight in its tool list

Backend

Endpoint Description
GET /api/v1/portal/knowledge/insights List user's insights (filtered by captured_by = user_id)
GET /api/v1/portal/knowledge/insights/stats Insight counts by status, category, confidence

Both endpoints use the existing knowledge.InsightStore.List() and Stats() methods with CapturedBy pre-set to the authenticated user.

Persona & Tools in /me Response

The GET /api/v1/portal/me endpoint now returns two additional fields:

{
  "user_id": "sarah.chen@acme-corp.com",
  "roles": ["analyst"],
  "is_admin": false,
  "persona": "data-analyst",
  "tools": ["trino_query", "datahub_search", "capture_insight", "..."]
}

The tools list is resolved by running the persona's Allow/Deny patterns against the full toolkit registry, giving the frontend the exact set of tools available to the user. This enables conditional UI rendering without additional API calls.

New types: PersonaResolver func(roles []string) *PersonaInfo and PersonaInfo{Name, Tools} in the portal package. The resolver is built from the persona and toolkit registries during platform initialization.


New: Tool Display Names

Tools are now displayed with human-readable titles throughout the UI instead of raw snake_case identifiers (e.g., "Execute SQL Query" instead of trino_query).

Backend

Every tool registered by the upstream toolkits already has a Title field set:

Toolkit Example Titles
Trino Execute SQL Query, Execute SQL (Write), Explain Query Plan, Describe Table, Browse Catalog
DataHub Search Catalog, Get Entity, Get Schema, Get Lineage, Get Queries
S3 List Buckets, List Objects, Get Object, Generate Presigned URL
Knowledge Capture Insight, Apply Knowledge
Portal Save Artifact, Manage Artifact

The Title field is now included in two admin API responses:

  • GET /api/v1/admin/toolstitle field on each toolInfo object
  • GET /api/v1/admin/tools/schemastitle field on each toolSchema object

For the tools list endpoint, buildToolTitleMap() calls session.ListTools() internally to resolve titles from the MCP server.

Frontend

New utility formatToolName(name, title?) — uses the backend-provided title when available, falls back to converting snake_case to Title Case.

Applied across all UI surfaces where tool names appear:

Page What changed
Tools (inventory table) Tool names show titles
Tools (tool selector) Dropdown shows titles
Tools (explore tab) Schema names show titles
Audit Log (events table) tool_name column shows titles
Dashboard (top tools chart) Bar chart labels show titles
Activity (top tools chart) Bar chart labels show titles via labelMap prop
ProvenancePanel Unified with formatToolName, removed hardcoded mapping

The BreakdownBarChart component now accepts an optional labelMap prop (Record<string, string>) for mapping raw dimension values to display labels.


Fix: Sidebar Dashboard Highlight Bug

Bug: When navigating from Dashboard to another admin section (e.g., Tools), Dashboard remained highlighted alongside the actual active section.

Root cause: The isActive() function in Sidebar.tsx matched both exact path AND prefix for admin routes. So /admin/tools matched /admin via route.startsWith("/admin" + "/"), causing Dashboard to always appear active.

Fix: /admin now uses exact match only, consistent with / and /shared.


Rewritten: Admin Help Sections

All five admin help tabs have been rewritten for non-technical administrators:

Page Lines changed
Dashboard (Home) Simplified from developer reference to user-oriented overview
Tools Removed YAML config examples, API endpoint docs
Audit Log Focused on "what you can learn" not "how it's stored"
Knowledge Explained the insight lifecycle in plain language
Personas Removed config file references, explained role mapping simply

Guidelines applied:

  • No references to YAML, configuration files, config_mode, DSN, or PostgreSQL
  • No admin API endpoint documentation (admins are not developers)
  • Replaced "injection" with "enrichment" (2 instances)
  • Focus on what it does for you, not how it's configured
  • Plain language, short paragraphs, practical examples

Improved: Onboarding Empty States

My Assets (no assets yet):

Assets are interactive dashboards, visualizations, and documents created during your conversations. Try asking your assistant to "create an interactive dashboard" or say "save this as an asset" to get started.

My Knowledge (no insights yet):

When you share knowledge about your data — corrections, business context, or quality observations — it gets captured here for review. Try telling your assistant something like "the revenue column excludes returns" or "this table is refreshed weekly". Approved insights improve the data catalog for everyone.


Portal Wiring

New optional dependencies on the portal handler, all nil-safe:

Dependency Source Purpose
AuditMetrics platform.AuditStore() User-scoped activity metrics
InsightStore platform.KnowledgeInsightStore() User-scoped insight listing
PersonaResolver persona.Registry + registry.Registry Resolve roles → persona + tools

Extracted wirePortalOptionalDeps() and buildPersonaResolver() helper functions from mountPortalAPI() to stay under the cognitive complexity limit (gocognit ≤ 15).


Files Changed

Area Files Delta
Backend wiring cmd/mcp-data-platform/main.go +38
Admin API pkg/admin/system.go, tools.go, handler.go, audit_metrics.go +59
Audit metrics pkg/audit/metrics.go, postgres/metrics.go +47
Portal API pkg/portal/handler.go +239
Portal tests pkg/portal/handler_test.go +417
Metrics tests pkg/audit/postgres/metrics_test.go +125
Swagger docs internal/apidocs/ +20
Frontend types & hooks ui/src/api/ +186
New pages ActivityPage.tsx, MyKnowledgePage.tsx +334
Layout & nav Sidebar.tsx, AppShell.tsx +23
Tool formatting formatToolName.ts, BarChart.tsx, ProvenancePanel.tsx +72
Help rewrites 5 admin page files -730
Mock data ui/src/mocks/handlers.ts +95
Auth store ui/src/stores/auth.ts +2

Total: 34 files changed, 1,810 insertions, 1,010 deletions


Installation

Homebrew (macOS)

brew install txn2/tap/mcp-data-platform

Claude Code CLI

claude mcp add mcp-data-platform -- mcp-data-platform

Docker

docker pull ghcr.io/txn2/mcp-data-platform:v0.36.0

Verification

All release artifacts are signed with Cosign. Verify with:

cosign verify-blob --bundle mcp-data-platform_0.36.0_linux_amd64.tar.gz.sigstore.json \
  mcp-data-platform_0.36.0_linux_amd64.tar.gz