@restforgejs/mcp-server 1.2.0 → 1.2.2
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 +51 -8
- package/dist/server.js +71 -1
- package/dist/server.js.map +1 -1
- package/dist/tools/codegen/dbschema-apply.d.ts +2 -0
- package/dist/tools/codegen/dbschema-apply.js +324 -0
- package/dist/tools/codegen/dbschema-apply.js.map +1 -0
- package/dist/tools/codegen/dbschema-diff.d.ts +2 -0
- package/dist/tools/codegen/dbschema-diff.js +352 -0
- package/dist/tools/codegen/dbschema-diff.js.map +1 -0
- package/dist/tools/codegen/dbschema-generate-ddl.js +6 -3
- package/dist/tools/codegen/dbschema-generate-ddl.js.map +1 -1
- package/dist/tools/codegen/dbschema-init.js +9 -2
- package/dist/tools/codegen/dbschema-init.js.map +1 -1
- package/dist/tools/codegen/dbschema-introspect.js +25 -19
- package/dist/tools/codegen/dbschema-introspect.js.map +1 -1
- package/dist/tools/codegen/dbschema-migrate.js +55 -26
- package/dist/tools/codegen/dbschema-migrate.js.map +1 -1
- package/dist/tools/codegen/dbschema-models.js +11 -12
- package/dist/tools/codegen/dbschema-models.js.map +1 -1
- package/dist/tools/codegen/dbschema-template.d.ts +2 -0
- package/dist/tools/codegen/dbschema-template.js +384 -0
- package/dist/tools/codegen/dbschema-template.js.map +1 -0
- package/dist/tools/codegen/dbschema-validate.js +13 -13
- package/dist/tools/codegen/dbschema-validate.js.map +1 -1
- package/dist/tools/codegen/generate-payload.js +1 -1
- package/dist/tools/codegen/get-dbschema-catalog.js +4 -2
- package/dist/tools/codegen/get-dbschema-catalog.js.map +1 -1
- package/dist/tools/codegen/index.js +6 -0
- package/dist/tools/codegen/index.js.map +1 -1
- package/dist/tools/codegen/list-tables.js +4 -1
- package/dist/tools/codegen/list-tables.js.map +1 -1
- package/dist/tools/designer/generate.d.ts +2 -0
- package/dist/tools/designer/generate.js +212 -0
- package/dist/tools/designer/generate.js.map +1 -0
- package/dist/tools/designer/index.d.ts +2 -0
- package/dist/tools/designer/index.js +17 -0
- package/dist/tools/designer/index.js.map +1 -0
- package/dist/tools/designer/init-project.d.ts +2 -0
- package/dist/tools/designer/init-project.js +235 -0
- package/dist/tools/designer/init-project.js.map +1 -0
- package/dist/tools/designer/inspect-plugin.d.ts +2 -0
- package/dist/tools/designer/inspect-plugin.js +148 -0
- package/dist/tools/designer/inspect-plugin.js.map +1 -0
- package/dist/tools/designer/list-plugins.d.ts +2 -0
- package/dist/tools/designer/list-plugins.js +141 -0
- package/dist/tools/designer/list-plugins.js.map +1 -0
- package/dist/tools/designer/preview-files.d.ts +2 -0
- package/dist/tools/designer/preview-files.js +150 -0
- package/dist/tools/designer/preview-files.js.map +1 -0
- package/dist/tools/designer/scaffold-plugin.d.ts +2 -0
- package/dist/tools/designer/scaffold-plugin.js +162 -0
- package/dist/tools/designer/scaffold-plugin.js.map +1 -0
- package/dist/tools/designer/validate-payload.d.ts +2 -0
- package/dist/tools/designer/validate-payload.js +158 -0
- package/dist/tools/designer/validate-payload.js.map +1 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,12 +1,28 @@
|
|
|
1
1
|
# @restforgejs/mcp-server
|
|
2
2
|
|
|
3
|
-
MCP (Model Context Protocol) server for the RESTForge
|
|
3
|
+
MCP (Model Context Protocol) server for the RESTForge Platform. Exposes RESTForge capabilities to AI Agents (Claude Desktop, Cursor, Claude CLI, and other MCP clients) so agents can operate RESTForge through natural language without manually invoking CLI commands.
|
|
4
|
+
|
|
5
|
+
> **Scope Notice:** This MCP server is a thin orchestrator that exposes RESTForge Platform commands to AI agents via the Model Context Protocol. It is not a generic MCP framework, an API testing tool, an API client, or an HTTP request proxy. Its tools strictly invoke RESTForge Platform CLI commands; it does not consume or test arbitrary third-party APIs.
|
|
4
6
|
|
|
5
7
|
## Requirements
|
|
6
8
|
|
|
7
9
|
- Node.js >= 18
|
|
8
10
|
- npm >= 9
|
|
9
|
-
- For full setup workflow: PostgreSQL / MySQL / Oracle
|
|
11
|
+
- For full setup workflow: PostgreSQL / MySQL / Oracle, RESTForge license key
|
|
12
|
+
|
|
13
|
+
## Access & License
|
|
14
|
+
|
|
15
|
+
This MCP server package (`@restforgejs/mcp-server`) is distributed under the **MIT License** and may be installed and inspected freely.
|
|
16
|
+
|
|
17
|
+
The MCP server orchestrates the **RESTForge Platform** (`@restforgejs/platform`), which is **commercial software currently in closed evaluation**. Full workflow execution (setup validation, code generation, runtime launch) requires a valid RESTForge license key.
|
|
18
|
+
|
|
19
|
+
License key acquisition:
|
|
20
|
+
|
|
21
|
+
- **Early Access Program** — Limited slots for volunteer evaluators. Apply at [restforge.dev](https://restforge.dev)
|
|
22
|
+
- **Commercial Trial** — Coming soon. Register interest at [restforge.dev](https://restforge.dev)
|
|
23
|
+
- **Commercial License** — Available upon general release
|
|
24
|
+
|
|
25
|
+
Without a valid license key, MCP tools that depend on the platform runtime (e.g. `setup_validate_config`, `codegen_*`, `runtime_*`) will return authentication errors.
|
|
10
26
|
|
|
11
27
|
## Installation
|
|
12
28
|
|
|
@@ -24,7 +40,7 @@ After installation, the `restforge-mcp` command is available in PATH.
|
|
|
24
40
|
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | restforge-mcp
|
|
25
41
|
```
|
|
26
42
|
|
|
27
|
-
Output should list
|
|
43
|
+
Output should list 39 tools across the `health_*`, `setup_*`, `codegen_*`, and `runtime_*` domains.
|
|
28
44
|
|
|
29
45
|
### 2. Register with MCP Client
|
|
30
46
|
|
|
@@ -66,13 +82,13 @@ In your AI client chat, type prompts like:
|
|
|
66
82
|
|
|
67
83
|
> Generate a CRUD endpoint for the `customer` table
|
|
68
84
|
|
|
69
|
-
>
|
|
85
|
+
> Start my RESTForge project (the agent generates a launcher script for the user to execute)
|
|
70
86
|
|
|
71
87
|
The agent orchestrates the appropriate tools to fulfill the request end-to-end.
|
|
72
88
|
|
|
73
89
|
## Available Tools
|
|
74
90
|
|
|
75
|
-
|
|
91
|
+
39 tools organized by domain. AI agents call these via the MCP protocol; end users do not invoke them directly.
|
|
76
92
|
|
|
77
93
|
### Health Domain (1 tool)
|
|
78
94
|
|
|
@@ -94,12 +110,33 @@ The agent orchestrates the appropriate tools to fulfill the request end-to-end.
|
|
|
94
110
|
| `setup_get_config_schema` | Get JSON schema of all 63 parameters available in `db-connection.env` |
|
|
95
111
|
| `setup_get_init_template` | Get raw `db-connection.env` template content |
|
|
96
112
|
|
|
97
|
-
### Codegen Domain (
|
|
113
|
+
### Codegen Domain (23 tools)
|
|
114
|
+
|
|
115
|
+
Live database introspection:
|
|
98
116
|
|
|
99
117
|
| Tool | Description |
|
|
100
118
|
|------|-------------|
|
|
101
119
|
| `codegen_list_tables` | List all tables in the project's database (live introspection) |
|
|
102
120
|
| `codegen_describe_table` | Describe columns, primary key, and foreign keys of a specific table |
|
|
121
|
+
|
|
122
|
+
Schema-as-code (dbschema-kit / SDF):
|
|
123
|
+
|
|
124
|
+
| Tool | Description |
|
|
125
|
+
|------|-------------|
|
|
126
|
+
| `codegen_dbschema_init` | Create a new dbschema-kit schema definition skeleton file (minimal starter) |
|
|
127
|
+
| `codegen_dbschema_template` | Browse, preview, and generate from the Schema Reference collection (87 templates across 30+ domains) |
|
|
128
|
+
| `codegen_dbschema_validate` | Validate dbschema-kit definition files (single-model structure + cross-model FK checks) |
|
|
129
|
+
| `codegen_dbschema_models` | List dbschema-kit models with a structural summary (fields, keys, indexes, relations) |
|
|
130
|
+
| `codegen_dbschema_introspect` | Reverse-engineer an existing database into dbschema-kit definition files |
|
|
131
|
+
| `codegen_dbschema_generate_ddl` | Generate dialect-specific DDL (CREATE TABLE/INDEX, optional DROP) from dbschema-kit files |
|
|
132
|
+
| `codegen_dbschema_migrate` | Apply dbschema-kit files to a live database (load → validate → DDL → apply; DESTRUCTIVE with `drop=true`) |
|
|
133
|
+
| `codegen_dbschema_diff` | Detect schema drift between dbschema-kit files and the live database (read-only, bidirectional) |
|
|
134
|
+
| `codegen_dbschema_apply` | Resolve schema drift to the live database via incremental `ALTER` (additive-only by default; opt-in destructive) |
|
|
135
|
+
|
|
136
|
+
Payload, scaffolding, and SQL:
|
|
137
|
+
|
|
138
|
+
| Tool | Description |
|
|
139
|
+
|------|-------------|
|
|
103
140
|
| `codegen_generate_payload` | Generate payload JSON from a database table |
|
|
104
141
|
| `codegen_validate_payload` | Validate payload JSON structure and constraints |
|
|
105
142
|
| `codegen_validate_dashboard_payload` | Validate dashboard payload structure |
|
|
@@ -108,9 +145,15 @@ The agent orchestrates the appropriate tools to fulfill the request end-to-end.
|
|
|
108
145
|
| `codegen_create_endpoint` | Scaffold an endpoint module from a payload spec |
|
|
109
146
|
| `codegen_create_dashboard` | Scaffold a dashboard module from a payload spec |
|
|
110
147
|
| `codegen_validate_sql` | Validate a SELECT or WITH (CTE) SQL statement via EXPLAIN against the live database |
|
|
148
|
+
|
|
149
|
+
Grounding catalogs:
|
|
150
|
+
|
|
151
|
+
| Tool | Description |
|
|
152
|
+
|------|-------------|
|
|
111
153
|
| `codegen_get_field_validation_catalog` | Get the field validation catalog (for grounding payload constraints) |
|
|
112
154
|
| `codegen_get_query_declarative_catalog` | Get the query declarative catalog (for grounding query JSON) |
|
|
113
155
|
| `codegen_get_dashboard_catalog` | Get the dashboard widget catalog (for grounding dashboard config) |
|
|
156
|
+
| `codegen_get_dbschema_catalog` | Get the dbschema (SDF) catalog: model options, field types, and the soft-delete contract (for grounding schema definition files) |
|
|
114
157
|
|
|
115
158
|
### Runtime Domain (6 tools)
|
|
116
159
|
|
|
@@ -141,8 +184,8 @@ The model used (Claude, GPT, Gemini, etc.) depends on the client configuration.
|
|
|
141
184
|
|
|
142
185
|
## Repository
|
|
143
186
|
|
|
144
|
-
- Source: [https://github.com/restforge-
|
|
145
|
-
- Issues: [https://github.com/restforge-
|
|
187
|
+
- Source: [https://github.com/restforge/restforge-mcp](https://github.com/restforge/restforge-mcp)
|
|
188
|
+
- Issues: [https://github.com/restforge/restforge-mcp/issues](https://github.com/restforge/restforge-mcp/issues)
|
|
146
189
|
|
|
147
190
|
## License
|
|
148
191
|
|
package/dist/server.js
CHANGED
|
@@ -1,11 +1,20 @@
|
|
|
1
|
+
import { createRequire } from 'node:module';
|
|
1
2
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
3
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
3
4
|
import { registerHealthTools } from './tools/health/index.js';
|
|
4
5
|
import { registerSetupTools } from './tools/setup/index.js';
|
|
5
6
|
import { registerCodegenTools } from './tools/codegen/index.js';
|
|
6
7
|
import { registerRuntimeTools } from './tools/runtime/index.js';
|
|
8
|
+
import { registerDesignerTools } from './tools/designer/index.js';
|
|
7
9
|
const SERVER_NAME = 'restforge-mcp';
|
|
8
|
-
|
|
10
|
+
// Read the version from package.json at runtime so the advertised server version
|
|
11
|
+
// never drifts from the published package version. createRequire resolves the JSON
|
|
12
|
+
// relative to this module's location (dist/server.js -> ../package.json, and
|
|
13
|
+
// src/server.ts -> ../package.json under tsx), so the path holds in both build and
|
|
14
|
+
// dev. createRequire is used instead of a static JSON import because rootDir is
|
|
15
|
+
// ./src and package.json lives outside it; a static import would break the build.
|
|
16
|
+
const require = createRequire(import.meta.url);
|
|
17
|
+
const { version: SERVER_VERSION } = require('../package.json');
|
|
9
18
|
const SERVER_INSTRUCTIONS = `
|
|
10
19
|
This MCP server manages RESTForge backend project configuration.
|
|
11
20
|
|
|
@@ -116,6 +125,14 @@ route them as follows:
|
|
|
116
125
|
for 'schema migrate' (apply DDL to database) and produced by
|
|
117
126
|
'schema introspect' (reverse-engineer database).
|
|
118
127
|
Example: <project>/schema/category.js
|
|
128
|
+
An SDF may declare a soft-delete block: softDelete { enabled, reusable }.
|
|
129
|
+
When enabled, the three contract columns is_deleted (boolean),
|
|
130
|
+
deleted_at (timestamp), and deleted_by (string) are mandatory and
|
|
131
|
+
biconditional: declaring the columns without enabled=true, or
|
|
132
|
+
enabled=true with missing/wrongly-typed columns, is a validation ERROR.
|
|
133
|
+
Soft-delete is PostgreSQL-only in Phase 1. The generated DDL emits a
|
|
134
|
+
consistency CHECK (chk_<table>_soft_delete_consistency) and partial
|
|
135
|
+
indexes (WHERE is_deleted = FALSE) for non-unique indexes.
|
|
119
136
|
|
|
120
137
|
- RDF (Resource Definition File): JSON file (.json) at
|
|
121
138
|
payload/<resource>.json that declares a backend REST API endpoint (CRUD +
|
|
@@ -129,12 +146,21 @@ route them as follows:
|
|
|
129
146
|
|
|
130
147
|
Routing for SDF requests:
|
|
131
148
|
- create / init / scaffold -> codegen_dbschema_init
|
|
149
|
+
- browse/preview/generate schema templates (87-template reference collection) -> codegen_dbschema_template
|
|
132
150
|
- validate -> codegen_dbschema_validate
|
|
133
151
|
- list models / show structural summary -> codegen_dbschema_models
|
|
134
152
|
- generate DDL (preview or to file) -> codegen_dbschema_generate_ddl
|
|
135
153
|
- reverse-engineer from database -> codegen_dbschema_introspect
|
|
154
|
+
WARNING: on PostgreSQL, a table whose soft-delete columns do not meet
|
|
155
|
+
the contract (partial column set, wrong types, or missing consistency
|
|
156
|
+
CHECK) BLOCKS introspect with an error whose message lists concrete
|
|
157
|
+
mitigation options. Relay that message and its options to the user;
|
|
158
|
+
do not swallow it as a generic failure.
|
|
159
|
+
- check drift / compare SDF vs database -> codegen_dbschema_diff
|
|
160
|
+
- resolve drift incrementally via ALTER (additive-safe, opt-in destructive) -> codegen_dbschema_apply
|
|
136
161
|
- apply to database (DESTRUCTIVE) -> codegen_dbschema_migrate
|
|
137
162
|
- lookup syntax / defineModel API spec -> codegen_get_dbschema_catalog
|
|
163
|
+
- lookup soft-delete contract/rules -> codegen_get_dbschema_catalog (section=softDelete)
|
|
138
164
|
|
|
139
165
|
Routing for RDF requests:
|
|
140
166
|
- generate from database table -> codegen_generate_payload
|
|
@@ -202,6 +228,49 @@ documentationUrl returned by each catalog points to narrative
|
|
|
202
228
|
documentation which may lag behind the most recent npm release; trust
|
|
203
229
|
the catalog data over the URL for property reference, but use the URL
|
|
204
230
|
for use case examples and decision guides.
|
|
231
|
+
|
|
232
|
+
DESIGNER (FRONTEND) DOMAIN:
|
|
233
|
+
The codegen/setup/runtime tools above all wrap the backend CLI
|
|
234
|
+
('restforge', the @restforgejs/platform package). A separate family of
|
|
235
|
+
tools — the 'designer_*' tools — wraps a DIFFERENT command-line product,
|
|
236
|
+
'restforge-designer' (the RESTForge Designer frontend generator). Keep
|
|
237
|
+
the two straight: backend payload/schema/API work goes through the
|
|
238
|
+
'restforge' tools; frontend application work goes through the
|
|
239
|
+
'designer_*' tools.
|
|
240
|
+
|
|
241
|
+
Prefer the 'designer_*' tools when the user wants to:
|
|
242
|
+
- Generate, validate, or preview a FRONTEND application (not a backend
|
|
243
|
+
API) from a UI Definition File (UDF) payload
|
|
244
|
+
- Work with a frontend/designer PLUGIN (list, inspect, scaffold) — plugin
|
|
245
|
+
ids look like 'vanilla-js-basic', 'vanilla-js-auth', 'vanilla-js-custom'
|
|
246
|
+
- Initialise a new frontend project from a designer plugin
|
|
247
|
+
- Phrases like "generate frontend", "build the UI from this payload",
|
|
248
|
+
"generate aplikasi frontend", "preview file frontend", "buat project
|
|
249
|
+
frontend dari plugin", "validate UDF", or any mention of
|
|
250
|
+
"restforge-designer", "designer", "rfd", or "frontend generation"
|
|
251
|
+
|
|
252
|
+
Detection signals that this is RESTForge Designer (frontend) work:
|
|
253
|
+
- The 'restforge-designer' binary (alias 'rfd') is installed and on PATH
|
|
254
|
+
- The user mentions UDF (UI Definition File), frontend generation, or a
|
|
255
|
+
designer plugin ('vanilla-js-*')
|
|
256
|
+
- A frontend project folder with a UDF payload (payload/NN-<name>.json
|
|
257
|
+
in the frontend project) is in play
|
|
258
|
+
|
|
259
|
+
Boundaries for the designer domain:
|
|
260
|
+
- The 'designer_*' tools wrap the 'restforge-designer' binary, which is a
|
|
261
|
+
product SEPARATE from the backend 'restforge' CLI. They are not
|
|
262
|
+
interchangeable; do not route a backend RDF/SDF request to a
|
|
263
|
+
'designer_*' tool, or a UDF/frontend request to a 'codegen_*' tool.
|
|
264
|
+
- Designer LICENSE management and activation/deactivation are NOT
|
|
265
|
+
available through this MCP server (consistent with the backend, which
|
|
266
|
+
also does not manage per-machine license here). When a license-gated
|
|
267
|
+
designer operation (init, generate) fails because the license is not
|
|
268
|
+
active, relay that and tell the user to activate their RESTForge
|
|
269
|
+
Designer license through the Designer desktop application or its own
|
|
270
|
+
CLI — this server cannot activate it.
|
|
271
|
+
- If the 'restforge-designer' binary is not installed or not on PATH, the
|
|
272
|
+
designer tools return a non-error precondition; relay it as a setup
|
|
273
|
+
step (install RESTForge Designer), not a failure.
|
|
205
274
|
`.trim();
|
|
206
275
|
export async function startServer() {
|
|
207
276
|
const server = new McpServer({
|
|
@@ -214,6 +283,7 @@ export async function startServer() {
|
|
|
214
283
|
registerSetupTools(server);
|
|
215
284
|
registerCodegenTools(server);
|
|
216
285
|
registerRuntimeTools(server);
|
|
286
|
+
registerDesignerTools(server);
|
|
217
287
|
const transport = new StdioServerTransport();
|
|
218
288
|
await server.connect(transport);
|
|
219
289
|
}
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAElE,MAAM,WAAW,GAAG,eAAe,CAAC;AAEpC,iFAAiF;AACjF,mFAAmF;AACnF,6EAA6E;AAC7E,mFAAmF;AACnF,gFAAgF;AAChF,kFAAkF;AAClF,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC,iBAAiB,CAAwB,CAAC;AAEtF,MAAM,mBAAmB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgQ3B,CAAC,IAAI,EAAE,CAAC;AAET,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,MAAM,MAAM,GAAG,IAAI,SAAS,CAC1B;QACE,IAAI,EAAE,WAAW;QACjB,OAAO,EAAE,cAAc;KACxB,EACD;QACE,YAAY,EAAE,mBAAmB;KAClC,CACF,CAAC;IAEF,mBAAmB,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAC5C,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAC3B,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAC7B,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAC7B,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAE9B,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAClC,CAAC"}
|
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { access } from 'node:fs/promises';
|
|
3
|
+
import { resolve, join } from 'node:path';
|
|
4
|
+
import { execProcess } from '../../lib/exec.js';
|
|
5
|
+
// Pull one labelled block (e.g. 'Warnings:' or 'Summary:') out of the structured
|
|
6
|
+
// human-readable stdout. The CLI prints the header on its own line and the block
|
|
7
|
+
// ends at the first blank line. Defensive: returns null when the header is absent
|
|
8
|
+
// or the shape is unexpected — the caller then falls back to the full stdout.
|
|
9
|
+
function extractBlock(stdout, header) {
|
|
10
|
+
const lines = stdout.split(/\r?\n/);
|
|
11
|
+
const start = lines.findIndex((l) => l.trim() === header);
|
|
12
|
+
if (start === -1)
|
|
13
|
+
return null;
|
|
14
|
+
const block = [lines[start]];
|
|
15
|
+
for (let i = start + 1; i < lines.length; i++) {
|
|
16
|
+
if (lines[i].trim() === '')
|
|
17
|
+
break;
|
|
18
|
+
block.push(lines[i]);
|
|
19
|
+
}
|
|
20
|
+
return block.join('\n');
|
|
21
|
+
}
|
|
22
|
+
// Compose the Warnings + Summary excerpt for the opt-in branch. Falls back to a
|
|
23
|
+
// pointer line when neither block is found, so the response never loses signal.
|
|
24
|
+
function extractWarningsAndSummary(stdout) {
|
|
25
|
+
const parts = [];
|
|
26
|
+
const warnings = extractBlock(stdout, 'Warnings:');
|
|
27
|
+
if (warnings)
|
|
28
|
+
parts.push(warnings);
|
|
29
|
+
const summary = extractBlock(stdout, 'Summary:');
|
|
30
|
+
if (summary)
|
|
31
|
+
parts.push(summary);
|
|
32
|
+
if (parts.length === 0) {
|
|
33
|
+
return '(no Warnings:/Summary: blocks recognised — see the full CLI output above)';
|
|
34
|
+
}
|
|
35
|
+
return parts.join('\n\n');
|
|
36
|
+
}
|
|
37
|
+
export function registerCodegenDbschemaApply(server) {
|
|
38
|
+
server.registerTool('codegen_dbschema_apply', {
|
|
39
|
+
title: 'Apply Schema Drift Incrementally via ALTER',
|
|
40
|
+
description: `Resolve schema drift from dbschema-kit SDF files to the live database via incremental ALTER TABLE statements, by wrapping restforge schema apply. This is the incremental complement of 'codegen_dbschema_diff' (which only detects drift) and the SAFE alternative to 'codegen_dbschema_migrate' with drop=true (which destroys and recreates tables). By default the apply is ADDITIVE-ONLY: ADD COLUMN, CREATE INDEX, ADD UNIQUE, and ADD FOREIGN KEY are emitted; every destructive change is skipped with a warning unless explicitly opted in (allowDrop for DROP COLUMN/INDEX/UNIQUE/FOREIGN KEY, allowModify for ALTER COLUMN length/nullable and FOREIGN KEY action changes).
|
|
41
|
+
|
|
42
|
+
RECOMMENDED WORKFLOW:
|
|
43
|
+
1. Run 'codegen_dbschema_diff' first to see the drift.
|
|
44
|
+
2. Run this tool with dryRun=true to preview the exact ALTER statements.
|
|
45
|
+
3. Show the preview to the user and ask for confirmation.
|
|
46
|
+
4. Only then run with dryRun=false to apply. Pass allowDrop/allowModify ONLY when the user explicitly asked for that destructive change — never to "make a warning go away".
|
|
47
|
+
|
|
48
|
+
EXIT CODE SEMANTICS (important):
|
|
49
|
+
- Exit 0 = success: every applicable drift was applied (or previewed in dry-run, or there was no drift). The output may still contain warnings for operations the platform defers (see below) — relay those.
|
|
50
|
+
- Exit 1 = some drift was SKIPPED because it requires allowDrop or allowModify. This is a NORMAL, meaningful result — NOT a failure. In a real apply the additive statements WERE applied; only the skipped items remain. NEVER retry automatically with allowDrop/allowModify: those options drop or mutate data and need explicit user confirmation first.
|
|
51
|
+
- Exit 2 = system error (invalid config, SDF load failure, connection failure, or apply failure). ROLLBACK means the database is unchanged; PARTIAL means some statements were applied and the database needs manual inspection.
|
|
52
|
+
|
|
53
|
+
USE WHEN:
|
|
54
|
+
- 'codegen_dbschema_diff' reported drift and the user wants to bring the database in sync incrementally
|
|
55
|
+
- The user asks "apply the drift", "sinkronkan database dengan schema", "tambahkan kolom yang kurang ke database", "apply perubahan schema tanpa drop"
|
|
56
|
+
- Evolving an existing populated database without recreating tables (data preserved)
|
|
57
|
+
- The user wants a preview of the ALTER statements first — pass dryRun=true (safe path)
|
|
58
|
+
|
|
59
|
+
DO NOT USE FOR:
|
|
60
|
+
- Detecting drift without changing anything -> use 'codegen_dbschema_diff' (read-only)
|
|
61
|
+
- Full CREATE/DROP deployment of a schema or initial setup of an empty database -> use 'codegen_dbschema_migrate'
|
|
62
|
+
- Retrofitting the soft-delete consistency CHECK -> not supported here (detection-only); goes through 'codegen_dbschema_migrate' with drop (destructive) or manual SQL
|
|
63
|
+
- Type changes, PK changes, default value changes, CHECK constraint changes -> not supported by the platform yet (always skipped); suggest a manual SQL migration
|
|
64
|
+
- Validating SDF file correctness -> use 'codegen_dbschema_validate'
|
|
65
|
+
- Reverse-engineering SDF files from the database -> use 'codegen_dbschema_introspect'
|
|
66
|
+
|
|
67
|
+
This tool runs: npx restforge schema apply --path=<path> --config=<config> [--table=<name>] [--dry-run] [--allow-drop] [--allow-modify] in the given cwd. The output is a structured human-readable report (DDL preview or per-statement progress, Warnings, Summary) — there is no JSON mode.
|
|
68
|
+
|
|
69
|
+
OPERATIONS NOT SUPPORTED by the platform yet (always skipped with a 'deferred' warning, regardless of opt-in flags):
|
|
70
|
+
- ALTER COLUMN type change (needs a data conversion strategy per dialect)
|
|
71
|
+
- ALTER COLUMN precision/scale change
|
|
72
|
+
- DEFAULT value change
|
|
73
|
+
- PRIMARY KEY changes (need a table rebuild)
|
|
74
|
+
- CHECK constraint add/drop
|
|
75
|
+
On SQLite, MODIFY/DROP COLUMN and ALL foreign key changes are additionally skipped ('sqlite limitation') even with opt-in flags; the sqlite dialect is rejected entirely by the default introspector.
|
|
76
|
+
|
|
77
|
+
Soft-delete note: drift in the soft-delete consistency CHECK is detection-only. It is reported as a warning (never auto-applied) and does NOT by itself cause exit 1; the warning text suggests retrofitting via 'schema migrate --drop' (recreate) or adding the CHECK manually.
|
|
78
|
+
|
|
79
|
+
Preconditions:
|
|
80
|
+
- The project must have @restforgejs/platform installed in node_modules.
|
|
81
|
+
- The config file (default 'db-connection.env') must exist and contain valid database credentials.
|
|
82
|
+
- SDF files must exist at the given path. The --path flag is required by the CLI.
|
|
83
|
+
|
|
84
|
+
PRESENTATION GUIDANCE:
|
|
85
|
+
- Match the user's language. If the user writes in Indonesian, respond in Indonesian.
|
|
86
|
+
- Never mention internal tool names in the reply to the user. Describe actions by what they do (e.g. "apply the missing columns", "preview the ALTER statements").
|
|
87
|
+
- Exit 1 is NOT an error. Present it as: "these changes were applied/previewed, these were skipped because they would drop or modify existing data". Then ask the user whether they want the destructive part — do not decide for them.
|
|
88
|
+
- This tool MUTATES the live database when dryRun=false. Prefer dryRun=true on the first call and confirm with the user before the real apply.
|
|
89
|
+
- Speak in plain language. Summarise the applied/skipped items; do not paste raw CLI output unless the user explicitly asks.
|
|
90
|
+
- When a precondition is not met, frame it as a question or next-step suggestion rather than an error.`,
|
|
91
|
+
inputSchema: {
|
|
92
|
+
cwd: z
|
|
93
|
+
.string()
|
|
94
|
+
.min(1)
|
|
95
|
+
.describe('Absolute path of the project folder (must contain node_modules/@restforgejs/platform and the config file)'),
|
|
96
|
+
config: z
|
|
97
|
+
.string()
|
|
98
|
+
.min(1)
|
|
99
|
+
.default('db-connection.env')
|
|
100
|
+
.describe('Config file name relative to the project, used by the CLI to connect to the database'),
|
|
101
|
+
path: z
|
|
102
|
+
.string()
|
|
103
|
+
.min(1)
|
|
104
|
+
.describe('Path to schema file or folder relative to cwd (e.g. "./schema" or "schema/users.js"). Required by the CLI.'),
|
|
105
|
+
table: z
|
|
106
|
+
.string()
|
|
107
|
+
.min(1)
|
|
108
|
+
.optional()
|
|
109
|
+
.describe('Apply only one specific table. When omitted, all models in the schema path are processed.'),
|
|
110
|
+
dryRun: z
|
|
111
|
+
.boolean()
|
|
112
|
+
.default(false)
|
|
113
|
+
.describe('Default false. When true, preview the ALTER statements without applying. Safe path: prefer this on the first call.'),
|
|
114
|
+
allowDrop: z
|
|
115
|
+
.boolean()
|
|
116
|
+
.default(false)
|
|
117
|
+
.describe('Default false. Opt-in for DROP COLUMN/INDEX/UNIQUE/FOREIGN KEY (destroys data or constraints). Require explicit user confirmation before passing true.'),
|
|
118
|
+
allowModify: z
|
|
119
|
+
.boolean()
|
|
120
|
+
.default(false)
|
|
121
|
+
.describe('Default false. Opt-in for ALTER COLUMN length/nullable and FOREIGN KEY action changes (potential data loss). Require explicit user confirmation before passing true.'),
|
|
122
|
+
},
|
|
123
|
+
annotations: {
|
|
124
|
+
title: 'Apply Schema Drift Incrementally via ALTER',
|
|
125
|
+
destructiveHint: true, // mutates the live database; with opt-in flags also drops columns/constraints
|
|
126
|
+
idempotentHint: false, // re-running applies whatever drift remains; state-dependent
|
|
127
|
+
},
|
|
128
|
+
}, async ({ cwd, config, path, table, dryRun, allowDrop, allowModify }) => {
|
|
129
|
+
const projectCwd = resolve(cwd);
|
|
130
|
+
// Precondition check: @restforgejs/platform must be present in node_modules. per §3.4
|
|
131
|
+
try {
|
|
132
|
+
await access(join(projectCwd, 'node_modules', '@restforgejs', 'platform'));
|
|
133
|
+
}
|
|
134
|
+
catch {
|
|
135
|
+
return {
|
|
136
|
+
content: [
|
|
137
|
+
{
|
|
138
|
+
type: 'text',
|
|
139
|
+
text: `Precondition not met: the RESTForge package is not installed in this project.
|
|
140
|
+
|
|
141
|
+
Project path: ${projectCwd}
|
|
142
|
+
Expected location: node_modules/@restforgejs/platform
|
|
143
|
+
Requested config: ${config}
|
|
144
|
+
Requested schema path: ${path}
|
|
145
|
+
Requested table filter: ${table ?? 'all tables'}
|
|
146
|
+
Requested dryRun: ${dryRun}
|
|
147
|
+
|
|
148
|
+
For the assistant:
|
|
149
|
+
- The user needs to install the RESTForge package before drift can be applied to the database.
|
|
150
|
+
- Suggest installing the package first, then retry the apply.
|
|
151
|
+
- When explaining to the user, say something like "the RESTForge package isn't installed yet — should I install it first?". Do not mention internal tool names.`,
|
|
152
|
+
},
|
|
153
|
+
],
|
|
154
|
+
isError: false, // per §3.4
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
// Boolean flags are only forwarded when true, following the migrate/introspect
|
|
158
|
+
// pattern. There is no JSON output mode for schema apply. per §3.5
|
|
159
|
+
const cliArgs = [
|
|
160
|
+
'restforge',
|
|
161
|
+
'schema',
|
|
162
|
+
'apply',
|
|
163
|
+
`--path=${path}`,
|
|
164
|
+
`--config=${config}`,
|
|
165
|
+
];
|
|
166
|
+
if (table !== undefined)
|
|
167
|
+
cliArgs.push(`--table=${table}`);
|
|
168
|
+
if (dryRun === true)
|
|
169
|
+
cliArgs.push('--dry-run');
|
|
170
|
+
if (allowDrop === true)
|
|
171
|
+
cliArgs.push('--allow-drop');
|
|
172
|
+
if (allowModify === true)
|
|
173
|
+
cliArgs.push('--allow-modify');
|
|
174
|
+
const result = await execProcess('npx', cliArgs, {
|
|
175
|
+
cwd: projectCwd,
|
|
176
|
+
timeout: 120_000, // introspection + ALTER execution on a populated DB can be slow
|
|
177
|
+
env: { NODE_ENV: 'production' },
|
|
178
|
+
stripFinalNewline: true,
|
|
179
|
+
});
|
|
180
|
+
// Exit code semantics are part of the CLI spec: 0 = all applicable drift
|
|
181
|
+
// applied (or no drift), 1 = some drift skipped pending opt-in (a meaningful
|
|
182
|
+
// result, NOT an error), 2 = system error. Deliberately NO "exit 2 = dry-run
|
|
183
|
+
// success" sentinel here: a successful apply dry-run exits 0 or 1.
|
|
184
|
+
const optInRequired = result.exitCode === 1;
|
|
185
|
+
// Branch C: system error (exit 2 or any other non-0/1 exit). per §3.4
|
|
186
|
+
if (!result.success && !optInRequired) {
|
|
187
|
+
return {
|
|
188
|
+
content: [
|
|
189
|
+
{
|
|
190
|
+
type: 'text',
|
|
191
|
+
text: `Failed to apply schema drift to the database.
|
|
192
|
+
|
|
193
|
+
Project path: ${projectCwd}
|
|
194
|
+
Config: ${config}
|
|
195
|
+
Schema path: ${path}
|
|
196
|
+
Table filter: ${table ?? 'all tables'}
|
|
197
|
+
Mode: ${dryRun ? 'dry-run' : 'apply'}
|
|
198
|
+
Command: ${result.command}
|
|
199
|
+
Exit code: ${result.exitCode}
|
|
200
|
+
|
|
201
|
+
--- CLI output ---
|
|
202
|
+
stdout:
|
|
203
|
+
${result.stdout}
|
|
204
|
+
|
|
205
|
+
stderr:
|
|
206
|
+
${result.stderr}
|
|
207
|
+
--- end CLI output ---
|
|
208
|
+
|
|
209
|
+
For the assistant:
|
|
210
|
+
- Tell the user that the apply could not complete. This is a system error, not a drift result.
|
|
211
|
+
- Check the CLI output for ROLLBACK or PARTIAL status first:
|
|
212
|
+
* ROLLBACK applied — the database state is UNCHANGED; the failed statement is reported. Safe to fix the cause and retry.
|
|
213
|
+
* Partial apply detected — SOME statements were applied before the failure and were NOT reverted. The user must inspect the database state manually before any retry.
|
|
214
|
+
- Other common causes, in plain language:
|
|
215
|
+
* Config file not found or invalid — suggest verifying the config path and its content.
|
|
216
|
+
* Database connection failed — suggest verifying credentials, host, and port.
|
|
217
|
+
* Schema path not found or no models in it — suggest verifying the folder or file name passed via --path.
|
|
218
|
+
* SDF load error — a schema file has invalid syntax or violates the defineModel contract. Suggest running the validate action first.
|
|
219
|
+
* Table filter not found in SDF — the --table value does not match any model.
|
|
220
|
+
* Unsupported dialect — schema apply does not support sqlite. Suggest checking DB_TYPE in the config.
|
|
221
|
+
* Unknown command 'schema apply' — the installed RESTForge version may be older than this CLI subcommand; suggest upgrading the package.
|
|
222
|
+
- Do not paste the raw stdout/stderr unless the user explicitly asks. Do not mention internal tool names.
|
|
223
|
+
- Offer to retry once the underlying issue is resolved (after manual inspection in the PARTIAL case).`,
|
|
224
|
+
},
|
|
225
|
+
],
|
|
226
|
+
isError: true, // per §3.4
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
// Branch B (opt-in required): exit 1 — part of the drift was skipped because
|
|
230
|
+
// it needs --allow-drop / --allow-modify. A meaningful result, NOT an error.
|
|
231
|
+
if (optInRequired) {
|
|
232
|
+
const excerpt = extractWarningsAndSummary(result.stdout);
|
|
233
|
+
return {
|
|
234
|
+
content: [
|
|
235
|
+
{
|
|
236
|
+
type: 'text',
|
|
237
|
+
text: `Schema apply ${dryRun ? 'dry-run ' : ''}completed with skipped drift: some changes require explicit opt-in (this is a result, not an error).
|
|
238
|
+
|
|
239
|
+
Project path: ${projectCwd}
|
|
240
|
+
Config: ${config}
|
|
241
|
+
Schema path: ${path}
|
|
242
|
+
Table filter: ${table ?? 'all tables'}
|
|
243
|
+
Mode: ${dryRun ? 'dry-run (nothing applied)' : 'apply (additive statements WERE applied)'}
|
|
244
|
+
|
|
245
|
+
--- Warnings and Summary (from the CLI) ---
|
|
246
|
+
${excerpt}
|
|
247
|
+
--- end Warnings and Summary ---
|
|
248
|
+
|
|
249
|
+
--- Full CLI output ---
|
|
250
|
+
${result.stdout}
|
|
251
|
+
--- end Full CLI output ---
|
|
252
|
+
|
|
253
|
+
For the assistant:
|
|
254
|
+
- Present this as a two-part factual result: (1) what was ${dryRun ? 'previewed' : 'applied'} — see the ${dryRun ? 'DDL preview' : 'progress lines'} in the full output; (2) what was SKIPPED — the Warnings above list each skipped item with its reason ('requires --allow-drop' or 'requires --allow-modify').
|
|
255
|
+
- ${dryRun ? 'This was a preview only. Nothing was applied to the database.' : 'The additive statements were applied to the live database; only the skipped items remain outstanding.'}
|
|
256
|
+
- Do NOT retry with allowDrop/allowModify on your own. Those options drop columns/constraints or alter existing columns — explain to the user what would be dropped or modified, and only proceed after the user explicitly confirms.
|
|
257
|
+
- Warnings with reason 'deferred', 'detection-only', or 'sqlite limitation' cannot be resolved by opt-in flags at all — those need a manual migration or a full recreate; say so plainly.
|
|
258
|
+
- Do not paste the full CLI output unless the user asks; the Warnings/Summary excerpt is usually enough.
|
|
259
|
+
- Match the user's language.`,
|
|
260
|
+
},
|
|
261
|
+
],
|
|
262
|
+
isError: false, // exit 1 = drift pending opt-in, a normal result per CLI spec
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
// Branch B (dry-run success): exit 0 with --dry-run — preview only.
|
|
266
|
+
if (dryRun) {
|
|
267
|
+
return {
|
|
268
|
+
content: [
|
|
269
|
+
{
|
|
270
|
+
type: 'text',
|
|
271
|
+
text: `Schema apply dry-run completed (no changes applied).
|
|
272
|
+
|
|
273
|
+
Project path: ${projectCwd}
|
|
274
|
+
Config: ${config}
|
|
275
|
+
Schema path: ${path}
|
|
276
|
+
Table filter: ${table ?? 'all tables'}
|
|
277
|
+
Mode: dry-run
|
|
278
|
+
|
|
279
|
+
--- DDL preview ---
|
|
280
|
+
${result.stdout}
|
|
281
|
+
--- end DDL preview ---
|
|
282
|
+
|
|
283
|
+
For the assistant:
|
|
284
|
+
- Confirm to the user that this was a preview only. No ALTER statement was applied to the database.
|
|
285
|
+
- The statements shown above are exactly what would run if the same action is repeated without dry-run. "No applicable ALTER statements." means schema and database are already in sync for the applicable operations.
|
|
286
|
+
- If a Warnings block is present, relay it: warnings with reason 'deferred', 'detection-only', or 'sqlite limitation' are operations the platform cannot apply incrementally yet (they do not block the rest).
|
|
287
|
+
- Encourage the user to review the preview, then confirm before running the real apply.
|
|
288
|
+
- Match the user's language.`,
|
|
289
|
+
},
|
|
290
|
+
],
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
// Branch B (apply success): exit 0 — every applicable drift applied (or no drift).
|
|
294
|
+
return {
|
|
295
|
+
content: [
|
|
296
|
+
{
|
|
297
|
+
type: 'text',
|
|
298
|
+
text: `Schema apply completed successfully: all applicable drift was applied.
|
|
299
|
+
|
|
300
|
+
Project path: ${projectCwd}
|
|
301
|
+
Config: ${config}
|
|
302
|
+
Schema path: ${path}
|
|
303
|
+
Table filter: ${table ?? 'all tables'}
|
|
304
|
+
Mode: apply
|
|
305
|
+
allowDrop: ${allowDrop}
|
|
306
|
+
allowModify: ${allowModify}
|
|
307
|
+
|
|
308
|
+
--- CLI output ---
|
|
309
|
+
${result.stdout}
|
|
310
|
+
--- end CLI output ---
|
|
311
|
+
|
|
312
|
+
For the assistant:
|
|
313
|
+
- Confirm to the user that the incremental changes were applied to the live database. "No drift to apply." means schema and database were already in sync.
|
|
314
|
+
- Read the Summary in the CLI output and mention the number of statements applied in plain language.
|
|
315
|
+
- If skipped warnings are present (reason 'deferred', 'detection-only', or 'sqlite limitation'), relay them: those operations cannot be applied incrementally yet and need a manual migration or a full recreate. They did not block this apply.
|
|
316
|
+
- Suggest verifying the result with a drift check (read-only) if the user wants confirmation that everything is now in sync.
|
|
317
|
+
- Do not paste the raw CLI output unless the user explicitly asks.
|
|
318
|
+
- Match the user's language.`,
|
|
319
|
+
},
|
|
320
|
+
],
|
|
321
|
+
};
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
//# sourceMappingURL=dbschema-apply.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dbschema-apply.js","sourceRoot":"","sources":["../../../src/tools/codegen/dbschema-apply.ts"],"names":[],"mappings":"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"}
|