diff --git a/src/main/java/it/cnr/isti/workflow/manager/blocks/configurations/MCPAgentUploadInput.java b/src/main/java/it/cnr/isti/workflow/manager/blocks/configurations/MCPAgentUploadInput.java index 4fa9852..da27aa0 100644 --- a/src/main/java/it/cnr/isti/workflow/manager/blocks/configurations/MCPAgentUploadInput.java +++ b/src/main/java/it/cnr/isti/workflow/manager/blocks/configurations/MCPAgentUploadInput.java @@ -1,5 +1,6 @@ package it.cnr.isti.workflow.manager.blocks.configurations; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import it.cnr.isti.workflow.manager.configurations.annotations.FieldRetriever; @@ -40,7 +41,15 @@ public record MCPAgentUploadInput( this(name, kind, multiple, null); } - /** Whether this attachment comes from a global input rather than a port of its own. */ + /** + * Whether this attachment comes from a global input rather than a port of its own. + * + *
{@code @JsonIgnore} because Jackson reads an is-prefixed no-arg boolean as a property:
+ * without it a "fromGlobalInput" field appeared in every API payload and every persisted flow,
+ * in a shape the schema does not declare - the same trap {@code ModelParameters.isEmpty} carries
+ * the same guard for.
+ */
+ @JsonIgnore
public boolean isFromGlobalInput() {
return globalInput != null && !globalInput.isBlank();
}
diff --git a/src/test/java/it/cnr/isti/workflow/manager/blocks/configurations/MCPAgentUploadGlobalSchemaTest.java b/src/test/java/it/cnr/isti/workflow/manager/blocks/configurations/MCPAgentUploadGlobalSchemaTest.java
new file mode 100644
index 0000000..88e44ba
--- /dev/null
+++ b/src/test/java/it/cnr/isti/workflow/manager/blocks/configurations/MCPAgentUploadGlobalSchemaTest.java
@@ -0,0 +1,55 @@
+package it.cnr.isti.workflow.manager.blocks.configurations;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.TestPropertySource;
+
+import tools.jackson.databind.JsonNode;
+
+import it.cnr.isti.workflow.manager.app.ObjectMapperHolder;
+import it.cnr.isti.workflow.manager.blocks.Block;
+import it.cnr.isti.workflow.manager.blocks.types.MCPAgentBlockType;
+import it.cnr.isti.workflow.manager.controllers.BlocksController;
+
+@SpringBootTest
+@TestPropertySource(locations = "classpath:test.properties")
+public class MCPAgentUploadGlobalSchemaTest {
+
+ @Autowired
+ private JsonSchemaProducer schemaProducer;
+
+ @Autowired
+ private BlocksController blocksController;
+
+ @Test
+ public void theEditorIsToldAnUploadCanNameAGlobal() {
+ JsonNode schema = schemaProducer.generateSchemaNode(MCPAgentBlockConfiguration.class);
+ assertNotNull(schema);
+ String asText = schema.toString();
+ assertTrue(asText.contains("globalInput"), "the upload input schema must carry the new field: " + asText);
+ }
+
+ @Test
+ public void aBlockWhoseUploadNamesAGlobalSurvivesTheRoundTripTheEditorMakes() {
+ // Exactly what the editor posts back when the field is filled from the dropdown.
+ String payload = """
+ {"type":"MCPAgentBlockConfiguration","name":"Read the plan","model":"llama3.1:8b",
+ "prompt":"Summarize the attached plan","mcpServers":[],
+ "uploadInputs":[{"name":"planDoc","kind":"DOCUMENT","multiple":false,"globalInput":"document"}],
+ "shareSession":false,"useSharedSession":false}
+ """;
+ MCPAgentBlockConfiguration configuration =
+ ObjectMapperHolder.mapper.readValue(payload, MCPAgentBlockConfiguration.class);
+ assertEquals("document", configuration.getUploadInputs().getFirst().globalInput());
+
+ Block