Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion plugin/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@
<!-- MCP stack versions (override pom-scijava where needed). The MCP SDK and
Jetty 12 require Java 17 bytecode, so they cannot live on Fiji's shared
classpath; they are bundled into an isolated lib/mcp-bundle.jar instead. -->
<mcp.version>1.1.2</mcp.version>
<mcp.version>2.0.0</mcp.version>
<jetty.version>12.0.16</jetty.version>
<jackson.version>2.18.0</jackson.version>
<slf4j.version>2.0.9</slf4j.version>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@
public class AnalyzeBioimagePrompt {

public static McpSchema.Prompt definition() {
return new McpSchema.Prompt("analyze_bioimage",
"Template for bioimage analysis workflows in Fiji",
List.of(
new McpSchema.PromptArgument("task",
"Analysis goal (e.g., 'segment objects', 'measure fluorescence')", false)
));
return McpSchema.Prompt.builder("analyze_bioimage")
.description("Template for bioimage analysis workflows in Fiji")
.arguments(List.of(
McpSchema.PromptArgument.builder("task")
.description("Analysis goal (e.g., 'segment objects', 'measure fluorescence')")
.required(false)
.build()))
.build();
}

public McpSchema.GetPromptResult handle(McpSyncServerExchange exchange, McpSchema.GetPromptRequest request) {
Expand All @@ -39,7 +41,8 @@ public McpSchema.GetPromptResult handle(McpSyncServerExchange exchange, McpSchem
5. Execute the macro with run_macro and verify results with capture_fiji_screen
""".formatted(task);

return new McpSchema.GetPromptResult(null, List.of(
new McpSchema.PromptMessage(McpSchema.Role.USER, new McpSchema.TextContent(promptText))));
return McpSchema.GetPromptResult.builder(List.of(
new McpSchema.PromptMessage(McpSchema.Role.USER, McpSchema.TextContent.builder(promptText).build())))
.build();
}
}
23 changes: 15 additions & 8 deletions plugin/src/main/java/copilotj/mcp/prompts/DebugMacroPrompt.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,18 @@
public class DebugMacroPrompt {

public static McpSchema.Prompt definition() {
return new McpSchema.Prompt("debug_macro",
"Template for debugging ImageJ macro errors",
List.of(
new McpSchema.PromptArgument("error_message", "The error message received", true),
new McpSchema.PromptArgument("original_script", "The macro script that caused the error", true)
));
return McpSchema.Prompt.builder("debug_macro")
.description("Template for debugging ImageJ macro errors")
.arguments(List.of(
McpSchema.PromptArgument.builder("error_message")
.description("The error message received")
.required(true)
.build(),
McpSchema.PromptArgument.builder("original_script")
.description("The macro script that caused the error")
.required(true)
.build()))
.build();
}

public McpSchema.GetPromptResult handle(McpSyncServerExchange exchange, McpSchema.GetPromptRequest request) {
Expand All @@ -46,7 +52,8 @@ public McpSchema.GetPromptResult handle(McpSyncServerExchange exchange, McpSchem
4. Test the corrected macro with run_macro
""".formatted(errorMessage, originalScript);

return new McpSchema.GetPromptResult(null, List.of(
new McpSchema.PromptMessage(McpSchema.Role.USER, new McpSchema.TextContent(promptText))));
return McpSchema.GetPromptResult.builder(List.of(
new McpSchema.PromptMessage(McpSchema.Role.USER, McpSchema.TextContent.builder(promptText).build())))
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,7 @@ public EnvironmentResource(EventHandler handler) {
}

public static McpSchema.Resource definition() {
return McpSchema.Resource.builder()
.uri("fiji://environment")
.name("fiji-environment")
return McpSchema.Resource.builder("fiji://environment", "fiji-environment")
.description("Fiji/ImageJ2 environment information")
.mimeType("application/json")
.build();
Expand All @@ -34,12 +32,13 @@ public static McpSchema.Resource definition() {
public McpSchema.ReadResourceResult handle(McpSyncServerExchange exchange, McpSchema.ReadResourceRequest request) {
try {
String result = McpModule.callEvent(handler, "summarise_environment", null);
return new McpSchema.ReadResourceResult(
List.of(new McpSchema.TextResourceContents(request.uri(), "application/json", result)));
return McpSchema.ReadResourceResult.builder(List.of(
McpSchema.TextResourceContents.builder(request.uri(), result)
.mimeType("application/json").build())).build();
} catch (Exception e) {
return new McpSchema.ReadResourceResult(
List.of(new McpSchema.TextResourceContents(request.uri(), "application/json",
"{\"error\": \"Fiji not connected\"}")));
return McpSchema.ReadResourceResult.builder(List.of(
McpSchema.TextResourceContents.builder(request.uri(), "{\"error\": \"Fiji not connected\"}")
.mimeType("application/json").build())).build();
}
}
}
15 changes: 7 additions & 8 deletions plugin/src/main/java/copilotj/mcp/resources/WindowsResource.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,7 @@ public WindowsResource(EventHandler handler) {
}

public static McpSchema.Resource definition() {
return McpSchema.Resource.builder()
.uri("fiji://windows")
.name("fiji-windows")
return McpSchema.Resource.builder("fiji://windows", "fiji-windows")
.description("Currently open Fiji windows")
.mimeType("application/json")
.build();
Expand All @@ -34,12 +32,13 @@ public static McpSchema.Resource definition() {
public McpSchema.ReadResourceResult handle(McpSyncServerExchange exchange, McpSchema.ReadResourceRequest request) {
try {
String result = McpModule.callEvent(handler, "take_snapshot", null);
return new McpSchema.ReadResourceResult(
List.of(new McpSchema.TextResourceContents(request.uri(), "application/json", result)));
return McpSchema.ReadResourceResult.builder(List.of(
McpSchema.TextResourceContents.builder(request.uri(), result)
.mimeType("application/json").build())).build();
} catch (Exception e) {
return new McpSchema.ReadResourceResult(
List.of(new McpSchema.TextResourceContents(request.uri(), "application/json",
"{\"error\": \"Fiji not connected\"}")));
return McpSchema.ReadResourceResult.builder(List.of(
McpSchema.TextResourceContents.builder(request.uri(), "{\"error\": \"Fiji not connected\"}")
.mimeType("application/json").build())).build();
}
}
}
21 changes: 10 additions & 11 deletions plugin/src/main/java/copilotj/mcp/tools/CallActionTool.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,17 @@ public CallActionTool(EventHandler handler) {
}

public static McpSchema.Tool definition() {
return McpSchema.Tool.builder()
.name("call_action")
return McpSchema.Tool.builder("call_action",
Map.of(
"type", "object",
"properties", Map.of(
"snapshot_id", Map.of("type", "integer", "description", "Snapshot ID from take_snapshot"),
"action_id", Map.of("type", "integer", "description", "Action ID within the snapshot"),
"parameters", Map.of("type", "array", "description", "Action parameters", "items", Map.of())),
"required", List.of("snapshot_id", "action_id")))
.description("Execute a UI action from a previous snapshot. "
+ "First call take_snapshot() to get available actions and their IDs, "
+ "then call this with the snapshot_id and action_id.")
.inputSchema(new McpSchema.JsonSchema("object",
Map.of(
"snapshot_id", Map.of("type", "integer", "description", "Snapshot ID from take_snapshot"),
"action_id", Map.of("type", "integer", "description", "Action ID within the snapshot"),
"parameters", Map.of("type", "array", "description", "Action parameters", "items", Map.of())
),
List.of("snapshot_id", "action_id"), true, null, null))
.build();
}

Expand All @@ -51,11 +50,11 @@ public McpSchema.CallToolResult handle(McpSyncServerExchange exchange, McpSchema
try {
String result = McpModule.callEvent(handler, "run_action", data);
return McpSchema.CallToolResult.builder()
.content(List.of(new McpSchema.TextContent(result)))
.content(List.of(McpSchema.TextContent.builder(result).build()))
.build();
} catch (Exception e) {
return McpSchema.CallToolResult.builder()
.content(List.of(new McpSchema.TextContent("Failed to execute action: " + e.getMessage())))
.content(List.of(McpSchema.TextContent.builder("Failed to execute action: " + e.getMessage()).build()))
.isError(true)
.build();
}
Expand Down
18 changes: 9 additions & 9 deletions plugin/src/main/java/copilotj/mcp/tools/CaptureImageTool.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,14 @@ public CaptureImageTool(EventHandler handler) {
}

public static McpSchema.Tool definition() {
return McpSchema.Tool.builder()
.name("capture_image")
return McpSchema.Tool.builder("capture_image",
Map.of(
"type", "object",
"properties", Map.of(
"title", Map.of("type", "string", "description", "Window title of the image to capture (optional)"))))
.description("Capture the current active Fiji image with metadata. "
+ "Returns image content along with dimensions, bit depth, and histogram. "
+ "Optionally specify a window title to capture a specific image.")
.inputSchema(new McpSchema.JsonSchema("object",
Map.of("title", Map.of("type", "string", "description", "Window title of the image to capture (optional)")),
null, true, null, null))
.build();
}

Expand All @@ -58,15 +58,15 @@ public McpSchema.CallToolResult handle(McpSyncServerExchange exchange, McpSchema
metadata.put("histogram", McpModule.objectMapper.convertValue(root.get("histogram"), Map.class));
}
if (!metadata.isEmpty()) {
content.add(new McpSchema.TextContent(
McpModule.objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(metadata)));
content.add(McpSchema.TextContent.builder(
McpModule.objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(metadata)).build());
}

if (root.has("image") && !root.get("image").isNull()) {
// The image is stored as a data URI ("data:image/png;base64,…");
// keep only the base64 payload for ImageContent.
String base64Image = IjImageHelper.extractBase64(root.get("image").asText());
content.add(new McpSchema.ImageContent(null, base64Image, "image/png"));
content.add(McpSchema.ImageContent.builder(base64Image, "image/png").build());
}

if (content.isEmpty()) {
Expand All @@ -81,7 +81,7 @@ public McpSchema.CallToolResult handle(McpSyncServerExchange exchange, McpSchema

private static McpSchema.CallToolResult error(String msg) {
return McpSchema.CallToolResult.builder()
.content(List.of(new McpSchema.TextContent(msg)))
.content(List.of(McpSchema.TextContent.builder(msg).build()))
.isError(true)
.build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,9 @@ public CaptureScreenTool(EventHandler handler) {
}

public static McpSchema.Tool definition() {
return McpSchema.Tool.builder()
.name("capture_fiji_screen")
return McpSchema.Tool.builder("capture_fiji_screen", Map.of("type", "object"))
.description("Capture the current Fiji screen as a PNG image. "
+ "Returns a screenshot showing all open Fiji windows and their state.")
.inputSchema(new McpSchema.JsonSchema("object", Map.of(), null, true, null, null))
.build();
}

Expand All @@ -51,7 +49,7 @@ public McpSchema.CallToolResult handle(McpSyncServerExchange exchange, McpSchema
String base64Image = IjImageHelper.extractBase64(screenshots.get(0).get("image").asText());

return McpSchema.CallToolResult.builder()
.content(List.of(new McpSchema.ImageContent(null, base64Image, "image/png")))
.content(List.of(McpSchema.ImageContent.builder(base64Image, "image/png").build()))
.build();
} catch (Exception e) {
return error("Failed to capture screen: " + e.getMessage());
Expand All @@ -60,7 +58,7 @@ public McpSchema.CallToolResult handle(McpSyncServerExchange exchange, McpSchema

private static McpSchema.CallToolResult error(String msg) {
return McpSchema.CallToolResult.builder()
.content(List.of(new McpSchema.TextContent(msg)))
.content(List.of(McpSchema.TextContent.builder(msg).build()))
.isError(true)
.build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,23 +24,21 @@ public FijiEnvironmentTool(EventHandler handler) {
}

public static McpSchema.Tool definition() {
return McpSchema.Tool.builder()
.name("fiji_environment")
return McpSchema.Tool.builder("fiji_environment", Map.of("type", "object"))
.description("Get Fiji/ImageJ2 environment information. "
+ "Returns ImageJ home, Java version, installed plugins, and other system details.")
.inputSchema(new McpSchema.JsonSchema("object", Map.of(), null, true, null, null))
.build();
}

public McpSchema.CallToolResult handle(McpSyncServerExchange exchange, McpSchema.CallToolRequest request) {
try {
String result = McpModule.callEvent(handler, "summarise_environment", null);
return McpSchema.CallToolResult.builder()
.content(List.of(new McpSchema.TextContent(result)))
.content(List.of(McpSchema.TextContent.builder(result).build()))
.build();
} catch (Exception e) {
return McpSchema.CallToolResult.builder()
.content(List.of(new McpSchema.TextContent("Failed to get environment: " + e.getMessage())))
.content(List.of(McpSchema.TextContent.builder("Failed to get environment: " + e.getMessage()).build()))
.isError(true)
.build();
}
Expand Down
15 changes: 8 additions & 7 deletions plugin/src/main/java/copilotj/mcp/tools/FolderSummaryTool.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,15 @@ public class FolderSummaryTool {
private static final int MAX_FILES = 300;

public static McpSchema.Tool definition() {
return McpSchema.Tool.builder()
.name("folder_summary")
return McpSchema.Tool.builder("folder_summary",
Map.of(
"type", "object",
"properties", Map.of(
"folder_path", Map.of("type", "string", "description", "Absolute or relative directory path")),
"required", List.of("folder_path")))
.description("List files in a directory on the local filesystem. "
+ "Useful for discovering image files to open in Fiji. "
+ "Returns up to 300 items with relative paths.")
.inputSchema(new McpSchema.JsonSchema("object",
Map.of("folder_path", Map.of("type", "string", "description", "Absolute or relative directory path")),
List.of("folder_path"), true, null, null))
.build();
}

Expand Down Expand Up @@ -73,13 +74,13 @@ public McpSchema.CallToolResult handle(McpSyncServerExchange exchange, McpSchema
}

return McpSchema.CallToolResult.builder()
.content(List.of(new McpSchema.TextContent(sb.toString())))
.content(List.of(McpSchema.TextContent.builder(sb.toString()).build()))
.build();
}

private static McpSchema.CallToolResult error(String msg) {
return McpSchema.CallToolResult.builder()
.content(List.of(new McpSchema.TextContent(msg)))
.content(List.of(McpSchema.TextContent.builder(msg).build()))
.isError(true)
.build();
}
Expand Down
20 changes: 10 additions & 10 deletions plugin/src/main/java/copilotj/mcp/tools/ListOperationsTool.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@ public ListOperationsTool(EventHandler handler) {
}

public static McpSchema.Tool definition() {
return McpSchema.Tool.builder()
.name("list_operations")
return McpSchema.Tool.builder("list_operations",
Map.of(
"type", "object",
"properties", Map.of(
"since", Map.of("type", "string", "description", "ISO 8601 datetime (e.g., '2026-04-15T10:00:00')"))))
.description("Get recent Fiji operation history. "
+ "Returns list of operations performed since the given datetime (ISO 8601 format). "
+ "If no datetime is provided, returns operations since the last call.")
.inputSchema(new McpSchema.JsonSchema("object",
Map.of("since", Map.of("type", "string", "description", "ISO 8601 datetime (e.g., '2026-04-15T10:00:00')")),
null, true, null, null))
.build();
}

Expand All @@ -42,9 +42,9 @@ public McpSchema.CallToolResult handle(McpSyncServerExchange exchange, McpSchema

if (since == null) {
return McpSchema.CallToolResult.builder()
.content(List.of(new McpSchema.TextContent(
"No timestamp provided and no previous call recorded. "
+ "Please provide a 'since' parameter (ISO 8601 datetime).")))
.content(List.of(McpSchema.TextContent.builder(
"No timestamp provided and no previous call recorded. "
+ "Please provide a 'since' parameter (ISO 8601 datetime).").build()))
.isError(true)
.build();
}
Expand All @@ -56,11 +56,11 @@ public McpSchema.CallToolResult handle(McpSyncServerExchange exchange, McpSchema
// Record timestamp after successful call
lastCallTimestamp = java.time.LocalDateTime.now().toString();
return McpSchema.CallToolResult.builder()
.content(List.of(new McpSchema.TextContent(result)))
.content(List.of(McpSchema.TextContent.builder(result).build()))
.build();
} catch (Exception e) {
return McpSchema.CallToolResult.builder()
.content(List.of(new McpSchema.TextContent("Failed to get operations: " + e.getMessage())))
.content(List.of(McpSchema.TextContent.builder("Failed to get operations: " + e.getMessage()).build()))
.isError(true)
.build();
}
Expand Down
Loading