@restforgejs/mcp-server 1.2.2 → 1.2.4

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.
Files changed (80) hide show
  1. package/dist/server.js +71 -2
  2. package/dist/server.js.map +1 -1
  3. package/dist/tools/codegen/create-kafka-consumer.d.ts +2 -0
  4. package/dist/tools/codegen/create-kafka-consumer.js +140 -0
  5. package/dist/tools/codegen/create-kafka-consumer.js.map +1 -0
  6. package/dist/tools/codegen/create-processor.d.ts +2 -0
  7. package/dist/tools/codegen/create-processor.js +157 -0
  8. package/dist/tools/codegen/create-processor.js.map +1 -0
  9. package/dist/tools/codegen/generate-test.d.ts +2 -0
  10. package/dist/tools/codegen/generate-test.js +149 -0
  11. package/dist/tools/codegen/generate-test.js.map +1 -0
  12. package/dist/tools/codegen/index.js +8 -0
  13. package/dist/tools/codegen/index.js.map +1 -1
  14. package/dist/tools/codegen/migrate-payload.d.ts +2 -0
  15. package/dist/tools/codegen/migrate-payload.js +210 -0
  16. package/dist/tools/codegen/migrate-payload.js.map +1 -0
  17. package/dist/tools/data/index.d.ts +2 -0
  18. package/dist/tools/data/index.js +7 -0
  19. package/dist/tools/data/index.js.map +1 -0
  20. package/dist/tools/data/pull.d.ts +2 -0
  21. package/dist/tools/data/pull.js +202 -0
  22. package/dist/tools/data/pull.js.map +1 -0
  23. package/dist/tools/data/push.d.ts +2 -0
  24. package/dist/tools/data/push.js +190 -0
  25. package/dist/tools/data/push.js.map +1 -0
  26. package/dist/tools/designer/generate.js +86 -81
  27. package/dist/tools/designer/generate.js.map +1 -1
  28. package/dist/tools/designer/get-udf-catalog.d.ts +2 -0
  29. package/dist/tools/designer/get-udf-catalog.js +225 -0
  30. package/dist/tools/designer/get-udf-catalog.js.map +1 -0
  31. package/dist/tools/designer/index.js +2 -0
  32. package/dist/tools/designer/index.js.map +1 -1
  33. package/dist/tools/designer/init-project.js +73 -73
  34. package/dist/tools/designer/inspect-plugin.js +70 -65
  35. package/dist/tools/designer/inspect-plugin.js.map +1 -1
  36. package/dist/tools/designer/list-plugins.js +62 -62
  37. package/dist/tools/designer/preview-files.js +72 -67
  38. package/dist/tools/designer/preview-files.js.map +1 -1
  39. package/dist/tools/designer/scaffold-plugin.js +72 -72
  40. package/dist/tools/designer/validate-payload.js +74 -69
  41. package/dist/tools/designer/validate-payload.js.map +1 -1
  42. package/dist/tools/key/generate.d.ts +2 -0
  43. package/dist/tools/key/generate.js +130 -0
  44. package/dist/tools/key/generate.js.map +1 -0
  45. package/dist/tools/key/index.d.ts +2 -0
  46. package/dist/tools/key/index.js +9 -0
  47. package/dist/tools/key/index.js.map +1 -0
  48. package/dist/tools/key/list.d.ts +2 -0
  49. package/dist/tools/key/list.js +126 -0
  50. package/dist/tools/key/list.js.map +1 -0
  51. package/dist/tools/key/revoke.d.ts +2 -0
  52. package/dist/tools/key/revoke.js +117 -0
  53. package/dist/tools/key/revoke.js.map +1 -0
  54. package/dist/tools/project/delete.d.ts +2 -0
  55. package/dist/tools/project/delete.js +116 -0
  56. package/dist/tools/project/delete.js.map +1 -0
  57. package/dist/tools/project/index.d.ts +2 -0
  58. package/dist/tools/project/index.js +7 -0
  59. package/dist/tools/project/index.js.map +1 -0
  60. package/dist/tools/project/list.d.ts +2 -0
  61. package/dist/tools/project/list.js +107 -0
  62. package/dist/tools/project/list.js.map +1 -0
  63. package/dist/tools/runtime/generate-launcher.js +3 -3
  64. package/dist/tools/setup/clear-default-config.d.ts +2 -0
  65. package/dist/tools/setup/clear-default-config.js +104 -0
  66. package/dist/tools/setup/clear-default-config.js.map +1 -0
  67. package/dist/tools/setup/get-default-config.d.ts +2 -0
  68. package/dist/tools/setup/get-default-config.js +104 -0
  69. package/dist/tools/setup/get-default-config.js.map +1 -0
  70. package/dist/tools/setup/index.js +8 -0
  71. package/dist/tools/setup/index.js.map +1 -1
  72. package/dist/tools/setup/init-config.js +3 -5
  73. package/dist/tools/setup/init-config.js.map +1 -1
  74. package/dist/tools/setup/list-configs.d.ts +2 -0
  75. package/dist/tools/setup/list-configs.js +104 -0
  76. package/dist/tools/setup/list-configs.js.map +1 -0
  77. package/dist/tools/setup/set-default-config.d.ts +2 -0
  78. package/dist/tools/setup/set-default-config.js +109 -0
  79. package/dist/tools/setup/set-default-config.js.map +1 -0
  80. package/package.json +1 -1
@@ -0,0 +1,210 @@
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
+ export function registerCodegenMigratePayload(server) {
6
+ server.registerTool('codegen_migrate_payload', {
7
+ title: 'Migrate Payload (RDF backend -> UDF frontend)',
8
+ description: `Convert an existing backend payload file (RDF) into a frontend payload (UDF) for RESTForge Designer, by wrapping restforge payload migrate. The output is always a SPLIT multi-file set written into an output directory (app-config.json, one file per page under pages/, and an aggregator <appCode>.json), not a single UDF file. The migrator also auto-discovers JOINed tables, so one JOINed RDF can produce several pages at once.
9
+
10
+ PRIMARY PATH TO CREATE A UDF (firm): this is the FIRST and preferred way to produce a UDF. RESTForge is backend-first — a UDF is normally DERIVED from an existing backend RDF via this tool, not written by hand. Whenever a backend RDF payload exists and the user wants a UDF/frontend, START HERE. Only hand-author a UDF from scratch (grounded by 'designer_get_udf_catalog') when there is genuinely no RDF to migrate from.
11
+
12
+ USE WHEN:
13
+ - The user wants to CREATE or start a frontend UDF and a backend RDF payload exists — this is the default on-ramp, before any hand-authoring
14
+ - The user wants to build a frontend UDF from an existing backend payload, e.g. "buat UDF dari payload backend", "konversi RDF ke UDF", "migrate payload ke frontend", "bikin payload designer dari backend existing"
15
+ - The user has a working backend payload and now wants to start authoring the matching frontend in RESTForge Designer (on-ramp from backend to frontend)
16
+ - The user mentions migrating, converting, or porting a backend payload over to the designer / frontend side
17
+
18
+ DO NOT USE FOR:
19
+ - Generating the actual frontend web application from a UDF that already exists -> use the designer generate action (describe it by what it does, do not name the tool)
20
+ - Validating a backend payload against the database schema -> use 'codegen_validate_payload'
21
+ - Generating a backend payload from a database table that has no payload yet -> use 'codegen_generate_payload'
22
+
23
+ This tool runs: npx restforge payload migrate --name=<name> --project=<project> [--output] [--config] [--app-name] [--app-code] [--plugin] [--port] [--overwrite] in the given cwd.
24
+ The CLI reads the backend RDF (resolved relative to cwd or cwd/payload/), reads SERVER_ADDRESS/SERVER_PORT from the DB config (or the default config) to build apiBaseUrl, and writes the split UDF files into the output directory (default frontend/payload/).
25
+
26
+ Cross-reference (downstream UDF flow):
27
+ - This tool is the on-ramp that creates a UDF from an existing backend RDF. Its split UDF output is consumed by the designer tools: validate it with 'designer_validate_payload', dry-run it with 'designer_preview_files', and generate the frontend with 'designer_generate' — always point those at the aggregator file (<appCode>.json), not the individual page fragments.
28
+ - To see the target UDF structure and rules (valid field types, required appConfig fields, enums, limits), use 'designer_get_udf_catalog'.
29
+ - Canonical UDF flow: codegen_migrate_payload -> designer_get_udf_catalog -> designer_validate_payload -> designer_preview_files -> designer_generate.
30
+
31
+ Preconditions:
32
+ - The project must have @restforgejs/platform installed in node_modules.
33
+ - The named RDF payload file must exist (resolved relative to cwd or cwd/payload/).
34
+ - Without --overwrite, the command fails if any split output file already exists in the output directory.
35
+ This tool does not pre-check those — if the CLI fails, the failure response will surface the cause.
36
+
37
+ PRESENTATION GUIDANCE:
38
+ - Match the user's language. If the user writes in Indonesian, respond in Indonesian.
39
+ - Never mention internal tool names in the reply to the user. Describe actions by what they do (e.g. "convert the backend payload into a frontend payload", "validate the frontend payload", "generate the frontend application").
40
+ - Speak in plain language. Confirm the migration, mention the output directory and that the result is a split multi-file UDF; do not paste the raw CLI output unless the user explicitly asks.
41
+ - After a successful migration, the usual next steps are to validate the resulting UDF, preview it, or generate the frontend application from it. Describe those steps by what they do; do not name internal tools.
42
+ - When a precondition is not met, frame it as a question or next-step suggestion rather than an error.`,
43
+ inputSchema: {
44
+ cwd: z
45
+ .string()
46
+ .min(1)
47
+ .describe('Absolute path of the backend project folder (must contain node_modules/@restforgejs/platform; the RDF payload is read from here)'),
48
+ name: z
49
+ .string()
50
+ .min(1)
51
+ .describe('Backend RDF payload file name (e.g. visitors.json). Resolved relative to cwd or cwd/payload/. REQUIRED.'),
52
+ project: z
53
+ .string()
54
+ .min(1)
55
+ .describe('Project name in kebab-case, used as the path segment in apiBaseUrl (http://{host}:{port}/api/{project}). REQUIRED.'),
56
+ output: z
57
+ .string()
58
+ .min(1)
59
+ .optional()
60
+ .describe('Output directory for the split UDF files, relative to cwd. When omitted, the CLI uses its default (frontend/payload/). A value ending in .json is reduced to its parent directory.'),
61
+ config: z
62
+ .string()
63
+ .min(1)
64
+ .optional()
65
+ .describe('Database config file (.env) read for SERVER_ADDRESS/SERVER_PORT (backend host/port). When omitted, the CLI falls back to the default config.'),
66
+ appName: z
67
+ .string()
68
+ .min(1)
69
+ .optional()
70
+ .describe('Value for appConfig.appName in the UDF output. When omitted, derived from project in Title Case (e.g. visitors-app -> "Visitors App").'),
71
+ appCode: z
72
+ .string()
73
+ .min(1)
74
+ .optional()
75
+ .describe('Value for appConfig.appCode in the UDF output (kebab-case). Also used as the aggregator file name (<appCode>.json). When omitted, follows project.'),
76
+ plugin: z
77
+ .string()
78
+ .min(1)
79
+ .optional()
80
+ .describe('Designer plugin ID written to appConfig.plugin. When omitted, the CLI uses its default (vanilla-js-basic).'),
81
+ port: z
82
+ .number()
83
+ .int()
84
+ .min(1)
85
+ .max(65535)
86
+ .optional()
87
+ .describe('Frontend application port written to appConfig.port. Independent of the backend port used in apiBaseUrl. When omitted, the CLI uses its default (8000).'),
88
+ overwrite: z
89
+ .boolean()
90
+ .optional()
91
+ .describe('Overwrite existing split output files. Without it, the command fails if any split file already exists in the output directory.'),
92
+ },
93
+ annotations: {
94
+ title: 'Migrate Payload (RDF backend -> UDF frontend)',
95
+ readOnlyHint: false,
96
+ idempotentHint: false, // re-running can fail or overwrite depending on --overwrite
97
+ destructiveHint: false,
98
+ },
99
+ }, async ({ cwd, name, project, output, config, appName, appCode, plugin, port, overwrite }) => {
100
+ const projectCwd = resolve(cwd);
101
+ // Precondition check: @restforgejs/platform must be present in node_modules.
102
+ // Treated as a non-error precondition per the authoring guide §3.4.
103
+ try {
104
+ await access(join(projectCwd, 'node_modules', '@restforgejs', 'platform'));
105
+ }
106
+ catch {
107
+ return {
108
+ content: [
109
+ {
110
+ type: 'text',
111
+ text: `Precondition not met: the RESTForge package is not installed in this project.
112
+
113
+ Project path: ${projectCwd}
114
+ Expected location: node_modules/@restforgejs/platform
115
+ Requested RDF: ${name}
116
+ Requested project: ${project}
117
+
118
+ For the assistant:
119
+ - The user needs to install the RESTForge package before a backend payload can be migrated into a frontend payload.
120
+ - Suggest installing the package first, then retry the migration.
121
+ - 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.`,
122
+ },
123
+ ],
124
+ isError: false, // per §3.4
125
+ };
126
+ }
127
+ // Forward only the arguments the user supplied. CLI defaults
128
+ // (frontend/payload/ output, vanilla-js-basic plugin, port 8000, etc.)
129
+ // stay in effect when the user does not specify them. per §3.5
130
+ const args = ['restforge', 'payload', 'migrate', `--name=${name}`, `--project=${project}`];
131
+ if (output)
132
+ args.push(`--output=${output}`);
133
+ if (config)
134
+ args.push(`--config=${config}`);
135
+ if (appName)
136
+ args.push(`--app-name=${appName}`);
137
+ if (appCode)
138
+ args.push(`--app-code=${appCode}`);
139
+ if (plugin)
140
+ args.push(`--plugin=${plugin}`);
141
+ if (port !== undefined)
142
+ args.push(`--port=${port}`);
143
+ if (overwrite)
144
+ args.push('--overwrite');
145
+ const result = await execProcess('npx', args, { cwd: projectCwd, timeout: 60_000 });
146
+ // Branch C: CLI failure — real error per §3.4. A failed or partial migration
147
+ // needs recovery, so this is isError: true. Structured per §3.5.
148
+ if (!result.success) {
149
+ return {
150
+ content: [
151
+ {
152
+ type: 'text',
153
+ text: `Failed to migrate the backend payload into a frontend payload.
154
+
155
+ Project path: ${projectCwd}
156
+ RDF name: ${name}
157
+ Project: ${project}
158
+ Output: ${output ?? 'default (frontend/payload/)'}
159
+ Config: ${config ?? 'default config'}
160
+ Command: ${result.command}
161
+ Exit code: ${result.exitCode}
162
+
163
+ --- CLI output ---
164
+ stdout:
165
+ ${result.stdout}
166
+
167
+ stderr:
168
+ ${result.stderr}
169
+ --- end CLI output ---
170
+
171
+ For the assistant:
172
+ - Tell the user that the payload migration did not complete successfully, and that any partially written output may need cleanup.
173
+ - Summarise the most likely cause from the CLI output in plain language. Common causes:
174
+ * The named RDF payload was not found — it is resolved relative to cwd or cwd/payload/. Suggest checking the file name and location.
175
+ * The database config could not be read (missing or incomplete SERVER_ADDRESS/SERVER_PORT), or no default config is set. Suggest pointing at a valid config file.
176
+ * Output files already exist and --overwrite was not set — suggest re-running with overwrite enabled or choosing a different output directory.
177
+ - Do not paste the raw stdout/stderr unless the user explicitly asks. Do not mention internal tool names.`,
178
+ },
179
+ ],
180
+ isError: true, // per §3.4
181
+ };
182
+ }
183
+ // Branch B: success — labeled facts + fenced raw output per §3.5.
184
+ return {
185
+ content: [
186
+ {
187
+ type: 'text',
188
+ text: `Payload migration completed (RDF backend -> UDF frontend).
189
+
190
+ Project path: ${projectCwd}
191
+ RDF name: ${name}
192
+ Project: ${project}
193
+ Output dir: ${output ?? 'default (frontend/payload/)'}
194
+ Command: ${result.command}
195
+
196
+ --- CLI output ---
197
+ ${result.stdout}
198
+ --- end CLI output ---
199
+
200
+ For the assistant:
201
+ - Confirm to the user that the backend payload was converted into a frontend payload. Mention that the output is a split multi-file set (a shared app-config file, one file per page under pages/, and an aggregator file) written into the output directory above.
202
+ - Read the CLI output for the number of pages and the file list; mention how many pages were produced (auto-discovered JOINs can produce more than one page from a single RDF).
203
+ - Suggest the usual next steps in plain language: validate the resulting frontend payload, preview it, or generate the frontend application from it (always pointing at the aggregator file, not the individual page fragments). Do not name internal tools.
204
+ - Keep the reply concise. Do not paste the raw CLI output unless the user explicitly asks. Do not mention internal tool names.`,
205
+ },
206
+ ],
207
+ };
208
+ });
209
+ }
210
+ //# sourceMappingURL=migrate-payload.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrate-payload.js","sourceRoot":"","sources":["../../../src/tools/codegen/migrate-payload.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare function registerDataTools(server: McpServer): void;
@@ -0,0 +1,7 @@
1
+ import { registerDataPull } from './pull.js';
2
+ import { registerDataPush } from './push.js';
3
+ export function registerDataTools(server) {
4
+ registerDataPull(server);
5
+ registerDataPush(server);
6
+ }
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tools/data/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAE7C,MAAM,UAAU,iBAAiB,CAAC,MAAiB;IACjD,gBAAgB,CAAC,MAAM,CAAC,CAAC;IACzB,gBAAgB,CAAC,MAAM,CAAC,CAAC;AAC3B,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare function registerDataPull(server: McpServer): void;
@@ -0,0 +1,202 @@
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
+ export function registerDataPull(server) {
6
+ server.registerTool('data_pull', {
7
+ title: 'Pull Table Data to Envelope Files',
8
+ description: `Export rows from database tables into JSON envelope files (data-storage/<table>.json), driven purely by SDF metadata, by wrapping restforge data pull. Exports one table (--table), a schema or comma-separated schemas (--schema), or every registered table (--all-schemas). Only tables registered in the SDF can be pulled.
9
+
10
+ USE WHEN:
11
+ - The user wants to export, dump, snapshot, or back up table rows to files, e.g. "export data tabel", "pull data", "dump rows ke file", "snapshot data tabel"
12
+ - The user wants to move data between databases (pull from source, then 'data_push' into target) — pull is the first half
13
+ - The user wants a dialect-agnostic export based on the SDF (not raw DB introspection)
14
+
15
+ DO NOT USE FOR:
16
+ - Loading/importing rows INTO a database -> use 'data_push'
17
+ - Generating or reading the table SCHEMA (DDL/structure) -> use the dbschema tools
18
+ - Reading the live database connection config -> use 'setup_read_env'
19
+
20
+ This tool runs: npx restforge data pull (--table | --schema | --all-schemas) [--config] [--schema-path] [--limit] [--batch-size] [--storage-path] [--force] --json in the given cwd. The --json flag is always passed so the summary is machine-readable.
21
+
22
+ Scope (exactly ONE required): provide exactly one of 'table', 'schema', or 'allSchemas'. Supplying none or more than one is a usage error.
23
+
24
+ Preconditions:
25
+ - The project must have @restforgejs/platform installed in node_modules.
26
+ - The SDF (schema files) and a database config must be resolvable. Without --config, a default config must be set. This tool does not pre-check these — if the CLI fails, the failure response surfaces the cause.
27
+
28
+ PRESENTATION GUIDANCE:
29
+ - Match the user's language. If the user writes in Indonesian, respond in Indonesian.
30
+ - Never mention internal tool names in the reply to the user. Describe actions by what they do (e.g. "export the table data", "load the data into the target database").
31
+ - The CLI prints a JSON summary; read it and tell the user how many rows/tables were exported and where the files were written. Do not paste the raw JSON unless the user explicitly asks.
32
+ - When a precondition is not met, frame it as a question or next-step suggestion rather than an error.`,
33
+ inputSchema: {
34
+ cwd: z
35
+ .string()
36
+ .min(1)
37
+ .describe('Absolute path of the project folder (must contain node_modules/@restforgejs/platform; SDF + data-storage resolved from here)'),
38
+ table: z
39
+ .string()
40
+ .min(1)
41
+ .optional()
42
+ .describe('Source table name (must be registered in SDF). Use schema.table for schema-qualified tables. Exactly one of table/schema/allSchemas.'),
43
+ schema: z
44
+ .string()
45
+ .min(1)
46
+ .optional()
47
+ .describe('Schema filter: one name or comma-separated (e.g. public,sales). Pulls all SDF tables in those schemas. Exactly one of table/schema/allSchemas.'),
48
+ allSchemas: z
49
+ .boolean()
50
+ .optional()
51
+ .describe('Pull every table registered in the SDF across all schemas. Exactly one of table/schema/allSchemas.'),
52
+ config: z
53
+ .string()
54
+ .min(1)
55
+ .optional()
56
+ .describe('Database config file (.env). When omitted, the CLI falls back to the default config.'),
57
+ schemaPath: z
58
+ .string()
59
+ .min(1)
60
+ .optional()
61
+ .describe('SDF location (file or folder). When omitted, the CLI uses its default (schema).'),
62
+ limit: z
63
+ .number()
64
+ .int()
65
+ .min(1)
66
+ .optional()
67
+ .describe('Maximum total rows to export (applied per table for schema/allSchemas). When omitted, all rows are exported.'),
68
+ batchSize: z
69
+ .number()
70
+ .int()
71
+ .min(1)
72
+ .optional()
73
+ .describe('Internal read batch size. When omitted, the CLI uses its default (1000).'),
74
+ storagePath: z
75
+ .string()
76
+ .min(1)
77
+ .optional()
78
+ .describe('Output folder relative to cwd. When omitted, the CLI uses its default (data-storage).'),
79
+ force: z
80
+ .boolean()
81
+ .optional()
82
+ .describe('Overwrite output files if they already exist. Without it, an existing output file aborts the pull.'),
83
+ },
84
+ annotations: {
85
+ title: 'Pull Table Data to Envelope Files',
86
+ readOnlyHint: false,
87
+ idempotentHint: false,
88
+ destructiveHint: false,
89
+ },
90
+ }, async ({ cwd, table, schema, allSchemas, config, schemaPath, limit, batchSize, storagePath, force }) => {
91
+ const projectCwd = resolve(cwd);
92
+ try {
93
+ await access(join(projectCwd, 'node_modules', '@restforgejs', 'platform'));
94
+ }
95
+ catch {
96
+ return {
97
+ content: [
98
+ {
99
+ type: 'text',
100
+ text: `Precondition not met: the RESTForge package is not installed in this project.
101
+
102
+ Project path: ${projectCwd}
103
+ Expected location: node_modules/@restforgejs/platform
104
+
105
+ For the assistant:
106
+ - The user needs to install the RESTForge package before table data can be exported.
107
+ - Suggest installing the package first, then retry. Do not mention internal tool names.`,
108
+ },
109
+ ],
110
+ isError: false,
111
+ };
112
+ }
113
+ // Scope is mutually exclusive: exactly one of table / schema / allSchemas.
114
+ const scopeCount = [table, schema, allSchemas ? true : undefined].filter((v) => v !== undefined).length;
115
+ if (scopeCount !== 1) {
116
+ return {
117
+ content: [
118
+ {
119
+ type: 'text',
120
+ text: `Scope not specified correctly: provide exactly one of 'table', 'schema', or 'allSchemas' (got ${scopeCount}).
121
+
122
+ For the assistant:
123
+ - Ask the user which scope they want: a single table, one/more schemas, or every registered table. Then retry with exactly one scope set.`,
124
+ },
125
+ ],
126
+ isError: false,
127
+ };
128
+ }
129
+ const args = ['restforge', 'data', 'pull'];
130
+ if (table)
131
+ args.push(`--table=${table}`);
132
+ if (schema)
133
+ args.push(`--schema=${schema}`);
134
+ if (allSchemas)
135
+ args.push('--all-schemas');
136
+ if (config)
137
+ args.push(`--config=${config}`);
138
+ if (schemaPath)
139
+ args.push(`--schema-path=${schemaPath}`);
140
+ if (limit !== undefined)
141
+ args.push(`--limit=${limit}`);
142
+ if (batchSize !== undefined)
143
+ args.push(`--batch-size=${batchSize}`);
144
+ if (storagePath)
145
+ args.push(`--storage-path=${storagePath}`);
146
+ if (force)
147
+ args.push('--force');
148
+ args.push('--json');
149
+ const result = await execProcess('npx', args, { cwd: projectCwd, timeout: 120_000 });
150
+ if (!result.success) {
151
+ return {
152
+ content: [
153
+ {
154
+ type: 'text',
155
+ text: `Failed to pull table data.
156
+
157
+ Project path: ${projectCwd}
158
+ Scope: ${table ? `table=${table}` : schema ? `schema=${schema}` : 'all-schemas'}
159
+ Command: ${result.command}
160
+ Exit code: ${result.exitCode}
161
+
162
+ --- CLI output ---
163
+ stdout:
164
+ ${result.stdout}
165
+
166
+ stderr:
167
+ ${result.stderr}
168
+ --- end CLI output ---
169
+
170
+ For the assistant:
171
+ - Tell the user the data export did not complete.
172
+ - Summarise the likely cause from the CLI output. Common causes by exit code: 1 = an output file already exists (suggest force) or the SDF could not be read; 2 = usage problem (config required but no default, table not registered/ambiguous, schema matched no tables); 3 = database connection or query error.
173
+ - Do not paste raw output unless the user asks. Do not mention internal tool names.`,
174
+ },
175
+ ],
176
+ isError: true,
177
+ };
178
+ }
179
+ return {
180
+ content: [
181
+ {
182
+ type: 'text',
183
+ text: `Table data exported.
184
+
185
+ Project path: ${projectCwd}
186
+ Scope: ${table ? `table=${table}` : schema ? `schema=${schema}` : 'all-schemas'}
187
+ Command: ${result.command}
188
+
189
+ --- CLI output (JSON summary) ---
190
+ ${result.stdout}
191
+ --- end CLI output ---
192
+
193
+ For the assistant:
194
+ - Read the JSON summary above and tell the user how many rows/tables were exported and the output file path(s) (under the storage folder, schema-qualified tables nested under their schema subfolder).
195
+ - If the user's goal is to move data into another database, the next step is to load these files into the target. Describe it by what it does; do not name internal tools.
196
+ - Keep the reply concise. Do not paste the raw JSON unless the user explicitly asks. Do not mention internal tool names.`,
197
+ },
198
+ ],
199
+ };
200
+ });
201
+ }
202
+ //# sourceMappingURL=pull.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pull.js","sourceRoot":"","sources":["../../../src/tools/data/pull.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare function registerDataPush(server: McpServer): void;
@@ -0,0 +1,190 @@
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
+ export function registerDataPush(server) {
6
+ server.registerTool('data_push', {
7
+ title: 'Push Envelope Files into Database',
8
+ description: `Load rows from JSON envelope files (data-storage/<table>.json) INTO target database tables via batch INSERT, driven purely by SDF metadata, by wrapping restforge data push. This is APPEND-ONLY (no upsert/replace). Loads one table (--table), a schema or comma-separated schemas (--schema), or every table that has a file (--all-schemas). File names match 'data_pull' exactly, so pulled files can be pushed directly.
9
+
10
+ USE WHEN:
11
+ - The user wants to import, load, seed, or restore table rows from envelope files into a database, e.g. "push data", "import data ke database", "load rows dari file", "seed data tabel"
12
+ - The user is moving data between databases and has already exported files with 'data_pull' — push is the second half
13
+ - The user wants a dialect-agnostic import based on the SDF
14
+
15
+ DO NOT USE FOR:
16
+ - Exporting rows OUT of a database to files -> use 'data_pull'
17
+ - Updating or replacing existing rows -> not supported; this is append-only INSERT and will add duplicate rows if run again
18
+ - Creating the table SCHEMA itself -> use the dbschema tools
19
+
20
+ This tool runs: npx restforge data push (--table | --schema | --all-schemas) [--config] [--schema-path] [--storage-path] [--batch-size] --json in the given cwd. The --json flag is always passed so the summary is machine-readable. There is intentionally NO force/overwrite/upsert option — the verb only appends.
21
+
22
+ Scope (exactly ONE required): provide exactly one of 'table', 'schema', or 'allSchemas'. For schema/allSchemas, tables are loaded in topological FK order (parent before child).
23
+
24
+ IMPORTANT — this MUTATES the target database (inserts rows). Because it is append-only, running it twice inserts the data twice. Confirm with the user before pushing into a database that may already contain the rows.
25
+
26
+ Preconditions:
27
+ - The project must have @restforgejs/platform installed in node_modules.
28
+ - The envelope files must exist under the storage folder, and a database config must be resolvable. This tool does not pre-check these — if the CLI fails, the failure response surfaces the cause.
29
+
30
+ PRESENTATION GUIDANCE:
31
+ - Match the user's language. If the user writes in Indonesian, respond in Indonesian.
32
+ - Never mention internal tool names in the reply to the user. Describe actions by what they do (e.g. "load the data into the database").
33
+ - The CLI prints a JSON summary; read it and tell the user how many rows/tables were inserted. Do not paste the raw JSON unless the user explicitly asks.
34
+ - Because the import is append-only, remind the user that re-running adds duplicate rows.
35
+ - When a precondition is not met, frame it as a question or next-step suggestion rather than an error.`,
36
+ inputSchema: {
37
+ cwd: z
38
+ .string()
39
+ .min(1)
40
+ .describe('Absolute path of the project folder (must contain node_modules/@restforgejs/platform; SDF + data-storage resolved from here)'),
41
+ table: z
42
+ .string()
43
+ .min(1)
44
+ .optional()
45
+ .describe('Target table name (must be registered in SDF). Use schema.table for schema-qualified tables. Exactly one of table/schema/allSchemas.'),
46
+ schema: z
47
+ .string()
48
+ .min(1)
49
+ .optional()
50
+ .describe('Schema filter: one name or comma-separated (e.g. public,sales). Pushes SDF tables in those schemas that have a file, in FK parent->child order. Exactly one of table/schema/allSchemas.'),
51
+ allSchemas: z
52
+ .boolean()
53
+ .optional()
54
+ .describe('Push every SDF table that has a file under storage, across all schemas, in FK parent->child order. Exactly one of table/schema/allSchemas.'),
55
+ config: z
56
+ .string()
57
+ .min(1)
58
+ .optional()
59
+ .describe('Target database config file (.env). When omitted, the CLI falls back to the default config.'),
60
+ schemaPath: z
61
+ .string()
62
+ .min(1)
63
+ .optional()
64
+ .describe('SDF location (file or folder). When omitted, the CLI uses its default (schema).'),
65
+ storagePath: z
66
+ .string()
67
+ .min(1)
68
+ .optional()
69
+ .describe('Source folder for envelope files, relative to cwd. When omitted, the CLI uses its default (data-storage).'),
70
+ batchSize: z
71
+ .number()
72
+ .int()
73
+ .min(1)
74
+ .optional()
75
+ .describe('INSERT batch size (also the commit unit). When omitted, the CLI uses its default (1000).'),
76
+ },
77
+ annotations: {
78
+ title: 'Push Envelope Files into Database',
79
+ readOnlyHint: false,
80
+ idempotentHint: false, // append-only: re-running duplicates rows
81
+ destructiveHint: true, // mutates the target database
82
+ },
83
+ }, async ({ cwd, table, schema, allSchemas, config, schemaPath, storagePath, batchSize }) => {
84
+ const projectCwd = resolve(cwd);
85
+ try {
86
+ await access(join(projectCwd, 'node_modules', '@restforgejs', 'platform'));
87
+ }
88
+ catch {
89
+ return {
90
+ content: [
91
+ {
92
+ type: 'text',
93
+ text: `Precondition not met: the RESTForge package is not installed in this project.
94
+
95
+ Project path: ${projectCwd}
96
+ Expected location: node_modules/@restforgejs/platform
97
+
98
+ For the assistant:
99
+ - The user needs to install the RESTForge package before envelope files can be loaded into a database.
100
+ - Suggest installing the package first, then retry. Do not mention internal tool names.`,
101
+ },
102
+ ],
103
+ isError: false,
104
+ };
105
+ }
106
+ const scopeCount = [table, schema, allSchemas ? true : undefined].filter((v) => v !== undefined).length;
107
+ if (scopeCount !== 1) {
108
+ return {
109
+ content: [
110
+ {
111
+ type: 'text',
112
+ text: `Scope not specified correctly: provide exactly one of 'table', 'schema', or 'allSchemas' (got ${scopeCount}).
113
+
114
+ For the assistant:
115
+ - Ask the user which scope they want: a single table, one/more schemas, or every table with a file. Then retry with exactly one scope set.`,
116
+ },
117
+ ],
118
+ isError: false,
119
+ };
120
+ }
121
+ const args = ['restforge', 'data', 'push'];
122
+ if (table)
123
+ args.push(`--table=${table}`);
124
+ if (schema)
125
+ args.push(`--schema=${schema}`);
126
+ if (allSchemas)
127
+ args.push('--all-schemas');
128
+ if (config)
129
+ args.push(`--config=${config}`);
130
+ if (schemaPath)
131
+ args.push(`--schema-path=${schemaPath}`);
132
+ if (storagePath)
133
+ args.push(`--storage-path=${storagePath}`);
134
+ if (batchSize !== undefined)
135
+ args.push(`--batch-size=${batchSize}`);
136
+ args.push('--json');
137
+ const result = await execProcess('npx', args, { cwd: projectCwd, timeout: 120_000 });
138
+ if (!result.success) {
139
+ return {
140
+ content: [
141
+ {
142
+ type: 'text',
143
+ text: `Failed to push data into the database.
144
+
145
+ Project path: ${projectCwd}
146
+ Scope: ${table ? `table=${table}` : schema ? `schema=${schema}` : 'all-schemas'}
147
+ Command: ${result.command}
148
+ Exit code: ${result.exitCode}
149
+
150
+ --- CLI output ---
151
+ stdout:
152
+ ${result.stdout}
153
+
154
+ stderr:
155
+ ${result.stderr}
156
+ --- end CLI output ---
157
+
158
+ For the assistant:
159
+ - Tell the user the data import did not complete. Note that, because import is append-only and commits per batch, some early batches/tables may already be inserted.
160
+ - Summarise the likely cause from the CLI output. Common causes by exit code: 1 = the envelope file is missing or its shape/columns do not match the SDF; 2 = usage problem (config required but no default, table not registered, schema matched no tables); 3 = database connection or INSERT error.
161
+ - Do not paste raw output unless the user asks. Do not mention internal tool names.`,
162
+ },
163
+ ],
164
+ isError: true,
165
+ };
166
+ }
167
+ return {
168
+ content: [
169
+ {
170
+ type: 'text',
171
+ text: `Data loaded into the database (append-only INSERT).
172
+
173
+ Project path: ${projectCwd}
174
+ Scope: ${table ? `table=${table}` : schema ? `schema=${schema}` : 'all-schemas'}
175
+ Command: ${result.command}
176
+
177
+ --- CLI output (JSON summary) ---
178
+ ${result.stdout}
179
+ --- end CLI output ---
180
+
181
+ For the assistant:
182
+ - Read the JSON summary above and tell the user how many rows/tables were inserted.
183
+ - Remind the user this was append-only: running it again would insert the same rows a second time.
184
+ - Keep the reply concise. Do not paste the raw JSON unless the user explicitly asks. Do not mention internal tool names.`,
185
+ },
186
+ ],
187
+ };
188
+ });
189
+ }
190
+ //# sourceMappingURL=push.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"push.js","sourceRoot":"","sources":["../../../src/tools/data/push.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1C,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,MAAM,UAAU,gBAAgB,CAAC,MAAiB;IAChD,MAAM,CAAC,YAAY,CACjB,WAAW,EACX;QACE,KAAK,EAAE,mCAAmC;QAC1C,WAAW,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;uGA2BoF;QACjG,WAAW,EAAE;YACX,GAAG,EAAE,CAAC;iBACH,MAAM,EAAE;iBACR,GAAG,CAAC,CAAC,CAAC;iBACN,QAAQ,CAAC,8HAA8H,CAAC;YAC3I,KAAK,EAAE,CAAC;iBACL,MAAM,EAAE;iBACR,GAAG,CAAC,CAAC,CAAC;iBACN,QAAQ,EAAE;iBACV,QAAQ,CAAC,sIAAsI,CAAC;YACnJ,MAAM,EAAE,CAAC;iBACN,MAAM,EAAE;iBACR,GAAG,CAAC,CAAC,CAAC;iBACN,QAAQ,EAAE;iBACV,QAAQ,CAAC,yLAAyL,CAAC;YACtM,UAAU,EAAE,CAAC;iBACV,OAAO,EAAE;iBACT,QAAQ,EAAE;iBACV,QAAQ,CAAC,4IAA4I,CAAC;YACzJ,MAAM,EAAE,CAAC;iBACN,MAAM,EAAE;iBACR,GAAG,CAAC,CAAC,CAAC;iBACN,QAAQ,EAAE;iBACV,QAAQ,CAAC,6FAA6F,CAAC;YAC1G,UAAU,EAAE,CAAC;iBACV,MAAM,EAAE;iBACR,GAAG,CAAC,CAAC,CAAC;iBACN,QAAQ,EAAE;iBACV,QAAQ,CAAC,iFAAiF,CAAC;YAC9F,WAAW,EAAE,CAAC;iBACX,MAAM,EAAE;iBACR,GAAG,CAAC,CAAC,CAAC;iBACN,QAAQ,EAAE;iBACV,QAAQ,CAAC,2GAA2G,CAAC;YACxH,SAAS,EAAE,CAAC;iBACT,MAAM,EAAE;iBACR,GAAG,EAAE;iBACL,GAAG,CAAC,CAAC,CAAC;iBACN,QAAQ,EAAE;iBACV,QAAQ,CAAC,0FAA0F,CAAC;SACxG;QACD,WAAW,EAAE;YACX,KAAK,EAAE,mCAAmC;YAC1C,YAAY,EAAE,KAAK;YACnB,cAAc,EAAE,KAAK,EAAE,0CAA0C;YACjE,eAAe,EAAE,IAAI,EAAE,8BAA8B;SACtD;KACF,EACD,KAAK,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,SAAS,EAAE,EAAE,EAAE;QACvF,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;QAEhC,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,cAAc,EAAE,cAAc,EAAE,UAAU,CAAC,CAAC,CAAC;QAC7E,CAAC;QAAC,MAAM,CAAC;YACP,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE;;gBAEJ,UAAU;;;;;wFAK8D;qBAC3E;iBACF;gBACD,OAAO,EAAE,KAAK;aACf,CAAC;QACJ,CAAC;QAED,MAAM,UAAU,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,MAAM,CAAC;QACxG,IAAI,UAAU,KAAK,CAAC,EAAE,CAAC;YACrB,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,iGAAiG,UAAU;;;2IAGY;qBAC9H;iBACF;gBACD,OAAO,EAAE,KAAK;aACf,CAAC;QACJ,CAAC;QAED,MAAM,IAAI,GAAG,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;QAC3C,IAAI,KAAK;YAAE,IAAI,CAAC,IAAI,CAAC,WAAW,KAAK,EAAE,CAAC,CAAC;QACzC,IAAI,MAAM;YAAE,IAAI,CAAC,IAAI,CAAC,YAAY,MAAM,EAAE,CAAC,CAAC;QAC5C,IAAI,UAAU;YAAE,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QAC3C,IAAI,MAAM;YAAE,IAAI,CAAC,IAAI,CAAC,YAAY,MAAM,EAAE,CAAC,CAAC;QAC5C,IAAI,UAAU;YAAE,IAAI,CAAC,IAAI,CAAC,iBAAiB,UAAU,EAAE,CAAC,CAAC;QACzD,IAAI,WAAW;YAAE,IAAI,CAAC,IAAI,CAAC,kBAAkB,WAAW,EAAE,CAAC,CAAC;QAC5D,IAAI,SAAS,KAAK,SAAS;YAAE,IAAI,CAAC,IAAI,CAAC,gBAAgB,SAAS,EAAE,CAAC,CAAC;QACpE,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAEpB,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;QAErF,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE;;gBAEJ,UAAU;SACjB,KAAK,CAAC,CAAC,CAAC,SAAS,KAAK,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,MAAM,EAAE,CAAC,CAAC,CAAC,aAAa;WACpE,MAAM,CAAC,OAAO;aACZ,MAAM,CAAC,QAAQ;;;;EAI1B,MAAM,CAAC,MAAM;;;EAGb,MAAM,CAAC,MAAM;;;;;;oFAMqE;qBACvE;iBACF;gBACD,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;QAED,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE;;gBAEF,UAAU;SACjB,KAAK,CAAC,CAAC,CAAC,SAAS,KAAK,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,MAAM,EAAE,CAAC,CAAC,CAAC,aAAa;WACpE,MAAM,CAAC,OAAO;;;EAGvB,MAAM,CAAC,MAAM;;;;;;yHAM0G;iBAC9G;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}