Commit e6d14d3
fix: chart time-axis rendering, auto-detection, and MCP ergonomic fixes (#39)
* fix(mcp): disable ANSI escape codes on stderr tracing layer
MCP servers communicate over stdio; their stderr goes to a client log
pane (e.g. Claude Code output panel) that doesn't render ANSI codes.
On Windows this produced raw escape sequences like [2m...[0m. Force
plain text on both the daemon and MCP stderr layers.
Also adds a pre-1.0 stability note to the README.
* fix(mcp): auto-create parent dirs for chart/export output paths
validate_output_path previously rejected paths whose parent directory
didn't exist. Now it creates the directory tree (create_dir_all) before
canonicalizing, so users don't need to pre-create output directories.
Also improves chart tool description to guide LLMs on:
- Long-format data requirement (one numeric y, use series for grouping)
- x_as_category=true requirement for DATE/TIMESTAMP x-axes
- UNION ALL reshaping for wide-format data
* fix(chart): auto-detect categorical x columns for line/scatter charts
Line and scatter charts now peek at the first row's x value — if it's
not numeric (DATE, TIMESTAMP, TEXT, etc.), categorical mode activates
automatically. This eliminates the need to manually set
x_as_category=true for date-based time series.
The explicit x_as_category parameter still works as an override.
* fix(chart): auto-shorten TIMESTAMPTZ labels and thin dense tick marks
Categorical axis labels now go through a shortening pass:
1. Strip shared timezone offset (+00:00) when all labels end with it
2. Auto-thin: blank intermediate labels when they'd overlap based on
estimated character width vs chart pixel width
This prevents label collision on charts with 12+ TIMESTAMPTZ ticks at
800px width. First and last labels are always preserved.
* feat(chart): proportional time axis for DATE/TIMESTAMP/TIMESTAMPTZ + fix tick thinning
Line and scatter charts now auto-detect DATE / TIMESTAMP / TIMESTAMPTZ
x columns and render with a proportional time axis: real wall-clock
gaps between data points are reflected on the chart's x-axis instead
of being flattened to even spacing. Tick labels are formatted via
chrono to match the input kind (%Y-%m-%d, %Y-%m-%d %H:%M:%S, or
%Y-%m-%d %H:%M:%S%:z), with the originating offset captured from the
first row preserved for TIMESTAMPTZ. Pass x_as_category: true to opt
out and force the previous categorical layout; TEXT x columns
continue to render categorically.
Also fixes a tick-label thinning regression in the categorical path.
The old shorten_labels blanked individual labels at non-step indices,
but plotters picks its own tick positions on the float axis and
rounds them to integer indices, so almost none of the chosen ticks
landed on a kept index - a 90-point hourly TIMESTAMP series at any
chart width rendered with only ONE visible x-axis label. The chart
layer now computes a target tick count from chart width and label
size, then passes it to plotters via .x_labels(N); every drawn tick
carries a real label.
Refactors:
- shorten_labels split into strip_shared_tz_suffix (cosmetic +HH:MM
compaction) and auto_tick_count (no-overlap budget for plotters).
- group_series x_as_category: bool -> x_mode: XMode enum (Numeric /
Categorical / Temporal(TemporalKind)).
- New parse_temporal, format_temporal_tick, detect_line_x_mode,
tick_count_for_label_width helpers.
Tests: 16 new unit tests for the helpers (parse, format, detect,
tick math, NaN safety, offset capture); 1 new integration test
(line_chart_long_timestamp_series_renders_multiple_visible_labels)
asserts >=3 visible date labels in the rendered SVG, locking in the
regression fix. Total: 26 unit, 37 integration, all green; clippy
--all-targets -D warnings clean.
Docs: chart tool description in server.rs and LLM-facing readme.rs
updated to document the new auto-detect behavior; CHANGELOG.md
[Unreleased] gains two ### Fixed entries.
* chore: re-enable release-please to release v0.2.0
* chore: fix formatting
---------
Co-authored-by: Stefan Steiner <ssteiner@salesforce.com>1 parent 7b4a1a9 commit e6d14d3
10 files changed
Lines changed: 808 additions & 105 deletions
File tree
- .github/workflows
- hyperdb-mcp
- src
- tests
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
28 | 28 | | |
29 | 29 | | |
30 | 30 | | |
31 | | - | |
32 | | - | |
33 | | - | |
| 31 | + | |
34 | 32 | | |
35 | 33 | | |
36 | 34 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
10 | 10 | | |
11 | 11 | | |
12 | 12 | | |
13 | | - | |
| 13 | + | |
14 | 14 | | |
15 | 15 | | |
16 | | - | |
17 | | - | |
| 16 | + | |
| 17 | + | |
18 | 18 | | |
19 | 19 | | |
20 | 20 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
143 | 143 | | |
144 | 144 | | |
145 | 145 | | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
146 | 175 | | |
147 | 176 | | |
148 | 177 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
| 3 | + | |
| 4 | + | |
3 | 5 | | |
4 | 6 | | |
5 | 7 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
727 | 727 | | |
728 | 728 | | |
729 | 729 | | |
| 730 | + | |
| 731 | + | |
| 732 | + | |
| 733 | + | |
| 734 | + | |
| 735 | + | |
| 736 | + | |
| 737 | + | |
730 | 738 | | |
731 | 739 | | |
732 | 740 | | |
| |||
924 | 932 | | |
925 | 933 | | |
926 | 934 | | |
927 | | - | |
928 | | - | |
929 | | - | |
930 | | - | |
931 | | - | |
932 | | - | |
933 | | - | |
934 | | - | |
| 935 | + | |
| 936 | + | |
| 937 | + | |
| 938 | + | |
| 939 | + | |
| 940 | + | |
| 941 | + | |
| 942 | + | |
| 943 | + | |
| 944 | + | |
| 945 | + | |
| 946 | + | |
| 947 | + | |
935 | 948 | | |
936 | 949 | | |
937 | 950 | | |
| |||
0 commit comments