This is an automated email from the ASF dual-hosted git repository. asf-gitbox-commits pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/cayenne.git
commit a5d3f88806a119f2445a8de70dbe0cc7574ff809 Author: Andrus Adamchik <[email protected]> AuthorDate: Sun May 24 11:50:54 2026 -0400 CAY-2949 CayenneModeler MCP: dbimport_run tool docs --- ai-plugin/references/datamap-schema.md | 2 +- ai-plugin/references/dbimport-config.md | 8 +-- ai-plugin/references/mcp-tools.md | 64 +++++++++++++++++- ai-plugin/skills/cayenne-reverse-engineer/SKILL.md | 75 +++++++++++++++------- .../asciidoc/_cayenne-guide/part3/mcpTools.adoc | 34 +++++++++- .../modeler/ui/dbgen/DBGeneratorOptionsDialog.java | 2 +- .../modeler/ui/dbmerge/MergerOptionsDialog.java | 2 +- 7 files changed, 155 insertions(+), 32 deletions(-) diff --git a/ai-plugin/references/datamap-schema.md b/ai-plugin/references/datamap-schema.md index c38e59fd7..d1149f467 100644 --- a/ai-plugin/references/datamap-schema.md +++ b/ai-plugin/references/datamap-schema.md @@ -240,7 +240,7 @@ A separate namespace, embedded directly in the DataMap. See `cgen-config.md` for ## `<dbImport>` — embedded reverse-engineering config -A separate namespace, used by the Modeler's reverse-engineering wizard to persist its options. See `dbimport-config.md` for fields. +A separate namespace, used by the Modeler's reverse-engineering dialog to persist its options. See `dbimport-config.md` for fields. ## Anti-patterns to avoid diff --git a/ai-plugin/references/dbimport-config.md b/ai-plugin/references/dbimport-config.md index 9dd3beacb..e7cad14bf 100644 --- a/ai-plugin/references/dbimport-config.md +++ b/ai-plugin/references/dbimport-config.md @@ -18,7 +18,7 @@ --> # Reverse-engineering config (`<dbImport>`) -Reference for the options shown by the CayenneModeler reverse-engineering wizard, persisted as a `<dbImport>` block inside a DataMap. +Reference for the options shown by the CayenneModeler reverse-engineering dialog, persisted as a `<dbImport>` block inside a DataMap. ## XML shape (persisted inside a DataMap) @@ -87,16 +87,16 @@ Reference for the options shown by the CayenneModeler reverse-engineering wizard | `<forceDataMapCatalog>` | boolean | `false` | When `true`, every imported DbEntity is tagged with the DataMap's catalog, overriding the DB's reported value. Use only when the DB catalog reported by JDBC is wrong or noisy. | | `<forceDataMapSchema>` | boolean | `false` | Same as above for schema. | -## How the Modeler wizard maps to these fields +## How the Modeler dialog maps to these fields -Walking the **Tools → Reengineer Database Schema** wizard, the screens correspond to: +Walking the **Tools → Reengineer Database Schema** dialog, the screens correspond to: 1. **Datasource** — JDBC connection (adapter, driver, URL, user/password). Not stored in `<dbImport>`; it's a one-shot connection. 2. **Configure** — filter tables/columns/procedures. Maps to `<includeTable>`, `<excludeTable>`, `<tableTypes>`, etc. 3. **Naming** — `<namingStrategy>`, `<stripFromTableNames>`, `<defaultPackage>`, `<meaningfulPkTables>`. 4. **Other options** — checkboxes for `skipPrimaryKeyLoading`, `skipRelationshipsLoading`, `forceDataMapCatalog`, `forceDataMapSchema`, `useJava7Types`. -After running the wizard, the chosen settings are persisted as a `<dbImport>` block in the DataMap so subsequent re-imports re-use them. +After running the dialog, the chosen settings are persisted as a `<dbImport>` block in the DataMap so subsequent re-imports re-use them. ## Re-running an import diff --git a/ai-plugin/references/mcp-tools.md b/ai-plugin/references/mcp-tools.md index f0a61506e..da7dc8631 100644 --- a/ai-plugin/references/mcp-tools.md +++ b/ai-plugin/references/mcp-tools.md @@ -64,6 +64,66 @@ Surface the `summary` to the user verbatim. List the first few `writtenFiles` pa **Source:** `cayenne-mcp-server/src/main/java/org/apache/cayenne/mcp/tools/cgen/CgenRunTool.java`. +## Tool: `dbimport_run` + +Runs Cayenne reverse-engineering (dbimport) for one DataMap. Reads the JDBC connection from the DBConnector that CayenneModeler stored in preferences when the user last ran the reverse-engineering dialog for this DataMap. If the DataMap has a `<reverse-engineering>` block its filters are applied; otherwise the full database schema is imported. Rewrites the DataMap XML on disk with the merged schema. + +**Arguments:** + +| Name | Type | Required | Description | +|---|---|---|---| +| `projectPath` | string | yes | Absolute path to the top-level Cayenne project descriptor (`cayenne-*.xml`), **not** a DataMap file. | +| `dataMap` | string | yes | Name of the target DataMap as it appears in the `<map name="...">` element of the project descriptor. Not a file path. | + +JDBC URL, driver, and credentials are **not** arguments — they come from CayenneModeler preferences. Schema filters come from the DataMap's `<reverse-engineering>` block if present. + +**Returns:** JSON object with fields: + +```json +{ + "status": "imported | up_to_date | validation_failed | error", + "summary": { + "tokensConsidered": 5, + "tokensApplied": 5, + "entitiesAdded": 3, + "entitiesRemoved": 0, + "entitiesModified": 2, + "relationshipsAdded": 4 + }, + "resolved": { + "dataMapFile": "/path/to/datamap.map.xml", + "jdbcUrl": "jdbc:postgresql://localhost/mydb", + "jdbcDriver": "org.postgresql.Driver", + "dbAdapter": "org.apache.cayenne.dba.postgres.PostgresAdapter" + }, + "warnings": [], + "validation": { + "projectFound": true, + "dataMapFound": true, + "dbConnectorPresent": true, + "jdbcDriverLoadable": true, + "jdbcConnectionOpened": true + }, + "error": null +} +``` + +Surface the `summary` to the user. If `status` is `imported`, report entity/relationship counts. If `up_to_date`, nothing changed. Show `warnings` if non-empty; they are `WARN`-level log lines captured from the dbsync engine. + +**Failure modes:** + +| Error code | Meaning | Remediation | +|---|---|---| +| `project_not_found` | `projectPath` not readable | Verify path. | +| `project_parse_failed` | Not a valid Cayenne project descriptor | Confirm the file is a `cayenne-*.xml`. | +| `datamap_not_found` | No matching DataMap name; error message lists available names | Correct the `dataMap` argument. | +| `dbconnector_not_configured` | No DBConnector stored in preferences for this DataMap | Open the Modeler via `open_project`, run the Modeler's reverse-engineering dialog once to save the connection, then re-run `dbimport_run`. | +| `jdbc_driver_not_loadable` | Driver class not on CayenneModeler's classpath | Open CayenneModeler → Preferences → Classpath, add the JDBC driver jar, save, then re-run. | +| `jdbc_connection_failed` | Connection could not be opened | Check JDBC URL, credentials, and network access. | +| `dbimport_runtime_error` | Import started but threw mid-run | Check the error message; `summary` shows counts captured before the failure. | + +**Source:** `cayenne-mcp-server/src/main/java/org/apache/cayenne/mcp/tools/dbimport/DbImportRunTool.java`. + ## Tool: `open_project` Launches CayenneModeler with a project file pre-loaded. @@ -83,7 +143,7 @@ Launches CayenneModeler with a project file pre-loaded. **Returns:** JSON object with `status` (`ok` / `error`), and on error a `code` indicating the failure (e.g., `modeler_not_found`, `project_not_found`, `handshake_timeout`). -**When to call:** for reverse-engineering workflows (drives the user through the Modeler's import wizard), bulk visual editing, or when the user explicitly asks to open the Modeler. +**When to call:** for reverse-engineering workflows (drives the user through the Modeler's import dialog), bulk visual editing, or when the user explicitly asks to open the Modeler. **Don't call it** as a fallback for simple XML edits — direct edits via the `cayenne-modeling` skill are faster and don't require the user to switch context. @@ -91,7 +151,7 @@ Launches CayenneModeler with a project file pre-loaded. ## Detecting whether the server is connected -The MCP tools surface in this session under names `mcp__cayenne__cgen_run` and `mcp__cayenne__open_project`. If they are not in the available tools, the server is not registered. +The MCP tools surface in this session under names `mcp__cayenne__cgen_run`, `mcp__cayenne__open_project`, and `mcp__cayenne__dbimport_run`. If they are not in the available tools, the server is not registered. When unavailable: diff --git a/ai-plugin/skills/cayenne-reverse-engineer/SKILL.md b/ai-plugin/skills/cayenne-reverse-engineer/SKILL.md index 0c6d8dcbc..9f5654c13 100644 --- a/ai-plugin/skills/cayenne-reverse-engineer/SKILL.md +++ b/ai-plugin/skills/cayenne-reverse-engineer/SKILL.md @@ -1,6 +1,6 @@ --- name: cayenne-reverse-engineer -description: "Use this skill whenever the user wants to import database schema metadata into a Cayenne DataMap — full-schema sync from a live DB. Trigger on phrases like 'reverse engineer the database', 'import the schema', 'generate a DataMap from my DB', 'sync the model with the database', 'add the new tables from the DB', 'import the customer table', 'pick up the latest schema changes', 'create entities from these tables', or any request that involves reading database metadata to popu [...] +description: "Use this skill whenever the user wants to import database schema metadata into a Cayenne DataMap — full-schema sync from a live DB. Trigger on phrases like 'reverse engineer the database', 'import the schema', 'generate a DataMap from my DB', 'sync the model with the database', 'add the new tables from the DB', 'import the customer table', 'pick up the latest schema changes', 'create entities from these tables', or any request that involves reading database metadata to popu [...] --- <!-- @@ -23,13 +23,13 @@ description: "Use this skill whenever the user wants to import database schema m --> # cayenne-reverse-engineer -Import a database schema into a Cayenne DataMap by driving the CayenneModeler's reverse-engineering wizard through MCP. Cayenne 5.0 does not yet expose reverse engineering as a direct MCP tool, so the workflow launches the GUI and walks the user through the wizard. +Import a database schema into a Cayenne DataMap using the `mcp__cayenne__dbimport_run` MCP tool. If a DBConnector is already stored in preferences for the DataMap the import runs directly without any GUI interaction. When the connection has not been configured yet, the workflow launches CayenneModeler and walks the user through the dialog once to save the connection, then re-runs `dbimport_run`. ## Required reading - `${CLAUDE_PLUGIN_ROOT}/references/project-layout.md` — locate or create the project descriptor. -- `${CLAUDE_PLUGIN_ROOT}/references/dbimport-config.md` — the field semantics behind every wizard screen, so you can explain options in user terms. -- `${CLAUDE_PLUGIN_ROOT}/references/mcp-tools.md` — `open_project` tool reference and behavior when MCP is not connected. +- `${CLAUDE_PLUGIN_ROOT}/references/dbimport-config.md` — field semantics for every dialog screen, so you can explain options in user terms. +- `${CLAUDE_PLUGIN_ROOT}/references/mcp-tools.md` — `dbimport_run` and `open_project` tool references and failure modes. ## Step 1 — Confirm scope @@ -44,21 +44,49 @@ Follow `project-layout.md` to find the existing `cayenne-*.xml`. If none exists, - Either generate a minimal descriptor first (use `cayenne-modeling`'s patterns — namespace `http://cayenne.apache.org/schema/12/domain`, `project-version="12"`, one empty `<map name="..."/>` plus a sibling empty `*.map.xml`), or - Tell the user to use **File → New Project** inside the Modeler once it's open. -The descriptor path needs to be **absolute** when passed to `open_project`. +The descriptor path needs to be **absolute** when passed to the MCP tools. -## Step 3 — Launch the Modeler +## Step 3 — Run `dbimport_run` Call the MCP tool: ``` -mcp__cayenne__open_project({ "projectPath": "<absolute path to cayenne-*.xml>" }) +mcp__cayenne__dbimport_run({ "projectPath": "<absolute path to cayenne-*.xml>", "dataMap": "<DataMap name>" }) ``` If the tool is not available (server not registered), surface `cayenne-mcp-server/README.md` and stop. **Do not** suggest `mvn cayenne:cdbimport` or any Gradle equivalent — those build plugins are out of scope. -If `open_project` returns a non-`ok` status, surface the error code and message; common ones are `modeler_not_found`, `project_not_found`, `handshake_timeout`. Don't retry blindly — diagnose first. +### Interpreting the result + +- **`imported`** — success. Surface the `summary` counters (entities added/removed/modified, relationships added) to the user. +- **`up_to_date`** — the DataMap already matches the database. Tell the user nothing changed. +- **`error`** — import started but failed mid-run. Show the `error.message` and the partial `summary`. +- **`validation_failed`** — a pre-flight check failed. Use the `error.code` to guide next steps (see below). + +### Validation failures and their remediation + +| Code | What failed | What to do | +|---|---|---| +| `project_not_found` | Project path not readable | Verify path. | +| `project_parse_failed` | File is not a valid Cayenne descriptor | Confirm the file is a `cayenne-*.xml`. | +| `datamap_not_found` | DataMap name not in project | The error message lists available names; use one. | +| `dbconnector_not_configured` | No connection saved for this DataMap | → Go to **Step 4** to configure via the Modeler dialog. | +| `jdbc_driver_not_loadable` | Driver jar not on the Modeler classpath | Open CayenneModeler → Preferences → Classpath, add the driver jar, save, then re-run. | +| `jdbc_connection_failed` | Connection could not be opened | Check JDBC URL, credentials, and network access. | + +## Step 4 — Configure the connection (first-time only) + +This step is only needed when `dbimport_run` returns `dbconnector_not_configured`. + +### 4a — Launch the Modeler -## Step 4 — Walk the user through the wizard +``` +mcp__cayenne__open_project({ "projectPath": "<absolute path to cayenne-*.xml>" }) +``` + +If `open_project` returns a non-`ok` status, surface the error code; common ones are `modeler_not_found`, `project_not_found`, `handshake_timeout`. Don't retry blindly — diagnose first. + +### 4b — Walk the user through the dialog The user now has the Modeler open. Give them the exact GUI sequence: @@ -67,32 +95,35 @@ The user now has the Modeler open. Give them the exact GUI sequence: - **JDBC Driver** — e.g., `org.postgresql.Driver` - **DB URL** — full JDBC URL - **User Name / Password** — credentials - - **Cayenne Adapter** (optional, autodetected for known DBs) — e.g., `org.apache.cayenne.dba.postgres.PostgresAdapter` + - **Cayenne Adapter** (optional, autodetected for known DBs) - Click **Test Connection**, then **Continue**. 3. **Configure** screen — set table/column/procedure filters: - Include/exclude regex patterns under the relevant catalog/schema. - - **Table Types** — usually leave at `TABLE`; add `VIEW` if the user wants views imported. + - **Table Types** — usually `TABLE`; add `VIEW` if needed. 4. **Naming** screen: - - **Naming Strategy** — usually the default (`DefaultObjectNameGenerator`). - - **Strip from Table Names** — regex to strip a prefix like `^TBL_`. - - **Default Package** — Java package for generated ObjEntity classes. - - **Meaningful PK Tables** — regex (or `*`) for tables whose PK columns should be exposed as ObjAttributes. Leave empty unless the user needs PK visibility. -5. **Other Options** — toggles for `skipPrimaryKeyLoading`, `skipRelationshipsLoading`, `forceDataMapCatalog`, `forceDataMapSchema`, `useJava7Types`. See `dbimport-config.md` for what each does; defaults are usually right. -6. Click **Save** then **Run Import**. The Modeler runs the import and reports a diff (added/changed/removed entities). + - **Naming Strategy**, **Strip from Table Names**, **Default Package**, **Meaningful PK Tables**. + - See `dbimport-config.md` for what each does. +5. **Other Options** — toggles for `skipPrimaryKeyLoading`, `skipRelationshipsLoading`, etc. +6. Click **Save** (not **Run Import** — the goal here is to save the connection, not run the import through the GUI). + +After the user saves, the DBConnector is written to CayenneModeler preferences. + +### 4c — Re-run `dbimport_run` -Explain options as the user asks — `dbimport-config.md` has the semantics. When unsure, recommend the default. +Go back to **Step 3** and call `dbimport_run` again. This time it should find the saved connection and proceed. ## Step 5 — Confirm and follow up -Once the user reports the import is done and they've saved the project: +Once the import succeeds: -- Tell them to **save the project** in the Modeler (File → Save). The Modeler persists wizard settings as a `<dbImport>` block inside the DataMap for repeat runs. +- Tell the user to **save the project** in the Modeler if it is open (File → Save). The dialog settings persist as a `<dbImport>` block inside the DataMap for repeat runs. - Hand off to `cayenne-cgen` to regenerate Java classes for the new/changed entities. Quote the DataMap name so the cgen skill can pass it to `cgen_run`. - If the DB has columns that don't follow the user's preferred naming, recommend tweaking the naming strategy and re-running. ## Anti-patterns -- **Do not** suggest `mvn cayenne:cdbimport`, the Gradle `cdbimport` task, or hand-running the `cayenne-dbsync` Java APIs. The Modeler GUI is the only supported execution path here. -- **Do not** try to hand-write a DataMap from a DB schema description as a substitute for the wizard — the wizard handles JDBC types, PK detection, FK relationships, and naming consistently. Hand-rolling produces subtle mistakes. +- **Do not** suggest `mvn cayenne:cdbimport`, the Gradle `cdbimport` task, or hand-running the `cayenne-dbsync` Java APIs. `dbimport_run` is the only supported execution path. +- **Do not** try to hand-write a DataMap from a DB schema description as a substitute — the import handles JDBC types, PK detection, FK relationships, and naming consistently. Hand-rolling produces subtle mistakes. - **Do not** enable `forceDataMapCatalog` / `forceDataMapSchema` defensively. They suppress legitimate DB metadata and cause hard-to-debug issues in multi-catalog setups. - **Do not** offer reverse engineering without MCP — if the server isn't connected, point at `cayenne-mcp-server/README.md` and stop. +- **Do not** run the import through the Modeler GUI dialog when `dbimport_run` is available — the GUI path is only for the first-time connection setup. diff --git a/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part3/mcpTools.adoc b/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part3/mcpTools.adoc index 131c07f35..937989165 100644 --- a/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part3/mcpTools.adoc +++ b/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part3/mcpTools.adoc @@ -14,7 +14,7 @@ === MCP Tools -The server currently exposes two tools. Your agent will discover them on its own, but it is useful to understand the capabilities and possible prompts. Both tools operate on a Cayenne project descriptor (a `cayenne-*.xml` file) and take absolute paths - agents should resolve relative paths against the current workspace before invoking. +The server exposes three tools. Your agent will discover them on its own, but it is useful to understand the capabilities and possible prompts. All tools operate on a Cayenne project descriptor (a `cayenne-*.xml` file) and take absolute paths - agents should resolve relative paths against the current workspace before invoking. ==== open_project @@ -65,3 +65,35 @@ ____ regenerate Java classes from Cayenne model ____ + + +==== dbimport_run + +Runs Cayenne reverse engineering (dbimport) for a single DataMap inside the project. +The tool reads the JDBC connection from the DBConnector that CayenneModeler stored in preferences when the user last ran the reverse-engineering dialog for this DataMap. +If the DataMap has a `<reverse-engineering>` block its filters are applied; otherwise the full database schema is imported. +The DataMap XML is rewritten on disk with the merged schema, and a JSON summary of what changed is returned. + +JDBC credentials are not passed as arguments — they come from CayenneModeler preferences. +If no connection has been saved yet (`dbconnector_not_configured` error), open the project in the Modeler with `open_project`, run the dialog once to save the connection, then call `dbimport_run` again. + +.Parameters +[cols="1,1,3", options="header"] +|=== +| Name | Required | Description +| `projectPath` | yes | Absolute path to the top-level Cayenne project descriptor (`cayenne-*.xml`), not a DataMap file. +| `dataMap` | yes | Name of the target DataMap as it appears in the `<map name='...'>` element of the project descriptor. +|=== + +A typical agent prompt that triggers this tool: +[quote] +____ +sync the Cayenne model with the database +____ + +Or more specifically: +[quote] +____ +re-import the `MyDataMap` schema from the database into `/path/to/cayenne-project.xml` +____ + diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/dbgen/DBGeneratorOptionsDialog.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/dbgen/DBGeneratorOptionsDialog.java index 9e375e572..5ef71547e 100644 --- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/dbgen/DBGeneratorOptionsDialog.java +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/dbgen/DBGeneratorOptionsDialog.java @@ -69,7 +69,7 @@ import java.util.Collection; import java.util.Iterator; /** - * Modal wizard for generating the database from a set of DataMaps. Two tabs: SQL options + * Modal dialog for generating the database from a set of DataMaps. Two tabs: SQL options * (CRUD checkboxes + adapter + previewed SQL) and Tables (per-table include/exclude). */ public class DBGeneratorOptionsDialog extends ProjectDialog { diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/dbmerge/MergerOptionsDialog.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/dbmerge/MergerOptionsDialog.java index 233a4d577..03ca46d78 100644 --- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/dbmerge/MergerOptionsDialog.java +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/dbmerge/MergerOptionsDialog.java @@ -85,7 +85,7 @@ import java.util.LinkedList; import java.util.List; /** - * Modal wizard for altering the database schema to match a DataMap. Two tabs: + * Modal dialog for altering the database schema to match a DataMap. Two tabs: * Operations (per-token include/exclude via {@link MergerTokenSelector}) and Generated SQL. */ public class MergerOptionsDialog extends ProjectDialog {
