diff --git a/.gitignore b/.gitignore index 549e00a..65ebd52 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,5 @@ build/ ### VS Code ### .vscode/ + +*.log \ No newline at end of file diff --git a/pom.xml b/pom.xml index 94e9b1a..7b3c1e8 100644 --- a/pom.xml +++ b/pom.xml @@ -33,7 +33,7 @@ org.springframework.ai - spring-ai-starter-mcp-server-webmvc + spring-ai-starter-mcp-server-webflux @@ -41,12 +41,6 @@ - - - org.springframework.boot - spring-boot-starter-actuator - - org.springframework.boot spring-boot-devtools diff --git a/src/main/java/cn/louisxiv/mcp/dbconnect/DbConnectTool.java b/src/main/java/cn/louisxiv/mcp/dbconnect/DbConnectTool.java deleted file mode 100644 index b0928c5..0000000 --- a/src/main/java/cn/louisxiv/mcp/dbconnect/DbConnectTool.java +++ /dev/null @@ -1,7 +0,0 @@ -package cn.louisxiv.mcp.dbconnect; - -import org.springframework.stereotype.Component; - -@Component -public class DbConnectTool { -} diff --git a/src/main/java/cn/louisxiv/mcp/dbconnect/McpDbConnectApplication.java b/src/main/java/cn/louisxiv/mcp/dbconnect/McpDbConnectApplication.java index c4ff2f7..0c5257d 100644 --- a/src/main/java/cn/louisxiv/mcp/dbconnect/McpDbConnectApplication.java +++ b/src/main/java/cn/louisxiv/mcp/dbconnect/McpDbConnectApplication.java @@ -1,14 +1,7 @@ package cn.louisxiv.mcp.dbconnect; -import org.springframework.ai.tool.ToolCallback; -import org.springframework.ai.tool.function.FunctionToolCallback; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.Bean; - -import java.time.LocalTime; -import java.time.ZoneId; -import java.time.ZonedDateTime; @SpringBootApplication public class McpDbConnectApplication { @@ -16,26 +9,4 @@ public class McpDbConnectApplication { public static void main(String[] args) { SpringApplication.run(McpDbConnectApplication.class, args); } - - -// @Bean -// public ToolCallbackProvider dbConnectTool() { -// List tools = ... -// return ToolCallbackProvider.from(tools); -// } - - @Bean - public ToolCallback getTime() { - return FunctionToolCallback.builder("getNowTime", this::getNowTime) - .inputType(String.class) - .description("Get now time, input: timeZone") - .build(); - } - - private String getNowTime(String timeZone) { - ZonedDateTime zonedDateTime = ZonedDateTime.now(); - LocalTime localTime = zonedDateTime.withZoneSameInstant(ZoneId.of(timeZone)).toLocalTime(); - return localTime.toString(); - - } } diff --git a/src/main/java/cn/louisxiv/mcp/dbconnect/config/AppConfiguration.java b/src/main/java/cn/louisxiv/mcp/dbconnect/config/AppConfiguration.java new file mode 100644 index 0000000..6e422d3 --- /dev/null +++ b/src/main/java/cn/louisxiv/mcp/dbconnect/config/AppConfiguration.java @@ -0,0 +1,19 @@ +package cn.louisxiv.mcp.dbconnect.config; + +import cn.louisxiv.mcp.dbconnect.tool.DbConnectTool; +import org.springframework.ai.tool.ToolCallbackProvider; +import org.springframework.ai.tool.method.MethodToolCallbackProvider; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class AppConfiguration { + + /** + * 声明ToolCallbackProvider + */ + @Bean + public ToolCallbackProvider toolCallbackProvider(DbConnectTool dbConnectTool) { + return MethodToolCallbackProvider.builder().toolObjects(dbConnectTool).build(); + } +} diff --git a/src/main/java/cn/louisxiv/mcp/dbconnect/tool/DbConnectTool.java b/src/main/java/cn/louisxiv/mcp/dbconnect/tool/DbConnectTool.java new file mode 100644 index 0000000..c1b5968 --- /dev/null +++ b/src/main/java/cn/louisxiv/mcp/dbconnect/tool/DbConnectTool.java @@ -0,0 +1,16 @@ +package cn.louisxiv.mcp.dbconnect.tool; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.ai.tool.annotation.Tool; +import org.springframework.stereotype.Component; + +@Slf4j +@Component +public class DbConnectTool { + + @Tool(description = "获取表结构定义,参数是表名") + public String getTableDefinition(String tableName) { + log.info("get table definition: {}", tableName); + return "create " + tableName; + } +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index df1ad5a..a77b689 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -4,21 +4,14 @@ spring: mcp: server: name: mcp-db-connect - version: 1.0.0 - type: SYNC - sse-message-endpoint: /mcp/messages + version: 0.0.1 + type: ASYNC + sse-message-endpoint: /mcp/sse + # 退化为STDIO模式需要关闭banner main: banner-mode: off -management: - endpoints: - web: - exposure: - include: health,info,metrics,env,beans,mappings - endpoint: - health: - show-details: always - +# 退化为STDIO模式需要关闭控制台日志 logging: file: - name: ./model-context-protocol/weather/starter-webmvc-server/target/starter-webmvc-server.log \ No newline at end of file + name: ./log/mcp-server.log \ No newline at end of file diff --git a/src/test/java/cn/louisxiv/mcp/dbconnect/tool/DbConnectToolStdioTest.java b/src/test/java/cn/louisxiv/mcp/dbconnect/tool/DbConnectToolStdioTest.java new file mode 100644 index 0000000..d6cd0cd --- /dev/null +++ b/src/test/java/cn/louisxiv/mcp/dbconnect/tool/DbConnectToolStdioTest.java @@ -0,0 +1,28 @@ +package cn.louisxiv.mcp.dbconnect.tool; + +import io.modelcontextprotocol.client.McpAsyncClient; +import io.modelcontextprotocol.client.McpClient; +import io.modelcontextprotocol.client.transport.StdioClientTransport; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; + +@SpringBootTest +@ActiveProfiles("stdio") +public class DbConnectToolStdioTest { + + McpAsyncClient mcpAsyncClient; + + @BeforeEach + public void init() { + //mcpAsyncClient = McpClient.async(new StdioClientTransport()); + } + + + @Test + public void testStdio() { + + } + +} diff --git a/src/test/java/cn/louisxiv/mcp/dbconnect/tool/DbConnectToolWebFluxTest.java b/src/test/java/cn/louisxiv/mcp/dbconnect/tool/DbConnectToolWebFluxTest.java new file mode 100644 index 0000000..cad09b8 --- /dev/null +++ b/src/test/java/cn/louisxiv/mcp/dbconnect/tool/DbConnectToolWebFluxTest.java @@ -0,0 +1,50 @@ +package cn.louisxiv.mcp.dbconnect.tool; + +import io.modelcontextprotocol.client.McpAsyncClient; +import io.modelcontextprotocol.client.McpClient; +import io.modelcontextprotocol.client.transport.WebFluxSseClientTransport; +import io.modelcontextprotocol.spec.McpSchema; +import lombok.extern.slf4j.Slf4j; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.web.reactive.function.client.WebClient; + +import java.util.Map; + +@Slf4j +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) +@ActiveProfiles("webflux") +public class DbConnectToolWebFluxTest { + + McpAsyncClient mcpAsyncClient; + + @Value(value = "${app.base-url}") + String baseUrl; + + @Value(value = "/sse") + String sseEndpoint; + + @BeforeEach + public void init() { + log.info("baseUrl: {}", baseUrl); + log.info("sseEndpoint: {}", sseEndpoint); + var webClient = WebClient.builder().baseUrl(baseUrl); + var client = WebFluxSseClientTransport.builder(webClient) + .sseEndpoint(sseEndpoint) + .build(); + mcpAsyncClient = McpClient.async(client).build(); + } + + @Test + public void testWebFlux() { + log.info("test webflux start"); + Map map = Map.of("tableName", "t_test"); + McpSchema.CallToolRequest request = new McpSchema.CallToolRequest("getTableDefinition", map); + var result = mcpAsyncClient.callTool(request); + var a = result.contextCapture().subscribe(); + log.info("test end: {}", a); + } +} diff --git a/src/test/resources/application-stdio.yml b/src/test/resources/application-stdio.yml new file mode 100644 index 0000000..40e7269 --- /dev/null +++ b/src/test/resources/application-stdio.yml @@ -0,0 +1,9 @@ +spring: + ai: + mcp: + server: + stdio: true + +logging: + file: + name: ./log/stdio/test.log \ No newline at end of file diff --git a/src/test/resources/application-webflux.yml b/src/test/resources/application-webflux.yml new file mode 100644 index 0000000..28f859b --- /dev/null +++ b/src/test/resources/application-webflux.yml @@ -0,0 +1,6 @@ +app: + base-url: http://localhost:8080 + +logging: + file: + name: ./log/webflux/test.log \ No newline at end of file