Raylight is a motion design video editor (raylight.app). These tools drive the user's LIVE editor tab: the user watches every edit happen on their canvas in real time.
This server's tools are: get_editor_status, list_projects, file_shared_project, get_editor_capabilities, get_project_overview, get_shot_details, render_stills, render_filmstrip, render_waveform, check_sync, get_design_guide, apply_edits, save_as_video, list_videos, update_share_page, list_templates, start_from_template, get_import_report, get_import_status, discard_import_session, score_import_fidelity, upload_media. A Raylight tool name outside this list does not exist on this server (it will fail with a hint pointing at the nearest real tool).
Workflow: call get_editor_status first. If no tab is connected, give the user the exact project link to open and wait. Once connected, get_project_overview describes the whole project (coordinate system, shots, styleDigest, media). Read a shot with get_shot_details before editing it, make changes with apply_edits, then LOOK at your work with render_stills or render_filmstrip and fix what reads wrong. apply_edits takes up to 200 edits per call and validates each one on its own (a malformed edit fails alone, the rest still run), so create and animate in ONE batch: give a creating op ref: "name" and write "$name" in any id field of a later edit instead of round-tripping ids; every creating result carries a structured created object, and the top level carries refs and createdIds. Batch flags: lint: false skips the composition lint; bypassTasteRules: true skips the taste guards (text stack, camera wobble, text size caps) while hard limits stay, for deliberate cases only. Motion you already have as sampled values (a traced curve, a spring you computed, another tool's output) goes in with set_keyframes and the editor fits the blocks; set the framing a shot opens on with set_camera_rest before adding moves; new frames carry their members through animation (membersFo
Protocol
Pass100/10020 / 20 pts
Connection, authentication, and protocol compatibility.
The title clearly communicates the tool’s action and subject. Keep it concise.
Description87/100
Check whether the user has a Raylight editor tab open and connected, and which project it is editing. Call this FIRST: every editing and rendering tool routes through that live tab. If nothing is connected, tell the user to open their project at raylight.app (use list_projects to give them the exact link) and wait for them to confirm.
Describe the returned information so the agent knows whether it will answer the request.
Inputs100/100
This tool declares no inputs, so argument descriptions are not needed.
No input fields.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "get_editor_status",
"title": "Check editor connection",
"description": "Check whether the user has a Raylight editor tab open and connected, and which project it is editing. Call this FIRST: every editing and rendering tool routes through that live tab. If nothing is connected, tell the user to open their project at raylight.app (use list_projects to give them the exact link) and wait for them to confirm.",
"inputSchema": {
"type": "object",
"properties": {}
},
"annotations": {
"title": "Check editor connection",
"readOnlyHint": true,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description95/100
List the user's Raylight projects (newest first, capped at 50) with an editUrl for each, plus the projects other people shared with them by link or invite that aren't already in one of the user's workspaces (sharedWithMe, with sharedBy and which of the user's workspaces each is filed under) and the user's workspaces. Works even when no editor tab is connected, so use it to tell the user exactly which link to open.
The description explains the capability, when to use it, and what to expect.
Inputs100/100
This tool declares no inputs, so argument descriptions are not needed.
No input fields.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "list_projects",
"title": "List projects",
"description": "List the user's Raylight projects (newest first, capped at 50) with an editUrl for each, plus the projects other people shared with them by link or invite that aren't already in one of the user's workspaces (sharedWithMe, with sharedBy and which of the user's workspaces each is filed under) and the user's workspaces. Works even when no editor tab is connected, so use it to tell the user exactly which link to open.",
"inputSchema": {
"type": "object",
"properties": {}
},
"annotations": {
"title": "List projects",
"readOnlyHint": true,
"openWorldHint": false,
"destructiveHint": false
}
}
Align the title with the capability actually described by this tool.
Description89/100
Choose which of the user's workspaces a project someone shared with them shows up in on their projects page. Only for sharedWithMe entries from list_projects. This is the user's own filing: it gives nobody access and the owner's project is not moved.
The description explains the capability, when to use it, and what to expect.
Inputs96/100
Input documentation gives an agent enough context to populate the arguments.
projectId
A sharedWithMe project id from list_projects.
Clear enough to supply this argument.
workspaceId
One of the user's workspace ids from list_projects.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "file_shared_project",
"title": "File shared project",
"description": "Choose which of the user's workspaces a project someone shared with them shows up in on their projects page. Only for sharedWithMe entries from list_projects. This is the user's own filing: it gives nobody access and the owner's project is not moved.",
"inputSchema": {
"type": "object",
"required": [
"projectId",
"workspaceId"
],
"properties": {
"projectId": {
"type": "string",
"description": "A sharedWithMe project id from list_projects."
},
"workspaceId": {
"type": "string",
"description": "One of the user's workspace ids from list_projects."
}
}
},
"annotations": {
"title": "File shared project",
"readOnlyHint": false,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description89/100
Return the full list of tools this server exposes and the recommended workflow. Optional discovery helper: you never need to call this before working, just start with get_editor_status. It exists so a capabilities query resolves cleanly instead of erroring.
Describe the returned information so the agent knows whether it will answer the request.
Inputs100/100
This tool declares no inputs, so argument descriptions are not needed.
No input fields.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "get_editor_capabilities",
"title": "List capabilities",
"description": "Return the full list of tools this server exposes and the recommended workflow. Optional discovery helper: you never need to call this before working, just start with get_editor_status. It exists so a capabilities query resolves cleanly instead of erroring.",
"inputSchema": {
"type": "object",
"properties": {}
},
"annotations": {
"title": "List capabilities",
"readOnlyHint": true,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description99/100
Read the whole project at a glance: the coordinate system and visible canvas bounds in world units (canvasWorldUnits.center + visibleX/visibleY; the center is NOT always (0,0)), every shot with its absolute start/duration and asset list, the styleDigest (every color in use with its roles, every font family with its weights: match these when adding elements so the project stays cohesive), the mediaLibrary (every image/video/audio available to the project: media used in shots plus everything uploaded to the Assets panel, usageCount 0 = uploaded but not yet placed; placeable via add_image/add_shot), savedEasings when the user has saved any (easings they kept from the timeline, applied by name with easingPreset: the count plus the newest few names, or unavailable when the library could not be loaded, which does not mean it is empty), where the user currently is (playhead, current shot, selection), and on projects imported from another app an import block (decision counts, fidelity score, and the renderedLayers that were placed as media because they could not be rebuilt natively, each with its assetId and reason code). A fresh copy of this exact data is already included in the user's message as project_state; call this tool only to RE-read after apply_edits changes the project, never at the start of a run. Pass section: "savedEasings" to get ONLY the user's complete saved easing library instead of the overview (every name, newest first, each with the curve or spring it plays in the form the easing op fields take); use it when the name you need is not among the newest few, or to read a saved curve's values.
The description explains the capability, when to use it, and what to expect.
Inputs88/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
section
Optional. Return only this part of the overview, in full, instead of the whole overview. savedEasings = every saved easing with its curve or spring.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
projectId
Optional: route this call to the editor tab that has this project open (ids from list_projects or get_editor_status). Omit to use the user's active tab.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "get_project_overview",
"title": "Read project overview",
"description": "Read the whole project at a glance: the coordinate system and visible canvas bounds in world units (canvasWorldUnits.center + visibleX/visibleY; the center is NOT always (0,0)), every shot with its absolute start/duration and asset list, the styleDigest (every color in use with its roles, every font family with its weights: match these when adding elements so the project stays cohesive), the mediaLibrary (every image/video/audio available to the project: media used in shots plus everything uploaded to the Assets panel, usageCount 0 = uploaded but not yet placed; placeable via add_image/add_shot), savedEasings when the user has saved any (easings they kept from the timeline, applied by name with easingPreset: the count plus the newest few names, or unavailable when the library could not be loaded, which does not mean it is empty), where the user currently is (playhead, current shot, selection), and on projects imported from another app an import block (decision counts, fidelity score, and the renderedLayers that were placed as media because they could not be rebuilt natively, each with its assetId and reason code). A fresh copy of this exact data is already included in the user's message as project_state; call this tool only to RE-read after apply_edits changes the project, never at the start of a run. Pass section: \"savedEasings\" to get ONLY the user's complete saved easing library instead of the overview (every name, newest first, each with the curve or spring it plays in the form the easing op fields take); use it when the name you need is not among the newest few, or to read a saved curve's values.",
"inputSchema": {
"type": "object",
"properties": {
"section": {
"enum": [
"savedEasings"
],
"type": "string",
"description": "Optional. Return only this part of the overview, in full, instead of the whole overview. savedEasings = every saved easing with its curve or spring."
},
"projectId": {
"type": "string",
"description": "Optional: route this call to the editor tab that has this project open (ids from list_projects or get_editor_status). Omit to use the user's active tab."
}
}
},
"annotations": {
"title": "Read project overview",
"readOnlyHint": true,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description97/100
Read one shot in full detail: every asset with transform (world units, degrees), MEASURED rendered footprint (sizeWorld: width/height plus left/right/top/bottom world edges; use these for spacing and overlap math, never guess sizes), lifetime (shot-local ms), entrance/exit, animation blocks, per-kind extras (crop and video trim, enabled layerEffects, frame size/clipContent, containerId = the frame a layer belongs to, icon identity on inserted icons, audio mix, material on extruded layers and bevel on extruded paths), groups with their members, their explicit pivot when one is set (absent = the measured visual center of the members), and group animation blocks, plus camera framings/moves (framings report rollDeg when set), enabled effects, and the key light for the shot (resting pose plus its animation blocks) when it has one. Fields at their rest defaults are OMITTED from asset summaries: no rotationDeg means {0,0,0}, no scale means 1, no opacity means 1, no entrance/exit means type "none", no name means unnamed, no depth on a shape, path, or text layer means flat (depth is reported in world units when the layer is extruded), no material means Matte, no bevel means square depth edges, no light means the shot is unlit, and only enabled effects are listed. Scale animation blocks report amount as amountUnit "multiplierOfRest"; the same multiplier basis add_animation accepts, so a block you wrote as 1.1 reads back as 1.1 and can be passed back to update_animation unchanged. Non-uniform scale reads back as a {x, y, z} object instead of a single number (read-only: update_asset.scale writes a uniform scalar, so adjust size via sizeWorld-aware position/size edits rather than by flattening a non-uniform scale). When the shot has geometric problems, the payload includes lint: findings for layers clipped by the frame edge, buried behind opaque layers in paint order, colliding text, frame members clipped away, near-miss alignment, and cramped gaps; fix warnings before adding anything new. Call this for any shot you intend to edit before editing it.
The description explains the capability, when to use it, and what to expect.
Inputs75/100
Clarify units, where to obtain this value, or conventions not already expressed in the schema.
shotId
Id of the shot to inspect
Clarify units, where to obtain this value, or conventions not already expressed in the schema.
projectId
Optional: route this call to the editor tab that has this project open (ids from list_projects or get_editor_status). Omit to use the user's active tab.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "get_shot_details",
"title": "Read shot details",
"description": "Read one shot in full detail: every asset with transform (world units, degrees), MEASURED rendered footprint (sizeWorld: width/height plus left/right/top/bottom world edges; use these for spacing and overlap math, never guess sizes), lifetime (shot-local ms), entrance/exit, animation blocks, per-kind extras (crop and video trim, enabled layerEffects, frame size/clipContent, containerId = the frame a layer belongs to, icon identity on inserted icons, audio mix, material on extruded layers and bevel on extruded paths), groups with their members, their explicit pivot when one is set (absent = the measured visual center of the members), and group animation blocks, plus camera framings/moves (framings report rollDeg when set), enabled effects, and the key light for the shot (resting pose plus its animation blocks) when it has one. Fields at their rest defaults are OMITTED from asset summaries: no rotationDeg means {0,0,0}, no scale means 1, no opacity means 1, no entrance/exit means type \"none\", no name means unnamed, no depth on a shape, path, or text layer means flat (depth is reported in world units when the layer is extruded), no material means Matte, no bevel means square depth edges, no light means the shot is unlit, and only enabled effects are listed. Scale animation blocks report amount as amountUnit \"multiplierOfRest\"; the same multiplier basis add_animation accepts, so a block you wrote as 1.1 reads back as 1.1 and can be passed back to update_animation unchanged. Non-uniform scale reads back as a {x, y, z} object instead of a single number (read-only: update_asset.scale writes a uniform scalar, so adjust size via sizeWorld-aware position/size edits rather than by flattening a non-uniform scale). When the shot has geometric problems, the payload includes lint: findings for layers clipped by the frame edge, buried behind opaque layers in paint order, colliding text, frame members clipped away, near-miss alignment, and cramped gaps; fix warnings before adding anything new. Call this for any shot you intend to edit before editing it.",
"inputSchema": {
"type": "object",
"required": [
"shotId"
],
"properties": {
"shotId": {
"type": "string",
"description": "Id of the shot to inspect"
},
"projectId": {
"type": "string",
"description": "Optional: route this call to the editor tab that has this project open (ids from list_projects or get_editor_status). Omit to use the user's active tab."
}
}
},
"annotations": {
"title": "Read shot details",
"readOnlyHint": true,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description98/100
SEE your work: renders 1-4 real frames of the final film at the given ABSOLUTE project times and returns them as images. Each frame is the true render the user will see: camera moves, entrance/exit animations mid-flight, animation blocks, effects, background, everything. Use this after apply_edits to review composition, spacing, legibility, and effect intensity with your own eyes, then fix what reads wrong and render once more to confirm. Pick decisive moments: just after entrances settle (shot start + ~700ms), the composed mid-shot hold, just before a cut. To judge motion over time, prefer render_filmstrip. Pass region to ZOOM onto part of the canvas at full resolution: use it to verify small text is legible and details are crisp (region frames render with camera moves suppressed, so also check the real framing without a region). The first content block is a JSON calibration record: with a region it is {regionView: {zoom, center, visibleWorld {minX,minY,maxX,maxY}, imagePx, pxPerWorldAtZ0}} computed from the framing actually rendered (the region is FIT inside the image at the project aspect, so visibleWorld is usually wider or taller than the rect you asked for; never assume pxPerWorld = imagePx.width / region.width), and without a region it is {frameView: {imagePx, canvasWorld, pxPerWorldAtRest}} (exact only while no camera move is active). Each still's label also carries layers: [{assetId, name, kind, px: {x, y, w, h}}], the resting pixel rect of every visible layer in that image (top-left origin, z=0 plane through the camera active at that time), so you can point at what you see. Morphs are the one motion the rects follow: a layer a morph has taken out of the picture at that time (a morph target before the flight lands, a layer after it has become its target) is left out, and a layer a morph is flying or landing is listed where the morph has it, marked morphing: true. A frame with a missing or half-loaded asset means media was still loading; render that time again.
The description explains the capability, when to use it, and what to expect.
Inputs29/100
2 of 6 inputs have descriptions. Add descriptions to the missing inputs, including where to obtain IDs and how to supply values.
timesMs
Absolute project times in ms to render (clamped inside the timeline)
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
region › centerX
Not provided
Missing description. Explain what this value means and how to supply it.
region › centerY
Not provided
Missing description. Explain what this value means and how to supply it.
region › width
Not provided
Missing description. Explain what this value means and how to supply it.
region › height
Not provided
Missing description. Explain what this value means and how to supply it.
projectId
Optional: route this call to the editor tab that has this project open (ids from list_projects or get_editor_status). Omit to use the user's active tab.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "render_stills",
"title": "Render frames",
"description": "SEE your work: renders 1-4 real frames of the final film at the given ABSOLUTE project times and returns them as images. Each frame is the true render the user will see: camera moves, entrance/exit animations mid-flight, animation blocks, effects, background, everything. Use this after apply_edits to review composition, spacing, legibility, and effect intensity with your own eyes, then fix what reads wrong and render once more to confirm. Pick decisive moments: just after entrances settle (shot start + ~700ms), the composed mid-shot hold, just before a cut. To judge motion over time, prefer render_filmstrip. Pass region to ZOOM onto part of the canvas at full resolution: use it to verify small text is legible and details are crisp (region frames render with camera moves suppressed, so also check the real framing without a region). The first content block is a JSON calibration record: with a region it is {regionView: {zoom, center, visibleWorld {minX,minY,maxX,maxY}, imagePx, pxPerWorldAtZ0}} computed from the framing actually rendered (the region is FIT inside the image at the project aspect, so visibleWorld is usually wider or taller than the rect you asked for; never assume pxPerWorld = imagePx.width / region.width), and without a region it is {frameView: {imagePx, canvasWorld, pxPerWorldAtRest}} (exact only while no camera move is active). Each still's label also carries layers: [{assetId, name, kind, px: {x, y, w, h}}], the resting pixel rect of every visible layer in that image (top-left origin, z=0 plane through the camera active at that time), so you can point at what you see. Morphs are the one motion the rects follow: a layer a morph has taken out of the picture at that time (a morph target before the flight lands, a layer after it has become its target) is left out, and a layer a morph is flying or landing is listed where the morph has it, marked morphing: true. A frame with a missing or half-loaded asset means media was still loading; render that time again.",
"inputSchema": {
"type": "object",
"required": [
"timesMs"
],
"properties": {
"region": {
"type": "object",
"required": [
"centerX",
"centerY",
"width",
"height"
],
"properties": {
"width": {
"type": "number",
"exclusiveMinimum": 0
},
"height": {
"type": "number",
"exclusiveMinimum": 0
},
"centerX": {
"type": "number"
},
"centerY": {
"type": "number"
}
},
"description": "Optional world-unit rect to zoom onto (clamped to the visible canvas, then FIT at the project aspect, zoom capped at the framer's ceiling). Use an asset's sizeWorld from get_shot_details, padded ~20%, to inspect that layer up close; read the exact visible extent and px/world back from the regionView block."
},
"timesMs": {
"type": "array",
"items": {
"type": "number"
},
"maxItems": 4,
"minItems": 1,
"description": "Absolute project times in ms to render (clamped inside the timeline)"
},
"projectId": {
"type": "string",
"description": "Optional: route this call to the editor tab that has this project open (ids from list_projects or get_editor_status). Omit to use the user's active tab."
}
}
},
"annotations": {
"title": "Render frames",
"readOnlyHint": true,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description98/100
SEE MOTION: renders 4, 6, or 9 evenly spaced real frames across a time span and returns them as ONE contact-sheet image (reading order left to right, top to bottom, each tile labeled with its absolute time). This is how you judge animation: whether an entrance cascade actually cascades, whether a camera move eases in, whether elements collide mid-flight, how a cut lands. Span one beat at a time: an entrance (shot start to start + ~1200ms), a camera move, the 600ms around a cut. Use 6 frames by default, 9 for a long or busy span, 4 for a quick check. Tiles are smaller than single stills; for fine detail or small-text legibility follow up with render_stills (optionally with a region).
The description explains the capability, when to use it, and what to expect.
Inputs94/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
startMs
Absolute span start in ms (clamped inside the timeline)
Clear enough to supply this argument.
endMs
Absolute span end in ms (clamped inside the timeline)
Clear enough to supply this argument.
frameCount
How many frames to sample (default 6)
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
projectId
Optional: route this call to the editor tab that has this project open (ids from list_projects or get_editor_status). Omit to use the user's active tab.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "render_filmstrip",
"title": "Render filmstrip",
"description": "SEE MOTION: renders 4, 6, or 9 evenly spaced real frames across a time span and returns them as ONE contact-sheet image (reading order left to right, top to bottom, each tile labeled with its absolute time). This is how you judge animation: whether an entrance cascade actually cascades, whether a camera move eases in, whether elements collide mid-flight, how a cut lands. Span one beat at a time: an entrance (shot start to start + ~1200ms), a camera move, the 600ms around a cut. Use 6 frames by default, 9 for a long or busy span, 4 for a quick check. Tiles are smaller than single stills; for fine detail or small-text legibility follow up with render_stills (optionally with a region).",
"inputSchema": {
"type": "object",
"required": [
"startMs",
"endMs"
],
"properties": {
"endMs": {
"type": "number",
"description": "Absolute span end in ms (clamped inside the timeline)"
},
"startMs": {
"type": "number",
"description": "Absolute span start in ms (clamped inside the timeline)"
},
"projectId": {
"type": "string",
"description": "Optional: route this call to the editor tab that has this project open (ids from list_projects or get_editor_status). Omit to use the user's active tab."
},
"frameCount": {
"enum": [
4,
6,
9
],
"type": "number",
"description": "How many frames to sample (default 6)"
}
}
},
"annotations": {
"title": "Render filmstrip",
"readOnlyHint": true,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description94/100
HEAR your work: renders the real project mix across a time span as a waveform + spectrogram strip (one image, timeline-aligned), with the span's visual beats - cuts, entrances, animation starts - overlaid as numbered markers and listed with absolute times. This is the audio filmstrip: use it after placing sounds to see whether transients land on the markers, whether a music bed leaves room for SFX (spectrogram shows competing energy), whether a sound is present at all, and where dead air sits. The mix is the true export mix: block envelopes, fades, per-layer effects, ducking, everything. Span one moment at a time (the ~1500ms around a cut or entrance) for precise reading, or a whole shot for the energy arc. For exact numeric offsets between sounds and beats, use check_sync; this tool is for seeing the shape.
Describe the returned information so the agent knows whether it will answer the request.
Inputs92/100
Input documentation gives an agent enough context to populate the arguments.
startMs
Absolute span start in ms (clamped inside the timeline)
Clear enough to supply this argument.
endMs
Absolute span end in ms (clamped inside the timeline)
Clear enough to supply this argument.
projectId
Optional: route this call to the editor tab that has this project open (ids from list_projects or get_editor_status). Omit to use the user's active tab.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "render_waveform",
"title": "Render waveform",
"description": "HEAR your work: renders the real project mix across a time span as a waveform + spectrogram strip (one image, timeline-aligned), with the span's visual beats - cuts, entrances, animation starts - overlaid as numbered markers and listed with absolute times. This is the audio filmstrip: use it after placing sounds to see whether transients land on the markers, whether a music bed leaves room for SFX (spectrogram shows competing energy), whether a sound is present at all, and where dead air sits. The mix is the true export mix: block envelopes, fades, per-layer effects, ducking, everything. Span one moment at a time (the ~1500ms around a cut or entrance) for precise reading, or a whole shot for the energy arc. For exact numeric offsets between sounds and beats, use check_sync; this tool is for seeing the shape.",
"inputSchema": {
"type": "object",
"required": [
"startMs",
"endMs"
],
"properties": {
"endMs": {
"type": "number",
"description": "Absolute span end in ms (clamped inside the timeline)"
},
"startMs": {
"type": "number",
"description": "Absolute span start in ms (clamped inside the timeline)"
},
"projectId": {
"type": "string",
"description": "Optional: route this call to the editor tab that has this project open (ids from list_projects or get_editor_status). Omit to use the user's active tab."
}
}
},
"annotations": {
"title": "Render waveform",
"readOnlyHint": true,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description99/100
MEASURE audio-visual sync: detects transient onsets in the real project mix and correlates them with the span's visual beats (cuts, entrances, animation starts). Returns JSON: per beat, the nearest onset and the signed offset in ms (positive = the sound lands LATE, negative = early, null = no sound marks that moment within 250ms), plus unmatched onsets (sounds that mark nothing visual). Use it after sound work to verify hits land where they should, then fix offsets with move_sound (impacts land ON the cut; whooshes typically lead it by ~60-120ms so the energy peak arrives with the visual). Omit startMs/endMs to check the whole timeline. A null onset on a beat you scored means the sound is missing, too quiet, or too soft-attacked to register - render_waveform shows which.
The description explains the capability, when to use it, and what to expect.
Inputs92/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
startMs
Optional absolute span start in ms (default 0)
Clear enough to supply this argument.
endMs
Optional absolute span end in ms (default: end of the timeline)
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
projectId
Optional: route this call to the editor tab that has this project open (ids from list_projects or get_editor_status). Omit to use the user's active tab.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "check_sync",
"title": "Check audio sync",
"description": "MEASURE audio-visual sync: detects transient onsets in the real project mix and correlates them with the span's visual beats (cuts, entrances, animation starts). Returns JSON: per beat, the nearest onset and the signed offset in ms (positive = the sound lands LATE, negative = early, null = no sound marks that moment within 250ms), plus unmatched onsets (sounds that mark nothing visual). Use it after sound work to verify hits land where they should, then fix offsets with move_sound (impacts land ON the cut; whooshes typically lead it by ~60-120ms so the energy peak arrives with the visual). Omit startMs/endMs to check the whole timeline. A null onset on a beat you scored means the sound is missing, too quiet, or too soft-attacked to register - render_waveform shows which.",
"inputSchema": {
"type": "object",
"properties": {
"endMs": {
"type": "number",
"description": "Optional absolute span end in ms (default: end of the timeline)"
},
"startMs": {
"type": "number",
"description": "Optional absolute span start in ms (default 0)"
},
"projectId": {
"type": "string",
"description": "Optional: route this call to the editor tab that has this project open (ids from list_projects or get_editor_status). Omit to use the user's active tab."
}
}
},
"annotations": {
"title": "Check audio sync",
"readOnlyHint": true,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description94/100
Raylight's motion design guide, distilled from the official hand-built templates (recreations of top-tier motion design from Linear, Apple, Fey, Revolut and others). Topic "craft-rules" returns the full craft ruleset (identical to the in-app director's brief; skip it if those rules are already in your system prompt). Topic "measured-craft" returns the aggregate timing/text/camera/effects numbers; a template topic returns that template's scene-by-scene beat sheet (exact arrival times, amounts, easings, camera beats, palette) plus preview images. The templates are the ground truth of what looks good: fetch the closest template's topic BEFORE authoring any scene's motion (not just when recreating a known look) and mirror or transplant its beats; its "Scene N" numbering matches apply_template_motion's sceneIndex. Topics: craft-rules, measured-craft, 3d-mobile-app, twitter-app, raylight-launch, airbnb-3d-app, nowak, liquid-glass, linear-agent, revolut-app, framer, raylight-agent-launch, raylight-marketplace, macbook-pro-around-linear, linear-hero, image-slide, manicule, limelight, drop-in, fey, lines, linear-reviews, prompt-button-press, bouncy-liquid-glass, apple-news, rubik-s-cube-liquid-glass.
The description explains the capability, when to use it, and what to expect.
Inputs65/100
Input documentation gives an agent enough context to populate the arguments.
topic
Guide topic. Defaults to "measured-craft" (the aggregate numbers).
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "get_design_guide",
"title": "Read design guide",
"description": "Raylight's motion design guide, distilled from the official hand-built templates (recreations of top-tier motion design from Linear, Apple, Fey, Revolut and others). Topic \"craft-rules\" returns the full craft ruleset (identical to the in-app director's brief; skip it if those rules are already in your system prompt). Topic \"measured-craft\" returns the aggregate timing/text/camera/effects numbers; a template topic returns that template's scene-by-scene beat sheet (exact arrival times, amounts, easings, camera beats, palette) plus preview images. The templates are the ground truth of what looks good: fetch the closest template's topic BEFORE authoring any scene's motion (not just when recreating a known look) and mirror or transplant its beats; its \"Scene N\" numbering matches apply_template_motion's sceneIndex. Topics: craft-rules, measured-craft, 3d-mobile-app, twitter-app, raylight-launch, airbnb-3d-app, nowak, liquid-glass, linear-agent, revolut-app, framer, raylight-agent-launch, raylight-marketplace, macbook-pro-around-linear, linear-hero, image-slide, manicule, limelight, drop-in, fey, lines, linear-reviews, prompt-button-press, bouncy-liquid-glass, apple-news, rubik-s-cube-liquid-glass.",
"inputSchema": {
"type": "object",
"properties": {
"topic": {
"type": "string",
"description": "Guide topic. Defaults to \"measured-craft\" (the aggregate numbers)."
}
}
},
"annotations": {
"title": "Read design guide",
"readOnlyHint": true,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description100/100
Copy the CURRENT project, which must be a design (a still: get_project_overview reports a designSize), into a NEW video project so it can be animated. The layers, lights, effects, and background carry over; the canvas snaps to the nearest video aspect ratio and the camera pulls back if needed so the whole design stays in frame. Returns the new project id and an editUrl. It does NOT open or switch to the new project: give the user the editUrl and keep working in the current project unless they switch. Pass "name" to title it (default: "<design name> (Video)"). Use when the user wants motion on a design; a design itself never plays.
The description explains the capability, when to use it, and what to expect.
Inputs88/100
Explain what happens when this optional value is omitted.
name
Optional name for the new video project.
Explain what happens when this optional value is omitted.
projectId
Optional: route this call to the editor tab that has this project open (ids from list_projects or get_editor_status). Omit to use the user's active tab.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "save_as_video",
"title": "Save design as video",
"description": "Copy the CURRENT project, which must be a design (a still: get_project_overview reports a designSize), into a NEW video project so it can be animated. The layers, lights, effects, and background carry over; the canvas snaps to the nearest video aspect ratio and the camera pulls back if needed so the whole design stays in frame. Returns the new project id and an editUrl. It does NOT open or switch to the new project: give the user the editUrl and keep working in the current project unless they switch. Pass \"name\" to title it (default: \"<design name> (Video)\"). Use when the user wants motion on a design; a design itself never plays.",
"inputSchema": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Optional name for the new video project."
},
"projectId": {
"type": "string",
"description": "Optional: route this call to the editor tab that has this project open (ids from list_projects or get_editor_status). Omit to use the user's active tab."
}
}
},
"annotations": {
"title": "Save design as video",
"readOnlyHint": false,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description99/100
List the user's exported videos (hosted share pages), newest first, capped at 50. Each entry has a shareId, title, shareUrl, status (ready or pending), visibility ("public" = anyone with the link can watch, "private" = only the user; a private video's shareUrl does not play for anyone else, so check it before handing out a link, and change it with update_share_page video.visibility, asking the user before making a video public), durationMs, viewCount, reactions (count per one-tap reaction viewers left), signups (new Raylight accounts that started on that video's page; each one counts toward the user's referral earnings), and the video's page settings (description, cta, allowRemix). Use it to find the shareId for update_share_page, or to hand the user a link to a video they already exported.
The description explains the capability, when to use it, and what to expect.
Inputs100/100
This tool declares no inputs, so argument descriptions are not needed.
No input fields.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "list_videos",
"title": "List exported videos",
"description": "List the user's exported videos (hosted share pages), newest first, capped at 50. Each entry has a shareId, title, shareUrl, status (ready or pending), visibility (\"public\" = anyone with the link can watch, \"private\" = only the user; a private video's shareUrl does not play for anyone else, so check it before handing out a link, and change it with update_share_page video.visibility, asking the user before making a video public), durationMs, viewCount, reactions (count per one-tap reaction viewers left), signups (new Raylight accounts that started on that video's page; each one counts toward the user's referral earnings), and the video's page settings (description, cta, allowRemix). Use it to find the shareId for update_share_page, or to hand the user a link to a video they already exported.",
"inputSchema": {
"type": "object",
"properties": {}
},
"annotations": {
"title": "List exported videos",
"readOnlyHint": true,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description98/100
Customize the user's share page: the Linktree-style page every exported video lands on (their name and avatar, a headline, the video, link buttons, colors). "page" edits the page itself and applies to every video: headline (one line under the name, max 80 chars), links (up to 8 {label, url} buttons; the full list replaces the old one), background and accent (#rrggbb; text color follows the background automatically), backgroundGradient (a gradient over the background color, or null for a flat color: {gradientType: "linear" | "radial" | "angular" | "diamond", angle in degrees where 0 = bottom to top, 90 = left to right, 180 = top to bottom, stops: 2 to 12 of {position 0-1, color #rrggbb}}; when setting one, also set background to its first stop), pattern (a faint repeating texture on top: "none", "dots", "grid", "warp" (a wavy grid symmetric around the middle of the screen), "waves", "mesh", "rings", "ripple", "blobs", "dither", "grain"), buttonStyle ("fill", "outline", "soft"), showDownload, showShareLinks (the copy link, X and LinkedIn buttons under the video), hideBranding (removes the "Made in Raylight" credit; Max plan only. Free pages always show a "Made in Raylight" block with a sign-up button and an end card when the video finishes; Hobby and Pro pages show a small credit in the footer). Free plans can set headline and links only; the other fields answer with an error naming the plan gate, so tell the user instead of retrying. "video" edits one video and needs shareId (from list_videos): title, description (under the video, max 500 chars), cta ({label, url} button above the links, null to remove), allowRemix (lets viewers open a live copy; only shows on a public video made from a project the user owns, video.remixAvailable in the result says whether it is live; turning it off kills the remix link on the page right away), visibility ("public" = anyone with the link can watch, "private" = only the user; ask before making a video public), showViewCount ("everyone" shows the view count on the page, "owner" hides it from visitors). Returns the resulting page. Use when the user asks to brand, personalize, or add links or a call to action to their share link.
The description explains the capability, when to use it, and what to expect.
Inputs2/100
1 of 22 inputs have descriptions. Add descriptions to the missing inputs, including where to obtain IDs and how to supply values.
page › headline
Not provided
Missing description. Explain what this value means and how to supply it.
page › links › items › label
Not provided
Missing description. Explain what this value means and how to supply it.
page › links › items › url
Not provided
Missing description. Explain what this value means and how to supply it.
page › background
Not provided
Missing description. Explain what this value means and how to supply it.
page › backgroundGradient › gradientType
Not provided
Missing description. Explain what this value means and how to supply it.
page › backgroundGradient › angle
Not provided
Missing description. Explain what this value means and how to supply it.
page › backgroundGradient › stops › items › position
Not provided
Missing description. Explain what this value means and how to supply it.
page › backgroundGradient › stops › items › color
Not provided
Missing description. Explain what this value means and how to supply it.
page › pattern
Not provided
Missing description. Explain what this value means and how to supply it.
page › accent
Not provided
Missing description. Explain what this value means and how to supply it.
page › buttonStyle
Not provided
Missing description. Explain what this value means and how to supply it.
page › showDownload
Not provided
Missing description. Explain what this value means and how to supply it.
page › showShareLinks
Not provided
Missing description. Explain what this value means and how to supply it.
page › hideBranding
Not provided
Missing description. Explain what this value means and how to supply it.
shareId
The video to edit when passing "video".
Clarify units, where to obtain this value, or conventions not already expressed in the schema.
video › title
Not provided
Missing description. Explain what this value means and how to supply it.
video › description
Not provided
Missing description. Explain what this value means and how to supply it.
video › cta › label
Not provided
Missing description. Explain what this value means and how to supply it.
video › cta › url
Not provided
Missing description. Explain what this value means and how to supply it.
video › allowRemix
Not provided
Missing description. Explain what this value means and how to supply it.
video › visibility
Not provided
Missing description. Explain what this value means and how to supply it.
video › showViewCount
Not provided
Missing description. Explain what this value means and how to supply it.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "update_share_page",
"title": "Customize share page",
"description": "Customize the user's share page: the Linktree-style page every exported video lands on (their name and avatar, a headline, the video, link buttons, colors). \"page\" edits the page itself and applies to every video: headline (one line under the name, max 80 chars), links (up to 8 {label, url} buttons; the full list replaces the old one), background and accent (#rrggbb; text color follows the background automatically), backgroundGradient (a gradient over the background color, or null for a flat color: {gradientType: \"linear\" | \"radial\" | \"angular\" | \"diamond\", angle in degrees where 0 = bottom to top, 90 = left to right, 180 = top to bottom, stops: 2 to 12 of {position 0-1, color #rrggbb}}; when setting one, also set background to its first stop), pattern (a faint repeating texture on top: \"none\", \"dots\", \"grid\", \"warp\" (a wavy grid symmetric around the middle of the screen), \"waves\", \"mesh\", \"rings\", \"ripple\", \"blobs\", \"dither\", \"grain\"), buttonStyle (\"fill\", \"outline\", \"soft\"), showDownload, showShareLinks (the copy link, X and LinkedIn buttons under the video), hideBranding (removes the \"Made in Raylight\" credit; Max plan only. Free pages always show a \"Made in Raylight\" block with a sign-up button and an end card when the video finishes; Hobby and Pro pages show a small credit in the footer). Free plans can set headline and links only; the other fields answer with an error naming the plan gate, so tell the user instead of retrying. \"video\" edits one video and needs shareId (from list_videos): title, description (under the video, max 500 chars), cta ({label, url} button above the links, null to remove), allowRemix (lets viewers open a live copy; only shows on a public video made from a project the user owns, video.remixAvailable in the result says whether it is live; turning it off kills the remix link on the page right away), visibility (\"public\" = anyone with the link can watch, \"private\" = only the user; ask before making a video public), showViewCount (\"everyone\" shows the view count on the page, \"owner\" hides it from visitors). Returns the resulting page. Use when the user asks to brand, personalize, or add links or a call to action to their share link.",
"inputSchema": {
"type": "object",
"properties": {
"page": {
"type": "object",
"properties": {
"links": {
"type": "array",
"items": {
"type": "object",
"required": [
"label",
"url"
],
"properties": {
"url": {
"type": "string"
},
"label": {
"type": "string"
}
}
}
},
"accent": {
"type": "string"
},
"pattern": {
"enum": [
"none",
"dots",
"grid",
"warp",
"waves",
"mesh",
"rings",
"ripple",
"blobs",
"dither",
"grain"
],
"type": "string"
},
"headline": {
"type": "string"
},
"background": {
"type": "string"
},
"buttonStyle": {
"enum": [
"fill",
"outline",
"soft"
],
"type": "string"
},
"hideBranding": {
"type": "boolean"
},
"showDownload": {
"type": "boolean"
},
"showShareLinks": {
"type": "boolean"
},
"backgroundGradient": {
"type": [
"object",
"null"
],
"required": [
"stops"
],
"properties": {
"angle": {
"type": "number"
},
"stops": {
"type": "array",
"items": {
"type": "object",
"required": [
"position",
"color"
],
"properties": {
"color": {
"type": "string"
},
"position": {
"type": "number"
}
}
}
},
"gradientType": {
"enum": [
"linear",
"radial",
"angular",
"diamond"
],
"type": "string"
}
}
}
},
"description": "Owner-level page settings; every key optional."
},
"video": {
"type": "object",
"properties": {
"cta": {
"type": [
"object",
"null"
],
"required": [
"label",
"url"
],
"properties": {
"url": {
"type": "string"
},
"label": {
"type": "string"
}
}
},
"title": {
"type": "string"
},
"allowRemix": {
"type": "boolean"
},
"visibility": {
"enum": [
"public",
"private"
],
"type": "string"
},
"description": {
"type": [
"string",
"null"
]
},
"showViewCount": {
"enum": [
"everyone",
"owner"
],
"type": "string"
}
},
"description": "Per-video settings; every key optional."
},
"shareId": {
"type": "string",
"description": "The video to edit when passing \"video\"."
}
}
},
"annotations": {
"title": "Customize share page",
"readOnlyHint": false,
"openWorldHint": true,
"destructiveHint": true
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description95/100
List Raylight's ready-made templates (free ones only), best first. Each entry has a slug, name, category, styles, duration, and slot counts, plus a designGuideTopic when a get_design_guide style card exists for it. Entries WITH a designGuideTopic are official hand-built Raylight templates; prefer those. Use this to pick a starting point for start_from_template, which beats building from an empty canvas: the motion craft comes pre-built and you swap in the user's content.
The description explains the capability, when to use it, and what to expect.
Inputs100/100
This tool declares no inputs, so argument descriptions are not needed.
No input fields.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "list_templates",
"title": "List templates",
"description": "List Raylight's ready-made templates (free ones only), best first. Each entry has a slug, name, category, styles, duration, and slot counts, plus a designGuideTopic when a get_design_guide style card exists for it. Entries WITH a designGuideTopic are official hand-built Raylight templates; prefer those. Use this to pick a starting point for start_from_template, which beats building from an empty canvas: the motion craft comes pre-built and you swap in the user's content.",
"inputSchema": {
"type": "object",
"properties": {}
},
"annotations": {
"title": "List templates",
"readOnlyHint": true,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description100/100
Create a NEW project for the user from a template (slug or id from list_templates; free templates only). Returns the project id and an editUrl. It does NOT open or switch to the new project: give the user the editUrl and keep working in the current project unless they switch. Pass "name" to title the project. Use when the user wants to start something new that a template fits; do not use to modify the current project.
The description explains the capability, when to use it, and what to expect.
Inputs82/100
Explain what happens when this optional value is omitted.
template
Template slug or id from list_templates.
Clear enough to supply this argument.
name
Optional name for the new project.
Explain what happens when this optional value is omitted.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "start_from_template",
"title": "Start from template",
"description": "Create a NEW project for the user from a template (slug or id from list_templates; free templates only). Returns the project id and an editUrl. It does NOT open or switch to the new project: give the user the editUrl and keep working in the current project unless they switch. Pass \"name\" to title the project. Use when the user wants to start something new that a template fits; do not use to modify the current project.",
"inputSchema": {
"type": "object",
"required": [
"template"
],
"properties": {
"name": {
"type": "string",
"description": "Optional name for the new project."
},
"template": {
"type": "string",
"description": "Template slug or id from list_templates."
}
}
},
"annotations": {
"title": "Start from template",
"readOnlyHint": false,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description99/100
Read the import report of a project that was brought in from After Effects, as it stands NOW: per source layer whether it became editable Raylight layers (native), was rendered to an image or video (bake-image / bake-video), was dropped or skipped, with reason codes and messages; the rendered media (bakes); warnings; the reference frames; the fidelity score when one was measured; and stats recomputed from the layers the project still has (stats.removed = imported layers the user has since deleted, which are left out of layers). Use it before rebuilding a rendered layer natively, and after, to confirm the report changed. Omit projectId to read the open project (in the app that includes unsaved edits); pass projectId (from list_projects) to read another project. Errors when the project was not imported, and the error says how the user starts an import.
The description explains the capability, when to use it, and what to expect.
Inputs99/100
Input documentation gives an agent enough context to populate the arguments.
projectId
The project to read (ids from list_projects). Omit for the open project.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "get_import_report",
"title": "Read import report",
"description": "Read the import report of a project that was brought in from After Effects, as it stands NOW: per source layer whether it became editable Raylight layers (native), was rendered to an image or video (bake-image / bake-video), was dropped or skipped, with reason codes and messages; the rendered media (bakes); warnings; the reference frames; the fidelity score when one was measured; and stats recomputed from the layers the project still has (stats.removed = imported layers the user has since deleted, which are left out of layers). Use it before rebuilding a rendered layer natively, and after, to confirm the report changed. Omit projectId to read the open project (in the app that includes unsaved edits); pass projectId (from list_projects) to read another project. Errors when the project was not imported, and the error says how the user starts an import.",
"inputSchema": {
"type": "object",
"properties": {
"projectId": {
"type": "string",
"description": "The project to read (ids from list_projects). Omit for the open project."
}
}
},
"annotations": {
"title": "Read import report",
"readOnlyHint": true,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description98/100
Check where the user's After Effects imports stand. Returns pendingSessions (imports started in the After Effects panel that have not finished: sessionId, projectId, projectName, the comp's name and size, createdAt, expiresAt, status pending or expired), project (when projectId is passed: whether it was imported and its live report), and howToImport (the exact steps the user follows in After Effects). You cannot start an import yourself: it needs After Effects open on the user's machine. When the user asks to import or re-import a comp, give them the howToImport steps, then call this again to see the session appear and get_import_report once it lands. Works without an open editor tab.
The description explains the capability, when to use it, and what to expect.
Inputs97/100
Input documentation gives an agent enough context to populate the arguments.
projectId
Optional project to report on (ids from list_projects).
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "get_import_status",
"title": "Check import status",
"description": "Check where the user's After Effects imports stand. Returns pendingSessions (imports started in the After Effects panel that have not finished: sessionId, projectId, projectName, the comp's name and size, createdAt, expiresAt, status pending or expired), project (when projectId is passed: whether it was imported and its live report), and howToImport (the exact steps the user follows in After Effects). You cannot start an import yourself: it needs After Effects open on the user's machine. When the user asks to import or re-import a comp, give them the howToImport steps, then call this again to see the session appear and get_import_report once it lands. Works without an open editor tab.",
"inputSchema": {
"type": "object",
"properties": {
"projectId": {
"type": "string",
"description": "Optional project to report on (ids from list_projects)."
}
}
},
"annotations": {
"title": "Check import status",
"readOnlyHint": true,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description97/100
Throw away a pending After Effects import the user started and will not finish (ids from get_import_status pendingSessions). Removes the stored capture and that import's uploads. The project is deleted only when that import created it and nothing was ever imported or built in it; a project that existed before, or already holds a finished import, is never deleted. Cannot be undone, so ask the user first. A finished import cannot be discarded.
The description explains the capability, when to use it, and what to expect.
Inputs50/100
Clarify units, where to obtain this value, or conventions not already expressed in the schema.
projectId
The pending session's projectId.
Clarify units, where to obtain this value, or conventions not already expressed in the schema.
sessionId
The pending session's sessionId.
Explain the meaning of this value, not just its name.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "discard_import_session",
"title": "Discard pending import",
"description": "Throw away a pending After Effects import the user started and will not finish (ids from get_import_status pendingSessions). Removes the stored capture and that import's uploads. The project is deleted only when that import created it and nothing was ever imported or built in it; a project that existed before, or already holds a finished import, is never deleted. Cannot be undone, so ask the user first. A finished import cannot be discarded.",
"inputSchema": {
"type": "object",
"required": [
"projectId",
"sessionId"
],
"properties": {
"projectId": {
"type": "string",
"description": "The pending session's projectId."
},
"sessionId": {
"type": "string",
"description": "The pending session's sessionId."
}
}
},
"annotations": {
"title": "Discard pending import",
"readOnlyHint": false,
"openWorldHint": false,
"destructiveHint": true
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description99/100
Measure how closely the open imported project matches After Effects: renders the project at each reference instant the importer saved, compares it with After Effects' own render of that instant, and stores the result on the project. Returns meanScore (0 to 1, structural similarity; 1 = identical) and frames [{ms, score, error?}], lowest first, so you can see WHEN the project drifts from the source and inspect those moments with render_stills. Run it after rebuilding a rendered layer to confirm the rebuild still matches. Needs the project open in the editor; errors when the project was not imported or has no reference frames. Read a previously stored score with get_import_report (fidelity).
The description explains the capability, when to use it, and what to expect.
Inputs99/100
Input documentation gives an agent enough context to populate the arguments.
projectId
Optional: route this call to the editor tab that has this project open (ids from list_projects or get_editor_status). Omit to use the user's active tab.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "score_import_fidelity",
"title": "Score import fidelity",
"description": "Measure how closely the open imported project matches After Effects: renders the project at each reference instant the importer saved, compares it with After Effects' own render of that instant, and stores the result on the project. Returns meanScore (0 to 1, structural similarity; 1 = identical) and frames [{ms, score, error?}], lowest first, so you can see WHEN the project drifts from the source and inspect those moments with render_stills. Run it after rebuilding a rendered layer to confirm the rebuild still matches. Needs the project open in the editor; errors when the project was not imported or has no reference frames. Read a previously stored score with get_import_report (fidelity).",
"inputSchema": {
"type": "object",
"properties": {
"projectId": {
"type": "string",
"description": "Optional: route this call to the editor tab that has this project open (ids from list_projects or get_editor_status). Omit to use the user's active tab."
}
}
},
"annotations": {
"title": "Score import fidelity",
"readOnlyHint": false,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description99/100
Put an image, video, or audio file into the project's asset library so apply_edits can place it (add_image {src}, add_shot {mediaSrc}, set_background {image}, add_sound {mediaSrc}). Use it whenever the user gives you a file or a link to one. Three ways to call it, chosen by which fields you pass:
1. {url}: a direct, publicly reachable link to the file itself (not a page that embeds it). The server fetches it (max 100 MB). This is the usual path.
2. {base64, mime}: the file bytes inline. Small files only (under 5 MB decoded; a data: URL is accepted).
3. {mime, bytes} with no url/base64: for a LOCAL file you can read with a shell but cannot inline. Returns an uploadUrl; PUT the raw bytes to it (curl -X PUT -H "Content-Type: <mime>" --upload-file <path> "<uploadUrl>"), then call upload_media again with {assetId} to finish. bytes must be the exact file size; for video over 100 MB also pass durationMs.
Bulk (up to 20 per call, one result per item in input order, one bad item never fails the others): {urls: [{url, name?, mime?}]} fetches several links (way 1) and returns results[]; {files: [{mime, bytes, name?, durationMs?}]} reserves several signed PUT slots (way 3) and returns uploads[] each with assetId + uploadUrl + headers + name; {assetIds: [...]} finishes several signed uploads in one call (safe to retry: already-finished ids return ok). Each item carries ok plus either the asset fields or an error; retry only the failed items.
Supported: image/png, image/jpeg, image/webp, image/gif, video/mp4, video/webm, video/quicktime, audio/mpeg, audio/wav, audio/mp4, audio/x-m4a, audio/aac. The file is measured (width/height, duration) and appears in the user's Assets panel immediately with an "Add to canvas" toast; the result's src, libraryRef, and name are all accepted by apply_edits. Videos are stored as given (no re-encode): prefer H.264 mp4.
The description explains the capability, when to use it, and what to expect.
Inputs48/100
9 of 16 inputs have descriptions. Add descriptions to the missing inputs, including where to obtain IDs and how to supply values.
projectId
Optional: the project to upload into (ids from list_projects). Omit to use the project open in the user's connected editor tab.
Clear enough to supply this argument.
url
Way 1: direct public http(s) link to the file.
Clear enough to supply this argument.
base64
Way 2: the file bytes as base64 (small files only).
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
mime
The file's mime type. Required for ways 2 and 3; optional with url. One of: image/png, image/jpeg, image/webp, image/gif, video/mp4, video/webm, video/quicktime, audio/mpeg, audio/wav, audio/mp4, audio/x-m4a, audio/aac.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
bytes
Way 3: exact file size in bytes.
Clarify units, where to obtain this value, or conventions not already expressed in the schema.
durationMs
Way 3, video/audio: duration in ms if known (ffprobe or file metadata). Required for videos too large for the server to measure.
Clear enough to supply this argument.
assetId
Way 3, second call: the assetId returned with the uploadUrl, once the PUT has succeeded. Safe to retry.
Clear enough to supply this argument.
name
Display name for the asset in the library (defaults to the URL's filename). apply_edits can reference the asset by this name.
Clear enough to supply this argument.
urls › items › url
Not provided
Missing description. Explain what this value means and how to supply it.
urls › items › name
Not provided
Missing description. Explain what this value means and how to supply it.
urls › items › mime
Not provided
Missing description. Explain what this value means and how to supply it.
files › items › mime
Not provided
Missing description. Explain what this value means and how to supply it.
files › items › bytes
Not provided
Missing description. Explain what this value means and how to supply it.
files › items › name
Not provided
Missing description. Explain what this value means and how to supply it.
files › items › durationMs
Not provided
Missing description. Explain what this value means and how to supply it.
assetIds
Bulk finish: the assetIds from a {files} call once every PUT has succeeded. Returns results[] per id; safe to retry with only the failed ids.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "upload_media",
"title": "Upload media",
"description": "Put an image, video, or audio file into the project's asset library so apply_edits can place it (add_image {src}, add_shot {mediaSrc}, set_background {image}, add_sound {mediaSrc}). Use it whenever the user gives you a file or a link to one. Three ways to call it, chosen by which fields you pass:\n1. {url}: a direct, publicly reachable link to the file itself (not a page that embeds it). The server fetches it (max 100 MB). This is the usual path.\n2. {base64, mime}: the file bytes inline. Small files only (under 5 MB decoded; a data: URL is accepted).\n3. {mime, bytes} with no url/base64: for a LOCAL file you can read with a shell but cannot inline. Returns an uploadUrl; PUT the raw bytes to it (curl -X PUT -H \"Content-Type: <mime>\" --upload-file <path> \"<uploadUrl>\"), then call upload_media again with {assetId} to finish. bytes must be the exact file size; for video over 100 MB also pass durationMs.\nBulk (up to 20 per call, one result per item in input order, one bad item never fails the others): {urls: [{url, name?, mime?}]} fetches several links (way 1) and returns results[]; {files: [{mime, bytes, name?, durationMs?}]} reserves several signed PUT slots (way 3) and returns uploads[] each with assetId + uploadUrl + headers + name; {assetIds: [...]} finishes several signed uploads in one call (safe to retry: already-finished ids return ok). Each item carries ok plus either the asset fields or an error; retry only the failed items.\nSupported: image/png, image/jpeg, image/webp, image/gif, video/mp4, video/webm, video/quicktime, audio/mpeg, audio/wav, audio/mp4, audio/x-m4a, audio/aac. The file is measured (width/height, duration) and appears in the user's Assets panel immediately with an \"Add to canvas\" toast; the result's src, libraryRef, and name are all accepted by apply_edits. Videos are stored as given (no re-encode): prefer H.264 mp4.",
"inputSchema": {
"type": "object",
"properties": {
"url": {
"type": "string",
"description": "Way 1: direct public http(s) link to the file."
},
"mime": {
"type": "string",
"description": "The file's mime type. Required for ways 2 and 3; optional with url. One of: image/png, image/jpeg, image/webp, image/gif, video/mp4, video/webm, video/quicktime, audio/mpeg, audio/wav, audio/mp4, audio/x-m4a, audio/aac."
},
"name": {
"type": "string",
"description": "Display name for the asset in the library (defaults to the URL's filename). apply_edits can reference the asset by this name."
},
"urls": {
"type": "array",
"items": {
"type": "object",
"required": [
"url"
],
"properties": {
"url": {
"type": "string"
},
"mime": {
"type": "string"
},
"name": {
"type": "string"
}
}
},
"maxItems": 20,
"description": "Bulk way 1: several direct public links fetched in one call. Returns results[] in the same order, each {ok, url, ...asset} or {ok: false, url, error}."
},
"bytes": {
"type": "integer",
"description": "Way 3: exact file size in bytes."
},
"files": {
"type": "array",
"items": {
"type": "object",
"required": [
"mime",
"bytes"
],
"properties": {
"mime": {
"type": "string"
},
"name": {
"type": "string"
},
"bytes": {
"type": "integer"
},
"durationMs": {
"type": "integer"
}
}
},
"maxItems": 20,
"description": "Bulk way 3: reserve a signed PUT slot per local file in one call. Returns uploads[] in the same order, each {ok, assetId, uploadUrl, headers, name} or {ok: false, name, error}; PUT each file, then finish them all with {assetIds}."
},
"base64": {
"type": "string",
"description": "Way 2: the file bytes as base64 (small files only)."
},
"assetId": {
"type": "string",
"description": "Way 3, second call: the assetId returned with the uploadUrl, once the PUT has succeeded. Safe to retry."
},
"assetIds": {
"type": "array",
"items": {
"type": "string"
},
"maxItems": 20,
"description": "Bulk finish: the assetIds from a {files} call once every PUT has succeeded. Returns results[] per id; safe to retry with only the failed ids."
},
"projectId": {
"type": "string",
"description": "Optional: the project to upload into (ids from list_projects). Omit to use the project open in the user's connected editor tab."
},
"durationMs": {
"type": "integer",
"description": "Way 3, video/audio: duration in ms if known (ffprobe or file metadata). Required for videos too large for the server to measure."
}
}
},
"annotations": {
"title": "Upload media",
"readOnlyHint": false,
"openWorldHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description92/100
Admin only. List grouped production errors from Raylight's web app, API and render worker (the self-hosted Sentry replacement). Each issue has a title, culprit (where it happens), level, status, lifetime event count, events and users affected inside the window, and a 14-day daily trend. Use admin_get_error_issue for the stack trace.
The description explains the capability, when to use it, and what to expect.
Inputs96/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
status
Triage status filter. Default unresolved.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
project
Only issues from this app. Omit for all.
Clear enough to supply this argument.
query
Case-insensitive text match on the title or culprit.
Clear enough to supply this argument.
sort
Sort order. Default last_seen. events/users sort by activity inside the window.
Clear enough to supply this argument.
days
Window in days: only issues seen in it are listed. Default 14.
Clear enough to supply this argument.
limit
Page size. Default 20.
Clear enough to supply this argument.
offset
Page offset. Default 0.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
The title clearly communicates the tool’s action and subject. Keep it concise.
Description94/100
Admin only. Full detail for one error issue: decoded stack trace with source excerpts from the newest stored event, breadcrumbs, tags, request, plus breakdowns by release, environment, browser, OS and page, the most affected users (with emails) and the daily trend.
The description explains the capability, when to use it, and what to expect.
Inputs88/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
issueId
Issue id from admin_list_error_issues.
Clear enough to supply this argument.
days
Window for counts and breakdowns. Default 14.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
The title clearly communicates the tool’s action and subject. Keep it concise.
Description92/100
Admin only. List an issue's individual occurrences, newest first: time, release, environment, user, page, browser, OS, and whether the full payload was kept (an issue keeps 20 full payloads per hour). Page by passing the previous response's nextCursor as `cursor`.
The description explains the capability, when to use it, and what to expect.
Inputs75/100
Explain the meaning of this value, not just its name.
issueId
Issue id.
Explain the meaning of this value, not just its name.
limit
Page size. Default 20.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
cursor
nextCursor from the previous page, for older events.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
The title clearly communicates the tool’s action and subject. Keep it concise.
Description89/100
Admin only. One occurrence with its full payload: decoded stack trace with source excerpts, breadcrumbs (what happened right before), tags, contexts and extra data.
The description explains the capability, when to use it, and what to expect.
Inputs89/100
Input documentation gives an agent enough context to populate the arguments.
eventId
Event id from admin_list_error_events.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
The title clearly communicates the tool’s action and subject. Keep it concise.
Description80/100
Admin only. Triage an issue. resolved: mark fixed; the next event reopens it and emails as a regression. ignored: keep counting but never alert or reopen. unresolved: reopen.
Explain mutations, irreversible effects, or prerequisites that matter before calling this tool.
Inputs50/100
Explain the meaning of this value, not just its name.
issueId
Issue id.
Explain the meaning of this value, not just its name.
status
The new status.
Explain the meaning of this value, not just its name.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "admin_update_error_issue",
"title": "Update error issue",
"description": "Admin only. Triage an issue. resolved: mark fixed; the next event reopens it and emails as a regression. ignored: keep counting but never alert or reopen. unresolved: reopen.",
"inputSchema": {
"type": "object",
"required": [
"issueId",
"status"
],
"properties": {
"status": {
"enum": [
"unresolved",
"resolved",
"ignored"
],
"type": "string",
"description": "The new status."
},
"issueId": {
"type": "string",
"description": "Issue id."
}
}
},
"annotations": {
"title": "Update error issue",
"readOnlyHint": false,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}
}
Loading score analytics…
Put your MCP to the test
A few tasks worth trying with this server, chosen from its reviewed tools. These have not been run.
01List projectsList the user's Raylight projects (newest first, capped at 50) with an editUrl for each, plus the projects other people shared with them by link or invite th…
02List exported videosList the user's exported videos (hosted share pages), newest first, capped at 50.
03List templatesList Raylight's ready-made templates (free ones only), best first.
04Read shot detailsRead one shot in full detail: every asset with transform (world units, degrees), MEASURED rendered footprint (sizeWorld: width/height plus left/right/top/bot…
05Read design guideRaylight's motion design guide, distilled from the official hand-built templates (recreations of top-tier motion design from Linear, Apple, Fey, Revolut and…
Want to run these tasks against your MCP server with us?
Raylight setup, tools, quality score, publishing readiness, and alternatives.
How do I add Raylight to Claude, ChatGPT, or Cursor?
Add Raylight to Claude, ChatGPT, or Cursor by connecting its remote MCP URL in each client's MCP settings. In Claude, add a custom connector. In ChatGPT, add an MCP app. In Cursor, add an MCP server under Settings. The MCP URL is https://api.raylight.app/mcp.
Is Raylight MCP ready for ChatGPT and Claude?
As of October 14, 2026, Raylight scores 96/100 on Manufact's MCP publishing checklist. The scan meets ChatGPT publishing checks and meets Claude publishing checks. Passing these checks does not guarantee marketplace approval.
How clear is Raylight's MCP tool documentation?
As of October 14, 2026, Raylight scores 77/100 in Manufact's review of tool titles, descriptions, input and output schemas, and behavior annotations. The review covers 27 of 27 discovered tools. The quality score measures documentation clarity; runtime behavior and marketplace readiness require separate checks.
What are the best alternatives to Raylight?
As of October 15, 2026, alternatives to Raylight in design-creative on the Manufact MCP catalog include Motion, Image Generation, Runway, pmw-mcp, and SlidesGPT.
How can Raylight improve its MCP documentation?
update_share_page is the lowest-scoring reviewed tool at 59/100. No output schema is declared. Add one for structured results so clients can interpret returned fields. Open its review for feedback and a copyable fix prompt, then rerun the documentation review after updating your tool metadata.
Not your MCP?
Review any public or OAuth MCP server for protocol compatibility, tool documentation, and ChatGPT and Claude publishing readiness. No account required.