@restforgejs/mcp-server 1.2.3 → 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.
- package/dist/server.js +52 -7
- package/dist/server.js.map +1 -1
- package/dist/tools/codegen/create-kafka-consumer.d.ts +2 -0
- package/dist/tools/codegen/create-kafka-consumer.js +140 -0
- package/dist/tools/codegen/create-kafka-consumer.js.map +1 -0
- package/dist/tools/codegen/create-processor.d.ts +2 -0
- package/dist/tools/codegen/create-processor.js +157 -0
- package/dist/tools/codegen/create-processor.js.map +1 -0
- package/dist/tools/codegen/generate-test.d.ts +2 -0
- package/dist/tools/codegen/generate-test.js +149 -0
- package/dist/tools/codegen/generate-test.js.map +1 -0
- package/dist/tools/codegen/index.js +6 -0
- package/dist/tools/codegen/index.js.map +1 -1
- package/dist/tools/codegen/migrate-payload.js +3 -0
- package/dist/tools/codegen/migrate-payload.js.map +1 -1
- package/dist/tools/data/index.d.ts +2 -0
- package/dist/tools/data/index.js +7 -0
- package/dist/tools/data/index.js.map +1 -0
- package/dist/tools/data/pull.d.ts +2 -0
- package/dist/tools/data/pull.js +202 -0
- package/dist/tools/data/pull.js.map +1 -0
- package/dist/tools/data/push.d.ts +2 -0
- package/dist/tools/data/push.js +190 -0
- package/dist/tools/data/push.js.map +1 -0
- package/dist/tools/key/generate.d.ts +2 -0
- package/dist/tools/key/generate.js +130 -0
- package/dist/tools/key/generate.js.map +1 -0
- package/dist/tools/key/index.d.ts +2 -0
- package/dist/tools/key/index.js +9 -0
- package/dist/tools/key/index.js.map +1 -0
- package/dist/tools/key/list.d.ts +2 -0
- package/dist/tools/key/list.js +126 -0
- package/dist/tools/key/list.js.map +1 -0
- package/dist/tools/key/revoke.d.ts +2 -0
- package/dist/tools/key/revoke.js +117 -0
- package/dist/tools/key/revoke.js.map +1 -0
- package/dist/tools/project/delete.d.ts +2 -0
- package/dist/tools/project/delete.js +116 -0
- package/dist/tools/project/delete.js.map +1 -0
- package/dist/tools/project/index.d.ts +2 -0
- package/dist/tools/project/index.js +7 -0
- package/dist/tools/project/index.js.map +1 -0
- package/dist/tools/project/list.d.ts +2 -0
- package/dist/tools/project/list.js +107 -0
- package/dist/tools/project/list.js.map +1 -0
- package/dist/tools/setup/clear-default-config.d.ts +2 -0
- package/dist/tools/setup/clear-default-config.js +104 -0
- package/dist/tools/setup/clear-default-config.js.map +1 -0
- package/dist/tools/setup/get-default-config.d.ts +2 -0
- package/dist/tools/setup/get-default-config.js +104 -0
- package/dist/tools/setup/get-default-config.js.map +1 -0
- package/dist/tools/setup/index.js +8 -0
- package/dist/tools/setup/index.js.map +1 -1
- package/dist/tools/setup/init-config.js +3 -5
- package/dist/tools/setup/init-config.js.map +1 -1
- package/dist/tools/setup/list-configs.d.ts +2 -0
- package/dist/tools/setup/list-configs.js +104 -0
- package/dist/tools/setup/list-configs.js.map +1 -0
- package/dist/tools/setup/set-default-config.d.ts +2 -0
- package/dist/tools/setup/set-default-config.js +109 -0
- package/dist/tools/setup/set-default-config.js.map +1 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migrate-payload.js","sourceRoot":"","sources":["../../../src/tools/codegen/migrate-payload.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,6BAA6B,CAAC,MAAiB;IAC7D,MAAM,CAAC,YAAY,CACjB,yBAAyB,EACzB;QACE,KAAK,EAAE,+CAA+C;QACtD,WAAW,EAAE
|
|
1
|
+
{"version":3,"file":"migrate-payload.js","sourceRoot":"","sources":["../../../src/tools/codegen/migrate-payload.ts"],"names":[],"mappings":"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"}
|
|
@@ -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,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,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":"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"}
|
|
@@ -0,0 +1,130 @@
|
|
|
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 registerKeyGenerate(server) {
|
|
6
|
+
server.registerTool('key_generate', {
|
|
7
|
+
title: 'Generate API Key',
|
|
8
|
+
description: `Generate a new API key and write it into an .env file, by wrapping restforge key generate.
|
|
9
|
+
|
|
10
|
+
USE WHEN:
|
|
11
|
+
- The user wants to create/generate a new API key for a RESTForge project, e.g. "buat api key", "generate api key", "bikin key baru"
|
|
12
|
+
- The user is setting up authentication and needs a key written to .env
|
|
13
|
+
|
|
14
|
+
DO NOT USE FOR:
|
|
15
|
+
- Listing existing keys -> use 'key_list'
|
|
16
|
+
- Revoking a key -> use 'key_revoke'
|
|
17
|
+
- Writing arbitrary env values -> use 'setup_write_env'
|
|
18
|
+
|
|
19
|
+
This tool runs: npx restforge key generate [--output] [--force] in the given cwd.
|
|
20
|
+
|
|
21
|
+
NON-INTERACTIVE NOTE: if a key already exists in the output file and 'force' is not set, the CLI asks for overwrite confirmation. In this non-interactive context that prompt cannot be answered and the call may stall until timeout — set 'force' to regenerate over an existing key. Generating into a file with no existing key works without 'force'.
|
|
22
|
+
|
|
23
|
+
SECURITY NOTE: the generated key value is sensitive and will appear in this tool's output. Do not echo it back to the user in plain text unless they ask; the key is written to the .env file.
|
|
24
|
+
|
|
25
|
+
Preconditions:
|
|
26
|
+
- The project must have @restforgejs/platform installed in node_modules.
|
|
27
|
+
|
|
28
|
+
PRESENTATION GUIDANCE:
|
|
29
|
+
- Match the user's language. Never mention internal tool names; describe the action (e.g. "generate the API key").
|
|
30
|
+
- Confirm the key was written to the target file; do not paste the raw key unless the user explicitly asks for it.
|
|
31
|
+
- When a precondition is not met, frame it as a question or next-step suggestion rather than an error.`,
|
|
32
|
+
inputSchema: {
|
|
33
|
+
cwd: z
|
|
34
|
+
.string()
|
|
35
|
+
.min(1)
|
|
36
|
+
.describe('Absolute path of the project folder (must contain node_modules/@restforgejs/platform)'),
|
|
37
|
+
output: z
|
|
38
|
+
.string()
|
|
39
|
+
.min(1)
|
|
40
|
+
.optional()
|
|
41
|
+
.describe('Output .env file to write the key into (relative to cwd; must be INSIDE the project directory — the CLI rejects paths outside cwd). When omitted, the CLI uses its default (.env).'),
|
|
42
|
+
force: z
|
|
43
|
+
.boolean()
|
|
44
|
+
.optional()
|
|
45
|
+
.describe('Overwrite an existing key without confirmation. Set this to regenerate over an existing key (otherwise the CLI may prompt and stall).'),
|
|
46
|
+
},
|
|
47
|
+
annotations: {
|
|
48
|
+
title: 'Generate API Key',
|
|
49
|
+
readOnlyHint: false,
|
|
50
|
+
idempotentHint: false,
|
|
51
|
+
destructiveHint: false,
|
|
52
|
+
},
|
|
53
|
+
}, async ({ cwd, output, force }) => {
|
|
54
|
+
const projectCwd = resolve(cwd);
|
|
55
|
+
try {
|
|
56
|
+
await access(join(projectCwd, 'node_modules', '@restforgejs', 'platform'));
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
return {
|
|
60
|
+
content: [
|
|
61
|
+
{
|
|
62
|
+
type: 'text',
|
|
63
|
+
text: `Precondition not met: the RESTForge package is not installed in this project.
|
|
64
|
+
|
|
65
|
+
Project path: ${projectCwd}
|
|
66
|
+
Expected location: node_modules/@restforgejs/platform
|
|
67
|
+
|
|
68
|
+
For the assistant:
|
|
69
|
+
- The user needs to install the RESTForge package before an API key can be generated. Suggest installing it first, then retry. Do not mention internal tool names.`,
|
|
70
|
+
},
|
|
71
|
+
],
|
|
72
|
+
isError: false,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
const args = ['restforge', 'key', 'generate'];
|
|
76
|
+
if (output)
|
|
77
|
+
args.push(`--output=${output}`);
|
|
78
|
+
if (force)
|
|
79
|
+
args.push('--force');
|
|
80
|
+
const result = await execProcess('npx', args, { cwd: projectCwd, timeout: 60_000 });
|
|
81
|
+
if (!result.success) {
|
|
82
|
+
return {
|
|
83
|
+
content: [
|
|
84
|
+
{
|
|
85
|
+
type: 'text',
|
|
86
|
+
text: `Failed to generate the API key.
|
|
87
|
+
|
|
88
|
+
Project path: ${projectCwd}
|
|
89
|
+
Output: ${output ?? 'default (.env)'}
|
|
90
|
+
Command: ${result.command}
|
|
91
|
+
Exit code: ${result.exitCode}
|
|
92
|
+
|
|
93
|
+
--- CLI output ---
|
|
94
|
+
stdout:
|
|
95
|
+
${result.stdout}
|
|
96
|
+
|
|
97
|
+
stderr:
|
|
98
|
+
${result.stderr}
|
|
99
|
+
--- end CLI output ---
|
|
100
|
+
|
|
101
|
+
For the assistant:
|
|
102
|
+
- Tell the user the API key was not generated. A common cause is that a key already exists and overwrite was not allowed (the operation may have stalled waiting for confirmation) — suggest retrying with overwrite enabled. Do not paste raw output unless asked. Do not mention internal tool names.`,
|
|
103
|
+
},
|
|
104
|
+
],
|
|
105
|
+
isError: true,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
return {
|
|
109
|
+
content: [
|
|
110
|
+
{
|
|
111
|
+
type: 'text',
|
|
112
|
+
text: `API key generated.
|
|
113
|
+
|
|
114
|
+
Project path: ${projectCwd}
|
|
115
|
+
Output: ${output ?? 'default (.env)'}
|
|
116
|
+
Command: ${result.command}
|
|
117
|
+
|
|
118
|
+
--- CLI output ---
|
|
119
|
+
${result.stdout}
|
|
120
|
+
--- end CLI output ---
|
|
121
|
+
|
|
122
|
+
For the assistant:
|
|
123
|
+
- Confirm the key was written to the target .env file. Treat the key value as a secret: do not repeat it back in plain text unless the user explicitly asks.
|
|
124
|
+
- Keep the reply concise. Do not mention internal tool names.`,
|
|
125
|
+
},
|
|
126
|
+
],
|
|
127
|
+
};
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=generate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate.js","sourceRoot":"","sources":["../../../src/tools/key/generate.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,mBAAmB,CAAC,MAAiB;IACnD,MAAM,CAAC,YAAY,CACjB,cAAc,EACd;QACE,KAAK,EAAE,kBAAkB;QACzB,WAAW,EAAE;;;;;;;;;;;;;;;;;;;;;;;uGAuBoF;QACjG,WAAW,EAAE;YACX,GAAG,EAAE,CAAC;iBACH,MAAM,EAAE;iBACR,GAAG,CAAC,CAAC,CAAC;iBACN,QAAQ,CAAC,uFAAuF,CAAC;YACpG,MAAM,EAAE,CAAC;iBACN,MAAM,EAAE;iBACR,GAAG,CAAC,CAAC,CAAC;iBACN,QAAQ,EAAE;iBACV,QAAQ,CAAC,oLAAoL,CAAC;YACjM,KAAK,EAAE,CAAC;iBACL,OAAO,EAAE;iBACT,QAAQ,EAAE;iBACV,QAAQ,CAAC,uIAAuI,CAAC;SACrJ;QACD,WAAW,EAAE;YACX,KAAK,EAAE,kBAAkB;YACzB,YAAY,EAAE,KAAK;YACnB,cAAc,EAAE,KAAK;YACrB,eAAe,EAAE,KAAK;SACvB;KACF,EACD,KAAK,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE;QAC/B,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;QAChC,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;;;;mKAIyI;qBACtJ;iBACF;gBACD,OAAO,EAAE,KAAK;aACf,CAAC;QACJ,CAAC;QAED,MAAM,IAAI,GAAG,CAAC,WAAW,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC;QAC9C,IAAI,MAAM;YAAE,IAAI,CAAC,IAAI,CAAC,YAAY,MAAM,EAAE,CAAC,CAAC;QAC5C,IAAI,KAAK;YAAE,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAEhC,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QAEpF,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE;;gBAEJ,UAAU;UAChB,MAAM,IAAI,gBAAgB;WACzB,MAAM,CAAC,OAAO;aACZ,MAAM,CAAC,QAAQ;;;;EAI1B,MAAM,CAAC,MAAM;;;EAGb,MAAM,CAAC,MAAM;;;;wSAIyR;qBAC3R;iBACF;gBACD,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;QAED,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE;;gBAEF,UAAU;UAChB,MAAM,IAAI,gBAAgB;WACzB,MAAM,CAAC,OAAO;;;EAGvB,MAAM,CAAC,MAAM;;;;;8DAK+C;iBACnD;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { registerKeyGenerate } from './generate.js';
|
|
2
|
+
import { registerKeyList } from './list.js';
|
|
3
|
+
import { registerKeyRevoke } from './revoke.js';
|
|
4
|
+
export function registerKeyTools(server) {
|
|
5
|
+
registerKeyGenerate(server);
|
|
6
|
+
registerKeyList(server);
|
|
7
|
+
registerKeyRevoke(server);
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tools/key/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEhD,MAAM,UAAU,gBAAgB,CAAC,MAAiB;IAChD,mBAAmB,CAAC,MAAM,CAAC,CAAC;IAC5B,eAAe,CAAC,MAAM,CAAC,CAAC;IACxB,iBAAiB,CAAC,MAAM,CAAC,CAAC;AAC5B,CAAC"}
|