MCP App Store
by KeenEthics

Overview

Use ChatGPT with Martini to navigate visual project boards, organize scenes and shot ideas, manage subjects and reference assets, add production notes, and structure filmmaking work on a shared canvas.

Tools

add_comment

ChatGPT
Add a review comment. Pass anchor (canvas/node/clip/time) to start a new thread, or threadId to reply to one. Reuse the caller-generated commentId on network retries. Your comment is attributed to the signed-in user with your agent kind badged — never pretend to be a human. After completing work a thread asked for, reply here with what you did, then resolve_comment.

add_subjects_to_collection

ChatGPT
Add one or more subjects to an existing collection. The subjects are appended to the current member list and may come from any canvas.

add_workflow_to_canvas

ChatGPT
Place a copy of a saved workflow on a canvas: fresh Action cards wired to fresh bins (plus any notes/variables the briefs reference), laid out and ready to run. Omit canvasId to create a new canvas named after the workflow. Bins saved with their contents ("Include contents" — update_bins includeContents on the source canvas before saving) arrive filled; every other input bin arrives empty — fill those on the new canvas, then run_workflow. The result names the agent skills the kit ships; read them first. To run a saved workflow without placing it yourself, call run_workflow with its saved workflowId; omit bins to keep presets and supply only required inputs or deliberate replacements.

analyze_video_audio

ChatGPT
Judge a clip's audio track without downloading it: speech segments (start/end), integrated loudness (LUFS) and true peak, RMS level — and, with referenceAudioAssetId, where that take sits in the clip (best cross-correlation lag, peak-to-sidelobe ratio, z-score) plus head/mid/tail lags and a time-stretch ratio so re-timing is visible, including per-phrase lags and inserted holds, with an optional framingChanges pass for framing changes and a 10 Hz motion series. Waveform alignment is sample-accurate; the envelope alignment survives re-timing at 10 ms. Read-only, computed server-side with ffmpeg, cached per asset checksum.

analyze_video_frames

ChatGPT
Judge a clip's pictures without a contact sheet: a black-frame scan at the timecodes you name (mean and spread of gray, share of black pixels, a black verdict per frame — cut points and join edges), and, with firstFrameReferenceAssetId / lastFrameReferenceAssetId, whether the clip's first and last frames are the stills it was staged from (64-bit difference-hash distance, gray correlation, match / similar / different). Read-only, computed server-side from the same frames inspect_video samples, cached per asset checksum. Use inspect_video when you need to see the motion itself.

apply_timeline_edit

ChatGPT
Apply or dry-run a batched timeline edit. Positions snap to 24 fps frames (2000 ticks) while source lengths do not: chain clips with insert sequential: true rather than computing starts. An update batch is one transaction (clips it moves are overlap-checked against the finished result, in any order). "end" means the sequence end on start/at/timeRange and the source end on trimOut, and is rejected on durations, gaps, and fades. Includes clip gain/fades and volumePoints (clip-local time, gainDb or null for silence, linear/hold curve), loop (audio clips only; repeats the source window to fill duration, envelope runs once), constant speed or fitDuration (preserves source bounds; linked audio follows, pitch preserved by default), track gain/pan, and sequence frame dimensions and Fit/Fill through update.sequence.frame. Read context first and pass its revisionToken as ifRevision so concurrent human edits fail cleanly; omitting ifRevision preserves last-write-wins compatibility. A dry run returns the revisionToken to use for guarded apply. For applied mutations, reuse one caller-generated operationId across network retries so Martini returns the original result without applying twice. Actions: assemble, insert, update, remove, reorder, normalize, split, createSequence, duplicateSequence.

approve_run

ChatGPT
The Go for a run parked at awaiting_approval: get_run shows the parked Action's plan (units, planned outputs, olive estimate); approve_run lets it execute. Approval binds to that plan's hash, so consent never carries over to a plan re-derived after the inputs changed. A run started with a budget (run_workflow) keeps it as a soft marker: the Go proceeds whatever the estimate, and a higher oliveBudget with the Go raises the marker get_run reports spend against (refused below the current budget). A canvas-started run has no budget of its own; its Go arms the spend rail at spend so far plus 1.5× the estimate. A rehearsal parks again before its next Action regardless, and its Go first re-reads the Instructions files from the project, so a fix lands on this Action. Refused when the run is not awaiting approval, the plan has no units, the plan was already approved (a second Go), or the run was cancelled meanwhile. This is how a rehearsal started over MCP is driven end to end without a person on the canvas.

arrange_workflow

ChatGPT
Tidy an existing workflow: re-run the auto-layout over Action cards, the bins they read/write, and the assets their briefs pin, moving them to clear canvas space. Actions chain left to right in run order with input bins and pinned assets above and outputs directly under their last writer. A pinned asset filed in an unwired bin moves with that bin. Notes, variables, untagged assets, and bins used by other Actions stay where they are.

cancel_run

ChatGPT
Cancel a run for good; a cancelled run cannot be resumed (start a new one). The run is marked cancelled at once and its open Actions are closed. A busy executor learns of it within about a minute (its next lease renewal, or sooner at its next generate_nodes): the agent session is aborted, generations still in flight are cancelled at the provider and their olives refunded (finished ones keep their output and cost), and a generate_nodes batch already mid-submit still lands and is then cancelled the same way. Refused once the run has completed or failed; cancelling a cancelled run is a no-op.

check_storage_reachability

ChatGPT
Preflight check before the first upload OR download in a session. Confirms the agent's environment can reach R2 for PUT requests (upload_asset_init / upload_asset_init_batch) and GET requests (get_asset_download_url's presigned URLs). Curl the returned probeUrl from your environment: a response containing a cf-ray header means R2 is reachable. Any other outcome — curl error, HTTP 000, X-Proxy-Error: blocked-by-allowlist header, or missing cf-ray — means storage is blocked. In that case, do not call upload_asset_init or fetch get_asset_download_url URLs, and print suggestion.message to the user verbatim so they can unblock. Call once per session.

checkpoint_timeline

ChatGPT
Create an immutable R2 checkpoint of the selected sequence and its direct tracks/clips before a risky edit. Nested sequence contents are intentionally excluded so restoring a parent never erases newer child-sequence work. operationId makes retries safe.

create_actions

ChatGPT
Create Action cards on a Martini canvas. An Action is a plain-language brief that reads assets, notes, variables, or bins and writes into output bins; the brief IS the wiring — its @-refs decide the input and output edges, and how many times it runs is decided by a plan pass at run time, not configured here. An Action may read and write the same bin for generate-then-review, seeing existing takes as inputs and adding new takes there; make such an Action idempotent: check what already exists before generating. Prefer BIN inputs over fixed asset refs: create an input bin (create_bin) so the user can drag material in and re-run — an asset ref pins the Action to one specific item forever. This authors the Actions but does not run them or spend olives. To change an existing Action, use update_actions instead of re-creating it — get_canvas_children (actions section) lists the existing cards with their ids.

create_bin

ChatGPT
Create a root-level canvas bin. MCP intentionally does not support creating bins inside bins.

create_canvas

ChatGPT
Create a new canvas in the project and return its deep link.

create_json_file

ChatGPT
Upload JSON as a File on the canvas. Accepts an ordinary JSON value; embedded images are preserved in immutable storage, never in the canvas document. Does not start generation. Use a binId to add the File to a bin.

create_node

ChatGPT
Create an empty draft asset-backed node on the board. This seeds editable draft settings but never starts generation or spends credits.

create_node_and_generate

ChatGPT
Create a planned shot node and run an approved generation for it. Requires user approval of the model, prompt, target shot, count, and estimated cost.

create_nodes

ChatGPT
Create multiple empty asset-backed nodes in one server-owned layout pass. For nodes without explicit positions, Martini uses rendered node widths and default canvas spacing instead of source asset pixel dimensions.

create_nodes_and_generate

ChatGPT
Create multiple planned shot nodes and run approved generations for them. Requires one user approval for the whole batch.

create_project

ChatGPT
Create a new Martini project for the authenticated user. Optionally pass a teamId to create a private team project. After creating an empty project, use create_canvas before adding board content.

create_subject

ChatGPT
Create a new subject (prop, animal, character, etc.) on a project board. Subjects are reusable visual references that keep characters and objects consistent across shots. Provide image URLs to make the subject immediately usable for generation.

create_subject_collection

ChatGPT
Group subjects into a named collection. The collection gets a home canvas for its card placement; member subjects may come from any canvas.

create_text_note

ChatGPT
Create a canvas text note from plain text. This does not start generation or spend credits. Position is absolute canvas coordinates; content is stored as paragraph text.

create_variable

ChatGPT
Create a reusable text variable on a canvas. Variables are prompt text snippets, not visual labels for board organization. Reference it in prompts as @{variableId:variableName}; it expands to its value at generation time. Names are unique within the project — a numeric suffix is auto-appended on collision.

crop_image

ChatGPT
Crop operations on completed images — deterministic pixel extraction, no generation, no credits. Action "create" authors 1-16 cropped child image nodes from a source image (rects in natural pixels of the source; read its width/height with get_asset first); crops land on the board as completed image nodes (operation "crop") parented to the source. Action "recrop" re-points an existing crop node at a new rect of its PARENT image; the previous crop is kept in the node's cropRevisions history. Action "restore" re-points a crop node at an earlier cropRevisions entry (find revision IDs with get_asset).

delete_bins

ChatGPT
Delete empty canvas bins. A bin that still contains nodes is refused with its member list — move members out first (move_nodes / move_node_to_bin). A bin an Action reads or writes is refused too: remove it from the Action with update_actions first. Nested empty bins can be deleted with their parent in the same call. Use dryRun to preview.

delete_nodes

ChatGPT
Delete empty DRAFT nodes (never generated or uploaded media) from the board: the draft record, its position, draft settings, and display name are removed, bin membership and variation stacks are tidied. Nodes with media are refused unless includeMedia is true (board-only removal, clips included; files stay in storage). Use dryRun to preview.

delete_text_notes

ChatGPT
Delete text notes from the board (the note record and its position; bin membership is tidied). Use dryRun to preview.

diagnose_camera_motion_guide

ChatGPT
Read-only diagnostics for a camera-control draft or rendered node. Returns validation status, expected guide branch, related media HEAD checks, guide failure metadata, raw cameraMotion metadata, and draft settings.

duplicate_nodes

ChatGPT
Duplicate asset nodes by reference: new nodes pointing at the SAME stored media (nothing is re-generated, re-uploaded, or copied in storage — exactly like project duplication). Fresh shot numbers; draft settings and display names are copied; parent/variation lineage is not. Use for "same assets, different arrangement" views, e.g. mirroring shots onto a second canvas sorted another way. targetCanvasId defaults to the source canvas; placement (incl. bin "new:<name>" + columns) applies to every copy.

edit_library

ChatGPT
THE library write tool — applies an ordered batch of library commands (the same seam the Martini UI uses). Everything except bulk file ingestion (import_library_assets) goes through here. Commands (each { type, ...fields }; creates auto-fill ids/slugs/revs/timestamps — pass only what you know): - collection.create {collection:{name, type?, folder?, tags?}} — a collection is one reusable subject (character, prop, location, style) - collection.rename {id,name} · collection.delete {id} (soft, cascades to assets) · collection.restore {id} · collection.move {id,folder} (folder path or null=unfiled) · collection.setTags {id,tags} · collection.setHero {id,assetId|null} · collection.setDescription {id,description} (free-form notes shown under the title) - folder.create {path} ('Night Shift' or nested 'Night Shift/Cast') · folder.rename {path,next} · folder.delete {path} (collections become unfiled) - asset.create {asset:{collectionId, kind:'image'|'video'|'audio'|'model3d'|'text', name, src (https URL; '' for text), textValue? (text fragments)}} — prefer import_library_assets for bulk/external files - asset.rename {id,name} · asset.move {ids,collectionId} · asset.delete {ids} · asset.restore {ids} - asset.setValue {id,key,value} — set a property value (key from get_library; select values are option IDs; null clears) - asset.update {id,patch:{src?,textValue?,...}} — patch.src replaces media and appends a version to history automatically - asset.setCurrentVersion {id,versionId} — restore an older version (pointer move, never rewrites history) - property.create {property:{label, type:'select'|'text'|'number'|'checkbox', options?:[{value,color?}], config?:{multiline?,precision?}}} - property.rename {key,label} · property.delete {key} · property.restore {key} · property.addOption {key,option:{value,color?}} · property.removeOption {key,optionId} (hard delete) · property.renameOption {key,optionId,value} - tag.addToVocab {tags} · view.save {view:{name,definition:{collectionId,layout,filters?,groupBy?,sort?,axes?}}} · view.update {id,name?,definition?} · view.delete {id} - link.setProject {projectId,collectionIds} — FULL REPLACEMENT of the project's enabled set; prefer link_library_to_project for add/remove - batch {label, commands:[…]} groups sub-commands under one label · asset.move accepts perAssetTarget {assetId→collectionId} for per-asset destinations · folder.delete accepts restoreCollections {collectionId→path|null} to re-file displaced collections - Cross-referencing within one batch: supply your OWN ids (any unique short string) on creates instead of relying on autofill — e.g. collection.create {collection:{id:"cast0001", name:…}} then asset.create {asset:{collectionId:"cast0001", …}} in the same commands array. createdIds in the response lists the ids assigned to your creates; a create that hits an existing live id is a no-op revive (nothing overwritten) — confirm with a read when reusing ids. - Value semantics: asset.setValue with a value whose type mismatches the property is a SILENT no-op (revs unchanged); unknown property keys are written as-is (legacy attrs) — read get_library properties first. property.removeOption hard-deletes the option but does NOT clear asset attrs still holding its id — re-set or clear those yourself. Rules: never modify collections with sample:true (community samples — copy what you need instead). Deletes are soft and restorable except property options. collection.delete cascades to its assets but collection.restore does NOT restore them — get_library_collection on the deleted collection returns the asset.restore command to pair with it. collection.setHero should point at an image or video asset. Unknown ids are no-op successes: applied counts commands executed, revs lists rows that actually changed — check revs to confirm a mutation landed.

enhance_draft

ChatGPT
Enhance a completed FLUX.3 or Seedance 2.5 draft to 1080p as a new version of the same node. Call without approval for eligibility and exact olive cost; present it, then re-call with approval and planHash to spend. FLUX drafts can be enhanced once. Seedance drafts can be enhanced until enhanceUntil (seven days from provider creation); check get_board_assets or get_asset. Creative settings are fixed by the draft. Seedance draft creation is available on the native BytePlus and fal routes (not on the US-hosted seedance-2.5-us models).

export_timeline_xml

ChatGPT
Start a durable Premiere Pro XMEML bundle export from current collaborative timeline state. The ZIP contains XML plus original media; clip levels and fades and track pan travel as Audio Levels / Audio Pan filters. Returns immediately with an exportId; poll get_timeline_delivery_status. operationId makes identical retries safe, but an interrupted worker requires a new operationId.

extract_video_frame

ChatGPT
Extract a durable JPEG still from a completed video asset. By default this creates only a reusable R2-backed frame file, not a visible canvas node. Optionally attach the frame to a draft start/end slot or create a visible video-frame image node.

generate

ChatGPT
Generate media for an existing shot after the user has approved the model, prompt, target shot, count, and estimated cost.

generate_nodes

ChatGPT
Generate existing draft nodes from their staged settings (model, prompt, frames, references). First call without batchApproval: Martini returns a server-computed olive estimate and generates nothing. Present the plan and total to the user, then re-call with batchApproval and the returned planHash. Submission has per-node error isolation; poll with get_jobs. Board variables expand at submit time. FLUX.3 drafts staged with flux3RenderQuality "draft" are estimated and billed at draft rates, and auto-duration drafts are quoted at their full hold with the unused seconds refunded on completion.

get_asset

ChatGPT
Get one asset with full stored metadata, deep links, and its canvas position. Use this after get_board_assets or get_canvas when you need deep detail on a specific node. Use the imageUrl field for referenceImages — do not construct URLs from the id.

get_asset_download_url

ChatGPT
Return a short-lived presigned URL for downloading a completed asset file. Use this when the user wants to save an asset to disk or needs a direct file URL for export/download workflows. Fetch the returned URL promptly before it expires.

get_asset_draft_settings

ChatGPT
Get the full draft settings for one asset. Use this only when you need the asset-specific generation configuration.

get_board_assets

ChatGPT
Get summarized asset nodes, deep links, and their canvas positions for a project. Use filters for shot-number lookup, empty-draft discovery, or smaller operational reads. Use get_asset or get_asset_draft_settings when you need full per-asset detail.

get_board_canvases

ChatGPT
Get canvases with deep links, canvas bins, and text annotations for a project.

get_board_overview

ChatGPT
One-call project and board orientation for agents. Resolves a project by projectId or projectQuery, then returns canvases with deep links, subjects, subject collections, and direct canvas children for one canvas. Prefer this before separate canvas/subject/collection lookup tools.

get_board_subjects

ChatGPT
Get all subjects (characters, props, animals, etc.) on a project board. Subjects are reusable visual references that keep characters and objects consistent across shots. Use get_subject for full detail on a specific subject.

get_board_variables

ChatGPT
List variables on a project board. Variables are reusable named text snippets referenced in prompts via @{variableId:variableName} and expanded to their value at generation time; a value may embed other variables. Optionally filter by canvas.

get_canvas

ChatGPT
Get a single canvas with its deep link and canvas-scoped summaries plus positions, including raw subjectCollections with collection names and memberOrder subject IDs. Use get_subject_collections for hydrated collection members. Use get_asset or get_asset_draft_settings for full per-asset detail. If canvasId is omitted, returns a deterministic canvas.

get_canvas_children

ChatGPT
Get direct spatial children of a canvas or bin. Canvas parent responses include the canvas deep link. Canvas parents can include bins, asset/job nodes, standalone subjects, subject collection cards, and text notes. Bin parents can include asset/job nodes, standalone subjects, subject collection cards, and text notes. This does not expand subject collection members; use get_subject_collection for that semantic membership.

get_comments

ChatGPT
List review comment threads on a project (canvas pins + timeline markers). Each comment includes parsed refs (each with the exact ref token to paste into add_comment) and an authorRef, and top-level me identifies you using the @[kind-id:label] reference grammar. Threads are flat: the root carries the anchor and resolved state; replies share its threadId. Threads mentioning you (mentions:"me") are your work queue — read them, do the work, reply with add_comment, then resolve_comment. Timecodes are MM:SS:FF at 24 fps. A timecode in a body belongs to the nearest preceding asset ref with a clock (video/audio), else the thread anchor: time/clip anchors mean sequence time, node anchors on a video/audio mean time inside that file. Timeline anchors are in ticks (48000/s); clip anchors ride edits via stable clip ids and fall back to fallbackTicks when the clip is gone.

get_elevenlabs_voices

ChatGPT
List the voices in the project team's connected ElevenLabs account. Use a returned voiceId as the voice parameter when generating with elevenlabs-tts-byok (its get_models voice options are empty because voices are per-team).

get_job_status

ChatGPT
Get the status of a generation job.

get_jobs

ChatGPT
Get one generation job by jobId, several by jobIds (one call, one read), or list a project's jobs by projectId. Running jobs carry estimatedTimeSeconds (remaining, from the model's timing table) — size a wait_for_jobs timeout from it instead of polling on a fixed interval. With jobId or jobIds, projectId scopes the lookup: a job from another project reads as not found.

get_library

ChatGPT
The workspace library: reusable collections (characters, props, locations, styles — each holding image/video/text variant assets), folders, typed properties, saved views, and tags. Call this first to orient before any library work. Pass projectId to also see which collections that project has enabled for prompt references. Use get_library_collection for one collection's assets.

get_library_collection

ChatGPT
One library collection in depth: its assets (with property values and version history), text fragments as ready-to-paste @{id:name} prompt chips, and which projects have it enabled.

get_model

ChatGPT
Get detailed info for a specific model (inputs, pricing, constraints).

get_models

ChatGPT
List models (compact, paged), resolve a model/provider name, or inspect one exact model in full. query resolves names like "GPT image" or "Kling"; modelId inspects one exact ID (guidance and inputs live there); omit both to list.

get_projects

ChatGPT
List projects the authenticated user is a member of. Use query or exactName when the user named a project; results default to 20 so agents do not load every project unnecessarily.

get_run

ChatGPT
Inspect one durable Action run: the derived plan for each Action (units, planned outputs, olive estimate, ambiguity), per-Action progress, item-level provenance, measured agent cost, generation cost, and errors. billing, when present, is the separately metered agent-work receipt (model, active compute and paid tools); failed/cancelled usage is charged and funding pauses preserve progress. olives sums generation and agent spend against the budget (total, remaining, overBudget, policy). With waitSeconds it long-polls: one held call replaces a sleep-and-poll loop. The per-Action diagnostics trace (every session, tool call, judge verdict, and note — by far the largest field, 100–250 KB on a long run) is left out by default: poll without it, and pass include: ['trace'] when diagnosing a failure.

get_subject

ChatGPT
Get full detail for a single subject, including all reference images and costumes. Use this after get_board_subjects when you need the complete image set for generation.

get_subject_collection

ChatGPT
Get one subject collection by ID, including its memberOrder and hydrated member subject summaries. This is the semantic collection-member reader; canvas/bin tools only show the collection card as a spatial object.

get_subject_collections

ChatGPT
List subject collections with collection names, home canvases, memberOrder subject IDs, and hydrated member subject summaries including names and thumbnails. Use get_subject_collection when you already know the collection ID.

get_text_note

ChatGPT
Read one canvas text note, including plain text content and absolute canvas position. Use get_board_overview or get_canvas_children with include ["textNotes"] to discover text note IDs.

get_timeline_audio_report

ChatGPT
Hear the selected cut through measurements: composes the current original-media audio mix without video encoding, then returns an annotated waveform, dead-air intervals, integrated loudness, true peak, and loudness range. Reports compare measurements with an optional delivery target and can measure an optional sequence time range. Each new report consumes one daily draft-render quota slot for the project. The browser uses AAC proxies, so use browser playback to confirm audibility/sync and this tolerance-based report for mix QA.

get_timeline_context

ChatGPT
Read compact sequence, track, clip, gap, and relevant asset context for timeline edits. Prefer this before apply_timeline_edit, then pass the returned revisionToken as ifRevision so a concurrent human edit produces a clean conflict instead of a stale overwrite.

get_timeline_delivery_status

ChatGPT
Poll a durable timeline render or Premiere XML export. Render responses include effective videoBitrateKbps and bitrate derivation, including draft-ignore or infeasible-size notes. Completed responses include a short-lived download URL and stable artifactId. WORKER_INTERRUPTED means resubmit the original tool call with a new operationId.

get_upscale_presets

ChatGPT
List the image and video upscale presets available to this project. Presets are created and edited in the Martini app.

get_variable

ChatGPT
Get full detail for a single variable: name, value, color, bin, and absolute canvas position.

get_workflow_authoring

ChatGPT
Read Workflow Beta briefs, the shared compiler authoring guide, seven compiler context sections, kit freshness, exact file metadata and edit baselines without starting a run. Without sections it returns a table of contents (each section with its byte size) plus discovery and the edit baseline; pass sections to fetch the ones you need (the models section alone is the largest). The kit section lists the agent skills the kit ships (kit.skills), each with its files and a download call. The workflow section returns each Action under the field names update_actions writes (instruction, outputBinIds, inputRefs, pinned, gate); bin names are in its bins list. For a workflow placed on a canvas, those fields can be written back to update_actions unchanged; a saved workflow read by ID is read-only (place it with add_workflow_to_canvas to edit its Actions). Accepts saved workflow IDs directly (no placed copy needed). Pass download: true for signed per-file URLs with SHA-256 checksums; fetch them directly to disk in parallel. Read exact kit bytes in bounded base64 chunks with filePath, offset and expectedBundleSha256 from the first response. No compilation, generation or publication occurs.

group_nodes_into_bin

ChatGPT
Create a root-level bin around existing root-level asset/job nodes. Nodes keep their current visual canvas positions; stored positions become bin-relative. To organize the children into a tidy grid, call layout_bin_children after grouping.

import_library_assets

ChatGPT
Bulk-ingest media into a library collection: external file URLs (from any asset-management system — images are mirrored into Martini storage) and/or existing Martini project assets (captured by reference with provenance, no copy). Creates the collection in the same call when newCollection is given. Set names and property values per item as you ingest. Per-item failures are reported without failing the batch. For local file BYTES (no URL), upload into a project first with upload_asset_from_base64, then capture it here via projectId+assetId.

import_timeline_artifact

ChatGPT
Place a completed render on a project canvas as a normal video node. Martini performs a server-side object copy, then creates the poster and playback proxy; the durable render artifact is never moved or deleted. Reuse the caller-generated assetId on network retries.

inspect_json_file

ChatGPT
Read a bounded preview of a JSON File, optionally at a JSON Pointer such as /scenes/0/lines. Long strings are shortened. Full bytes remain in the file URL; workflow runs provide a local input path.

inspect_timeline_artifact

ChatGPT
Inspect a completed render directly from its durable artifact: returns an evenly sampled, timecode-labeled contact sheet plus duration, fps, and dimensions. Use this after a draft render and before spending time on final quality.

inspect_video

ChatGPT
See a completed video AS VIDEO in one round-trip: samples N frames evenly across the clip into a single labeled contact sheet (timecodes burned in), plus duration, fps, and pixel dimensions in the metadata block. Use this to judge motion, continuity, and whether the intended action actually happened across a generation — instead of guessing timestamps and firing extract_video_frame N times. Read-only and creates no nodes. Without a range or explicit timestamps the sheet comes from a filmstrip persisted alongside the video (16 frames cut once when the generation completed); an explicit frameCount picks that many of its frames without decoding; a range or explicit timestamps decodes the source live. For a durable single still or a start/end frame, use extract_video_frame instead. Or videoAssetIds for several takes in one call, sheets in input order.

layout_bin_children

ChatGPT
Arrange direct asset/job/subject children of a root-level canvas bin into a grid. Positions are stored and returned in bin coordinate space, with absolute positions included for visual verification. Use dryRun first when reorganizing an existing user board.

list_models

ChatGPT
List available generation models. Returns compact summaries by default; use get_model for full constraints.

list_project_files

ChatGPT
List the project's memory files — small text files kept per project (conventions, what past Action runs learned). Returns paths, sizes, and update times; read one with read_project_file. Sorted by path, up to 100 files at a time (fewer when paths are long, so a page always arrives whole): when the result carries nextAfter, call again with after set to that path for the next page.

list_project_jobs

ChatGPT
List all generation jobs for a project.

list_runs

ChatGPT
Recent Action runs in a project, newest first: id, name, status, when they started and ended, the current Action, and any error. Use it to find the run id behind "my run failed" before calling get_run.

list_saved_workflows

ChatGPT
Workflows of a workspace (organization). Saved workflows are reusable Action chains with their folder (null when unfiled), steps, inputs, outputs, fingerprint, the agent skills their kit ships (skills; read one before working on that workflow), and the copies placed on canvases; placed workflows without a saved one are listed on their own. Pass query (case-insensitive name substring) or exactName to find a workflow; compact: true omits steps, inputs, outputs and placements. Pass a projectId to list the workspace that owns that project, or an orgId directly. To run saved defaults, use saved[].workflowId directly with run_workflow and omit projectId and bins. Full-detail bin inputs expose required and defaultSource (saved_preset, saved_files, or null); only required inputs need values. placed entries are independently editable copies, not sources of the saved presets; do not choose the first or newest placement to run a saved workflow. Run a placed workflowId only to intentionally use that live canvas, or place a saved one with add_workflow_to_canvas.

move_bin

ChatGPT
Move or resize a root-level canvas bin using absolute canvas bounds. Children keep their bin-relative positions.

move_node

ChatGPT
Move an existing asset-backed node on the canvas.

move_node_to_bin

ChatGPT
Move an asset/job/subject node into a root-level bin or out to the canvas root. Default placement is auto; use absolute only when you need a specific final canvas coordinate.

move_nodes

ChatGPT
Move multiple asset-backed board nodes in one patch. Coordinates are absolute canvas pixels; if targetBinId is set, Martini converts to bin-relative storage. Use dryRun first for cleanup/layout previews.

move_variable

ChatGPT
Move a variable on the canvas, into a root-level bin, or out to the canvas root. Default placement is auto; absolute requires position. Pass targetBinId null to move to the canvas root, or omit it to keep the current bin.

pause_run

ChatGPT
Pause a pending, running, or awaiting-approval run; resume_run continues it at the same Action. A pause does not interrupt work in flight: the executor stops at its next checkpoint (before the next unit or take, after an Action's units settle, before the next Action), so a unit whose agent session is mid tool call finishes first, and generations it already submitted complete and are charged. To stop spending, use cancel_run.

prepare_blender_camera_path_upload

ChatGPT
Presign a PUT URL for a Blender take's authored camera-path JSON, stored as a sidecar of the guide video asset. PUT the export_take.py camera-path.json to the returned uploadUrl with the returned uploadHeaders (content-type application/json plus If-None-Match: * — the URL is create-only); render_blender_take then reads it by reference (guideAssetId) to preserve the authored move — no need to inline the multi-KB sample blob. If directUpload is false (filesystem-only local storage), skip this and pass cameraPath inline to render_blender_take instead.

prepare_kit_upload

ChatGPT
Presign a create-only PUT URL for a whole kit as one tar or tar.gz archive, so the bytes never pass through the model or an MCP payload. Build it with tar -czf kit.tgz -C tools . (paths relative to tools/, executable bits kept), PUT exactly sizeBytes bytes to uploadUrl with the returned uploadHeaders, then call submit_kit_candidate with archive: { uploadId, sha256 } instead of files. The archive replaces the kit: baseline files it omits are deleted. Nothing is recorded until that submit; an unused upload is harmless. Limits: 64 MB uploaded, 128 MB extracted. Budget: 32 MB total, no audio, video or font files, images under 1 MB; a kit is scripts, media belongs in assets and is referenced by URL. Over budget still submits, with the copy in warnings.

prepare_support_request

ChatGPT
Prepare a redacted support request preview when Martini support could help diagnose or unblock the user. This does not create a Productlane case. Use only after the user asks for help/support or agrees to prepare a support packet.

promote_kit_candidate

ChatGPT
Verify and publish exact candidate bytes without an authoring model or generation. For external candidates provide candidateId and snapshotId; legacy runtime repairs accept runId. Failed or no-op verification retains the candidate. A promotion runs the kit's tests in its own sandbox (its own admission lane, about half a minute when a slot is free); pass waitSeconds: 45 to hold for the result and, on completed, receive publishedKit { id, sha256 }, the baseline for the next submit_kit_candidate. A failed promotion answers with kitVerification { passed, failed, blamed, outputTail }: the kit tests' blamed files and the tail of their output (also on get_run and on the candidate in get_workflow_authoring), since the verification sandbox is gone. Every terminal reply carries promotion { compilePhase, consumedCandidate, kitVerification, publishedKit, mirror, timings }: errorMessage names the phase a promotion failed in and timings shows where the time went (sandbox boot, baseline, tests, freeze, publish).

read_project_file

ChatGPT
Read one project memory file by its relative path (see list_project_files).

recreate_drafts

ChatGPT
The canvas "Reuse Settings" action: recreate completed generated image, video, or audio nodes as EMPTY editable drafts. Copies each source’s full saved generation settings and source lineage, but never copies its media URI or starts generation. A source that already has an untouched empty draft (same prompt, no media) returns that existing draft instead of creating a duplicate, so repeat calls are idempotent. Results preserve nodeIds order, keep the selected source arrangement as one nearby collision-free cluster, inherit source bins, and receive fresh shot numbers. Use this—not duplicate_nodes—when the user wants to rerun or revise existing generations.

remove_subjects_from_collection

ChatGPT
Remove one or more subjects from a collection. If all members are removed, the collection is dissolved.

rename_project

ChatGPT
Rename a Martini project. Requires project-update permission and updates the board's live projectName metadata for open collaborators.

rename_subject_collection

ChatGPT
Rename an existing subject collection without changing its member subjects or canvas placement.

render_blender_take

ChatGPT
Bring an authored Blender camera shot into Martini and render it faithfully. Blender renders a clean flythrough of the real scene along the camera the artist (or you) authored; this hands that guide to Seedance with a 'follow the guide's exact trajectory' instruction, so the authored move is preserved with an AI restyle on top. Returns a project URL + node handles — poll get_jobs for completion and view_asset to SEE the result, then iterate. Provide the guide video + first frame either as base64 (guideBase64/firstFrameBase64 — the no-addon path: Blender renders, you pass the bytes here, nothing else needed) or as already-uploaded Martini asset URLs/ids. Set autoRender=false to land editable drafts the user frames in Martini before spending.

render_timeline

ChatGPT
Start a durable MP4 render of the selected sequence from current collaborative timeline state, with optional loudness and true-peak targets. For final quality, maxSizeBytes (integer >= 1000000) targets delivery size and videoBitrateKbps (integer 300–20000) constrains video bitrate; the smaller rate wins when both are set, without changing frame dimensions. Draft ignores both with a note. Responses include effective videoBitrateKbps and bitrate derivation. Output defaults to the sequence frame configured by apply_timeline_edit; choose another destination to override it. Use draft for rapid review, inspect the artifact, then request final. Returns a renderId; poll get_timeline_delivery_status. Render manifests wait for queued/processing timeline assets first. operationId makes retries safe, but an interrupted worker requires a new operationId.

render_timeline_frame

ChatGPT
See the COMPOSED timeline as it plays: renders the top visible clip at a given time (or a strip of frames across a range) into a JPEG image block, so you can QA an edit you just made — clip order, trims, ordering, nested sequences, and track priority. This is editor-preview compositing (the winning clip at each instant); it does NOT bake in transitions, opacity, or filters — use the full render/export for final output. Gaps render as black frames. Read-only; reads from R2 on every call.

reorder_subjects_in_collection

ChatGPT
Reorder the existing subjects in a collection. The subjectIds array must contain exactly the current members; this tool does not add, remove, or dissolve subjects.

reorder_variation_stack_members

ChatGPT
Reorder the existing members in a variation stack. The memberIds array must contain exactly the current stack members using asset-{id} or subject-{id}; this tool does not add, remove, or dissolve stack members.

resolve_comment

ChatGPT
Mark a comment thread resolved (or reopen it with resolved:false). Resolve after the requested work is done and you have replied describing what changed — or leave open for the author to sign off.

restore_checkpoint

ChatGPT
Restore one immutable timeline checkpoint into its original sequence. This replaces only the sequence record and its direct tracks/clips; nested sequence contents remain untouched. ifRevision is mandatory so restore cannot overwrite intervening human work, and operationId makes network retries safe.

resume_run

ChatGPT
Resume a run that is paused, failed, or needs revision. A paused run continues at the Action it stopped in. A failed or needs_revision run re-enters at the earliest Action with a unit still asking for revision, else at the Action that failed: completed Actions before that point keep their outputs, the Actions from there on re-plan where their inputs changed and run only the units that never landed, and a run on the agent environment keeps the scratch files of the earlier attempt. Runs repair their own outputs before they fail (a defective output comes back to its unit as a repair take; a downstream unit that flags an output by asset id sends the run back to its producer), so a resume is for what that could not fix. Either way the run re-reads, for the Actions still to run, their briefs from the canvas (update_actions) and their Instructions files from the project, so a fix to either lands; an Action whose brief changed is planned again. Fix what made it stop first (a brief, a missing input, an Instructions file) — the same failure repeats otherwise. Pass oliveBudget to raise the run's budget with the resume (refused below the current budget, and for canvas runs, which arm their own rail); for a legacy-engine run started over MCP or chat the budget is soft, so the raise resets what get_run reports as overBudget rather than unblocking anything.

run_workflow

ChatGPT
Run a workflow. Either Actions already authored on a canvas (projectId + canvasId, optionally actionIds), or a workflow by id from list_saved_workflows: a SAVED workflow uses its saved definition, variable values and preset contents on a fresh execution canvas. Omit projectId to use the workspace’s "Workflow runs" project; projectId selects only the destination, never the source. Omit bins to keep saved presets; only input bins marked required need caller input. Explicit bins replace saved contents, including [] to empty a media bin. JSON file inputs still require files. Do not fetch a placed copy’s assets to reconstruct saved presets. A PLACED workflow runs that editable copy in place. Execution follows bin dependencies (the Action writing a bin runs before Actions reading it); canvas order only breaks ties. Workflow Beta enforces a strict generation budget regardless of origin, with agent allowance tracked separately. Legacy-engine runs require an olive budget, which is soft for runs started here: each Action first gets a server-expanded plan (how many times it runs, what it produces, the olive estimate) and auto-approves unless rehearsal is set; a plan or spend over the budget is noted on the Action’s trace and reported by get_run (olives.overBudget), never a stop. What stops a run is cancel_run, the per-unit step cap, and the repeated-error guard. Raise the budget later with resume_run or approve_run. Returns immediately with a durable run ID; get_run { runId, waitSeconds: 45 } holds until the run changes and answers with the plan, per-Action, and per-item progress.

set_asset_labels

ChatGPT
Compatibility alias for set_asset_metadata. Existing clients can continue using it to set or clear review flags, star ratings, and color labels on asset-backed canvas nodes.

set_asset_metadata

ChatGPT
Set or clear metadata on asset-backed canvas nodes: review flag ("favorite" or "reject"), independent 1-5 star rating, color label ("green", "yellow", "red", "blue", or "purple"), and user-visible display names. Use displayNames for requests like "rename these shots"; null or blank displayName clears the custom name.

set_file_input

ChatGPT
Constrain an existing bin as a JSON workflow input. The Action must still tag the bin in its brief. Choose a stable API key, one or many files, and optionally select current file IDs as immutable saved defaults. Does not run Actions.

set_node_color_labels

ChatGPT
Set or clear the color label on asset-backed canvas nodes. This updates the node color bar; it does not create variable cards. Use this for requests like "make carrot nodes yellow" or "label these shots red".

submit_kit_candidate

ChatGPT
Submit a kit candidate against the complete reviewed definition and immutable kit baseline (null only when the workflow has no kit). Two sources, pick one: files (exact per-file changes, canonical base64, null to delete) or archive (a whole kit uploaded through prepare_kit_upload; it replaces the kit, so baseline files it omits are deleted). Stores a candidate without running a model or generation. The resulting kit (baseline plus these changes) is validated as a whole: its kit.json must declare version: 1, runtimeContract: "martini-kit-v1", and tests.command (the command promotion runs before publishing); driver, entrypoint, workflowFingerprint, compiledAt, compiledByRunId, and per-Action fingerprint entries are optional (example in get_workflow_authoring sections: ["guide"]). Prefer the archive for a whole kit or anything large: one call, no base64 in the payload. Every candidate binds to the published baseline, so a kit split across calls must be promoted between parts. Retry the same content with the same idempotency key; use promote_kit_candidate with the returned candidateId and snapshotId to verify and publish. A kit over budget (32 MB total, any audio, video or font file, an image over 1 MB) is accepted and named in warnings: a kit is scripts, media belongs in assets and is referenced by URL.

submit_support_request

ChatGPT
Create a Martini support case in Productlane from a prepared support packet after the user reviewed the preview and explicitly approved submission.

update_actions

ChatGPT
Edit existing Action cards in place — brief, name, agent, order, pinned settings, input refs, output bins, gate. Always prefer this over deleting and re-creating an Action: an edit keeps the card, its canvas position, and its run history. Provided fields replace the existing values; omitted fields are untouched. Supply expectedUpdatedAt on each Action from its last read to reject stale edits; if any supplied timestamp no longer matches, no Actions in the batch are written. Omit it to retain the existing update behavior. An Action may read and write the same bin for generate-then-review, seeing existing takes as inputs and adding new takes there; make such an Action idempotent: check what already exists before generating. Find ids with get_canvas_children (actions section), from a chat [Canvas reference: action …] line, or from create_actions / add_workflow_to_canvas results — never guess one.

update_bin

ChatGPT
Rename a root-level canvas bin.

update_bins

ChatGPT
Rename, move, resize, rate (1-5 stars), color-label, collapse, configure auto-layout, or mark "Include contents" (includeContents) for multiple canvas bins in one patch. Nested bins require parentBinId: null to move to the canvas root; without bounds, their absolute position is preserved. Layout bounds never change membership. starRating and colorLabel accept null to clear. Bounds are absolute canvas pixels; children keep their bin-relative positions. Requested sizes are clamped to minimums (height ≥ 150px) — the applied bounds are returned. Use dryRun first for cleanup/layout previews. Note: switching layoutMode to freeform without an open canvas client keeps members at their last materialized positions, so call layout_bin_children when you need freshly computed coordinates instead of relying on the mode flip.

update_draft

ChatGPT
Update an empty draft node's settings in place — prompt, model, reference images, video/audio references, source video, start/end frames (null clears), elements, aspect ratio, resolution, duration, video input mode, and model-scoped generation settings. Only provided scalar fields change; each reference list (referenceImages + libraryReferences, videoReferences, audioReferences, elements) replaces wholesale, [] clears. referenceImages replacement rebinds asset IDs, resets names not supplied in the same call, and clears stale slots/crops; referenceImageNames cannot be patched alone. replaceReference replaces one zero-based image reference with a completed image asset, preserving its slot identity and repeated prompt mentions while clearing its crop/library metadata. Concurrent draft changes reject cleanly so the agent can read and retry. Never starts generation or spends credits. Works only on draft nodes (no generated content yet) — generated nodes are immutable history.

update_subject_images

ChatGPT
Update a subject's main image and/or reference images. Set appendReferences to true to add reference images without replacing existing ones.

update_text_note

ChatGPT
Update a canvas text note. This does not start generation or spend credits. Content is a full plain-text replacement. Position is absolute canvas coordinates; binId null moves the note to the canvas root.

update_variable

ChatGPT
Update a variable: name, value, color, color label, or rating. Value is a full replacement. Renaming rewrites @{id:name} references in other variables. Pass null for color, colorLabel, or rating to clear them.

upload_asset_complete

ChatGPT
Finish an image upload started with upload_asset_init. Verifies the R2 object arrived, extracts width/height server-side, and triggers thumbnail/proxy generation. Returns immediately with status: "processing" — the Asset flips to "completed" when background processing finishes.

upload_asset_complete_batch

ChatGPT
Finish up to 50 image uploads started with upload_asset_init_batch in a single call. Verifies each R2 object arrived, extracts width/height server-side, and triggers the thumbnail/proxy pipeline. Per-asset completion failures (missing bytes, decode error, wrong MIME, already processed) return structured error entries without failing the rest of the batch.

upload_asset_from_base64

ChatGPT
Fallback image upload for MCP clients that cannot PUT directly to Martini R2 storage. Accepts a base64-encoded JPEG, PNG, or WebP image, writes it to Martini storage server-side, places it on the requested scene, and starts thumbnail/proxy processing. Prefer upload_asset_init/upload_asset_complete when the client can reach R2, especially for large files or batches.

upload_asset_from_url

ChatGPT
One-call upload of a file the agent can already point at: Martini fetches the public https URL server-side (up to 50 MB), stores it, places it on the canvas, and starts processing — replacing the upload_assets_prepare → PUT → upload_assets_complete round trip for images (JPEG/PNG/WebP), MP4 video, and MP3/WAV/AAC-M4A/FLAC/OGG audio. Nothing rides the agent context. Private, local, and presigned-Martini URLs are refused; use upload_assets_prepare for those or for other containers.

upload_asset_init

ChatGPT
Upload an image onto a canvas so it appears for the user. Returns a short-lived presigned R2 PUT URL the agent should upload bytes to, and writes a placeholder Asset into the project so collaborators see the upload in flight. Follow with upload_asset_complete. If this is the first storage operation in the session, call check_storage_reachability first and only proceed if its probe succeeds.

upload_asset_init_batch

ChatGPT
Upload up to 50 images onto a canvas in a single call, collapsing what would be N per-file round trips into one PartyKit read and one merge. Each file returns a presigned R2 PUT URL; follow with upload_asset_complete_batch after all bytes are uploaded. Per-file validation failures do not fail the rest of the batch; batch-level failures (empty array, over 50 files, canvas missing, access denied) reject the whole call with no writes. Prefer this over upload_asset_init when uploading 5 or more files. If this is the first storage operation in the session, call check_storage_reachability first and only proceed if its probe succeeds.

upload_assets_complete

ChatGPT
Complete one or more image, video, or audio uploads started with upload_assets_prepare in a single call. Verifies each R2 object arrived, extracts image dimensions, or hands off to the video proxy/thumbnail or audio proxy/waveform pipeline based on the asset type set at prepare time. Per-asset completion failures (missing bytes, decode error, wrong MIME, already processed) return structured error entries without failing the rest of the batch. To use completed audio as a generation reference, pass its returned url to update_draft { audioReferences: [{ url }] } and cite it in draftPrompt as @Audio1; models such as Seedance 2.5 do not use uncited audio references.

upload_assets_prepare

ChatGPT
Prepare up to 50 image, video, or audio uploads in one batch. Each valid file creates an in-flight placeholder and returns a presigned R2 PUT URL. Set binId to auto-place the batch directly in an existing root or nested bin; omit it for canvas-root placement. PUT bytes with the returned uploadHeaders (Content-Type and If-None-Match: *), then call upload_assets_complete. File validation errors are returned per file; invalid canvas/bin, conflicting placement options, or denied access reject the batch before writes. Call check_storage_reachability before the session's first upload. For audio references, use update_draft { audioReferences: [{ url }] } with the completed URL and cite @Audio1 in draftPrompt.

upscale_assets

ChatGPT
Upscale existing image nodes via Topaz presets/models, and video nodes via upscaleModel: "FLUX Video Upscale" (precise by default; detail: "creative" plus an optional prompt invents detail; scale 1.5–3; sources up to 19.5s / 50 MB; longer shots are upscaled from their first 19.5s). Each node starts one job that attaches as a version of its source. First call without batchApproval for a server-computed per-node olive quote, planHash, and batchRequestId; present the total, then re-call unchanged with that planHash, batchRequestId, and batchApproval. Replaying an approved call resumes it (alreadySubmitted per node) instead of charging again. Image settings may come from an organization image preset by name and inline fields override it (an inline size choice replaces the preset size entirely). Presets are created and edited in the Martini app.

view_asset

ChatGPT
Inline an image asset's bytes directly into your context so you can SEE it. The leading content block is the actual ImageContent — no fetch step required. Use when you want to inspect an image, not save it. Image-only (Claude can't perceive AudioContent meaningfully and videos don't fit) — videos, audio, oversized images all error with a hint to use get_asset_download_url. Hard cap: 10MB. Reads from R2 on every call — call only when you actually need to look at the asset.

view_library_asset

ChatGPT
Inline a library image asset's bytes into your context so you can SEE it (video assets show their poster still; text fragments return their text). Use before electing an asset as a generation element or hero.

view_subject_collection_card

ChatGPT
Render one subject collection as an inline visual card. The card includes all available member subjects as thumbnail tiles with labels, plus placeholders for members without thumbnails or missing subjects. Use this when the user wants to see a collection or compare all subjects in it.

view_subject_image

ChatGPT
Inline images from a subject node as MCP ImageContent so you can SEE the subject's main image, an individual reference image, or all subject images in one response. Use slot "all" to avoid repeated calls. Defaults to resized previews for all-images requests and full resolution for single-image requests. Hard cap: 10MB per returned image and 25MB per all-images response.

wait_for_jobs

ChatGPT
Hold one call until every listed generation job is terminal (completed, failed, cancelled) or timeoutSeconds elapses, then answer with each job's status, assetId, error and remaining-time estimate. Replaces a sleep-and-poll loop over get_jobs: pass every jobId you are waiting on in one call, use timeoutSeconds 45 (the maximum — MCP clients time a request out at 60 s), and on timedOut: true call again with the same jobIds. Read-only; jobs you cannot read are reported under notFound and never held for.

write_project_file

ChatGPT
Write a project memory file: replace its content, or pass append=true to add to the end (the file is created when absent). An append only ever adds — the file keeps everything it already held — except workflows/<slug>/experience.md, the rolling log of what runs learned, which drops its oldest entries to stay readable in one result. Pass createOnly=true to create the file only where none exists: an existing file is kept and the call refused, so two writers racing to author one file never overwrite each other. Pass expectedUpdatedAt (the updatedAt a read_project_file or list_project_files returned) to replace only while the file is still that version; a newer version answers PROJECT_FILE_CHANGED instead of being overwritten. Paths are relative and slash-separated (letters, digits, . _ -); at most 2,000 files per project, 1 MiB each. project.md is human-owned and refused here — propose changes to it in your reply. Locked files are refused until a person unlocks them. Instructions files (workflows/<slug>/instructions/<action-slug>.md, or any file a brief tags as @[Instructions:…]) must stay within 16 KiB each and 48 KiB per Action (own file plus tagged files); a run injects them whole.

Capabilities

Writes

Example Prompts

Click any prompt to copy it.

Similar Apps