staticforge 0.0.0-stage → 0.1.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 +21 -0
- package/README.md +49 -2
- package/dist/.tsbuildinfo +1 -0
- package/dist/bin.d.ts +3 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +4 -0
- package/dist/bin.js.map +1 -0
- package/dist/browser.d.ts +3 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/browser.js +18 -0
- package/dist/browser.js.map +1 -0
- package/dist/cloud.d.ts +31 -0
- package/dist/cloud.d.ts.map +1 -0
- package/dist/cloud.js +102 -0
- package/dist/cloud.js.map +1 -0
- package/dist/command.d.ts +54 -0
- package/dist/command.d.ts.map +1 -0
- package/dist/command.js +70 -0
- package/dist/command.js.map +1 -0
- package/dist/commands/build.d.ts +4 -0
- package/dist/commands/build.d.ts.map +1 -0
- package/dist/commands/build.js +54 -0
- package/dist/commands/build.js.map +1 -0
- package/dist/commands/check.d.ts +4 -0
- package/dist/commands/check.d.ts.map +1 -0
- package/dist/commands/check.js +100 -0
- package/dist/commands/check.js.map +1 -0
- package/dist/commands/config.d.ts +4 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +27 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/deploy.d.ts +4 -0
- package/dist/commands/deploy.d.ts.map +1 -0
- package/dist/commands/deploy.js +184 -0
- package/dist/commands/deploy.js.map +1 -0
- package/dist/commands/dev.d.ts +4 -0
- package/dist/commands/dev.d.ts.map +1 -0
- package/dist/commands/dev.js +81 -0
- package/dist/commands/dev.js.map +1 -0
- package/dist/commands/iac.d.ts +4 -0
- package/dist/commands/iac.d.ts.map +1 -0
- package/dist/commands/iac.js +64 -0
- package/dist/commands/iac.js.map +1 -0
- package/dist/commands/init.d.ts +4 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +55 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/mcp.d.ts +4 -0
- package/dist/commands/mcp.d.ts.map +1 -0
- package/dist/commands/mcp.js +46 -0
- package/dist/commands/mcp.js.map +1 -0
- package/dist/commands/new.d.ts +4 -0
- package/dist/commands/new.d.ts.map +1 -0
- package/dist/commands/new.js +30 -0
- package/dist/commands/new.js.map +1 -0
- package/dist/commands/preview.d.ts +4 -0
- package/dist/commands/preview.d.ts.map +1 -0
- package/dist/commands/preview.js +34 -0
- package/dist/commands/preview.js.map +1 -0
- package/dist/commands/provision.d.ts +11 -0
- package/dist/commands/provision.d.ts.map +1 -0
- package/dist/commands/provision.js +133 -0
- package/dist/commands/provision.js.map +1 -0
- package/dist/commands/schema.d.ts +4 -0
- package/dist/commands/schema.d.ts.map +1 -0
- package/dist/commands/schema.js +21 -0
- package/dist/commands/schema.js.map +1 -0
- package/dist/commands/version.d.ts +4 -0
- package/dist/commands/version.d.ts.map +1 -0
- package/dist/commands/version.js +17 -0
- package/dist/commands/version.js.map +1 -0
- package/dist/context.d.ts +27 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +19 -0
- package/dist/context.js.map +1 -0
- package/dist/io.d.ts +19 -0
- package/dist/io.d.ts.map +1 -0
- package/dist/io.js +34 -0
- package/dist/io.js.map +1 -0
- package/dist/main.d.ts +10 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +81 -0
- package/dist/main.js.map +1 -0
- package/dist/mcp/invoke.d.ts +29 -0
- package/dist/mcp/invoke.d.ts.map +1 -0
- package/dist/mcp/invoke.js +82 -0
- package/dist/mcp/invoke.js.map +1 -0
- package/dist/mcp/server.d.ts +25 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +531 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/output.d.ts +17 -0
- package/dist/output.d.ts.map +1 -0
- package/dist/output.js +37 -0
- package/dist/output.js.map +1 -0
- package/dist/paths.d.ts +3 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +9 -0
- package/dist/paths.js.map +1 -0
- package/dist/project.d.ts +10 -0
- package/dist/project.d.ts.map +1 -0
- package/dist/project.js +20 -0
- package/dist/project.js.map +1 -0
- package/dist/schemas.d.ts +16 -0
- package/dist/schemas.d.ts.map +1 -0
- package/dist/schemas.js +241 -0
- package/dist/schemas.js.map +1 -0
- package/dist/server-options.d.ts +12 -0
- package/dist/server-options.d.ts.map +1 -0
- package/dist/server-options.js +26 -0
- package/dist/server-options.js.map +1 -0
- package/dist/version.d.ts +3 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +4 -0
- package/dist/version.js.map +1 -0
- package/dist/workers.d.ts +7 -0
- package/dist/workers.d.ts.map +1 -0
- package/dist/workers.js +20 -0
- package/dist/workers.js.map +1 -0
- package/package.json +64 -3
- package/schema/diagnostics.schema.json +183 -0
- package/schema/output.schema.json +1537 -0
- package/schema/staticforge.schema.json +649 -0
|
@@ -0,0 +1,531 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { dirname, join } from 'node:path';
|
|
3
|
+
import { McpServer, } from '@modelcontextprotocol/server';
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { ErrorCode } from '@staticforge/core';
|
|
6
|
+
import { standaloneDataSchema } from '../schemas.js';
|
|
7
|
+
import { VERSION } from '../version.js';
|
|
8
|
+
import { invoke } from './invoke.js';
|
|
9
|
+
const INSTRUCTIONS = `staticforge (sforge) builds, checks, previews and deploys accessible static sites.
|
|
10
|
+
Content lives in content/ (Markdown or HTML with YAML front-matter), assets in assets/, files copied as is in static/, configuration in staticforge.config.*.
|
|
11
|
+
A typical loop: edit content, call sforge_check, read the diagnostics (ruleId, severity, file, line, url, selector, wcag, hint), fix them, check again. sforge_fix_preview shows the safe automatic fixes as a diff; sforge_check with fix: true applies them. The checker never invents alt text: describe images yourself.
|
|
12
|
+
sforge_dev_start serves the site with live reload at a local URL; call it again for the latest build's problems.
|
|
13
|
+
Tools return the same data as \`sforge <command> --json\`. Errors carry a stable code (SF_*) and often a hint.
|
|
14
|
+
Deploying, rolling back and removing previews change live sites: ask the user first, then pass confirm: true.`;
|
|
15
|
+
const READ_ONLY = { readOnlyHint: true, openWorldHint: false };
|
|
16
|
+
const LOCAL_WRITE = {
|
|
17
|
+
readOnlyHint: false,
|
|
18
|
+
destructiveHint: false,
|
|
19
|
+
idempotentHint: true,
|
|
20
|
+
openWorldHint: false,
|
|
21
|
+
};
|
|
22
|
+
const CLOUD_READ = { readOnlyHint: true, openWorldHint: true };
|
|
23
|
+
const CLOUD_WRITE = {
|
|
24
|
+
readOnlyHint: false,
|
|
25
|
+
destructiveHint: true,
|
|
26
|
+
idempotentHint: false,
|
|
27
|
+
openWorldHint: true,
|
|
28
|
+
};
|
|
29
|
+
/** Advertise a hand-written JSON Schema. Tests validate real output against it. */
|
|
30
|
+
function jsonSchema(schema) {
|
|
31
|
+
return {
|
|
32
|
+
'~standard': {
|
|
33
|
+
version: 1,
|
|
34
|
+
vendor: 'staticforge',
|
|
35
|
+
validate: (value) => ({ value }),
|
|
36
|
+
jsonSchema: { input: () => schema, output: () => schema },
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
const value = (description) => z.string().min(1).describe(description);
|
|
41
|
+
const target = value('Target name from the config (`targets.<name>`), e.g. "staging".');
|
|
42
|
+
const confirm = z
|
|
43
|
+
.boolean()
|
|
44
|
+
.optional()
|
|
45
|
+
.describe('Must be true: the user has agreed to this change of a live site.');
|
|
46
|
+
/**
|
|
47
|
+
* argv for a command: options as `--name=value`, then `--` and the positionals,
|
|
48
|
+
* so no value is ever read as an option.
|
|
49
|
+
*/
|
|
50
|
+
function argv(command, flags = {}, positionals = []) {
|
|
51
|
+
const args = [...command];
|
|
52
|
+
for (const [flag, v] of Object.entries(flags)) {
|
|
53
|
+
if (v === undefined || v === false)
|
|
54
|
+
continue;
|
|
55
|
+
if (v === true)
|
|
56
|
+
args.push(flag);
|
|
57
|
+
else if (Array.isArray(v))
|
|
58
|
+
args.push(...v.map((item) => `${flag}=${item}`));
|
|
59
|
+
else
|
|
60
|
+
args.push(`${flag}=${v}`);
|
|
61
|
+
}
|
|
62
|
+
return positionals.length > 0 ? [...args, '--', ...positionals] : args;
|
|
63
|
+
}
|
|
64
|
+
const text = (s) => ({ type: 'text', text: s });
|
|
65
|
+
function errorResult(code, message, extra) {
|
|
66
|
+
return {
|
|
67
|
+
isError: true,
|
|
68
|
+
content: [
|
|
69
|
+
text(`${code}: ${message}`),
|
|
70
|
+
...(extra !== undefined ? [text(JSON.stringify(extra))] : []),
|
|
71
|
+
],
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/** The tool result for a command outcome: a summary plus the data as JSON, or the error. */
|
|
75
|
+
function toolResult(outcome, summary) {
|
|
76
|
+
const { envelope } = outcome;
|
|
77
|
+
if (envelope.error !== undefined) {
|
|
78
|
+
const { code, message, hint } = envelope.error;
|
|
79
|
+
return errorResult(code, hint === undefined ? message : `${message}\nhint: ${hint}`, envelope.error);
|
|
80
|
+
}
|
|
81
|
+
const data = (envelope.data ?? {});
|
|
82
|
+
const line = summary === 'none'
|
|
83
|
+
? undefined
|
|
84
|
+
: summary === 'text'
|
|
85
|
+
? outcome.text
|
|
86
|
+
: summary(data);
|
|
87
|
+
return {
|
|
88
|
+
content: [...(line !== undefined ? [text(line)] : []), text(JSON.stringify(data))],
|
|
89
|
+
structuredContent: data,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
function checkSummary(data) {
|
|
93
|
+
const { error, warning, info } = data.summary;
|
|
94
|
+
const lines = [
|
|
95
|
+
`Checked ${data.pages} page${data.pages === 1 ? '' : 's'}: ${error} error${error === 1 ? '' : 's'}, ` +
|
|
96
|
+
`${warning} warning${warning === 1 ? '' : 's'}, ${info} notice${info === 1 ? '' : 's'} ` +
|
|
97
|
+
`(rendered checks: ${data.rendered}).`,
|
|
98
|
+
];
|
|
99
|
+
if (data.fixes?.applied === true) {
|
|
100
|
+
lines.push(data.fixes.files.length > 0
|
|
101
|
+
? `Fixed ${data.fixes.files.map((f) => `${f.file} (${f.ruleIds.join(', ')})`).join(', ')}.`
|
|
102
|
+
: 'No automatic fixes applied.');
|
|
103
|
+
}
|
|
104
|
+
return lines.join('\n');
|
|
105
|
+
}
|
|
106
|
+
function fixPreviewSummary(data) {
|
|
107
|
+
const diff = data.fixes?.diff ?? '';
|
|
108
|
+
return diff === '' ? 'No automatic fixes apply.' : diff;
|
|
109
|
+
}
|
|
110
|
+
export function createSforgeMcp(options) {
|
|
111
|
+
let dev;
|
|
112
|
+
let devStarting;
|
|
113
|
+
let latest;
|
|
114
|
+
/** Logs go to options.log, and as progress notifications while the request is open. */
|
|
115
|
+
function progress(ctx) {
|
|
116
|
+
const token = ctx?.mcpReq._meta?.progressToken;
|
|
117
|
+
let step = 0;
|
|
118
|
+
let open = true;
|
|
119
|
+
return {
|
|
120
|
+
onLog(line) {
|
|
121
|
+
options.log?.(line);
|
|
122
|
+
if (!open || token === undefined || ctx === undefined)
|
|
123
|
+
return;
|
|
124
|
+
void ctx.mcpReq
|
|
125
|
+
.notify({
|
|
126
|
+
method: 'notifications/progress',
|
|
127
|
+
params: { progressToken: token, progress: ++step, message: line },
|
|
128
|
+
})
|
|
129
|
+
.catch(() => { });
|
|
130
|
+
},
|
|
131
|
+
end() {
|
|
132
|
+
open = false;
|
|
133
|
+
},
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
function start(args, onLog) {
|
|
137
|
+
return invoke(args, {
|
|
138
|
+
run: options.run,
|
|
139
|
+
cwd: options.cwd,
|
|
140
|
+
env: options.env,
|
|
141
|
+
...(options.globalArgs !== undefined && { globalArgs: options.globalArgs }),
|
|
142
|
+
...(options.providers && { providers: options.providers }),
|
|
143
|
+
onLog,
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
/** Run a command to completion. */
|
|
147
|
+
async function command(args, ctx) {
|
|
148
|
+
const logs = progress(ctx);
|
|
149
|
+
try {
|
|
150
|
+
const invocation = start(args, logs.onLog);
|
|
151
|
+
const outcome = await invocation.outcome;
|
|
152
|
+
await invocation.done;
|
|
153
|
+
return outcome;
|
|
154
|
+
}
|
|
155
|
+
finally {
|
|
156
|
+
logs.end();
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
function remember(source, outcome) {
|
|
160
|
+
const data = outcome.envelope.data;
|
|
161
|
+
if (data?.diagnostics === undefined)
|
|
162
|
+
return;
|
|
163
|
+
latest = {
|
|
164
|
+
source,
|
|
165
|
+
at: new Date().toISOString(),
|
|
166
|
+
ok: data.ok ?? outcome.envelope.ok,
|
|
167
|
+
...(data.summary !== undefined && { summary: data.summary }),
|
|
168
|
+
diagnostics: data.diagnostics,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
async function startDev(flags, ctx) {
|
|
172
|
+
// A call made while another is starting the server waits for it, then reports on it.
|
|
173
|
+
while (devStarting !== undefined)
|
|
174
|
+
await devStarting;
|
|
175
|
+
if (dev !== undefined) {
|
|
176
|
+
return {
|
|
177
|
+
content: [text('The dev server is already running; this is its latest build.')],
|
|
178
|
+
structuredContent: dev.data(),
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
const starting = launchDev(flags, ctx);
|
|
182
|
+
devStarting = starting.then(() => undefined, () => undefined);
|
|
183
|
+
try {
|
|
184
|
+
return await starting;
|
|
185
|
+
}
|
|
186
|
+
finally {
|
|
187
|
+
devStarting = undefined;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
async function launchDev(flags, ctx) {
|
|
191
|
+
const logs = progress(ctx);
|
|
192
|
+
const invocation = start(argv(['dev'], { '--port': flags.port ?? 0, '--drafts': flags.drafts }), logs.onLog);
|
|
193
|
+
try {
|
|
194
|
+
const outcome = await invocation.outcome;
|
|
195
|
+
if (outcome.envelope.error !== undefined) {
|
|
196
|
+
await invocation.done;
|
|
197
|
+
return toolResult(outcome, 'none');
|
|
198
|
+
}
|
|
199
|
+
const session = {
|
|
200
|
+
invocation,
|
|
201
|
+
data: outcome.live ?? (() => outcome.envelope.data),
|
|
202
|
+
};
|
|
203
|
+
dev = session;
|
|
204
|
+
void invocation.done.then(() => {
|
|
205
|
+
if (dev === session)
|
|
206
|
+
dev = undefined;
|
|
207
|
+
});
|
|
208
|
+
return toolResult(outcome, 'text');
|
|
209
|
+
}
|
|
210
|
+
finally {
|
|
211
|
+
logs.end();
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
async function stopDev() {
|
|
215
|
+
const session = dev;
|
|
216
|
+
if (session === undefined)
|
|
217
|
+
return { stopped: false };
|
|
218
|
+
dev = undefined;
|
|
219
|
+
const { url } = session.data();
|
|
220
|
+
session.invocation.stop();
|
|
221
|
+
await session.invocation.done;
|
|
222
|
+
return { stopped: true, url };
|
|
223
|
+
}
|
|
224
|
+
async function json(args) {
|
|
225
|
+
const { envelope } = await command(args);
|
|
226
|
+
if (envelope.error !== undefined) {
|
|
227
|
+
throw new Error(`${envelope.error.code}: ${envelope.error.message}`);
|
|
228
|
+
}
|
|
229
|
+
return envelope.data;
|
|
230
|
+
}
|
|
231
|
+
function createServer() {
|
|
232
|
+
const server = new McpServer({ name: 'staticforge', title: 'staticforge', version: VERSION }, { instructions: INSTRUCTIONS });
|
|
233
|
+
const tool = (name, spec, handler) => {
|
|
234
|
+
server.registerTool(name, {
|
|
235
|
+
title: spec.title,
|
|
236
|
+
description: spec.description,
|
|
237
|
+
inputSchema: spec.input,
|
|
238
|
+
outputSchema: jsonSchema(standaloneDataSchema(spec.data)),
|
|
239
|
+
annotations: { title: spec.title, ...spec.annotations },
|
|
240
|
+
},
|
|
241
|
+
// The SDK infers the arguments through Standard Schema, which TypeScript cannot
|
|
242
|
+
// relate to z.infer for a generic I.
|
|
243
|
+
(async (args, ctx) => {
|
|
244
|
+
try {
|
|
245
|
+
return await handler(args, ctx);
|
|
246
|
+
}
|
|
247
|
+
catch (error) {
|
|
248
|
+
return errorResult(ErrorCode.Internal, error instanceof Error ? error.message : String(error));
|
|
249
|
+
}
|
|
250
|
+
}));
|
|
251
|
+
};
|
|
252
|
+
tool('sforge_build', {
|
|
253
|
+
title: 'Build the site',
|
|
254
|
+
description: 'Build the site into the output directory (build.outDir, usually dist/). Returns the pages built and the build diagnostics.',
|
|
255
|
+
input: z.object({
|
|
256
|
+
drafts: z.boolean().optional().describe('Include pages marked draft: true.'),
|
|
257
|
+
baseUrl: z
|
|
258
|
+
.url()
|
|
259
|
+
.optional()
|
|
260
|
+
.describe('Site URL for canonical links (default: site.baseUrl).'),
|
|
261
|
+
outDir: value('Output directory (default: build.outDir).').optional(),
|
|
262
|
+
}),
|
|
263
|
+
data: 'build',
|
|
264
|
+
annotations: LOCAL_WRITE,
|
|
265
|
+
}, async (args, ctx) => {
|
|
266
|
+
const outcome = await command(argv(['build'], {
|
|
267
|
+
'--drafts': args.drafts,
|
|
268
|
+
'--base-url': args.baseUrl,
|
|
269
|
+
'--out': args.outDir,
|
|
270
|
+
}), ctx);
|
|
271
|
+
remember('build', outcome);
|
|
272
|
+
return toolResult(outcome, 'text');
|
|
273
|
+
});
|
|
274
|
+
const pages = z
|
|
275
|
+
.array(value('A URL or source glob.'))
|
|
276
|
+
.optional()
|
|
277
|
+
.describe('Only check pages whose URL or source matches, e.g. ["/blog/**", "content/about.md"].');
|
|
278
|
+
tool('sforge_check', {
|
|
279
|
+
title: 'Check the site',
|
|
280
|
+
description: 'Build the site into a temporary directory and check it for accessibility (WCAG 2.2 AA) and correctness: HTML validity, links, landmarks, headings, and axe-core in headless Chromium. With fix: true, apply the safe automatic fixes to the sources first. data.ok is false when problems at or above check.failOn remain.',
|
|
281
|
+
input: z.object({
|
|
282
|
+
fix: z
|
|
283
|
+
.boolean()
|
|
284
|
+
.optional()
|
|
285
|
+
.describe('Apply safe fixes to the source files, then check again.'),
|
|
286
|
+
headless: z
|
|
287
|
+
.boolean()
|
|
288
|
+
.optional()
|
|
289
|
+
.describe('Run the rendered checks in headless Chromium (default: check.headless). Slower.'),
|
|
290
|
+
pages,
|
|
291
|
+
failOn: z
|
|
292
|
+
.enum(['error', 'warning'])
|
|
293
|
+
.optional()
|
|
294
|
+
.describe('Threshold for data.ok (default: check.failOn).'),
|
|
295
|
+
drafts: z.boolean().optional().describe('Include pages marked draft: true.'),
|
|
296
|
+
}),
|
|
297
|
+
data: 'check',
|
|
298
|
+
annotations: { ...LOCAL_WRITE, idempotentHint: false },
|
|
299
|
+
}, async (args, ctx) => {
|
|
300
|
+
const outcome = await command(argv(['check'], {
|
|
301
|
+
'--fix': args.fix,
|
|
302
|
+
'--headless': args.headless === true,
|
|
303
|
+
'--no-headless': args.headless === false,
|
|
304
|
+
'--fail-on': args.failOn,
|
|
305
|
+
'--drafts': args.drafts,
|
|
306
|
+
'--pages': args.pages,
|
|
307
|
+
}), ctx);
|
|
308
|
+
remember('check', outcome);
|
|
309
|
+
return toolResult(outcome, checkSummary);
|
|
310
|
+
});
|
|
311
|
+
tool('sforge_fix_preview', {
|
|
312
|
+
title: 'Preview automatic fixes',
|
|
313
|
+
description: 'Show the safe automatic fixes `sforge_check` with fix: true would make, as a unified diff of the source files (data.fixes.diff). Changes nothing.',
|
|
314
|
+
input: z.object({
|
|
315
|
+
pages,
|
|
316
|
+
headless: z
|
|
317
|
+
.boolean()
|
|
318
|
+
.optional()
|
|
319
|
+
.describe('Also run the rendered checks (default: false).'),
|
|
320
|
+
}),
|
|
321
|
+
data: 'check',
|
|
322
|
+
annotations: READ_ONLY,
|
|
323
|
+
}, async (args, ctx) => {
|
|
324
|
+
const outcome = await command(argv(['check'], {
|
|
325
|
+
'--fix': true,
|
|
326
|
+
'--dry-run': true,
|
|
327
|
+
'--headless': args.headless === true,
|
|
328
|
+
'--no-headless': args.headless !== true,
|
|
329
|
+
'--pages': args.pages,
|
|
330
|
+
}), ctx);
|
|
331
|
+
remember('check', outcome);
|
|
332
|
+
return toolResult(outcome, fixPreviewSummary);
|
|
333
|
+
});
|
|
334
|
+
tool('sforge_dev_start', {
|
|
335
|
+
title: 'Start the dev server',
|
|
336
|
+
description: 'Build and serve the site on 127.0.0.1 with live reload; it rebuilds on every file change until sforge_dev_stop. Returns the URL and the first build. If it is already running, returns its latest build, so call it again after editing to see new problems.',
|
|
337
|
+
input: z.object({
|
|
338
|
+
port: z.int().min(0).max(65535).optional().describe('Port (default: 0, a free port).'),
|
|
339
|
+
drafts: z.boolean().optional().describe('Include pages marked draft: true.'),
|
|
340
|
+
}),
|
|
341
|
+
data: 'dev',
|
|
342
|
+
annotations: { ...LOCAL_WRITE, idempotentHint: true },
|
|
343
|
+
}, (args, ctx) => startDev(args, ctx));
|
|
344
|
+
server.registerTool('sforge_dev_stop', {
|
|
345
|
+
title: 'Stop the dev server',
|
|
346
|
+
description: 'Stop the dev server started by sforge_dev_start.',
|
|
347
|
+
inputSchema: z.object({}),
|
|
348
|
+
outputSchema: z.object({ stopped: z.boolean(), url: z.string().optional() }),
|
|
349
|
+
annotations: { title: 'Stop the dev server', ...LOCAL_WRITE },
|
|
350
|
+
}, async () => {
|
|
351
|
+
const result = await stopDev();
|
|
352
|
+
return {
|
|
353
|
+
content: [
|
|
354
|
+
text(result.stopped
|
|
355
|
+
? `Stopped the dev server at ${result.url}`
|
|
356
|
+
: 'No dev server is running.'),
|
|
357
|
+
],
|
|
358
|
+
structuredContent: result,
|
|
359
|
+
};
|
|
360
|
+
});
|
|
361
|
+
tool('sforge_new_page', {
|
|
362
|
+
title: 'Create a page or post',
|
|
363
|
+
description: 'Create a Markdown (or HTML) page or blog post under content/ with front-matter. Returns the file and the URL it will have.',
|
|
364
|
+
input: z.object({
|
|
365
|
+
kind: z
|
|
366
|
+
.enum(['page', 'post'])
|
|
367
|
+
.default('page')
|
|
368
|
+
.describe('Posts go to blog/ unless the path has a directory.'),
|
|
369
|
+
path: value('Path inside content/ without extension, e.g. "about" or "guides/setup".'),
|
|
370
|
+
title: z.string().min(1).optional().describe('Title (default: from the path).'),
|
|
371
|
+
format: z.enum(['md', 'html']).optional().describe('Source format (default: md).'),
|
|
372
|
+
draft: z.boolean().optional().describe('Mark as draft.'),
|
|
373
|
+
force: z.boolean().optional().describe('Overwrite an existing file.'),
|
|
374
|
+
}),
|
|
375
|
+
data: 'new',
|
|
376
|
+
annotations: { ...LOCAL_WRITE, idempotentHint: false },
|
|
377
|
+
}, async (args, ctx) => toolResult(await command(argv(['new'], {
|
|
378
|
+
'--title': args.title,
|
|
379
|
+
'--format': args.format,
|
|
380
|
+
'--draft': args.draft,
|
|
381
|
+
'--force': args.force,
|
|
382
|
+
}, [args.kind, args.path]), ctx), 'text'));
|
|
383
|
+
tool('sforge_config', {
|
|
384
|
+
title: 'Show the config',
|
|
385
|
+
description: 'Validate the project config and return it resolved, with defaults applied. Invalid configs return SF_CONFIG_INVALID with the problems.',
|
|
386
|
+
input: z.object({}),
|
|
387
|
+
data: 'config show',
|
|
388
|
+
annotations: READ_ONLY,
|
|
389
|
+
}, async (_args, ctx) => toolResult(await command(['config', 'show'], ctx), 'none'));
|
|
390
|
+
tool('sforge_schema', {
|
|
391
|
+
title: 'Get a JSON Schema',
|
|
392
|
+
description: 'Return a JSON Schema: "config" (the config file), "diagnostics" (the check report), or "output" (the --json envelope with every command\'s data).',
|
|
393
|
+
input: z.object({ name: z.enum(['config', 'diagnostics', 'output']).default('config') }),
|
|
394
|
+
data: 'schema',
|
|
395
|
+
annotations: READ_ONLY,
|
|
396
|
+
}, async (args, ctx) => toolResult(await command(['schema', args.name], ctx), 'none'));
|
|
397
|
+
tool('sforge_deploy', {
|
|
398
|
+
title: 'Deploy the site',
|
|
399
|
+
description: 'Build, check and deploy the site to a provisioned target, or deploy a PR preview. Refuses (SF_CHECK_FAILED) when the check finds problems at or above check.failOn. Production deploys switch the live site: ask the user, then pass confirm: true. dryRun shows what would be uploaded without confirmation.',
|
|
400
|
+
input: z.object({
|
|
401
|
+
target,
|
|
402
|
+
preview: value('Deploy a PR preview with this id (e.g. "pr-42") instead of production.').optional(),
|
|
403
|
+
dryRun: z.boolean().optional().describe('Show what would be uploaded; change nothing.'),
|
|
404
|
+
check: z.boolean().optional().describe('Run the checker first (default: true).'),
|
|
405
|
+
headless: z
|
|
406
|
+
.boolean()
|
|
407
|
+
.optional()
|
|
408
|
+
.describe('Run the rendered checks (default: check.headless).'),
|
|
409
|
+
confirm,
|
|
410
|
+
}),
|
|
411
|
+
data: 'deploy',
|
|
412
|
+
annotations: CLOUD_WRITE,
|
|
413
|
+
}, async (args, ctx) => {
|
|
414
|
+
if (args.dryRun !== true && args.confirm !== true) {
|
|
415
|
+
return errorResult(ErrorCode.ConfirmationRequired, `Deploying changes ${args.preview === undefined ? `the live site of "${args.target}"` : `preview ${args.preview}`}. Ask the user, then call again with confirm: true (or use dryRun: true).`);
|
|
416
|
+
}
|
|
417
|
+
return toolResult(await command(argv(['deploy'], {
|
|
418
|
+
'--preview': args.preview,
|
|
419
|
+
'--dry-run': args.dryRun,
|
|
420
|
+
'--no-check': args.check === false,
|
|
421
|
+
'--headless': args.headless === true,
|
|
422
|
+
'--no-headless': args.headless === false,
|
|
423
|
+
}, [args.target]), ctx), 'text');
|
|
424
|
+
});
|
|
425
|
+
tool('sforge_status', {
|
|
426
|
+
title: 'Target status',
|
|
427
|
+
description: "Show a target's URL and active version, and detect infrastructure drift (data.drifted). Runs OpenTofu/Terraform with a refresh-only plan.",
|
|
428
|
+
input: z.object({ target }),
|
|
429
|
+
data: 'status',
|
|
430
|
+
annotations: CLOUD_READ,
|
|
431
|
+
}, async (args, ctx) => toolResult(await command(argv(['status'], {}, [args.target]), ctx), 'text'));
|
|
432
|
+
tool('sforge_versions', {
|
|
433
|
+
title: 'List deployed versions',
|
|
434
|
+
description: 'List the deployed versions of a target (newest first, the active one marked) and its PR previews.',
|
|
435
|
+
input: z.object({ target }),
|
|
436
|
+
data: 'versions',
|
|
437
|
+
annotations: CLOUD_READ,
|
|
438
|
+
}, async (args, ctx) => toolResult(await command(argv(['versions'], {}, [args.target]), ctx), 'text'));
|
|
439
|
+
tool('sforge_rollback', {
|
|
440
|
+
title: 'Roll back',
|
|
441
|
+
description: 'Serve an earlier version of a target again (default: the one before the active version; see sforge_versions). Changes the live site: ask the user, then pass confirm: true.',
|
|
442
|
+
input: z.object({ target, to: value('Version id to serve.').optional(), confirm }),
|
|
443
|
+
data: 'rollback',
|
|
444
|
+
annotations: CLOUD_WRITE,
|
|
445
|
+
}, async (args, ctx) => {
|
|
446
|
+
if (args.confirm !== true) {
|
|
447
|
+
return errorResult(ErrorCode.ConfirmationRequired, `Rolling back changes the live site of "${args.target}". Ask the user, then call again with confirm: true.`);
|
|
448
|
+
}
|
|
449
|
+
return toolResult(await command(argv(['rollback'], { '--yes': true, '--to': args.to }, [args.target]), ctx), 'text');
|
|
450
|
+
});
|
|
451
|
+
tool('sforge_preview_destroy', {
|
|
452
|
+
title: 'Remove a preview',
|
|
453
|
+
description: 'Remove a PR preview of a target. Ask the user, then pass confirm: true.',
|
|
454
|
+
input: z.object({ target, id: value('Preview id, e.g. "pr-42".'), confirm }),
|
|
455
|
+
data: 'preview-destroy',
|
|
456
|
+
annotations: CLOUD_WRITE,
|
|
457
|
+
}, async (args, ctx) => {
|
|
458
|
+
if (args.confirm !== true) {
|
|
459
|
+
return errorResult(ErrorCode.ConfirmationRequired, `Removing preview ${args.id} of "${args.target}" cannot be undone. Ask the user, then call again with confirm: true.`);
|
|
460
|
+
}
|
|
461
|
+
return toolResult(await command(argv(['preview-destroy'], {}, [args.target, args.id]), ctx), 'text');
|
|
462
|
+
});
|
|
463
|
+
if (options.allowInfra === true) {
|
|
464
|
+
tool('sforge_provision', {
|
|
465
|
+
title: 'Provision infrastructure',
|
|
466
|
+
description: 'Create or update the infrastructure of a target with OpenTofu/Terraform. diff: true only plans. Applying needs confirm: true after the user has seen the plan.',
|
|
467
|
+
input: z.object({
|
|
468
|
+
target,
|
|
469
|
+
diff: z.boolean().optional().describe('Only show what would change.'),
|
|
470
|
+
bootstrapState: z
|
|
471
|
+
.boolean()
|
|
472
|
+
.optional()
|
|
473
|
+
.describe("Create the target's remote state backend first, if missing."),
|
|
474
|
+
confirm,
|
|
475
|
+
}),
|
|
476
|
+
data: 'provision',
|
|
477
|
+
annotations: CLOUD_WRITE,
|
|
478
|
+
}, async (args, ctx) => {
|
|
479
|
+
if (args.diff !== true && args.confirm !== true) {
|
|
480
|
+
return errorResult(ErrorCode.ConfirmationRequired, `Provisioning changes the cloud resources of "${args.target}". Show the user the plan (diff: true), then call again with confirm: true.`);
|
|
481
|
+
}
|
|
482
|
+
return toolResult(await command(argv(['provision'], {
|
|
483
|
+
'--diff': args.diff,
|
|
484
|
+
'--bootstrap-state': args.bootstrapState,
|
|
485
|
+
'--yes': args.diff !== true,
|
|
486
|
+
}, [args.target]), ctx), 'text');
|
|
487
|
+
});
|
|
488
|
+
tool('sforge_destroy', {
|
|
489
|
+
title: 'Destroy infrastructure',
|
|
490
|
+
description: 'Delete every resource of a target, including its deployed content. Irreversible: only after the user has explicitly asked for it, passing the target name again as confirm.',
|
|
491
|
+
input: z.object({ target, confirm: value('The target name again.') }),
|
|
492
|
+
data: 'destroy',
|
|
493
|
+
annotations: CLOUD_WRITE,
|
|
494
|
+
}, async (args, ctx) => toolResult(await command(argv(['destroy'], { '--confirm': args.confirm }, [args.target]), ctx), 'text'));
|
|
495
|
+
}
|
|
496
|
+
const resource = (name, uri, description, read) => server.registerResource(name, uri, { description, mimeType: 'application/json' }, async (url) => ({
|
|
497
|
+
contents: [
|
|
498
|
+
{
|
|
499
|
+
uri: url.href,
|
|
500
|
+
mimeType: 'application/json',
|
|
501
|
+
text: JSON.stringify(await read(), null, 2),
|
|
502
|
+
},
|
|
503
|
+
],
|
|
504
|
+
}));
|
|
505
|
+
resource('config', 'sforge://config', 'The resolved project config, with defaults applied.', async () => json(['config', 'show']));
|
|
506
|
+
resource('latest-diagnostics', 'sforge://diagnostics/latest', "Problems found by the dev server's latest build, or else by the latest build or check of this session.", async () => {
|
|
507
|
+
if (dev !== undefined) {
|
|
508
|
+
const { build } = dev.data();
|
|
509
|
+
return { source: 'dev', at: new Date().toISOString(), ...build };
|
|
510
|
+
}
|
|
511
|
+
return (latest ?? {
|
|
512
|
+
source: null,
|
|
513
|
+
diagnostics: [],
|
|
514
|
+
hint: 'Run sforge_check or sforge_build first.',
|
|
515
|
+
});
|
|
516
|
+
});
|
|
517
|
+
resource('build-manifest', 'sforge://build-manifest', 'Every file of the last build with its SHA-256, size and cache class (build.outDir/.sforge/build-manifest.json).', async () => {
|
|
518
|
+
const { path, config } = (await json(['config', 'show']));
|
|
519
|
+
const manifest = join(dirname(path), config.build.outDir, '.sforge', 'build-manifest.json');
|
|
520
|
+
if (!existsSync(manifest))
|
|
521
|
+
throw new Error('There is no build yet: run sforge_build first');
|
|
522
|
+
return JSON.parse(readFileSync(manifest, 'utf8'));
|
|
523
|
+
});
|
|
524
|
+
for (const name of ['config', 'diagnostics', 'output']) {
|
|
525
|
+
resource(`schema-${name}`, `sforge://schema/${name}`, `JSON Schema: sforge schema ${name}.`, () => json(['schema', name]));
|
|
526
|
+
}
|
|
527
|
+
return server;
|
|
528
|
+
}
|
|
529
|
+
return { createServer, close: async () => void (await stopDev()) };
|
|
530
|
+
}
|
|
531
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"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"}
|
package/dist/output.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { SerializedError } from '@staticforge/core';
|
|
2
|
+
/** Version of the `--json` envelope. Bump only on breaking changes. */
|
|
3
|
+
export declare const OUTPUT_SCHEMA_VERSION = 1;
|
|
4
|
+
/** The single JSON document written to stdout by every command under `--json`. */
|
|
5
|
+
export interface Envelope<T = unknown> {
|
|
6
|
+
schemaVersion: typeof OUTPUT_SCHEMA_VERSION;
|
|
7
|
+
command: string;
|
|
8
|
+
ok: boolean;
|
|
9
|
+
data?: T;
|
|
10
|
+
error?: SerializedError;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* JSON Schema of the envelope. `data` is typed per command: the schema of
|
|
14
|
+
* e.g. `sforge build --json` data is `$defs/build-data`.
|
|
15
|
+
*/
|
|
16
|
+
export declare function outputJsonSchema(): Record<string, unknown>;
|
|
17
|
+
//# sourceMappingURL=output.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAGzD,uEAAuE;AACvE,eAAO,MAAM,qBAAqB,IAAI,CAAC;AAEvC,kFAAkF;AAClF,MAAM,WAAW,QAAQ,CAAC,CAAC,GAAG,OAAO;IACnC,aAAa,EAAE,OAAO,qBAAqB,CAAC;IAC5C,OAAO,EAAE,MAAM,CAAC;IAChB,EAAE,EAAE,OAAO,CAAC;IACZ,IAAI,CAAC,EAAE,CAAC,CAAC;IACT,KAAK,CAAC,EAAE,eAAe,CAAC;CACzB;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA2B1D"}
|
package/dist/output.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { commandDataSchemas, dataDefName, sharedDefs } from './schemas.js';
|
|
2
|
+
/** Version of the `--json` envelope. Bump only on breaking changes. */
|
|
3
|
+
export const OUTPUT_SCHEMA_VERSION = 1;
|
|
4
|
+
/**
|
|
5
|
+
* JSON Schema of the envelope. `data` is typed per command: the schema of
|
|
6
|
+
* e.g. `sforge build --json` data is `$defs/build-data`.
|
|
7
|
+
*/
|
|
8
|
+
export function outputJsonSchema() {
|
|
9
|
+
const commands = commandDataSchemas();
|
|
10
|
+
const defs = { ...sharedDefs() };
|
|
11
|
+
for (const [command, schema] of Object.entries(commands))
|
|
12
|
+
defs[dataDefName(command)] = schema;
|
|
13
|
+
return {
|
|
14
|
+
$schema: 'https://json-schema.org/draft/2020-12/schema',
|
|
15
|
+
$id: 'urn:staticforge:schema:output:v1',
|
|
16
|
+
title: 'staticforge --json output envelope',
|
|
17
|
+
type: 'object',
|
|
18
|
+
required: ['schemaVersion', 'command', 'ok'],
|
|
19
|
+
additionalProperties: false,
|
|
20
|
+
properties: {
|
|
21
|
+
schemaVersion: { const: OUTPUT_SCHEMA_VERSION },
|
|
22
|
+
command: {
|
|
23
|
+
type: 'string',
|
|
24
|
+
description: 'Command path, e.g. "config validate"; empty for usage errors.',
|
|
25
|
+
},
|
|
26
|
+
ok: { type: 'boolean', description: 'False when the command failed or found failures.' },
|
|
27
|
+
data: { description: 'Command-specific result; see the per-command rules below.' },
|
|
28
|
+
error: { $ref: '#/$defs/error' },
|
|
29
|
+
},
|
|
30
|
+
allOf: Object.keys(commands).map((command) => ({
|
|
31
|
+
if: { properties: { command: { const: command } }, required: ['command', 'data'] },
|
|
32
|
+
then: { properties: { data: { $ref: `#/$defs/${dataDefName(command)}` } } },
|
|
33
|
+
})),
|
|
34
|
+
$defs: defs,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=output.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.js","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE3E,uEAAuE;AACvE,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC;AAWvC;;;GAGG;AACH,MAAM,UAAU,gBAAgB;IAC9B,MAAM,QAAQ,GAAG,kBAAkB,EAAE,CAAC;IACtC,MAAM,IAAI,GAA4B,EAAE,GAAG,UAAU,EAAE,EAAE,CAAC;IAC1D,KAAK,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC;QAAE,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,GAAG,MAAM,CAAC;IAC9F,OAAO;QACL,OAAO,EAAE,8CAA8C;QACvD,GAAG,EAAE,kCAAkC;QACvC,KAAK,EAAE,oCAAoC;QAC3C,IAAI,EAAE,QAAQ;QACd,QAAQ,EAAE,CAAC,eAAe,EAAE,SAAS,EAAE,IAAI,CAAC;QAC5C,oBAAoB,EAAE,KAAK;QAC3B,UAAU,EAAE;YACV,aAAa,EAAE,EAAE,KAAK,EAAE,qBAAqB,EAAE;YAC/C,OAAO,EAAE;gBACP,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,+DAA+D;aAC7E;YACD,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,kDAAkD,EAAE;YACxF,IAAI,EAAE,EAAE,WAAW,EAAE,2DAA2D,EAAE;YAClF,KAAK,EAAE,EAAE,IAAI,EAAE,eAAe,EAAE;SACjC;QACD,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;YAC7C,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,SAAS,EAAE,MAAM,CAAC,EAAE;YAClF,IAAI,EAAE,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,WAAW,WAAW,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,EAAE;SAC5E,CAAC,CAAC;QACH,KAAK,EAAE,IAAI;KACZ,CAAC;AACJ,CAAC"}
|
package/dist/paths.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAEA,+EAA+E;AAC/E,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAI7D"}
|
package/dist/paths.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { relative } from 'node:path';
|
|
2
|
+
/** A path for humans: relative to `cwd` when inside it, otherwise absolute. */
|
|
3
|
+
export function displayPath(cwd, path) {
|
|
4
|
+
const rel = relative(cwd, path);
|
|
5
|
+
if (rel === '')
|
|
6
|
+
return '.';
|
|
7
|
+
return rel.startsWith('..') ? path : rel;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=paths.js.map
|