Skip to content

tdfs4ds.agent.chart_render

tdfs4ds.agent.chart_render

Host-side rendering of MCP tool chart data for the consumer-agent chatbot.

The teradata-mcp-server plot_* tools return Chart.js JSON (not MCP-UI / MCP Apps resources)::

{"data": {"labels": [...], "datasets": [{"label", "data", ...}]},
 "metadata": {"tool_description", "table_name", "labels", "columns"}}

This module maps that JSON to a Plotly figure and emits a self-contained HTML document with plotly.js inlined (no CDN — works air-gapped), then wraps it in a sandboxed <iframe srcdoc> for safe embedding in Gradio.

Only the Chart.js path is handled here (generic ui:// MCP-UI resources are out of scope by design).

_TOOL_KIND module-attribute

_TOOL_KIND = {'plot_line_chart': 'line', 'plot_pie_chart': 'pie', 'plot_polar_chart': 'polar', 'plot_radar_chart': 'radar'}

_infer_kind

_infer_kind(tool_name: str, metadata: dict) -> str

Resolve the chart kind from the tool name, then from the description.

_first_color

_first_color(value)

Chart.js colors may be a string or a per-point list; take a usable scalar.

_chartjs_to_plotly_html

_chartjs_to_plotly_html(tool_name: str, spec: dict) -> Optional[dict]

Convert a Chart.js JSON spec to a self-contained Plotly HTML document.

Parameters:

Name Type Description Default
tool_name str

The MCP tool that produced spec (selects the chart kind).

required
spec dict

Chart.js JSON dict with data.labels / data.datasets.

required

Returns:

Type Description
Optional[dict]

{"title": str, "html": str} where html is a full HTML page with

Optional[dict]

plotly.js inlined, or None if spec is not Chart.js-shaped.

wrap_iframe

wrap_iframe(chart_html: str, height: int = 440) -> str

Wrap a full HTML document in a sandboxed iframe for safe embedding.

Uses sandbox="allow-scripts allow-downloads" (Plotly needs JS; the chart toolbar downloads its PNG / SVG) and deliberately omits allow-same-origin so the embedded content runs in a unique, isolated origin. The HTML is escaped for the srcdoc attribute.

charts_to_panel_html

charts_to_panel_html(charts: list) -> str

Render a list of {"title","html"} charts as stacked sandboxed iframes.