Unified React + Angular MCP tool UI (npm packages)
This skill applies to the Data360 MCP monorepo (data360-mcp): published packages that chat hosts and portals install to render tool output. It does not replace MCP Apps work (registerAppResource, HTML in an iframe, @modelcontextprotocol/ext-apps). For iframe UIs, use add-app-to-server. Here, the deliverable is @data360/mcp-ui (React) and @data360/mcp-ui-angular (Angular), sharing @data360/tool-types and @data360/mcp-viz-core.
Architecture
| Layer |
Package |
Role |
| Tool JSON contract |
@data360/tool-types |
Zod schemas, runtime parsers, versioned tool result shapes |
| Framework-agnostic UI logic |
@data360/mcp-viz-core |
prepareSpec, parseSpec, themes, shared props types (e.g. VegaChartCardBaseProps) |
| React |
@data360/mcp-ui |
Vite library; components + re-exports from viz-core |
| Angular |
@data360/mcp-ui-angular |
ng-packagr library; standalone components |
flowchart LR
toolTypes["@data360/tool-types"]
vizCore["@data360/mcp-viz-core"]
reactUi["@data360/mcp-ui"]
angularUi["@data360/mcp-ui-angular"]
toolTypes --> reactUi
toolTypes --> angularUi
vizCore --> reactUi
vizCore --> angularUi
Unification rules (non-negotiable)
- One contract — Parsers and types for MCP tool payloads live in
packages/tool-types. Bump the documented contract version when JSON shapes change.
- No duplicated pipelines — Anything that is not inherently React or Angular (spec normalization, palettes, shared prop fields) belongs in
packages/mcp-viz-core. Do not fork prepareSpec-style logic into a single framework.
- Props parity — Shared fields use types from viz-core (e.g. extend
VegaChartCardBaseProps). Framework-only extras: React ReactNode slots vs Angular TemplateRef / ng-content, same semantics.
- Same peer stack —
vega, vega-lite, vega-embed peers aligned across React and Angular packages; @data360/mcp-viz-core version aligned in both consumers.
- Docs and versions — Update README compatibility tables and bump packages together when viz behavior or contracts change.
Workflow (follow in order)
- Tool output — Read the MCP tool handler / schema. Define or update parsers and types in
packages/tool-types (schemas, parse* helpers, exports).
- Shared logic — Add or extend
packages/mcp-viz-core for any TS that both UIs need (types, prepare* / parse*, constants). Keep JSX or Angular templates out of this package.
- React — Add or change components under
packages/mcp-ui (e.g. src/<feature>/). Register a library entry in vite.config.ts if you add a new subpath; add @data360/mcp-viz-core to Rollup external and package.json dependencies. Re-export shared APIs from viz-core where useful.
- Angular — Add or change standalone components under
packages/mcp-ui-angular/src/lib/. Export from src/public-api.ts. Build with ng-packagr; publishing ships the repo package.json plus the dist/ tree (files: dist, README.md) with entry points under ./dist/... (module, typings, exports).
- Documentation — Update
packages/mcp-ui/README.md, packages/mcp-ui-angular/README.md, and components/README.md (package list / compatibility).
- Manual check — Optionally extend
packages/mcp-ui-angular-demo and use packages/mcp-ui’s Vite demo (npm run dev) to verify both surfaces.
Parity checklist (React vs Angular)
Use this when reviewing or implementing a pair of components. For the chart card reference implementation, compare packages/mcp-ui/src/viz-card/VegaChartCard.tsx with packages/mcp-ui-angular/src/lib/data360-vega-chart-card.component.ts (and template).
| Concern |
React |
Angular |
Inputs match VegaChartCardBaseProps (+ framework slot) |
Props interface extends base + railTopSlot? |
@Input() mirrors base + railTopSlot as TemplateRef |
| Legend / filter state |
parseSpec on raw spec, activeGroups |
Same |
| Embed |
prepareSpec → vega-embed, same options |
Same |
| Download / PNG / copy spec |
Same defaults and callbacks |
Same |
| Edge: no color series |
Embed still runs |
Same |
| Edge: all groups toggled off |
Skip embed when multi-series would be empty |
Same |
A printable copy lives in references/checklist.md.
Repo hygiene: strict JSON hooks
If pre-commit runs check-json, tsconfig*.json and .vscode/*.json must be strict JSON (no // or /* */ comments). The Angular CLI often generates JSONC; strip comments or exclude those paths in the hook config. The mcp-ui-angular-demo package was normalized accordingly.
Publishing (reminder)
- Build artifacts:
npm run build from monorepo root (or per workspace).
- Publish
@data360/mcp-viz-core before @data360/mcp-ui and @data360/mcp-ui-angular when viz-core changed.
- Align
dependencies / peerDependencies on @data360/mcp-viz-core with the published version.
- Use
npm publish -w @data360/<package> from root, or npm publish inside each package (Angular: tarball includes dist/ per files; prepublishOnly runs build).
Out of scope for this skill
- Codegen / Angular schematics (document manual steps first).
- Python MCP server changes (separate task unless wiring new tool names).
1---2name: data360-mcp-ui-packages3description: Use when adding or changing **host-embeddable** UI for Data360 MCP tools as npm packages: paired React (`@data360/mcp-ui`) and Angular (`@data360/mcp-ui-angular`) components with shared contracts. Triggers include: "add React and Angular component for MCP tool", "pair mcp-ui with mcp-ui-angular", "keep viz tool UI in sync", "extend tool-types for new tool", "shared prepareSpec for new chart", "dual framework MCP UI", "unify React and Angular MCP components". This skill covers the monorepo packages under `packages/` — not iframe MCP Apps. Skip when only the Python server or iframe `ext-apps` HTML is in scope (use the add-app-to-server skill for that).4---56# Unified React + Angular MCP tool UI (npm packages)78This skill applies to the **Data360 MCP monorepo** (`data360-mcp`): published packages that chat hosts and portals install to render tool output. It does **not** replace **MCP Apps** work (`registerAppResource`, HTML in an iframe, `@modelcontextprotocol/ext-apps`). For iframe UIs, use **add-app-to-server**. Here, the deliverable is **`@data360/mcp-ui`** (React) and **`@data360/mcp-ui-angular`** (Angular), sharing **`@data360/tool-types`** and **`@data360/mcp-viz-core`**.910## Architecture1112| Layer | Package | Role |13|-------|---------|------|14| Tool JSON contract | `@data360/tool-types` | Zod schemas, runtime parsers, versioned tool result shapes |15| Framework-agnostic UI logic | `@data360/mcp-viz-core` | `prepareSpec`, `parseSpec`, themes, shared props types (e.g. `VegaChartCardBaseProps`) |16| React | `@data360/mcp-ui` | Vite library; components + re-exports from viz-core |17| Angular | `@data360/mcp-ui-angular` | ng-packagr library; standalone components |1819```mermaid20flowchart LR21 toolTypes["@data360/tool-types"]22 vizCore["@data360/mcp-viz-core"]23 reactUi["@data360/mcp-ui"]24 angularUi["@data360/mcp-ui-angular"]25 toolTypes --> reactUi26 toolTypes --> angularUi27 vizCore --> reactUi28 vizCore --> angularUi29```3031## Unification rules (non-negotiable)32331. **One contract** — Parsers and types for MCP tool payloads live in `packages/tool-types`. Bump the documented contract version when JSON shapes change.342. **No duplicated pipelines** — Anything that is not inherently React or Angular (spec normalization, palettes, shared prop fields) belongs in `packages/mcp-viz-core`. Do not fork `prepareSpec`-style logic into a single framework.353. **Props parity** — Shared fields use types from viz-core (e.g. extend `VegaChartCardBaseProps`). Framework-only extras: React `ReactNode` slots vs Angular `TemplateRef` / `ng-content`, same semantics.364. **Same peer stack** — `vega`, `vega-lite`, `vega-embed` peers aligned across React and Angular packages; `@data360/mcp-viz-core` version aligned in both consumers.375. **Docs and versions** — Update README compatibility tables and bump packages together when viz behavior or contracts change.3839## Workflow (follow in order)40411. **Tool output** — Read the MCP tool handler / schema. Define or update parsers and types in `packages/tool-types` (schemas, `parse*` helpers, exports).422. **Shared logic** — Add or extend `packages/mcp-viz-core` for any TS that both UIs need (types, `prepare*` / `parse*`, constants). Keep JSX or Angular templates out of this package.433. **React** — Add or change components under `packages/mcp-ui` (e.g. `src/<feature>/`). Register a library entry in `vite.config.ts` if you add a new subpath; add `@data360/mcp-viz-core` to Rollup `external` and `package.json` dependencies. Re-export shared APIs from viz-core where useful.444. **Angular** — Add or change standalone components under `packages/mcp-ui-angular/src/lib/`. Export from `src/public-api.ts`. Build with ng-packagr; publishing ships the repo `package.json` plus the `dist/` tree (`files`: `dist`, `README.md`) with entry points under `./dist/...` (`module`, `typings`, `exports`).455. **Documentation** — Update `packages/mcp-ui/README.md`, `packages/mcp-ui-angular/README.md`, and `components/README.md` (package list / compatibility).466. **Manual check** — Optionally extend `packages/mcp-ui-angular-demo` and use `packages/mcp-ui`’s Vite demo (`npm run dev`) to verify both surfaces.4748## Parity checklist (React vs Angular)4950Use this when reviewing or implementing a pair of components. For the chart card reference implementation, compare `packages/mcp-ui/src/viz-card/VegaChartCard.tsx` with `packages/mcp-ui-angular/src/lib/data360-vega-chart-card.component.ts` (and template).5152| Concern | React | Angular |53|---------|--------|---------|54| Inputs match `VegaChartCardBaseProps` (+ framework slot) | Props interface extends base + `railTopSlot?` | `@Input()` mirrors base + `railTopSlot` as `TemplateRef` |55| Legend / filter state | `parseSpec` on raw `spec`, `activeGroups` | Same |56| Embed | `prepareSpec` → `vega-embed`, same options | Same |57| Download / PNG / copy spec | Same defaults and callbacks | Same |58| Edge: no color series | Embed still runs | Same |59| Edge: all groups toggled off | Skip embed when multi-series would be empty | Same |6061A printable copy lives in [`references/checklist.md`](references/checklist.md).6263## Repo hygiene: strict JSON hooks6465If **pre-commit** runs `check-json`, `tsconfig*.json` and `.vscode/*.json` must be **strict JSON** (no `//` or `/* */` comments). The Angular CLI often generates JSONC; strip comments or exclude those paths in the hook config. The `mcp-ui-angular-demo` package was normalized accordingly.6667## Publishing (reminder)6869- Build artifacts: `npm run build` from monorepo root (or per workspace).70- Publish **`@data360/mcp-viz-core`** before **`@data360/mcp-ui`** and **`@data360/mcp-ui-angular`** when viz-core changed.71- Align `dependencies` / `peerDependencies` on `@data360/mcp-viz-core` with the published version.72- Use `npm publish -w @data360/<package>` from root, or `npm publish` inside each package (Angular: tarball includes `dist/` per `files`; `prepublishOnly` runs `build`).7374## Out of scope for this skill7576- Codegen / Angular schematics (document manual steps first).77- Python MCP server changes (separate task unless wiring new tool names).