office-dynamixs-ai/dynamixs-ai-mcp/src/main/java/ai/dynamixs/mcp/MCPTool.java

283 lines
No EOL
8.7 KiB
Java

package ai.dynamixs.mcp;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import jakarta.json.Json;
import jakarta.json.JsonObject;
import jakarta.json.JsonObjectBuilder;
/**
* Represents an MCP Tool based on Imixs-Workflow BPMN models.
*
* MCP Tools represent functions that can be called by the MCP client. Each tool
* corresponds to a workflow task/event combination.
*/
public class MCPTool implements Serializable {
private static final long serialVersionUID = 1L;
// MCP Standard Fields
private String name; // Tool name/identifier
private String description; // Tool description
private JsonObject inputSchema; // JSON Schema for input parameters
// Imixs-specific fields
private String modelVersion;
private int taskId;
private int eventId;
private List<String> tags;
private List<String> examples;
// Constructors
public MCPTool() {
this.tags = new ArrayList<>();
this.examples = new ArrayList<>();
}
public MCPTool(String modelVersion, int taskId, int eventId) {
this();
this.modelVersion = modelVersion;
this.taskId = taskId;
this.eventId = eventId;
this.name = createToolName(modelVersion, taskId, eventId);
}
/**
* Creates a tool name from Imixs workflow components
*/
public static String createToolName(String modelVersion, int taskId, int eventId) {
if (modelVersion == null || modelVersion.trim().isEmpty()) {
throw new IllegalArgumentException("Model version cannot be null or empty");
}
return String.format("%s_%d_%d", modelVersion.replace("-", "_"), taskId, eventId);
}
/**
* Parses model version from tool name
*/
public String getModelVersionFromName() {
if (name == null || !name.contains("_")) {
throw new IllegalStateException("Invalid tool name format: " + name);
}
return name.substring(0, name.lastIndexOf('_', name.lastIndexOf('_') - 1)).replace("_", "-");
}
/**
* Parses task ID from tool name
*/
public int getTaskIdFromName() {
if (name == null || !name.contains("_")) {
throw new IllegalStateException("Invalid tool name format: " + name);
}
String[] parts = name.split("_");
if (parts.length < 3) {
throw new IllegalStateException("Invalid tool name format: " + name);
}
try {
return Integer.parseInt(parts[parts.length - 2]);
} catch (NumberFormatException e) {
throw new IllegalStateException("Invalid task ID in tool name: " + name, e);
}
}
/**
* Parses event ID from tool name
*/
public int getEventIdFromName() {
if (name == null || !name.contains("_")) {
throw new IllegalStateException("Invalid tool name format: " + name);
}
String[] parts = name.split("_");
if (parts.length < 3) {
throw new IllegalStateException("Invalid tool name format: " + name);
}
try {
return Integer.parseInt(parts[parts.length - 1]);
} catch (NumberFormatException e) {
throw new IllegalStateException("Invalid event ID in tool name: " + name, e);
}
}
/**
* Creates a default input schema for workflow tools
*/
public JsonObject createDefaultInputSchema() {
return Json.createObjectBuilder()
.add("type", "object")
.add("properties", Json.createObjectBuilder()
.add("workitem", Json.createObjectBuilder()
.add("type", "object")
.add("description", "Workflow item data")
.add("properties", Json.createObjectBuilder()
.add("$modelversion", Json.createObjectBuilder()
.add("type", "string")
.add("description", "Workflow model version")
.build())
.add("$taskid", Json.createObjectBuilder()
.add("type", "integer")
.add("description", "Task ID")
.build())
.add("$eventid", Json.createObjectBuilder()
.add("type", "integer")
.add("description", "Event ID")
.build())
.build())
.add("required", Json.createArrayBuilder()
.add("$modelversion")
.add("$taskid")
.add("$eventid")
.build())
.build())
.build())
.add("required", Json.createArrayBuilder()
.add("workitem")
.build())
.build();
}
/**
* Converts this tool to MCP JSON format
*/
public JsonObject toJsonObject() {
JsonObjectBuilder builder = Json.createObjectBuilder()
.add("name", name != null ? name : "")
.add("description", description != null ? description : "");
// Input schema
if (inputSchema != null) {
builder.add("inputSchema", inputSchema);
} else {
builder.add("inputSchema", createDefaultInputSchema());
}
return builder.build();
}
/**
* Creates an MCPTool from a JsonObject
*/
public static MCPTool fromJsonObject(JsonObject jsonObject) {
MCPTool tool = new MCPTool();
tool.setName(jsonObject.getString("name", ""));
tool.setDescription(jsonObject.getString("description", ""));
if (jsonObject.containsKey("inputSchema")) {
tool.setInputSchema(jsonObject.getJsonObject("inputSchema"));
}
return tool;
}
/**
* Validates this tool for MCP compliance
*/
public boolean isValid() {
if (name == null || name.trim().isEmpty()) {
return false;
}
if (description == null || description.trim().isEmpty()) {
return false;
}
// Validate tool name format
try {
getModelVersionFromName();
getTaskIdFromName();
getEventIdFromName();
} catch (Exception e) {
return false;
}
return true;
}
// Getters and Setters
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public JsonObject getInputSchema() {
return inputSchema;
}
public void setInputSchema(JsonObject inputSchema) {
this.inputSchema = inputSchema;
}
public String getModelVersion() {
return modelVersion;
}
public void setModelVersion(String modelVersion) {
this.modelVersion = modelVersion;
}
public int getTaskId() {
return taskId;
}
public void setTaskId(int taskId) {
this.taskId = taskId;
}
public int getEventId() {
return eventId;
}
public void setEventId(int eventId) {
this.eventId = eventId;
}
public List<String> getTags() {
return tags;
}
public void setTags(List<String> tags) {
this.tags = tags != null ? tags : new ArrayList<>();
}
public List<String> getExamples() {
return examples;
}
public void setExamples(List<String> examples) {
this.examples = examples != null ? examples : new ArrayList<>();
}
@Override
public String toString() {
return String.format("MCPTool{name='%s', description='%s', modelVersion='%s', taskId=%d, eventId=%d}",
name, description, modelVersion, taskId, eventId);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null || getClass() != obj.getClass())
return false;
MCPTool that = (MCPTool) obj;
return name != null ? name.equals(that.name) : that.name == null;
}
@Override
public int hashCode() {
return name != null ? name.hashCode() : 0;
}
}