@restforgejs/mcp-server 1.2.0
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/LICENSE.md +21 -0
- package/README.md +149 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/env-parser.d.ts +30 -0
- package/dist/lib/env-parser.js +150 -0
- package/dist/lib/env-parser.js.map +1 -0
- package/dist/lib/exec.d.ts +29 -0
- package/dist/lib/exec.js +38 -0
- package/dist/lib/exec.js.map +1 -0
- package/dist/server.d.ts +1 -0
- package/dist/server.js +220 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/codegen/create-dashboard.d.ts +2 -0
- package/dist/tools/codegen/create-dashboard.js +256 -0
- package/dist/tools/codegen/create-dashboard.js.map +1 -0
- package/dist/tools/codegen/create-endpoint.d.ts +2 -0
- package/dist/tools/codegen/create-endpoint.js +263 -0
- package/dist/tools/codegen/create-endpoint.js.map +1 -0
- package/dist/tools/codegen/dbschema-generate-ddl.d.ts +2 -0
- package/dist/tools/codegen/dbschema-generate-ddl.js +187 -0
- package/dist/tools/codegen/dbschema-generate-ddl.js.map +1 -0
- package/dist/tools/codegen/dbschema-init.d.ts +2 -0
- package/dist/tools/codegen/dbschema-init.js +158 -0
- package/dist/tools/codegen/dbschema-init.js.map +1 -0
- package/dist/tools/codegen/dbschema-introspect.d.ts +2 -0
- package/dist/tools/codegen/dbschema-introspect.js +241 -0
- package/dist/tools/codegen/dbschema-introspect.js.map +1 -0
- package/dist/tools/codegen/dbschema-migrate.d.ts +2 -0
- package/dist/tools/codegen/dbschema-migrate.js +219 -0
- package/dist/tools/codegen/dbschema-migrate.js.map +1 -0
- package/dist/tools/codegen/dbschema-models.d.ts +2 -0
- package/dist/tools/codegen/dbschema-models.js +146 -0
- package/dist/tools/codegen/dbschema-models.js.map +1 -0
- package/dist/tools/codegen/dbschema-validate.d.ts +2 -0
- package/dist/tools/codegen/dbschema-validate.js +153 -0
- package/dist/tools/codegen/dbschema-validate.js.map +1 -0
- package/dist/tools/codegen/describe-table.d.ts +2 -0
- package/dist/tools/codegen/describe-table.js +259 -0
- package/dist/tools/codegen/describe-table.js.map +1 -0
- package/dist/tools/codegen/diff-payload.d.ts +2 -0
- package/dist/tools/codegen/diff-payload.js +165 -0
- package/dist/tools/codegen/diff-payload.js.map +1 -0
- package/dist/tools/codegen/generate-payload.d.ts +2 -0
- package/dist/tools/codegen/generate-payload.js +145 -0
- package/dist/tools/codegen/generate-payload.js.map +1 -0
- package/dist/tools/codegen/get-dashboard-catalog.d.ts +2 -0
- package/dist/tools/codegen/get-dashboard-catalog.js +213 -0
- package/dist/tools/codegen/get-dashboard-catalog.js.map +1 -0
- package/dist/tools/codegen/get-dbschema-catalog.d.ts +2 -0
- package/dist/tools/codegen/get-dbschema-catalog.js +244 -0
- package/dist/tools/codegen/get-dbschema-catalog.js.map +1 -0
- package/dist/tools/codegen/get-field-validation-catalog.d.ts +2 -0
- package/dist/tools/codegen/get-field-validation-catalog.js +186 -0
- package/dist/tools/codegen/get-field-validation-catalog.js.map +1 -0
- package/dist/tools/codegen/get-query-declarative-catalog.d.ts +2 -0
- package/dist/tools/codegen/get-query-declarative-catalog.js +200 -0
- package/dist/tools/codegen/get-query-declarative-catalog.js.map +1 -0
- package/dist/tools/codegen/index.d.ts +2 -0
- package/dist/tools/codegen/index.js +43 -0
- package/dist/tools/codegen/index.js.map +1 -0
- package/dist/tools/codegen/list-tables.d.ts +2 -0
- package/dist/tools/codegen/list-tables.js +220 -0
- package/dist/tools/codegen/list-tables.js.map +1 -0
- package/dist/tools/codegen/sync-payload.d.ts +2 -0
- package/dist/tools/codegen/sync-payload.js +177 -0
- package/dist/tools/codegen/sync-payload.js.map +1 -0
- package/dist/tools/codegen/validate-dashboard-payload.d.ts +2 -0
- package/dist/tools/codegen/validate-dashboard-payload.js +239 -0
- package/dist/tools/codegen/validate-dashboard-payload.js.map +1 -0
- package/dist/tools/codegen/validate-payload.d.ts +2 -0
- package/dist/tools/codegen/validate-payload.js +166 -0
- package/dist/tools/codegen/validate-payload.js.map +1 -0
- package/dist/tools/codegen/validate-sql.d.ts +2 -0
- package/dist/tools/codegen/validate-sql.js +270 -0
- package/dist/tools/codegen/validate-sql.js.map +1 -0
- package/dist/tools/health/index.d.ts +2 -0
- package/dist/tools/health/index.js +5 -0
- package/dist/tools/health/index.js.map +1 -0
- package/dist/tools/health/ping.d.ts +2 -0
- package/dist/tools/health/ping.js +68 -0
- package/dist/tools/health/ping.js.map +1 -0
- package/dist/tools/runtime/check-launcher-exists.d.ts +2 -0
- package/dist/tools/runtime/check-launcher-exists.js +111 -0
- package/dist/tools/runtime/check-launcher-exists.js.map +1 -0
- package/dist/tools/runtime/check-status.d.ts +2 -0
- package/dist/tools/runtime/check-status.js +417 -0
- package/dist/tools/runtime/check-status.js.map +1 -0
- package/dist/tools/runtime/detect-config.d.ts +2 -0
- package/dist/tools/runtime/detect-config.js +130 -0
- package/dist/tools/runtime/detect-config.js.map +1 -0
- package/dist/tools/runtime/detect-project.d.ts +2 -0
- package/dist/tools/runtime/detect-project.js +132 -0
- package/dist/tools/runtime/detect-project.js.map +1 -0
- package/dist/tools/runtime/generate-launcher.d.ts +2 -0
- package/dist/tools/runtime/generate-launcher.js +438 -0
- package/dist/tools/runtime/generate-launcher.js.map +1 -0
- package/dist/tools/runtime/index.d.ts +2 -0
- package/dist/tools/runtime/index.js +15 -0
- package/dist/tools/runtime/index.js.map +1 -0
- package/dist/tools/runtime/validate-preflight.d.ts +2 -0
- package/dist/tools/runtime/validate-preflight.js +209 -0
- package/dist/tools/runtime/validate-preflight.js.map +1 -0
- package/dist/tools/setup/create-folder.d.ts +2 -0
- package/dist/tools/setup/create-folder.js +138 -0
- package/dist/tools/setup/create-folder.js.map +1 -0
- package/dist/tools/setup/get-config-schema.d.ts +2 -0
- package/dist/tools/setup/get-config-schema.js +158 -0
- package/dist/tools/setup/get-config-schema.js.map +1 -0
- package/dist/tools/setup/get-init-template.d.ts +2 -0
- package/dist/tools/setup/get-init-template.js +130 -0
- package/dist/tools/setup/get-init-template.js.map +1 -0
- package/dist/tools/setup/index.d.ts +2 -0
- package/dist/tools/setup/index.js +21 -0
- package/dist/tools/setup/index.js.map +1 -0
- package/dist/tools/setup/init-config.d.ts +2 -0
- package/dist/tools/setup/init-config.js +120 -0
- package/dist/tools/setup/init-config.js.map +1 -0
- package/dist/tools/setup/install-package.d.ts +2 -0
- package/dist/tools/setup/install-package.js +133 -0
- package/dist/tools/setup/install-package.js.map +1 -0
- package/dist/tools/setup/read-env.d.ts +2 -0
- package/dist/tools/setup/read-env.js +138 -0
- package/dist/tools/setup/read-env.js.map +1 -0
- package/dist/tools/setup/update-env.d.ts +2 -0
- package/dist/tools/setup/update-env.js +176 -0
- package/dist/tools/setup/update-env.js.map +1 -0
- package/dist/tools/setup/validate-config.d.ts +2 -0
- package/dist/tools/setup/validate-config.js +138 -0
- package/dist/tools/setup/validate-config.js.map +1 -0
- package/dist/tools/setup/write-env.d.ts +2 -0
- package/dist/tools/setup/write-env.js +168 -0
- package/dist/tools/setup/write-env.js.map +1 -0
- package/package.json +60 -0
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { access, readFile } from 'node:fs/promises';
|
|
3
|
+
import { resolve, join } from 'node:path';
|
|
4
|
+
import { createServer } from 'node:net';
|
|
5
|
+
import { execProcess } from '../../lib/exec.js';
|
|
6
|
+
async function checkPortAvailable(port) {
|
|
7
|
+
return new Promise((resolveFn) => {
|
|
8
|
+
const tester = createServer()
|
|
9
|
+
.once('error', () => resolveFn(false))
|
|
10
|
+
.once('listening', () => {
|
|
11
|
+
tester.close(() => resolveFn(true));
|
|
12
|
+
})
|
|
13
|
+
.listen(port);
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
function isProcessAlive(pid) {
|
|
17
|
+
try {
|
|
18
|
+
process.kill(pid, 0);
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
catch (err) {
|
|
22
|
+
const e = err;
|
|
23
|
+
if (e.code === 'ESRCH')
|
|
24
|
+
return false;
|
|
25
|
+
if (e.code === 'EPERM')
|
|
26
|
+
return true;
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function truncate(s, n) {
|
|
31
|
+
return s.length > n ? s.substring(0, n) + '...' : s;
|
|
32
|
+
}
|
|
33
|
+
export function registerRuntimeValidatePreflight(server) {
|
|
34
|
+
server.registerTool('runtime_validate_preflight', {
|
|
35
|
+
title: 'Validate RESTForge Runtime Preflight',
|
|
36
|
+
description: `Run a runtime preflight check before generating a launcher. Wraps 'npx restforge validate --config=<config>' (license + database + redis/kafka) and additionally inspects: (1) .restforge/server.pid to detect a possibly-running server, (2) optional local port availability via Node net binding.
|
|
37
|
+
|
|
38
|
+
USE WHEN:
|
|
39
|
+
- Before invoking 'runtime_generate_launcher' — to verify the project is ready to launch
|
|
40
|
+
- The user asks "is this ready to run?", "preflight check", "cek apakah server bisa dijalankan"
|
|
41
|
+
- After changing config or installing a new license — to verify everything still works
|
|
42
|
+
- The user reports the server fails to start — to identify the failing component
|
|
43
|
+
|
|
44
|
+
DO NOT USE FOR:
|
|
45
|
+
- Validating ONLY the config (license/database) without runtime context -> use 'setup_validate_config'
|
|
46
|
+
- Listing or reading config values -> use 'setup_read_env'
|
|
47
|
+
- Generating launcher files -> use 'runtime_generate_launcher'
|
|
48
|
+
|
|
49
|
+
This tool runs: npx restforge validate --config=<config> in the given cwd, plus filesystem checks (PID file, optional port).
|
|
50
|
+
|
|
51
|
+
Preconditions:
|
|
52
|
+
- The project must have @restforgejs/platform installed in node_modules.
|
|
53
|
+
- The config file must exist in the config/ folder.
|
|
54
|
+
|
|
55
|
+
PRESENTATION GUIDANCE:
|
|
56
|
+
- Match the user's language.
|
|
57
|
+
- Never mention internal tool names.
|
|
58
|
+
- Summarise by component: license, database, optional redis/kafka, PID file presence, port availability.
|
|
59
|
+
- Do not echo license keys, passwords, or full connection URIs from the CLI output.
|
|
60
|
+
- Preflight failure is informational, not a blocker. The user can still proceed to generate the launcher (with a warning recorded).
|
|
61
|
+
- Port check is best-effort: a "free" result on this machine does not guarantee the port is free for the eventual server bind address (which may differ).`,
|
|
62
|
+
inputSchema: {
|
|
63
|
+
cwd: z.string().min(1).describe('Absolute path of the project folder root'),
|
|
64
|
+
config: z
|
|
65
|
+
.string()
|
|
66
|
+
.min(1)
|
|
67
|
+
.default('db-connection.env')
|
|
68
|
+
.describe('Config file name in the config/ folder (default: db-connection.env)'),
|
|
69
|
+
port: z
|
|
70
|
+
.number()
|
|
71
|
+
.int()
|
|
72
|
+
.min(1)
|
|
73
|
+
.max(65535)
|
|
74
|
+
.optional()
|
|
75
|
+
.describe('Port to check availability (optional). When set, the tool tries to bind locally to detect if the port is free.'),
|
|
76
|
+
},
|
|
77
|
+
annotations: {
|
|
78
|
+
title: 'Validate Runtime Preflight',
|
|
79
|
+
readOnlyHint: true,
|
|
80
|
+
idempotentHint: false,
|
|
81
|
+
},
|
|
82
|
+
}, async ({ cwd, config, port }) => {
|
|
83
|
+
const projectCwd = resolve(cwd);
|
|
84
|
+
try {
|
|
85
|
+
await access(join(projectCwd, 'node_modules', '@restforgejs', 'platform'));
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
return {
|
|
89
|
+
content: [
|
|
90
|
+
{
|
|
91
|
+
type: 'text',
|
|
92
|
+
text: `Precondition not met: the RESTForge package is not installed in this project.
|
|
93
|
+
|
|
94
|
+
Project path: ${projectCwd}
|
|
95
|
+
Expected location: node_modules/@restforgejs/platform
|
|
96
|
+
|
|
97
|
+
For the assistant:
|
|
98
|
+
- The user needs to install the RESTForge package before runtime preflight can run.
|
|
99
|
+
- Suggest installing the package first, then retry preflight.
|
|
100
|
+
- Match the user's language. Do not mention internal tool names.`,
|
|
101
|
+
},
|
|
102
|
+
],
|
|
103
|
+
isError: false,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
const result = {
|
|
107
|
+
config_validation: {
|
|
108
|
+
ran: false,
|
|
109
|
+
success: false,
|
|
110
|
+
cli_command: '',
|
|
111
|
+
cli_exit_code: -1,
|
|
112
|
+
cli_stdout: '',
|
|
113
|
+
cli_stderr: '',
|
|
114
|
+
},
|
|
115
|
+
pid_file: { path: '', exists: false, pid: null, process_alive: null },
|
|
116
|
+
port_check: {
|
|
117
|
+
requested: port !== undefined,
|
|
118
|
+
port: port ?? null,
|
|
119
|
+
available: null,
|
|
120
|
+
},
|
|
121
|
+
warnings: [],
|
|
122
|
+
errors: [],
|
|
123
|
+
};
|
|
124
|
+
const cliResult = await execProcess('npx', ['restforge', 'validate', `--config=${config}`], { cwd: projectCwd, timeout: 30_000 });
|
|
125
|
+
result.config_validation = {
|
|
126
|
+
ran: true,
|
|
127
|
+
success: cliResult.success,
|
|
128
|
+
cli_command: cliResult.command,
|
|
129
|
+
cli_exit_code: cliResult.exitCode,
|
|
130
|
+
cli_stdout: truncate(cliResult.stdout || '', 500),
|
|
131
|
+
cli_stderr: truncate(cliResult.stderr || '', 500),
|
|
132
|
+
};
|
|
133
|
+
if (!cliResult.success) {
|
|
134
|
+
result.warnings.push('Config validation did not pass — see config_validation.cli_stderr for details.');
|
|
135
|
+
}
|
|
136
|
+
const pidPath = join(projectCwd, '.restforge', 'server.pid');
|
|
137
|
+
result.pid_file.path = pidPath;
|
|
138
|
+
try {
|
|
139
|
+
const raw = await readFile(pidPath, 'utf8');
|
|
140
|
+
const pid = parseInt(raw.trim(), 10);
|
|
141
|
+
result.pid_file.exists = true;
|
|
142
|
+
if (Number.isFinite(pid) && pid > 0) {
|
|
143
|
+
result.pid_file.pid = pid;
|
|
144
|
+
result.pid_file.process_alive = isProcessAlive(pid);
|
|
145
|
+
if (result.pid_file.process_alive === true) {
|
|
146
|
+
result.warnings.push(`A server appears to be already running with PID ${pid}. Stop it first or it may conflict on the port.`);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
result.warnings.push('PID file exists but contains an invalid value.');
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
catch {
|
|
154
|
+
result.pid_file.exists = false;
|
|
155
|
+
}
|
|
156
|
+
if (port !== undefined) {
|
|
157
|
+
result.port_check.available = await checkPortAvailable(port);
|
|
158
|
+
if (result.port_check.available === false) {
|
|
159
|
+
result.warnings.push(`Port ${port} is already in use on this machine.`);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
const envelope = result;
|
|
163
|
+
const prettyJson = JSON.stringify(envelope, null, 2);
|
|
164
|
+
const allPassed = result.config_validation.success && result.warnings.length === 0;
|
|
165
|
+
const summary = allPassed
|
|
166
|
+
? 'Runtime preflight passed: config valid, no PID file conflict, port available.'
|
|
167
|
+
: 'Runtime preflight completed with warnings — see details below.';
|
|
168
|
+
const pidFileSummary = result.pid_file.exists
|
|
169
|
+
? `exists (pid=${result.pid_file.pid}, alive=${result.pid_file.process_alive})`
|
|
170
|
+
: 'absent';
|
|
171
|
+
const portSummary = result.port_check.requested
|
|
172
|
+
? result.port_check.available
|
|
173
|
+
? 'yes'
|
|
174
|
+
: 'no'
|
|
175
|
+
: '(not checked)';
|
|
176
|
+
return {
|
|
177
|
+
content: [
|
|
178
|
+
{
|
|
179
|
+
type: 'text',
|
|
180
|
+
text: `${summary}
|
|
181
|
+
|
|
182
|
+
Project path: ${projectCwd}
|
|
183
|
+
Config: ${config}
|
|
184
|
+
Port checked: ${port ?? '(not requested)'}
|
|
185
|
+
Config validation: ${result.config_validation.success ? 'OK' : 'FAILED'}
|
|
186
|
+
PID file: ${pidFileSummary}
|
|
187
|
+
Port available: ${portSummary}
|
|
188
|
+
Warnings: ${result.warnings.length}
|
|
189
|
+
|
|
190
|
+
--- Preflight Result (JSON) ---
|
|
191
|
+
${prettyJson}
|
|
192
|
+
--- end Preflight Result (JSON) ---
|
|
193
|
+
|
|
194
|
+
For the assistant:
|
|
195
|
+
- ${allPassed
|
|
196
|
+
? 'All preflight checks passed. The user can proceed to generate the launcher.'
|
|
197
|
+
: 'Some checks reported warnings. Summarise them in plain language to the user. The user can still choose to proceed (the launcher will be generated regardless).'}
|
|
198
|
+
- Config validation runs the same checks as the standalone validator: license, database connection, and any enabled feature dependencies (redis, kafka).
|
|
199
|
+
- PID file check inspects .restforge/server.pid: if a process is alive, warn the user that another server may be running.
|
|
200
|
+
- Port check is best-effort: it tries to bind locally to the port. A port may still be in use by another machine on the same address — this only checks the local machine.
|
|
201
|
+
- Do not echo full CLI stdout/stderr unless explicitly asked. Do not echo license keys or credentials.
|
|
202
|
+
- Match the user's language. Do not mention internal tool names.`,
|
|
203
|
+
},
|
|
204
|
+
],
|
|
205
|
+
isError: false,
|
|
206
|
+
};
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
//# sourceMappingURL=validate-preflight.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-preflight.js","sourceRoot":"","sources":["../../../src/tools/runtime/validate-preflight.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { mkdir, access } from 'node:fs/promises';
|
|
3
|
+
import { resolve, join } from 'node:path';
|
|
4
|
+
export function registerSetupCreateFolder(server) {
|
|
5
|
+
server.registerTool('setup_create_folder', {
|
|
6
|
+
title: 'Create Project Folder',
|
|
7
|
+
description: `Create a new folder to serve as the root of a RESTForge project. The folder will host node_modules (@restforgejs/platform), config/, payload/, and generated src/.
|
|
8
|
+
|
|
9
|
+
USE WHEN:
|
|
10
|
+
- The user wants to set up a new RESTForge project working folder
|
|
11
|
+
- Starting a RESTForge project from scratch in a specific location
|
|
12
|
+
- The user says things like "buat folder project baru", "create a new project folder",
|
|
13
|
+
"siapkan folder untuk project baru", "make a directory for my new RESTForge project",
|
|
14
|
+
"bikinkan project baru di folder X", "scaffold a new restforge project"
|
|
15
|
+
- A safe mkdir with collision detection is needed
|
|
16
|
+
|
|
17
|
+
DO NOT USE FOR:
|
|
18
|
+
- Installing the @restforgejs/platform package -> use 'setup_install_package'
|
|
19
|
+
- Generating skeleton config -> use 'setup_init_config'
|
|
20
|
+
- Writing credentials -> use 'setup_write_env'
|
|
21
|
+
|
|
22
|
+
This is typically the very first step in setting up a new RESTForge project.
|
|
23
|
+
The natural next step after this is 'setup_install_package' to install the
|
|
24
|
+
RESTForge package into the new folder. // per §5.2
|
|
25
|
+
|
|
26
|
+
This tool runs: fs.mkdir(<parentCwd>/<folderName>, { recursive: true })
|
|
27
|
+
Output: absolute path of the created folder. Pass this path as 'cwd' to subsequent setup_* tools.
|
|
28
|
+
|
|
29
|
+
PRESENTATION GUIDANCE:
|
|
30
|
+
- Match the user's language. If the user writes in Indonesian, respond in Indonesian.
|
|
31
|
+
- Never mention internal tool names in the reply to the user. Describe actions by what they do (e.g. "install the package", "set up the initial config").
|
|
32
|
+
- Speak in plain language. Confirm the folder was created and state the absolute path.
|
|
33
|
+
- When the folder already exists and force was not set, frame it as a choice or question, not as a hard error.`,
|
|
34
|
+
inputSchema: {
|
|
35
|
+
folderName: z
|
|
36
|
+
.string()
|
|
37
|
+
.min(1)
|
|
38
|
+
.regex(/^[a-zA-Z0-9_-]+$/, 'Only alphanumeric, underscore, and dash are allowed')
|
|
39
|
+
.default('backend-server')
|
|
40
|
+
.describe('Project folder name. Default: backend-server'),
|
|
41
|
+
parentCwd: z
|
|
42
|
+
.string()
|
|
43
|
+
.optional()
|
|
44
|
+
.describe('Parent directory where the folder is created. Default: process.cwd()'),
|
|
45
|
+
force: z
|
|
46
|
+
.boolean()
|
|
47
|
+
.default(false)
|
|
48
|
+
.describe('Continue even if the folder already exists (mkdir recursive remains idempotent)'),
|
|
49
|
+
},
|
|
50
|
+
annotations: {
|
|
51
|
+
title: 'Create Project Folder',
|
|
52
|
+
readOnlyHint: false,
|
|
53
|
+
idempotentHint: false,
|
|
54
|
+
},
|
|
55
|
+
}, async ({ folderName, parentCwd, force }) => {
|
|
56
|
+
const parent = parentCwd ? resolve(parentCwd) : process.cwd();
|
|
57
|
+
const targetPath = join(parent, folderName);
|
|
58
|
+
// Pre-check: detect whether the target folder already exists.
|
|
59
|
+
let alreadyExists = false;
|
|
60
|
+
try {
|
|
61
|
+
await access(targetPath);
|
|
62
|
+
alreadyExists = true;
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
/* not present, OK to create */
|
|
66
|
+
}
|
|
67
|
+
// Already-exists collision (force=false): non-error precondition per §3.4.
|
|
68
|
+
if (alreadyExists && !force) {
|
|
69
|
+
return {
|
|
70
|
+
content: [
|
|
71
|
+
{
|
|
72
|
+
type: 'text',
|
|
73
|
+
text: `Precondition not met: a folder with this name already exists.
|
|
74
|
+
|
|
75
|
+
Parent directory: ${parent}
|
|
76
|
+
Folder name: ${folderName}
|
|
77
|
+
Existing path: ${targetPath}
|
|
78
|
+
|
|
79
|
+
For the assistant:
|
|
80
|
+
- The user asked to create a new project folder, but one with this name already exists.
|
|
81
|
+
- Offer the user a choice in plain words: pick a different folder name, reuse the existing folder (continue with force enabled, since recursive mkdir is idempotent), or cancel.
|
|
82
|
+
- Do not present this as a hard error. Do not mention internal tool names.`,
|
|
83
|
+
},
|
|
84
|
+
],
|
|
85
|
+
isError: false, // per §3.4
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
// Real I/O failure: surface as error per §3.4.
|
|
89
|
+
try {
|
|
90
|
+
await mkdir(targetPath, { recursive: true });
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
94
|
+
return {
|
|
95
|
+
content: [
|
|
96
|
+
{
|
|
97
|
+
type: 'text',
|
|
98
|
+
text: `Failed to create the project folder.
|
|
99
|
+
|
|
100
|
+
Parent directory: ${parent}
|
|
101
|
+
Folder name: ${folderName}
|
|
102
|
+
Target path: ${targetPath}
|
|
103
|
+
Reason: ${msg}
|
|
104
|
+
|
|
105
|
+
For the assistant:
|
|
106
|
+
- Tell the user that the folder could not be created.
|
|
107
|
+
- Summarise the likely cause in plain language (permissions, parent missing, disk full); do not paste the raw error unless the user explicitly asks.
|
|
108
|
+
- Offer to retry once the underlying issue is resolved. Do not mention internal tool names.`,
|
|
109
|
+
},
|
|
110
|
+
],
|
|
111
|
+
isError: true, // per §3.4
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
// Success: one-line summary + labeled facts per §3.5.
|
|
115
|
+
const stateNote = alreadyExists
|
|
116
|
+
? 'State: the folder already existed and was reused (force=true).'
|
|
117
|
+
: 'State: a new folder was created.';
|
|
118
|
+
return {
|
|
119
|
+
content: [
|
|
120
|
+
{
|
|
121
|
+
type: 'text',
|
|
122
|
+
text: `Project folder ready.
|
|
123
|
+
|
|
124
|
+
Parent directory: ${parent}
|
|
125
|
+
Folder name: ${folderName}
|
|
126
|
+
Absolute path: ${targetPath}
|
|
127
|
+
${stateNote}
|
|
128
|
+
|
|
129
|
+
For the assistant:
|
|
130
|
+
- Confirm to the user that the project folder is ready and state its absolute path.
|
|
131
|
+
- Suggest the next step in plain words: installing the RESTForge package into this folder so the project can be configured.
|
|
132
|
+
- Pass the absolute path above as the working-directory argument for subsequent setup actions. Do not mention internal tool names.`,
|
|
133
|
+
},
|
|
134
|
+
],
|
|
135
|
+
};
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=create-folder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-folder.js","sourceRoot":"","sources":["../../../src/tools/setup/create-folder.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,158 @@
|
|
|
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 registerSetupGetConfigSchema(server) {
|
|
6
|
+
server.registerTool('setup_get_config_schema', {
|
|
7
|
+
title: 'Get Config Schema',
|
|
8
|
+
description: `Get JSON schema of all parameters available in db-connection.env template.
|
|
9
|
+
Schema includes parameter name, section, type (string/integer/boolean), default value,
|
|
10
|
+
description, and required status.
|
|
11
|
+
|
|
12
|
+
USE WHEN:
|
|
13
|
+
- The agent needs to know what parameters are configurable before writing config
|
|
14
|
+
- Listing available config options for user reference
|
|
15
|
+
- Building a dynamic UI or validator from the schema
|
|
16
|
+
- The user asks things like "what parameters are available", "list all config options",
|
|
17
|
+
"parameter apa saja yang bisa di-set", "tampilkan schema config", "what can I configure",
|
|
18
|
+
"show me the configurable fields", "field apa saja yang valid"
|
|
19
|
+
|
|
20
|
+
DO NOT USE FOR:
|
|
21
|
+
- Reading actual current config values -> use 'setup_read_env'
|
|
22
|
+
- Writing config -> use 'setup_write_env' or 'setup_update_env'
|
|
23
|
+
- Getting raw template text -> use 'setup_get_init_template'
|
|
24
|
+
|
|
25
|
+
This tool runs: npx restforge config:schema in the given cwd.
|
|
26
|
+
The schema is sourced from restforge (single source of truth) so it stays
|
|
27
|
+
in sync with the restforge runtime version installed in the project.
|
|
28
|
+
Requires @restforgejs/platform >= 2.3.1.
|
|
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. "install the package", "fill in the credentials").
|
|
33
|
+
- Speak in plain language. Summarise the schema (number of parameters, sections present, key required fields); do not paste the entire JSON unless the user explicitly asks for it.
|
|
34
|
+
- When a precondition is not met (e.g. the package is not installed), frame it as a question or next-step suggestion rather than an error.`,
|
|
35
|
+
inputSchema: {
|
|
36
|
+
cwd: z.string().min(1).describe('Absolute path of the project folder (must have @restforgejs/platform installed in node_modules)'),
|
|
37
|
+
},
|
|
38
|
+
annotations: {
|
|
39
|
+
title: 'Get Config Schema',
|
|
40
|
+
readOnlyHint: true,
|
|
41
|
+
idempotentHint: true,
|
|
42
|
+
},
|
|
43
|
+
}, async ({ cwd }) => {
|
|
44
|
+
const projectCwd = resolve(cwd);
|
|
45
|
+
// Precondition check: @restforgejs/platform must be installed before this CLI command can run.
|
|
46
|
+
// Treated as a non-error precondition per the authoring guide §3.4.
|
|
47
|
+
try {
|
|
48
|
+
await access(join(projectCwd, 'node_modules', '@restforgejs', 'platform'));
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
return {
|
|
52
|
+
content: [
|
|
53
|
+
{
|
|
54
|
+
type: 'text',
|
|
55
|
+
text: `Precondition not met: the RESTForge package is not installed in this project.
|
|
56
|
+
|
|
57
|
+
Project path: ${projectCwd}
|
|
58
|
+
Expected location: node_modules/@restforgejs/platform
|
|
59
|
+
|
|
60
|
+
For the assistant:
|
|
61
|
+
- The schema can only be retrieved once the RESTForge package is installed locally.
|
|
62
|
+
- Suggest installing the package first, then retry getting the schema.
|
|
63
|
+
- 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.`,
|
|
64
|
+
},
|
|
65
|
+
],
|
|
66
|
+
isError: false, // per §3.4
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
// Run subprocess with NODE_ENV=production to suppress legacy banner output
|
|
70
|
+
const result = await execProcess('npx', ['restforge', 'config', 'schema'], {
|
|
71
|
+
cwd: projectCwd,
|
|
72
|
+
timeout: 15_000,
|
|
73
|
+
env: { NODE_ENV: 'production' },
|
|
74
|
+
});
|
|
75
|
+
// CLI failure: real error per §3.4; structured per §3.5.
|
|
76
|
+
if (!result.success) {
|
|
77
|
+
return {
|
|
78
|
+
content: [
|
|
79
|
+
{
|
|
80
|
+
type: 'text',
|
|
81
|
+
text: `Failed to retrieve the configuration schema.
|
|
82
|
+
|
|
83
|
+
Project path: ${projectCwd}
|
|
84
|
+
Command: ${result.command}
|
|
85
|
+
Exit code: ${result.exitCode}
|
|
86
|
+
|
|
87
|
+
--- CLI output ---
|
|
88
|
+
stdout:
|
|
89
|
+
${result.stdout}
|
|
90
|
+
|
|
91
|
+
stderr:
|
|
92
|
+
${result.stderr}
|
|
93
|
+
--- end CLI output ---
|
|
94
|
+
|
|
95
|
+
For the assistant:
|
|
96
|
+
- Tell the user that the schema could not be retrieved.
|
|
97
|
+
- A common cause is an older RESTForge version that does not yet expose the schema command (requires @restforgejs/platform >= 2.3.1). Suggest upgrading the package as a likely fix.
|
|
98
|
+
- Do not paste the raw stdout/stderr unless the user explicitly asks. Do not mention internal tool names.`,
|
|
99
|
+
},
|
|
100
|
+
],
|
|
101
|
+
isError: true, // per §3.4
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
// Validate JSON output. Parse failure is a real error per §3.4 (CLI succeeded but produced invalid output).
|
|
105
|
+
let parsed;
|
|
106
|
+
try {
|
|
107
|
+
parsed = JSON.parse(result.stdout);
|
|
108
|
+
}
|
|
109
|
+
catch (err) {
|
|
110
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
111
|
+
return {
|
|
112
|
+
content: [
|
|
113
|
+
{
|
|
114
|
+
type: 'text',
|
|
115
|
+
text: `Failed to parse the schema JSON returned by the CLI.
|
|
116
|
+
|
|
117
|
+
Project path: ${projectCwd}
|
|
118
|
+
Reason: ${msg}
|
|
119
|
+
|
|
120
|
+
--- Raw stdout ---
|
|
121
|
+
${result.stdout}
|
|
122
|
+
--- end Raw stdout ---
|
|
123
|
+
|
|
124
|
+
For the assistant:
|
|
125
|
+
- The CLI returned output that is not valid JSON.
|
|
126
|
+
- Summarise this to the user in plain language; do not paste the raw stdout unless they explicitly ask.
|
|
127
|
+
- Suggest checking that the installed package version is compatible (requires @restforgejs/platform >= 2.3.1). Do not mention internal tool names.`,
|
|
128
|
+
},
|
|
129
|
+
],
|
|
130
|
+
isError: true, // per §3.4
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
// Re-stringify for consistent pretty formatting
|
|
134
|
+
const prettyJson = JSON.stringify(parsed, null, 2);
|
|
135
|
+
// Success: one-line summary + labeled facts + fenced JSON output per §3.5.
|
|
136
|
+
return {
|
|
137
|
+
content: [
|
|
138
|
+
{
|
|
139
|
+
type: 'text',
|
|
140
|
+
text: `Configuration schema retrieved successfully.
|
|
141
|
+
|
|
142
|
+
Project path: ${projectCwd}
|
|
143
|
+
Source: restforge (single source of truth for the installed runtime version)
|
|
144
|
+
|
|
145
|
+
--- Schema (JSON) ---
|
|
146
|
+
${prettyJson}
|
|
147
|
+
--- end Schema (JSON) ---
|
|
148
|
+
|
|
149
|
+
For the assistant:
|
|
150
|
+
- Confirm to the user that the schema is available.
|
|
151
|
+
- Summarise in plain language: how many parameters there are, which sections are present (e.g. database, license, optional Live Sync / Redis / Kafka / Logging), and which fields are required.
|
|
152
|
+
- Do not paste the full JSON block unless the user explicitly asks for it. Do not mention internal tool names.`,
|
|
153
|
+
},
|
|
154
|
+
],
|
|
155
|
+
};
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=get-config-schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-config-schema.js","sourceRoot":"","sources":["../../../src/tools/setup/get-config-schema.ts"],"names":[],"mappings":"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"}
|