From 8b8e8a8d8c2af27199d1c0305d2410539581baf6 Mon Sep 17 00:00:00 2001 From: Gabriel Kaszewski Date: Tue, 17 Mar 2026 14:32:02 +0100 Subject: [PATCH] fix(mcp): update block mutations for ScheduleConfig V2 day_blocks --- k-tv-backend/mcp/src/server.rs | 31 ++++++++++++++------------ k-tv-backend/mcp/src/tools/channels.rs | 10 +++++++-- 2 files changed, 25 insertions(+), 16 deletions(-) diff --git a/k-tv-backend/mcp/src/server.rs b/k-tv-backend/mcp/src/server.rs index 4768869..30d4828 100644 --- a/k-tv-backend/mcp/src/server.rs +++ b/k-tv-backend/mcp/src/server.rs @@ -59,14 +59,16 @@ pub struct DeleteChannelParams { pub struct SetScheduleConfigParams { /// Channel UUID pub channel_id: String, - /// JSON array of ProgrammingBlock objects - pub blocks_json: String, + /// JSON object of the full ScheduleConfig shape: {"monday": [...], "tuesday": [...], ...} + pub day_blocks_json: String, } #[derive(Debug, Deserialize, JsonSchema)] pub struct AddBlockParams { /// Channel UUID pub channel_id: String, + /// Day of week: "monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday" + pub day: String, /// ProgrammingBlock serialized as JSON pub block_json: String, } @@ -163,43 +165,44 @@ impl KTvMcpServer { } #[tool( - description = "Replace a channel's entire schedule config. blocks_json is a JSON array of ProgrammingBlock objects." + description = "Replace a channel's entire schedule config. day_blocks_json is a JSON object of the ScheduleConfig shape: {\"monday\": [...], ...}" )] async fn set_schedule_config(&self, #[tool(aggr)] p: SetScheduleConfigParams) -> String { let channel_id = match parse_uuid(&p.channel_id) { Ok(id) => id, Err(e) => return e, }; - let blocks: Vec = match serde_json::from_str(&p.blocks_json) { - Ok(b) => b, + let config: ScheduleConfig = match serde_json::from_str(&p.day_blocks_json) { + Ok(c) => c, Err(e) => { - return serde_json::json!({"error": format!("invalid blocks_json: {e}")}) + return serde_json::json!({"error": format!("invalid day_blocks_json: {e}")}) .to_string() } }; - channels::set_schedule_config( - &self.channel_service, - channel_id, - ScheduleConfig { blocks }, - ) - .await + channels::set_schedule_config(&self.channel_service, channel_id, config).await } #[tool( - description = "Append a ProgrammingBlock to a channel's schedule. block_json is a serialized ProgrammingBlock." + description = "Append a ProgrammingBlock to a channel's schedule for a specific day. day: monday|tuesday|wednesday|thursday|friday|saturday|sunday. block_json is a serialized ProgrammingBlock." )] async fn add_programming_block(&self, #[tool(aggr)] p: AddBlockParams) -> String { let channel_id = match parse_uuid(&p.channel_id) { Ok(id) => id, Err(e) => return e, }; + let day: domain::Weekday = match serde_json::from_str(&format!("\"{}\"", p.day)) { + Ok(d) => d, + Err(e) => { + return serde_json::json!({"error": format!("invalid day: {e}")}).to_string() + } + }; let block: ProgrammingBlock = match serde_json::from_str(&p.block_json) { Ok(b) => b, Err(e) => { return serde_json::json!({"error": format!("invalid block_json: {e}")}).to_string() } }; - channels::add_programming_block(&self.channel_service, channel_id, block).await + channels::add_programming_block(&self.channel_service, channel_id, day, block).await } #[tool(description = "Remove a programming block from a channel's schedule by block UUID")] diff --git a/k-tv-backend/mcp/src/tools/channels.rs b/k-tv-backend/mcp/src/tools/channels.rs index b1012fd..e780d6a 100644 --- a/k-tv-backend/mcp/src/tools/channels.rs +++ b/k-tv-backend/mcp/src/tools/channels.rs @@ -95,13 +95,17 @@ pub async fn set_schedule_config( pub async fn add_programming_block( svc: &Arc, channel_id: Uuid, + day: domain::Weekday, block: domain::ProgrammingBlock, ) -> String { let mut channel: Channel = match svc.find_by_id(channel_id).await { Ok(c) => c, Err(e) => return domain_err(e), }; - channel.schedule_config.blocks.push(block); + channel.schedule_config.day_blocks + .entry(day) + .or_default() + .push(block); channel.updated_at = chrono::Utc::now(); match svc.update(channel).await { Ok(c) => ok_json(&c), @@ -118,7 +122,9 @@ pub async fn remove_programming_block( Ok(c) => c, Err(e) => return domain_err(e), }; - channel.schedule_config.blocks.retain(|b| b.id != block_id); + for blocks in channel.schedule_config.day_blocks.values_mut() { + blocks.retain(|b| b.id != block_id); + } channel.updated_at = chrono::Utc::now(); match svc.update(channel).await { Ok(c) => ok_json(&c),