Implementing MCP Agent Tools for Video Editor Automation in Palmier Pro
Palmier Pro exposes an MCP (Macro-Control-Protocol) server on localhost:19789 that lets external agents programmatically drive video editing through HTTP endpoints, with tools defined in ToolDefinitions.swift and executed via ToolExecutor.swift.
The palmier-io/palmier-pro repository provides a native macOS video editor with full programmatic control via MCP agent tools for video editor automation. This Macro-Control-Protocol implementation allows external agents like Cursor, custom scripts, or AI-driven tools to discover capabilities, query project state, and execute editing commands through a local HTTP interface.
Core Architecture of the MCP Stack
The MCP implementation rests on three coordinated components that handle networking, business logic, and API schema.
MCPService: The HTTP Gateway
Located in Sources/PalmierPro/Agent/MCP/MCPService.swift, MCPService starts an HTTP server on the local loopback interface (127.0.0.1:19789). It advertises server capabilities, registers available tools and resources, and routes incoming MCP calls to a per-session ToolExecutor. The start() method constructs an MCPHTTPServer while registerTools(on:executor:) converts AgentTool definitions into MCP.Tool registrations and binds method handlers for ListTools and CallTool requests.
ToolExecutor: The Domain Dispatcher
Sources/PalmierPro/Agent/Tools/ToolExecutor.swift implements the execution logic for every MCP tool. It receives JSON argument dictionaries from MCP, validates inputs via ToolArgsBridge.argsFromMCP(), and dispatches to the editor's domain model on the MainActor. The execute(name:args:source:) method handles project navigation, timeline mutation, media import, and AI generation, returning a ToolResult convertible to MCP responses via toMCPResult().
ToolDefinitions: The Capability Catalog
Sources/PalmierPro/Agent/Tools/ToolDefinitions.swift declares the complete tool catalog as static constants. Each AgentTool specifies a ToolName, human-readable description, and JSON Schema inputSchema that MCP clients use for validation and UI generation. This stateless design means adding new tools requires only appending entries here without modifying server code.
Request Flow for MCP Agent Tools
Understanding the lifecycle of an MCP request helps when debugging automation scripts or extending the protocol.
Server Initialization and Registration
When the app launches, AppState.startMCPService() creates an MCPService instance with a closure returning the currently visible VideoProject. The service constructs an MCPHTTPServer configured with static Server metadata describing available resources—such as AI model listings at palmier://models/video and palmier://models/image—and the full ToolDefinitions.mcpServer tool set.
Request Handling and Execution
When clients POST to /mcp/call_tool, the server deserializes arguments and MCPService.dispatchCall converts raw MCP dictionaries to Swift [String: Any] using ToolArgsBridge.argsFromMCP(). The system then invokes ToolExecutor.execute(name:args:source:) on the MainActor to ensure thread-safe UI access, while heavy operations (file imports, MLXRuntime AI generation) run on background utilities.
Result Conversion and Session Management
After execution, ToolResult transforms into MCP.CallTool.Result via toMCPResult() for the HTTP response. The first request from any client supplies MCPClientInfo (name, version) through ToolExecutor.setMCPClientInfo(_:), enabling per-client logging and session tracking for authentication or debugging purposes.
Design Principles for Reliable Automation
The MCP stack adheres to specific architectural constraints that ensure safety and consistency.
Single Source of Truth
All mutable editor state lives in the domain model (VideoProject, Timeline). MCP tools forward to the same APIs used by UI actions, ensuring undo/redo behavior remains identical for human and programmatic edits.
Actor Isolation and Concurrency
While MCPService operates on the MainActor, the implementation dispatches heavy work to background actors. This respects the "main-actor is a scarce UI resource" rule while maintaining responsive editing during AI generation or large file imports.
Practical Automation Examples
External agents interact with Palmier Pro via standard HTTP requests. These examples use curl, but any language capable of HTTP+JSON works identically.
Discovering Available Tools
List all MCP agent tools for video editor automation to understand the API surface:
curl -s http://127.0.0.1:19789/mcp/list_tools | jq '.tools | .[] | .name, .description'
Querying Project State
Retrieve the active timeline including fps, resolution, track IDs, and clip IDs:
curl -s -X POST http://127.0.0.1:19789/mcp/call_tool \
-H "Content-Type: application/json" \
-d '{
"name": "get_timeline",
"arguments": {}
}' | jq '.result'
Mutating the Timeline
Add clips to a specific track using media references obtained from prior tool calls:
curl -s -X POST http://127.0.0.1:19789/mcp/call_tool \
-H "Content-Type: application/json" \
-d '{
"name": "add_clips",
"arguments": {
"mediaRefs": ["media-123"],
"trackId": "track-5",
"startFrame": 150,
"durationFrames": 300
}
}' | jq '.result'
Key Source Files Reference
Package.swift: Declares the MCP package dependency and macOS-only build configuration.Sources/PalmierPro/Agent/MCP/MCPService.swift: HTTP server lifecycle and tool/resource registration.Sources/PalmierPro/Agent/Tools/ToolExecutor.swift: Core dispatch logic mapping MCP calls to editor operations.Sources/PalmierPro/Agent/Tools/ToolDefinitions.swift: Complete catalog of MCP-exposed tools with JSON Schemas.Sources/PalmierPro/Agent/AgentInstructions.swift: In-app human-readable guidance for MCP users.Sources/PalmierPro/Agent/MCP/MCPHTTPServer.swift: Low-level async HTTP implementation for MCP JSON-RPC.Sources/PalmierPro/Agent/Tools/ToolResult.swift: Conversion utilities between internal types and MCP wire format.
Summary
- Palmier Pro implements MCP agent tools for video editor automation through three Swift components:
MCPService,ToolExecutor, andToolDefinitions. - The server runs on
localhost:19789and exposes JSON-RPC endpoints for tool discovery (/mcp/list_tools) and execution (/mcp/call_tool). - All tool definitions include JSON Schema validation declared in
ToolDefinitions.swiftand are registered dynamically without server restarts. - Execution occurs on the MainActor for UI safety, with heavy operations dispatched to background utilities like
MLXRuntime. - External agents can discover capabilities, query the timeline via
get_timeline, edit viaadd_clips, and export viaexport_projectusing standard HTTP POST requests.
Frequently Asked Questions
What port does the Palmier Pro MCP server use?
The MCP service binds to port 19789 on the local loopback interface (127.0.0.1) as implemented in MCPService.swift, ensuring only local processes can access the automation API.
How do I add custom tools to the MCP server?
Extend Sources/PalmierPro/Agent/Tools/ToolDefinitions.swift by appending new AgentTool entries with unique ToolName values, descriptions, and inputSchema definitions. The MCPService.registerTools method automatically exposes new tools without requiring changes to server routing logic.
Can MCP clients execute timeline mutations while the user is actively editing?
Yes. ToolExecutor.execute operates on the MainActor and forwards to the same domain APIs used by the UI, ensuring thread-safe access and maintaining a single source of truth for project state. Concurrent modifications follow the application's existing undo/redo stack behavior.
What authentication mechanisms exist for MCP connections?
The current implementation stores client identity via MCPClientInfo set during the first request through ToolExecutor.setMCPClientInfo(_:), enabling per-client logging. Additional authentication layers would require extending the request handling logic in MCPHTTPServer.swift.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →