@amg555/frameforge-mcp 2.4.0 → 2.4.1
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/CHANGELOG.md +13 -0
- package/package.json +2 -1
- package/scripts/deep-validate.js +2 -2
- package/src/cli/make.js +14 -0
- package/src/mcp-server/server.js +1 -1
- package/src/mcp-server/stdio.js +28 -0
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,19 @@ All notable changes to FrameForge are documented here.
|
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
+
## [2.4.1] — 2026-11-09
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
- **CLI & npx Invocation Handling (`src/mcp-server/stdio.js`, `package.json`)**:
|
|
11
|
+
- Registered `frameforge-make` binary alias in `package.json` so `npx --package=@amg555/frameforge-mcp frameforge-make` works immediately.
|
|
12
|
+
- Added CLI dispatch interception in `stdio.js` when flags or subcommands (`make`, `--topic`, `doctor`, `setup`, `harness`) are passed, preventing npx CLI invocations from hanging on stdio JSON-RPC stdin.
|
|
13
|
+
- **Language & Orientation Forwarding in CLI (`src/cli/make.js`)**:
|
|
14
|
+
- Added `--orientation <landscape|portrait>` and `--portrait` flags.
|
|
15
|
+
- Forwarded `language` and auto-selected `voice` (`ml-IN-MidhunNeural`, `hi-IN-MadhurNeural`, etc.) to `runAssets` and `runRender`.
|
|
16
|
+
- Forwarded `renderWidth` and `renderHeight` to `runRender` so canvas dimensions match requested orientation.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
7
20
|
## [2.4.0] — 2026-11-09
|
|
8
21
|
|
|
9
22
|
### Added
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@amg555/frameforge-mcp",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.1",
|
|
4
4
|
"description": "FrameForge — AI video production engine for agentic IDEs. npx @amg555/frameforge-mcp. FFmpeg + TTS run on your machine. 21 MCP tools.",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
"main": "src/mcp-server/server.js",
|
|
9
9
|
"bin": {
|
|
10
10
|
"frameforge": "src/cli/make.js",
|
|
11
|
+
"frameforge-make": "src/cli/make.js",
|
|
11
12
|
"frameforge-mcp": "src/mcp-server/stdio.js",
|
|
12
13
|
"frameforge-setup": "src/cli/setup-keys.js",
|
|
13
14
|
"frameforge-doctor": "src/cli/doctor.js",
|
package/scripts/deep-validate.js
CHANGED
|
@@ -20,7 +20,7 @@ check('batch handling', code.includes('Array.isArray(body)'));
|
|
|
20
20
|
check('ping handler', code.includes("method === 'ping'"));
|
|
21
21
|
check('notifications/init', code.includes("notifications/initialized"));
|
|
22
22
|
check('body size limit', code.includes('MAX_BODY_BYTES'));
|
|
23
|
-
check('SERVER_INFO version 2.4.
|
|
23
|
+
check('SERVER_INFO version 2.4.1', code.includes("version: '2.4.1'"));
|
|
24
24
|
check('18 tools defined (incl get_job_status)', code.includes('get_job_status'));
|
|
25
25
|
check('export_to_editor tool defined', code.includes('export_to_editor'));
|
|
26
26
|
check('edit_video tool defined', code.includes('edit_video'));
|
|
@@ -299,7 +299,7 @@ check('cf-worker has checkRateLimit', cfWorker.includes('checkRateLimit'));
|
|
|
299
299
|
check('cf-worker hashes token (SHA-256)', cfWorker.includes('SHA-256'));
|
|
300
300
|
check('cf-worker uses RATE_LIMITS KV', cfWorker.includes('env.RATE_LIMITS'));
|
|
301
301
|
check('cf-worker returns 429 on limit', cfWorker.includes('429'));
|
|
302
|
-
check('cf-worker version 2.4.
|
|
302
|
+
check('cf-worker version 2.4.1', cfWorker.includes("'2.4.1'"));
|
|
303
303
|
check('wrangler.toml has kv_namespaces',fs.readFileSync('./cloudflare-mcp/wrangler.toml','utf8').includes('kv_namespaces'));
|
|
304
304
|
|
|
305
305
|
// ── plugins/skills present ────────────────────────────────────────────────
|
package/src/cli/make.js
CHANGED
|
@@ -98,6 +98,7 @@ function parseArgs(argv) {
|
|
|
98
98
|
mode: 'full-auto',
|
|
99
99
|
topic: '', topicsFile: '', language: 'en',
|
|
100
100
|
style: 'educational comedy', channels: ['file'],
|
|
101
|
+
orientation: 'landscape',
|
|
101
102
|
scenesFile: '', scriptFile: '', mediaDir: '',
|
|
102
103
|
shorts: true, dryRun: false,
|
|
103
104
|
noResearch: false, noScript: false, noImages: false, noTts: false, noPublish: false,
|
|
@@ -112,6 +113,8 @@ function parseArgs(argv) {
|
|
|
112
113
|
case '--script-file': args.scriptFile = argv[++i] || ''; break;
|
|
113
114
|
case '--media-dir': args.mediaDir = argv[++i] || ''; break;
|
|
114
115
|
case '--language': args.language = (argv[++i] || 'en').toLowerCase(); break;
|
|
116
|
+
case '--orientation': args.orientation = (argv[++i] || 'landscape').toLowerCase(); break;
|
|
117
|
+
case '--portrait': args.orientation = 'portrait'; break;
|
|
115
118
|
case '--style': args.style = argv[++i] || args.style; break;
|
|
116
119
|
case '--channels': args.channels = (argv[++i] || 'file').split(',').map(s => s.trim()); break;
|
|
117
120
|
case '--no-research': args.noResearch = true; break;
|
|
@@ -399,10 +402,13 @@ async function runSingleVideo(args, topic, outDir, workflows) {
|
|
|
399
402
|
// Pass stage-skip flags into scenes so runAssets can honour them
|
|
400
403
|
const preparedScenes = scenes.map(s => ({
|
|
401
404
|
...s,
|
|
405
|
+
language: s.language || args.language,
|
|
402
406
|
_skipImageGen: skipImages,
|
|
403
407
|
_skipTts: args.noTts,
|
|
404
408
|
}));
|
|
405
409
|
|
|
410
|
+
const resolvedVoice = LANGUAGE_VOICES[args.language] || null;
|
|
411
|
+
|
|
406
412
|
const assetsResult = await runAssets({
|
|
407
413
|
productionId,
|
|
408
414
|
scenes: preparedScenes,
|
|
@@ -413,17 +419,25 @@ async function runSingleVideo(args, topic, outDir, workflows) {
|
|
|
413
419
|
topic,
|
|
414
420
|
title,
|
|
415
421
|
style: args.style || '',
|
|
422
|
+
language: args.language,
|
|
423
|
+
voice: resolvedVoice,
|
|
416
424
|
});
|
|
417
425
|
log('Assets', `✅ ${assetsResult.sceneCount} scenes prepared`);
|
|
418
426
|
|
|
419
427
|
// ── Stage D: Render ────────────────────────────────────────────────────────
|
|
420
428
|
logSection('Stage D: Video Render (FFmpeg)');
|
|
429
|
+
const renderWidth = args.orientation === 'portrait' ? 1080 : 1920;
|
|
430
|
+
const renderHeight = args.orientation === 'portrait' ? 1920 : 1080;
|
|
431
|
+
|
|
421
432
|
const renderResult = await runRender({
|
|
422
433
|
productionId,
|
|
423
434
|
sceneAssets: assetsResult.sceneAssets,
|
|
424
435
|
topic,
|
|
425
436
|
title,
|
|
426
437
|
style: args.style || '',
|
|
438
|
+
language: args.language,
|
|
439
|
+
renderWidth,
|
|
440
|
+
renderHeight,
|
|
427
441
|
});
|
|
428
442
|
if (!renderResult.passed) {
|
|
429
443
|
throw new Error(`Quality gate FAILED: ${JSON.stringify(renderResult.qcReport?.checks?.filter(c => !c.passed).map(c => c.name))}`);
|
package/src/mcp-server/server.js
CHANGED
package/src/mcp-server/stdio.js
CHANGED
|
@@ -34,6 +34,34 @@
|
|
|
34
34
|
// Load config BEFORE requiring server.js so env vars are set when providers initialise
|
|
35
35
|
require('../config/load-config').loadConfig();
|
|
36
36
|
|
|
37
|
+
// ── CLI Dispatch Fallback ──────────────────────────────────────────────────
|
|
38
|
+
// When run via `npx @amg555/frameforge-mcp` with CLI arguments (e.g. `make`, `--topic`,
|
|
39
|
+
// `doctor`, `setup`, `harness`, or `--help`), dispatch to the CLI tool instead of
|
|
40
|
+
// hanging on stdin JSON-RPC.
|
|
41
|
+
const firstArg = process.argv[2];
|
|
42
|
+
if (firstArg && (firstArg === 'make' || firstArg.startsWith('-') || firstArg === 'doctor' || firstArg === 'setup' || firstArg === 'harness')) {
|
|
43
|
+
if (firstArg === 'doctor') {
|
|
44
|
+
require('../cli/doctor');
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
if (firstArg === 'setup') {
|
|
48
|
+
require('../cli/setup-keys');
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
if (firstArg === 'harness') {
|
|
52
|
+
const harnessBin = require('path').resolve(__dirname, '../harness/bin/harness.mjs');
|
|
53
|
+
const { spawnSync } = require('child_process');
|
|
54
|
+
const res = spawnSync(process.execPath, [harnessBin, ...process.argv.slice(3)], { stdio: 'inherit' });
|
|
55
|
+
process.exit(res.status ?? 0);
|
|
56
|
+
}
|
|
57
|
+
// Otherwise dispatch to make.js (stripping 'make' if present)
|
|
58
|
+
if (firstArg === 'make') {
|
|
59
|
+
process.argv.splice(2, 1);
|
|
60
|
+
}
|
|
61
|
+
require('../cli/make');
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
|
|
37
65
|
const readline = require('readline');
|
|
38
66
|
const { handleMCPRequest } = require('./server');
|
|
39
67
|
|