@vibeframe/mcp-server 0.112.1 → 0.113.2

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 +139 -126
  2. package/dist/index.js +1919 -693
  3. package/package.json +3 -3
package/README.md CHANGED
@@ -1,18 +1,29 @@
1
1
  # @vibeframe/mcp-server
2
2
 
3
- The MCP (Model Context Protocol) **server** for [VibeFrame](https://github.com/vericontext/vibeframe). This package is *only* the MCP adapter — it exposes VibeFrame's operations as typed MCP tools so an MCP-capable host can call them by natural language.
3
+ The MCP (Model Context Protocol) **server** for [VibeFrame](https://github.com/vericontext/vibeframe). This package is _only_ the MCP adapter — it exposes VibeFrame's operations as typed MCP tools so an MCP-capable host can call them by natural language.
4
4
 
5
5
  VibeFrame is CLI-first, not terminal-only. The CLI is the stable runtime; MCP is the app-host surface for clients that prefer typed tools over shell commands.
6
6
 
7
7
  Confirmed MCP hosts today: **Claude Desktop**, **Cursor**, and **Claude Code**. Codex can drive `vibe` natively via shell + `AGENTS.md`, and can also load a project-scoped MCP server through `.codex/config.toml`. For other shell-capable hosts, use [`@vibeframe/cli`](https://www.npmjs.com/package/@vibeframe/cli) directly — same operations.
8
8
 
9
+ For long-running video builds, use the host's native goal mode as the outer
10
+ loop: Codex `/goal`, Claude Code `/goal`, Cursor's agent loop, or the host
11
+ equivalent. VibeFrame's MCP tools provide the inner video runtime: JSON-style
12
+ results, dry-run/cost gates, `build-report.json`, `review-report.json`,
13
+ `retryWith`, `fixOwner`, deterministic repair, and render inspection.
14
+
9
15
  > **Just want a CLI?** Use [`@vibeframe/cli`](https://www.npmjs.com/package/@vibeframe/cli) instead — same operations, invoked directly in your shell as `vibe <command>`. This package and the CLI wrap the same underlying engine; pick whichever fits your workflow. Many users install both.
10
16
 
11
- | Surface | Package | How you call it |
12
- |---------|---------|-----------------|
13
- | MCP host (Claude Desktop / Cursor / OpenCode / Claude Code) | `@vibeframe/mcp-server` *(this)* | host calls tool by name, for example `mcp__vibeframe__build({...})` |
14
- | Shell / scripts (any agent host: Codex / Aider / Gemini CLI / etc.) | `@vibeframe/cli` | `vibe init my-video && vibe build my-video && vibe render my-video` |
15
- | Optional standalone agent REPL | `@vibeframe/cli` (`vibe agent`) | natural language -> CLI calls when you do not already use Claude Code/Codex/Cursor/etc. |
17
+ | Surface | Package | How you call it |
18
+ | ------------------------------------------------------------------- | -------------------------------- | --------------------------------------------------------------------------------------- |
19
+ | MCP host (Claude Desktop / Cursor / OpenCode / Claude Code) | `@vibeframe/mcp-server` _(this)_ | host calls tool by name, for example `mcp__vibeframe__build({...})` |
20
+ | Shell / scripts (any agent host: Codex / Aider / Gemini CLI / etc.) | `@vibeframe/cli` | `vibe init my-video && vibe build my-video && vibe render my-video` |
21
+ | Optional standalone agent REPL | `@vibeframe/cli` (`vibe agent`) | natural language -> CLI calls when you do not already use Claude Code/Codex/Cursor/etc. |
22
+
23
+ Native goal stop rules should be explicit: final MP4 path exists, duration and
24
+ aspect ratio match the brief, render inspection has no errors, any AI review score
25
+ meets the goal threshold when AI review is requested, and every `fixOwner:"host-agent"` issue is fixed,
26
+ accepted with rationale, or reported as blocked.
16
27
 
17
28
  The tool list below is what the MCP host sees. The same operations exist as `vibe <verb> <noun>` subcommands in the CLI — see `vibe --help`.
18
29
 
@@ -45,16 +56,17 @@ enabled = true
45
56
 
46
57
  Install the prebuilt Desktop Extension — no Node, npx, or JSON editing needed:
47
58
 
48
- 1. Download `vibeframe-<version>.mcpb` from the
49
- [latest GitHub Release](https://github.com/vericontext/vibeframe/releases/latest).
59
+ 1. Download the extension: [vibeframe.mcpb (always latest)](https://github.com/vericontext/vibeframe/releases/latest/download/vibeframe.mcpb)
60
+ — or pick a specific version from the [releases page](https://github.com/vericontext/vibeframe/releases).
50
61
  2. In Claude Desktop open **Settings → Extensions** and drag the `.mcpb` file in
51
62
  (or double-click the file).
52
63
  3. In the extension's settings pick your **Workspace folder** (projects are
53
64
  created there; a `.env` file in that folder is loaded for API keys) and
54
65
  optionally paste provider keys.
55
66
 
56
- Rendering still needs Google Chrome and `ffmpeg` on the machine. For free local
57
- Kokoro TTS, run `npm i kokoro-js` once inside the workspace folder. To update,
67
+ Rendering still needs Google Chrome and `ffmpeg` on the machine. Free local
68
+ Kokoro narration is bundled inside the extension — no install step; the first
69
+ use downloads a ~90 MB voice model to `~/.cache/vibeframe/models`. To update,
58
70
  download the new release's `.mcpb` and install it over the old one.
59
71
 
60
72
  To build the bundle from source: `pnpm -F @vibeframe/mcp-server build:mcpb`
@@ -131,8 +143,9 @@ The server prefers asking over silently picking defaults:
131
143
 
132
144
  - On hosts that support **MCP elicitation** (Claude Code 2.1.76+), the `build`
133
145
  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.
146
+ left unspecified: narration provider (Kokoro free/local, OpenAI's
147
+ gpt-4o-mini-tts, or ElevenLabs), backdrop image generation (skip vs paid
148
+ OpenAI), and a max cost cap.
136
149
  Declining cancels the build before any provider spend. Set
137
150
  `VIBE_MCP_ELICIT=off` in the server env to disable the form (headless and
138
151
  automation setups).
@@ -145,13 +158,13 @@ The server prefers asking over silently picking defaults:
145
158
  Once connected, your MCP host can resolve prompts like these into typed tool calls:
146
159
 
147
160
  > "Scaffold a 12-second Swiss-Pulse promo project, three beats, and render it"
148
- > *→ `init` + 3× `scene_add` + `render`*
161
+ > _→ `init` + 3× `scene_add` + `render`_
149
162
 
150
163
  > "Generate a cinematic backdrop image, animate it for 5 seconds, add narration"
151
- > *→ `generate_image` + `generate_video` + `generate_speech`*
164
+ > _→ `generate_image` + `generate_video` + `generate_speech`_
152
165
 
153
166
  > "Remove silent segments and add captions to my interview"
154
- > *→ `edit_silence_cut` + `edit_caption`*
167
+ > _→ `edit_silence_cut` + `edit_caption`_
155
168
 
156
169
  ## Available Tools
157
170
 
@@ -159,165 +172,165 @@ Tool names are MCP-side. Your host typically prefixes them (e.g. Claude shows th
159
172
 
160
173
  ### Project flow (top-level)
161
174
 
162
- | Tool | Description |
163
- |------|-------------|
164
- | `project_list` | List workspace video projects with build/render status (`_archive/` skipped) |
165
- | `init` | Scaffold a video project with `STORYBOARD.md` + `DESIGN.md` |
166
- | `build` | Build a storyboard project: narration TTS, image assets, scene HTML composition |
167
- | `render` | Deterministic Hyperframes render → MP4/WebM/MOV |
175
+ | Tool | Description |
176
+ | -------------- | ------------------------------------------------------------------------------- |
177
+ | `project_list` | List workspace video projects with build/render status (`_archive/` skipped) |
178
+ | `init` | Scaffold a video project with `STORYBOARD.md` + `DESIGN.md` |
179
+ | `build` | Build a storyboard project: narration TTS, image assets, scene HTML composition |
180
+ | `render` | Deterministic Hyperframes render → MP4/WebM/MOV |
168
181
 
169
182
  ### Scene authoring (lower-level)
170
183
 
171
- | Tool | Description |
172
- |------|-------------|
173
- | `scene_list_styles` | List the 8 vendored visual identities (Swiss Pulse, Data Drift, …) or fetch one |
174
- | `scene_add` | Append a beat (narration + backdrop + composed HTML) |
175
- | `scene_install_skill` | Install the Hyperframes skill bundle into a scene project |
176
- | `scene_lint` | Validate composition HTML against the visual identity |
177
- | `scene_compose_prompts` | Emit the per-beat compose plan without making an LLM call |
184
+ | Tool | Description |
185
+ | ----------------------- | ------------------------------------------------------------------------------- |
186
+ | `scene_list_styles` | List the 8 vendored visual identities (Swiss Pulse, Data Drift, …) or fetch one |
187
+ | `scene_add` | Append a beat (narration + backdrop + composed HTML) |
188
+ | `scene_install_skill` | Install the Hyperframes skill bundle into a scene project |
189
+ | `scene_lint` | Validate composition HTML against the visual identity |
190
+ | `scene_compose_prompts` | Emit the per-beat compose plan without making an LLM call |
178
191
 
179
192
  ### Generation (13)
180
193
 
181
- | Tool | Description | Providers |
182
- |------|-------------|-----------|
183
- | `generate_image` | Text-to-image | OpenAI, Google, Stability |
184
- | `generate_background` | Cinematic backdrop image (video-tuned prompt) | OpenAI |
185
- | `generate_video` | Text/image-to-video (long-running) | Seedance via fal.ai, Grok, Kling, Runway, Google Veo |
186
- | `generate_video_status` / `_cancel` / `_extend` | Manage long-running video jobs | (provider-specific) |
187
- | `generate_motion` | Generate standalone designed motion graphics | Claude or Gemini + Remotion |
188
- | `generate_speech` | Text-to-speech | ElevenLabs |
189
- | `generate_music` | AI background music | Suno, ElevenLabs, Replicate MusicGen |
190
- | `generate_music_status` | Poll Replicate music task | Replicate |
191
- | `generate_sound_effect` | SFX from prompt | ElevenLabs |
192
- | `generate_thumbnail` | AI thumbnail composition | OpenAI, Google |
193
- | `generate_storyboard` | Multi-beat storyboard frames | OpenAI, Google |
194
+ | Tool | Description | Providers |
195
+ | ----------------------------------------------- | --------------------------------------------- | ---------------------------------------------------- |
196
+ | `generate_image` | Text-to-image | OpenAI, Google, Stability |
197
+ | `generate_background` | Cinematic backdrop image (video-tuned prompt) | OpenAI |
198
+ | `generate_video` | Text/image-to-video (long-running) | Seedance via fal.ai, Grok, Kling, Runway, Google Veo |
199
+ | `generate_video_status` / `_cancel` / `_extend` | Manage long-running video jobs | (provider-specific) |
200
+ | `generate_motion` | Generate standalone designed motion graphics | Claude or Gemini + Remotion |
201
+ | `generate_speech` | Text-to-speech | ElevenLabs |
202
+ | `generate_music` | AI background music | Suno, ElevenLabs, Replicate MusicGen |
203
+ | `generate_music_status` | Poll Replicate music task | Replicate |
204
+ | `generate_sound_effect` | SFX from prompt | ElevenLabs |
205
+ | `generate_thumbnail` | AI thumbnail composition | OpenAI, Google |
206
+ | `generate_storyboard` | Multi-beat storyboard frames | OpenAI, Google |
194
207
 
195
208
  ### Editing (16)
196
209
 
197
- | Tool | Description |
198
- |------|-------------|
199
- | `edit_silence_cut` | Remove silent segments (FFmpeg or Gemini) |
200
- | `edit_jump_cut` | Remove filler words (Whisper) |
201
- | `edit_caption` / `edit_animated_caption` | Burn styled / animated captions |
202
- | `edit_text_overlay` | Simple static text burn-in |
203
- | `edit_motion_overlay` | Designed animated overlays or user-provided Lottie overlays |
204
- | `edit_fade` | Fade in/out |
205
- | `edit_grade` | Color grading |
206
- | `edit_speed_ramp` | Variable-speed segments |
207
- | `edit_reframe` | Aspect-ratio reframe (e.g. 16:9 → 9:16) |
208
- | `edit_interpolate` | Frame interpolation / slow-mo |
209
- | `edit_upscale` | AI upscaling |
210
- | `edit_image` | Image editing (gpt-image-2, Gemini) |
211
- | `edit_noise_reduce` | Audio/video denoise |
212
- | `edit_translate_srt` | Translate SRT subtitles |
213
- | `edit_fill_gaps` | Detect & fill missing video segments via TTS narration timing (Plan G — Phase 4) |
210
+ | Tool | Description |
211
+ | ---------------------------------------- | -------------------------------------------------------------------------------- |
212
+ | `edit_silence_cut` | Remove silent segments (FFmpeg or Gemini) |
213
+ | `edit_jump_cut` | Remove filler words (Whisper) |
214
+ | `edit_caption` / `edit_animated_caption` | Burn styled / animated captions |
215
+ | `edit_text_overlay` | Simple static text burn-in |
216
+ | `edit_motion_overlay` | Designed animated overlays or user-provided Lottie overlays |
217
+ | `edit_fade` | Fade in/out |
218
+ | `edit_grade` | Color grading |
219
+ | `edit_speed_ramp` | Variable-speed segments |
220
+ | `edit_reframe` | Aspect-ratio reframe (e.g. 16:9 → 9:16) |
221
+ | `edit_interpolate` | Frame interpolation / slow-mo |
222
+ | `edit_upscale` | AI upscaling |
223
+ | `edit_image` | Image editing (gpt-image-2, Gemini) |
224
+ | `edit_noise_reduce` | Audio/video denoise |
225
+ | `edit_translate_srt` | Translate SRT subtitles |
226
+ | `edit_fill_gaps` | Detect & fill missing video segments via TTS narration timing (Plan G — Phase 4) |
214
227
 
215
228
  ### Audio (5)
216
229
 
217
- | Tool | Description |
218
- |------|-------------|
219
- | `audio_dub` | AI voice dubbing (ElevenLabs) |
220
- | `audio_clone_voice` | Voice clone from sample |
221
- | `audio_isolate` | Vocal / background isolation |
222
- | `audio_duck` | Auto-duck BGM under speech |
223
- | `audio_transcribe` | Transcript with word-level timing (Whisper) |
230
+ | Tool | Description |
231
+ | ------------------- | ------------------------------------------- |
232
+ | `audio_dub` | AI voice dubbing (ElevenLabs) |
233
+ | `audio_clone_voice` | Voice clone from sample |
234
+ | `audio_isolate` | Vocal / background isolation |
235
+ | `audio_duck` | Auto-duck BGM under speech |
236
+ | `audio_transcribe` | Transcript with word-level timing (Whisper) |
224
237
 
225
238
  ### Detection (3)
226
239
 
227
- | Tool | Description |
228
- |------|-------------|
240
+ | Tool | Description |
241
+ | ---------------- | -------------------- |
229
242
  | `detect_silence` | Find silent segments |
230
- | `detect_scenes` | Find shot boundaries |
231
- | `detect_beats` | Find music beats |
243
+ | `detect_scenes` | Find shot boundaries |
244
+ | `detect_beats` | Find music beats |
232
245
 
233
246
  ### Inspection (4)
234
247
 
235
- | Tool | Description |
236
- |------|-------------|
237
- | `inspect_media` | Unified image / video / YouTube analysis (Gemini) |
238
- | `inspect_video` | Temporal video understanding (Gemini) |
239
- | `inspect_review` | AI video review + auto-fix suggestions |
248
+ | Tool | Description |
249
+ | ----------------- | ----------------------------------------------------------------------- |
250
+ | `inspect_media` | Unified image / video / YouTube analysis (Gemini) |
251
+ | `inspect_video` | Temporal video understanding (Gemini) |
252
+ | `inspect_review` | AI video review + auto-fix suggestions |
240
253
  | `inspect_suggest` | Natural-language project edit suggestions (Gemini); optional auto-apply |
241
254
 
242
255
  ### Timeline (10)
243
256
 
244
- | Tool | Description |
245
- |------|-------------|
246
- | `timeline_create` / `timeline_info` | Create or inspect low-level timeline JSON state |
247
- | `timeline_add_source` | Import media (video/audio/image) |
248
- | `timeline_add_clip` / `_split_clip` / `_trim_clip` | Build & shape clips |
249
- | `timeline_move_clip` / `_duplicate_clip` / `_delete_clip` | Arrange clips |
250
- | `timeline_add_track` | Add video/audio track |
251
- | `timeline_add_effect` | Apply effect (fade, blur, …) |
252
- | `timeline_list` | List all project contents |
257
+ | Tool | Description |
258
+ | --------------------------------------------------------- | ----------------------------------------------- |
259
+ | `timeline_create` / `timeline_info` | Create or inspect low-level timeline JSON state |
260
+ | `timeline_add_source` | Import media (video/audio/image) |
261
+ | `timeline_add_clip` / `_split_clip` / `_trim_clip` | Build & shape clips |
262
+ | `timeline_move_clip` / `_duplicate_clip` / `_delete_clip` | Arrange clips |
263
+ | `timeline_add_track` | Add video/audio track |
264
+ | `timeline_add_effect` | Apply effect (fade, blur, …) |
265
+ | `timeline_list` | List all project contents |
253
266
 
254
267
  ### Compatibility & Export
255
268
 
256
- | Tool | Description |
257
- |------|-------------|
269
+ | Tool | Description |
270
+ | --------------------------------- | -------------------------------------------------------- |
258
271
  | `project_create` / `project_info` | Deprecated compatibility aliases for timeline JSON state |
259
- | `export_video` | Export timeline JSON to MP4/WebM/MOV via FFmpeg |
272
+ | `export_video` | Export timeline JSON to MP4/WebM/MOV via FFmpeg |
260
273
 
261
274
  ### Remix & pipelines (4)
262
275
 
263
- | Tool | Description |
264
- |------|-------------|
265
- | `run` | Execute a multi-stage YAML pipeline (`vibe run pipeline.yaml`) |
266
- | `remix_highlights` | Long-form → highlight clips |
267
- | `remix_auto_shorts` | Long-form → vertical shorts |
276
+ | Tool | Description |
277
+ | ------------------------ | ------------------------------------------------------------------- |
278
+ | `run` | Execute a multi-stage YAML pipeline (`vibe run pipeline.yaml`) |
279
+ | `remix_highlights` | Long-form → highlight clips |
280
+ | `remix_auto_shorts` | Long-form → vertical shorts |
268
281
  | `remix_regenerate_scene` | Re-render a single scene against an existing storyboard.{yaml,json} |
269
282
 
270
283
  ### Guides (1)
271
284
 
272
- | Tool | Description |
273
- |------|-------------|
285
+ | Tool | Description |
286
+ | ------- | ------------------------------------------------------------------------- |
274
287
  | `guide` | Cross-host guides for motion, scene, pipeline, and architecture workflows |
275
288
 
276
289
  > **CLI ↔ MCP sync**: `packages/mcp-server/src/tools/cli-sync.test.ts` is a vitest hook that fails CI when a CLI subcommand is added/removed/renamed without the matching MCP change. Open the test file to see the live mapping table — `null` rows mark CLI-only commands (e.g. `vibe audio list-voices`, `vibe timeline set`) that are intentionally not exposed via MCP.
277
290
 
278
291
  ## Resources
279
292
 
280
- | URI | Description |
281
- |-----|-------------|
282
- | `vibe://project/current` | Full project state |
283
- | `vibe://project/clips` | All clips |
284
- | `vibe://project/sources` | Media sources |
285
- | `vibe://project/tracks` | Track list |
286
- | `vibe://project/settings` | Project settings |
293
+ | URI | Description |
294
+ | ------------------------- | ------------------ |
295
+ | `vibe://project/current` | Full project state |
296
+ | `vibe://project/clips` | All clips |
297
+ | `vibe://project/sources` | Media sources |
298
+ | `vibe://project/tracks` | Track list |
299
+ | `vibe://project/settings` | Project settings |
287
300
 
288
301
  ## Prompts
289
302
 
290
- | Prompt | Description |
291
- |--------|-------------|
292
- | `edit_video` | Natural-language editing instructions |
293
- | `create_montage` | Montage with automatic pacing |
294
- | `add_transitions` | Add transitions between clips |
295
- | `color_grade` | Apply color grading |
296
- | `generate_subtitles` | Subtitles via AI transcription |
297
- | `create_shorts` | Short-form from longer video |
298
- | `sync_to_music` | Cut to music beats |
303
+ | Prompt | Description |
304
+ | -------------------- | ------------------------------------- |
305
+ | `edit_video` | Natural-language editing instructions |
306
+ | `create_montage` | Montage with automatic pacing |
307
+ | `add_transitions` | Add transitions between clips |
308
+ | `color_grade` | Apply color grading |
309
+ | `generate_subtitles` | Subtitles via AI transcription |
310
+ | `create_shorts` | Short-form from longer video |
311
+ | `sync_to_music` | Cut to music beats |
299
312
 
300
313
  ## Environment Variables
301
314
 
302
315
  API keys are read from the host's environment (`~/.zshrc`, MCP config `env` block, etc.). All optional — only set the ones whose providers you use.
303
316
 
304
- | Variable | Used by |
305
- |----------|---------|
306
- | `OPENAI_API_KEY` | gpt-image-2, Whisper, GPT |
307
- | `ANTHROPIC_API_KEY` | Claude (translate-srt, highlights, build compose pipeline) |
308
- | `GOOGLE_API_KEY` | Gemini (analyze, review, silence-cut, narrate) |
309
- | `ELEVENLABS_API_KEY` | TTS, voice-clone, dubbing, SFX |
310
- | `XAI_API_KEY` | Grok |
311
- | `FAL_API_KEY` | Seedance image-to-video |
312
- | `RUNWAY_API_SECRET` | Runway video |
313
- | `KLING_API_KEY` | Kling video |
314
- | `IMGBB_API_KEY` | Default temporary image host for Seedance/Kling image-to-video |
315
- | `VIBE_UPLOAD_PROVIDER` | `imgbb` (default) or `s3` for temporary image uploads |
316
- | `VIBE_UPLOAD_S3_BUCKET` | S3 bucket when `VIBE_UPLOAD_PROVIDER=s3` |
317
- | `VIBE_UPLOAD_S3_PREFIX` | Optional S3 key prefix for temporary image uploads |
318
- | `VIBE_UPLOAD_TTL_SECONDS` | Optional TTL hint for temporary upload URLs |
319
- | `AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY` / `AWS_REGION` | S3 upload host credentials |
320
- | `VIBE_PROJECT_PATH` | Default timeline JSON path for resources |
317
+ | Variable | Used by |
318
+ | ------------------------------------------------------------ | -------------------------------------------------------------- |
319
+ | `OPENAI_API_KEY` | gpt-image-2, Whisper, GPT |
320
+ | `ANTHROPIC_API_KEY` | Claude (translate-srt, highlights, build compose pipeline) |
321
+ | `GOOGLE_API_KEY` | Gemini (analyze, review, silence-cut, narrate) |
322
+ | `ELEVENLABS_API_KEY` | TTS, voice-clone, dubbing, SFX |
323
+ | `XAI_API_KEY` | Grok |
324
+ | `FAL_API_KEY` | Seedance image-to-video |
325
+ | `RUNWAY_API_SECRET` | Runway video |
326
+ | `KLING_API_KEY` | Kling video |
327
+ | `IMGBB_API_KEY` | Default temporary image host for Seedance/Kling image-to-video |
328
+ | `VIBE_UPLOAD_PROVIDER` | `imgbb` (default) or `s3` for temporary image uploads |
329
+ | `VIBE_UPLOAD_S3_BUCKET` | S3 bucket when `VIBE_UPLOAD_PROVIDER=s3` |
330
+ | `VIBE_UPLOAD_S3_PREFIX` | Optional S3 key prefix for temporary image uploads |
331
+ | `VIBE_UPLOAD_TTL_SECONDS` | Optional TTL hint for temporary upload URLs |
332
+ | `AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY` / `AWS_REGION` | S3 upload host credentials |
333
+ | `VIBE_PROJECT_PATH` | Default timeline JSON path for resources |
321
334
 
322
335
  ## Requirements
323
336