@unovis/mcp 1.7.0-mcp.1 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -2
- package/dist/cli.js +7 -0
- package/dist/cli.js.map +1 -1
- package/dist/codegen/index.js +23 -8
- package/dist/codegen/index.js.map +1 -1
- package/dist/html/document.d.ts +16 -3
- package/dist/html/document.js +50 -20
- package/dist/html/document.js.map +1 -1
- package/dist/index.d.ts +7 -6
- package/dist/index.js +6 -3
- package/dist/index.js.map +1 -1
- package/dist/recipes/area.d.ts +3 -2
- package/dist/recipes/bar.d.ts +4 -3
- package/dist/recipes/bar.js +4 -1
- package/dist/recipes/bar.js.map +1 -1
- package/dist/recipes/boxplot.d.ts +3 -2
- package/dist/recipes/chord.d.ts +1 -0
- package/dist/recipes/choropleth.d.ts +1 -0
- package/dist/recipes/donut.d.ts +1 -0
- package/dist/recipes/graph.d.ts +1 -0
- package/dist/recipes/heatmap.d.ts +1 -0
- package/dist/recipes/index.d.ts +2 -0
- package/dist/recipes/index.js +3 -0
- package/dist/recipes/index.js.map +1 -1
- package/dist/recipes/line.d.ts +3 -2
- package/dist/recipes/nested-donut.d.ts +1 -0
- package/dist/recipes/radial-bar.d.ts +1 -0
- package/dist/recipes/sankey.d.ts +1 -0
- package/dist/recipes/scatter.d.ts +3 -2
- package/dist/recipes/shared.d.ts +6 -10
- package/dist/recipes/shared.js +7 -53
- package/dist/recipes/shared.js.map +1 -1
- package/dist/recipes/timeline.d.ts +1 -0
- package/dist/recipes/treemap.d.ts +1 -0
- package/dist/render/materialize.d.ts +9 -3
- package/dist/render/materialize.js +66 -27
- package/dist/render/materialize.js.map +1 -1
- package/dist/render/renderer.d.ts +2 -7
- package/dist/render/renderer.js +1 -1
- package/dist/render/renderer.js.map +1 -1
- package/dist/render/spec-schema.d.ts +1180 -0
- package/dist/render/spec-schema.js +71 -0
- package/dist/render/spec-schema.js.map +1 -0
- package/dist/render/spec.d.ts +15 -7
- package/dist/render/spec.js +9 -8
- package/dist/render/spec.js.map +1 -1
- package/dist/render/time-ticks.d.ts +10 -0
- package/dist/render/time-ticks.js +56 -0
- package/dist/render/time-ticks.js.map +1 -0
- package/dist/server.js +12 -3
- package/dist/server.js.map +1 -1
- package/dist/tools/register.d.ts +20 -1
- package/dist/tools/register.js +98 -15
- package/dist/tools/register.js.map +1 -1
- package/dist/widget/bundle.js +470 -465
- package/dist/widget/bundle.meta.json +2 -1
- package/dist/widget/bundle.standard.js +799 -0
- package/dist/widget/entry.d.ts +4 -0
- package/dist/widget/entry.js +149 -13
- package/dist/widget/entry.js.map +1 -1
- package/dist/widget/events.d.ts +25 -0
- package/dist/widget/events.js +97 -0
- package/dist/widget/events.js.map +1 -0
- package/dist/widget/interactions.js +22 -12
- package/dist/widget/interactions.js.map +1 -1
- package/dist/widget/unpack.d.ts +1 -0
- package/dist/widget/unpack.js +1 -0
- package/dist/widget/unpack.js.map +1 -0
- package/dist/widget/variants.d.ts +14 -0
- package/dist/widget/variants.js +22 -0
- package/dist/widget/variants.js.map +1 -0
- package/docs/README.md +2 -1
- package/docs/architecture.md +29 -76
- package/docs/chart-spec.md +41 -0
- package/docs/getting-started.md +5 -0
- package/docs/interactive.md +72 -14
- package/docs/output-types.md +9 -9
- package/docs/programmatic.md +24 -0
- package/docs/tools.md +7 -7
- package/docs/troubleshooting.md +14 -44
- package/docs/webview.md +83 -0
- package/package.json +35 -13
- package/schema/chart-spec.v0.1.baseline.json +309 -0
- package/schema/chart-spec.v0.1.json +309 -0
- package/dist/env/bbox.d.ts +0 -13
- package/dist/env/bbox.js +0 -335
- package/dist/env/bbox.js.map +0 -1
- package/dist/env/canvas.d.ts +0 -9
- package/dist/env/canvas.js +0 -55
- package/dist/env/canvas.js.map +0 -1
- package/dist/env/computed-style.d.ts +0 -38
- package/dist/env/computed-style.js +0 -186
- package/dist/env/computed-style.js.map +0 -1
- package/dist/env/fonts.d.ts +0 -3
- package/dist/env/fonts.js +0 -103
- package/dist/env/fonts.js.map +0 -1
- package/dist/env/index.d.ts +0 -13
- package/dist/env/index.js +0 -121
- package/dist/env/index.js.map +0 -1
- package/dist/env/raf-queue.d.ts +0 -23
- package/dist/env/raf-queue.js +0 -51
- package/dist/env/raf-queue.js.map +0 -1
- package/dist/env/size.d.ts +0 -9
- package/dist/env/size.js +0 -30
- package/dist/env/size.js.map +0 -1
- package/dist/render/headless.d.ts +0 -62
- package/dist/render/headless.js +0 -158
- package/dist/render/headless.js.map +0 -1
- package/dist/render/mutex.d.ts +0 -9
- package/dist/render/mutex.js +0 -14
- package/dist/render/mutex.js.map +0 -1
- package/dist/render/rasterize.d.ts +0 -10
- package/dist/render/rasterize.js +0 -29
- package/dist/render/rasterize.js.map +0 -1
- package/dist/svg/collect-css.d.ts +0 -14
- package/dist/svg/collect-css.js +0 -53
- package/dist/svg/collect-css.js.map +0 -1
- package/dist/svg/css-vars.d.ts +0 -17
- package/dist/svg/css-vars.js +0 -64
- package/dist/svg/css-vars.js.map +0 -1
- package/dist/svg/header.d.ts +0 -8
- package/dist/svg/header.js +0 -81
- package/dist/svg/header.js.map +0 -1
- package/dist/svg/ids.d.ts +0 -12
- package/dist/svg/ids.js +0 -94
- package/dist/svg/ids.js.map +0 -1
- package/dist/svg/postprocess.d.ts +0 -41
- package/dist/svg/postprocess.js +0 -135
- package/dist/svg/postprocess.js.map +0 -1
- package/fonts/README.md +0 -19
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/** The ChartSpec contract as a zod schema.
|
|
2
|
+
*
|
|
3
|
+
* The TypeScript interface types the IR for this codebase; this schema is the
|
|
4
|
+
* same contract for everyone else — hosts that persist specs, build them by
|
|
5
|
+
* hand, or validate before rendering. `scripts/generate-spec-schema.mjs`
|
|
6
|
+
* emits it as JSON Schema (shipped as `@unovis/mcp/chart-spec.schema.json`),
|
|
7
|
+
* and test/spec-schema.test.ts holds three lines of defense: the emitted file
|
|
8
|
+
* matches this source, every recipe-produced spec validates, and the frozen
|
|
9
|
+
* v1 baseline stays additively compatible.
|
|
10
|
+
*/
|
|
11
|
+
import { z } from 'zod';
|
|
12
|
+
import { XY_COMPONENTS, SINGLE_COMPONENTS } from './materialize.js';
|
|
13
|
+
const fieldType = z.enum(['number', 'string', 'date']);
|
|
14
|
+
/** One schema per accessor form so validation errors name the exact shape */
|
|
15
|
+
export const accessorRefSchema = z.union([
|
|
16
|
+
z.object({ $field: z.string(), as: fieldType.optional() }).strict()
|
|
17
|
+
.describe('d => coerce(d[field])'),
|
|
18
|
+
z.object({ $index: z.literal(true) }).strict().describe('(d, i) => i'),
|
|
19
|
+
z.object({ $const: z.unknown() }).strict().describe('() => value'),
|
|
20
|
+
z.object({ $dateTickFormat: z.literal(true) }).strict()
|
|
21
|
+
.describe('Locale-aware date tick formatter'),
|
|
22
|
+
z.object({ $numTickFormat: z.literal(true) }).strict()
|
|
23
|
+
.describe('Locale-aware number tick formatter'),
|
|
24
|
+
z.object({ $lookup: z.array(z.union([z.string(), z.number()])) }).strict()
|
|
25
|
+
.describe('(d, i) => values[i % values.length]'),
|
|
26
|
+
z.object({
|
|
27
|
+
$format: z.object({ field: z.string(), prefix: z.string().optional(), suffix: z.string().optional() }).strict(),
|
|
28
|
+
}).strict().describe('d => prefix + formatNumber(d[field]) + suffix'),
|
|
29
|
+
z.object({
|
|
30
|
+
$mapField: z.object({ field: z.string(), mapping: z.record(z.string(), z.string()), fallback: z.string().optional() }).strict(),
|
|
31
|
+
}).strict().describe('d => mapping[String(d[field])] ?? fallback'),
|
|
32
|
+
]);
|
|
33
|
+
const axisSchema = z.object({
|
|
34
|
+
label: z.string().optional(),
|
|
35
|
+
gridLine: z.boolean().optional(),
|
|
36
|
+
numTicks: z.number().optional(),
|
|
37
|
+
tickFormat: accessorRefSchema.optional(),
|
|
38
|
+
domainLine: z.boolean().optional(),
|
|
39
|
+
tickTextAngle: z.number().optional(),
|
|
40
|
+
tickValues: z.array(z.number()).optional(),
|
|
41
|
+
}).catchall(z.unknown());
|
|
42
|
+
export const chartSpecSchema = z.object({
|
|
43
|
+
specVersion: z.string().regex(/^\d+\.\d+$/).optional()
|
|
44
|
+
.describe('ChartSpec contract version as major.minor (see SPEC_VERSION). While the major is 0, breaking changes bump the minor; from 1.0 on, minors are additive and only the major breaks'),
|
|
45
|
+
container: z.enum(['xy', 'single']),
|
|
46
|
+
width: z.number().positive(),
|
|
47
|
+
height: z.number().positive(),
|
|
48
|
+
theme: z.enum(['light', 'dark']),
|
|
49
|
+
title: z.string().optional(),
|
|
50
|
+
/** Extra container options — deliberately open: the escape hatch to Unovis
|
|
51
|
+
* config the tool schemas don't expose */
|
|
52
|
+
containerConfig: z.record(z.string(), z.unknown()).optional(),
|
|
53
|
+
components: z.array(z.object({
|
|
54
|
+
type: z.enum([...XY_COMPONENTS, ...SINGLE_COMPONENTS]),
|
|
55
|
+
/** Component config is open for the same reason as containerConfig;
|
|
56
|
+
* accessor descriptors are validated where they appear in typed slots */
|
|
57
|
+
config: z.record(z.string(), z.unknown()),
|
|
58
|
+
}).strict()).min(1),
|
|
59
|
+
xAxis: axisSchema.optional(),
|
|
60
|
+
yAxis: axisSchema.optional(),
|
|
61
|
+
colors: z.array(z.string()).optional(),
|
|
62
|
+
locale: z.string().optional()
|
|
63
|
+
.describe('BCP-47 locale for date/number formatting (default en-US)'),
|
|
64
|
+
legend: z.array(z.object({
|
|
65
|
+
name: z.string(),
|
|
66
|
+
color: z.string().optional(),
|
|
67
|
+
paletteIndex: z.number().int().optional(),
|
|
68
|
+
}).strict()).optional(),
|
|
69
|
+
data: z.unknown(),
|
|
70
|
+
}).strict();
|
|
71
|
+
//# sourceMappingURL=spec-schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spec-schema.js","sourceRoot":"","sources":["../../src/render/spec-schema.ts"],"names":[],"mappings":"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"}
|
package/dist/render/spec.d.ts
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* generation. Accessors are descriptors referencing data fields by name —
|
|
7
7
|
* user input is never evaluated as code.
|
|
8
8
|
*/
|
|
9
|
+
import type { LegendItemSpec } from '@unovis/ssr';
|
|
9
10
|
export type FieldType = 'number' | 'string' | 'date';
|
|
10
11
|
/** Accessor descriptors (JSON-safe stand-ins for Unovis accessor functions) */
|
|
11
12
|
export type AccessorRef =
|
|
@@ -67,14 +68,19 @@ export interface AxisSpec {
|
|
|
67
68
|
tickTextAngle?: number;
|
|
68
69
|
[key: string]: SpecConfigValue;
|
|
69
70
|
}
|
|
70
|
-
export
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
71
|
+
export type { LegendItemSpec } from '@unovis/ssr';
|
|
72
|
+
/** Version of the ChartSpec contract, as `major.minor`.
|
|
73
|
+
*
|
|
74
|
+
* While the major is 0 the contract is explicitly unstable: breaking changes
|
|
75
|
+
* are allowed and bump the minor (0.1 → 0.2), each with a freshly frozen
|
|
76
|
+
* schema baseline. Additions never require a bump. Declaring 1.0 is the
|
|
77
|
+
* deliberate act of adopting the additive-only promise — from then on the
|
|
78
|
+
* major moves only on breaking changes. Consumers that persist specs or
|
|
79
|
+
* embed documents compare it via the `unovis:ready` handshake. */
|
|
80
|
+
export declare const SPEC_VERSION = "0.1";
|
|
77
81
|
export interface ChartSpec {
|
|
82
|
+
/** ChartSpec contract version this spec was written against (see SPEC_VERSION) */
|
|
83
|
+
specVersion?: string;
|
|
78
84
|
container: 'xy' | 'single';
|
|
79
85
|
width: number;
|
|
80
86
|
height: number;
|
|
@@ -87,6 +93,8 @@ export interface ChartSpec {
|
|
|
87
93
|
yAxis?: AxisSpec;
|
|
88
94
|
/** Custom palette — overrides --vis-colorN for the whole chart */
|
|
89
95
|
colors?: string[];
|
|
96
|
+
/** BCP-47 locale for date/number tick and tooltip formatting (default en-US) */
|
|
97
|
+
locale?: string;
|
|
90
98
|
legend?: LegendItemSpec[];
|
|
91
99
|
data: unknown;
|
|
92
100
|
}
|
package/dist/render/spec.js
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
/** ChartSpec — a JSON-serializable intermediate representation of a chart.
|
|
2
|
-
*
|
|
3
|
-
* Tool inputs are converted to a ChartSpec (recipes), which the renderer
|
|
4
|
-
* materializes into live Unovis containers/components. Keeping the IR
|
|
5
|
-
* serializable enables the `config` output mode and, later, framework code
|
|
6
|
-
* generation. Accessors are descriptors referencing data fields by name —
|
|
7
|
-
* user input is never evaluated as code.
|
|
8
|
-
*/
|
|
9
1
|
export const isAccessorRef = (value) => {
|
|
10
2
|
if (typeof value !== 'object' || value === null || Array.isArray(value))
|
|
11
3
|
return false;
|
|
12
4
|
const keys = Object.keys(value);
|
|
13
5
|
return keys.some(k => ['$field', '$index', '$const', '$dateTickFormat', '$numTickFormat', '$lookup', '$format', '$mapField'].includes(k));
|
|
14
6
|
};
|
|
7
|
+
/** Version of the ChartSpec contract, as `major.minor`.
|
|
8
|
+
*
|
|
9
|
+
* While the major is 0 the contract is explicitly unstable: breaking changes
|
|
10
|
+
* are allowed and bump the minor (0.1 → 0.2), each with a freshly frozen
|
|
11
|
+
* schema baseline. Additions never require a bump. Declaring 1.0 is the
|
|
12
|
+
* deliberate act of adopting the additive-only promise — from then on the
|
|
13
|
+
* major moves only on breaking changes. Consumers that persist specs or
|
|
14
|
+
* embed documents compare it via the `unovis:ready` handshake. */
|
|
15
|
+
export const SPEC_VERSION = '0.1';
|
|
15
16
|
//# sourceMappingURL=spec.js.map
|
package/dist/render/spec.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spec.js","sourceRoot":"","sources":["../../src/render/spec.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"spec.js","sourceRoot":"","sources":["../../src/render/spec.ts"],"names":[],"mappings":"AA+BA,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,KAAc,EAAwB,EAAE;IACpE,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAA;IACrF,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAC/B,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAA;AAC3I,CAAC,CAAA;AAyBD;;;;;;;kEAOkE;AAClE,MAAM,CAAC,MAAM,YAAY,GAAG,KAAK,CAAA"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** Calendar-aligned tick values for time axes — env-free, shared by the
|
|
2
|
+
* recipes (which bake ticks into specs) and the materializer (which derives
|
|
3
|
+
* them when a hand-written spec omits them). */
|
|
4
|
+
/** Calendar-aligned tick values for date axes. Linear-scale ticks land at
|
|
5
|
+
* arbitrary times of day, which the date formatter would render as
|
|
6
|
+
* time-of-day labels ("08:53 AM" on a 3-month chart) — align ticks to
|
|
7
|
+
* month/day/hour/minute boundaries instead. */
|
|
8
|
+
export declare function dateTickValues(min: number, max: number, target?: number): number[] | undefined;
|
|
9
|
+
/** Tick values for a time axis derived from the data extent of a date field */
|
|
10
|
+
export declare function timeTickValuesFromData(data: Record<string, unknown>[], fieldName: string): number[] | undefined;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/** Calendar-aligned tick values for time axes — env-free, shared by the
|
|
2
|
+
* recipes (which bake ticks into specs) and the materializer (which derives
|
|
3
|
+
* them when a hand-written spec omits them). */
|
|
4
|
+
const MINUTE = 60_000;
|
|
5
|
+
const HOUR = 60 * MINUTE;
|
|
6
|
+
const DAY = 24 * HOUR;
|
|
7
|
+
/** Calendar-aligned tick values for date axes. Linear-scale ticks land at
|
|
8
|
+
* arbitrary times of day, which the date formatter would render as
|
|
9
|
+
* time-of-day labels ("08:53 AM" on a 3-month chart) — align ticks to
|
|
10
|
+
* month/day/hour/minute boundaries instead. */
|
|
11
|
+
export function dateTickValues(min, max, target = 7) {
|
|
12
|
+
const span = max - min;
|
|
13
|
+
if (!Number.isFinite(span) || span <= 0)
|
|
14
|
+
return undefined;
|
|
15
|
+
const ticks = [];
|
|
16
|
+
if (span >= 60 * DAY) { // month starts
|
|
17
|
+
const stepMonths = Math.max(1, Math.ceil(span / (30 * DAY) / target));
|
|
18
|
+
const start = new Date(min);
|
|
19
|
+
let date = new Date(Date.UTC(start.getUTCFullYear(), start.getUTCMonth(), 1));
|
|
20
|
+
if (date.getTime() < min)
|
|
21
|
+
date = new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth() + 1, 1));
|
|
22
|
+
while (date.getTime() <= max && ticks.length < 24) {
|
|
23
|
+
ticks.push(date.getTime());
|
|
24
|
+
date = new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth() + stepMonths, 1));
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
// day / hour / minute boundaries (uniform in UTC epoch time)
|
|
29
|
+
const unit = span >= 2 * DAY ? DAY : span >= 2 * HOUR ? HOUR : MINUTE;
|
|
30
|
+
const niceSteps = unit === DAY ? [1, 2, 7, 14] : unit === HOUR ? [1, 2, 3, 6, 12] : [1, 2, 5, 10, 15, 30];
|
|
31
|
+
const rawStep = span / unit / target;
|
|
32
|
+
const step = (niceSteps.find(s => s >= rawStep) ?? Math.ceil(rawStep)) * unit;
|
|
33
|
+
for (let t = Math.ceil(min / step) * step; t <= max && ticks.length < 24; t += step)
|
|
34
|
+
ticks.push(t);
|
|
35
|
+
}
|
|
36
|
+
return ticks.length >= 2 ? ticks : undefined;
|
|
37
|
+
}
|
|
38
|
+
/** Tick values for a time axis derived from the data extent of a date field */
|
|
39
|
+
export function timeTickValuesFromData(data, fieldName) {
|
|
40
|
+
let min = Infinity;
|
|
41
|
+
let max = -Infinity;
|
|
42
|
+
for (const record of data) {
|
|
43
|
+
const raw = record[fieldName];
|
|
44
|
+
if (raw === null || raw === undefined || raw === '')
|
|
45
|
+
continue;
|
|
46
|
+
const time = typeof raw === 'number' ? raw : new Date(String(raw)).getTime();
|
|
47
|
+
if (Number.isNaN(time))
|
|
48
|
+
continue;
|
|
49
|
+
if (time < min)
|
|
50
|
+
min = time;
|
|
51
|
+
if (time > max)
|
|
52
|
+
max = time;
|
|
53
|
+
}
|
|
54
|
+
return dateTickValues(min, max);
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=time-ticks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"time-ticks.js","sourceRoot":"","sources":["../../src/render/time-ticks.ts"],"names":[],"mappings":"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"}
|
package/dist/server.js
CHANGED
|
@@ -2,7 +2,7 @@ import { readFileSync } from 'node:fs';
|
|
|
2
2
|
import { join, dirname } from 'node:path';
|
|
3
3
|
import { fileURLToPath } from 'node:url';
|
|
4
4
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
5
|
-
import { registerTools, WIDGET_URI } from './tools/register.js';
|
|
5
|
+
import { registerTools, sniffAppsCapability, WIDGET_URI, APPS_MIME_TYPE } from './tools/register.js';
|
|
6
6
|
import { buildEmbedDocument } from './html/document.js';
|
|
7
7
|
export function getPackageVersion() {
|
|
8
8
|
try {
|
|
@@ -18,6 +18,12 @@ export function buildServer(options = {}) {
|
|
|
18
18
|
name: 'unovis',
|
|
19
19
|
version: getPackageVersion(),
|
|
20
20
|
});
|
|
21
|
+
// Sniff the MCP Apps capability from the raw initialize (see register.ts)
|
|
22
|
+
const connect = server.connect.bind(server);
|
|
23
|
+
server.connect = async (transport) => {
|
|
24
|
+
sniffAppsCapability(server, transport);
|
|
25
|
+
await connect(transport);
|
|
26
|
+
};
|
|
21
27
|
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
22
28
|
registerWidgetResource(server);
|
|
23
29
|
registerTools(server, options);
|
|
@@ -32,11 +38,14 @@ function registerWidgetResource(server) {
|
|
|
32
38
|
server.registerResource('chart-widget', WIDGET_URI, {
|
|
33
39
|
title: 'Unovis chart widget',
|
|
34
40
|
description: 'Interactive chart renderer. Send it a chart spec to render.',
|
|
35
|
-
mimeType:
|
|
41
|
+
mimeType: APPS_MIME_TYPE,
|
|
42
|
+
// Empty CSP allowlists are the point: the widget is fully self-contained
|
|
43
|
+
// (a tested no-network guarantee), so hosts can sandbox it completely
|
|
44
|
+
_meta: { ui: { csp: { connectDomains: [], resourceDomains: [] }, prefersBorder: true } },
|
|
36
45
|
}, async () => ({
|
|
37
46
|
contents: [{
|
|
38
47
|
uri: WIDGET_URI,
|
|
39
|
-
mimeType:
|
|
48
|
+
mimeType: APPS_MIME_TYPE,
|
|
40
49
|
text: buildEmbedDocument(),
|
|
41
50
|
}],
|
|
42
51
|
}));
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAExC,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AAEnE,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAExC,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AAEnE,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAEpG,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AAEvD,MAAM,UAAU,iBAAiB;IAC/B,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,cAAc,CAAC,CAAA;QACnF,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,IAAI,OAAO,CAAA;IACrE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,OAAO,CAAA;IAChB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,WAAW,CAAE,UAA6B,EAAE;IAC1D,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;QAC3B,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,iBAAiB,EAAE;KAC7B,CAAC,CAAA;IACF,0EAA0E;IAC1E,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IAC3C,MAAM,CAAC,OAAO,GAAG,KAAK,EAAE,SAAS,EAAE,EAAE;QACnC,mBAAmB,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;QACtC,MAAM,OAAO,CAAC,SAAS,CAAC,CAAA;IAC1B,CAAC,CAAA;IACD,mEAAmE;IACnE,sBAAsB,CAAC,MAAM,CAAC,CAAA;IAC9B,aAAa,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC9B,OAAO,MAAM,CAAA;AACf,CAAC;AAED;;;;mEAImE;AACnE,SAAS,sBAAsB,CAAE,MAAiB;IAChD,MAAM,CAAC,gBAAgB,CACrB,cAAc,EACd,UAAU,EACV;QACE,KAAK,EAAE,qBAAqB;QAC5B,WAAW,EAAE,6DAA6D;QAC1E,QAAQ,EAAE,cAAc;QACxB,yEAAyE;QACzE,sEAAsE;QACtE,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,cAAc,EAAE,EAAE,EAAE,eAAe,EAAE,EAAE,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,EAAE;KACzF,EACD,KAAK,IAAI,EAAE,CAAC,CAAC;QACX,QAAQ,EAAE,CAAC;gBACT,GAAG,EAAE,UAAU;gBACf,QAAQ,EAAE,cAAc;gBACxB,IAAI,EAAE,kBAAkB,EAAE;aAC3B,CAAC;KACH,CAAC,CACH,CAAA;AACH,CAAC"}
|
package/dist/tools/register.d.ts
CHANGED
|
@@ -5,8 +5,27 @@ export interface ToolFilterOptions {
|
|
|
5
5
|
disabledTools?: string[];
|
|
6
6
|
/** When set, only these tools are exposed (--tools) */
|
|
7
7
|
enabledTools?: string[];
|
|
8
|
+
/** Where `outputPath` may write. `undefined` = anywhere (a local stdio
|
|
9
|
+
* server acts with its user's own authority); a directory = only inside
|
|
10
|
+
* it; `false` = file writes disabled. The HTTP transport defaults to
|
|
11
|
+
* `false` — an unauthenticated network endpoint must not double as a
|
|
12
|
+
* remote file-write primitive. */
|
|
13
|
+
writeDir?: string | false;
|
|
8
14
|
}
|
|
9
|
-
/** MCP
|
|
15
|
+
/** MCP Apps resource the interactive output binds to (registered in server.ts) */
|
|
10
16
|
export declare const WIDGET_URI = "ui://unovis/chart";
|
|
17
|
+
/** MCP Apps extension (SEP-1865, io.modelcontextprotocol/ui) wire constants.
|
|
18
|
+
* Pinned by tests; keep in sync with the extension spec rather than importing
|
|
19
|
+
* @modelcontextprotocol/ext-apps, whose react peer deps we don't need. */
|
|
20
|
+
export declare const APPS_MIME_TYPE = "text/html;profile=mcp-app";
|
|
21
|
+
export declare const APPS_EXTENSION_ID = "io.modelcontextprotocol/ui";
|
|
22
|
+
/** Enforce the write policy on a requested outputPath. Returns an error
|
|
23
|
+
* message, or undefined when the write is allowed. */
|
|
24
|
+
export declare function refuseWrite(outputPath: string, writeDir: ToolFilterOptions['writeDir']): string | undefined;
|
|
11
25
|
export declare function activeRecipes(filter?: ToolFilterOptions): AnyRecipe[];
|
|
26
|
+
/** Intercept a transport's onmessage assignment to sniff
|
|
27
|
+
* `capabilities.extensions` from the raw initialize request. Must run BEFORE
|
|
28
|
+
* connect — with an in-memory transport the initialize can arrive in the same
|
|
29
|
+
* microtask the connection is established in. */
|
|
30
|
+
export declare function sniffAppsCapability(server: McpServer, transport: object): void;
|
|
12
31
|
export declare function registerTools(server: McpServer, filter?: ToolFilterOptions): void;
|
package/dist/tools/register.js
CHANGED
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
/** Bind chart recipes to MCP tools. */
|
|
2
2
|
import { mkdirSync, mkdtempSync, writeFileSync } from 'node:fs';
|
|
3
3
|
import { tmpdir } from 'node:os';
|
|
4
|
-
import { dirname, isAbsolute, join } from 'node:path';
|
|
4
|
+
import { dirname, isAbsolute, join, resolve, sep } from 'node:path';
|
|
5
|
+
import { svgToPng, themeBackground } from '@unovis/ssr';
|
|
5
6
|
import { recipes } from '../recipes/index.js';
|
|
6
7
|
import { renderChart, resolveMapMarkers, ChartInputError } from '../render/renderer.js';
|
|
7
|
-
import { svgToPng, themeBackground } from '../render/rasterize.js';
|
|
8
8
|
import { buildChartDocument } from '../html/document.js';
|
|
9
9
|
import { generateCode, formatGeneratedFiles } from '../codegen/index.js';
|
|
10
|
-
/** MCP
|
|
10
|
+
/** MCP Apps resource the interactive output binds to (registered in server.ts) */
|
|
11
11
|
export const WIDGET_URI = 'ui://unovis/chart';
|
|
12
|
+
/** MCP Apps extension (SEP-1865, io.modelcontextprotocol/ui) wire constants.
|
|
13
|
+
* Pinned by tests; keep in sync with the extension spec rather than importing
|
|
14
|
+
* @modelcontextprotocol/ext-apps, whose react peer deps we don't need. */
|
|
15
|
+
export const APPS_MIME_TYPE = 'text/html;profile=mcp-app';
|
|
16
|
+
export const APPS_EXTENSION_ID = 'io.modelcontextprotocol/ui';
|
|
12
17
|
const textResult = (text, isError = false) => ({ content: [{ type: 'text', text }], ...(isError ? { isError: true } : {}) });
|
|
13
18
|
/** Map data lives behind a `{ $unovisMap }` marker that only the Node renderer
|
|
14
19
|
* resolves — the browser widget has no map bundles, so bake it into the spec */
|
|
@@ -16,17 +21,44 @@ async function specForBrowser(spec) {
|
|
|
16
21
|
return { ...spec, components: await resolveMapMarkers(spec.components) };
|
|
17
22
|
}
|
|
18
23
|
const chartSummary = (spec) => `${spec.title ?? spec.components.map(c => c.type).join(' + ')} (${spec.width}×${spec.height}, ${spec.theme} theme)`;
|
|
19
|
-
|
|
24
|
+
/** Enforce the write policy on a requested outputPath. Returns an error
|
|
25
|
+
* message, or undefined when the write is allowed. */
|
|
26
|
+
export function refuseWrite(outputPath, writeDir) {
|
|
27
|
+
if (writeDir === undefined)
|
|
28
|
+
return undefined;
|
|
29
|
+
if (writeDir === false) {
|
|
30
|
+
return 'outputPath is disabled on this server — request inline output, or start the server with --allow-write-dir <dir>';
|
|
31
|
+
}
|
|
32
|
+
const dir = resolve(writeDir);
|
|
33
|
+
const target = resolve(outputPath);
|
|
34
|
+
if (target !== dir && !target.startsWith(dir + sep)) {
|
|
35
|
+
return `outputPath must be inside ${dir} on this server, got: ${outputPath}`;
|
|
36
|
+
}
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
/** In an MCP Apps host, every declared tool call renders the widget iframe —
|
|
40
|
+
* so every result must carry the spec, or the frame sits empty next to the
|
|
41
|
+
* answer. Gated on the client capability to keep non-Apps responses lean
|
|
42
|
+
* (the spec embeds the full dataset). */
|
|
43
|
+
async function appsResult(result, spec, appsHost) {
|
|
44
|
+
if (!appsHost)
|
|
45
|
+
return result;
|
|
46
|
+
return {
|
|
47
|
+
...result,
|
|
48
|
+
structuredContent: { spec: (await specForBrowser(spec)) },
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
async function runRecipe(recipe, input, writeDir, appsHost = false) {
|
|
20
52
|
try {
|
|
21
53
|
const spec = recipe.toSpec(input);
|
|
22
54
|
if (input.outputType === 'config') {
|
|
23
|
-
return textResult(JSON.stringify(spec, null, 2));
|
|
55
|
+
return appsResult(textResult(JSON.stringify(spec, null, 2)), spec, appsHost);
|
|
24
56
|
}
|
|
25
57
|
// Code: emit source for the chosen wrapper. Uses the unresolved spec so
|
|
26
58
|
// map data stays an import rather than an inlined payload.
|
|
27
59
|
if (input.outputType === 'code') {
|
|
28
60
|
const files = generateCode(spec, input.framework ?? 'ts');
|
|
29
|
-
return textResult(formatGeneratedFiles(files));
|
|
61
|
+
return appsResult(textResult(formatGeneratedFiles(files)), spec, appsHost);
|
|
30
62
|
}
|
|
31
63
|
// Interactive: hand the spec to a UI-capable client, which renders it with
|
|
32
64
|
// the widget resource. Static content stays in the transcript as a summary.
|
|
@@ -35,6 +67,8 @@ async function runRecipe(recipe, input) {
|
|
|
35
67
|
return {
|
|
36
68
|
content: [{ type: 'text', text: `Interactive chart: ${chartSummary(spec)}` }],
|
|
37
69
|
structuredContent: { spec: browserSpec },
|
|
70
|
+
// Result-level template link kept for pre-MCP-Apps hosts; official
|
|
71
|
+
// hosts key off the tool-level _meta.ui declaration instead
|
|
38
72
|
_meta: { 'openai/outputTemplate': WIDGET_URI },
|
|
39
73
|
};
|
|
40
74
|
}
|
|
@@ -45,15 +79,25 @@ async function runRecipe(recipe, input) {
|
|
|
45
79
|
if (outputPath && (!isAbsolute(outputPath) || !outputPath.endsWith(extension))) {
|
|
46
80
|
return textResult(`outputPath must be an absolute path ending in ${extension} (matching outputType), got: ${outputPath}`, true);
|
|
47
81
|
}
|
|
82
|
+
if (outputPath) {
|
|
83
|
+
const refused = refuseWrite(outputPath, writeDir);
|
|
84
|
+
if (refused)
|
|
85
|
+
return textResult(refused, true);
|
|
86
|
+
}
|
|
48
87
|
// Self-contained interactive document. Always written to disk: the inlined
|
|
49
88
|
// widget bundle is far too large to put in a tool result.
|
|
50
89
|
if (isHtml) {
|
|
90
|
+
// html output IS a file — with writes disabled there is nothing to return
|
|
91
|
+
if (writeDir === false) {
|
|
92
|
+
return textResult('outputType "html" writes a file, which is disabled on this server — use "svg", "png" or "interactive", or start the server with --allow-write-dir <dir>', true);
|
|
93
|
+
}
|
|
51
94
|
const html = buildChartDocument(await specForBrowser(spec));
|
|
52
|
-
const
|
|
95
|
+
const fallbackDir = typeof writeDir === 'string' ? resolve(writeDir) : tmpdir();
|
|
96
|
+
const target = outputPath ?? join(mkdtempSync(join(fallbackDir, 'unovis-chart-')), 'chart.html');
|
|
53
97
|
mkdirSync(dirname(target), { recursive: true });
|
|
54
98
|
writeFileSync(target, html);
|
|
55
|
-
return textResult(`Interactive chart saved to ${target} — open it in a browser for tooltips, ` +
|
|
56
|
-
`crosshair and hover highlighting. ${chartSummary(spec)}`);
|
|
99
|
+
return appsResult(textResult(`Interactive chart saved to ${target} — open it in a browser for tooltips, ` +
|
|
100
|
+
`crosshair and hover highlighting. ${chartSummary(spec)}`), spec, appsHost);
|
|
57
101
|
}
|
|
58
102
|
const result = await renderChart(spec);
|
|
59
103
|
const warningsNote = result.warnings.length ? ` (warnings: ${result.warnings.join('; ')})` : '';
|
|
@@ -66,21 +110,21 @@ async function runRecipe(recipe, input) {
|
|
|
66
110
|
if (outputPath) {
|
|
67
111
|
mkdirSync(dirname(outputPath), { recursive: true });
|
|
68
112
|
writeFileSync(outputPath, png);
|
|
69
|
-
return textResult(`Chart saved to ${outputPath} (${result.width}×${result.height} at ${input.scale ?? 2}x)${warningsNote}`);
|
|
113
|
+
return appsResult(textResult(`Chart saved to ${outputPath} (${result.width}×${result.height} at ${input.scale ?? 2}x)${warningsNote}`), spec, appsHost);
|
|
70
114
|
}
|
|
71
|
-
return {
|
|
115
|
+
return appsResult({
|
|
72
116
|
content: [
|
|
73
117
|
{ type: 'image', data: png.toString('base64'), mimeType: 'image/png' },
|
|
74
118
|
...(warningsNote ? [{ type: 'text', text: warningsNote.trim() }] : []),
|
|
75
119
|
],
|
|
76
|
-
};
|
|
120
|
+
}, spec, appsHost);
|
|
77
121
|
}
|
|
78
122
|
if (outputPath) {
|
|
79
123
|
mkdirSync(dirname(outputPath), { recursive: true });
|
|
80
124
|
writeFileSync(outputPath, `<?xml version="1.0" encoding="UTF-8"?>\n${result.svg}`);
|
|
81
|
-
return textResult(`Chart saved to ${outputPath} (${result.width}×${result.height})${warningsNote}`);
|
|
125
|
+
return appsResult(textResult(`Chart saved to ${outputPath} (${result.width}×${result.height})${warningsNote}`), spec, appsHost);
|
|
82
126
|
}
|
|
83
|
-
return textResult(result.svg + (result.warnings.length ? `\n<!-- warnings: ${result.warnings.join('; ')} -->` : ''));
|
|
127
|
+
return appsResult(textResult(result.svg + (result.warnings.length ? `\n<!-- warnings: ${result.warnings.join('; ')} -->` : '')), spec, appsHost);
|
|
84
128
|
}
|
|
85
129
|
catch (e) {
|
|
86
130
|
if (e instanceof ChartInputError) {
|
|
@@ -94,6 +138,42 @@ export function activeRecipes(filter = {}) {
|
|
|
94
138
|
const enabled = filter.enabledTools?.length ? new Set(filter.enabledTools) : undefined;
|
|
95
139
|
return recipes.filter(r => !disabled.has(r.name) && (!enabled || enabled.has(r.name)));
|
|
96
140
|
}
|
|
141
|
+
/** Connections whose client advertised the MCP Apps extension.
|
|
142
|
+
*
|
|
143
|
+
* The SDK's ClientCapabilities schema predates SEP-1724, so it strips the
|
|
144
|
+
* `extensions` key during initialize — getClientCapabilities() can never see
|
|
145
|
+
* it (verified end-to-end). Until the SDK learns the field, the raw
|
|
146
|
+
* initialize message is sniffed at the transport seam; the schema path below
|
|
147
|
+
* takes over automatically once it stops returning undefined. */
|
|
148
|
+
const appsClients = new WeakSet();
|
|
149
|
+
/** Intercept a transport's onmessage assignment to sniff
|
|
150
|
+
* `capabilities.extensions` from the raw initialize request. Must run BEFORE
|
|
151
|
+
* connect — with an in-memory transport the initialize can arrive in the same
|
|
152
|
+
* microtask the connection is established in. */
|
|
153
|
+
export function sniffAppsCapability(server, transport) {
|
|
154
|
+
let assigned;
|
|
155
|
+
Object.defineProperty(transport, 'onmessage', {
|
|
156
|
+
configurable: true,
|
|
157
|
+
enumerable: true,
|
|
158
|
+
get: () => assigned,
|
|
159
|
+
set: (handler) => {
|
|
160
|
+
assigned = handler && ((...args) => {
|
|
161
|
+
const message = args[0];
|
|
162
|
+
if (message?.method === 'initialize' && message.params?.capabilities?.extensions?.[APPS_EXTENSION_ID]) {
|
|
163
|
+
appsClients.add(server);
|
|
164
|
+
}
|
|
165
|
+
handler.apply(transport, args);
|
|
166
|
+
});
|
|
167
|
+
},
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
/** Did the connected client advertise the MCP Apps extension capability? */
|
|
171
|
+
function appsCapableClient(server) {
|
|
172
|
+
if (appsClients.has(server))
|
|
173
|
+
return true;
|
|
174
|
+
const capabilities = server.server.getClientCapabilities();
|
|
175
|
+
return Boolean(capabilities?.extensions?.[APPS_EXTENSION_ID]);
|
|
176
|
+
}
|
|
97
177
|
export function registerTools(server, filter = {}) {
|
|
98
178
|
for (const recipe of activeRecipes(filter)) {
|
|
99
179
|
server.registerTool(recipe.name, {
|
|
@@ -104,9 +184,12 @@ export function registerTools(server, filter = {}) {
|
|
|
104
184
|
readOnlyHint: false, // outputPath can write a file
|
|
105
185
|
openWorldHint: false, // fully local, no network
|
|
106
186
|
},
|
|
187
|
+
// MCP Apps: the template is declared on the tool, ahead of time, so
|
|
188
|
+
// hosts can prefetch, cache and security-review it before any call
|
|
189
|
+
_meta: { ui: { resourceUri: WIDGET_URI } },
|
|
107
190
|
},
|
|
108
191
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
109
|
-
async (args) => runRecipe(recipe, args));
|
|
192
|
+
async (args) => runRecipe(recipe, args, filter.writeDir, appsCapableClient(server)));
|
|
110
193
|
}
|
|
111
194
|
server.registerTool('get_unovis_info', {
|
|
112
195
|
title: 'Unovis info',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"register.js","sourceRoot":"","sources":["../../src/tools/register.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAC/D,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAChC,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"register.js","sourceRoot":"","sources":["../../src/tools/register.ts"],"names":[],"mappings":"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"}
|