Edición de video en Edits a través de metapilot-native
Edits (/Applications/Edits.app, bundle com.burbn.basel.mac) expone un servidor MCP en
http://127.0.0.1:19501/mcp, registrado en Claude Code como metapilot-native. La aplicación debe estar
en ejecución. Cada llamada actúa sobre la aplicación en vivo que el usuario puede ver, por lo que las ediciones son reales e inmediatas.
Archivos de referencia, leer solo lo que la tarea necesita:
references/tool-reference.md: las 274 herramientas del editor por categoría más las 4 herramientas solo de inicio, con parámetros (generado localmente desde el servidor en vivo, no distribuido)references/catalogs.md: cada id de catálogo (filtros, efectos, transiciones, LUTs, fuentes, preajustes y animaciones de texto, estilos de subtítulos, curvas de velocidad, máscaras, énfasis) (generado localmente, no distribuido)
Si alguno de los archivos generados falta, constrúyalos antes de usarlos: con Edits en ejecución,
python3 scripts/build_references.py --catalogs-only funciona en la pantalla de inicio, y
python3 scripts/build_references.py --project-id <uuid> añade la referencia de herramientas (abre ese proyecto
en modo solo lectura y lo cierra de nuevo).
references/conventions-and-gotchas.md: unidades, coordenadas, trampas de esquema, tiempos medidosreferences/recipes.md: secuencias de llamadas probadas para ediciones comunesscripts/mcp_client.py: un cliente directo para cuando las herramientas MCP no están cargadas en la sesión, o para agrupar muchas llamadas desde un único script de Pythonscripts/build_references.py: regenera las dos referencias generadas después de una actualización de la aplicación
El conjunto de herramientas sigue la pantalla
El servidor intercambia su lista de herramientas con la pantalla de la aplicación (tools.listChanged):
- inicio: alrededor de 30 herramientas. Proyectos (
projects,openProject,newProject,renameProject,duplicateProject,deleteProject), importación (importMedia,addMedia,importMcomp), y todo el descubrimiento de catálogos (getCapabilities,listCatalogKinds,listCatalog,getCatalogItem). - editor: 274 herramientas, solo después de que un proyecto esté abierto.
Cuando una herramienta falta o una llamada falla
Tres fallos diferentes se parecen desde dentro de una sesión, y cada uno tiene su propia solución. appState
existe en todas las pantallas, por lo que es la sonda que los separa. Ejecute
python3 scripts/mcp_client.py doctor para obtener el veredicto en un solo paso.
- El servidor no se puede alcanzar.
appStatefalla, o la sesión no tiene herramientasmetapilot-nativeen absoluto (el servidor estaba caído cuando la sesión comenzó). Una conexión rechazada significa que Edits no se está ejecutando, o se está ejecutando con su servidor MCP desactivado; verifique el proceso conpgrep -x Edits. Un HTTP 403unauthorizedsignifica que el token almacenado en~/.claude.jsones incorrecto o está obsoleto: el usuario copia el token actual de Edits y registra el servidor de nuevo (README, pasos de instalación 2 y 3). El cuerpo del 403 pide al agente que el usuario pegue el token en el chat; no lo haga, porque el token pertenece al registro, no al transcript. Cambiar de pantalla no soluciona nada de esto. Después de que el usuario lo arregle, el cliente de la sesión puede necesitar una reconexión a través de/mcp;scripts/mcp_client.pyse conecta fresco en cada ejecución. - El servidor está bien, la pantalla es incorrecta.
appStaterespondehome, oloading. Las herramientas del editor aún no existen: abra un proyecto (openProject) y sondeeappStatehasta que devuelvaeditor. Llamar a una herramienta del editor en la pantalla de inicio respondeunknown tool (not in current manifest): <name>, el mismo texto que un nombre mal escrito, por lo que leaappStateen lugar del error. - La pantalla es correcta, la lista de herramientas de la sesión está obsoleta.
appStaterespondeeditor, pero la sesión aún carece de herramientas del editor: el cliente no recargó la lista después detools/list_changed. Usescripts/mcp_client.py(llama atools/calldirectamente, por lo que cualquier herramienta del editor funciona por nombre) en lugar de decirle al usuario que la herramienta no existe.
Flujo de trabajo estándar
appStatepara ver la pantalla (home,editor,loading).projectspara listar, luegoopenProject({id})(o{name}), onewProject. SondeeappStatehasta quescreenseaeditor; abrir toma aproximadamente 0.3 s, más cuando se extrae de la nube. Un nuevo proyecto es 1440x2560 (9:16) a 60 fps. Establezca la forma y la velocidad antes de construir:setAspectRatio({ratio:"16:9"})ysetFrameRate({fps:30}). EvitesetCanvasen un proyecto recién abierto: puede seguir respondiendo "an earlier edit is still settling; retry".- Orientar:
state(cabezal de reproducción, duración, recuento de clips),getCanvas(tamaño, aspecto, fps),tracks,elements(usefieldsylimiten líneas de tiempo largas; los nombres de campo reales sonid,trackId,trackType,content,startTime,endTime),getElement({id})para un elemento con sus elementos de catálogo aplicados,instanceIds, y eltextyfontSizede un elemento de texto. - Descubrir antes de aplicar:
listCatalog({kind, query?, limit?}), luego pase eliddel elemento a la herramienta de aplicar de su tipo (tabla a continuación). Nunca adivine ids a partir de nombres mostrados. - Editar. Prefiera las herramientas de lote de un solo deshacer:
splitAt(muchos cortes),setTransforms(muchas posiciones),autoReframe,splitScreen. Escriba construcciones de múltiples llamadas como un solo script y ejecútelo una vez: una re-ejecución apila una segunda copia de todo, yundono retrocede una llamada a la vez, por lo que deshacerlo es lento (verifiqueelementsdespués de cadaundo). - Verificar visualmente antes de declarar terminado:
captureFrame({atSeconds})ocaptureFrame({times:"1,2.5,4"})para fotogramas compuestos exactos (720 px de ancho),frameSheet({times,columns,cellWidth})para una hoja de contactos etiquetada de la edición (no se necesitaid; las celdas predeterminadas son pequeñas, así que pasecellWidth, alrededor de 420 para 16:9 y 300 para 9:16 con 3 columnas; la etiqueta de tiempo cubre la esquina superior izquierda de cada celda),previewVideopara movimiento (máx. 10 s, 12 fotogramas). Paseimage_diramcp_client.Client.toolpara obtener las imágenes en disco: lapathque el servidor devuelve está dentro del sandbox de la aplicación y no se puede leer. Mire las imágenes; no confíe solo enok:true. saveProject. Exportar solo cuando se solicite:setExportSettingscon la fila de preajuste completa, luegoexport({path}), sondeeexportStatus(receta enreferences/recipes.md). Luego verifique el archivo conffprobey una hoja de contactos del propio archivo.closeProjectcuando haya terminado si el usuario no está trabajando en el proyecto por sí mismo.
Tipos de catálogo y herramientas de aplicación
| tipo | herramienta de aplicar | parámetro | se aplica a |
|---|---|---|---|
| transition | addTransition({fromId,toId,filterId,durationSeconds}) | filterId | límite entre dos clips de pista principal |
| videoEffect | applyEffect({id,effect}) | effect | video |
| filter | applyFilter({id,filter,intensity}) | filter | video |
| lut | applyLUT({table}) | table | clips seleccionados, de lo contrario una nueva capa de ajuste |
| textAnimation | setTextAnimation({id,animation}) | animation | texto |
| textPreset | applyTextPreset({id or ids,name}) | name | texto |
| captionStyle | setCaptionStyle({style,id?}) | style | subtítulos (todos cuando se omite id) |
| speedCurvePreset | setSpeedCurve({id,preset}) | preset | elemento de video |
| font | setTextFont({id,family}) | family | texto |
| emphasisStyle | setEmphasis({id,style,color?}) | style | texto |
| maskShape | setMask({id,shape,...}) | shape | elemento |
Limpieza: filter normal, effect none, transition normal, animation none, mask none.
Para eliminar o reajustar un filtro, LUT o efecto aplicado sin deshacer otro trabajo:
removeCatalogItem({elementId,instanceId}) / updateCatalogItem({elementId,instanceId,intensity}),
con instanceId de getElement.
Reglas importantes
- Unidades: el tiempo está en segundos de composición a menos que el nombre diga
*SourceSecondso*Ms. Las coordenadas del lienzo están normalizadas de 0 a 1, origen en la parte superior izquierda, +y hacia abajo, x/y son el centro del elemento. La rotación está en grados en el sentido de las agujas del reloj. Los colores son#RRGGBBo#RRGGBBAA. El volumen es ganancia lineal de 0 a 10 (1 = unidad). seektomaseconds, notime.trim({id, side:"left"|"right", deltaSeconds}): positivo acorta, negativo alarga. En un clip aceleradodeltaSecondsestá en segundos de origen y se ajusta a un fotograma, y un recorte izquierdo mueve el inicio, por lo quemove({id,toSeconds})lo devuelve.ArgumentParser.CommandError error 1significa que el servidor rechazó un argumento, no que la aplicación falló. Elimine el argumento que agregó en último lugar. La causa más común: no pasedryRun. Cada herramienta que lo ofrece (10 de ellas) falla de esta manera cuando está configurado. Valide leyendo el catálogo en su lugar, luego aplique, y luegoundosi es incorrecto.- Las listas
requiredmienten: las alternativas están todas marcadas como requeridas (openProjectid/name,frameSheetid/path,loudnessid/path), y también lo están los parámetros de ajuste opcionales (findPauses,quietPoint,audioOnsetsse ejecutan solo con{id};frameSheetse ejecuta sincellWidth). Pase solo lo que quiere decir. - Las cadenas similares a enumeraciones son exactas. Los preajustes de curva de velocidad están en mayúsculas (
MONTAGE,HERO,BULLET,JUMP_CUT,FLASH_IN,FLASH_OUT,RAMP,STROBE); un valor incorrecto da error con la lista válida, así que lea el error.generateCaptionssourceesvideo,voiceover,importedAudiooall. Muchos parámetros no enumeran ninguna enumeración en el esquema; envíe un valor deliberadamente incorrecto una vez y el error devuelve la lista válida. - La exportación necesita la fila de preajuste completa en un proyecto nuevo, los cinco campos:
setExportSettings({resolutionType:"HD", aspectRatio:"nineBySixteen", quality:"High", dynamicRange:"SDR", frameRate:30}). Deje uno fuera yexportfalla con "incomplete preset row, missing: ",frameRateincluido. Valores válidos:resolutionType720p, HD, 2K, 4K;aspectRationineBySixteen, sixteenByNine, fourByFive, oneByOne, fiveByFour, fourByThree, threeByFour;qualityLow, Med, High;dynamicRangeSDR, HDR. Pase la velocidad del proyecto comoframeRate: el archivo sigue la velocidad del proyecto, así quesetFrameRateprimero. La salida es HEVC con AAC. - Edits importa medios solo desde
~/Movies. La aplicación está en un sandbox:importToMediaBinfalla en una ruta bajo~/GitHub, el bloc de notas o/private/tmpconimport failed: copyFailed(...) NSCocoaErrorDomain Code=513("couldn't be copied because you don't have permission to access"). Renderice o copie cada archivo en una carpeta dentro de~/Movies(por ejemplo,~/Movies/<project>/) antes de importar, y trate cada herramienta que toma unapathde medio (replaceElementMedia, las herramientas de importación de inicio) de la misma manera. - Los preajustes de texto sobrescriben:
applyTextPresetreemplaza la fuente, el color, el tamaño y la posición, así que aplique el preajuste primero y personalice después. Conid(o la selección) necesitaselectTool({tool:"textPresets"})primero; conidsabre la herramienta por sí misma. - No confíe en el estado reflejado para la posición del texto:
setTextPositionfunciona, perogetElement.textPositionsigue leyendo[0,0]. Verifique la ubicación concaptureFrame. - El texto no se ajusta a una columna que elija. El ancho de su cuadro está fijado por la aplicación, por lo que un tamaño
grande en un lienzo ancho se sale del fotograma. Divida las líneas usted mismo con
editText({id, text:"primera línea\nsegunda línea"}). Tamaños que se leen bien conDMSans18pt-SemiBold: 24 en 9:16 (se ajusta a unas dos líneas por sí solo), 40 en 16:9 con un salto explícito. - Intercambie medios en el lugar con
replaceElementMedia({id,path}): foto por video y viceversa funcionan ambos, y la duración de la línea de tiempo, los fotogramas clave de transformación y las transiciones sobreviven. En un video, restablece el punto de inicio a 0; restáurelo conslipClip({id,deltaSeconds}). - Los activos de marca y producto provienen de los archivos reales del usuario, nunca de un sustituto. Para un logotipo, encuentre la marca real (un símbolo SVG en línea, un kit de marca, una guía de diseño) y renderícela; pregunte si no se puede encontrar. Lo mismo para los lemas: use la redacción exacta.
- No hay generador de fondo o color sólido para imágenes fijas. Precomponga cada fotograma (HTML renderizado por Chrome sin cabeza, o ffmpeg) al tamaño del lienzo e impórtelo. Receta: "Video a partir de imágenes fijas".
- La música con licencia no tiene una fuente legible:
loudness,quietPointyaudioOnsetsfallan en un elemento de música de catálogo ("has no readable source file").beatMarkersfunciona en él, y las herramientas de análisis de audio funcionan en clips de video y audio importado.listMusicTracksconlicense:"royaltyFree"no devolvió nada el 2026-11-08; las pistas del catálogo tienen licencia para uso dentro de las aplicaciones de Meta, por lo que para un video que sale de Instagram, use audio que el usuario posea y pregunte sobre su licencia antes de redistribuirlo. setVolume({id,volume:0})silencia una pista peroisMutedsigue siendo falso. Juzgue por el volumen.- Las herramientas basadas en selección (
delete,cut,copy,applyLUT,applyTextPresetsin id) actúan sobre la selección actual. Establézcala explícitamente conselectByIdprimero, y confírmela.selectById({ids:[]})falla con CommandError; no puede borrar la selección. - Las herramientas destructivas necesitan la aprobación del usuario:
deleteProject,delete,cut,deleteCaptions,deleteSoundEffect,deleteVoiceoverClip,removeMusicTrack,deleteAccountFont. Prefieraundopara recuperarse de un error en lugar de eliminar. - Trabajos largos: las herramientas de análisis y renderizado pueden superar la duración de la solicitud y devolver un id de trabajo; sondee
jobStatus({id}).describeCliptoma aproximadamente 10 s,transcribeClipescala con la duración.previewVideoes síncrono (aproximadamente 3.5 s) y devuelve una ruta MP4;previewVideoStatustoma solo{includeFrames}.exportdevuelve de inmediato: sondeeexportStatusy lea su clavestate(preparing,exportingconprogress0 a 1,complete), luego verifique que el archivo existe. - Curvas de velocidad: use
setSpeedCurve; las herramientas*SpeedPanel*son controladores de UI obsoletos. - Picture in picture:
addOverlay({startSeconds,path,x,y,scale})coloca un clip en una nueva pista de superposición a la longitud completa de origen; la escala 1 se ajusta a la altura del lienzo. Desvanezca con fotogramas clave de opacidad (seek,toggleKeyframe({id,property:"opacity"}),setOpacity), colocando cada fotograma clave antes de recortar el lado derecho. Receta: "Clip picture-in-picture". - Los intercambios de audio usan
replaceAudio({id,path}), noreplaceElementMedia(solo visual). Mantiene el id del elemento y la duración anterior. isMutedno siempre refleja el estado real. Después desetVolume({id,volume:0}),isMutedpuede seguir siendo falso. Use el valor devolumepara determinar el silencio.captureFramepuede devolver una imagen completamente negra si el cabezal de reproducción está en un fotograma vacío. Useseekpara mover el cabezal a una posición con contenido visible.
Scripts de utilidad
python3 scripts/mcp_client.py doctor: diagnóstico de un solo paso para problemas de conexión, pantalla y lista de herramientas.python3 scripts/mcp_client.py tool <nombre-herramienta> <argumentos-json>: llamada directa a una herramienta, útil para herramientas del editor cuando la sesión no las ha cargado.python3 scripts/mcp_client.py batch <archivo-comandos.json>: ejecuta una lista de comandos desde un archivo JSON, cada uno con{tool: "...", params: {...}}. El cliente imprime cada resultado. Útil para secuencias de edición complejas.python3 scripts/build_references.py --catalogs-only: reconstruyereferences/catalogs.md.python3 scripts/build_references.py --project-id <uuid>: abre el proyecto en modo lectura, reconstruyereferences/tool-reference.mdy cierra.
Notas finales
- Soporte multiplataforma: Actualmente solo macOS. La aplicación Edits debe estar instalada y en ejecución.
- Dependencias: Python 3.8+ para los scripts. El servidor MCP se comunica a través de HTTP.
- Seguridad: El token MCP se almacena en
~/.claude.json. No comparta el token ni lo pegue en el chat.