MCP doc_save: bridge mode refuses headless-only options instead of saving with defaults (#1138)

The bridge branch forwarded only the path to the running app's
app.save, silently dropping quality, format, tiffLayers and index (the
headless branch honours all of them): a client asking for a
quality-50 JPEG got an ok reply and whatever the app's current
settings produce. Those params now fail fast with the reason - naming
headless mode - before anything is written.
This commit is contained in:
Elvis33LE authored and GitHub committed 2026-10-08 16:09:10 -04:00
1 parent cd03d49c34
commit b44cad8747
2 files changed
+34

No files matched your search

+15
View File
@@ -656,6 +656,21 @@ impl PhotocraftMcp {
let Some(path) = p.path else {
return Ok(fail("bridge mode needs `path`"));
};
// The bridge forwards to the running app's `app.save`, which takes a path only:
// the extra options are headless-only. Saying so beats saving with defaults
// while the caller believes their quality or format was applied.
let unsupported: Vec<&str> = [
p.format.is_some().then_some("format"),
p.quality.is_some().then_some("quality"),
p.tiff_layers.then_some("tiffLayers"),
p.index.is_some().then_some("index"),
]
.into_iter()
.flatten()
.collect();
if !unsupported.is_empty() {
return Ok(fail(format!("bridge mode saves with the app's current settings; `{}` need headless mode", unsupported.join("`, `"))));
}
return to_result(b.call("app.save", json!({"path": path})).await);
}
let Some(r) = self
+19
View File
@@ -238,6 +238,25 @@ async fn preview_budget_failure_preserves_the_mcp_session() {
client.cancel().await.unwrap();
}
#[tokio::test(flavor = "multi_thread")]
async fn bridge_doc_save_rejects_headless_only_options_instead_of_saving_with_defaults() {
// Bridge mode forwards only the path to the running app: quality/format/tiffLayers/index
// must be refused up front (no bridge connection needed for that) rather than silently
// saving with the app's current settings.
let server = PhotocraftMcp::bridge("127.0.0.1:1", &"a".repeat(64)).unwrap();
let client = connect(server).await;
for params in [
json!({"path": "out.jpg", "quality": 50}),
json!({"path": "out.png", "format": "png"}),
json!({"path": "out.tif", "tiffLayers": true}),
json!({"path": "out.pcraft", "index": 0}),
] {
let r = call(&client, "doc_save", params.clone()).await;
assert_eq!(r.is_error, Some(true), "{params}: {:?}", text(&r));
assert!(text(&r).contains("headless"), "{params}: {}", text(&r));
}
}
#[tokio::test(flavor = "multi_thread")]
async fn bridge_response_budget_drops_connection_without_retrying_the_operation() {
use photocraft_automation::{BridgeClient, budgets::MAX_RESPONSE_BYTES};