@vibeframe/mcp-server 0.109.2 → 0.110.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/README.md +15 -0
- package/dist/index.js +132 -16
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -125,6 +125,21 @@ Claude Code drives `vibe` natively via shell + the scaffolded `AGENTS.md` / `CLA
|
|
|
125
125
|
claude mcp add vibeframe --scope project -- npx -y @vibeframe/mcp-server
|
|
126
126
|
```
|
|
127
127
|
|
|
128
|
+
## Human-in-the-Loop Choices
|
|
129
|
+
|
|
130
|
+
The server prefers asking over silently picking defaults:
|
|
131
|
+
|
|
132
|
+
- On hosts that support **MCP elicitation** (Claude Code 2.1.76+), the `build`
|
|
133
|
+
tool opens a native form before the build starts for any choice the call
|
|
134
|
+
left unspecified: narration provider (Kokoro free/local vs ElevenLabs),
|
|
135
|
+
backdrop image generation (skip vs paid OpenAI), and a max cost cap.
|
|
136
|
+
Declining cancels the build before any provider spend. Set
|
|
137
|
+
`VIBE_MCP_ELICIT=off` in the server env to disable the form (headless and
|
|
138
|
+
automation setups).
|
|
139
|
+
- On hosts without elicitation (Claude Desktop today), the server
|
|
140
|
+
instructions tell the agent to present the same choices in chat and wait
|
|
141
|
+
for your answer.
|
|
142
|
+
|
|
128
143
|
## What You Can Do
|
|
129
144
|
|
|
130
145
|
Once connected, your MCP host can resolve prompts like these into typed tool calls:
|
package/dist/index.js
CHANGED
|
@@ -486486,6 +486486,76 @@ function pickOutputPath(data) {
|
|
|
486486
486486
|
return typeof candidate === "string" ? candidate : void 0;
|
|
486487
486487
|
}
|
|
486488
486488
|
|
|
486489
|
+
// ../cli/src/tools/_shared/elicit.ts
|
|
486490
|
+
var NARRATION_CHOICES = ["kokoro", "elevenlabs"];
|
|
486491
|
+
var BACKDROP_CHOICES = ["skip", "openai"];
|
|
486492
|
+
function planBuildElicitation(args) {
|
|
486493
|
+
const assetsWillRun = args.stage === void 0 || args.stage === "all" || args.stage === "assets";
|
|
486494
|
+
if (!assetsWillRun) return null;
|
|
486495
|
+
const properties = {};
|
|
486496
|
+
const required = [];
|
|
486497
|
+
const narrationUndecided = !args.skipNarration && (args.ttsProvider === void 0 || args.ttsProvider === "auto");
|
|
486498
|
+
if (narrationUndecided) {
|
|
486499
|
+
properties.narration = {
|
|
486500
|
+
type: "string",
|
|
486501
|
+
title: "Narration voice-over",
|
|
486502
|
+
description: "Which TTS engine narrates the video?",
|
|
486503
|
+
enum: [...NARRATION_CHOICES],
|
|
486504
|
+
enumNames: [
|
|
486505
|
+
"Kokoro \u2014 free, runs locally on this machine",
|
|
486506
|
+
"ElevenLabs \u2014 cloud TTS, uses your ElevenLabs credits"
|
|
486507
|
+
]
|
|
486508
|
+
};
|
|
486509
|
+
required.push("narration");
|
|
486510
|
+
}
|
|
486511
|
+
if (args.skipBackdrop === void 0 && args.imageProvider === void 0) {
|
|
486512
|
+
properties.backdrop_images = {
|
|
486513
|
+
type: "string",
|
|
486514
|
+
title: "Backdrop images",
|
|
486515
|
+
description: "Generate AI background images for each scene?",
|
|
486516
|
+
enum: [...BACKDROP_CHOICES],
|
|
486517
|
+
enumNames: [
|
|
486518
|
+
"Skip \u2014 free, pure typographic scenes",
|
|
486519
|
+
"OpenAI \u2014 paid image generation (roughly $1-3 per video)"
|
|
486520
|
+
]
|
|
486521
|
+
};
|
|
486522
|
+
required.push("backdrop_images");
|
|
486523
|
+
}
|
|
486524
|
+
if (args.maxCostUsd === void 0) {
|
|
486525
|
+
properties.max_cost_usd = {
|
|
486526
|
+
type: "number",
|
|
486527
|
+
title: "Max provider spend (USD)",
|
|
486528
|
+
description: "Abort before any paid provider call when the estimate exceeds this cap. Leave empty for no cap.",
|
|
486529
|
+
minimum: 0
|
|
486530
|
+
};
|
|
486531
|
+
}
|
|
486532
|
+
if (Object.keys(properties).length === 0) return null;
|
|
486533
|
+
return {
|
|
486534
|
+
message: "VibeFrame is about to build this video. Choose how the assets are generated:",
|
|
486535
|
+
requestedSchema: { type: "object", properties, required }
|
|
486536
|
+
};
|
|
486537
|
+
}
|
|
486538
|
+
function applyElicitationAnswers(args, content) {
|
|
486539
|
+
if (!content) return args;
|
|
486540
|
+
const next = { ...args };
|
|
486541
|
+
const narration = content.narration;
|
|
486542
|
+
if (typeof narration === "string" && NARRATION_CHOICES.includes(narration)) {
|
|
486543
|
+
next.ttsProvider = narration;
|
|
486544
|
+
}
|
|
486545
|
+
const backdrop = content.backdrop_images;
|
|
486546
|
+
if (backdrop === "skip") {
|
|
486547
|
+
next.skipBackdrop = true;
|
|
486548
|
+
} else if (backdrop === "openai") {
|
|
486549
|
+
next.skipBackdrop = false;
|
|
486550
|
+
next.imageProvider = "openai";
|
|
486551
|
+
}
|
|
486552
|
+
const cap = content.max_cost_usd;
|
|
486553
|
+
if (typeof cap === "number" && Number.isFinite(cap) && cap >= 0) {
|
|
486554
|
+
next.maxCostUsd = cap;
|
|
486555
|
+
}
|
|
486556
|
+
return next;
|
|
486557
|
+
}
|
|
486558
|
+
|
|
486489
486559
|
// ../cli/src/commands/_shared/visual-styles.ts
|
|
486490
486560
|
var STYLES = [
|
|
486491
486561
|
{
|
|
@@ -488724,9 +488794,32 @@ var sceneBuildTool = defineTool({
|
|
|
488724
488794
|
name: "build",
|
|
488725
488795
|
category: "scene",
|
|
488726
488796
|
cost: "high",
|
|
488727
|
-
description: "v0.60 one-shot orchestrator: read STORYBOARD.md per-beat YAML cues (narration / backdrop / duration), dispatch TTS + image generation per beat, compose scene HTML via the compose-scenes-with-skills pipeline, then render to MP4. Use this instead of chaining init + scene_add + render manually. Caches by SHA256 of (DESIGN.md + cue body) so re-runs are idempotent and cheap. Long runs: over MCP, calls exceeding ~45s return immediately with { promoted: true, jobId, status: 'running' } \u2014 poll status_job every 15-30s until completed/failed instead of re-invoking build. Emits MCP progress notifications when the client supplies a progressToken.",
|
|
488797
|
+
description: "v0.60 one-shot orchestrator: read STORYBOARD.md per-beat YAML cues (narration / backdrop / duration), dispatch TTS + image generation per beat, compose scene HTML via the compose-scenes-with-skills pipeline, then render to MP4. Use this instead of chaining init + scene_add + render manually. Caches by SHA256 of (DESIGN.md + cue body) so re-runs are idempotent and cheap. Long runs: over MCP, calls exceeding ~45s return immediately with { promoted: true, jobId, status: 'running' } \u2014 poll status_job every 15-30s until completed/failed instead of re-invoking build. Emits MCP progress notifications when the client supplies a progressToken. When the MCP host supports elicitation, unspecified asset choices (narration provider, backdrop images, cost cap) are confirmed with the user via a form before the build starts.",
|
|
488728
488798
|
schema: sceneBuildSchema,
|
|
488729
488799
|
async execute(args, ctx) {
|
|
488800
|
+
let warnings;
|
|
488801
|
+
if (ctx.surface === "mcp" && ctx.elicit) {
|
|
488802
|
+
const form = planBuildElicitation(args);
|
|
488803
|
+
if (form) {
|
|
488804
|
+
const outcome = await ctx.elicit(form).catch(() => null);
|
|
488805
|
+
if (outcome === null) {
|
|
488806
|
+
warnings = ["Asset-choice elicitation failed or timed out; proceeding with defaults."];
|
|
488807
|
+
} else if (outcome.action === "accept") {
|
|
488808
|
+
args = applyElicitationAnswers(args, outcome.content);
|
|
488809
|
+
} else {
|
|
488810
|
+
return {
|
|
488811
|
+
success: false,
|
|
488812
|
+
error: "Build cancelled \u2014 the user declined the asset choices.",
|
|
488813
|
+
data: {
|
|
488814
|
+
cancelled: true,
|
|
488815
|
+
retryWith: [
|
|
488816
|
+
`build { projectDir: "${args.projectDir ?? "."}", ttsProvider: "kokoro", skipBackdrop: true }`
|
|
488817
|
+
]
|
|
488818
|
+
}
|
|
488819
|
+
};
|
|
488820
|
+
}
|
|
488821
|
+
}
|
|
488822
|
+
}
|
|
488730
488823
|
const projectDir = args.projectDir ? resolve34(ctx.workingDirectory, args.projectDir) : ctx.workingDirectory;
|
|
488731
488824
|
const runBuild = (report) => executeSceneBuild({
|
|
488732
488825
|
projectDir,
|
|
@@ -488754,7 +488847,9 @@ var sceneBuildTool = defineTool({
|
|
|
488754
488847
|
ctx.onProgress?.({ message: update2.message ?? update2.stage });
|
|
488755
488848
|
report(update2);
|
|
488756
488849
|
}
|
|
488757
|
-
}).then(mapBuildResultToToolResult)
|
|
488850
|
+
}).then(mapBuildResultToToolResult).then(
|
|
488851
|
+
(result) => warnings === void 0 ? result : { ...result, data: { ...result.data, elicitationWarnings: warnings } }
|
|
488852
|
+
);
|
|
488758
488853
|
if (ctx.surface !== "mcp") {
|
|
488759
488854
|
return runBuild(() => void 0);
|
|
488760
488855
|
}
|
|
@@ -497252,7 +497347,8 @@ function buildMcpDispatcher(manifest2) {
|
|
|
497252
497347
|
() => tool.execute(parsed.data, {
|
|
497253
497348
|
workingDirectory: process.cwd(),
|
|
497254
497349
|
surface: "mcp",
|
|
497255
|
-
...extra?.onProgress ? { onProgress: sink.send } : {}
|
|
497350
|
+
...extra?.onProgress ? { onProgress: sink.send } : {},
|
|
497351
|
+
...extra?.elicit ? { elicit: extra.elicit } : {}
|
|
497256
497352
|
})
|
|
497257
497353
|
);
|
|
497258
497354
|
const text = result.success ? JSON.stringify({ success: true, ...result.data }) : result.data ? JSON.stringify({
|
|
@@ -497747,10 +497843,22 @@ function buildServerInstructions(cwd = resolveServerWorkspaceRoot()) {
|
|
|
497747
497843
|
"For args named dir, projectDir, output, videoPath, or source, prefer workspace-relative paths unless the user explicitly provides an absolute path.",
|
|
497748
497844
|
"When creating projects with init, use a project name or workspace-relative path under the workspace root.",
|
|
497749
497845
|
"Do not create projects in /tmp, /home/claude, /workspace, or other synthetic roots unless the user explicitly asks.",
|
|
497750
|
-
"Before high or very-high cost provider work, run a dry-run or plan when available and ask the user to confirm provider spend."
|
|
497846
|
+
"Before high or very-high cost provider work, run a dry-run or plan when available and ask the user to confirm provider spend.",
|
|
497847
|
+
"When the user's request leaves them unspecified, ask the user before building instead of silently picking defaults: narration provider (kokoro = free local, elevenlabs = cloud credits), backdrop image generation (paid; skipping is free), and visual style (list options via scene_list_styles). Present the choices and wait for the answer."
|
|
497751
497848
|
].join("\n");
|
|
497752
497849
|
}
|
|
497753
497850
|
|
|
497851
|
+
// src/elicit.ts
|
|
497852
|
+
var ELICIT_TIMEOUT_MS = 6e5;
|
|
497853
|
+
function makeElicitFn(server3, env4 = process.env) {
|
|
497854
|
+
if ((env4.VIBE_MCP_ELICIT ?? "").toLowerCase() === "off") return void 0;
|
|
497855
|
+
if (!server3.getClientCapabilities()?.elicitation) return void 0;
|
|
497856
|
+
return (form) => server3.elicitInput(
|
|
497857
|
+
{ mode: "form", message: form.message, requestedSchema: form.requestedSchema },
|
|
497858
|
+
{ timeout: ELICIT_TIMEOUT_MS }
|
|
497859
|
+
);
|
|
497860
|
+
}
|
|
497861
|
+
|
|
497754
497862
|
// src/index.ts
|
|
497755
497863
|
console.log = (...args) => console.error(...args);
|
|
497756
497864
|
console.info = (...args) => console.error(...args);
|
|
@@ -497761,7 +497869,7 @@ var server2 = new Server(
|
|
|
497761
497869
|
{
|
|
497762
497870
|
name: "vibeframe",
|
|
497763
497871
|
// Stamped with the package version by build.js at bundle time.
|
|
497764
|
-
version: "0.
|
|
497872
|
+
version: "0.110.0"
|
|
497765
497873
|
},
|
|
497766
497874
|
{
|
|
497767
497875
|
capabilities: {
|
|
@@ -497778,20 +497886,28 @@ server2.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
497778
497886
|
server2.setRequestHandler(CallToolRequestSchema, async (request5, extra) => {
|
|
497779
497887
|
const { name, arguments: args } = request5.params;
|
|
497780
497888
|
const progressToken = request5.params._meta?.progressToken;
|
|
497889
|
+
const elicit = makeElicitFn(server2);
|
|
497781
497890
|
return handleToolCall(
|
|
497782
497891
|
name,
|
|
497783
497892
|
args || {},
|
|
497784
|
-
progressToken === void 0 ? void 0 : {
|
|
497785
|
-
|
|
497786
|
-
|
|
497787
|
-
|
|
497788
|
-
|
|
497789
|
-
|
|
497790
|
-
|
|
497791
|
-
|
|
497792
|
-
|
|
497793
|
-
|
|
497794
|
-
|
|
497893
|
+
progressToken === void 0 && elicit === void 0 ? void 0 : {
|
|
497894
|
+
...elicit ? { elicit } : {},
|
|
497895
|
+
...progressToken === void 0 ? {} : {
|
|
497896
|
+
onProgress: ({
|
|
497897
|
+
progress,
|
|
497898
|
+
total,
|
|
497899
|
+
message
|
|
497900
|
+
}) => {
|
|
497901
|
+
void extra.sendNotification({
|
|
497902
|
+
method: "notifications/progress",
|
|
497903
|
+
params: {
|
|
497904
|
+
progressToken,
|
|
497905
|
+
progress: progress ?? 0,
|
|
497906
|
+
...total !== void 0 ? { total } : {},
|
|
497907
|
+
...message ? { message } : {}
|
|
497908
|
+
}
|
|
497909
|
+
}).catch(() => void 0);
|
|
497910
|
+
}
|
|
497795
497911
|
}
|
|
497796
497912
|
}
|
|
497797
497913
|
);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vibeframe/mcp-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.110.0",
|
|
4
4
|
"description": "VibeFrame MCP Server - AI-native video editing via Model Context Protocol",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -60,8 +60,8 @@
|
|
|
60
60
|
"tsx": "^4.21.0",
|
|
61
61
|
"typescript": "^5.3.3",
|
|
62
62
|
"vitest": "^1.2.2",
|
|
63
|
-
"@vibeframe/core": "0.
|
|
64
|
-
"@vibeframe/cli": "0.
|
|
63
|
+
"@vibeframe/core": "0.110.0",
|
|
64
|
+
"@vibeframe/cli": "0.110.0"
|
|
65
65
|
},
|
|
66
66
|
"engines": {
|
|
67
67
|
"node": ">=20"
|