git.lucas.co / cce-designer
graphic design tool
git clone https://git.lucas.co/cce-designer.git

commit4eda26aa79de4f4c642de604b61e2ac8ff1cdde6
parentf0523fa17a
authorLucas Galante <[email protected]>
date2026-08-26 12:07
feat: expose playbar state in MCP get_state

An additive 'playbar' key beside the project fields (frame/playing/
start_frame/end_frame) — the playbar is app state, not project state,
so it stays out of the Project struct, but automation could not read
the timeline at all.

Co-Authored-By: Claude Fable 5 <[email protected]>

 src/window.rs | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/src/window.rs b/src/window.rs
index cd0c288..f196ba9 100644
--- a/src/window.rs
+++ b/src/window.rs
@@ -626,8 +626,19 @@ impl State {
         needs_redraw: &mut bool,
     ) -> Result<serde_json::Value, String> {
         if call.name == "get_state" {
-            return serde_json::to_value(self.project_snapshot())
-                .map_err(|e| format!("failed to serialize state: {e}"));
+            let mut v = serde_json::to_value(self.project_snapshot())
+                .map_err(|e| format!("failed to serialize state: {e}"))?;
+            // Additive sibling of the project fields: the playbar is app
+            // state, not project state, so it must not enter the Project
+            // struct (the save format) — but automation needs to read it.
+            let pb = self.slots.playbar.inner();
+            v["playbar"] = serde_json::json!({
+                "frame": pb.current_frame.round() as i64,
+                "playing": pb.playing,
+                "start_frame": pb.start_frame.round() as i64,
+                "end_frame": pb.end_frame.round() as i64,
+            });
+            return Ok(v);
         }
         let mut req = if call.arguments.is_object() {
             call.arguments.clone()