UI9000 helps you generate and display interactive charts through the Model Context Protocol (MCP). An LLM (or your app) sends a chart spec + data to the UI9000 MCP, which returns a UIResource containing a secure iframe URL. You render that iframe in your app using the UI9000 Client while the chart is drawn by Charts UI (Renderer).
Pro Tip: Lorem ipsum dolor sit amet, consectetur adipiscing elit tempus habitant a amet aliquet semper mauris risus pulvinar eget ipsum in rhoncus vestibulum orci bibendum viverra lorem cursus mi id nulla volutpat tortor turpis fusce donec et.
id, and issues signed render links (dataUrl).dataUrl and renders charts.UIResource in your app using a sandboxed iframe.Lorem ipsum dolor sit amet consectetur adipiscing elit adipiscing nec tristique vitae purus eleifend faucibus nunc quis lorem nec tellus ultrices at sed molestie nunc.
ui9000.chart.create) with chart spec + data.dataUrl for Charts UI.uri.Lorem ipsum dolor sit amet consectetur adipiscing elit adipiscing nec tristique vitae purus eleifend faucibus nunc quis lorem nec tellus ultrices at sed molestie nunc.
Lorem ipsum dolor sit amet consectetur adipiscing elit adipiscing nec tristique vitae purus eleifend faucibus nunc quis lorem nec tellus ultrices at sed molestie nunc.
Use the UI9000 Playground to try the system without installing anything. You’ll chat with a preconfigured environment backed by the cloud‑hosted UI9000 MCP, preview generated charts, and optionally attach your own MCP servers.
Pro Tip: Lorem ipsum dolor sit amet, consectetur adipiscing elit tempus habitant a amet aliquet semper mauris risus pulvinar eget ipsum in rhoncus vestibulum orci bibendum viverra lorem cursus mi id nulla volutpat tortor turpis fusce donec et.
Lorem ipsum dolor sit amet consectetur adipiscing elit adipiscing nec tristique vitae purus eleifend faucibus nunc quis lorem nec tellus ultrices at sed molestie nunc.
Visit: https://playground.ui9000.com/
?dataUrl=... pointing back to an MCP data-links/<id> endpoint.Lorem ipsum dolor sit amet consectetur adipiscing elit adipiscing nec tristique vitae purus eleifend faucibus nunc quis lorem nec tellus ultrices at sed molestie nunc.
MAPBOX_TOKEN when using map layers (self‑hosted renderer).Lorem ipsum dolor sit amet consectetur adipiscing elit adipiscing nec tristique vitae purus eleifend faucibus nunc quis lorem nec tellus ultrices at sed molestie nunc.
Lorem ipsum dolor sit amet consectetur adipiscing elit adipiscing nec tristique vitae purus eleifend faucibus nunc quis lorem nec tellus ultrices at sed molestie nunc.
Use the cloud‑hosted UI9000 MCP if you don’t want to manage infrastructure. You connect via SSE and call UI9000 tools; rendering happens in the hosted environment.
Pro Tip: Lorem ipsum dolor sit amet, consectetur adipiscing elit tempus habitant a amet aliquet semper mauris risus pulvinar eget ipsum in rhoncus vestibulum orci bibendum viverra lorem cursus mi id nulla volutpat tortor turpis fusce donec et.
Lorem ipsum dolor sit amet consectetur adipiscing elit adipiscing nec tristique vitae purus eleifend faucibus nunc quis lorem nec tellus ultrices at sed molestie nunc.
Add this to your host’s MCP configuration:
{
"mcpServers": {
"ui9000": {
"transport": "sse",
"url": "https://mcp.ui9000.com/see"
}
}
}
Base URL: https://mcp.ui9000.com/
From your LLM/host, invoke ui9000.chart.create with a chart spec and dataset. The MCP will return a UIResource containing an iframe uri.
Install the UI client and mount the returned resource:
pnpm add @fuselabcreative/ui9000-client
import { UIResourceRenderer } from '@fuselabcreative/ui9000-client';
export function ChartPane({ mcpResource }) {
if (mcpResource?.type === 'resource' && mcpResource.resource?.uri?.startsWith('ui://')) {
return <UIResourceRenderer resource={mcpResource.resource} />; }
return <p>No chart.</p>;
}
data-links/<id> endpoint when the iframe loads.Lorem ipsum dolor sit amet consectetur adipiscing elit adipiscing nec tristique vitae purus eleifend faucibus nunc quis lorem nec tellus ultrices at sed molestie nunc.
Lorem ipsum dolor sit amet consectetur adipiscing elit adipiscing nec tristique vitae purus eleifend faucibus nunc quis lorem nec tellus ultrices at sed molestie nunc.
Lorem ipsum dolor sit amet consectetur adipiscing elit adipiscing nec tristique vitae purus eleifend faucibus nunc quis lorem nec tellus ultrices at sed molestie nunc.
Self‑hosting gives you full control over security, performance, data persistence, and custom domains. You’ll run Charts UI (Renderer) and optionally UI9000 MCP on your own infrastructure, then render charts with the UI9000 Client.
Pro Tip: Lorem ipsum dolor sit amet, consectetur adipiscing elit tempus habitant a amet aliquet semper mauris risus pulvinar eget ipsum in rhoncus vestibulum orci bibendum viverra lorem cursus mi id nulla volutpat tortor turpis fusce donec et.
dataUrl pointing to MCP Data API.dataUrl tokens (HMAC) with TTL and issuer data.Lorem ipsum dolor sit amet consectetur adipiscing elit adipiscing nec tristique vitae purus eleifend faucibus nunc quis lorem nec tellus ultrices at sed molestie nunc.
Lorem ipsum dolor sit amet consectetur adipiscing elit adipiscing nec tristique vitae purus eleifend faucibus nunc quis lorem nec tellus ultrices at sed molestie nunc.
Run the official Docker image:
docker run -d \
--name ui9000-charts \
-p 8080:80 \
-e MAPBOX_TOKEN="pk.eyJ1Ijoi..." \
-e MAX_PAYLOAD_MB="10" \
-e CORS_ALLOWED_ORIGINS="https://your-app.com,https://admin.your-app.com" \
-e SIGNING_SECRET="change-me-long-random" \
ui9000/charts:latest
MAPBOX_TOKEN
required if you use map layers.
MAX_PAYLOAD_MB
upper bound for inline payload size accepted by the renderer.
CORS_ALLOWED_ORIGINS
comma‑separated allowlist of origins permitted to embed the iframe.
SIGNING_SECRET
HMAC secret to validate signed dataUrl tokens (prevents tampering, enables TTL).
Content-Security-Policy: frame-ancestors https://your-app.com and X-Frame-Options: DENY or SAMEORIGIN as appropriate for your embedding model).CORS_ALLOWED_ORIGINS to exact origins; avoid wildcards.Clone and configure the MCP server:
git clone git@github.com:fuselab-creative/ui9000-mcp.git
cd ui9000-mcp
pnpm i
export CHARTS_BASE_URL="https://charts.your-domain.com" # public Charts UI URL
export STORAGE_DIR=".data" # or a mounted volume/path
export PORT=7331
pnpm start
Notes
CHARTS_BASE_URL must be reachable by end‑users’ browsers.STORAGE_DIR in containers/VMs.systemd or a process manager (PM2) for uptime.For a containerized MCP, define a simple service:
# ui9000-mcp/Dockerfile# ui9000-mcp/Dockerfile
FROM node:20-alpine
WORKDIR /app
COPY . .
RUN corepack enable && corepack prepare pnpm@latest --activate && pnpm i --frozen-lockfileE
ENV PORT=7331 STORAGE_DIR=/data
CHARTS_BASE_URL=https://charts.your-domain.com
VOLUME ["/data"]
EXPOSE 7331
CMD ["pnpm", "start"]
Run it alongside Charts UI:
docker network create ui9000-net || true
docker run -d --name ui9000-charts --network ui9000-net \
-p 8080:80 -e SIGNING_SECRET=change-me ui9000/charts:latest
docker build -t yourorg/ui9000-mcp:latest
docker run -d --name ui9000-mcp --network ui9000-net \
-p 7331:7331 -e CHARTS_BASE_URL="http://ui9000-charts" \
-e STORAGE_DIR="/data" -v $(pwd)/.data:/data yourorg/ui9000-mcp:latest
ui9000.chart.create with the sample payload below.uri.dataUrl and render the chart.{
"name": "Demo Map Chart",
"layers": [
{
"geospatialData": ["Country"],
"arrangeByMetric": ["Population"],
"data": [
{ "Country": "United States", "Population": "331000000" },
{ "Country": "Brazil", "Population": "213000000" },
{ "Country": "India", "Population": "1393000000" }
],
"visualisationType": "choropleth",
"aggregationFunction": "sum",
"legend": true,
"tooltip": true
}
]
}
Install and use the UI client:
pnpm add @fuselabcreative/ui9000-client
import { UIResourceRenderer } from '@fuselabcreative/ui9000-client';
export function ChartPane({ mcpResource }) {
if (mcpResource?.type === 'resource' && mcpResource.resource?.uri?.startsWith('ui://')) {
return (
<UIResourceRenderer
resource={mcpResource.resource}
onUIAction={(e) => console.log('UI action', e)}
/>
);
}
return <p>No chart.</p>;
}
CORS_ALLOWED_ORIGINS includes the exact origin where the iframe is embedded.SIGNING_SECRET carefully and confirm system clocks; regenerate links if they expire.MAPBOX_TOKEN and network access to Mapbox endpoints.STORAGE_DIR in production.frame-ancestors CSP; avoid wildcard *.dataUrl links with reasonable TTLMAX_PAYLOAD_MB to your needs.