@dforge-core/dforge-mcp 0.1.4 → 0.1.5

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/CHANGELOG.md CHANGED
@@ -4,6 +4,16 @@ All notable changes to `@dforge-core/dforge-mcp`. This project uses semver-ish
4
4
  `0.1.0-rc.N` pre-release tags; the published version is set at publish time via
5
5
  the release workflow, so committed `package.json` versions are placeholders.
6
6
 
7
+ ## 0.1.5
8
+
9
+ ### Changed
10
+ - Bumped `@dforge-core/metadata` to `^0.0.5`. The re-vendored `reports.schema.json`
11
+ now **structurally validates** KPI and chart panel `config` (previously an
12
+ unvalidated object, so `dforge_module_validate` only checked `vizType`):
13
+ aggregation-vs-formula KPI metrics are mutually exclusive and non-empty; formula
14
+ inputs and chart overlay `series` are shape-checked; charts require
15
+ `chartType`/`categoryCol`/`valueCol`.
16
+
7
17
  ## 0.1.3
8
18
 
9
19
  ### Changed
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dforge-core/dforge-mcp",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "description": "MCP server for dForge module authoring. Exposes scaffold/pack/install tools and schema resources so AI agents (Claude Code, Cursor, Zed) can create and ship dForge modules.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://github.com/iash44/dForge-core",
@@ -32,7 +32,7 @@
32
32
  },
33
33
  "dependencies": {
34
34
  "@dforge-core/dforge-cli": "^0.2.2",
35
- "@dforge-core/metadata": "^0.0.4",
35
+ "@dforge-core/metadata": "^0.0.5",
36
36
  "@modelcontextprotocol/sdk": "^1.29.0",
37
37
  "zod": "^4.4.3"
38
38
  },
@@ -52,7 +52,7 @@
52
52
  "vizType": {
53
53
  "type": "string",
54
54
  "enum": ["table", "chart", "kpi", "pivot", "tree", "markdown"],
55
- "description": "Visualization type. (Older packages may use `metric` for `kpi`.)"
55
+ "description": "Visualization type. For any chart the vizType is `chart`; the chart kind goes in `config.chartType`."
56
56
  },
57
57
  "datasetCd": {
58
58
  "type": "string",
@@ -61,9 +61,142 @@
61
61
  "title": { "type": "string" },
62
62
  "config": {
63
63
  "type": "object",
64
- "description": "Viz-type-specific configuration.\n- chart: { chartType ('bar'|'horizontalBar'|'stackedBar'|'combo'|'line'|'area'|'pie'|'doughnut'|'scatter'|'bubble'|'funnel'|'heatmap'), categoryCol, valueCol, agg, seriesCol?, sizeCol?, chartSize? ('sm'|'m'|'l'|'xl'), clickAction?, showTrend?, series? }. `series` (a single object OR an array) declares CROSS-SOURCE overlay series on bar/horizontalBar/line/area, each { source?, categoryCol, valueCol, agg, label? }; `source` names a sibling dataset code (omit = the panel's own dataset). Overlays share one category axis (union of category values; bar gaps fill 0, line/area gap with null).\n- kpi: { metrics: [ metric, ... ] }. Each metric is EITHER an aggregation metric { column, agg ('sum'|'avg'|'min'|'max'|'count'), display?, label?, target?, min?, max?, icon?, sparklineDimension? } OR a FORMULA metric { formula (e.g. '[won] / [all] * 100'), inputs: [ { alias, column, agg, source? } ], format?: { style?: 'number'|'percent', decimals? }, display?, label? }. A formula input's `source` names a sibling dataset code for CROSS-DATASET metrics (omit = the panel's own dataset). Auto format (omit `format.style`) inherits the first input column's own formatter (currency/grouping).\n- table: { groupRules, aggregations, colorRules }."
64
+ "description": "Viz-type-specific configuration. `kpi` and `chart` are structurally validated (see kpiConfig / chartConfig below); `table`/`pivot`/`tree`/`markdown` accept any object."
65
65
  }
66
66
  },
67
+ "additionalProperties": false,
68
+ "allOf": [
69
+ {
70
+ "if": { "required": ["vizType"], "properties": { "vizType": { "const": "kpi" } } },
71
+ "then": { "properties": { "config": { "$ref": "#/$defs/kpiConfig" } } }
72
+ },
73
+ {
74
+ "if": { "required": ["vizType"], "properties": { "vizType": { "const": "chart" } } },
75
+ "then": { "properties": { "config": { "$ref": "#/$defs/chartConfig" } } }
76
+ }
77
+ ]
78
+ },
79
+
80
+ "aggFunc": {
81
+ "type": "string",
82
+ "enum": ["sum", "avg", "min", "max", "count"],
83
+ "description": "Aggregation function."
84
+ },
85
+
86
+ "kpiConfig": {
87
+ "type": "object",
88
+ "description": "KPI panel config: one or more metric cards.",
89
+ "required": ["metrics"],
90
+ "properties": {
91
+ "metrics": {
92
+ "type": "array",
93
+ "minItems": 1,
94
+ "items": { "$ref": "#/$defs/kpiMetric" }
95
+ }
96
+ },
97
+ "additionalProperties": false
98
+ },
99
+
100
+ "kpiMetric": {
101
+ "type": "object",
102
+ "description": "A KPI metric — EITHER an aggregation metric (`column` + `agg`, and no formula/inputs) OR a formula metric (`formula` + `inputs`, and no column/agg).",
103
+ "properties": {
104
+ "column": { "type": "string", "description": "Column to aggregate (aggregation metric)." },
105
+ "agg": { "$ref": "#/$defs/aggFunc" },
106
+ "formula": { "type": "string", "description": "Expression over `[alias]` inputs, e.g. '[won] / [all] * 100' (formula metric)." },
107
+ "inputs": {
108
+ "type": "array",
109
+ "minItems": 1,
110
+ "description": "Named aggregation inputs the formula references by `[alias]`.",
111
+ "items": { "$ref": "#/$defs/kpiInput" }
112
+ },
113
+ "format": { "$ref": "#/$defs/metricFormat" },
114
+ "display": { "type": "string", "enum": ["value", "gauge", "progress", "sparkline", "icon"] },
115
+ "label": { "type": "string" },
116
+ "target": { "type": "number" },
117
+ "min": { "type": "number" },
118
+ "max": { "type": "number" },
119
+ "icon": { "type": "string" },
120
+ "sparklineDimension": { "type": "string" }
121
+ },
122
+ "additionalProperties": false,
123
+ "allOf": [
124
+ {
125
+ "if": { "required": ["formula"] },
126
+ "then": {
127
+ "required": ["formula", "inputs"],
128
+ "not": { "anyOf": [ { "required": ["column"] }, { "required": ["agg"] } ] }
129
+ },
130
+ "else": {
131
+ "required": ["column", "agg"],
132
+ "not": { "anyOf": [ { "required": ["formula"] }, { "required": ["inputs"] } ] }
133
+ }
134
+ }
135
+ ]
136
+ },
137
+
138
+ "kpiInput": {
139
+ "type": "object",
140
+ "description": "One named aggregation a formula metric references by `[alias]`.",
141
+ "required": ["alias", "column", "agg"],
142
+ "properties": {
143
+ "alias": { "type": "string", "description": "Token used in the formula as `[alias]`." },
144
+ "column": { "type": "string" },
145
+ "agg": { "$ref": "#/$defs/aggFunc" },
146
+ "source": { "type": "string", "description": "Sibling dataset code to aggregate over (CROSS-DATASET); omit = the panel's own dataset." }
147
+ },
148
+ "additionalProperties": false
149
+ },
150
+
151
+ "metricFormat": {
152
+ "type": "object",
153
+ "description": "Formula-result format. OMIT for Auto — inherits the first input column's own formatter (currency/grouping).",
154
+ "properties": {
155
+ "style": { "type": "string", "enum": ["number", "percent"] },
156
+ "decimals": { "type": "integer", "minimum": 0 }
157
+ },
158
+ "additionalProperties": false
159
+ },
160
+
161
+ "chartConfig": {
162
+ "type": "object",
163
+ "description": "Chart panel config. The chart kind is `chartType`; the panel `vizType` is always `chart`.",
164
+ "required": ["chartType", "categoryCol", "valueCol"],
165
+ "properties": {
166
+ "chartType": {
167
+ "type": "string",
168
+ "enum": ["bar", "horizontalBar", "stackedBar", "combo", "line", "area", "pie", "doughnut", "scatter", "bubble", "funnel", "heatmap"]
169
+ },
170
+ "categoryCol": { "type": "string" },
171
+ "valueCol": { "type": "string" },
172
+ "agg": { "$ref": "#/$defs/aggFunc" },
173
+ "seriesCol": { "type": "string", "description": "Split-by dimension (same dataset)." },
174
+ "sizeCol": { "type": "string", "description": "Bubble radius column." },
175
+ "chartSize": { "type": "string", "enum": ["sm", "m", "l", "xl"] },
176
+ "clickAction": { "type": "string", "enum": ["crossFilter", "drillThrough", "none"] },
177
+ "showTrend": { "type": "boolean" },
178
+ "series": {
179
+ "description": "CROSS-SOURCE overlay series (bar/horizontalBar/line/area) — a single series OR an array. Each aligns on the shared category axis.",
180
+ "oneOf": [
181
+ { "$ref": "#/$defs/chartSeries" },
182
+ { "type": "array", "items": { "$ref": "#/$defs/chartSeries" } }
183
+ ]
184
+ }
185
+ },
186
+ "additionalProperties": false
187
+ },
188
+
189
+ "chartSeries": {
190
+ "type": "object",
191
+ "description": "One cross-source overlay series.",
192
+ "required": ["categoryCol", "valueCol", "agg"],
193
+ "properties": {
194
+ "source": { "type": "string", "description": "Sibling dataset code; omit = the panel's own dataset." },
195
+ "categoryCol": { "type": "string" },
196
+ "valueCol": { "type": "string" },
197
+ "agg": { "$ref": "#/$defs/aggFunc" },
198
+ "label": { "type": "string" }
199
+ },
67
200
  "additionalProperties": false
68
201
  },
69
202
 
@@ -140,11 +273,13 @@
140
273
  "leafKey": { "type": "string", "description": "Column on the query entity identifying the tree node a row belongs to (e.g. 'account_id' on balance_register)." },
141
274
  "measures": {
142
275
  "type": "array",
276
+ "minItems": 1,
143
277
  "items": { "type": "string" },
144
278
  "description": "Value column codes (on the query entity) to SUM into ancestors. Must be additively-rollable."
145
279
  },
146
280
  "labels": {
147
281
  "type": "array",
282
+ "minItems": 1,
148
283
  "items": { "type": "string" },
149
284
  "description": "Node-describing columns, expressed as the report column keys ('account.account_code'). Sourced from the tree entity's physical column (the segment after the dot); emitted under the same key so the report layout is unchanged."
150
285
  },