Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ and a Java MCP SDK dependency:
<dependency>
<groupId>io.modelcontextprotocol.sdk</groupId>
<artifactId>mcp</artifactId>
<version>0.12.0</version>
<version>0.13.0-SNAPSHOT</version>
</dependency>
```

Expand Down Expand Up @@ -1999,7 +1999,7 @@ public class StatelessMcpServerFactory {

- Java 17 or higher
- Reactor Core (for async operations)
- MCP Java SDK 0.12.0 or higher
- MCP Java SDK 0.13.0-SNAPSHOT or higher

## Building from Source

Expand Down
4 changes: 2 additions & 2 deletions mcp-annotations/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,11 @@
<version>${swagger-annotations.version}</version>
</dependency>

<dependency>
<!-- <dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson-databind.version}</version>
</dependency>
</dependency> -->

<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@
import java.lang.reflect.Method;
import java.util.List;

import io.modelcontextprotocol.json.McpJsonMapper;
import io.modelcontextprotocol.util.Assert;
import org.springaicommunity.mcp.annotation.McpTool;

public abstract class AbstractMcpToolProvider {

protected final List<Object> toolObjects;

protected McpJsonMapper jsonMapper = McpJsonMapper.createDefault();

public AbstractMcpToolProvider(List<Object> toolObjects) {
Assert.notNull(toolObjects, "toolObjects cannot be null");
this.toolObjects = toolObjects;
Expand All @@ -27,4 +30,12 @@ protected Class<? extends Throwable> doGetToolCallException() {
return Exception.class;
}

public void setJsonMapper(McpJsonMapper jsonMapper) {
this.jsonMapper = jsonMapper;
}

public McpJsonMapper getJsonMapper() {
return this.jsonMapper;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import java.util.function.BiFunction;
import java.util.stream.Stream;

import io.modelcontextprotocol.json.McpJsonMapper;
import io.modelcontextprotocol.server.McpAsyncServerExchange;
import io.modelcontextprotocol.server.McpServerFeatures.AsyncToolSpecification;
import io.modelcontextprotocol.spec.McpSchema;
Expand Down Expand Up @@ -79,7 +80,7 @@ public List<AsyncToolSpecification> getToolSpecifications() {
var toolBuilder = McpSchema.Tool.builder()
.name(toolName)
.description(toolDescrption)
.inputSchema(inputSchema);
.inputSchema(this.getJsonMapper(), inputSchema);

var title = toolJavaAnnotation.title();

Expand Down Expand Up @@ -119,8 +120,8 @@ public List<AsyncToolSpecification> getToolSpecifications() {
: null;
if (!ClassUtils.isPrimitiveOrWrapper(methodReturnType)
&& !ClassUtils.isSimpleValueType(methodReturnType)) {
toolBuilder
.outputSchema(JsonSchemaGenerator.generateFromClass((Class<?>) typeArgument));
toolBuilder.outputSchema(this.getJsonMapper(),
JsonSchemaGenerator.generateFromClass((Class<?>) typeArgument));
}
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.util.stream.Stream;

import io.modelcontextprotocol.common.McpTransportContext;
import io.modelcontextprotocol.json.McpJsonMapper;
import io.modelcontextprotocol.server.McpStatelessServerFeatures.AsyncToolSpecification;
import io.modelcontextprotocol.spec.McpSchema;
import io.modelcontextprotocol.spec.McpSchema.CallToolRequest;
Expand Down Expand Up @@ -83,7 +84,7 @@ public List<AsyncToolSpecification> getToolSpecifications() {
var toolBuilder = McpSchema.Tool.builder()
.name(toolName)
.description(toolDescrption)
.inputSchema(inputSchema);
.inputSchema(this.getJsonMapper(), inputSchema);

var title = toolJavaAnnotation.title();

Expand Down Expand Up @@ -123,7 +124,8 @@ public List<AsyncToolSpecification> getToolSpecifications() {
: null;
if (!ClassUtils.isPrimitiveOrWrapper(methodReturnType)
&& !ClassUtils.isSimpleValueType(methodReturnType)) {
toolBuilder.outputSchema(JsonSchemaGenerator.generateFromType(typeArgument));
toolBuilder.outputSchema(this.getJsonMapper(),
JsonSchemaGenerator.generateFromType(typeArgument));
}
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import java.util.function.BiFunction;
import java.util.stream.Stream;

import io.modelcontextprotocol.json.McpJsonMapper;
import io.modelcontextprotocol.server.McpServerFeatures.SyncToolSpecification;
import io.modelcontextprotocol.server.McpSyncServerExchange;
import io.modelcontextprotocol.spec.McpSchema;
Expand Down Expand Up @@ -74,10 +75,10 @@ public List<SyncToolSpecification> getToolSpecifications() {

String inputSchema = JsonSchemaGenerator.generateForMethodInput(mcpToolMethod);

var toolBuilder = McpSchema.Tool.builder()
McpSchema.Tool.Builder toolBuilder = McpSchema.Tool.builder()
.name(toolName)
.description(toolDescription)
.inputSchema(inputSchema);
.inputSchema(this.getJsonMapper(), inputSchema);

var title = toolJavaAnnotation.title();

Expand All @@ -104,8 +105,6 @@ public List<SyncToolSpecification> getToolSpecifications() {
}
toolBuilder.title(title);

// ReactiveUtils.isReactiveReturnTypeOfCallToolResult(mcpToolMethod);

// Generate Output Schema from the method return type.
// Output schema is not generated for primitive types, void,
// CallToolResult, simple value types (String, etc.)
Expand All @@ -116,8 +115,8 @@ public List<SyncToolSpecification> getToolSpecifications() {
&& methodReturnType != void.class && !ClassUtils.isPrimitiveOrWrapper(methodReturnType)
&& !ClassUtils.isSimpleValueType(methodReturnType)) {

toolBuilder
.outputSchema(JsonSchemaGenerator.generateFromType(mcpToolMethod.getGenericReturnType()));
toolBuilder.outputSchema(this.getJsonMapper(),
JsonSchemaGenerator.generateFromType(mcpToolMethod.getGenericReturnType()));
}

var tool = toolBuilder.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.util.stream.Stream;

import io.modelcontextprotocol.common.McpTransportContext;
import io.modelcontextprotocol.json.McpJsonMapper;
import io.modelcontextprotocol.server.McpStatelessServerFeatures.SyncToolSpecification;
import io.modelcontextprotocol.spec.McpSchema;
import io.modelcontextprotocol.spec.McpSchema.CallToolRequest;
Expand Down Expand Up @@ -80,7 +81,7 @@ public List<SyncToolSpecification> getToolSpecifications() {
var toolBuilder = McpSchema.Tool.builder()
.name(toolName)
.description(toolDescrption)
.inputSchema(inputSchema);
.inputSchema(this.getJsonMapper(), inputSchema);

var title = toolJavaAnnotation.title();

Expand Down Expand Up @@ -119,8 +120,8 @@ public List<SyncToolSpecification> getToolSpecifications() {
&& methodReturnType != void.class && !ClassUtils.isPrimitiveOrWrapper(methodReturnType)
&& !ClassUtils.isSimpleValueType(methodReturnType)) {

toolBuilder
.outputSchema(JsonSchemaGenerator.generateFromType(mcpToolMethod.getGenericReturnType()));
toolBuilder.outputSchema(this.getJsonMapper(),
JsonSchemaGenerator.generateFromType(mcpToolMethod.getGenericReturnType()));
}

var tool = toolBuilder.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

import org.junit.jupiter.api.Test;
import org.springaicommunity.mcp.annotation.McpToolListChanged;

import io.modelcontextprotocol.json.McpJsonMapper;
import io.modelcontextprotocol.spec.McpSchema;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
Expand All @@ -26,8 +26,16 @@
public class AsyncMcpToolListChangedMethodCallbackTests {

private static final List<McpSchema.Tool> TEST_TOOLS = List.of(
McpSchema.Tool.builder().name("test-tool-1").description("Test Tool 1").inputSchema("{}").build(),
McpSchema.Tool.builder().name("test-tool-2").description("Test Tool 2").inputSchema("{}").build());
McpSchema.Tool.builder()
.name("test-tool-1")
.description("Test Tool 1")
.inputSchema(McpJsonMapper.createDefault(), "{}")
.build(),
McpSchema.Tool.builder()
.name("test-tool-2")
.description("Test Tool 2")
.inputSchema(McpJsonMapper.createDefault(), "{}")
.build());

/**
* Test class with valid methods.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

import org.junit.jupiter.api.Test;
import org.springaicommunity.mcp.annotation.McpToolListChanged;

import io.modelcontextprotocol.json.McpJsonMapper;
import io.modelcontextprotocol.spec.McpSchema;

/**
Expand All @@ -24,8 +24,16 @@
public class SyncMcpToolListChangedMethodCallbackTests {

private static final List<McpSchema.Tool> TEST_TOOLS = List.of(
McpSchema.Tool.builder().name("test-tool-1").description("Test Tool 1").inputSchema("{}").build(),
McpSchema.Tool.builder().name("test-tool-2").description("Test Tool 2").inputSchema("{}").build());
McpSchema.Tool.builder()
.name("test-tool-1")
.description("Test Tool 1")
.inputSchema(McpJsonMapper.createDefault(), "{}")
.build(),
McpSchema.Tool.builder()
.name("test-tool-2")
.description("Test Tool 2")
.inputSchema(McpJsonMapper.createDefault(), "{}")
.build());

/**
* Test class with valid methods.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -320,8 +320,8 @@ public void testAsyncStructuredOutputWithCallToolRequest() throws Exception {
assertThat(result).isNotNull();
assertThat(result.isError()).isFalse();
assertThat(result.structuredContent()).isNotNull();
assertThat(result.structuredContent()).containsEntry("message", "test-message");
assertThat(result.structuredContent()).containsEntry("value", 42);
assertThat((Map<String, Object>) result.structuredContent()).containsEntry("message", "test-message");
assertThat((Map<String, Object>) result.structuredContent()).containsEntry("value", 42);
}).verifyComplete();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -570,8 +570,8 @@ public void testMonoToolReturningComplexObject() throws Exception {
assertThat(result.isError()).isFalse();
assertThat(result.content()).isEmpty();
assertThat(result.structuredContent()).isNotNull();
assertThat(result.structuredContent()).containsEntry("name", "test");
assertThat(result.structuredContent()).containsEntry("value", 42);
assertThat((Map<String, Object>) result.structuredContent()).containsEntry("name", "test");
assertThat((Map<String, Object>) result.structuredContent()).containsEntry("value", 42);
}).verifyComplete();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -606,8 +606,8 @@ public void testMonoToolReturningComplexObject() throws Exception {
assertThat(result.isError()).isFalse();
assertThat(result.content()).isEmpty();
assertThat(result.structuredContent()).isNotNull();
assertThat(result.structuredContent()).containsEntry("name", "test");
assertThat(result.structuredContent()).containsEntry("value", 42);
assertThat((Map<String, Object>) result.structuredContent()).containsEntry("name", "test");
assertThat((Map<String, Object>) result.structuredContent()).containsEntry("value", 42);
}).verifyComplete();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -446,8 +446,8 @@ public void testStructuredOutputWithCallToolRequest() throws Exception {
assertThat(result).isNotNull();
assertThat(result.isError()).isFalse();
assertThat(result.structuredContent()).isNotNull();
assertThat(result.structuredContent()).containsEntry("message", "test-message");
assertThat(result.structuredContent()).containsEntry("value", 42);
assertThat((Map<String, Object>) result.structuredContent()).containsEntry("message", "test-message");
assertThat((Map<String, Object>) result.structuredContent()).containsEntry("value", 42);
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -518,8 +518,8 @@ public void testToolReturningComplexObject() throws Exception {
// the new implementation should return structured content
assertThat(result.content()).isEmpty();
assertThat(result.structuredContent()).isNotNull();
assertThat(result.structuredContent()).containsEntry("name", "test");
assertThat(result.structuredContent()).containsEntry("value", 42);
assertThat((Map<String, Object>) result.structuredContent()).containsEntry("name", "test");
assertThat((Map<String, Object>) result.structuredContent()).containsEntry("value", 42);
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -539,8 +539,8 @@ public void testToolReturningComplexObject() throws Exception {
// the new implementation should return structured content
assertThat(result.content()).isEmpty();
assertThat(result.structuredContent()).isNotNull();
assertThat(result.structuredContent()).containsEntry("name", "test");
assertThat(result.structuredContent()).containsEntry("value", 42);
assertThat((Map<String, Object>) result.structuredContent()).containsEntry("name", "test");
assertThat((Map<String, Object>) result.structuredContent()).containsEntry("value", 42);
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import org.junit.jupiter.api.Test;
import org.springaicommunity.mcp.annotation.McpToolListChanged;
import org.springaicommunity.mcp.method.changed.tool.AsyncToolListChangedSpecification;

import io.modelcontextprotocol.json.McpJsonMapper;
import io.modelcontextprotocol.spec.McpSchema;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
Expand All @@ -26,8 +26,16 @@
public class AsyncMcpToolListChangedProviderTests {

private static final List<McpSchema.Tool> TEST_TOOLS = List.of(
McpSchema.Tool.builder().name("test-tool-1").description("Test Tool 1").inputSchema("{}").build(),
McpSchema.Tool.builder().name("test-tool-2").description("Test Tool 2").inputSchema("{}").build());
McpSchema.Tool.builder()
.name("test-tool-1")
.description("Test Tool 1")
.inputSchema(McpJsonMapper.createDefault(), "{}")
.build(),
McpSchema.Tool.builder()
.name("test-tool-2")
.description("Test Tool 2")
.inputSchema(McpJsonMapper.createDefault(), "{}")
.build());

/**
* Test class with tool list changed consumer methods.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import org.junit.jupiter.api.Test;
import org.springaicommunity.mcp.annotation.McpToolListChanged;
import org.springaicommunity.mcp.method.changed.tool.SyncToolListChangedSpecification;

import io.modelcontextprotocol.json.McpJsonMapper;
import io.modelcontextprotocol.spec.McpSchema;

/**
Expand All @@ -24,8 +24,16 @@
public class SyncMcpToolListChangedProviderTests {

private static final List<McpSchema.Tool> TEST_TOOLS = List.of(
McpSchema.Tool.builder().name("test-tool-1").description("Test Tool 1").inputSchema("{}").build(),
McpSchema.Tool.builder().name("test-tool-2").description("Test Tool 2").inputSchema("{}").build());
McpSchema.Tool.builder()
.name("test-tool-1")
.description("Test Tool 1")
.inputSchema(McpJsonMapper.createDefault(), "{}")
.build(),
McpSchema.Tool.builder()
.name("test-tool-2")
.description("Test Tool 2")
.inputSchema(McpJsonMapper.createDefault(), "{}")
.build());

/**
* Test class with tool list changed consumer methods.
Expand Down
6 changes: 4 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,13 @@
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>

<mcp.java.sdk.version>0.12.1</mcp.java.sdk.version>
<mcp.java.sdk.version>0.13.0-SNAPSHOT</mcp.java.sdk.version>

<jsonschema.version>4.38.0</jsonschema.version>
<swagger-annotations.version>2.2.36</swagger-annotations.version>
<jackson-databind.version>2.19.2</jackson-databind.version>

<!-- MUST KEEP JACKSON VERSION ALIGNED WITH the mcp-json-jackson2 version -->
<jackson-databind.version>2.17.0</jackson-databind.version>

<slf4j-api.version>2.0.16</slf4j-api.version>
<logback.version>1.5.15</logback.version>
Expand Down