@dforge-core/dforge-mcp 0.2.32 → 0.2.33

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,19 @@ 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
+ ## Unreleased
8
+
9
+ **`isView` / `viewSql` are gone** (dForge-core#1312). SQL-view entities were in the
10
+ entity schema and the references but never built: the entity installed as an empty table,
11
+ and passed `dforge_module_validate` on the way. They are now rejected, and will not be built.
12
+
13
+ - `dforge://schema/entity` drops both keys, so an editor flags them. Re-vendored from
14
+ `@dforge-core/metadata` — needs the metadata release that carries the change.
15
+ - `dforge_module_validate` reports them through the CLI's static checks — needs the CLI
16
+ release that carries `ViewEntityValidator`.
17
+ - The references say why, and what to use instead: a data view, a `G` total, the Query
18
+ Builder, or a stored-procedure report.
19
+
7
20
  ## 0.2.32
8
21
 
9
22
  **`auditHistory` levels in the vendored schemas were wrong.** The
package/dist/server.js CHANGED
@@ -31002,7 +31002,7 @@ var import_node_crypto = require("crypto");
31002
31002
  var fs2 = __toESM(require("fs"));
31003
31003
  var path2 = __toESM(require("path"));
31004
31004
 
31005
- // node_modules/.pnpm/@dforge-core+dforge-cli@0.2.25/node_modules/@dforge-core/dforge-cli/dist/lib.mjs
31005
+ // node_modules/.pnpm/@dforge-core+dforge-cli@0.2.26/node_modules/@dforge-core/dforge-cli/dist/lib.mjs
31006
31006
  function buildManifest(opts, moduleId) {
31007
31007
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
31008
31008
  const manifest = {
@@ -31285,7 +31285,7 @@ function buildZedTasks() {
31285
31285
  var fs = __toESM(require("fs"));
31286
31286
  var path = __toESM(require("path"));
31287
31287
 
31288
- // node_modules/.pnpm/@dforge-core+metadata@0.0.32/node_modules/@dforge-core/metadata/dist/index.js
31288
+ // node_modules/.pnpm/@dforge-core+metadata@0.0.33/node_modules/@dforge-core/metadata/dist/index.js
31289
31289
  var AggType = {
31290
31290
  Sum: "sum",
31291
31291
  Count: "count",
@@ -34597,7 +34597,7 @@ var path10 = __toESM(require("path"));
34597
34597
  var fs7 = __toESM(require("fs"));
34598
34598
  var path9 = __toESM(require("path"));
34599
34599
 
34600
- // node_modules/.pnpm/@dforge-core+metadata@0.0.32/node_modules/@dforge-core/metadata/dist/dsl/index.js
34600
+ // node_modules/.pnpm/@dforge-core+metadata@0.0.33/node_modules/@dforge-core/metadata/dist/dsl/index.js
34601
34601
  var PUNCT3 = ["===", "!=="];
34602
34602
  var PUNCT2 = [
34603
34603
  "==",
package/package.json CHANGED
@@ -1,49 +1,47 @@
1
1
  {
2
- "name": "@dforge-core/dforge-mcp",
3
- "version": "0.2.32",
4
- "description": "MCP server for dForge module authoring. Exposes 35 scaffold/patch/validate/pack/install tools and schema resources so AI agents (Claude Code, Cursor, Zed) can create and ship dForge modules.",
5
- "license": "MIT",
6
- "homepage": "https://github.com/iash44/dForge-core",
7
- "packageManager": "pnpm@11.22.0+sha512.1ff870c4c6133dfd88fb2afc46dd13d47f09c9794b438c6fdb47ca98caf3bc16381ee0be93a091b8e3824cf01f889f46d7d9e20910fb0be1ab0fb5baa80dd621",
8
- "repository": {
9
- "type": "git",
10
- "url": "git+https://github.com/dforge-core/dforge-mcp.git"
11
- },
12
- "bin": {
13
- "dforge-mcp": "dist/server.js",
14
- "dforge-install-skills": "scripts/install-skills.mjs"
15
- },
16
- "files": [
17
- "dist/",
18
- "docs/",
19
- "resources/",
20
- "skills/",
21
- "scripts/install-skills.mjs",
22
- "README.md",
23
- "CHANGELOG.md"
24
- ],
25
- "main": "dist/server.js",
26
- "engines": {
27
- "node": ">=18"
28
- },
29
- "scripts": {
30
- "build": "tsup",
31
- "sync-schemas": "node scripts/vendor-schemas.cjs",
32
- "prepublishOnly": "node scripts/vendor-schemas.cjs && tsup",
33
- "typecheck": "tsc --noEmit",
34
- "test": "vitest run",
35
- "install-skills": "node scripts/install-skills.mjs"
36
- },
37
- "dependencies": {
38
- "@dforge-core/dforge-cli": "^0.2.25",
39
- "@dforge-core/metadata": "^0.0.32",
40
- "@modelcontextprotocol/sdk": "^1.30.0",
41
- "zod": "^4.4.3"
42
- },
43
- "devDependencies": {
44
- "@types/node": "^26.2.0",
45
- "tsup": "^8.5.1",
46
- "typescript": "^6.0.3",
47
- "vitest": "^4.1.10"
48
- }
49
- }
2
+ "name": "@dforge-core/dforge-mcp",
3
+ "version": "0.2.33",
4
+ "description": "MCP server for dForge module authoring. Exposes 35 scaffold/patch/validate/pack/install tools and schema resources so AI agents (Claude Code, Cursor, Zed) can create and ship dForge modules.",
5
+ "license": "MIT",
6
+ "homepage": "https://github.com/iash44/dForge-core",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/dforge-core/dforge-mcp.git"
10
+ },
11
+ "bin": {
12
+ "dforge-mcp": "dist/server.js",
13
+ "dforge-install-skills": "scripts/install-skills.mjs"
14
+ },
15
+ "files": [
16
+ "dist/",
17
+ "docs/",
18
+ "resources/",
19
+ "skills/",
20
+ "scripts/install-skills.mjs",
21
+ "README.md",
22
+ "CHANGELOG.md"
23
+ ],
24
+ "main": "dist/server.js",
25
+ "engines": {
26
+ "node": ">=18"
27
+ },
28
+ "dependencies": {
29
+ "@dforge-core/dforge-cli": "^0.2.26",
30
+ "@dforge-core/metadata": "^0.0.33",
31
+ "@modelcontextprotocol/sdk": "^1.30.0",
32
+ "zod": "^4.4.3"
33
+ },
34
+ "devDependencies": {
35
+ "@types/node": "^26.2.0",
36
+ "tsup": "^8.5.1",
37
+ "typescript": "^6.0.3",
38
+ "vitest": "^4.1.10"
39
+ },
40
+ "scripts": {
41
+ "build": "tsup",
42
+ "sync-schemas": "node scripts/vendor-schemas.cjs",
43
+ "typecheck": "tsc --noEmit",
44
+ "test": "vitest run",
45
+ "install-skills": "node scripts/install-skills.mjs"
46
+ }
47
+ }
@@ -512,7 +512,7 @@ Two halves, both required:
512
512
 
513
513
  **`"default"` is the one exempt name** and means "no view" (full column set). It is what the ~100 shipped folder entries write, what `FolderExporter` writes back for a NULL `view_name`, and what the runtime auto-creates (column-less) for an entity reached without a folder binding — so rejecting it would fail every install. A module that really declares a view named `default` still gets it bound.
514
514
 
515
- Don't confuse the three things called "view": an **entity view** (`views`, this section) is column security; a **data view** (`ui/data_views.json`, referenced by a menu's `dataViewCode`) is a grid/kanban/calendar; `isView` + `viewSql` on an entity means it is backed by a SQL view. `folders.json`'s `viewName` binds the first.
515
+ Don't confuse the two things called "view": an **entity view** (`views`, this section) is column security; a **data view** (`ui/data_views.json`, referenced by a menu's `dataViewCode`) is a grid/kanban/calendar. `folders.json`'s `viewName` binds the first. An entity is never backed by a SQL view — `isView` / `viewSql` are rejected; use a data view, a report or a stored procedure instead.
516
516
 
517
517
  ## Column Domains (`domains.json`)
518
518
 
@@ -2,7 +2,7 @@
2
2
  "$schema": "http://json-schema.org/draft-07/schema#",
3
3
  "$id": "https://dforge.dev/schemas/entity.schema.json",
4
4
  "title": "dForge Entity Definition",
5
- "description": "Defines an entity (table/view mapping) for a dForge module",
5
+ "description": "Defines an entity (a table) for a dForge module",
6
6
  "type": "object",
7
7
  "anyOf": [
8
8
  { "required": ["fields"] },
@@ -24,16 +24,7 @@
24
24
  },
25
25
  "dbObject": {
26
26
  "type": "string",
27
- "description": "Database table or view name (defaults to entity code)"
28
- },
29
- "isView": {
30
- "type": "boolean",
31
- "description": "When true, entity maps to a SQL view (read-only, no DDL generation). Default: false (table-backed).",
32
- "default": false
33
- },
34
- "viewSql": {
35
- "type": "string",
36
- "description": "SQL SELECT statement for view-backed entities (isView=true). Executed as CREATE OR REPLACE VIEW during module install."
27
+ "description": "Database table name (defaults to entity code)"
37
28
  },
38
29
  "toString": {
39
30
  "description": "Display pattern using column placeholders, e.g. \"{first_name} {last_name}\" — the caption of a record wherever it is referenced. Every `{placeholder}` must name a field of the entity (trait columns included) and not a set; pack and install fail otherwise. Omitted, the install generates one from the fields and warns. Not declared on extension entities (with `extends`). No `type` constraint here because `toString` collides with Object.prototype.toString in JSON validators — they read the inherited function and reject it, even when the property is absent from the JSON."
@@ -151,7 +142,7 @@
151
142
  },
152
143
  "views": {
153
144
  "type": "object",
154
- "description": "Entity views keyed by view name — column-level security. Unrelated to 'isView'/'viewSql' (a SQL-view-backed entity) and to ui/data_views.json (grids, kanban, calendars). A folder binds one view per entity via ui/folders.json (entities.<code>.viewName); users working in that folder see ONLY the columns the view lists. Entities without views show the entity's full column set; a folder naming a view that isn't declared here FAILS the install, since resolving it to nothing would show every column \u2014 the opposite of what naming a view asks for. A view can only be declared by the entity's own module: an extension ('extends') declaring 'views' is rejected, because a view lists the complete column set and an extension knows only the columns it adds.",
145
+ "description": "Entity views keyed by view name — column-level security. Unrelated to ui/data_views.json (grids, kanban, calendars). A folder binds one view per entity via ui/folders.json (entities.<code>.viewName); users working in that folder see ONLY the columns the view lists. Entities without views show the entity's full column set; a folder naming a view that isn't declared here FAILS the install, since resolving it to nothing would show every column \u2014 the opposite of what naming a view asks for. A view can only be declared by the entity's own module: an extension ('extends') declaring 'views' is rejected, because a view lists the complete column set and an extension knows only the columns it adds.",
155
146
  "propertyNames": {
156
147
  "pattern": "^[a-zA-Z_][a-zA-Z0-9_-]*$",
157
148
  "maxLength": 100
@@ -32,9 +32,9 @@
32
32
  },
33
33
  "views": {
34
34
  "type": "object",
35
- "description": "Data view code → label.",
35
+ "description": "Data view code → label and description (the subtitle under the view title).",
36
36
  "additionalProperties": {
37
- "$ref": "#/$defs/labelOnly"
37
+ "$ref": "#/$defs/labelDesc"
38
38
  }
39
39
  },
40
40
  "menus": {
@@ -60,8 +60,7 @@ correct: a data view describes the presentation, and the folder's entity view de
60
60
  what a user in that folder is allowed to see of it. The grid renders whichever
61
61
  columns survive the view — you do not maintain one data view per role.
62
62
 
63
- Entity views are also unrelated to the two other things called "view" here: a *data
64
- view* (`ui/data_views.json`) is a grid/kanban/calendar, and `isView` + `viewSql` on an
65
- entity means it is backed by a SQL view.
63
+ Entity views are also unrelated to the other thing called "view" here: a *data view*
64
+ (`ui/data_views.json`) is a grid/kanban/calendar.
66
65
 
67
66
  See `dforge://reference/security` → Column-level security for the full rules.
@@ -4,7 +4,7 @@ Data views define how users see and interact with entity data. One entity can ha
4
4
 
5
5
  Lives in: `ui/data_views.json`
6
6
 
7
- > **Not to be confused with entity views.** An *entity view* (`views` on an entity file) is column-level **security** — which columns a folder may see at all — and is what `folders.json`'s `viewName` binds. A *data view* is a presentation of an entity, referenced by a menu's `dataViewCode`. A third thing, `isView` + `viewSql` on an entity, means the entity is backed by a SQL view. See `security.md` → Column-level security.
7
+ > **Not to be confused with entity views.** An *entity view* (`views` on an entity file) is column-level **security** — which columns a folder may see at all — and is what `folders.json`'s `viewName` binds. A *data view* is a presentation of an entity, referenced by a menu's `dataViewCode`. See `security.md` → Column-level security.
8
8
 
9
9
  ## Structure
10
10
 
@@ -318,16 +318,17 @@ Each of these is an install-time error, and each is silent at runtime if it slip
318
318
 
319
319
  `"viewName": "default"` means **no view** (full column set) and declares nothing. It is what every shipped module writes, and what the runtime auto-creates for an entity reached without a folder binding — so it is exempt from the checks above. A module that really declares a view named `default` still gets it bound.
320
320
 
321
- ### Don't confuse the three "views"
321
+ ### Don't confuse the two "views"
322
322
 
323
323
  | Term | Where | What it is |
324
324
  |---|---|---|
325
325
  | **Entity view** | `entities/*.json` → `views` | Column-level security (this section) |
326
326
  | **Data view** | `ui/data_views.json` | A grid / kanban / calendar over an entity (`data-views.md`) |
327
- | **SQL view** | `entities/*.json` → `isView` + `viewSql` | An entity backed by a SQL view instead of a table |
328
327
 
329
328
  `viewName` in `folders.json` binds the first. Menus' `dataViewCode` references the second.
330
329
 
330
+ There is no SQL-view entity. `isView` / `viewSql` are rejected at validate, pack and install: a view entity would duplicate the source entity's metadata, break when that module changes a column, and read around its row and column security. For a read-only slice use a data view (nav paths, `F` columns), a `G` total, the Query Builder, or a stored-procedure report — the last is the one way to show users a slice of an entity they have no rights on, behind an explicit `sp:` grant.
331
+
331
332
  ### When to use subfolders
332
333
 
333
334
  - **Multi-location modules** (warehouses, offices, branches) — one subfolder per location, filtered by location FK
@@ -38,7 +38,7 @@ Translation files mirror the module's content structure. Each translatable objec
38
38
  "crm.sales-rep": { "label": "Sales Representative" }
39
39
  },
40
40
  "views": {
41
- "contacts": { "label": "Contacts" },
41
+ "contacts": { "label": "Contacts", "desc": "People associated with customers" },
42
42
  "contacts_list": { "label": "Contact List" },
43
43
  "contacts_gallery": { "label": "Contact Cards" }
44
44
  },
@@ -80,7 +80,7 @@ Translation files mirror the module's content structure. Each translatable objec
80
80
  | `entities` | Entity labels (`label`, `desc`) and all field labels | Entity codes → `{ label, desc, fields: { field_code: { label } } }` |
81
81
  | `folders` | Folder labels | Folder codes (root folder key from `ui/folders.json`) |
82
82
  | `roles` | Role display labels | Role codes (keys from `security/roles.json`, already module-qualified — e.g. `crm.admin`) → `{ label }` |
83
- | `views` | Data view labels | View codes (keys from `ui/data_views.json`) |
83
+ | `views` | Data view labels and descriptions (`label`, `desc`) | View codes (keys from `ui/data_views.json`) → `{ label, desc }` |
84
84
  | `menus` | Menu node labels (root + nested items) | Menu root key → `{ label, items: { item_code: { label } } }` matching `ui/menus.json` structure |
85
85
  | `actions` | Action labels, descriptions, param labels **and param dropdown option labels** | Action codes (keys from `ui/actions.json`) → `{ label, desc, params: { param_cd: { label, options: { value: … } } } }` |
86
86
  | `reports` | Report dataset captions, param labels **and param dropdown option labels** | Report codes → `{ datasets: { ds_cd: { caption } }, params: { param_cd: { label, options: { value: … } } } }` |
@@ -242,7 +242,7 @@ If you include these sections, the install succeeds (they're silently ignored)
242
242
  "crm.sales-rep": { "label": "Vertriebsmitarbeiter" }
243
243
  },
244
244
  "views": {
245
- "contacts": { "label": "Kontakte" }
245
+ "contacts": { "label": "Kontakte", "desc": "Personen, die mit Kunden verknüpft sind" }
246
246
  },
247
247
  "menus": {
248
248
  "crm_menu": {