Skip to main content
Glama

Sparkline Cards

render_sparkline_chart
Read-onlyIdempotent

Render a grid of sparkline cards showing current values and trend lines for quick metric comparisons.

Instructions

Standalone sparkline card grid. Prefer using KPI cards with sparkline[] inside render_dashboard instead for a cleaner integrated look.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
titleYesChart title
dataYesArray of sparkline card items
themeNoTheme preset: boardroom, corporate, sales-floor, golden-treasury, clinical, startup, ops-control, tokyo-midnight, zen-garden, consultant, black-tron, black-elegance, black-matrix, forest-amber, forest-earth, sky-light, sky-ocean, sky-twilight, gray-hf, gray-copilot
paletteNoOverride palette only (mix-and-match)
typographyNoOverride typography: professional, luxury, cyberpunk, editorial, mono, bold, system, techno
effectsNoOverride effects: none, subtle, shimmer, neon, energetic

Implementation Reference

  • The main handler function for the render_sparkline_chart tool. Creates a sparkline card-based chart with SVG sparklines, color theming, click events, and export/refresh buttons.
    export function renderSparklineChart(container: HTMLElement, payload: SparklineData): void {
      const theme = resolveTheme(payload.theme, {
        palette: payload.palette,
        typography: payload.typography,
        effects: payload.effects,
      });
      if (theme) applyTheme(container, theme);
    
      const shimmer = theme?.effects.shimmerTitle ? " shimmer-text" : "";
      const colors = resolveColors(undefined, payload.data.length);
    
      const cards = payload.data.map((item, i) => {
        const color = colors[i % colors.length];
        const isGood = item.good !== undefined ? item.good : true;
        const changeClass = isGood ? "sparkline-card__change--good" : "sparkline-card__change--bad";
    
        return `
          <div class="sparkline-card" data-idx="${i}">
            <div class="sparkline-card__header">
              <span class="sparkline-card__label">${escapeHtml(item.label)}</span>
              ${item.change ? `<span class="sparkline-card__change ${changeClass}">${escapeHtml(item.change)}</span>` : ""}
            </div>
            <div class="sparkline-card__value">${escapeHtml(String(item.value))}</div>
            ${buildSparkSVG(item.sparkline, color)}
          </div>
        `;
      }).join("");
    
      container.className = "chart-view";
      container.innerHTML = `
        <div class="card chart-card">
          <div class="chart-card__header">
            <div><div class="chart-card__title${shimmer}">${escapeHtml(payload.title)}</div></div>
          </div>
          <div class="chart-card__body chart-card__body--css">
            <div class="sparkline-grid">${cards}</div>
          </div>
        </div>
      `;
    
      container.querySelectorAll<HTMLElement>(".sparkline-card").forEach((el) => {
        el.style.cursor = "pointer";
        el.addEventListener("click", () => {
          const idx = parseInt(el.dataset.idx ?? "0", 10);
          const item = payload.data[idx];
          sendClickMessage(`[Sparkline] "${payload.title}" - ${item.label}: ${item.value}`);
        });
      });
    
      const card = container.querySelector<HTMLElement>(".chart-card")!;
      addHtmlExportButton(card, payload.title);
      addRefreshButton(card, () => (window as any).__mcpRefresh?.());
    }
  • TypeScript interface SparklineData defining the input schema: type (sparkline), title, data array of SparklineItem (label, value, change, sparkline numbers, good), plus optional theme/palette/typography/effects.
    interface SparklineData {
      type: "sparkline";
      title: string;
      data: SparklineItem[];
      theme?: string;
      palette?: string;
      typography?: string;
      effects?: string;
    }
  • Registration call: registerChart('sparkline', 'render_sparkline_chart', renderSparklineChart) which enters the chart into the global registry under the tool name 'render_sparkline_chart'.
    registerChart("sparkline", "render_sparkline_chart", renderSparklineChart);
  • Helper function buildSparkSVG that generates an inline SVG from a numeric array and a color string, producing a sparkline with a line path and filled area.
    function buildSparkSVG(data: number[], color: string): string {
      if (data.length === 0) return "";
      const w = 120;
      const h = 32;
      const min = Math.min(...data);
      const max = Math.max(...data);
      const range = max - min || 1;
    
      const points = data.map((v, i) => {
        const x = (i / (data.length - 1)) * w;
        const y = h - ((v - min) / range) * (h - 4) - 2;
        return `${x},${y}`;
      });
    
      const linePath = `M${points.join(" L")}`;
      const areaPath = `${linePath} L${w},${h} L0,${h} Z`;
    
      return `
        <svg class="sparkline-card__svg" viewBox="0 0 ${w} ${h}" preserveAspectRatio="none">
          <path class="sparkline-card__area" d="${areaPath}" fill="${color}" />
          <path class="sparkline-card__path" d="${linePath}" stroke="${color}" />
        </svg>
      `;
    }
  • General renderFromData function that looks up the chart entry by type (e.g., 'sparkline') and calls its render method. This is the dispatch point that invokes renderSparklineChart.
    function renderFromData(data: any): void {
      if (!data?.type) {
        root.innerHTML = `<div class="loading">No chart data received.</div>`;
        reportSize();
        return;
      }
    
      try {
        const entry = getChartEntry(data.type);
        if (entry) {
          entry.render(root, data);
        } else {
          root.innerHTML = `<div class="loading">Unknown chart type: ${escapeHtml(String(data.type))}</div>`;
        }
        reportSize();
      } catch (err) {
        console.error("Render error:", err);
        root.innerHTML = `<div class="loading">Error rendering chart. Check console.</div>`;
        reportSize();
      }
    }
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, destructiveHint=false, idempotentHint=true, indicating a safe, read-only operation. The description adds no additional behavioral traits beyond mentioning it's standalone. With annotations present, a score of 3 is appropriate as the description doesn't contradict and provides minimal extra context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, no fluff. The first sentence states the tool's core function, and the second provides usage guidance. Every word is purposeful and front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the simple nature of a rendering tool, the combination of description, schema (100% coverage), and annotations provides sufficient context. The description could be slightly more detailed about the output format, but it is adequate for an agent to invoke correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% with all parameters described (title, data, theme, etc.). The description does not add any extra meaning beyond what's already in the schema. Baseline score of 3 is applied since the schema is comprehensive.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states what the tool does: 'Standalone sparkline card grid.' It distinguishes it from the sibling tool render_dashboard by suggesting an alternative integrated approach. The verb 'render' and specific output 'sparkline card grid' make the purpose unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit guidance provided: 'Prefer using KPI cards with sparkline[] inside render_dashboard instead for a cleaner integrated look.' This tells the agent when to avoid this tool and suggests a specific alternative, which is ideal for usage guidelines.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/KyuRish/mcp-dashboards'

If you have feedback or need assistance with the MCP directory API, please join our Discord server