Skip to content

Commit 26ae07a

Browse files
committed
refactor(server): Improve parameter conversion logic in McpServerToolFactory and enhance tool invocation tests
1 parent dcf1eb4 commit 26ae07a

File tree

3 files changed

+38
-25
lines changed

3 files changed

+38
-25
lines changed

src/main/java/com/github/codeboyzhou/mcp/declarative/server/component/McpServerToolFactory.java

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,8 @@ public McpServerFeatures.SyncToolSpecification create(Class<?> clazz, Method met
5353
boolean isError = false;
5454
try {
5555
Object instance = InjectorProvider.getInstance().getInjector().getInstance(clazz);
56-
Map<String, Object> args = request.arguments();
57-
Map<String, Object> typedArgs = asTypedParameters(paramSchema, args);
58-
result = method.invoke(instance, typedArgs.values().toArray());
56+
List<Object> typedValues = asTypedParameterValues(method, request.arguments());
57+
result = method.invoke(instance, typedValues.toArray());
5958
} catch (Exception e) {
6059
log.error("Error invoking tool method", e);
6160
result = e + ": " + e.getMessage();
@@ -147,23 +146,23 @@ private Map<String, Object> createJsonSchemaDefinition(Class<?> definitionClass)
147146
return definitionJsonSchema;
148147
}
149148

150-
@SuppressWarnings("unchecked")
151-
private Map<String, Object> asTypedParameters(
152-
McpSchema.JsonSchema schema, Map<String, Object> parameters) {
153-
Map<String, Object> properties = schema.properties();
154-
Map<String, Object> typedParameters = new LinkedHashMap<>(properties.size());
155-
156-
properties.forEach(
157-
(parameterName, parameterProperties) -> {
158-
Object parameterValue = parameters.get(parameterName);
159-
// Fill in a default value when the parameter is not specified
160-
// to ensure that the parameter type is correct when calling method.invoke()
161-
Map<String, Object> map = (Map<String, Object>) parameterProperties;
162-
final String jsonSchemaType = map.getOrDefault("type", Strings.EMPTY).toString();
163-
Object typedParameterValue = Types.convert(parameterValue, jsonSchemaType);
164-
typedParameters.put(parameterName, typedParameterValue);
165-
});
166-
167-
return typedParameters;
149+
private List<Object> asTypedParameterValues(Method method, Map<String, Object> parameters) {
150+
Parameter[] methodParams = method.getParameters();
151+
List<Object> typedValues = new ArrayList<>(methodParams.length);
152+
153+
for (Parameter param : methodParams) {
154+
Object rawValue = null;
155+
if (param.isAnnotationPresent(McpToolParam.class)) {
156+
McpToolParam toolParam = param.getAnnotation(McpToolParam.class);
157+
rawValue = parameters.get(toolParam.name());
158+
}
159+
// Fill in a default value when the parameter is not specified or unannotated
160+
// to ensure that the parameter type is correct when calling method.invoke()
161+
Class<?> targetType = param.getType();
162+
Object typed = Types.convert(rawValue, targetType);
163+
typedValues.add(typed);
164+
}
165+
166+
return typedValues;
168167
}
169168
}

src/test/java/com/github/codeboyzhou/mcp/declarative/McpServersTest.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
import static org.junit.jupiter.api.Assertions.assertFalse;
66
import static org.junit.jupiter.api.Assertions.assertSame;
77
import static org.junit.jupiter.api.Assertions.assertThrows;
8-
import static org.junit.jupiter.api.Assertions.assertTrue;
98

109
import com.github.codeboyzhou.mcp.declarative.configuration.McpServerConfiguration;
1110
import com.github.codeboyzhou.mcp.declarative.configuration.YAMLConfigurationLoader;
@@ -161,6 +160,7 @@ private void verify(McpSyncClient client) {
161160
verifyPromptsRegistered(client);
162161
verifyToolsRegistered(client);
163162
verifyPromptsCalled(client);
163+
verifyToolsCalled(client);
164164
}
165165

166166
private void verifyServerInfo(McpSyncClient client) {
@@ -217,6 +217,15 @@ private void verifyToolsRegistered(McpSyncClient client) {
217217
assertEquals("tool1_name", tool.name());
218218
assertEquals("tool1_title", tool.title());
219219
assertEquals("tool1_description", tool.description());
220-
assertTrue(tool.inputSchema().properties().isEmpty());
220+
}
221+
222+
private void verifyToolsCalled(McpSyncClient client) {
223+
String name1 = "tool1_name";
224+
Map<String, Object> args1 = Map.of("param1", "value1", "param2", "value2");
225+
McpSchema.CallToolRequest request1 = new McpSchema.CallToolRequest(name1, args1);
226+
McpSchema.CallToolResult result1 = client.callTool(request1);
227+
McpSchema.TextContent content = (McpSchema.TextContent) result1.content().get(0);
228+
assertEquals(ObjectMappers.toJson(args1), content.text());
229+
assertFalse(result1.isError());
221230
}
222231
}
Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
package com.github.codeboyzhou.mcp.declarative.test;
22

33
import com.github.codeboyzhou.mcp.declarative.annotation.McpTool;
4+
import com.github.codeboyzhou.mcp.declarative.annotation.McpToolParam;
5+
import com.github.codeboyzhou.mcp.declarative.util.ObjectMappers;
6+
import java.util.Map;
47

58
public class TestMcpTools {
69

710
@McpTool(name = "tool1_name", title = "tool1_title", description = "tool1_description")
8-
public String tool1() {
9-
return "tool1_content";
11+
public String tool1(
12+
@McpToolParam(name = "param1", description = "param1_description") String param1,
13+
@McpToolParam(name = "param2", description = "param2_description") String param2) {
14+
return ObjectMappers.toJson(Map.of("param1", param1, "param2", param2));
1015
}
1116
}

0 commit comments

Comments
 (0)