@vibeframe/mcp-server 0.109.2 → 0.111.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.
Files changed (3) hide show
  1. package/README.md +32 -0
  2. package/dist/index.js +346 -17
  3. 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:
@@ -308,6 +323,23 @@ API keys are read from the host's environment (`~/.zshrc`, MCP config `env` bloc
308
323
  - Node.js 20+
309
324
  - FFmpeg on `PATH` (export, editing, pipelines)
310
325
 
326
+ ## Privacy Policy
327
+
328
+ VibeFrame is local-first: no telemetry, no VibeFrame-operated servers in the
329
+ data path. Projects and generated media stay in the workspace folder you
330
+ choose; content is sent only to the AI providers you configure (Anthropic,
331
+ OpenAI, Google, ElevenLabs, …) when you explicitly invoke them, and API keys
332
+ live only on your machine. Tools that reach external services are marked with
333
+ `openWorldHint` in their MCP annotations; everything else (timeline edits,
334
+ ffmpeg operations, linting, rendering, local Kokoro TTS) runs fully locally.
335
+
336
+ Full policy: <https://vibeframe.ai/privacy> (source:
337
+ [PRIVACY.md](https://github.com/vericontext/vibeframe/blob/main/PRIVACY.md)).
338
+
339
+ > Installing the `.mcpb` file directly shows a standard "not verified by
340
+ > Anthropic" sideload notice in Claude Desktop — that is expected for
341
+ > extensions distributed outside the official directory.
342
+
311
343
  ## License
312
344
 
313
345
  MIT
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
  {
@@ -488289,6 +488359,8 @@ var sceneStylesTool = defineTool({
488289
488359
  name: "scene_list_styles",
488290
488360
  category: "scene",
488291
488361
  cost: "free",
488362
+ title: "List Visual Styles",
488363
+ annotations: { readOnly: true, openWorld: false },
488292
488364
  description: "List the 8 vendored visual identities available for `init --visual-style` (Swiss Pulse, Data Drift, \u2026) or, when `name` is provided, return the full DESIGN.md hard-gate body for one style. The DESIGN.md content is what the LLM uses as a non-negotiable visual rulebook during compose-scenes-with-skills.",
488293
488365
  schema: sceneStylesSchema,
488294
488366
  async execute(args) {
@@ -488350,6 +488422,8 @@ var sceneInitTool = defineTool({
488350
488422
  name: "init",
488351
488423
  category: "scene",
488352
488424
  cost: "free",
488425
+ title: "Initialize Video Project",
488426
+ annotations: { readOnly: false, destructive: false, idempotent: true, openWorld: false },
488353
488427
  description: "Scaffold a new VibeFrame video scene project. Supports minimal, agent, and full profiles; full includes the current HTML render backend metadata. Idempotent: re-running keeps user-authored files and merges backend config instead of overwriting. No API keys required.",
488354
488428
  schema: sceneInitSchema,
488355
488429
  async execute(args, ctx) {
@@ -488400,6 +488474,8 @@ var sceneAddTool = defineTool({
488400
488474
  name: "scene_add",
488401
488475
  category: "scene",
488402
488476
  cost: "low",
488477
+ title: "Add Scene from Preset",
488478
+ annotations: { readOnly: false, openWorld: true },
488403
488479
  description: "Add a single scene to an existing scene project. Optionally generates narration audio (ElevenLabs) and/or a backdrop image (Gemini/OpenAI), then emits compositions/scene-<id>.html with a paused GSAP timeline and splices a clip reference into the root index.html. Use skipAudio:true and skipImage:true for text-only scenes that need no API calls.",
488404
488480
  schema: sceneAddSchema,
488405
488481
  async execute(args, ctx) {
@@ -488478,6 +488554,8 @@ var sceneLintTool = defineTool({
488478
488554
  name: "scene_lint",
488479
488555
  category: "scene",
488480
488556
  cost: "free",
488557
+ title: "Lint Scene Compositions",
488558
+ annotations: { readOnly: false, idempotent: true, openWorld: false },
488481
488559
  description: "Validate every scene file in a project against the public Hyperframes lint rules (in-process, no Chrome required). Returns errors, warnings, and info findings per file. Optional fix:true mechanically repairs `timed_element_missing_clip_class` only \u2014 other issues surface with fixHints.",
488482
488560
  schema: sceneLintSchema,
488483
488561
  async execute(args, ctx) {
@@ -488515,6 +488593,8 @@ var sceneRepairTool = defineTool({
488515
488593
  name: "scene_repair",
488516
488594
  category: "scene",
488517
488595
  cost: "free",
488596
+ title: "Repair Scene Compositions",
488597
+ annotations: { readOnly: false, idempotent: true, openWorld: false },
488518
488598
  description: "Apply deterministic mechanical scene repairs. Currently uses the safe lint auto-fix allow-list and never performs semantic creative rewrites.",
488519
488599
  schema: sceneRepairSchema,
488520
488600
  async execute(args, ctx) {
@@ -488595,6 +488675,8 @@ var sceneRenderTool = defineTool({
488595
488675
  name: "render",
488596
488676
  category: "scene",
488597
488677
  cost: "free",
488678
+ title: "Render Video to MP4",
488679
+ annotations: { readOnly: false, openWorld: false },
488598
488680
  description: "Render a scene project to MP4/WebM/MOV via the Hyperframes producer. Requires Chrome installed locally. Output defaults to renders/<projectName>-<isoStamp>.<format>. 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 render. Emits MCP progress notifications when the client supplies a progressToken.",
488599
488681
  schema: sceneRenderSchema,
488600
488682
  async execute(args, ctx) {
@@ -488724,9 +488806,34 @@ var sceneBuildTool = defineTool({
488724
488806
  name: "build",
488725
488807
  category: "scene",
488726
488808
  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.",
488809
+ title: "Build Video from Storyboard",
488810
+ annotations: { readOnly: false, openWorld: true },
488811
+ 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
488812
  schema: sceneBuildSchema,
488729
488813
  async execute(args, ctx) {
488814
+ let warnings;
488815
+ if (ctx.surface === "mcp" && ctx.elicit) {
488816
+ const form = planBuildElicitation(args);
488817
+ if (form) {
488818
+ const outcome = await ctx.elicit(form).catch(() => null);
488819
+ if (outcome === null) {
488820
+ warnings = ["Asset-choice elicitation failed or timed out; proceeding with defaults."];
488821
+ } else if (outcome.action === "accept") {
488822
+ args = applyElicitationAnswers(args, outcome.content);
488823
+ } else {
488824
+ return {
488825
+ success: false,
488826
+ error: "Build cancelled \u2014 the user declined the asset choices.",
488827
+ data: {
488828
+ cancelled: true,
488829
+ retryWith: [
488830
+ `build { projectDir: "${args.projectDir ?? "."}", ttsProvider: "kokoro", skipBackdrop: true }`
488831
+ ]
488832
+ }
488833
+ };
488834
+ }
488835
+ }
488836
+ }
488730
488837
  const projectDir = args.projectDir ? resolve34(ctx.workingDirectory, args.projectDir) : ctx.workingDirectory;
488731
488838
  const runBuild = (report) => executeSceneBuild({
488732
488839
  projectDir,
@@ -488754,7 +488861,9 @@ var sceneBuildTool = defineTool({
488754
488861
  ctx.onProgress?.({ message: update2.message ?? update2.stage });
488755
488862
  report(update2);
488756
488863
  }
488757
- }).then(mapBuildResultToToolResult);
488864
+ }).then(mapBuildResultToToolResult).then(
488865
+ (result) => warnings === void 0 ? result : { ...result, data: { ...result.data, elicitationWarnings: warnings } }
488866
+ );
488758
488867
  if (ctx.surface !== "mcp") {
488759
488868
  return runBuild(() => void 0);
488760
488869
  }
@@ -488781,6 +488890,8 @@ var sceneInstallSkillTool = defineTool({
488781
488890
  name: "scene_install_skill",
488782
488891
  category: "scene",
488783
488892
  cost: "free",
488893
+ title: "Install Hyperframes Skill",
488894
+ annotations: { readOnly: false, idempotent: true, openWorld: false },
488784
488895
  description: "Install the vendored Hyperframes skill bundle into a scene project so the host agent (Claude Code, Cursor, Codex, Aider) can read framework rules + house style directly. Writes a universal SKILL.md + references/ at the project root, plus per-host layouts (.claude/skills/hyperframes/ for Claude Code, .cursor/rules/hyperframes.mdc for Cursor) when those hosts are detected. Phase H1 of the agentic-native composer plan \u2014 once installed, the host agent itself can author scene HTML using the rules instead of relying on vibe's internal LLM call.",
488785
488896
  schema: sceneInstallSkillSchema,
488786
488897
  async execute(args, ctx) {
@@ -488827,6 +488938,8 @@ var sceneComposePromptsTool = defineTool({
488827
488938
  name: "scene_compose_prompts",
488828
488939
  category: "scene",
488829
488940
  cost: "free",
488941
+ title: "Get Scene Authoring Prompts",
488942
+ annotations: { readOnly: true, openWorld: false },
488830
488943
  description: "Emit the per-beat compose plan for the host agent to author scene HTML itself. Reads STORYBOARD.md + DESIGN.md and returns each beat's outputPath + userPrompt + cues + body, plus references to the project's SKILL.md (Hyperframes rules) and DESIGN.md (visual identity). The host agent writes each compositions/scene-<id>.html file directly \u2014 VibeFrame makes NO LLM call here. Hosts that cannot write files (e.g. Claude Desktop) submit each authored beat with scene_submit instead. Pairs with scene_install_skill (Phase H1). Phase H2 of the agentic-native composer plan; the internal-LLM batch path (build) remains as a fallback for non-agent contexts.",
488831
488944
  schema: sceneComposePromptsSchema,
488832
488945
  async execute(args, ctx) {
@@ -488869,6 +488982,8 @@ var sceneSubmitTool = defineTool({
488869
488982
  name: "scene_submit",
488870
488983
  category: "scene",
488871
488984
  cost: "free",
488985
+ title: "Submit Scene HTML",
488986
+ annotations: { readOnly: false, idempotent: true, openWorld: false },
488872
488987
  description: "Submit host-authored Hyperframes scene HTML for one beat. Validates with the same lint as the batch composer and writes compositions/scene-<id>.html on pass; on lint errors it returns the findings WITHOUT writing so you can fix and resubmit. This completes agent-mode compose for hosts that cannot write files (e.g. Claude Desktop): build (mode agent) \u2192 needs-author plan \u2192 author each beat from its composePrompts userPrompt \u2192 scene_submit per beat \u2192 build (stage sync) \u2192 render. No internal LLM call \u2014 the submitting agent is the composer.",
488873
488988
  schema: sceneSubmitSchema,
488874
488989
  async execute(args, ctx) {
@@ -488911,6 +489026,8 @@ var audioTranscribeTool = defineTool({
488911
489026
  name: "audio_transcribe",
488912
489027
  category: "audio",
488913
489028
  cost: "low",
489029
+ title: "Transcribe Audio",
489030
+ annotations: { readOnly: false, openWorld: true },
488914
489031
  description: "Transcribe audio using OpenAI Whisper. Outputs text, SRT, or VTT. Requires OPENAI_API_KEY.",
488915
489032
  schema: z3.object({
488916
489033
  audioPath: z3.string().describe("Input audio file path"),
@@ -488940,6 +489057,8 @@ var audioIsolateTool = defineTool({
488940
489057
  name: "audio_isolate",
488941
489058
  category: "audio",
488942
489059
  cost: "low",
489060
+ title: "Isolate Vocals from Audio",
489061
+ annotations: { readOnly: false, openWorld: true },
488943
489062
  description: "Isolate vocals from audio using ElevenLabs. Requires ELEVENLABS_API_KEY.",
488944
489063
  schema: z3.object({
488945
489064
  audioPath: z3.string().describe("Input audio file path"),
@@ -488959,6 +489078,8 @@ var audioVoiceCloneTool = defineTool({
488959
489078
  name: "audio_clone_voice",
488960
489079
  category: "audio",
488961
489080
  cost: "low",
489081
+ title: "Clone Voice from Samples",
489082
+ annotations: { readOnly: false, destructive: false, openWorld: true },
488962
489083
  description: "Clone a voice from audio samples using ElevenLabs. Requires ELEVENLABS_API_KEY.",
488963
489084
  schema: z3.object({
488964
489085
  samplePaths: z3.array(z3.string()).describe("Audio sample file paths (1-25 files)"),
@@ -488980,6 +489101,8 @@ var audioDubTool = defineTool({
488980
489101
  name: "audio_dub",
488981
489102
  category: "audio",
488982
489103
  cost: "high",
489104
+ title: "Dub Audio to Another Language",
489105
+ annotations: { readOnly: false, openWorld: true },
488983
489106
  description: "Dub audio/video to another language (transcribe + translate + TTS). Requires OPENAI_API_KEY, ANTHROPIC_API_KEY, ELEVENLABS_API_KEY.",
488984
489107
  schema: z3.object({
488985
489108
  mediaPath: z3.string().describe("Input media file (video or audio)"),
@@ -489010,6 +489133,8 @@ var audioDuckTool = defineTool({
489010
489133
  name: "audio_duck",
489011
489134
  category: "audio",
489012
489135
  cost: "free",
489136
+ title: "Duck Background Music",
489137
+ annotations: { readOnly: false, openWorld: false },
489013
489138
  description: "Auto-duck background music when voice is present using FFmpeg sidechain compression. Free, no API key needed.",
489014
489139
  schema: z3.object({
489015
489140
  musicPath: z3.string().describe("Background music file path"),
@@ -489307,6 +489432,8 @@ var editSilenceCutTool = defineTool({
489307
489432
  name: "edit_silence_cut",
489308
489433
  category: "edit",
489309
489434
  cost: "free",
489435
+ title: "Cut Silence from Video",
489436
+ annotations: { readOnly: false, openWorld: true },
489310
489437
  description: "Remove silent segments from a video using FFmpeg or Gemini AI detection. No API key needed for FFmpeg mode.",
489311
489438
  schema: z4.object({
489312
489439
  videoPath: z4.string().describe("Path to the input video file"),
@@ -489337,6 +489464,8 @@ var editCaptionTool = defineTool({
489337
489464
  name: "edit_caption",
489338
489465
  category: "edit",
489339
489466
  cost: "low",
489467
+ title: "Burn Captions into Video",
489468
+ annotations: { readOnly: false, openWorld: true },
489340
489469
  description: "Transcribe audio and burn styled captions into video. Requires OPENAI_API_KEY for Whisper transcription.",
489341
489470
  schema: z4.object({
489342
489471
  videoPath: z4.string().describe("Path to the input video file"),
@@ -489361,6 +489490,8 @@ var editFadeTool = defineTool({
489361
489490
  name: "edit_fade",
489362
489491
  category: "edit",
489363
489492
  cost: "free",
489493
+ title: "Apply Fade Effects",
489494
+ annotations: { readOnly: false, openWorld: false },
489364
489495
  description: "Apply fade in/out effects to video and/or audio. No API key needed.",
489365
489496
  schema: z4.object({
489366
489497
  videoPath: z4.string().describe("Path to the input video file"),
@@ -489384,6 +489515,8 @@ var editNoiseReduceTool = defineTool({
489384
489515
  name: "edit_noise_reduce",
489385
489516
  category: "edit",
489386
489517
  cost: "free",
489518
+ title: "Reduce Audio Noise",
489519
+ annotations: { readOnly: false, openWorld: false },
489387
489520
  description: "Reduce audio/video noise using FFmpeg filters. No API key needed.",
489388
489521
  schema: z4.object({
489389
489522
  inputPath: z4.string().describe("Path to the input media file"),
@@ -489405,6 +489538,8 @@ var editJumpCutTool = defineTool({
489405
489538
  name: "edit_jump_cut",
489406
489539
  category: "edit",
489407
489540
  cost: "low",
489541
+ title: "Remove Filler Words",
489542
+ annotations: { readOnly: false, openWorld: true },
489408
489543
  description: "Remove filler words (um, uh, like, etc.) from video using Whisper transcription. Requires OPENAI_API_KEY.",
489409
489544
  schema: z4.object({
489410
489545
  videoPath: z4.string().describe("Path to the input video file"),
@@ -489428,6 +489563,8 @@ var editTextOverlayTool = defineTool({
489428
489563
  name: "edit_text_overlay",
489429
489564
  category: "edit",
489430
489565
  cost: "free",
489566
+ title: "Overlay Static Text",
489567
+ annotations: { readOnly: false, openWorld: false },
489431
489568
  description: "Apply simple static text burn-in on video using FFmpeg drawtext. No API key needed. For designed or animated overlays, use edit_motion_overlay.",
489432
489569
  schema: z4.object({
489433
489570
  videoPath: z4.string().describe("Path to the input video file"),
@@ -489454,6 +489591,8 @@ var editMotionOverlayTool = defineTool({
489454
489591
  name: "edit_motion_overlay",
489455
489592
  category: "edit",
489456
489593
  cost: "low",
489594
+ title: "Apply Motion Graphics Overlay",
489595
+ annotations: { readOnly: false, openWorld: true },
489457
489596
  description: "Apply designed motion graphics overlays to an existing video. Generates Remotion overlays from a prompt, or overlays a user-provided .json/.lottie animation via the Hyperframes renderer.",
489458
489597
  schema: z4.object({
489459
489598
  videoPath: z4.string().describe("Path to the input video file"),
@@ -489490,6 +489629,8 @@ var editTranslateSrtTool = defineTool({
489490
489629
  name: "edit_translate_srt",
489491
489630
  category: "edit",
489492
489631
  cost: "low",
489632
+ title: "Translate SRT Subtitles",
489633
+ annotations: { readOnly: false, openWorld: true },
489493
489634
  description: "Translate SRT subtitle files using Claude or OpenAI. Requires ANTHROPIC_API_KEY or OPENAI_API_KEY.",
489494
489635
  schema: z4.object({
489495
489636
  srtPath: z4.string().describe("Path to the input SRT file"),
@@ -489512,6 +489653,8 @@ var editGradeTool = defineTool({
489512
489653
  name: "edit_grade",
489513
489654
  category: "edit",
489514
489655
  cost: "low",
489656
+ title: "Apply Color Grading",
489657
+ annotations: { readOnly: false, openWorld: true },
489515
489658
  description: "Apply AI-generated color grading using Claude + FFmpeg. Use preset for free built-in grades, or style for custom AI-generated grades (needs ANTHROPIC_API_KEY).",
489516
489659
  schema: z4.object({
489517
489660
  videoPath: z4.string().describe("Input video file path"),
@@ -489534,6 +489677,8 @@ var editSpeedRampTool = defineTool({
489534
489677
  name: "edit_speed_ramp",
489535
489678
  category: "edit",
489536
489679
  cost: "low",
489680
+ title: "Apply Content-Aware Speed Ramping",
489681
+ annotations: { readOnly: false, openWorld: true },
489537
489682
  description: "Apply content-aware speed ramping. Analyzes speech with Whisper, plans speed changes with Claude, applies with FFmpeg. Requires OPENAI_API_KEY + ANTHROPIC_API_KEY.",
489538
489683
  schema: z4.object({
489539
489684
  videoPath: z4.string().describe("Input video file path (must have audio)"),
@@ -489558,6 +489703,8 @@ var editReframeTool = defineTool({
489558
489703
  name: "edit_reframe",
489559
489704
  category: "edit",
489560
489705
  cost: "free",
489706
+ title: "Reframe Video Aspect Ratio",
489707
+ annotations: { readOnly: false, openWorld: false },
489561
489708
  description: "Auto-reframe video to a different aspect ratio using smart cropping. Free (FFmpeg only).",
489562
489709
  schema: z4.object({
489563
489710
  videoPath: z4.string().describe("Input video file path"),
@@ -489580,6 +489727,8 @@ var editInterpolateTool = defineTool({
489580
489727
  name: "edit_interpolate",
489581
489728
  category: "edit",
489582
489729
  cost: "free",
489730
+ title: "Create Slow Motion with Frame Interpolation",
489731
+ annotations: { readOnly: false, openWorld: false },
489583
489732
  description: "Create slow motion with AI frame interpolation using FFmpeg minterpolate. Free, no API key needed.",
489584
489733
  schema: z4.object({
489585
489734
  videoPath: z4.string().describe("Input video file path"),
@@ -489602,6 +489751,8 @@ var editUpscaleTool = defineTool({
489602
489751
  name: "edit_upscale",
489603
489752
  category: "edit",
489604
489753
  cost: "free",
489754
+ title: "Upscale Video Resolution",
489755
+ annotations: { readOnly: false, openWorld: false },
489605
489756
  description: "Upscale video resolution using FFmpeg (Lanczos scaling). Free, no API key needed.",
489606
489757
  schema: z4.object({
489607
489758
  videoPath: z4.string().describe("Input video file path"),
@@ -489623,6 +489774,8 @@ var editAnimatedCaptionTool = defineTool({
489623
489774
  name: "edit_animated_caption",
489624
489775
  category: "edit",
489625
489776
  cost: "low",
489777
+ title: "Add Animated Captions",
489778
+ annotations: { readOnly: false, openWorld: true },
489626
489779
  description: "Add animated word-by-word captions (TikTok/Reels style). Supports highlight, bounce, pop-in, neon, karaoke-sweep, typewriter styles. Requires OPENAI_API_KEY for Whisper.",
489627
489780
  schema: z4.object({
489628
489781
  videoPath: z4.string().describe("Path to the input video file"),
@@ -489655,6 +489808,8 @@ var editImageTool = defineTool({
489655
489808
  name: "edit_image",
489656
489809
  category: "edit",
489657
489810
  cost: "low",
489811
+ title: "Edit Image with AI",
489812
+ annotations: { readOnly: false, openWorld: true },
489658
489813
  description: "Edit image(s) using Gemini (Nano Banana). Provide image paths and an edit prompt. Requires GOOGLE_API_KEY.",
489659
489814
  schema: z4.object({
489660
489815
  imagePaths: z4.array(z4.string()).describe("Input image file path(s)"),
@@ -489678,6 +489833,8 @@ var editFillGapsTool = defineTool({
489678
489833
  name: "edit_fill_gaps",
489679
489834
  category: "edit",
489680
489835
  cost: "high",
489836
+ title: "Fill Timeline Gaps with AI Video",
489837
+ annotations: { readOnly: false, openWorld: true },
489681
489838
  description: "Fill timeline gaps with AI-generated video using Kling image-to-video. Detects empty regions in a project's timeline, extracts the last frame of the preceding clip, and generates a continuation video. Requires KLING_API_KEY and IMGBB_API_KEY (image hosting for Kling).",
489682
489839
  schema: z4.object({
489683
489840
  projectPath: z4.string().describe("Path to timeline.json, a timeline directory, or a legacy *.vibe.json file"),
@@ -491161,6 +491318,8 @@ var inspectProjectTool = defineTool({
491161
491318
  name: "inspect_project",
491162
491319
  category: "analyze",
491163
491320
  cost: "free",
491321
+ title: "Inspect Project",
491322
+ annotations: { readOnly: false, openWorld: false },
491164
491323
  description: "Local project inspection: checks STORYBOARD.md, DESIGN.md, config, build-report, scene lint, composition files, and referenced assets. Writes review-report.json by default.",
491165
491324
  schema: z5.object({
491166
491325
  projectDir: z5.string().optional().describe(PROJECT_DIR_DESCRIPTION2),
@@ -491195,6 +491354,8 @@ var inspectRenderTool = defineTool({
491195
491354
  name: "inspect_render",
491196
491355
  category: "analyze",
491197
491356
  cost: "low",
491357
+ title: "Inspect Render",
491358
+ annotations: { readOnly: false, openWorld: false },
491198
491359
  description: "Render inspection: runs cheap local video checks by default, optionally adds Gemini AI review with ai: true, and writes review-report.json by default.",
491199
491360
  schema: z5.object({
491200
491361
  projectDir: z5.string().optional().describe(PROJECT_DIR_DESCRIPTION2),
@@ -491259,6 +491420,8 @@ var analyzeMediaTool = defineTool({
491259
491420
  name: "inspect_media",
491260
491421
  category: "analyze",
491261
491422
  cost: "low",
491423
+ title: "Inspect Media with AI",
491424
+ annotations: { readOnly: true, openWorld: true },
491262
491425
  description: "Analyze media (image, video, or YouTube URL) using Gemini AI. Requires GOOGLE_API_KEY.",
491263
491426
  schema: z5.object({
491264
491427
  source: z5.string().describe("Path to image/video or YouTube URL"),
@@ -491287,6 +491450,8 @@ var analyzeVideoTool = defineTool({
491287
491450
  name: "inspect_video",
491288
491451
  category: "analyze",
491289
491452
  cost: "low",
491453
+ title: "Inspect Video with AI",
491454
+ annotations: { readOnly: true, openWorld: true },
491290
491455
  description: "Analyze video content using Gemini AI with temporal understanding. Requires GOOGLE_API_KEY.",
491291
491456
  schema: z5.object({
491292
491457
  source: z5.string().describe("Path to video file"),
@@ -491315,6 +491480,8 @@ var analyzeReviewTool = defineTool({
491315
491480
  name: "inspect_review",
491316
491481
  category: "analyze",
491317
491482
  cost: "low",
491483
+ title: "Review Video with AI",
491484
+ annotations: { readOnly: false, openWorld: true },
491318
491485
  description: "AI video review: analyzes quality, suggests fixes, and optionally auto-applies them. Requires GOOGLE_API_KEY.",
491319
491486
  schema: z5.object({
491320
491487
  videoPath: z5.string().describe("Path to the video file to review"),
@@ -491343,6 +491510,8 @@ var analyzeSuggestTool = defineTool({
491343
491510
  name: "inspect_suggest",
491344
491511
  category: "analyze",
491345
491512
  cost: "low",
491513
+ title: "Suggest Edits with AI",
491514
+ annotations: { readOnly: false, openWorld: true },
491346
491515
  description: "Get natural-language edit suggestions for a project from Gemini. Returns suggestions array with type/confidence/clipIds. With `apply: true`, applies the first suggestion in place. Requires GOOGLE_API_KEY.",
491347
491516
  schema: z5.object({
491348
491517
  projectPath: z5.string().describe("Path to timeline.json, a timeline directory, or a legacy *.vibe.json file"),
@@ -491391,6 +491560,8 @@ var generateMotionTool = defineTool({
491391
491560
  name: "generate_motion",
491392
491561
  category: "generate",
491393
491562
  cost: "low",
491563
+ title: "Generate Motion Graphics",
491564
+ annotations: { readOnly: false, openWorld: true },
491394
491565
  description: "Generate standalone motion graphics using Claude or Gemini + Remotion. For overlays on an existing video, prefer edit_motion_overlay. Requires ANTHROPIC_API_KEY (Claude) or GOOGLE_API_KEY (Gemini).",
491395
491566
  schema: z6.object({
491396
491567
  description: z6.string().describe("Description of the motion graphic to generate"),
@@ -491430,6 +491601,8 @@ var generateSpeechTool = defineTool({
491430
491601
  name: "generate_speech",
491431
491602
  category: "generate",
491432
491603
  cost: "low",
491604
+ title: "Generate Speech Audio",
491605
+ annotations: { readOnly: false, openWorld: true },
491433
491606
  description: "Generate speech from text using ElevenLabs TTS. Requires ELEVENLABS_API_KEY.",
491434
491607
  schema: z6.object({
491435
491608
  text: z6.string().describe("Text to convert to speech"),
@@ -491450,6 +491623,8 @@ var generateNarrationTool = defineTool({
491450
491623
  name: "generate_narration",
491451
491624
  category: "generate",
491452
491625
  cost: "low",
491626
+ title: "Generate Narration Audio",
491627
+ annotations: { readOnly: false, openWorld: true },
491453
491628
  description: "Generate narration from text using ElevenLabs TTS. Product-facing alias for generate_speech. Requires ELEVENLABS_API_KEY.",
491454
491629
  schema: z6.object({
491455
491630
  text: z6.string().describe("Narration text to convert to speech"),
@@ -491474,6 +491649,8 @@ var generateSoundEffectTool = defineTool({
491474
491649
  name: "generate_sound_effect",
491475
491650
  category: "generate",
491476
491651
  cost: "low",
491652
+ title: "Generate Sound Effect",
491653
+ annotations: { readOnly: false, openWorld: true },
491477
491654
  description: "Generate sound effects using ElevenLabs. Requires ELEVENLABS_API_KEY.",
491478
491655
  schema: z6.object({
491479
491656
  prompt: z6.string().describe("Description of the sound effect"),
@@ -491495,6 +491672,8 @@ var generateMusicTool = defineTool({
491495
491672
  name: "generate_music",
491496
491673
  category: "generate",
491497
491674
  cost: "low",
491675
+ title: "Generate Music",
491676
+ annotations: { readOnly: false, openWorld: true },
491498
491677
  description: "Generate background music from text prompt. ElevenLabs (default, up to 10min) or Replicate MusicGen (max 30s). Requires ELEVENLABS_API_KEY or REPLICATE_API_TOKEN.",
491499
491678
  schema: z6.object({
491500
491679
  prompt: z6.string().describe("Description of the music to generate"),
@@ -491540,6 +491719,8 @@ var generateMusicStatusTool = defineTool({
491540
491719
  name: "generate_music_status",
491541
491720
  category: "generate",
491542
491721
  cost: "free",
491722
+ title: "Check Music Generation Status",
491723
+ annotations: { readOnly: true, openWorld: true },
491543
491724
  description: "Check Replicate music generation task status. `generate_music` returns a task id; this tool polls it until the audio URL is ready. Requires REPLICATE_API_TOKEN.",
491544
491725
  schema: z6.object({
491545
491726
  taskId: z6.string().describe("Task ID returned from generate_music")
@@ -491563,6 +491744,8 @@ var generateImageTool = defineTool({
491563
491744
  name: "generate_image",
491564
491745
  category: "generate",
491565
491746
  cost: "low",
491747
+ title: "Generate Image",
491748
+ annotations: { readOnly: false, openWorld: true },
491566
491749
  description: "Generate an image using AI. Supports Gemini (free), OpenAI GPT Image, or Grok Imagine. Requires GOOGLE_API_KEY (Gemini), OPENAI_API_KEY (OpenAI), or XAI_API_KEY (Grok).",
491567
491750
  schema: z6.object({
491568
491751
  prompt: z6.string().describe("Image description prompt"),
@@ -491596,6 +491779,8 @@ var generateStoryboardTool = defineTool({
491596
491779
  name: "generate_storyboard",
491597
491780
  category: "generate",
491598
491781
  cost: "low",
491782
+ title: "Generate Storyboard",
491783
+ annotations: { readOnly: false, openWorld: true },
491599
491784
  description: "Generate a video storyboard from text content using Claude. Returns scene segments with descriptions, visuals, and narration. Requires ANTHROPIC_API_KEY.",
491600
491785
  schema: z6.object({
491601
491786
  content: z6.string().describe("Text content to analyze (script, article, etc.)"),
@@ -491619,6 +491804,8 @@ var generateBackgroundTool = defineTool({
491619
491804
  name: "generate_background",
491620
491805
  category: "generate",
491621
491806
  cost: "low",
491807
+ title: "Generate Background Image",
491808
+ annotations: { readOnly: false, openWorld: true },
491622
491809
  description: "Generate a cinematic backdrop image (OpenAI gpt-image-2 / DALL\xB7E variant tuned for video backgrounds). Returns the image URL and, when `output` is provided, downloads the PNG to disk. Requires OPENAI_API_KEY.",
491623
491810
  schema: z6.object({
491624
491811
  description: z6.string().describe("Background description / image prompt."),
@@ -491643,6 +491830,8 @@ var generateThumbnailTool = defineTool({
491643
491830
  name: "generate_thumbnail",
491644
491831
  category: "generate",
491645
491832
  cost: "low",
491833
+ title: "Generate Thumbnail",
491834
+ annotations: { readOnly: false, openWorld: true },
491646
491835
  description: "Extract the best thumbnail frame from a video using Gemini AI analysis. Requires GOOGLE_API_KEY.",
491647
491836
  schema: z6.object({
491648
491837
  videoPath: z6.string().describe("Path to the video file"),
@@ -491664,6 +491853,8 @@ var generateVideoTool = defineTool({
491664
491853
  name: "generate_video",
491665
491854
  category: "generate",
491666
491855
  cost: "high",
491856
+ title: "Generate Video",
491857
+ annotations: { readOnly: false, openWorld: true },
491667
491858
  description: "Generate video using AI. Supports Seedance 2.0 via fal.ai, Grok, Kling, Runway, and Veo. Requires FAL_API_KEY, XAI_API_KEY, KLING_API_KEY, RUNWAY_API_SECRET, or GOOGLE_API_KEY.",
491668
491859
  schema: z6.object({
491669
491860
  prompt: z6.string().describe("Text prompt describing the video"),
@@ -491725,6 +491916,8 @@ var generateVideoStatusTool = defineTool({
491725
491916
  name: "generate_video_status",
491726
491917
  category: "generate",
491727
491918
  cost: "free",
491919
+ title: "Check Video Generation Status",
491920
+ annotations: { readOnly: false, openWorld: true },
491728
491921
  description: "Check video generation status for Grok, Runway, Kling, or Veo tasks.",
491729
491922
  schema: z6.object({
491730
491923
  taskId: z6.string().describe("Task ID from video generation"),
@@ -491755,6 +491948,8 @@ var generateVideoCancelTool = defineTool({
491755
491948
  name: "generate_video_cancel",
491756
491949
  category: "generate",
491757
491950
  cost: "free",
491951
+ title: "Cancel Video Generation",
491952
+ annotations: { readOnly: false, openWorld: true },
491758
491953
  description: "Cancel a Runway video generation task.",
491759
491954
  schema: z6.object({
491760
491955
  taskId: z6.string().describe("Task ID to cancel")
@@ -491773,6 +491968,8 @@ var generateVideoExtendTool = defineTool({
491773
491968
  name: "generate_video_extend",
491774
491969
  category: "generate",
491775
491970
  cost: "high",
491971
+ title: "Extend Generated Video",
491972
+ annotations: { readOnly: false, openWorld: true },
491776
491973
  description: "Extend video duration using Kling or Veo. Requires the video/operation ID from a previous generation.",
491777
491974
  schema: z6.object({
491778
491975
  videoId: z6.string().describe("Video ID (Kling) or operation name (Veo)"),
@@ -492175,6 +492372,8 @@ var storyboardListTool = defineTool({
492175
492372
  name: "storyboard_list",
492176
492373
  category: "storyboard",
492177
492374
  cost: "free",
492375
+ title: "List Storyboard Beats",
492376
+ annotations: { readOnly: true, openWorld: false },
492178
492377
  description: "List beats, ids, durations, and cue blocks from a project's STORYBOARD.md.",
492179
492378
  schema: projectDirSchema,
492180
492379
  async execute(args, ctx) {
@@ -492201,6 +492400,8 @@ var storyboardValidateTool = defineTool({
492201
492400
  name: "storyboard_validate",
492202
492401
  category: "storyboard",
492203
492402
  cost: "free",
492403
+ title: "Validate Storyboard",
492404
+ annotations: { readOnly: true, openWorld: false },
492204
492405
  description: "Validate STORYBOARD.md beat ids and cue blocks.",
492205
492406
  schema: projectDirSchema,
492206
492407
  async execute(args, ctx) {
@@ -492231,6 +492432,8 @@ var storyboardGetTool = defineTool({
492231
492432
  name: "storyboard_get",
492232
492433
  category: "storyboard",
492233
492434
  cost: "free",
492435
+ title: "Get Storyboard Beat",
492436
+ annotations: { readOnly: true, openWorld: false },
492234
492437
  description: "Return one STORYBOARD.md beat as structured data.",
492235
492438
  schema: z7.object({
492236
492439
  projectDir: z7.string().optional().describe(PROJECT_DIR_DESCRIPTION3),
@@ -492253,6 +492456,8 @@ var storyboardSetTool = defineTool({
492253
492456
  name: "storyboard_set",
492254
492457
  category: "storyboard",
492255
492458
  cost: "free",
492459
+ title: "Set Storyboard Cue",
492460
+ annotations: { readOnly: false, idempotent: true, openWorld: false },
492256
492461
  description: "Set or unset one cue on one beat in STORYBOARD.md.",
492257
492462
  schema: z7.object({
492258
492463
  projectDir: z7.string().optional().describe(PROJECT_DIR_DESCRIPTION3),
@@ -492289,6 +492494,8 @@ var storyboardMoveTool = defineTool({
492289
492494
  name: "storyboard_move",
492290
492495
  category: "storyboard",
492291
492496
  cost: "free",
492497
+ title: "Reorder Storyboard Beat",
492498
+ annotations: { readOnly: false, openWorld: false },
492292
492499
  description: "Move one beat after another beat in STORYBOARD.md.",
492293
492500
  schema: z7.object({
492294
492501
  projectDir: z7.string().optional().describe(PROJECT_DIR_DESCRIPTION3),
@@ -492319,6 +492526,8 @@ var storyboardReviseTool = defineTool({
492319
492526
  name: "storyboard_revise",
492320
492527
  category: "storyboard",
492321
492528
  cost: "low",
492529
+ title: "Revise Storyboard with AI",
492530
+ annotations: { readOnly: false, openWorld: true },
492322
492531
  description: "Revise an existing STORYBOARD.md from a natural-language request. Reads project context, validates the revised storyboard, and writes unless dryRun is true.",
492323
492532
  schema: z7.object({
492324
492533
  projectDir: z7.string().optional().describe(PROJECT_DIR_DESCRIPTION3),
@@ -492350,6 +492559,8 @@ var planTool = defineTool({
492350
492559
  name: "plan",
492351
492560
  category: "storyboard",
492352
492561
  cost: "free",
492562
+ title: "Plan Build Cost and Stages",
492563
+ annotations: { readOnly: true, openWorld: false },
492353
492564
  description: "Read STORYBOARD.md and return the build plan, missing artifacts, provider needs, and estimated cost.",
492354
492565
  schema: z7.object({
492355
492566
  projectDir: z7.string().optional().describe(PROJECT_DIR_DESCRIPTION3),
@@ -494048,6 +494259,8 @@ var pipelineHighlightsTool = defineTool({
494048
494259
  name: "remix_highlights",
494049
494260
  category: "pipeline",
494050
494261
  cost: "low",
494262
+ title: "Extract Video Highlights",
494263
+ annotations: { readOnly: false, openWorld: true },
494051
494264
  description: "Extract highlight clips from a longer video using AI analysis. Requires OPENAI_API_KEY+ANTHROPIC_API_KEY or GOOGLE_API_KEY (with --use-gemini).",
494052
494265
  schema: z8.object({
494053
494266
  media: z8.string().describe("Path to the input video file"),
@@ -494081,6 +494294,8 @@ var pipelineAutoShortsTool = defineTool({
494081
494294
  name: "remix_auto_shorts",
494082
494295
  category: "pipeline",
494083
494296
  cost: "medium",
494297
+ title: "Generate Auto Shorts",
494298
+ annotations: { readOnly: false, openWorld: true },
494084
494299
  description: "Automatically generate short-form content (Reels/TikTok/Shorts) from a longer video. Same API key requirements as remix_highlights.",
494085
494300
  schema: z8.object({
494086
494301
  video: z8.string().describe("Path to the input video file"),
@@ -494118,6 +494333,8 @@ var pipelineRunTool = defineTool({
494118
494333
  name: "run",
494119
494334
  category: "pipeline",
494120
494335
  cost: "very-high",
494336
+ title: "Run YAML Pipeline",
494337
+ annotations: { readOnly: false, openWorld: true },
494121
494338
  surfaces: ["mcp"],
494122
494339
  description: "Execute a declarative YAML pipeline (Video as Code). Accepts either a file path or inline YAML. Supports dry-run, resume-from-checkpoint, and budget limits. Cost depends on the steps \u2014 use dryRun: true first to preview.",
494123
494340
  schema: z8.object({
@@ -494197,6 +494414,8 @@ var pipelineRegenerateSceneTool = defineTool({
494197
494414
  name: "remix_regenerate_scene",
494198
494415
  category: "pipeline",
494199
494416
  cost: "high",
494417
+ title: "Regenerate Storyboard Scenes",
494418
+ annotations: { readOnly: false, openWorld: true },
494200
494419
  description: "Regenerate specific scenes against an existing storyboard.{yaml,json} on disk. Can regenerate video, image, or narration independently.",
494201
494420
  schema: z8.object({
494202
494421
  projectDir: z8.string().describe("Path to the project output directory containing storyboard.json"),
@@ -494234,6 +494453,8 @@ var detectScenesTool = defineTool({
494234
494453
  name: "detect_scenes",
494235
494454
  category: "detect",
494236
494455
  cost: "free",
494456
+ title: "Detect Scene Cuts",
494457
+ annotations: { readOnly: false, idempotent: true, openWorld: false },
494237
494458
  description: "Detect scene changes in video using FFmpeg. No API key needed.",
494238
494459
  schema: z9.object({
494239
494460
  videoPath: z9.string().describe("Path to the input video file"),
@@ -494258,6 +494479,8 @@ var detectSilenceTool = defineTool({
494258
494479
  name: "detect_silence",
494259
494480
  category: "detect",
494260
494481
  cost: "free",
494482
+ title: "Detect Silence Periods",
494483
+ annotations: { readOnly: false, idempotent: true, openWorld: false },
494261
494484
  description: "Detect silence periods in audio/video using FFmpeg. No API key needed.",
494262
494485
  schema: z9.object({
494263
494486
  mediaPath: z9.string().describe("Path to the audio/video file"),
@@ -494279,6 +494502,8 @@ var detectBeatsTool = defineTool({
494279
494502
  name: "detect_beats",
494280
494503
  category: "detect",
494281
494504
  cost: "free",
494505
+ title: "Detect Audio Beats",
494506
+ annotations: { readOnly: false, idempotent: true, openWorld: false },
494282
494507
  description: "Detect beats in audio for music sync using FFmpeg loudness analysis. No API key needed.",
494283
494508
  schema: z9.object({
494284
494509
  audioPath: z9.string().describe("Path to the audio file"),
@@ -494341,6 +494566,8 @@ var timelineCreateTool = defineTool({
494341
494566
  name: "timeline_create",
494342
494567
  category: "timeline",
494343
494568
  cost: "free",
494569
+ title: "Create Timeline",
494570
+ annotations: { readOnly: false, openWorld: false },
494344
494571
  description: "Create a low-level timeline JSON file for FFmpeg-style editing",
494345
494572
  schema: z10.object({
494346
494573
  name: z10.string().describe("Timeline name or directory path"),
@@ -494371,6 +494598,8 @@ var timelineInfoTool = defineTool({
494371
494598
  name: "timeline_info",
494372
494599
  category: "timeline",
494373
494600
  cost: "free",
494601
+ title: "Get Timeline Info",
494602
+ annotations: { readOnly: true, openWorld: false },
494374
494603
  description: "Get information about a timeline JSON file. Legacy *.vibe.json files are supported.",
494375
494604
  schema: z10.object({
494376
494605
  projectPath: z10.string().describe("Path to timeline.json, a timeline directory, or a legacy *.vibe.json file")
@@ -494398,6 +494627,8 @@ var timelineAddSourceTool = defineTool({
494398
494627
  name: "timeline_add_source",
494399
494628
  category: "timeline",
494400
494629
  cost: "free",
494630
+ title: "Add Source to Timeline",
494631
+ annotations: { readOnly: false, openWorld: false },
494401
494632
  description: "Add a media source (video, audio, image) to the timeline",
494402
494633
  schema: z10.object({
494403
494634
  projectPath: z10.string().describe("Path to timeline.json, a timeline directory, or a legacy *.vibe.json file"),
@@ -494423,6 +494654,8 @@ var timelineAddClipTool = defineTool({
494423
494654
  name: "timeline_add_clip",
494424
494655
  category: "timeline",
494425
494656
  cost: "free",
494657
+ title: "Add Clip to Timeline",
494658
+ annotations: { readOnly: false, openWorld: false },
494426
494659
  description: "Add a clip to the timeline from an existing source",
494427
494660
  schema: z10.object({
494428
494661
  projectPath: z10.string().describe("Path to timeline.json, a timeline directory, or a legacy *.vibe.json file"),
@@ -494454,6 +494687,8 @@ var timelineSplitClipTool = defineTool({
494454
494687
  name: "timeline_split_clip",
494455
494688
  category: "timeline",
494456
494689
  cost: "free",
494690
+ title: "Split Clip",
494691
+ annotations: { readOnly: false, openWorld: false },
494457
494692
  description: "Split a clip at a specific time",
494458
494693
  schema: z10.object({
494459
494694
  projectPath: z10.string().describe("Path to timeline.json, a timeline directory, or a legacy *.vibe.json file"),
@@ -494472,6 +494707,8 @@ var timelineTrimClipTool = defineTool({
494472
494707
  name: "timeline_trim_clip",
494473
494708
  category: "timeline",
494474
494709
  cost: "free",
494710
+ title: "Trim Clip",
494711
+ annotations: { readOnly: false, openWorld: false },
494475
494712
  description: "Trim a clip by adjusting its start or end",
494476
494713
  schema: z10.object({
494477
494714
  projectPath: z10.string().describe("Path to timeline.json, a timeline directory, or a legacy *.vibe.json file"),
@@ -494491,6 +494728,8 @@ var timelineMoveClipTool = defineTool({
494491
494728
  name: "timeline_move_clip",
494492
494729
  category: "timeline",
494493
494730
  cost: "free",
494731
+ title: "Move Clip",
494732
+ annotations: { readOnly: false, openWorld: false },
494494
494733
  description: "Move a clip to a new position or track",
494495
494734
  schema: z10.object({
494496
494735
  projectPath: z10.string().describe("Path to timeline.json, a timeline directory, or a legacy *.vibe.json file"),
@@ -494513,6 +494752,8 @@ var timelineDeleteClipTool = defineTool({
494513
494752
  name: "timeline_delete_clip",
494514
494753
  category: "timeline",
494515
494754
  cost: "free",
494755
+ title: "Delete Clip",
494756
+ annotations: { readOnly: false, openWorld: false },
494516
494757
  description: "Delete a clip from the timeline",
494517
494758
  schema: z10.object({
494518
494759
  projectPath: z10.string().describe("Path to timeline.json, a timeline directory, or a legacy *.vibe.json file"),
@@ -494529,6 +494770,8 @@ var timelineDuplicateClipTool = defineTool({
494529
494770
  name: "timeline_duplicate_clip",
494530
494771
  category: "timeline",
494531
494772
  cost: "free",
494773
+ title: "Duplicate Clip",
494774
+ annotations: { readOnly: false, openWorld: false },
494532
494775
  description: "Duplicate a clip on the timeline (optionally at a new start time)",
494533
494776
  schema: z10.object({
494534
494777
  projectPath: z10.string().describe("Path to timeline.json, a timeline directory, or a legacy *.vibe.json file"),
@@ -494547,6 +494790,8 @@ var timelineAddEffectTool = defineTool({
494547
494790
  name: "timeline_add_effect",
494548
494791
  category: "timeline",
494549
494792
  cost: "free",
494793
+ title: "Add Effect to Clip",
494794
+ annotations: { readOnly: false, openWorld: false },
494550
494795
  description: "Add an effect to a clip",
494551
494796
  schema: z10.object({
494552
494797
  projectPath: z10.string().describe("Path to timeline.json, a timeline directory, or a legacy *.vibe.json file"),
@@ -494573,6 +494818,8 @@ var timelineAddTrackTool = defineTool({
494573
494818
  name: "timeline_add_track",
494574
494819
  category: "timeline",
494575
494820
  cost: "free",
494821
+ title: "Add Track to Timeline",
494822
+ annotations: { readOnly: false, openWorld: false },
494576
494823
  description: "Add a new track to the timeline",
494577
494824
  schema: z10.object({
494578
494825
  projectPath: z10.string().describe("Path to timeline.json, a timeline directory, or a legacy *.vibe.json file"),
@@ -494599,6 +494846,8 @@ var timelineListTool = defineTool({
494599
494846
  name: "timeline_list",
494600
494847
  category: "timeline",
494601
494848
  cost: "free",
494849
+ title: "List Timeline Contents",
494850
+ annotations: { readOnly: true, openWorld: false },
494602
494851
  description: "List all sources, tracks, and clips in a project",
494603
494852
  schema: z10.object({
494604
494853
  projectPath: z10.string().describe("Path to timeline.json, a timeline directory, or a legacy *.vibe.json file")
@@ -494641,6 +494890,8 @@ var projectCreateTool = defineTool({
494641
494890
  name: "project_create",
494642
494891
  category: "project",
494643
494892
  cost: "free",
494893
+ title: "Create Project",
494894
+ annotations: { readOnly: false, openWorld: false },
494644
494895
  description: "Deprecated alias for creating low-level timeline state. Prefer timeline_create.",
494645
494896
  schema: z11.object({
494646
494897
  name: z11.string().describe("Project name"),
@@ -494665,6 +494916,8 @@ var projectInfoTool = defineTool({
494665
494916
  name: "project_info",
494666
494917
  category: "project",
494667
494918
  cost: "free",
494919
+ title: "Get Project Info",
494920
+ annotations: { readOnly: true, openWorld: false },
494668
494921
  description: "Deprecated alias for timeline_info. Legacy *.vibe.json files remain supported.",
494669
494922
  schema: z11.object({
494670
494923
  projectPath: z11.string().describe("Path to timeline.json, a timeline directory, or a legacy *.vibe.json file")
@@ -495552,6 +495805,8 @@ var exportVideoTool = defineTool({
495552
495805
  name: "export_video",
495553
495806
  category: "export",
495554
495807
  cost: "free",
495808
+ title: "Export Timeline to Video",
495809
+ annotations: { readOnly: false, openWorld: false },
495555
495810
  description: "Export a VibeFrame timeline to a video file (MP4, WebM, or MOV). Requires FFmpeg.",
495556
495811
  schema: z12.object({
495557
495812
  projectPath: z12.string().describe("Path to timeline.json, a timeline directory, or a legacy *.vibe.json file"),
@@ -495643,6 +495898,8 @@ var fsListTool = defineTool({
495643
495898
  name: "fs_list",
495644
495899
  category: "agent-only",
495645
495900
  cost: "free",
495901
+ title: "List Files",
495902
+ annotations: { readOnly: true, openWorld: false },
495646
495903
  surfaces: ["agent"],
495647
495904
  description: "List files and directories in a path",
495648
495905
  schema: z13.object({
@@ -495676,6 +495933,8 @@ var fsReadTool = defineTool({
495676
495933
  name: "fs_read",
495677
495934
  category: "agent-only",
495678
495935
  cost: "free",
495936
+ title: "Read File",
495937
+ annotations: { readOnly: true, openWorld: false },
495679
495938
  surfaces: ["agent"],
495680
495939
  description: "Read contents of a text file",
495681
495940
  schema: z13.object({
@@ -495698,6 +495957,8 @@ var fsWriteTool = defineTool({
495698
495957
  name: "fs_write",
495699
495958
  category: "agent-only",
495700
495959
  cost: "free",
495960
+ title: "Write File",
495961
+ annotations: { readOnly: false, openWorld: false },
495701
495962
  surfaces: ["agent"],
495702
495963
  description: "Write content to a file",
495703
495964
  schema: z13.object({
@@ -495718,6 +495979,8 @@ var fsExistsTool = defineTool({
495718
495979
  name: "fs_exists",
495719
495980
  category: "agent-only",
495720
495981
  cost: "free",
495982
+ title: "Check Path Exists",
495983
+ annotations: { readOnly: true, openWorld: false },
495721
495984
  surfaces: ["agent"],
495722
495985
  description: "Check if a file or directory exists",
495723
495986
  schema: z13.object({
@@ -495739,6 +496002,8 @@ var batchImportTool = defineTool({
495739
496002
  name: "batch_import",
495740
496003
  category: "agent-only",
495741
496004
  cost: "free",
496005
+ title: "Batch Import Media",
496006
+ annotations: { readOnly: false, openWorld: false },
495742
496007
  surfaces: ["agent"],
495743
496008
  description: "Import multiple media files from a directory into a project. Scans directory for video, audio, and image files.",
495744
496009
  schema: z13.object({
@@ -495808,6 +496073,8 @@ var batchConcatTool = defineTool({
495808
496073
  name: "batch_concat",
495809
496074
  category: "agent-only",
495810
496075
  cost: "free",
496076
+ title: "Batch Concatenate Sources",
496077
+ annotations: { readOnly: false, openWorld: false },
495811
496078
  surfaces: ["agent"],
495812
496079
  description: "Concatenate multiple sources into sequential clips on the timeline",
495813
496080
  schema: z13.object({
@@ -495877,6 +496144,8 @@ var batchApplyEffectTool = defineTool({
495877
496144
  name: "batch_apply_effect",
495878
496145
  category: "agent-only",
495879
496146
  cost: "free",
496147
+ title: "Batch Apply Effect",
496148
+ annotations: { readOnly: false, openWorld: false },
495880
496149
  surfaces: ["agent"],
495881
496150
  description: "Apply an effect to multiple clips at once",
495882
496151
  schema: z13.object({
@@ -495933,6 +496202,8 @@ var timelineClearTool = defineTool({
495933
496202
  name: "timeline_clear",
495934
496203
  category: "agent-only",
495935
496204
  cost: "free",
496205
+ title: "Clear Timeline",
496206
+ annotations: { readOnly: false, openWorld: false },
495936
496207
  surfaces: ["agent"],
495937
496208
  description: "Clear timeline contents (remove clips, tracks, or sources)",
495938
496209
  schema: z13.object({
@@ -496007,6 +496278,8 @@ var projectSetTool = defineTool({
496007
496278
  name: "project_set",
496008
496279
  category: "agent-only",
496009
496280
  cost: "free",
496281
+ title: "Update Project Settings",
496282
+ annotations: { readOnly: false, idempotent: true, openWorld: false },
496010
496283
  surfaces: ["agent"],
496011
496284
  description: "Update timeline settings (name, aspect ratio, frame rate)",
496012
496285
  schema: z13.object({
@@ -496052,6 +496325,8 @@ var projectOpenTool = defineTool({
496052
496325
  name: "project_open",
496053
496326
  category: "agent-only",
496054
496327
  cost: "free",
496328
+ title: "Open Project",
496329
+ annotations: { readOnly: false, idempotent: true, openWorld: false },
496055
496330
  surfaces: ["agent"],
496056
496331
  description: "Open an existing project and set it as the current context",
496057
496332
  schema: z13.object({
@@ -496090,6 +496365,8 @@ var projectSaveTool = defineTool({
496090
496365
  name: "project_save",
496091
496366
  category: "agent-only",
496092
496367
  cost: "free",
496368
+ title: "Save Project",
496369
+ annotations: { readOnly: false, openWorld: false },
496093
496370
  surfaces: ["agent"],
496094
496371
  description: "Save the current project (uses ctx.agent.projectPath if no path given)",
496095
496372
  schema: z13.object({
@@ -496124,6 +496401,8 @@ var exportAudioTool = defineTool({
496124
496401
  name: "export_audio",
496125
496402
  category: "agent-only",
496126
496403
  cost: "free",
496404
+ title: "Export Audio",
496405
+ annotations: { readOnly: false, openWorld: false },
496127
496406
  surfaces: ["agent"],
496128
496407
  description: "Export audio track from a project. Not implemented \u2014 use export_video then strip audio with FFmpeg.",
496129
496408
  schema: z13.object({
@@ -496142,6 +496421,8 @@ var exportSubtitlesTool = defineTool({
496142
496421
  name: "export_subtitles",
496143
496422
  category: "agent-only",
496144
496423
  cost: "free",
496424
+ title: "Export Subtitles",
496425
+ annotations: { readOnly: false, openWorld: false },
496145
496426
  surfaces: ["agent"],
496146
496427
  description: "Export subtitles from transcription. Not implemented \u2014 use audio_transcribe to generate subtitles from audio.",
496147
496428
  schema: z13.object({
@@ -496160,6 +496441,8 @@ var mediaInfoTool = defineTool({
496160
496441
  name: "media_info",
496161
496442
  category: "agent-only",
496162
496443
  cost: "free",
496444
+ title: "Get Media Info",
496445
+ annotations: { readOnly: true, openWorld: false },
496163
496446
  surfaces: ["agent"],
496164
496447
  description: "Get information about a media file (duration, resolution, codec, etc.)",
496165
496448
  schema: z13.object({
@@ -496244,6 +496527,8 @@ var mediaCompressTool = defineTool({
496244
496527
  name: "media_compress",
496245
496528
  category: "agent-only",
496246
496529
  cost: "free",
496530
+ title: "Compress Media",
496531
+ annotations: { readOnly: false, openWorld: false },
496247
496532
  surfaces: ["agent"],
496248
496533
  description: "Compress a video or audio file using FFmpeg",
496249
496534
  schema: z13.object({
@@ -496305,6 +496590,8 @@ var mediaConvertTool = defineTool({
496305
496590
  name: "media_convert",
496306
496591
  category: "agent-only",
496307
496592
  cost: "free",
496593
+ title: "Convert Media",
496594
+ annotations: { readOnly: false, openWorld: false },
496308
496595
  surfaces: ["agent"],
496309
496596
  description: "Convert media file to a different format using FFmpeg",
496310
496597
  schema: z13.object({
@@ -496352,6 +496639,8 @@ var mediaConcatTool = defineTool({
496352
496639
  name: "media_concat",
496353
496640
  category: "agent-only",
496354
496641
  cost: "free",
496642
+ title: "Concatenate Media Files",
496643
+ annotations: { readOnly: false, openWorld: false },
496355
496644
  surfaces: ["agent"],
496356
496645
  description: "Concatenate multiple media files into one using FFmpeg",
496357
496646
  schema: z13.object({
@@ -496891,6 +497180,8 @@ var guideTool = defineTool({
496891
497180
  name: "guide",
496892
497181
  category: "agent",
496893
497182
  cost: "free",
497183
+ title: "Load Workflow Guide",
497184
+ annotations: { readOnly: true, openWorld: false },
496894
497185
  description: "Load the step-by-step guide for a vibe workflow (motion overlays, BUILD scene authoring, YAML pipeline authoring, architecture choices). Universal CLI-equivalent of `vibe guide <topic>` and Claude Code's /vibe-* slash commands. Without a topic, returns the guide catalog for discovery.",
496895
497186
  schema: guideSchema,
496896
497187
  async execute(args) {
@@ -496927,6 +497218,8 @@ var statusJobTool = defineTool({
496927
497218
  name: "status_job",
496928
497219
  category: "status",
496929
497220
  cost: "free",
497221
+ title: "Check Job Status",
497222
+ annotations: { readOnly: false, destructive: false, openWorld: true },
496930
497223
  description: "Read one local async job record and optionally refresh supported provider status. Supports Runway/Kling video and Replicate music live checks. Also tracks long-running MCP build/render jobs (jobType build/render, provider local): their records are updated in-process \u2014 on completion result.payload carries the full tool result; status 'unknown' means the MCP server restarted mid-job (check build-report.json / render-report.json on disk).",
496931
497224
  schema: z15.object({
496932
497225
  jobId: z15.string().describe("Local job id returned by a no-wait command."),
@@ -496962,6 +497255,8 @@ var statusProjectTool = defineTool({
496962
497255
  name: "status_project",
496963
497256
  category: "status",
496964
497257
  cost: "free",
497258
+ title: "Check Project Status",
497259
+ annotations: { readOnly: false, destructive: false, openWorld: true },
496965
497260
  description: "Summarize build-report.json, review-report.json, and local async job records for a VibeFrame project.",
496966
497261
  schema: z15.object({
496967
497262
  projectDir: z15.string().optional().describe(PROJECT_DIR_DESCRIPTION4),
@@ -497218,16 +497513,29 @@ function manifestToMcpTools(manifest2) {
497218
497513
  const inputSchema = zodToJsonSchema(t2.schema);
497219
497514
  return {
497220
497515
  name: t2.name,
497516
+ title: t2.title,
497221
497517
  description: t2.description,
497222
497518
  inputSchema: {
497223
497519
  type: "object",
497224
497520
  properties: inputSchema.properties ?? {},
497225
497521
  required: inputSchema.required ?? [],
497226
497522
  ...inputSchema.description ? { description: inputSchema.description } : {}
497227
- }
497523
+ },
497524
+ annotations: toMcpAnnotations(t2.annotations)
497228
497525
  };
497229
497526
  });
497230
497527
  }
497528
+ function toMcpAnnotations(a2) {
497529
+ if (a2.readOnly) {
497530
+ return { readOnlyHint: true, openWorldHint: a2.openWorld };
497531
+ }
497532
+ return {
497533
+ readOnlyHint: false,
497534
+ destructiveHint: a2.destructive ?? true,
497535
+ ...a2.idempotent !== void 0 ? { idempotentHint: a2.idempotent } : {},
497536
+ openWorldHint: a2.openWorld
497537
+ };
497538
+ }
497231
497539
  function buildMcpDispatcher(manifest2) {
497232
497540
  const byName = /* @__PURE__ */ new Map();
497233
497541
  for (const t2 of manifest2) {
@@ -497252,7 +497560,8 @@ function buildMcpDispatcher(manifest2) {
497252
497560
  () => tool.execute(parsed.data, {
497253
497561
  workingDirectory: process.cwd(),
497254
497562
  surface: "mcp",
497255
- ...extra?.onProgress ? { onProgress: sink.send } : {}
497563
+ ...extra?.onProgress ? { onProgress: sink.send } : {},
497564
+ ...extra?.elicit ? { elicit: extra.elicit } : {}
497256
497565
  })
497257
497566
  );
497258
497567
  const text = result.success ? JSON.stringify({ success: true, ...result.data }) : result.data ? JSON.stringify({
@@ -497747,10 +498056,22 @@ function buildServerInstructions(cwd = resolveServerWorkspaceRoot()) {
497747
498056
  "For args named dir, projectDir, output, videoPath, or source, prefer workspace-relative paths unless the user explicitly provides an absolute path.",
497748
498057
  "When creating projects with init, use a project name or workspace-relative path under the workspace root.",
497749
498058
  "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."
498059
+ "Before high or very-high cost provider work, run a dry-run or plan when available and ask the user to confirm provider spend.",
498060
+ "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
498061
  ].join("\n");
497752
498062
  }
497753
498063
 
498064
+ // src/elicit.ts
498065
+ var ELICIT_TIMEOUT_MS = 6e5;
498066
+ function makeElicitFn(server3, env4 = process.env) {
498067
+ if ((env4.VIBE_MCP_ELICIT ?? "").toLowerCase() === "off") return void 0;
498068
+ if (!server3.getClientCapabilities()?.elicitation) return void 0;
498069
+ return (form) => server3.elicitInput(
498070
+ { mode: "form", message: form.message, requestedSchema: form.requestedSchema },
498071
+ { timeout: ELICIT_TIMEOUT_MS }
498072
+ );
498073
+ }
498074
+
497754
498075
  // src/index.ts
497755
498076
  console.log = (...args) => console.error(...args);
497756
498077
  console.info = (...args) => console.error(...args);
@@ -497761,7 +498082,7 @@ var server2 = new Server(
497761
498082
  {
497762
498083
  name: "vibeframe",
497763
498084
  // Stamped with the package version by build.js at bundle time.
497764
- version: "0.109.2"
498085
+ version: "0.111.0"
497765
498086
  },
497766
498087
  {
497767
498088
  capabilities: {
@@ -497778,20 +498099,28 @@ server2.setRequestHandler(ListToolsRequestSchema, async () => {
497778
498099
  server2.setRequestHandler(CallToolRequestSchema, async (request5, extra) => {
497779
498100
  const { name, arguments: args } = request5.params;
497780
498101
  const progressToken = request5.params._meta?.progressToken;
498102
+ const elicit = makeElicitFn(server2);
497781
498103
  return handleToolCall(
497782
498104
  name,
497783
498105
  args || {},
497784
- progressToken === void 0 ? void 0 : {
497785
- onProgress: ({ progress, total, message }) => {
497786
- void extra.sendNotification({
497787
- method: "notifications/progress",
497788
- params: {
497789
- progressToken,
497790
- progress: progress ?? 0,
497791
- ...total !== void 0 ? { total } : {},
497792
- ...message ? { message } : {}
497793
- }
497794
- }).catch(() => void 0);
498106
+ progressToken === void 0 && elicit === void 0 ? void 0 : {
498107
+ ...elicit ? { elicit } : {},
498108
+ ...progressToken === void 0 ? {} : {
498109
+ onProgress: ({
498110
+ progress,
498111
+ total,
498112
+ message
498113
+ }) => {
498114
+ void extra.sendNotification({
498115
+ method: "notifications/progress",
498116
+ params: {
498117
+ progressToken,
498118
+ progress: progress ?? 0,
498119
+ ...total !== void 0 ? { total } : {},
498120
+ ...message ? { message } : {}
498121
+ }
498122
+ }).catch(() => void 0);
498123
+ }
497795
498124
  }
497796
498125
  }
497797
498126
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibeframe/mcp-server",
3
- "version": "0.109.2",
3
+ "version": "0.111.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.109.2",
64
- "@vibeframe/cli": "0.109.2"
63
+ "@vibeframe/cli": "0.111.0",
64
+ "@vibeframe/core": "0.111.0"
65
65
  },
66
66
  "engines": {
67
67
  "node": ">=20"