Skip to content

Latest commit

 

History

History
86 lines (67 loc) · 4.41 KB

File metadata and controls

86 lines (67 loc) · 4.41 KB

MCP Dynamic Tool Groups

The Model Context Protocol (MCP) includes support for tools, allowing AI models to a) Get metadata (descriptions) of tool input and output; b) Provide input, call/take action and c) get output via the use of one or more of the available tools.

In this example application the com.composent.ai.mcp.examples.toolgroup.api project declares a ExampleToolGroup interface class, with McpTool and McpToolGroup metadata:

@McpToolGroup(description="Arithmetic operations exposed as mcp tools")
public interface ExampleToolGroup {

	@McpTool(description = "computes the sum of the two double precision input arguments a and b")
	double add(@McpToolParam(description = "x is the first argument") double x,
			@McpToolParam(description = "y is the second argument") double y);

	@McpTool(description = "return the product of the two given double precision arguments named a and b")
	double multiply(@McpToolParam(description = "x is the first argument") double x,
			@McpToolParam(description = "y is the second argument") double y);

	@McpTool(description = "return asynchronously the sum of the two double precision input arguments a and b")
	Mono<Double> asyncAdd(@McpToolParam(description = "x is the first argument") double x,
			@McpToolParam(description = "y is the second argument") double y);

	@McpTool(description = "return asynchronously the product of the two given double precision arguments named a and b")
	Mono<Double> asyncMultiply(@McpToolParam(description = "x is the first argument") double x,
			@McpToolParam(description = "y is the second argument") double y);
}

Each method is annotated with the @McpTool and @McpToolParam annotations from the mcp_annotations_java project. There are both synchronous mcp server methods (add, multiply) and asynchronous mcp server methods (asyncAdd and asyncMultiply).

Notice also the use of @McpToolGroup annotation for the ExampleToolGroup class along with the parent package. This shows the static creation of a hierarchical relationship between the top-level toolgroup (package), and a child toolgroup (class) with two tools (add and multiply) as leaves of this simple toolgroup tree.

Here is an OSGi component implementing the ExampleToolGroup interface.

public class ToolGroupComponent implements ExampleToolGroup {

	private static Logger logger = LoggerFactory.getLogger(ToolGroupComponent.class);

	// This reference will wait for the SyncToolGroupServerComponent
	// to be activated
	@Reference
	private SyncToolGroupServerComponent syncServer;
	// This reference will wait for the AsyncToolGroupServerComponent
	// to be activated
	@Reference
	private AsyncToolgroupServerComponent asyncServer;

	@Activate
	void activate() {
		// Add to syncServer
		syncServer.addToolGroups(this, ExampleToolGroup.class);
		// Add to asyncServer
		asyncServer.addToolGroups(this, ExampleToolGroup.class);
	}

	@Override
	public double add(double x, double y) {
		logger.debug("Adding x={} y={}", x, y);
		return x + y;
	}

	@Override
	public double multiply(double x, double y) {
		logger.debug("Multiplying x={} y={}", x, y);
		return x * y;
	}

	@Override
	public Mono<Double> asyncAdd(double x, double y) {
		logger.debug("Async Adding x={} y={}", x, y);
		return Mono.just(add(x, y));
	}

	@Override
	public Mono<Double> asyncMultiply(double x, double y) {
		logger.debug("Async Multiplying x={} y={}", x, y);
		return Mono.just(multiply(x, y));
	}

}

The ExampleToolGroup tools are processed and added to the appropriate (sync or async) server at runtime with this line:

		syncServer.addToolGroups(this, ExampleToolGroup.class);