Skip to content

Releases: txn2/mcp-data-platform

mcp-data-platform-v0.35.7

07 Mar 16:40
7205314

Choose a tag to compare

Portal UX Improvements

Five improvements to the portal UI addressing production issues and enhancing usability.

Fix: Emoji and Unicode Rendering in Iframes

Blob URLs created without an explicit charset caused browsers to default to Latin-1 encoding, rendering multi-byte UTF-8 characters as mojibake (e.g. П"Š instead of the intended emoji). This release adds <meta charset="UTF-8"> and charset=utf-8 Blob MIME types to all iframe HTML templates in both the JSX and HTML renderers.

New: Branded Loading Indicator

Replaced the plain "Loading..." text with a pulsating platform logo that uses the existing branding configuration. The branded loader appears during auth checks, asset loading, and content loading states.

New: Collapsible Left Sidebar

The left sidebar now toggles between full width (16rem) and icon-only mode (4rem) via a double-chevron button at the bottom. Features:

  • Smooth 200ms CSS width transition
  • Collapsed state persists to localStorage
  • Icon-only buttons show title tooltips when text labels are hidden
  • Admin section header hides cleanly in collapsed mode

New: Auto-Collapse on Dashboard Deep-Link

When navigating directly to /assets/:id, both the left sidebar and the right details panel start collapsed to maximize content space. The left sidebar auto-restores to its previous state when navigating away — unless the user explicitly toggled it during the session.

New: Provenance Panel Redesign

The raw provenance timeline has been replaced with an interactive card-based layout:

  • Tool-specific icons and labels — 22 tool mappings translate raw names like trino_query into human-friendly labels like "SQL Query" with a Database icon. Unknown tools fall back to the raw name with a Terminal icon.
  • Smart summary extraction — Parses the raw JSON parameters to surface the most relevant information: SQL snippets (truncated to 120 chars), search terms, URNs, fully-qualified table paths (catalog.schema.table), and S3 bucket/key paths.
  • Relative timestamps — Shows "just now", "5 min ago", "2h ago", etc. with a full timestamp on hover.
  • Detail modal — Click any provenance card to open a modal with pretty-printed parameters. SQL queries get a "SQL Query" heading; everything else shows "Parameters".

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.35.7

Verification

All release artifacts are signed with Cosign. Verify with:

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

mcp-data-platform-v0.35.6

07 Mar 06:46
11483fe

Choose a tag to compare

Session Stability Fix

This release fixes a critical session management bug that caused provenance tracking and enrichment deduplication to silently fail after session expiry.

The Problem

When a client reconnects after its session expires (30-min TTL or pod restart), the server previously generated a new random session ID. However, MCP clients like Claude Desktop cache their session ID from the initial handshake and never update it from response headers. This created an infinite replacement cycle:

Client sends Mcp-Session-Id: ABC123
  → store.Get("ABC123") returns nil (expired)
  → server generates new ID: XYZ789
  → client ignores new header, keeps sending ABC123
  → next request: store.Get("ABC123") returns nil again
  → cycle repeats indefinitely

Impact: Every tool call after session expiry was recorded under a different session ID, so provenance.harvest always returned 0 calls. Enrichment dedup (WasSentRecently) also broke since each request appeared to be a fresh session, causing redundant metadata injection on every response.

The Fix

A new reviveSession method recreates the expired session using the client's original ID instead of generating a new one. After revival, the session is stable and all subsequent requests resolve normally.

Client sends Mcp-Session-Id: ABC123
  → store.Get("ABC123") returns nil (expired)
  → reviveSession recreates session with ID ABC123
  → next request: store.Get("ABC123") succeeds
  → provenance and dedup work correctly from here on

Additional Hardening

  • Postgres upsert on session createINSERT ... ON CONFLICT (id) DO UPDATE eliminates unique constraint violations if two concurrent requests try to revive the same expired session simultaneously
  • Dead code removal — Removed the now-unused ReplacedSessionID / WithReplacedSessionID context propagation and the harvestProvenance replaced-session fallback, which became unreachable after switching to same-ID revival

Changed Files

File Change
pkg/session/handler.go New reviveSession method; handleExisting uses same-ID revival; removed ReplacedSessionID infrastructure
pkg/session/handler_test.go 6 new/updated tests covering revive stability, timestamps, error paths, and concurrent access
pkg/session/postgres/store.go Create uses upsert to handle race conditions on expired rows
pkg/middleware/mcp_provenance.go Simplified harvestProvenance — no longer checks for replaced session IDs
pkg/middleware/mcp_provenance_test.go Removed session-replacement merge tests (dead code paths)

Test Coverage

  • handleExisting: 96.3%
  • reviveSession: 100%
  • harvestProvenance: 100%
  • All checks pass via make verify

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.35.6

Verification

All release artifacts are signed with Cosign. Verify with:

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

mcp-data-platform-v0.33.5

06 Mar 22:07
957c3a6

Choose a tag to compare

What's Fixed

This release fixes the blank-page JSX rendering bug that affected v0.33.1 through v0.33.4, and adds provenance session ID propagation so tool-call history survives session recovery.

JSX Renderer: dual React instance bug

The sandboxed iframe used ?bundle on all esm.sh imports. Each ?bundle URL creates a self-contained bundle with its own copy of React internals:

  • react@19?bundle → React instance A
  • react@19&bundle/jsx-runtime → React instance B (Sucrase's automatic JSX runtime)
  • react-dom@19/client?bundle → React instance C

When `createRoot` (instance C) mounted a component whose hooks were compiled against instance B's jsx-runtime, `useState` tried to read a dispatcher that was never set — producing `TypeError: Cannot read properties of null (reading 'useState')` and a blank iframe.

Root cause: `?bundle` inlines ALL transitive dependencies, creating isolated copies of React internals that don't share state.

Fix: Remove `?bundle` from `react` and `react-dom` so esm.sh deduplicates via shared module URLs. Leaf packages (recharts, lucide-react) use `?bundle&external=react,react-dom` to bundle their own deps while externalizing React.

JSX Renderer: replaced blob-module imports with inline Sucrase transform

The old auto-mount path used `await import(blobUrl)` which triggered `TypeError: Failed to fetch dynamically imported module: blob:...` in sandboxed iframes. Now uses Sucrase to transform JSX at the host level, then injects the plain JS directly into the iframe's `<script type="module">` with an import map.

JSX Renderer: `</script>` injection safety

Transformed JSX injected into the iframe's `<script>` block could contain literal `</script>` strings, breaking the HTML structure. Added `escapeScriptClose()` to replace `</script` with `<\/script` (valid JS escape, does not terminate the HTML script tag). Error display also switched from raw HTML interpolation to safe `textContent` assignment via `JSON.stringify`.

Additional JSX Renderer improvements

  • `unhandledrejection` handler: Module-level import failures don't trigger `window.onerror`. The new handler catches these and displays the error instead of a silent blank page.
  • CSP entries for Google Fonts: Dashboard artifacts that use `@import url('fonts.googleapis.com/...')` no longer get blocked.
  • Component detection rewrite: `findComponentName()` replaces the old `ensureExport()` approach. Instead of mutating source to add `export default`, the renderer detects the component name and generates a mount call directly.

Provenance session ID propagation

When a browser session expires and gets replaced (user has a valid auth token), the old session's provenance data was previously lost because it was keyed to the old session ID.

  • `WithReplacedSessionID` / `ReplacedSessionID`: new context helpers in `pkg/session` to carry the old session ID through the replacement flow.
  • `harvestProvenance`: new helper in `pkg/middleware` that collects tool calls from both the current session AND the replaced session, merging them in chronological order.
  • The session handler now calls `WithReplacedSessionID` in `handleExisting` when creating a replacement session.

Test Coverage

  • 20 vitest tests (JSX transform, component detection, script escape, injection safety, renderer integration, regression)
  • 5 new Go tests (ReplacedSessionID roundtrip, empty context, session replacement, normal session, provenance harvest merge)
  • Full Go suite passes with `-race`
  • Browser-verified with complex 25KB JSX dashboard (recharts, tabs, KPI cards)

Installation

Homebrew (macOS)

```bash
brew install txn2/tap/mcp-data-platform
```

Claude Code CLI

```bash
claude mcp add mcp-data-platform -- mcp-data-platform
```

Docker

```bash
docker pull ghcr.io/txn2/mcp-data-platform:v0.33.5
```

Verification

All release artifacts are signed with Cosign. Verify with:
```bash
cosign verify-blob --bundle mcp-data-platform_0.33.5_linux_amd64.tar.gz.sigstore.json
mcp-data-platform_0.33.5_linux_amd64.tar.gz
```

mcp-data-platform-v0.33.4

06 Mar 20:13
f8f6254

Choose a tag to compare

Summary

Fixes two bugs in the Asset Portal and hardens the JSX renderer, provenance tracking, and test coverage.

Bug Fix: Blank JSX Content in Asset Viewer

Problem: Agent-generated JSX components define React components but never call createRoot/ReactDOM.render, so the iframe rendered blank with no errors.

Fix: The JsxRenderer now detects whether content is self-mounting (contains createRoot or ReactDOM.render) and handles each path differently:

  • Self-mounting path (backward compatible): content with mount calls uses the existing import-map + inline injection, now with error handling
  • Auto-mount path (new): content without mount calls goes through bare-specifier resolution (rewrites from 'react' to absolute esm.sh URLs for blob module compatibility), automatic export default detection, and dynamic import via React.createElement(mod.default)

Additional hardening:

  • Memory leak fix: module blob URLs are now tracked via useRef and properly revoked on cleanup
  • Single source of truth: IMPORT_MAP is derived from BARE_IMPORT_MAP — no more duplicated maps
  • XSS prevention: error display uses textContent via a showError() helper instead of innerHTML concatenation
  • Fewer false positives: hasMountCode uses regex (/\bcreateRoot\s*\(/) instead of String.includes(), reducing false matches from comments
  • Class component support: ensureExport now handles class declarations alongside function|const|let
  • CSP updated: added blob: to script-src and connect-src for the auto-mount path

Bug Fix: Empty Provenance ("No provenance data available")

Problem: The provenance middleware accumulates tool calls keyed by session ID, but AwareHandler's session ID was not propagated through the Go request context. MCPToolCallMiddleware used the default "stdio" key while save_artifact used a different key, resulting in an empty harvest.

Fix: Context-based session ID propagation:

  • AwareHandler now calls WithAwareSessionID(ctx, sessionID) in both handleInitialize and handleExisting, injecting the session ID into the Go request context
  • MCPToolCallMiddleware falls back to AwareSessionID(ctx) when the MCP SDK returns the default "stdio" session ID
  • This ensures Streamable HTTP requests always get the correct per-client session ID regardless of MCP SDK behavior
Transport Before After
Streamable HTTP + AwareHandler Works only if client echoes Mcp-Session-Id header Always works via context propagation
SSE All clients share "stdio" key Same (AwareHandler doesn't wrap SSE)
stdio Uses "stdio" Same (no HTTP layer)

Other Improvements

  • Provenance log noise reduced: Harvest() log level lowered from Info to Debug — no longer logs on every save_artifact call in production
  • Diagnostic logging: Record(), Harvest(), and save_artifact handler now emit structured debug/info logs with session ID and tool call counts for troubleshooting

Test Coverage

  • Integration test added: TestMiddlewareChain_AwareHandler_ProvenanceSessionID wires up the full AwareHandler → Stateless StreamableHTTP → MCPToolCallMiddlewareMCPProvenanceMiddleware chain and verifies end-to-end session ID propagation with a real HTTP transport
  • Unit tests: AwareSessionID/WithAwareSessionID roundtrip, handleInitialize and handleExisting context propagation, MCPToolCallMiddleware AwareHandler fallback
  • All new functions at 100% coverage

Files Changed

  • pkg/session/handler.goWithAwareSessionID/AwareSessionID context helpers
  • pkg/middleware/mcp.go — AwareHandler session ID fallback in MCPToolCallMiddleware
  • pkg/middleware/mcp_provenance.go — diagnostic logging, Harvest log level fix
  • pkg/toolkits/portal/toolkit.gosave_artifact provenance diagnostic logging
  • ui/src/components/renderers/JsxRenderer.tsx — auto-mount, memory leak, XSS, dedup fixes

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.33.4

Verification

All release artifacts are signed with Cosign. Verify with:

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

mcp-data-platform-v0.33.3

06 Mar 17:49
7030abc

Choose a tag to compare

Bug Fixes

Portal S3 client ignores use_path_stylepkg/platform/platform.go

The portal's S3 client (createPortalS3Client) constructed its own s3client.Config but never propagated UsePathStyle from the S3 instance configuration. The AWS SDK defaults to virtual-hosted style addressing, which prepends the bucket name to the endpoint hostname during DNS resolution — e.g., portal-assets.seaweedfs:8333 instead of seaweedfs:8333/portal-assets.

This caused no such host DNS lookup failures on any deployment using SeaweedFS, MinIO, or other S3-compatible storage that requires path-style URLs. All portal artifact operations (save, view, share) were broken in these environments even though the S3 toolkit's own client correctly honored use_path_style: true.

Root cause: Three values were missing from the portal's S3 client construction path:

Location What was missing
s3Config struct No UsePathStyle field — the value was never extracted
getS3Config() Never read use_path_style from the instance config map
createPortalS3Client() Never set UsePathStyle on the s3client.Config

The S3 toolkit's own initialization (pkg/toolkits/s3/toolkit.go) takes a separate code path through its typed InstanceConfig struct, which correctly sets UsePathStyle. The portal's path through getS3Config()createPortalS3Client() was a different code path that missed this field.

Fix: Three one-line additions in pkg/platform/platform.go to thread use_path_style through the full chain.

Code Quality

Fix noctx lint violations across test suite

Replaced httptest.NewRequest() with httptest.NewRequestWithContext(context.Background(), ...) in 24 test files to satisfy the noctx linter rule. No behavioral changes.

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.33.3

Verification

All release artifacts are signed with Cosign. Verify with:

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

mcp-data-platform-v0.33.2

06 Mar 08:07
c7e71a4

Choose a tag to compare

Bug Fixes

This release fixes three portal bugs discovered during production deployment, all related to the portal artifact system.

Nil S3Client panic (crash) — pkg/portal/handler.go, pkg/portal/public.go

When no s3_connection was configured, both getAssetContent and fetchPublicAsset called S3Client.GetObject() on a nil pointer, causing repeated panics (panic: nil pointer dereference). Both endpoints now return HTTP 503 with "content storage not configured" instead of crashing.

Additionally, the toolkit's write paths (handleSaveArtifact and uploadContentUpdate in pkg/toolkits/portal/toolkit.go) silently skipped S3 uploads when the client was nil, creating ghost assets in the metadata store that pointed to non-existent S3 content. These now fail early with a clear error instead of silently producing broken assets.

Admin section not visible — pkg/portal/handler.go, cmd/mcp-data-platform/main.go

The /api/v1/portal/me endpoint hardcoded slices.Contains(user.Roles, "admin") but OIDC roles arrive with a configured prefix (e.g., dp_admin). The check now uses AdminRoles populated from the admin persona's configured roles via the PersonaRegistry, so any role prefix scheme works correctly. When no admin persona is configured, the behavior is fail-closed (no admin access granted).

Wrong deep link URL from save_artifactpkg/toolkits/portal/toolkit.go

The buildSaveOutput function generated portal URLs with path /artifacts/{id} but the portal UI serves assets at /portal/assets/{id}. Fixed the path to match the actual route.

Changed Files

File Change
cmd/mcp-data-platform/main.go Populate AdminRoles from admin persona config via PersonaRegistry
pkg/portal/handler.go Add AdminRoles to Deps; nil-guard S3Client; use hasAnyRole for admin check
pkg/portal/handler_test.go Tests for nil S3Client, prefixed admin roles, hasAnyRole edge cases
pkg/portal/public.go Nil-guard S3Client in fetchPublicAsset, return 503
pkg/portal/public_test.go Test for nil S3Client in public view path
pkg/toolkits/portal/toolkit.go Fail early on nil S3Client in write paths; fix deep link URL
pkg/toolkits/portal/toolkit_test.go Tests for nil S3Client in save/update, buildSaveOutput URL

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.33.2

Verification

All release artifacts are signed with Cosign. Verify with:

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

mcp-data-platform-v0.33.1

06 Mar 06:00
151e680

Choose a tag to compare

Highlights

v0.33.1 fixes two portal authentication bugs that prevented the browser-based portal from working correctly when OIDC authentication is enabled. Users hitting the root path (/) in a browser were getting a 401 instead of being redirected to the portal, and once inside the portal, admin API calls failed because browser sessions produced different role names than the MCP auth path.

Portal Role Prefix Consistency (#190)

The browser session OIDC flow and the MCP OAuth/OIDC flow handled role_prefix differently, making it impossible for persona role matching to work across both paths.

Root cause: extractRoles in the browser session path used strings.CutPrefix to strip the configured prefix (e.g., dp_admin became admin), while filterByPrefix in the MCP auth path used strings.HasPrefix and kept the full role name (dp_admin stayed dp_admin). Since persona definitions use a single roles list that must match both auth paths, the browser session's stripped roles never matched.

Fix: Changed extractRoles to filter-only behavior (keep the full role name), matching filterByPrefix. Both paths now produce identical role lists.

Before:  MCP → dp_admin, Browser → admin     (persona match fails for browser)
After:   MCP → dp_admin, Browser → dp_admin   (persona match works for both)

Root Path Redirect Ordering (#190)

When both portal UI and authentication are enabled, browser requests to / received a 401 instead of being redirected to /portal/.

Root cause: MCPAuthGateway wrapped outside browserRedirectMiddleware in the HTTP handler chain. Since the auth gateway is method-agnostic (rejects any request without credentials), browser GET requests hit the 401 before the redirect middleware could fire.

Fix: Moved browserRedirectMiddleware to wrap outside the auth gateway in mountRootHandler, so browsers are redirected before auth is evaluated. MCP clients (POST requests without Accept: text/html) still pass through to the auth gateway normally.

Before:  MCPAuthGateway → browserRedirect → handler   (browser GET → 401)
After:   browserRedirect → MCPAuthGateway → handler   (browser GET → 307 /portal/)

DOMPurify Security Update (#188)

Updated the portal UI's DOMPurify dependency from 3.3.1 to 3.3.2, which addresses:

  • A possible sanitization bypass caused by jsdom's faulty raw-text tag parsing
  • A prototype pollution issue when working with custom elements
  • Lenient config parsing in _isValidAttribute

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.33.1

Verification

All release artifacts are signed with Cosign. Verify with:

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

mcp-data-platform-v0.33.0

06 Mar 04:14
7eb764d

Choose a tag to compare

Highlights

v0.33.0 extends apply_knowledge to work with all DataHub entity types, not just datasets. Domains, glossary terms, data products, dashboards, charts, and other entities can now receive description updates, tags, glossary term associations, documentation links, and quality issue flags directly through the MCP tool. A follow-up fix closes a pre-flight validation gap that could have allowed partial writes on unsupported entity types.

Non-Dataset Entity Support for apply_knowledge (#187)

Previously, apply_knowledge only worked with dataset URNs. This release lifts that restriction for most operations, enabling catalog-wide metadata management from a single tool.

  • Upgrade mcp-datahub v1.1.1 to v1.2.0 — brings entity-type-aware UpdateDescription that resolves the correct aspect name per entity type (dataset, dashboard, domain, glossaryTerm, etc.)
  • Pre-flight entity type validation — before executing any writes, all changes in a batch are validated against the target URN's entity type; incompatible operations reject the entire batch before any DataHub writes occur
  • Actionable error messages — when an operation is unsupported for an entity type, the error lists the operations that are supported (e.g., "add_curated_query is only supported for datasets, not domain entities. Supported operations for domain: update_description, add_tag, remove_tag, ...")
  • Tool description and schema updates — LLM clients now see which operations work on which entity types upfront in the tool schema

Entity Type Support Matrix

Operation Supported Entity Types
update_description dataset, dashboard, chart, dataFlow, dataJob, container, dataProduct, domain, glossaryTerm, glossaryNode
update_description with column:<field> dataset only
add_tag / remove_tag all
add_glossary_term all
add_documentation all
flag_quality_issue all
add_curated_query dataset only

Pre-flight Validation Fix (#189)

Fixes a bug where entity-level update_description on unsupported entity types (e.g., tag) passed pre-flight validation but failed at DataHub write time, breaking batch atomicity — earlier changes in the batch would already be applied.

  • Validation gap closeddescriptionSupportedTypes is now checked during pre-flight for entity-level description updates
  • Error chain preservedwrapUnsupportedEntityTypeError now uses %w so errors.Is works downstream

Dependency Changes

Dependency Previous New
github.com/txn2/mcp-datahub v1.1.1 v1.2.0

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.33.0

Verification

All release artifacts are signed with Cosign. Verify with:

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

mcp-data-platform-v0.32.0

06 Mar 00:32
ac43a42

Choose a tag to compare

Highlights

v0.32.0 is a major feature release that adds a unified web portal with SSO login, an asset management system for AI-generated artifacts, and upstream tool consolidation that reduces the platform's tool count by 7.

Unified Portal with OIDC Browser Login (#179)

The two separate admin and portal SPAs have been merged into a single React application served at /portal/. Users can now sign in via SSO (OIDC Authorization Code Flow with PKCE) instead of manually pasting API keys.

  • Cookie-based sessions — HMAC-SHA256 signed JWT cookies (stateless, configurable TTL)
  • Dual-mode auth — SSO login (primary) with API key fallback for service accounts
  • Role-gated navigation — Everyone sees asset management; admins also see Dashboard, Tools, Audit, Knowledge, and Personas
  • id_token validation — iss, aud, and exp claims verified per OIDC Core §3.1.3.7
  • Secure logoutid_token_hint sent to the OIDC provider for proper single logout
  • Friendly error UX — OIDC callback errors redirect to the portal with human-readable messages instead of raw HTTP errors
  • Browser redirectAccept: text/html requests to / auto-redirect to /portal/
auth:
  oidc:
    enabled: true
    issuer: "https://auth.example.com/realms/platform"
    client_id: "mcp-data-platform"
    client_secret: "${OIDC_CLIENT_SECRET}"
    scopes: ["openid", "profile", "email"]
  browser_session:
    enabled: true
    signing_key: "${SESSION_SIGNING_KEY}"
    ttl: 8h
    secure: true

Asset Portal — Backend (#174) & Web Layer (#175)

A full artifact management system for AI-generated content (dashboards, reports, charts, code). Artifacts that previously vanished when conversations ended are now persisted with provenance tracking.

  • MCP toolssave_artifact and manage_artifact for AI agents to persist and manage content
  • Provenance tracking — Middleware records which tool calls produced each artifact, creating an audit trail
  • 10 REST endpoints — CRUD for assets and shares, owner enforcement, paginated listing
  • Public sharing — 256-bit random token URLs with configurable TTL, per-IP rate limiting, immediate revocation
  • Secure rendering — JSX/HTML in sandboxed iframes (no allow-same-origin), SVG sanitized via DOMPurify, Markdown via react-markdown
  • PostgreSQL + S3 storage — Metadata in PostgreSQL (with soft-delete), content in S3

Tool Consolidation (#177)

Upstream library upgrades reduce the platform's tool count by 7, simplifying the tool namespace for AI agents:

Before After
trino_list_catalogs, trino_list_schemas, trino_list_tables trino_browse
datahub_list_tags, datahub_list_domains, datahub_list_data_products datahub_browse
datahub_get_column_lineage Merged into datahub_get_lineage with level=column
  • mcp-trino v1.0.0 → v1.1.0
  • mcp-datahub v1.0.3 → v1.1.1

Note: Wildcard persona filters like trino_* still work, but *_list_* patterns will no longer match the new browse tools. Update persona configs accordingly.

Documentation & Branding (#176)

  • SVG logo banners (light/dark) matching sister projects
  • Ecosystem page describing the composable MCP server suite
  • All docs URLs migrated to mcp-data-platform.txn2.com
  • 7 missing DataHub write tools added to documentation
  • Stale tool names replaced across all doc files

Breaking Changes

  • Removed tools: trino_list_catalogs, trino_list_schemas, trino_list_tables, datahub_list_tags, datahub_list_domains, datahub_list_data_products, datahub_get_column_lineage — replaced by trino_browse, datahub_browse, and datahub_get_lineage level=column
  • Removed paths: /admin/ is no longer served. The unified portal is at /portal/
  • Persona configs: *_list_* filter patterns no longer match browse tools — update to explicit names or *_browse

CI Updates

  • anchore/sbom-action 0.22.2 → 0.23.0 (#166)
  • actions/upload-artifact 6.0.0 → 7.0.0 (#168)
  • actions/setup-go 6.2.0 → 6.3.0 (#167)

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.32.0

Verification

All release artifacts are signed with Cosign. Verify with:

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

mcp-data-platform-v0.31.0

02 Mar 02:20
b14636f

Choose a tag to compare

Session Initialization Gate

LLM agents frequently skip the platform_info tool and jump directly to data tools like datahub_search or trino_query, causing them to miss critical operational instructions embedded in the platform info response (query routing rules, persona context, enrichment capabilities). This release adds both soft and hard enforcement to ensure platform_info is always the first call in every session.

Soft enforcement: Strengthened tool description

The platform_info tool description now leads with "MANDATORY first call in every session", explicitly names the tools that must not precede it (datahub_search, trino_query, trino_describe_table, s3_list_objects), and states the consequences of skipping: incorrect query routing, operational rule violations, and degraded output quality.

Hard enforcement: Session gating middleware

A new MCPSessionGateMiddleware blocks all non-exempt tool calls with a SETUP_REQUIRED error until platform_info has been invoked in the current session. Most agents will self-correct by calling platform_info and retrying.

Key behaviors:

  • Returns a structured SETUP_REQUIRED error that tells the agent exactly what to do
  • Configurable exempt tools list (e.g., list_connections, read_resource)
  • Per-session tracking with TTL-based expiration to prevent memory leaks
  • Gating violations are logged with session ID, tool name, user ID, and cumulative count
  • New tools added to the platform are automatically gated — no per-tool code changes

Middleware chain positioning:

Auth/Authz → Session Gate → Audit → Rules → Enrichment → handler

The gate sits inner to auth (so it has session/user context) and outer to audit (so gated calls don't produce audit events).

Configuration

Enable via session_gate in your platform config:

session_gate:
  enabled: true
  init_tool: platform_info        # default
  exempt_tools:
    - list_connections
    - read_resource

When disabled (the default), the platform behaves exactly as before — the description change is the only active enforcement.

Upgrade notes

  • No breaking changes. Session gating is disabled by default.
  • To enable, add session_gate.enabled: true to your config.
  • The platform_info description change takes effect immediately and requires no configuration.

Changelog

  • feat: enforce platform_info as mandatory first call via session gating middleware (#164) (#165)

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.31.0

Verification

All release artifacts are signed with Cosign. Verify with:

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