Add mcp-sdk-plain module: MCP server on the plain Java SDK 2.1.0 over stdio and Streamable HTTP, fat jar, wire transcripts and a Spring AI client

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_017ic4b5oh78z7gcH6QkxafF
This commit is contained in:
Claude
2026-11-08 18:28:07 +00:00
parent 7c20ea1370
commit 58eaf4c2e1
29 changed files with 864 additions and 0 deletions
@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- Standalone on purpose: the server module has no Spring in it; this is the Spring AI side of the conversation. -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>4.1.2</version>
<relativePath/>
</parent>
<groupId>com.ankurm.agents</groupId>
<artifactId>spring-ai-client</artifactId>
<version>1.0.0</version>
<properties>
<java.version>25</java.version>
<spring-ai.version>2.0.2</spring-ai.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>${spring-ai.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-client</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
+12
View File
@@ -0,0 +1,12 @@
#!/usr/bin/env bash
# Starts the plain server (HTTP, port 18090) and runs this Spring AI client against it.
# Needs ../../target/mcp-sdk-plain.jar (mvn -pl mcp-sdk-plain package from the repo root).
set -eu
cd "$(dirname "$0")"
OUT=../../output/07-spring-ai-client.txt
java -jar ../../target/mcp-sdk-plain.jar http 18090 >/dev/null 2>&1 &
PID=$!
trap 'kill $PID 2>/dev/null || true' EXIT
for i in $(seq 1 40); do curl -s -o /dev/null http://127.0.0.1:18090/ && break; sleep 0.5; done
mvn -B -q spring-boot:run 2>/dev/null | grep -E '^(clients|server|tool|word_stats)' > "$OUT"
cat "$OUT"
@@ -0,0 +1,33 @@
package com.ankurm.mcpplain.client;
import io.modelcontextprotocol.client.McpSyncClient;
import io.modelcontextprotocol.spec.McpSchema.CallToolRequest;
import io.modelcontextprotocol.spec.McpSchema.TextContent;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import java.util.List;
import java.util.Map;
/** Spring AI builds one McpSyncClient per configured connection; we only list tools and call one. */
@SpringBootApplication
public class ClientApp {
public static void main(String[] args) {
SpringApplication.run(ClientApp.class, args);
}
@Bean
CommandLineRunner run(List<McpSyncClient> clients) {
return args -> {
System.out.println("clients: " + clients.size());
for (McpSyncClient c : clients) {
System.out.println("server: " + c.getServerInfo().name() + " " + c.getServerInfo().version());
c.listTools().tools().forEach(t -> System.out.println("tool: " + t.name()));
var r = c.callTool(new CallToolRequest("word_stats", Map.of("text", "spring ai meets plain sdk")));
System.out.println("word_stats -> " + ((TextContent) r.content().get(0)).text());
}
};
}
}
@@ -0,0 +1,11 @@
spring:
main:
web-application-type: none
ai:
mcp:
client:
streamable-http:
connections:
notes:
url: http://127.0.0.1:18090
endpoint: /mcp