1+ package com .dddheroes .heroesofddd .creaturerecruitment .write .changeavailablecreatures ;
2+
3+ import com .dddheroes .heroesofddd .shared .application .GameMetaData ;
4+ import org .axonframework .commandhandling .gateway .CommandGateway ;
5+ import org .jetbrains .annotations .NotNull ;
6+ import org .springframework .ai .chat .model .ToolContext ;
7+ import org .springframework .ai .tool .ToolCallbackProvider ;
8+ import org .springframework .ai .tool .annotation .Tool ;
9+ import org .springframework .ai .tool .annotation .ToolParam ;
10+ import org .springframework .ai .tool .method .MethodToolCallbackProvider ;
11+ import org .springframework .context .annotation .Bean ;
12+ import org .springframework .context .annotation .Configuration ;
13+ import org .springframework .stereotype .Component ;
14+
15+ import java .util .Map ;
16+ import java .util .concurrent .CompletableFuture ;
17+
18+ public class IncreaseAvailableCreaturesMcp {
19+
20+ @ Component
21+ static class Tools {
22+
23+ private final CommandGateway commandGateway ;
24+
25+ public Tools (CommandGateway commandGateway ) {
26+ this .commandGateway = commandGateway ;
27+ }
28+
29+ @ Tool (
30+ name = "increase_available_creatures" ,
31+ description = "Increase the number of available creatures in a dwelling. This affects how many creatures can be recruited from this dwelling. The playerId should be provided via MCP client context (similar to REST API headers)."
32+ )
33+ public CompletableFuture <Map <String , Object >> increaseAvailableCreatures (
34+ @ ToolParam (description = "Unique identifier for the game instance" ) String gameId ,
35+ @ ToolParam (description = "Unique identifier for the dwelling to modify" ) String dwellingId ,
36+ @ ToolParam (description = "Type of creature to increase availability for (e.g., 'ANGEL', 'DRAGON', 'GRIFFIN')" ) String creatureId ,
37+ @ ToolParam (description = "Number of creatures to increase availability by (positive integer)" ) Integer increaseBy ,
38+ ToolContext toolContext
39+ ) {
40+ var playerId = playerId (toolContext );
41+
42+ var command = IncreaseAvailableCreatures .command (dwellingId , creatureId , increaseBy );
43+
44+ return commandGateway .send (command , GameMetaData .with (gameId , playerId ))
45+ .thenApply (_ -> success (dwellingId , creatureId , increaseBy , playerId ))
46+ .exceptionally (throwable -> failure (dwellingId , throwable ));
47+ }
48+
49+ @ NotNull
50+ private static Map <String , Object > success (String dwellingId , String creatureId , Integer increaseBy , String playerId ) {
51+ return Map .of (
52+ "success" , true ,
53+ "dwellingId" , dwellingId ,
54+ "creatureId" , creatureId ,
55+ "increaseBy" , increaseBy ,
56+ "playerId" , playerId ,
57+ "message" , "Available creatures increased successfully"
58+ );
59+ }
60+
61+ @ NotNull
62+ private static Map <String , Object > failure (String dwellingId , Throwable throwable ) {
63+ return Map .of (
64+ "success" , false ,
65+ "error" , throwable != null ? throwable .getMessage () : "Unknown error" ,
66+ "dwellingId" , dwellingId ,
67+ "message" , "Failed to increase available creatures: " + (throwable != null ? throwable .getMessage () : "Unknown error" )
68+ );
69+ }
70+
71+ private String playerId (ToolContext toolContext ) {
72+ return (String ) toolContext .getContext ().getOrDefault ("playerId" , "default-player-id" );
73+ }
74+
75+ }
76+
77+ @ Configuration
78+ static class Config {
79+
80+ @ Bean
81+ ToolCallbackProvider increaseAvailableCreaturesTool (IncreaseAvailableCreaturesMcp .Tools sliceTools ) {
82+ return MethodToolCallbackProvider .builder ().toolObjects (sliceTools ).build ();
83+ }
84+
85+ }
86+ }
0 commit comments