semiotic

MCP serverMedia

Semiotic lets your AI create charts as React components and verify they are correct before you use them. Each chart is checked for problems, repaired if something is off, and can be inspected to see how it was built. The result is charts that render as intended.

Use semiotic in Claude, ChatGPT or Ahel Desktop

Free. Sign in, add semiotic and connect your AI. About a minute.

Also: Claude Code · Cursor · Codex

Then ask your AI: use the createChart tool from semiotic

Details

Available today. Use it from your connected AI after setup.

After adding semiotic, share the data you want charted and ask your AI to build a chart. It will pick a chart type, verify it, and hand back the finished React chart.

semioticStart free

What your AI can do with it

  • Choose the chart type that fits your data
  • Create charts as React components
  • Check charts for errors before they are used
  • Repair charts that fail the checks
  • Render finished charts
  • Inspect a chart's structure and settings

Install semiotic

The server’s own address, for the clients that take one directly. Or connect Ahel once and every client you use reads it from one address, with the account kept on Ahel rather than in each client’s config.

  • Claude Code

    claude mcp add --transport http --scope user semiotic 'https://semiotic-mcp-server-481507046413.us-west1.run.app/mcp'

    Run it once in your project, then open /mcp to approve any sign-in the server asks for.

  • Claude Desktop

    https://semiotic-mcp-server-481507046413.us-west1.run.app/mcp

    Add a custom connector in Settings, paste this address, and approve the sign-in.

  • Cursor

    cursor://anysphere.cursor-deeplink/mcp/install?name=semiotic&config=eyJ1cmwiOiJodHRwczovL3NlbWlvdGljLW1jcC1zZXJ2ZXItNDgxNTA3MDQ2NDEzLnVzLXdlc3QxLnJ1bi5hcHAvbWNwIn0=

    Open the link and Cursor adds the server at that address.

  • ChatGPT

    https://semiotic-mcp-server-481507046413.us-west1.run.app/mcp

    In Settings, enable Developer mode, create an MCP app, and paste this address. Your plan and workspace must allow custom apps.

  • Codex

    codex mcp add semiotic --url 'https://semiotic-mcp-server-481507046413.us-west1.run.app/mcp'

    Run it once, then sign in with codex mcp login semiotic if the server asks for an account.

From the project's README

As published by nteract/semiotic in README.md.

A React data visualization library designed for AI-assisted development and streaming data.

Start with a small chart component. Add network graphs, streaming data and coordinated views when the task needs them. Structured schemas, diagnostics and rendering evidence help coding assistants implement, check and repair chart configurations.

Work through a complete task: check category totals, maintain a live chart, or correct a published chart. The source task packets identify their build and evidence scope; source availability does not establish installed or deployed parity.

What's New in 3.12.1

3.12.1 extends network perspectives to the Atlas readers and improves projected layout sizing, annotation anchors, and static SVG precision. Placement components retain their identity across package entries, and semioticVite() removes unused worker assets from Vite 7 builds while preserving workers that are used.

See the changelog for the full list and SVG compatibility notes.

Why Semiotic

Semiotic is a data visualization library for React that combines broad chart coverage with AI tooling. It supports network graphs, streaming data, statistical distributions and coordinated views, with schemas, examples and diagnostics for implementing and checking each task. Check the project's existing dependencies first: extending its current charting library may be the best fit for a small change.

Built for AI-assisted development

Semiotic provides a workflow for generating, checking and repairing chart configurations. The July 27, 2026 evaluation reports model- and task-specific results; it does not guarantee first-try correctness.

  • semiotic/ai — a single import with the schema-backed chart capability catalog (XY, ordinal, network, realtime, geo, value, and portable recipes), optimized for LLM code generation. See ai/surface-manifest.json for the generated current inventory. Named imports now tree-shake across published chunks. Prefer family subpaths (semiotic/xy, semiotic/geo, semiotic/value, …) in production code to keep the intended chart family explicit; the cold-consumer table below reports initial-load and on-demand costs.
  • ai/schema.json — machine-readable prop schemas for every component
  • npx -y -p semiotic semiotic-mcp — an MCP server for tool-based chart rendering in any MCP client
  • npx -p semiotic semiotic-ai --doctor — validate component + props JSON from the command line with typo suggestions and anti-pattern detection
  • diagnoseConfig(component, props) — programmatic anti-pattern detector with actionable fixes, spanning validation, encoding, accessibility, and misleading-design (deception) checks
  • auditData(component, props, data?) — chart-aware numeric preflight for inputs that pass schema validation but break the math: non-finite values, zero-span domains, invalid log inputs, negative size geometry, unsafe normalized totals, and scale-dominating outliers. Returns bounded row evidence and flows into diagnoseConfig, Chart Clinic, CLI doctor, and opt-in ChartContainer notifications
  • AGENTS.md — concise repository workflow shared by modern coding agents; CLAUDE.md imports it and Copilot receives a short compatibility bridge
  • ai/reference.md — complete on-demand product reference, kept out of always-loaded coding-agent context
  • llms.txt — machine-readable documentation following the emerging standard

Every chart includes a built-in error boundary, dev-mode validation warnings with typo suggestions, and accessibility features (canvas aria-label, keyboard-navigable legends, keyboard live-region announcements, SVG <title>/<desc>) so AI-generated code fails gracefully with actionable diagnostics instead of a blank screen.

Accessibility is a release surface

The European Accessibility Act has applied to covered products and services since 28 June 2025. A chart library cannot certify an application's legal compliance: scope, content, surrounding controls, testing, and national enforcement remain the application owner's responsibility. Semiotic supplies testable infrastructure for that work: keyboard interaction, accessible data tables, layered descriptions, structured navigation, reduced-motion and forced-colors paths, and WCAG-derived contrast tests for shipped theme presets. See the Accessibility docs and run the application's own assistive-technology and user testing.

Beyond standard charts

Network visualization. Force-directed graphs, Sankey diagrams, chord diagrams, tree layouts, treemaps, circle packing, and orbit diagrams — all as React components with the same prop API as LineChart.

Streaming data. Realtime charts render on canvas at 60fps with a ref-based push API. Rapid network edge pushes coalesce into one layout per animation frame, while read/mutation methods preserve synchronous read-after-write semantics. Built-in decay, pulse, and staleness encoding for monitoring dashboards.

Coordinated views. LinkedCharts provides hover cross-highlighting, brush cross-filtering, coordinate-based linked crosshairs, and selection synchronization across any combination of chart types through shared selection state.

Geographic visualization. Choropleth maps, proportional symbol maps, flow maps with animated particles, and distance cartograms — all canvas-rendered with d3-geo projections, zoom/pan, tile basemaps, and drag-rotate globe spinning.

Statistical summaries. Box plots, violin plots, swarm plots, histograms, LOESS smoothing, forecast with confidence envelopes, and anomaly detection. Marginal distribution graphics on scatterplot axes with a single prop.

First-class annotations. Annotations are data-bound objects, not post-hoc artwork. Labels, callouts, thresholds, enclosures, statistical overlays, and React widgets move with the chart and render through browser, SSR, and export paths. Opt into placement, hierarchy, density, progressive disclosure, audience-aware amount, provenance, and editorial lifecycle when the chart needs to communicate more than its encoding alone.

Choose the API layer

LayerForExample
ChartsCommon chart forms with chart-level props<LineChart data={d} xAccessor="x" yAccessor="y" />
FramesFull control over rendering, interaction, and layout<StreamXYFrame chartType="line" lineStyle={...} />

Chart HOCs register only the mark plugins they need. Direct StreamXYFrame loads the remaining built-ins on first client paint. Call registerBuiltInXYPlugins() from semiotic/xy or semiotic/realtime/core before the first render when SSR or the first frame must include marks.

Every Chart component accepts a frameProps prop to access the underlying Frame API without leaving the simpler interface.

Serialization and interop

Charts serialize to JSON and back: toConfig, fromConfig, toURL, copyConfig, configToJSX. Have Vega-Lite specs? fromVegaLite(spec) translates them to Semiotic configs — works with configToJSX() for full round-trip from notebooks and AI-generated specs.

Need an external pitfall review? The experimental unstable_toDataPitfallsChain() builds a dependency-free chain input for datapitfalls, combining the Semiotic config, JSX, reader grounding, diagnostics, accessibility audit, and optional rendered SVG/image evidence:

import { unstable_toDataPitfallsChain } from "semiotic/experimental"
import { detectPitfalls } from "datapitfalls"

const input = unstable_toDataPitfallsChain("LineChart", props, {
  narrative: "Monthly sales are accelerating.",
  rendered: { svg, evidence },
})

const report = await detectPitfalls(input, { apiKey: process.env.ANTHROPIC_API_KEY })

The return path stays dependency-free too. Use whole-chart findings as ChartContainer notifications, and only turn findings into annotations after your app can anchor them to marks or semantic positions:

import { ChartContainer } from "semiotic"
import { LineChart } from "semiotic/xy"
import {
  unstable_toDataPitfallsAnnotations,
  unstable_toDataPitfallsNotifications,
} from "semiotic/experimental"

const notifications = unstable_toDataPitfallsNotifications(report)
const annotations = unstable_toDataPitfallsAnnotations(report, {
  anchorFor: (finding) =>
    finding.ruleId === "truncated-axis" ? { x: 9, y: 9000 } : null,
})

<ChartContainer notifications={notifications}>
  <LineChart {...props} annotations={annotations} />
</ChartContainer>

When to use something else

Need a standard bar or line chart for a dashboard you'll never need to customize beyond colors and labels? Recharts has a larger ecosystem and more community examples. Need GPU-accelerated rendering for millions of data points? Apache ECharts handles that scale.

Semiotic is for projects that outgrow those libraries — when you need network graphs alongside time series, streaming data alongside static snapshots, or coordinated views across chart types.

Install

npm install semiotic

Requires React 18.1+ or React 19.

Quick Examples

Coordinated Dashboard

Hover one chart and highlight the same data in another through a shared selection:

import { LinkedCharts, Scatterplot, BarChart } from "semiotic"

<LinkedCharts>
  <Scatterplot
    data={data} xAccessor="age" yAccessor="income" colorBy="region"
    linkedHover={{ name: "hl", fields: ["region"] }}
    selection={{ name: "hl" }}
  />
  <BarChart
    data={summary} categoryAccessor="region" valueAccessor="total"
    selection={{ name: "hl" }}
  />
</LinkedCharts>

Streaming Metrics with Decay

Live data fades old points, flashes new ones, flags stale feeds:

import { RealtimeLineChart } from "semiotic"

const chartRef = useRef()
chartRef.current.push({ time: Date.now(), value: cpuLoad })

<RealtimeLineChart
  ref={chartRef}
  timeAccessor="time"
  valueAccessor="value"
  decay={{ type: "exponential", halfLife: 100 }}
  staleness={{ threshold: 5000, showBadge: true }}
/>

Network Graphs

Force-directed graphs and Sankey diagrams — same API as LineChart:

import { ForceDirectedGraph, SankeyDiagram } from "semiotic"

<ForceDirectedGraph
  nodes={people} edges={friendships}
  colorBy="team" nodeSize={8} showLabels
/>

<SankeyDiagram
  edges={budgetFlows}
  sourceAccessor="from" targetAccessor="to" valueAccessor="amount"
/>

Geographic Visualization

Choropleth maps, flow maps, and distance cartograms with canvas rendering, zoom/pan, tile basemaps, and animated particles:

import { ChoroplethMap, FlowMap, DistanceCartogram } from "semiotic/geo"

<ChoroplethMap
  areas={geoJsonFeatures} valueAccessor="gdp"
  colorScheme="viridis" projection="equalEarth" zoomable tooltip
/>

<FlowMap
  nodes={airports} flows={routes} valueAccessor="passengers"
  showParticles particleStyle={{ color: "source", speedMultiplier: 1.5 }}
/>

<DistanceCartogram
  points={cities} center="rome" costAccessor="travelDays"
  showRings costLabel="days" lines={routes}
/>

Streaming System Monitor

Live service topology with threshold alerting and click-to-inspect:

import { StreamNetworkFrame, ChartContainer, DetailsPanel, LinkedCharts } from "semiotic"

const chartRef = useRef()
chartRef.current.push({ source: "API", target: "Orders", value: 15 })

<LinkedCharts>
  <ChartContainer title="System Monitor" status="live"
    detailsPanel={
      <DetailsPanel position="right" trigger="click">
        {(datum) => <div>{datum.id}: {datum.value} req/s</div>}
      </DetailsPanel>
    }>
    <StreamNetworkFrame ref={chartRef} chartType="sankey"
      showParticles particleStyle={{ proportionalSpeed: true }}
      thresholds={{ metric: n => n.value, warning: 100, critical: 250 }}
    />
  </ChartContainer>
</LinkedCharts>

Standard Charts

Line, bar, scatter, and area charts share the same accessor-driven API:

import { LineChart, BarChart } from "semiotic"

<LineChart
  data={salesData}
  xAccessor="month" yAccessor="revenue"
  curve="monotoneX" showPoints
/>

<BarChart
  data={categoryData}
  categoryAccessor="department" valueAccessor="sales"
  orientation="horizontal" colorBy="region"
/>

All Chart Components

CategoryComponents
XYLineChart AreaChart DifferenceChart StackedAreaChart Scatterplot ConnectedScatterplot BubbleChart Heatmap QuadrantChart MultiAxisLineChart MinimapChart CandlestickChart ScatterplotMatrix
CategoricalBarChart StackedBarChart GroupedBarChart LikertChart SwimlaneChart FunnelChart SwarmPlot BoxPlot Histogram ViolinPlot RidgelinePlot DotPlot PieChart DonutChart GaugeChart
NetworkForceDirectedGraph ChordDiagram SankeyDiagram ProcessSankey TreeDiagram Treemap CirclePack OrbitDiagram
GeoChoroplethMap ProportionalSymbolMap FlowMap DistanceCartogram
RealtimeRealtimeLineChart RealtimeHistogram RealtimeSwarmChart RealtimeWaterfallChart RealtimeHeatmap
CoordinationLinkedCharts
LayoutChartGrid ContextLayout CategoryColorProvider
FramesStreamXYFrame StreamOrdinalFrame StreamNetworkFrame StreamGeoFrame

Vega-Lite Translation

Paste a Vega-Lite spec, get a Semiotic chart:

import { fromVegaLite } from "semiotic/data"
import { configToJSX, fromConfig } from "semiotic"

const config = fromVegaLite({
  mark: "bar",
  data: { values: [{ a: "A", b: 28 }, { a: "B", b: 55 }] },
  encoding: {
    x: { field: "a", type: "nominal" },
    y: { field: "b", type: "quantitative" },
  },
})

// Render directly
const { componentName, props } = fromConfig(config)
// → componentName: "BarChart", props: { data, categoryAccessor: "a", valueAccessor: "b" }

// Or generate JSX code
configToJSX(config)
// → <BarChart data={[...]} categoryAccessor="a" valueAccessor="b" />

Supports bar, line, area, point, rect, arc, tick marks with encoding translation for color, size, aggregation, and binning.

Conversation Arc Telemetry

Capture and replay the path an AI-assisted chart session took:

import {
  createLocalStorageConversationArcSink,
  enableConversationArc,
  getConversationArcStore,
  loadConversationArc,
  registerConversationArcSink,
} from "semiotic/ai"

const sink = createLocalStorageConversationArcSink({ key: "my-app:arc" })
registerConversationArcSink(sink)
enableConversationArc({ sessionId: "session-abc" })

getConversationArcStore().record({ type: "chart-rendered", component: "LineChart" })
loadConversationArc(sink.load(), { enabled: false })

Bundle Sizes

Semiotic ships 41 stable JavaScript entry points (40 subpaths plus the root). Don't import from "semiotic" unless you need everything — use the smallest sub-path that matches your charts or tooling.

Custom network layouts can opt into a virtual zoom/pan viewport through semiotic/network/zoom. It exports ZoomableNetworkCustomChart and projected-size/LOD hooks; ordinary chart imports exclude its gesture and LOD runtime.

The numbers below are first-party artifact cost: the gzip size of Semiotic's own code for each sub-path. They exclude React and other runtime dependencies, and each row counts every chunk the entry can reach, including code loaded only on demand, so they are not a prediction of a cold application bundle. Do not add artifact rows to estimate an app: dependency resolution and cross-import deduplication happen in the consumer bundler and are measured separately below.

Entry PointgzipWhat's inside
semiotic/atlas302 KBMotif Braid, Dependency Forest, and Flow Circuit readers
semiotic/atlas/core13 KBNetwork Atlas preparation, projections, and evidence queries
semiotic/access29 KBChart Access Contract factory and first-wave baseline contracts
semiotic/evidence45 KBChart Evidence Envelope, deterministic hashing, and publication gate
semiotic/artifact123 KBRenderer-independent contracts, claims, time, policy, grounding, and transfer audits
semiotic/artifact/react4 KBAccessible progressive disclosure for artifact contracts and policy evaluations
semiotic/line144 KBLineChart only — one-chart micro boundary
semiotic/xy183 KBLineChart, AreaChart, Scatterplot, Heatmap, + 8 more XY charts
semiotic/ordinal136 KBBarChart, PieChart, BoxPlot, Histogram, + 11 more categorical charts
semiotic/network178 KBForceDirectedGraph, SankeyDiagram, ProcessSankey, Treemap, + 4 more
semiotic/network/zoom183 KBOptional virtual network viewport, camera controls and consumer-owned LOD
semiotic/network/perspective2 KBIsometric pictograms and an accessible perspective toggle (the prop ships in ./network)
semiotic/network/perspective/core3 KBProjection sizing, resolution, and SVG placement helpers
semiotic/vite1 KBBuild plugin for unused Semiotic worker assets
semiotic/geo112 KBChoroplethMap, FlowMap, DistanceCartogram, ProportionalSymbolMap
semiotic/realtime211 KBRealtimeLineChart, RealtimeHistogram, + 4 streaming charts
semiotic/realtime/core209 KBStreaming chart types, HOCs, and buffer helpers
semiotic/realtime/react2 KBStream status and synced push hooks
semiotic/server264 KBrenderChart, renderDashboard, renderToImage, renderToAnimatedGif
semiotic/server/node264 KBrenderChart, renderDashboard, renderToImage, renderToAnimatedGif
semiotic/server/edge274 KBrenderChart, renderChartWithEvidence, renderToStaticSVG, renderDashboard
semiotic/utils107 KBThemeProvider, numeric/accessibility audits, serialization — no chart components
semiotic/utils/core99 KBPure theme helpers, numeric/accessibility audits, and serialization
semiotic/utils/react8 KBThemeProvider, useTheme, useReducedMotion, useHighContrast, useStreamStatus
semiotic/recipes115 KBPure layout functions (waffle, marimekko, flextree, dagre, …)
semiotic/recipes/core113 KBPure layout functions (waffle, marimekko, flextree, dagre, …)
semiotic/recipes/react2 KBGlyph and React layout-selection helpers
semiotic/themes13 KBTheme presets only (tufte, carbon, etc.)
semiotic/themes/core13 KBTheme presets and token helpers
semiotic/themes/react8 KBThemeProvider/useTheme and hooks
semiotic/data5 KBbin, rollup, groupBy, pivot, fromVegaLite
semiotic/value6 KBBigNumber — focal-value KPI / scorecard (SingleValueFrame POC)
semiotic/physics171 KBGaltonBoardChart, EventDropChart, UnitPileChart, CollisionSwarmChart, PacketFlowChart, PhysicsCustomChart
semiotic/physics/matter1 KBMatter.js migration helpers + optional peer guard (no chart components)
semiotic/physics/rapier1 KBRapier peer guard + adapter decision metadata (no chart components)
semiotic/ai642 KBAll schema-backed charts + validation — optimized for LLM code generation
semiotic/ai/core141 KBsuggestCharts, auditData, describeChart, repairChartConfig, tool adapters — no chart components
semiotic/controls18 KBDirectManipulationControl, CircularBrush, LinearBrush, MobileStandardControls, auditVisualizationControls — no frame renderer
semiotic/rough3 KBOptional deterministic Rough.js paint backend — exact Semiotic geometry remains authoritative
semiotic/text2 KBOptional Pretext annotation hook — peer package excluded
semiotic421 KBFull chart API and shared utilities

Cold-consumer named imports

The table above is first-party artifact cost, not an application bundle. The generated table below measures a different thing: a fresh consumer bundles one retained named import from a packed semiotic tarball through the public export path, with code splitting as an application build does. Initial load is what a page downloads before the chart renders; on demand is code fetched only when a feature needs it. It includes Semiotic and its resolved runtime dependencies, but externalizes React/React DOM and optional adapter peers that the host application owns. Each row starts cold, so use it to compare one public import choice—not to add together an application's rows. The checked machine-readable baseline is benchmarks/setup/cold-consumer-imports.json; refresh it after a production build with npm run docs:cold-consumer.

Method: fresh npm pack --ignore-scripts tarball → temporary consumer → minified/tree-shaken Rolldown (Vite's bundler) ESM build with code splitting and a production NODE_ENV → gzip -9 per file. Initial load counts the entry and its statically imported chunks; on demand counts chunks fetched only when a feature needs them (brushing, marginal graphics, animated transitions, a bare frame's built-in layouts). React/React DOM and optional adapter peers are external; Semiotic and its resolved runtime dependencies are included.

Shortened here. Read the whole README on GitHub.

Tools it offers (5)

What this server listed when Ahel dialed its public endpoint in Sep 2026, with no key and no account of yours. The names are the server’s own.

  • createChart
  • improveChart
  • explainChart
  • auditChart
  • getChartSchema

Signals

GitHub stars
3k
Forks
139
Last commit
Oct 2026
Weekly downloads
19k
Weekly_downloads
19k weekly_downloads
Advanced
Delivery
semiotic MCP server → your Ahel connector (mcp.ahel.ai) → your AI.
Item type
mcp-server
Key
io-github-nteract-semiotic
Source
github.com/nteract/semiotic
Hosted endpoint
https://semiotic-mcp-server-481507046413.us-west1.run.app/mcp