package mcp.server; import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import mcp.registry.DynamicToolLoader; import mcp.registry.ToolRegistry; import mcp.tools.McpTool; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import mcp.util.Err; import mcp.util.Ok; import mcp.util.Result; import java.io.IOException; import java.util.Map; /** * A Servlet that provides an endpoint for dynamic registration of external tools. *

* Expects a POST request with a JSON body: *

 * {
 *   "jarPath": "/path/to/tools.jar",
 *   "className": "com.example.MyTool"
 * }
 * 
*/ public class ToolRegistrationServlet extends HttpServlet { private static final Logger logger = LoggerFactory.getLogger(ToolRegistrationServlet.class); private final ToolRegistry toolRegistry; private final ObjectMapper objectMapper = new ObjectMapper(); public ToolRegistrationServlet(ToolRegistry toolRegistry) { this.toolRegistry = toolRegistry; } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException { logger.debug("Received tool registration request"); try { Map body = objectMapper.readValue(req.getInputStream(), Map.class); String jarPath = body.get("jarPath"); String className = body.get("className"); if (jarPath == null || className == null) { logger.warn("Missing jarPath or className in registration request"); resp.setStatus(HttpServletResponse.SC_BAD_REQUEST); resp.getWriter().write("Missing jarPath or className"); return; } logger.info("Attempting to register tool: {} from {}", className, jarPath); final Result result = registerTool(jarPath, className); switch (result) { case Ok ok -> { final McpTool tool = ok.value(); logger.info("Tool registered successfully: {}", tool.name()); resp.setStatus(HttpServletResponse.SC_OK); resp.getWriter().write("Tool registered successfully: " + tool.name()); } case Err err -> { logger.error("Error registering tool: {}", err.throwable().getMessage()); resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); resp.getWriter().write("Error registering tool: " + err.throwable().getMessage()); } } } catch (Exception e) { logger.error("Unexpected error during tool registration", e); resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); resp.getWriter().write("Error registering tool: " + e.getMessage()); } } public Result registerTool(final String jarPath, final String className) { try { McpTool tool = DynamicToolLoader.loadTool(jarPath, className); toolRegistry.register(tool); return new Ok<>(tool); } catch (Exception e) { return new Err<>(e); } } }