urano-charts
Officialby uranotools
README.md
<div align="center">
# Urano Charts — Gráficas avanzadas OSS
[](https://github.com/uranotools/UranoDesktop)
[](https://github.com/uranotools/UranoDesktop)
[](https://github.com/uranotools/UranoDesktop)
[](./LICENSE)
**Widgets JsonLive propios (uPlot + ECharts) para series temporales con zoom/pan, box plots y coordenadas paralelas — gratis, open-source, sin API keys ni CDN.**
*Complementa el `Chart` nativo del host; no lo reemplaza.*
</div>
---
## 1. Descripción humana
### Para quién es
Quien necesita gráficas que el widget nativo `Chart` no cubre bien (zoom fluido, cuartiles, exploración multivariada) y quiere instalarlas como MCP plug-and-play en UranoDesktop / Cloud.
### Qué problema resuelve
- El host ya pinta bar/line/pie/heatmap/sankey/etc. con `Chart`.
- Faltan tipos “avanzados” sin tocar `UranoFront` ni `COMPONENT_MAP`.
- No quieres depender de SaaS, keys ni scripts remotos: todo va en el ZIP del pack.
### Casos de uso
| Situación | Qué hace el agente |
|-----------|-------------------|
| Serie temporal larga con zoom | `build_timeseries_uispec` → `charts.TimeSeries` (uPlot) |
| Comparar distribuciones | `build_boxplot_uispec` → `charts.BoxPlot` |
| Perfiles multivariados | `build_parallel_uispec` → `charts.Parallel` |
| Smoke test post-install | `demo_uispec` → `urano_render_json` |
| Bar / line / pie / heatmap… | Widget **nativo** `Chart` (no este pack) |
### Capacidades
| Área | Capacidad |
|------|-----------|
| TimeSeries | uPlot — zoom/pan, multi-serie |
| BoxPlot | ECharts — cuartiles + outliers (muestras raw) |
| Parallel | ECharts — coordenadas paralelas |
| Tools | Builders de uiSpec + catálogo + demo |
| Coste | MIT + deps OSS; **cero** Vault / API keys / fetch remoto |
| UI | Types namespaced `charts.*` vía `ui/widgets.js` |
### Instalación en Urano
**Dev Mode:** MCP Manager → Desarrollador → Vincular Carpeta → selecciona `urano-charts/`. Luego `npm run deploy` (o al menos `build:ui`).
**ZIP:** `npm install` → `npm run deploy` → `npm run urano-launch` → Instalar MCP (`.zip`).
No hay settings de secrets: al instalar, ya está listo.
### Flujo demo (humano)
1. Instala / Dev Link el pack y Forzar Recarga skills (o reinicia Desktop).
2. En el chat: *“Corre demo_uispec de urano-charts y renderiza el uiSpec.”*
3. Deberías ver TimeSeries + BoxPlot + Parallel (no `UNKNOWN_TYPE`).
4. Para datos reales: builder correspondiente → `urano_render_json` (`waitForAction: false`).
### Flujo típico (builder → render)
```mermaid
flowchart LR
A[list_chart_types] --> B{Tipo}
B -->|nativo| C[Chart / Dashboard host]
B -->|pack| D[build_*_uispec]
D --> E[uiSpec charts.*]
E --> F[urano_render_json]
F --> G[Host carga ui/widgets.js]
G --> H[TimeSeries / BoxPlot / Parallel]
```
### Avisos importantes
- **No** overridees `type: "Chart"` / `Dashboard` con este pack.
- Si el lint dice `UNKNOWN_TYPE`, el catálogo no sincronizó: `npm run deploy` + reload skills (ver `SKILL.md`).
- Preferir Chart nativo para tipos ya soportados.
---
## 2. Descripción técnica
### Arquitectura
- MCP nativo: `mcpServer.command: 'native'`.
- Sin Engine Plugin (v1).
- `inDesktop: true`, `inCloud: true` (UI pura, sin FS local obligatorio).
- Widgets React empaquetados en IIFE; React viene del host (`window.__URANO_JSONLIVE__`).
- Deps UI: **uPlot** (MIT), **Apache ECharts** (Apache-2.0) — bundladas en el IIFE.
### Estructura (de dónde sale cada archivo)
```text
urano-charts/
├── config.ts # manifiesto + jsonLiveWidgets + pluginSchemas (tú lo escribes)
├── SKILL.md # protocolo del agente (tú lo escribes)
├── README.md / LICENSE
├── package.json # scripts build:ui / deploy / urano-launch
├── scripts/
│ └── build-ui.js # esbuild IIFE → genera widgets.js (tú lo copias/adaptas)
├── ui/
│ ├── src/
│ │ ├── index.ts # exporta TimeSeries, BoxPlot, Parallel (tú)
│ │ ├── TimeSeries.tsx # componente React (tú)
│ │ ├── BoxPlot.tsx
│ │ └── Parallel.tsx
│ ├── shims/
│ │ ├── react.ts # bridge a React del host (tú / molde climate)
│ │ └── jsx-runtime.ts
│ └── widgets.js # ★ GENERADO — no editar a mano
├── Plugins/
│ └── Charts/ChartsPlugin.ts # tools build_*_uispec (tú)
├── config.js # ★ GENERADO (copia de dist/config.js en deploy)
└── dist/ # ★ GENERADO — contenido del ZIP
├── config.js
├── Plugins/Charts/ChartsPlugin.js
└── ui/widgets.js
```
### Tools MCP (Charts)
| Tool | Rol |
|------|-----|
| `list_chart_types` | Nativo vs pack; licencias; sin keys |
| `build_timeseries_uispec` | Valida labels/series → uiSpec `charts.TimeSeries` |
| `build_boxplot_uispec` | categories + values raw → `charts.BoxPlot` |
| `build_parallel_uispec` | dimensions + rows → `charts.Parallel` |
| `demo_uispec` | Smoke test (`which`: all \| timeseries \| boxplot \| parallel) |
Flujo: **builder → `urano_render_json`** (`purpose` + `uiSpec`, `waitForAction: false`).
### Widgets JsonLive
| Type | Export | Props clave |
|------|--------|-------------|
| `charts.TimeSeries` | `TimeSeries` | `labels[]`, `series: number[][]`, `seriesNames?`, `height?` |
| `charts.BoxPlot` | `BoxPlot` | `categories[]`, `values: number[][]` (raw), `height?` |
| `charts.Parallel` | `Parallel` | `dimensions[{name,min?,max?}]`, `rows: number[][]`, `height?` |
Declarados en `config.ts` → `jsonLiveWidgets[]` (type, bundle, exportName, aliases, propsHint).
### Parámetros STRING JSON
```json
{
"title": "Temperatura",
"labelsJson": "[\"Lun\",\"Mar\",\"Mié\"]",
"seriesJson": "[[18,20,19],[10,12,11]]",
"seriesNamesJson": "[\"Max\",\"Min\"]",
"height": "320"
}
```
### Build
```bash
npm install
npm run build:ui # solo IIFE → dist/ui/widgets.js + copia a ui/widgets.js
npm run deploy # build:ui + esbuild backend + copia config.js a raíz
npm run urano-launch # ZIP desde dist/
```
Dev Mode: linkea la carpeta + `npm run build:ui:watch` (hot reload UI).
### Anti-contexto
- No pedir API keys.
- No inventar types `charts.*` fuera de los tres registrados.
- Arrays a tools como **STRING JSON**.
- Skill-First: protocolo en `SKILL.md`.
### Referencia de patrón
- Pack molde widgets: `urano-climate` (`DemoBadge`) y este pack.
- Docs host: `UranoDesktop/docs/CREATE_MCP_GUIDE.md` §8 · `RENDER_GUIDE.md` · `DEV_MODE.md` (`HOT_RELOAD_UI`).
---
## 3. Cómo crear un plugin de widgets JsonLive (solo lo específico)
Esto es **lo que cambia** respecto a un MCP normal (tools + `SKILL.md`). El resto (config, Plugins, deploy backend) es igual.
### 1. Fuentes que escribes tú
| Archivo | Rol |
|---------|-----|
| `ui/src/MiWidget.tsx` | Componente React. Contrato: `({ props, children, tabId }) => …` |
| `ui/src/index.ts` | `export { MiWidget } from './MiWidget'` |
| `ui/shims/react.ts` | Lee `window.__URANO_JSONLIVE__.React` (sin segunda copia de React) |
| `ui/shims/jsx-runtime.ts` | Lee `jsx` / `jsxs` del host |
| `scripts/build-ui.js` | esbuild: entry `ui/src/index.ts` → IIFE |
| `config.ts` → `jsonLiveWidgets` | Declara `type`, `bundle: 'ui/widgets.js'`, `exportName` |
| `SKILL.md` | Ejemplos `urano_render_json` con tu `type` |
### 2. De dónde sale `widgets.js` (no se escribe a mano)
```text
ui/src/*.tsx + shims + npm deps (uplot, echarts, …)
│
▼ npm run build:ui (scripts/build-ui.js → esbuild)
│
├─► dist/ui/widgets.js (artefacto para ZIP)
└─► ui/widgets.js (copia para Dev Link / catálogo)
```
El script:
1. Empaqueta todo en un **IIFE** browser (`format: 'iife'`).
2. Pone el global `__UranoMcpWidgetExports` con tus exports (`TimeSeries`, …).
3. Alias `react` / `react/jsx-runtime` → shims del host.
4. Añade un **footer** que llama `window.__URANO_JSONLIVE__.acceptBundle(...)`.
5. Escribe `dist/ui/widgets.js` y copia a `ui/widgets.js`.
Si editas solo el `.tsx` y no corres `build:ui`, el host sigue sirviendo el IIFE viejo.
### 3. Cómo el host lo usa
1. Al cargar skills, Desktop lee `config.jsonLiveWidgets` y registra los types (lint deja de marcar `UNKNOWN_TYPE`).
2. `urano_render_json` con `type: "charts.TimeSeries"` → Front pide el catálogo → carga `urano-mcp-ui://urano-charts/ui/widgets.js` (o HTTP en Cloud).
3. El IIFE se ejecuta, `acceptBundle` registra el componente, JsonLive lo pinta.
### 4. Reglas duras del bundle
- Prohibido: `electron`, `fs`, Node APIs, segunda copia de React, fetch a orígenes no controlados.
- Types **namespaced** (`mymodule.MiWidget`). No puedes overridear `Chart` / `Dashboard`.
- ZIP: `deploy` debe dejar `dist/ui/widgets.js`; `urano-launch` lo empaqueta como `ui/widgets.js` en el zip.
### 5. Checklist mínimo
1. Scaffold MCP normal (`config.ts`, `Plugins/…`, `SKILL.md`).
2. Añadir `ui/` + shims + `scripts/build-ui.js`.
3. Declarar `jsonLiveWidgets`.
4. `npm run build:ui` → verificar que existen `ui/widgets.js` y `dist/ui/widgets.js`.
5. Dev Link o ZIP → `demo` / `urano_render_json` con tu type.
---
## 4. Créditos
| | |
|--|--|
| **Pack** | urano-charts |
| **Licencia** | MIT — ver [LICENSE](./LICENSE) |
| **Deps UI** | [uPlot](https://github.com/leeoniya/uPlot) (MIT) · [Apache ECharts](https://echarts.apache.org/) (Apache-2.0) |
| **Runtime** | UranoDesktop / Cloud · MCP nativo + JsonLive widgets |
| **Molde** | `urano-climate` (`ui/` + `build-ui.js`) |
Hecho para demostrar gráficas avanzadas **locales, gratis y sin keys**, como extensión del render JsonLive.
This server cannot be deployed
Maintenance
ActivitySlowing
ResponsivenessNo issues