{"data":{"name":"com.frapea/editor","title":"Frapea","description":"A video editor in your browser that your AI drives: cuts, captions, multicam, motion titles, export.","version":"0.2.0","websiteUrl":"https://frapea.com","repositoryUrl":null,"remotes":[{"url":"https://app.frapea.com/mcp","type":"streamable-http"}],"packages":[],"status":"active","isLatest":true,"publishedAt":"2026-10-11T08:19:10.290Z","updatedAt":"2026-10-11T08:19:10.290Z","source":"official-registry","verification":"official","confidence":100,"stars":null,"sources":[{"stars":null,"title":"Frapea","source":"official-registry","sourceId":"com.frapea/editor","updatedAt":"2026-10-11T08:19:10.290Z","confidence":100,"websiteUrl":"https://frapea.com","description":"A video editor in your browser that your AI drives: cuts, captions, multicam, motion titles, export.","verification":"official","repositoryUrl":null}],"toolIndex":{"tools":[{"serverName":"com.frapea/editor","endpointFingerprint":"cceef1cf3f47b142bc892cb7ab17e36107fdb6ee91dd5c5a86fba43270aefe34","name":"add_clips","title":"Add clips","description":"Places media segments on a timeline. Each clip: mediaRef (from get_media, 'timeline:<id>' to NEST another timeline as a clip, 'solid:#rrggbb' , 'motion:<id>' for a MOTION composition (create_motion_composition) for a generated solid-colour matte, 'adjustment:' for an adjustment clip — no picture of its own, its effects/masks/opacity grade everything below it — or 'text:' for a title, restyled via set_clip_properties' `text`), atFrame (timeline position), sourceInSec/sourceOutSec (the segment of the source to use — align these with transcript words or sceneSamples), and optional trackId (from get_timeline) to target a specific same-kind track — without it clips land on V1/A1 with overwrite semantics. A spare empty track always exists above the highest used one, so V2/A2 is available before anything sits on it. Video sources with audio get a linked audio clip automatically (on the matching A track: V2 ⇒ A2). Returns the created clip ids in order. Frames are in the target timeline's fps.","inputSchema":{"type":"object","properties":{"projectId":{"type":"string","description":"Project id from get_projects."},"timelineId":{"type":"string","description":"Target timeline id from get_timeline."},"clips":{"type":"array","description":"[{mediaRef, atFrame, sourceInSec, sourceOutSec, trackId?}] — segments in playback order; trackId targets a specific track (default V1/A1)."},"token":{"type":"string","description":"The session token `connect` returned. Pass it on every call — it says which browser to drive."}},"required":["projectId","timelineId","clips","token"]},"annotations":{"readOnlyHint":false,"destructiveHint":true,"idempotentHint":false,"openWorldHint":false},"definitionHash":"7235e8221a39d0562ea442277482b141fd46fb5b1562dfb218b3e3230e8679a6","schemaStatus":"valid","origin":"official-registry","observedAt":"2026-11-03T18:47:25.723Z","metadataTrust":"untrusted"},{"serverName":"com.frapea/editor","endpointFingerprint":"cceef1cf3f47b142bc892cb7ab17e36107fdb6ee91dd5c5a86fba43270aefe34","name":"await_user_action","title":"Wait for the user","description":"Waits (up to ~45 s per call) for the user to resolve a pending Frapea prompt — e.g. the folder-permission dialog another tool just opened. The dialog waits for the user in the Frapea tab; the tool that opened it returned what they need to click. Returns {status: 'granted' | 'denied' | 'pending'}: 'pending' means they have not acted yet (call again to keep waiting), 'denied' that they declined.","inputSchema":{"type":"object","properties":{"actionId":{"type":"string","description":"The actionId a previous tool returned."},"token":{"type":"string","description":"The session token `connect` returned. Pass it on every call — it says which browser to drive."}},"required":["actionId","token"]},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"definitionHash":"da1cdfbddacca96b01eb32e8bd57dd2abeafdc792a48e773a6ddb606a63d37ee","schemaStatus":"valid","origin":"official-registry","observedAt":"2026-11-03T18:47:25.723Z","metadataTrust":"untrusted"},{"serverName":"com.frapea/editor","endpointFingerprint":"cceef1cf3f47b142bc892cb7ab17e36107fdb6ee91dd5c5a86fba43270aefe34","name":"close_project","title":"Close project","description":"Navigates the user's Frapea tab back to the project manager and releases this session's headless runtime for the project. When the tab shows that project it reloads, so an export or render running there stops.","inputSchema":{"type":"object","properties":{"projectId":{"type":"string","description":"Project id from get_projects."},"token":{"type":"string","description":"The session token `connect` returned. Pass it on every call — it says which browser to drive."}},"required":["projectId","token"]},"annotations":{"readOnlyHint":false,"destructiveHint":true,"idempotentHint":true,"openWorldHint":false},"definitionHash":"698f4b050d084be4b7743ef9b432f1e533dfa900d92ed3a0871b78a7985c3869","schemaStatus":"valid","origin":"official-registry","observedAt":"2026-11-03T18:47:25.723Z","metadataTrust":"untrusted"},{"serverName":"com.frapea/editor","endpointFingerprint":"cceef1cf3f47b142bc892cb7ab17e36107fdb6ee91dd5c5a86fba43270aefe34","name":"connect","title":"Connect to Frapea","description":"Pairs you with the user's Frapea browser tab. TWO WAYS ROUND. (1) If they already have Frapea open: ask them for the pairing code (the Connect MCP button) and call this with it. (2) If they do not, or you are not sure: call this with NO arguments and you get back a link — send them the link, then call this again with the code it contains every few seconds until it returns a token (they have to accept it in their browser first). Either way you end up with a session token to pass on every later call. Codes are single-use and expire in ten minutes; a token lasts until the user disconnects.","inputSchema":{"type":"object","properties":{"code":{"type":"string","description":"The 8-character code — from the user's screen, or from the link this tool gave you. Omit it to get a link to send them."}}},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false},"definitionHash":"37ef2dbb1a4cb04f2df0922d57060b4179cbb02d6b233ba7e25d8c8cc0a5c9d6","schemaStatus":"valid","origin":"official-registry","observedAt":"2026-11-03T18:47:25.723Z","metadataTrust":"untrusted"},{"serverName":"com.frapea/editor","endpointFingerprint":"cceef1cf3f47b142bc892cb7ab17e36107fdb6ee91dd5c5a86fba43270aefe34","name":"connect_media_folder","title":"Ask to connect a media folder","description":"Asks the user to attach a folder of THEIR OWN source footage to the project — opens a dialog in Frapea with a 'Connect folder' button. Only a human can do this (browser security gesture): tell the user IN YOUR REPLY to click it, then call await_user_action with the returned actionId; on 'granted', get_media will list the folder's files. Use when get_media comes back empty and the user has footage somewhere on their disk.\nNEVER call it for files YOU made or fetched. The project folder's `media/` folder is scanned: any media file placed there joins the pool by itself (within a second, or when the user returns to the tab), with no dialog. `reason` is shown in the dialog word for word — say which footage you need and what you will do with it, so the user knows what to pick.","inputSchema":{"type":"object","properties":{"projectId":{"type":"string","description":"Project id from get_projects."},"reason":{"type":"string","description":"One or two sentences for the dialog, addressed to the user: which folder to pick and why — e.g. 'Pick the folder with your trip clips from Lisbon, so I can cut them into the reel you asked for.'"},"token":{"type":"string","description":"The session token `connect` returned. Pass it on every call — it says which browser to drive."}},"required":["projectId","reason","token"]},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false},"definitionHash":"75345e031b02b9eca68e97e2d5cdeafeb1224506e0e61f66a0059930632b4cf6","schemaStatus":"valid","origin":"official-registry","observedAt":"2026-11-03T18:47:25.723Z","metadataTrust":"untrusted"},{"serverName":"com.frapea/editor","endpointFingerprint":"cceef1cf3f47b142bc892cb7ab17e36107fdb6ee91dd5c5a86fba43270aefe34","name":"create_motion_composition","title":"Create motion composition","description":"Creates a MOTION COMPOSITION — an animated graphic (infographic, title, promo end-card, chart…) written as a React TSX component. Read the 'motion' skill (read_skill {topic:'motion'}) for the exact API surface, available fonts/icons and golden examples before writing one. files maps file names to TSX source; the entry must `export default` the component. schema declares the editable props (type string|number|color|boolean|select|mediaRef + default) — they become Inspector controls the user can tweak, so parameterize colors, copy and media slots. The composition is compiled and test-rendered BEFORE saving; on failure the error returns verbatim — fix the code and retry. Returns the mediaRef to place with add_clips. Creative guidance is in read_skill {topic:'motion'}. With UI-like parts (buttons, pills, progress bars, cards), write them in their own file with a partsBoard prop (default false) and look at the board first: preview:true, previewProps:{partsBoard:true} returns one large frame with the reply.","inputSchema":{"type":"object","properties":{"projectId":{"type":"string","description":"Project id from get_projects."},"name":{"type":"string","description":"Display name, e.g. 'Pink promo end card'."},"files":{"type":"object","description":"File name → TSX source. Relative imports between them work."},"entry":{"type":"string","description":"Entry file (default composition.tsx); must export default."},"schema":{"type":"object","description":"Editable props: {key: {type, default, label?, min?, max?, options?, multiline?}}. type mediaRef makes a media-pool slot."},"width":{"type":"number","description":"Composition width px (default 1920)."},"height":{"type":"number","description":"Composition height px (default 1080)."},"fps":{"type":"number","description":"Composition fps (default 30)."},"durationInFrames":{"type":"number","description":"Length in frames (default 150)."},"preview":{"type":"boolean","description":"Return one large frame (≤1560 px) with the reply. Media is not loaded in a preview: media slots draw empty and the reply says how many."},"previewProps":{"type":"object","description":"Merged over the schema defaults for the preview picture only, e.g. {partsBoard:true}. Nothing saved changes."},"previewFrame":{"type":"number","description":"Frame to preview (default 0)."},"token":{"type":"string","description":"The session token `connect` returned. Pass it on every call — it says which browser to drive."}},"required":["projectId","name","files","token"]},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false},"definitionHash":"da9bdab83dfeb205d0d91a5e08836320542a06fd57017b36c911c366073f1301","schemaStatus":"valid","origin":"official-registry","observedAt":"2026-11-03T18:47:25.723Z","metadataTrust":"untrusted"},{"serverName":"com.frapea/editor","endpointFingerprint":"cceef1cf3f47b142bc892cb7ab17e36107fdb6ee91dd5c5a86fba43270aefe34","name":"create_timeline","title":"Create timeline","description":"Creates a new timeline in the project and returns its id. Set fps, width and height for the target format (e.g. 1080×1920 @30 for a vertical short). The new timeline starts with one video and one audio track; spare tracks appear automatically as clips land.","inputSchema":{"type":"object","properties":{"projectId":{"type":"string","description":"Project id from get_projects."},"name":{"type":"string","description":"Display name, e.g. 'TikTok short'."},"fps":{"type":"number","description":"Optional frames per second (default 30)."},"width":{"type":"number","description":"Optional width in px (default 1920)."},"height":{"type":"number","description":"Optional height in px (default 1080)."},"token":{"type":"string","description":"The session token `connect` returned. Pass it on every call — it says which browser to drive."}},"required":["projectId","name","token"]},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false},"definitionHash":"516a5eb5dcca31b48831e061e6983dcb9174da5f31cfc7c466b7832af36874ad","schemaStatus":"valid","origin":"official-registry","observedAt":"2026-11-03T18:47:25.723Z","metadataTrust":"untrusted"},{"serverName":"com.frapea/editor","endpointFingerprint":"cceef1cf3f47b142bc892cb7ab17e36107fdb6ee91dd5c5a86fba43270aefe34","name":"cut_to_angle","title":"Cut to camera angle","description":"MULTICAM angle switch. The angles are ordinary video tracks stacked over each other (sync them beforehand — clips of the same take on V1..Vn); this razors the whole angle stack at `atFrame` and keeps only `chosenTrackId` live from there to the next cut — the other angles' clips are DISABLED, not deleted, so every switch stays re-decidable (cut again with a different angle to change your mind). Linked audio follows the video by default (audioFollowsVideo: false keeps audio untouched — the usual choice when one good mic carries the sound). angleTrackIds defaults to every video track with a clip under the frame. Refused when the chosen track has no clip at the frame.","inputSchema":{"type":"object","properties":{"projectId":{"type":"string","description":"Project id from get_projects."},"timelineId":{"type":"string","description":"Target timeline."},"atFrame":{"type":"number","description":"The switch point (timeline frame)."},"chosenTrackId":{"type":"string","description":"The angle to show from atFrame on."},"angleTrackIds":{"type":"array","items":{"type":"string"},"description":"Optional explicit angle set (video track ids)."},"audioFollowsVideo":{"type":"boolean","description":"Default true: linked audio toggles with its angle."},"token":{"type":"string","description":"The session token `connect` returned. Pass it on every call — it says which browser to drive."}},"required":["projectId","timelineId","atFrame","chosenTrackId","token"]},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false},"definitionHash":"9d2ae3d2a845b5cfc8e6a540b5ae4568538cb45228711727cc46db6ee1fd5aa4","schemaStatus":"valid","origin":"official-registry","observedAt":"2026-11-03T18:47:25.723Z","metadataTrust":"untrusted"},{"serverName":"com.frapea/editor","endpointFingerprint":"cceef1cf3f47b142bc892cb7ab17e36107fdb6ee91dd5c5a86fba43270aefe34","name":"download_stock_media","title":"Download Pexels stock","description":"Downloads one Pexels asset into the project's media pool as a virtual file at the Library root (name `pexels-<id>.jpg|.mp4`). Asynchronous: the first call accepts the download and returns its state; CALL AGAIN with the same arguments to poll — state becomes 'done' with the asset's mediaRef, ready for add_clips. maxHeight picks the best video rendition not exceeding it (default: the best available).\nASK FOR THE WHOLE SHOT LIST AT ONCE — three files stream at a time and the rest wait their turn, so a batch is queued for you, in the order you asked. State 'queued' is normal and needs no action but polling.\nONCE DOWNLOADED, CHECK THE MOMENT YOU MEAN TO USE — not just the first frame. A clip that opens on your subject can cut away, change subject or hold a logo exactly where you planned to trim. Read the scene samples from get_media, or render frames with inspect_media, across the range you intend to cut. See read_skill {topic:'verify'}.","inputSchema":{"type":"object","properties":{"projectId":{"type":"string","description":"Project id from get_projects."},"kind":{"type":"string","description":"photo | video"},"pexelsId":{"type":"number","description":"The item id from search_stock_media."},"maxHeight":{"type":"number","description":"Videos only: cap the rendition height (e.g. 1080)."},"token":{"type":"string","description":"The session token `connect` returned. Pass it on every call — it says which browser to drive."}},"required":["projectId","kind","pexelsId","token"]},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true,"openWorldHint":true},"definitionHash":"7b36cf5a14b3192218f58e1d18aa458bfd19338ce4ec171caada9967a8e1c75c","schemaStatus":"valid","origin":"official-registry","observedAt":"2026-11-03T18:47:25.723Z","metadataTrust":"untrusted"},{"serverName":"com.frapea/editor","endpointFingerprint":"cceef1cf3f47b142bc892cb7ab17e36107fdb6ee91dd5c5a86fba43270aefe34","name":"generate_captions","title":"Generate captions","description":"Generates animated captions from a spoken clip's transcript (the same generator as Frapea's UI): transcript words group into caption text clips over the clip's span, word-timed so the animation follows speech. One undo, and they share a captionGroupId — restyle them all via set_clip_properties with text.wholeCaptionGroup. Needs a transcript (get_transcript tells you). Returns the created clip ids.\nPLACEMENT: they JOIN the existing caption track whenever they fit in its gaps, and only open a new one when they would overlap (a second language, a second layer). So captioning four narration segments in four calls leaves ONE caption track, not four — no tidying needed afterwards for this. Call manage_tracks {action:'tidy'} at the end of the build for the empty tracks left by everything else.\nThey join the LOWEST caption track, so a picture layer you add ABOVE it after an earlier pass will cover them — captions render behind b-roll rather than looking wrong, which is the hardest kind of mistake to notice. Move the whole lane with manage_tracks {action:'merge'} if you want the captions on top.","inputSchema":{"type":"object","properties":{"projectId":{"type":"string","description":"Project id from get_projects."},"timelineId":{"type":"string","description":"Timeline containing the spoken clip."},"clipId":{"type":"string","description":"The spoken clip to caption."},"preset":{"type":"string","description":"Style preset: clean (default) | boldPop | karaoke | highlight | minimal | editorial."},"position":{"type":"string","description":"bottom (default) | top."},"textCase":{"type":"string","description":"original (default) | upper | lower."},"censorProfanity":{"type":"boolean","description":"Star out profane words."},"maxWordsPerCaption":{"type":"number","description":"Words per caption before a new one starts (default 4)."},"token":{"type":"string","description":"The session token `connect` returned. Pass it on every call — it says which browser to drive."}},"required":["projectId","timelineId","clipId","token"]},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false},"definitionHash":"41914d8ef6ddceb9e26f4bdb292eb1c67953d745daea9a484be75b02d288d62e","schemaStatus":"valid","origin":"official-registry","observedAt":"2026-11-03T18:47:25.723Z","metadataTrust":"untrusted"},{"serverName":"com.frapea/editor","endpointFingerprint":"cceef1cf3f47b142bc892cb7ab17e36107fdb6ee91dd5c5a86fba43270aefe34","name":"generate_voiceover","title":"Generate voiceover","description":"Generates an AI voiceover from a script — on-device with the free models, or in the cloud with ElevenLabs (the user's own key and credits). The WAV lands in the project's media library as a normal audio asset (with waveform and analysis), the script is stored as asset metadata, and a script-corrected word-level transcript is written so captions work immediately.\nNarration is best generated before the picture is cut: a script does not tell you how long it takes to SAY, so a narrated edit assembled first is built on guessed cut points that the real audio then breaks — every section, graphic and transition has to be retimed. Generate the narration, read its word timings with get_transcript, then lay picture against those frames.\nSegments read better than one block (e.g. hook / body / close, or one per section), each laid on the timeline separately. A single long generation comes out FLAT and evenly paced, everything pressed together at one energy; segmenting gives each part its own intent, puts natural air at the joins, and lets you redo one section instead of all of it. Write for the ear: short sentences, one idea each, LINE BREAKS between them — the strongest signal the model has to actually stop. See read_skill {topic:'voiceover'}. Async: returns {jobId, fileName} — fileName is the audio file's final name in the project's media/ folder, decided up front (WAV for local providers, MP3 for ElevenLabs). The job runs on the analysis MASTER tab and its request is persisted on disk: it survives tab closes and browser restarts, and get_job_status answers from disk even in a fresh session. Poll until done; the finished job also carries the asset's mediaRef. Voices/languages come from list_voiceover_models; a local model must be downloaded first (phase 'ready'), otherwise this returns PERMISSION_REQUIRED.\nPREMIUM (provider 'elevenlabs' — SPENDS THE USER'S CREDITS): check list_voiceover_models' `elevenlabs` status object first. Structured refusals you must handle: NO_API_KEY (no key stored — ask the USER to add their key in the Voiceover generator's ElevenLabs onboarding; never ask for, or pass, the key yourself), INSUFFICIENT_CREDITS (carries needed vs remaining — shorten the script or ask the user), CONSENT_REQUIRED (paid features are set to 'ask': a consent dialog with the cost is now open in Frapea and the error carries an actionId for the user to confirm; call await_user_action with that actionId, and on 'granted' retry this call with consentActionId set to it; 'denied' means drop it).\nAUDIO TAGS (ElevenLabs): inline bracket tags like [calm], [excited], [whispers] direct the delivery ONLY on models whose list_voiceover_models entry says supportsAudioTags: true (the v3 family). Every other model reads them ALOUD — so only write tags when the chosen model supports them. As a safety net, tags sent to a non-supporting model are stripped before synthesis and the success message says so.","inputSchema":{"type":"object","properties":{"projectId":{"type":"string","description":"Project id from get_projects."},"text":{"type":"string","description":"The script to speak (multi-line ok)."},"provider":{"type":"string","description":"TTS provider id from list_voiceover_models (default 'kokoro'; 'elevenlabs' = premium, needs the user's key + consent)."},"voice":{"type":"string","description":"Voice id from the provider's manifest (default: its first voice for the chosen language)."},"language":{"type":"string","description":"Language tag from the provider's manifest (e.g. 'en-us'). Ignored for ElevenLabs — its voices are multilingual."},"speed":{"type":"number","description":"Speaking rate multiplier (default 1). Local providers accept 0.5–2; ElevenLabs 0.7–1.2."},"modelId":{"type":"string","description":"ElevenLabs only: TTS model id from list_voiceover_models (default 'eleven_v3' — expressive, reads [calm]-style audio tags as directions; use 'eleven_multilingual_v2' only when the user asks for v2; turbo/flash cost half). Check the model's supportsAudioTags before writing [calm]-style tags into the text — non-v3 models would read them aloud."},"voiceSettings":{"type":"object","description":"ElevenLabs only: voice knobs, each optional. stability, similarityBoost and style are 0–1; speakerBoost is a boolean.","properties":{"stability":{"type":"number","description":"0–1; higher = steadier."},"similarityBoost":{"type":"number","description":"0–1; voice adherence."},"style":{"type":"number","description":"0–1; style exaggeration."},"speakerBoost":{"type":"boolean","description":"Speaker boost on/off."}}},"consentActionId":{"type":"string","description":"The actionId from a CONSENT_REQUIRED refusal, after await_user_action returned 'granted'. Good for one job."},"fileName":{"type":"string","description":"Optional base name for the audio file written into media/."},"token":{"type":"string","description":"The session token `connect` returned. Pass it on every call — it says which browser to drive."}},"required":["projectId","text","token"]},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":true},"definitionHash":"033dbee239739c1224d2757be16e460345c410caa137b96fbe8af87de1480d53","schemaStatus":"valid","origin":"official-registry","observedAt":"2026-11-03T18:47:25.723Z","metadataTrust":"untrusted"},{"serverName":"com.frapea/editor","endpointFingerprint":"cceef1cf3f47b142bc892cb7ab17e36107fdb6ee91dd5c5a86fba43270aefe34","name":"get_analysis_status","title":"Get analysis status","description":"How far the project's media analysis has got. Analysis runs BY ITSELF whenever media is connected. Returns percent (0-100) — 100 means nothing is OUTSTANDING, not that everything succeeded: `failed` lists items whose analysis failed (retry_analysis re-runs one) — done/total/pending item counts, runningItem {mediaRef, kind, progress}, etaSeconds (null until something has finished), blockedOnModels, and models {visual, speech}. Poll this while you wait; when blockedOnModels is above zero, call request_ai_models.","inputSchema":{"type":"object","properties":{"projectId":{"type":"string","description":"Project id from get_projects."},"token":{"type":"string","description":"The session token `connect` returned. Pass it on every call — it says which browser to drive."}},"required":["projectId","token"]},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"definitionHash":"d672840efcaeb0aef81858fd607d49bc2e2311a8dfd880d0d1cdb1d7730dc891","schemaStatus":"valid","origin":"official-registry","observedAt":"2026-11-03T18:47:25.723Z","metadataTrust":"untrusted"},{"serverName":"com.frapea/editor","endpointFingerprint":"cceef1cf3f47b142bc892cb7ab17e36107fdb6ee91dd5c5a86fba43270aefe34","name":"get_bug_report","title":"Prepare bug report","description":"Prepare a BUG REPORT for the user: it opens in Frapea (Problems → Create bug report) for them to read and save. The report itself is NOT returned to you — it would leave the user's machine before they have seen it. You get a summary: open problems, media counts, and how many of the user's own words remain in composition code. It contains versions, problems with engine details, the project's structure with names and texts replaced, provider files by public id, the user's own files only as encoding fingerprints, and motion code. timelineIds limits it to those timelines and what they nest.","inputSchema":{"type":"object","properties":{"projectId":{"type":"string","description":"Project id from get_projects (must be open in the editor)."},"timelineIds":{"type":"array","description":"Only these timelines and the timelines they nest (default: all)."},"token":{"type":"string","description":"The session token `connect` returned. Pass it on every call — it says which browser to drive."}},"required":["projectId","token"]},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"definitionHash":"642d419314a57f7265e83988fd3e17c35f382c78641318046f9d4d02650d9850","schemaStatus":"valid","origin":"official-registry","observedAt":"2026-11-03T18:47:25.723Z","metadataTrust":"untrusted"},{"serverName":"com.frapea/editor","endpointFingerprint":"cceef1cf3f47b142bc892cb7ab17e36107fdb6ee91dd5c5a86fba43270aefe34","name":"get_job_status","title":"Get job status","description":"Status of a background job started by a job-returning tool (generate_voiceover, verify_timeline, measure_loudness): {state: queued|running|done|failed|cancelled, progress: 0-1, detail, ...result fields such as mediaRef when done; verify_timeline, measure_loudness puts its report in `result`}. Poll every few seconds while state is 'queued' or 'running' (queued = waiting for the analysis master tab, which loads the models once for the whole browser). For analysis started by start_transcription or start_visual_indexing, poll get_analysis_status instead.","inputSchema":{"type":"object","properties":{"jobId":{"type":"string","description":"Id returned by the start_* tool."},"token":{"type":"string","description":"The session token `connect` returned. Pass it on every call — it says which browser to drive."}},"required":["jobId","token"]},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"definitionHash":"78e7e35b8daffab098c5d66c0e8eeba76f7ade0fe2565796438f8596f16e8fc4","schemaStatus":"valid","origin":"official-registry","observedAt":"2026-11-03T18:47:25.723Z","metadataTrust":"untrusted"},{"serverName":"com.frapea/editor","endpointFingerprint":"cceef1cf3f47b142bc892cb7ab17e36107fdb6ee91dd5c5a86fba43270aefe34","name":"get_media","title":"List media","description":"Lists the project's media library: mediaRef (the id clips use), name, kind (video/audio/image), durationSeconds, resolution, and sceneSamples — timestamps (seconds) where the visual indexer detected distinct moments. sceneSamples is a ready-made shot map: inspect or cut at those times first. Each asset also carries visualIndex and transcript objects: {phase: 'ready'|'pending'|'queued'|'running'|'failed'|'no-audio'|'disabled', error, attempts, sealed}. Analysis starts by itself and retries a failure a few times before sealing it. If a phase is 'failed', read `error` and decide: call retry_analysis to run just that one analysis again, or leave it. If 'disabled', call request_ai_models.\nVideo and audio assets also carry beats: {phase: 'ready'|'pending'|'failed'|'none', bpm, confidence}. These come from an ONSET detector (spectral flux): every energy rise — drum hits, plucks, syllables — not bars or downbeats. bpm is the tempo of those onsets, or null when there is no steady pulse (confidence 0–1 below the detector's 0.3, or too few onsets) — speech has onsets and no bpm. 'none' = no audio to analyze. Pass mediaRef to get ONE asset with beats.onsetsSec (source seconds, the first 2000; truncated + onsetCount say when there are more) — map them through the clip's trim and speed yourself.","inputSchema":{"type":"object","properties":{"projectId":{"type":"string","description":"Project id from get_projects."},"mediaRef":{"type":"string","description":"Optional: return only this asset, as {asset}, with its onset times. Omit to list every asset (no onset times)."},"token":{"type":"string","description":"The session token `connect` returned. Pass it on every call — it says which browser to drive."}},"required":["projectId","token"]},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"definitionHash":"531a8cb77a8576f94c8622b007844dcbf7cd0335ba771386520f7003343c4886","schemaStatus":"valid","origin":"official-registry","observedAt":"2026-11-03T18:47:25.723Z","metadataTrust":"untrusted"},{"serverName":"com.frapea/editor","endpointFingerprint":"cceef1cf3f47b142bc892cb7ab17e36107fdb6ee91dd5c5a86fba43270aefe34","name":"get_motion_composition","title":"Get motion composition","description":"Returns a motion composition's manifest and full TSX sources.","inputSchema":{"type":"object","properties":{"projectId":{"type":"string","description":"Project id from get_projects."},"compositionId":{"type":"string","description":"Composition id."},"token":{"type":"string","description":"The session token `connect` returned. Pass it on every call — it says which browser to drive."}},"required":["projectId","compositionId","token"]},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"definitionHash":"62b1de1fbc3e38b512bb524d19c11b9283288d545330c556988ad6ba108854f6","schemaStatus":"valid","origin":"official-registry","observedAt":"2026-11-03T18:47:25.723Z","metadataTrust":"untrusted"},{"serverName":"com.frapea/editor","endpointFingerprint":"cceef1cf3f47b142bc892cb7ab17e36107fdb6ee91dd5c5a86fba43270aefe34","name":"get_problems","title":"Get problems","description":"What has gone WRONG in the user's editor — renders that failed or stopped, footage that would not decode, chunks that could not be prepared for playback, exports that failed — each with WHERE (the timeline and frames, the source and its own frames, the footage and frame the engine could not decode) and the reason in the engine's own words.\nYou also hear about new problems for free: every other tool result carries a `problems` list of what changed since your last call. Call this for the whole history, or after a `moreProblems` count.\nA problem that is open on a timeline means that timeline does NOT play or export correctly there, whatever inspect_timeline showed: fix the named layer (e.g. update_motion_composition) to fix it. `state` is open | fixed | superseded (the thing it was about was edited and not yet re-rendered — NOT proof it works) | dismissed.","inputSchema":{"type":"object","properties":{"projectId":{"type":"string","description":"Project id from get_projects. Omit for every project in this browser."},"includeResolved":{"type":"boolean","description":"Also list problems that are no longer open (default false)."},"detail":{"type":"boolean","description":"Include the engine's raw diagnostic text per problem (default false — it can be long)."},"token":{"type":"string","description":"The session token `connect` returned. Pass it on every call — it says which browser to drive."}},"required":["token"]},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"definitionHash":"0864fd8b61ffaa1550ddea13aa095ac38f25d089e61ec322337cea4ff4bfa434","schemaStatus":"valid","origin":"official-registry","observedAt":"2026-11-03T18:47:25.723Z","metadataTrust":"untrusted"},{"serverName":"com.frapea/editor","endpointFingerprint":"cceef1cf3f47b142bc892cb7ab17e36107fdb6ee91dd5c5a86fba43270aefe34","name":"get_projects","title":"List projects","description":"Lists the projects Frapea knows on this machine: id, name, lastOpenedAt, and for a project stored in a folder on disk its `folder` (the directory's name — files you write into its `media/` subfolder join the pool by themselves). Call first to find the projectId every other tool needs. A project the browser has no permission for will surface PERMISSION_REQUIRED when used — relay the returned instruction to the user, then retry.\nALSO RETURNS `providers` — Pexels (stock video/photos), Freesound (music, ambience, SFX) and ElevenLabs (voiceover), each 'connected' | 'checking' | 'missing' | 'invalid'. These are the user's OWN API keys and they cannot be set from here.\nWhen any is not usable, `providersAdvice` is present: a short note for the user saying which and where they connect them (only the user can add a key). When everything is connected it is absent. A call that fails with PERMISSION_REQUIRED carries its own instruction for the user.","inputSchema":{"type":"object","properties":{"token":{"type":"string","description":"The session token `connect` returned. Pass it on every call — it says which browser to drive."}},"required":["token"]},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"definitionHash":"c17206c4cb9be4928bf256b3b33b409a278a91c5cea96af10ad0fc92352852b0","schemaStatus":"valid","origin":"official-registry","observedAt":"2026-11-03T18:47:25.723Z","metadataTrust":"untrusted"},{"serverName":"com.frapea/editor","endpointFingerprint":"cceef1cf3f47b142bc892cb7ab17e36107fdb6ee91dd5c5a86fba43270aefe34","name":"get_timeline","title":"Get timeline","description":"Reads a project's timeline structure: timelines (id, name, fps, resolution) with tracks and clips. THE USER CAN COPY A CLIP'S ID from the editor's right-click menu, so a bare UUID in their message names exactly one clip — call this with NO timelineId to search every timeline and match `clip.id`, rather than guessing from a name. Clips carry id, name, mediaRef, kind, startFrame, endFrame (exclusive), trimStartFrame and linkGroupId (linked A/V pairs share it), plus `look` (opacity, blend, transform, crop, keyframes, volume, fadeInFrames, fadeOutFrames) whenever any of it differs from the defaults — an untouched clip has no `look` key. Omit timelineId to get every timeline; frames are in that timeline's fps.","inputSchema":{"type":"object","properties":{"projectId":{"type":"string","description":"Project id from get_projects."},"timelineId":{"type":"string","description":"Optional single timeline to read."},"token":{"type":"string","description":"The session token `connect` returned. Pass it on every call — it says which browser to drive."}},"required":["projectId","token"]},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"definitionHash":"53b7fbc4cbb97aba11916c6d4539b6ab9dd1d99b47f02c429e0505d34b2fe1a6","schemaStatus":"valid","origin":"official-registry","observedAt":"2026-11-03T18:47:25.723Z","metadataTrust":"untrusted"},{"serverName":"com.frapea/editor","endpointFingerprint":"cceef1cf3f47b142bc892cb7ab17e36107fdb6ee91dd5c5a86fba43270aefe34","name":"get_transcript","title":"Get transcript","description":"Returns the word-level speech transcript of one media asset: language and words [{text, startSec, endSec}]. Only assets the user has transcribed have one — NOT_FOUND means ask the user to run Transcribe on the clip in Frapea. Use the timestamps to align cuts with what is being said.","inputSchema":{"type":"object","properties":{"projectId":{"type":"string","description":"Project id from get_projects."},"mediaRef":{"type":"string","description":"Asset reference from get_media."},"token":{"type":"string","description":"The session token `connect` returned. Pass it on every call — it says which browser to drive."}},"required":["projectId","mediaRef","token"]},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"definitionHash":"b417c5056be6298985614b3a320adc5c2b2a3da926dce4fd1a8fdd92aab3a410","schemaStatus":"valid","origin":"official-registry","observedAt":"2026-11-03T18:47:25.723Z","metadataTrust":"untrusted"},{"serverName":"com.frapea/editor","endpointFingerprint":"cceef1cf3f47b142bc892cb7ab17e36107fdb6ee91dd5c5a86fba43270aefe34","name":"insert_clips","title":"Insert clips","description":"Ripple-inserts media segments: everything at/after atFrame shifts right to make room (clips under the cut split). Same clip shape as add_clips. Use to splice a shot INTO an existing sequence without overwriting.","inputSchema":{"type":"object","properties":{"projectId":{"type":"string","description":"Project id from get_projects."},"timelineId":{"type":"string","description":"Target timeline."},"atFrame":{"type":"number","description":"Insertion point (timeline frame)."},"clips":{"type":"array","description":"[{mediaRef, sourceInSec, sourceOutSec}]"},"token":{"type":"string","description":"The session token `connect` returned. Pass it on every call — it says which browser to drive."}},"required":["projectId","timelineId","atFrame","clips","token"]},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false},"definitionHash":"c38d9e7d29a8f042d788a81d75585e7dab84adecbaf31f19c76a8fe2ca98af73","schemaStatus":"valid","origin":"official-registry","observedAt":"2026-11-03T18:47:25.723Z","metadataTrust":"untrusted"},{"serverName":"com.frapea/editor","endpointFingerprint":"cceef1cf3f47b142bc892cb7ab17e36107fdb6ee91dd5c5a86fba43270aefe34","name":"inspect_media","title":"Inspect source frames","description":"Looks INSIDE a source asset. Returns ONE contact sheet — every requested moment as a labelled cell in a single grid image — plus a per-cell fingerprint. Pass atSec (max 12 timestamps, seconds); combine with get_media's sceneSamples for an instant storyboard of the whole file. Shows the RAW source; use inspect_timeline for the composed cut.\nSTART WITH pixels:false WHEN YOU ARE ONLY CHECKING FOR EMPTINESS. The fingerprint answers 'is this black / flat / did it decode' for no image cost — nonBlankRatio near 0 is an empty or black frame, colorRange near 0 is a featureless one. Ask for pixels when you must judge WHAT is in the frame: subject, framing, legibility.","inputSchema":{"type":"object","properties":{"projectId":{"type":"string","description":"Project id from get_projects."},"mediaRef":{"type":"string","description":"Asset from get_media."},"atSec":{"type":"array","description":"Timestamps in seconds, max 12."},"pixels":{"type":"boolean","description":"False = fingerprints only, no image (default true)."},"columns":{"type":"number","description":"Grid columns (default 3, or one row if ≤3)."},"cellHeight":{"type":"number","description":"Target px height per cell (default 300). Shrunk automatically if the sheet would exceed the response budget — the reply says so when that happens."},"token":{"type":"string","description":"The session token `connect` returned. Pass it on every call — it says which browser to drive."}},"required":["projectId","mediaRef","atSec","token"]},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"definitionHash":"cfa51d4b744e7c536713eb8a58d35003d24cb6f568e36cb71a0bf0e789e61a4b","schemaStatus":"valid","origin":"official-registry","observedAt":"2026-11-03T18:47:25.723Z","metadataTrust":"untrusted"},{"serverName":"com.frapea/editor","endpointFingerprint":"cceef1cf3f47b142bc892cb7ab17e36107fdb6ee91dd5c5a86fba43270aefe34","name":"inspect_timeline","title":"Inspect timeline frames","description":"WATCHES the cut. Composites every video layer at each requested frame and returns ONE contact sheet — the frames as labelled cells of a single grid image — plus, per cell, the visibleClipIds that contributed pixels and a fingerprint. Pass frames (timeline frame numbers, max 12). Use it to check an edit: this is the only tool that shows what actually PLAYS, as opposed to what get_timeline says is arranged.\nSAMPLE THE CUT POINTS AND THE MIDDLE OF EACH SECTION, not only frame 0. An entrance animation that never resolves, a graphic clipped by its own box, an offline clip rendering black — all look perfect in get_timeline and are obvious here.\nUSE pixels:false FOR A CHEAP SWEEP. visibleClipIds plus nonBlankRatio confirms 'the right clip is in every slot and none of them is black' across a dozen positions with no image cost; spend pixels on the few frames where you must judge typography, framing or timing.","inputSchema":{"type":"object","properties":{"projectId":{"type":"string","description":"Project id from get_projects."},"timelineId":{"type":"string","description":"Timeline to render."},"frames":{"type":"array","description":"Timeline frame numbers, max 12."},"pixels":{"type":"boolean","description":"False = structure + fingerprints only, no image (default true)."},"columns":{"type":"number","description":"Grid columns (default 3, or one row if ≤3)."},"cellHeight":{"type":"number","description":"Target px height per cell (default 300). Shrunk automatically if the sheet would exceed the response budget — the reply says so when that happens."},"token":{"type":"string","description":"The session token `connect` returned. Pass it on every call — it says which browser to drive."}},"required":["projectId","timelineId","frames","token"]},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"definitionHash":"0a6b3a84227833ea6787388c2b9c2c206e56156cdb642d05cf2846677625c3ee","schemaStatus":"valid","origin":"official-registry","observedAt":"2026-11-03T18:47:25.723Z","metadataTrust":"untrusted"},{"serverName":"com.frapea/editor","endpointFingerprint":"cceef1cf3f47b142bc892cb7ab17e36107fdb6ee91dd5c5a86fba43270aefe34","name":"list_motion_compositions","title":"List motion compositions","description":"Lists the project's motion compositions: id, mediaRef (for add_clips), name, size, fps, duration and the editable props schema.","inputSchema":{"type":"object","properties":{"projectId":{"type":"string","description":"Project id from get_projects."},"token":{"type":"string","description":"The session token `connect` returned. Pass it on every call — it says which browser to drive."}},"required":["projectId","token"]},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"definitionHash":"0c4a649ecf823eb599f9143ce9853403c1c32e1000a0d52e368620ed3c3bc0af","schemaStatus":"valid","origin":"official-registry","observedAt":"2026-11-03T18:47:25.723Z","metadataTrust":"untrusted"},{"serverName":"com.frapea/editor","endpointFingerprint":"cceef1cf3f47b142bc892cb7ab17e36107fdb6ee91dd5c5a86fba43270aefe34","name":"list_voiceover_models","title":"List voiceover models","description":"The text-to-speech providers Frapea can generate voiceovers with. Returns providers[]: the FREE in-browser models straight from the TTS registry ({id, label, languages, voices: [{id, label, language, gender, grade}], modelAssets, state: {phase: needs-download|downloading|ready|error}}), plus the PREMIUM cloud provider flagged premium: true ({id: 'elevenlabs', label, premium, voices: [{id, label}], models: [{id, label, creditsPerCharacter, supportsAudioTags, note}]}, voices/models empty until a key is stored). supportsAudioTags tells you whether that model understands inline audio tags like [calm], [laughs], [whispers] as delivery directions (only the v3 family does); on every other model such tags are READ ALOUD, so send those models plain text — each model's `note` restates its rule. Also returns a top-level status object `elevenlabs`: {provider: 'elevenlabs', hasApiKey, credits: {used, limit, remaining} | null, consent: 'ask' | 'always'} — READ IT BEFORE choosing the premium provider, so you know whether a key exists, what the account can afford and whether a consent dialog will be involved. A free provider whose phase is 'needs-download' cannot generate until the user enables it in the Generators panel (Voiceover) — there is no tool to force the download; ask the user.","inputSchema":{"type":"object","properties":{"token":{"type":"string","description":"The session token `connect` returned. Pass it on every call — it says which browser to drive."}},"required":["token"]},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":true},"definitionHash":"440222f860238da1c894cb1f6ae422476d0777c2d756a39cd390448032110de1","schemaStatus":"valid","origin":"official-registry","observedAt":"2026-11-03T18:47:25.723Z","metadataTrust":"untrusted"}],"endpoints":[{"endpointFingerprint":"cceef1cf3f47b142bc892cb7ab17e36107fdb6ee91dd5c5a86fba43270aefe34","protocol":"streamable-http","status":"indexed","toolCount":50,"observedAt":"2026-11-03T18:47:25.723Z"}],"authentication":"unknown"},"connectionConfigurations":{"status":"ready","authentication":"not embedded","clients":{"Claude Desktop":{"mcpServers":{"com.frapea/editor":{"url":"https://app.frapea.com/mcp"}}},"Cursor":{"mcpServers":{"com.frapea/editor":{"url":"https://app.frapea.com/mcp"}}},"VS Code":{"servers":{"com.frapea/editor":{"type":"http","url":"https://app.frapea.com/mcp"}}}}},"resourceType":"mcp-server","callable":true,"runtime":{"callable":true,"protocols":["mcp"]},"interfaces":[{"protocol":"mcp","transport":"streamable-http","url":"https://app.frapea.com/mcp"}],"profile":{"apiVersion":"1","schemaVersion":"1","id":"mcp-server:com.frapea%2Feditor","resourceType":"mcp-server","canonicalUrl":"https://www.agentsjunction.com/api/v1/servers/com.frapea%2Feditor","name":"com.frapea/editor","description":"A video editor in your browser that your AI drives: cuts, captions, multicam, motion titles, export.","interfaces":[{"protocol":"mcp","transport":"streamable-http","url":"https://app.frapea.com/mcp"}],"capabilities":[],"identity":{"source":"official-registry","websiteUrl":"https://frapea.com","repositoryUrl":null,"version":"0.2.0"},"verification":{"state":"official","confidence":100},"operations":{"resourceType":"mcp-server","name":"com.frapea/editor","status":"online","lastCheckedAt":"2026-11-03T20:17:58.354Z","lastSuccessfulCheck":"2026-11-03T20:17:58.354Z","latencyMs":123,"consecutiveFailures":0,"isStale":false,"checks":{"endpointReachable":true,"protocolValid":true,"agentCardValid":null,"mcpHandshakeValid":true},"lastSeen":null,"lastSuccessfulInteraction":null,"lastHealthCheck":"2026-11-03T20:17:58.354Z","source":{"type":"health-check","url":null},"observedAt":"2026-11-03T20:17:58.354Z"},"security":null,"timestamps":{"createdAt":"2026-10-11T08:19:10.290Z","updatedAt":"2026-10-11T08:19:10.290Z","observedAt":"2026-11-03T20:17:58.354Z"},"compatibility":{"serverVersion":"0.2.0","protocolVersions":[{"protocol":"mcp","version":null}]}}}}