Restructure
Signed-off-by: Christian Tzolov <christian.tzolov@broadcom.com>
This commit is contained in:
58
mcp.servlet-server.log
Normal file
58
mcp.servlet-server.log
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
2025-02-09T21:26:38.153+01:00 INFO 95924 --- [main] .s.a.m.s.s.s.McpServletServerApplication : Starting McpServletServerApplication using Java 17.0.12 with PID 95924 (/Users/christiantzolov/Dev/projects/spring-ai-examples/model-context-protocol/book-library/manual-servlet-server/target/classes started by christiantzolov in /Users/christiantzolov/Dev/projects/spring-ai-examples)
|
||||||
|
2025-02-09T21:26:38.154+01:00 INFO 95924 --- [main] .s.a.m.s.s.s.McpServletServerApplication : No active profile set, falling back to 1 default profile: "default"
|
||||||
|
2025-02-09T21:26:38.468+01:00 INFO 95924 --- [main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port 8080 (http)
|
||||||
|
2025-02-09T21:26:38.473+01:00 INFO 95924 --- [main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
|
||||||
|
2025-02-09T21:26:38.473+01:00 INFO 95924 --- [main] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/10.1.33]
|
||||||
|
2025-02-09T21:26:38.493+01:00 INFO 95924 --- [main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
|
||||||
|
2025-02-09T21:26:38.493+01:00 INFO 95924 --- [main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 319 ms
|
||||||
|
2025-02-09T21:26:38.711+01:00 INFO 95924 --- [main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port 8080 (http) with context path '/'
|
||||||
|
2025-02-09T21:26:38.715+01:00 INFO 95924 --- [main] .s.a.m.s.s.s.McpServletServerApplication : Started McpServletServerApplication in 0.731 seconds (process running for 0.85)
|
||||||
|
2025-02-09T21:26:43.707+01:00 INFO 95924 --- [http-nio-8080-exec-2] i.m.spec.DefaultMcpSession : Received request: JSONRPCRequest[jsonrpc=2.0, method=initialize, id=6c0682de-0, params={protocolVersion=2024-11-05, capabilities={}, clientInfo={name=Java SDK MCP Client, version=1.0.0}}]
|
||||||
|
2025-02-09T21:26:43.711+01:00 INFO 95924 --- [http-nio-8080-exec-2] i.m.server.McpAsyncServer : Client initialize request - Protocol: 2024-11-05, Capabilities: ClientCapabilities[experimental=null, roots=null, sampling=null], Info: Implementation[name=Java SDK MCP Client, version=1.0.0]
|
||||||
|
2025-02-09T21:26:43.756+01:00 INFO 95924 --- [http-nio-8080-exec-3] i.m.spec.DefaultMcpSession : Received notification: JSONRPCNotification[jsonrpc=2.0, method=notifications/initialized, params=null]
|
||||||
|
2025-02-09T21:26:43.758+01:00 INFO 95924 --- [http-nio-8080-exec-4] i.m.spec.DefaultMcpSession : Received request: JSONRPCRequest[jsonrpc=2.0, method=ping, id=6c0682de-1, params=null]
|
||||||
|
2025-02-09T21:26:43.760+01:00 INFO 95924 --- [http-nio-8080-exec-5] i.m.spec.DefaultMcpSession : Received request: JSONRPCRequest[jsonrpc=2.0, method=tools/list, id=6c0682de-2, params={}]
|
||||||
|
2025-02-09T21:26:43.770+01:00 INFO 95924 --- [http-nio-8080-exec-6] i.m.spec.DefaultMcpSession : Received request: JSONRPCRequest[jsonrpc=2.0, method=tools/call, id=6c0682de-3, params={name=toUpperCase, arguments={input=accountName}}]
|
||||||
|
2025-02-09T21:26:43.794+01:00 INFO 95924 --- [http-nio-8080-exec-7] i.m.spec.DefaultMcpSession : Received request: JSONRPCRequest[jsonrpc=2.0, method=tools/call, id=6c0682de-4, params={name=getBooks, arguments={title=Spring Framework}}]
|
||||||
|
2025-02-09T21:26:44.908+01:00 INFO 95924 --- [http-nio-8080-exec-8] i.m.spec.DefaultMcpSession : Received request: JSONRPCRequest[jsonrpc=2.0, method=resources/list, id=6c0682de-5, params={}]
|
||||||
|
2025-02-09T21:26:44.917+01:00 INFO 95924 --- [http-nio-8080-exec-9] i.m.spec.DefaultMcpSession : Received request: JSONRPCRequest[jsonrpc=2.0, method=resources/read, id=6c0682de-6, params={uri=system://info}]
|
||||||
|
2025-02-09T21:26:44.927+01:00 INFO 95924 --- [http-nio-8080-exec-10] i.m.spec.DefaultMcpSession : Received request: JSONRPCRequest[jsonrpc=2.0, method=prompts/list, id=6c0682de-7, params={}]
|
||||||
|
2025-02-09T21:26:44.934+01:00 INFO 95924 --- [http-nio-8080-exec-1] i.m.spec.DefaultMcpSession : Received request: JSONRPCRequest[jsonrpc=2.0, method=prompts/get, id=6c0682de-8, params={name=greeting, arguments={name=Spring}}]
|
||||||
|
2025-02-09T21:26:46.642+01:00 ERROR 95924 --- [SpringApplicationShutdownHook] reactor.core.publisher.Operators : Operator called default onErrorDropped
|
||||||
|
|
||||||
|
reactor.core.Exceptions$ErrorCallbackNotImplemented: java.lang.IllegalStateException: The request associated with the AsyncContext has already completed processing.
|
||||||
|
Caused by: java.lang.IllegalStateException: The request associated with the AsyncContext has already completed processing.
|
||||||
|
at org.apache.catalina.core.AsyncContextImpl.check(AsyncContextImpl.java:529) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
|
||||||
|
at org.apache.catalina.core.AsyncContextImpl.complete(AsyncContextImpl.java:92) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
|
||||||
|
at io.modelcontextprotocol.server.transport.HttpServletSseServerTransport.removeSession(HttpServletSseServerTransport.java:379) ~[mcp-0.7.0-SNAPSHOT.jar:0.7.0-SNAPSHOT]
|
||||||
|
at java.base/java.util.concurrent.ConcurrentHashMap$ValuesView.forEach(ConcurrentHashMap.java:4780) ~[na:na]
|
||||||
|
at io.modelcontextprotocol.server.transport.HttpServletSseServerTransport.lambda$closeGracefully$4(HttpServletSseServerTransport.java:351) ~[mcp-0.7.0-SNAPSHOT.jar:0.7.0-SNAPSHOT]
|
||||||
|
at reactor.core.publisher.MonoCreate.subscribe(MonoCreate.java:61) ~[reactor-core-3.6.12.jar:3.6.12]
|
||||||
|
at reactor.core.publisher.Mono.subscribe(Mono.java:4576) ~[reactor-core-3.6.12.jar:3.6.12]
|
||||||
|
at reactor.core.publisher.Mono.subscribeWith(Mono.java:4642) ~[reactor-core-3.6.12.jar:3.6.12]
|
||||||
|
at reactor.core.publisher.Mono.subscribe(Mono.java:4403) ~[reactor-core-3.6.12.jar:3.6.12]
|
||||||
|
at io.modelcontextprotocol.spec.McpTransport.close(McpTransport.java:61) ~[mcp-0.7.0-SNAPSHOT.jar:0.7.0-SNAPSHOT]
|
||||||
|
at io.modelcontextprotocol.server.transport.HttpServletSseServerTransport.close(HttpServletSseServerTransport.java:323) ~[mcp-0.7.0-SNAPSHOT.jar:0.7.0-SNAPSHOT]
|
||||||
|
at io.modelcontextprotocol.spec.DefaultMcpSession.close(DefaultMcpSession.java:283) ~[mcp-0.7.0-SNAPSHOT.jar:0.7.0-SNAPSHOT]
|
||||||
|
at io.modelcontextprotocol.server.McpAsyncServer.close(McpAsyncServer.java:255) ~[mcp-0.7.0-SNAPSHOT.jar:0.7.0-SNAPSHOT]
|
||||||
|
at io.modelcontextprotocol.server.McpSyncServer.close(McpSyncServer.java:205) ~[mcp-0.7.0-SNAPSHOT.jar:0.7.0-SNAPSHOT]
|
||||||
|
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
|
||||||
|
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
|
||||||
|
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
|
||||||
|
at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
|
||||||
|
at org.springframework.beans.factory.support.DisposableBeanAdapter.invokeCustomDestroyMethod(DisposableBeanAdapter.java:316) ~[spring-beans-6.1.15.jar:6.1.15]
|
||||||
|
at org.springframework.beans.factory.support.DisposableBeanAdapter.destroy(DisposableBeanAdapter.java:249) ~[spring-beans-6.1.15.jar:6.1.15]
|
||||||
|
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroyBean(DefaultSingletonBeanRegistry.java:587) ~[spring-beans-6.1.15.jar:6.1.15]
|
||||||
|
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingleton(DefaultSingletonBeanRegistry.java:559) ~[spring-beans-6.1.15.jar:6.1.15]
|
||||||
|
at org.springframework.beans.factory.support.DefaultListableBeanFactory.destroySingleton(DefaultListableBeanFactory.java:1202) ~[spring-beans-6.1.15.jar:6.1.15]
|
||||||
|
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingletons(DefaultSingletonBeanRegistry.java:520) ~[spring-beans-6.1.15.jar:6.1.15]
|
||||||
|
at org.springframework.beans.factory.support.DefaultListableBeanFactory.destroySingletons(DefaultListableBeanFactory.java:1195) ~[spring-beans-6.1.15.jar:6.1.15]
|
||||||
|
at org.springframework.context.support.AbstractApplicationContext.destroyBeans(AbstractApplicationContext.java:1195) ~[spring-context-6.1.15.jar:6.1.15]
|
||||||
|
at org.springframework.context.support.AbstractApplicationContext.doClose(AbstractApplicationContext.java:1156) ~[spring-context-6.1.15.jar:6.1.15]
|
||||||
|
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.doClose(ServletWebServerApplicationContext.java:174) ~[spring-boot-3.3.6.jar:3.3.6]
|
||||||
|
at org.springframework.context.support.AbstractApplicationContext.close(AbstractApplicationContext.java:1102) ~[spring-context-6.1.15.jar:6.1.15]
|
||||||
|
at org.springframework.boot.SpringApplicationShutdownHook.closeAndWait(SpringApplicationShutdownHook.java:145) ~[spring-boot-3.3.6.jar:3.3.6]
|
||||||
|
at java.base/java.lang.Iterable.forEach(Iterable.java:75) ~[na:na]
|
||||||
|
at org.springframework.boot.SpringApplicationShutdownHook.run(SpringApplicationShutdownHook.java:114) ~[spring-boot-3.3.6.jar:3.3.6]
|
||||||
|
at java.base/java.lang.Thread.run(Thread.java:842) ~[na:na]
|
||||||
|
|
||||||
50
mcp.webflux.log
Normal file
50
mcp.webflux.log
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
2025-02-09T21:25:36.624+01:00 INFO 95283 --- [main] o.s.a.m.s.server.McpServerApplication : Starting McpServerApplication using Java 17.0.12 with PID 95283 (/Users/christiantzolov/Dev/projects/spring-ai-examples/model-context-protocol/book-library/manual-webflux-server/target/classes started by christiantzolov in /Users/christiantzolov/Dev/projects/spring-ai-examples)
|
||||||
|
2025-02-09T21:25:36.625+01:00 INFO 95283 --- [main] o.s.a.m.s.server.McpServerApplication : No active profile set, falling back to 1 default profile: "default"
|
||||||
|
2025-02-09T21:25:38.595+01:00 WARN 95283 --- [main] o.s.c.support.DefaultLifecycleProcessor : Failed to stop bean 'reactorResourceFactory'
|
||||||
|
|
||||||
|
reactor.core.Exceptions$ReactiveException: java.lang.InterruptedException
|
||||||
|
at reactor.core.Exceptions.propagate(Exceptions.java:410) ~[reactor-core-3.6.12.jar:3.6.12]
|
||||||
|
at reactor.core.publisher.BlockingSingleSubscriber.blockingGet(BlockingSingleSubscriber.java:96) ~[reactor-core-3.6.12.jar:3.6.12]
|
||||||
|
at reactor.core.publisher.Mono.block(Mono.java:1779) ~[reactor-core-3.6.12.jar:3.6.12]
|
||||||
|
at org.springframework.http.client.ReactorResourceFactory.stop(ReactorResourceFactory.java:298) ~[spring-web-6.1.15.jar:6.1.15]
|
||||||
|
at org.springframework.context.SmartLifecycle.stop(SmartLifecycle.java:117) ~[spring-context-6.1.15.jar:6.1.15]
|
||||||
|
at org.springframework.context.support.DefaultLifecycleProcessor.doStop(DefaultLifecycleProcessor.java:346) ~[spring-context-6.1.15.jar:6.1.15]
|
||||||
|
at org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup.stop(DefaultLifecycleProcessor.java:488) ~[spring-context-6.1.15.jar:6.1.15]
|
||||||
|
at java.base/java.lang.Iterable.forEach(Iterable.java:75) ~[na:na]
|
||||||
|
at org.springframework.context.support.DefaultLifecycleProcessor.stopBeans(DefaultLifecycleProcessor.java:315) ~[spring-context-6.1.15.jar:6.1.15]
|
||||||
|
at org.springframework.context.support.DefaultLifecycleProcessor.onRefresh(DefaultLifecycleProcessor.java:207) ~[spring-context-6.1.15.jar:6.1.15]
|
||||||
|
at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:990) ~[spring-context-6.1.15.jar:6.1.15]
|
||||||
|
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:628) ~[spring-context-6.1.15.jar:6.1.15]
|
||||||
|
at org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext.refresh(ReactiveWebServerApplicationContext.java:66) ~[spring-boot-3.3.6.jar:3.3.6]
|
||||||
|
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) ~[spring-boot-3.3.6.jar:3.3.6]
|
||||||
|
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456) ~[spring-boot-3.3.6.jar:3.3.6]
|
||||||
|
at org.springframework.boot.SpringApplication.run(SpringApplication.java:335) ~[spring-boot-3.3.6.jar:3.3.6]
|
||||||
|
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1363) ~[spring-boot-3.3.6.jar:3.3.6]
|
||||||
|
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1352) ~[spring-boot-3.3.6.jar:3.3.6]
|
||||||
|
at org.springframework.ai.mcp.sample.server.McpServerApplication.main(McpServerApplication.java:10) ~[classes/:na]
|
||||||
|
Caused by: java.lang.InterruptedException: null
|
||||||
|
at java.base/java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1048) ~[na:na]
|
||||||
|
at java.base/java.util.concurrent.CountDownLatch.await(CountDownLatch.java:230) ~[na:na]
|
||||||
|
at reactor.core.publisher.BlockingSingleSubscriber.blockingGet(BlockingSingleSubscriber.java:91) ~[reactor-core-3.6.12.jar:3.6.12]
|
||||||
|
... 17 common frames omitted
|
||||||
|
|
||||||
|
2025-02-09T21:25:38.599+01:00 WARN 95283 --- [main] onfigReactiveWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.context.ApplicationContextException: Failed to start bean 'webServerStartStop'
|
||||||
|
2025-02-09T21:25:38.609+01:00 INFO 95283 --- [main] o.s.a.m.s.t.WebFluxSseServerTransport : Graceful shutdown completed
|
||||||
|
2025-02-09T21:25:38.610+01:00 INFO 95283 --- [main] o.s.a.m.s.t.WebFluxSseServerTransport : Graceful shutdown completed
|
||||||
|
2025-02-09T21:25:44.586+01:00 INFO 95411 --- [main] o.s.a.m.s.server.McpServerApplication : Starting McpServerApplication using Java 17.0.12 with PID 95411 (/Users/christiantzolov/Dev/projects/spring-ai-examples/model-context-protocol/book-library/manual-webflux-server/target/classes started by christiantzolov in /Users/christiantzolov/Dev/projects/spring-ai-examples)
|
||||||
|
2025-02-09T21:25:44.587+01:00 INFO 95411 --- [main] o.s.a.m.s.server.McpServerApplication : No active profile set, falling back to 1 default profile: "default"
|
||||||
|
2025-02-09T21:25:45.244+01:00 INFO 95411 --- [main] o.s.b.web.embedded.netty.NettyWebServer : Netty started on port 8080 (http)
|
||||||
|
2025-02-09T21:25:45.252+01:00 INFO 95411 --- [main] o.s.a.m.s.server.McpServerApplication : Started McpServerApplication in 0.833 seconds (process running for 0.968)
|
||||||
|
2025-02-09T21:25:49.434+01:00 INFO 95411 --- [reactor-http-nio-3] o.s.ai.mcp.spec.DefaultMcpSession : Received request: JSONRPCRequest[jsonrpc=2.0, method=initialize, id=12e95de7-0, params={protocolVersion=2024-11-05, capabilities={}, clientInfo={name=Spring AI MCP Client, version=1.0.0}}]
|
||||||
|
2025-02-09T21:25:49.438+01:00 INFO 95411 --- [reactor-http-nio-3] o.s.ai.mcp.server.McpAsyncServer : Client initialize request - Protocol: 2024-11-05, Capabilities: ClientCapabilities[experimental=null, roots=null, sampling=null], Info: Implementation[name=Spring AI MCP Client, version=1.0.0]
|
||||||
|
2025-02-09T21:25:49.488+01:00 INFO 95411 --- [reactor-http-nio-4] o.s.ai.mcp.spec.DefaultMcpSession : Received notification: JSONRPCNotification[jsonrpc=2.0, method=notifications/initialized, params=null]
|
||||||
|
2025-02-09T21:25:49.492+01:00 INFO 95411 --- [reactor-http-nio-3] o.s.ai.mcp.spec.DefaultMcpSession : Received request: JSONRPCRequest[jsonrpc=2.0, method=ping, id=12e95de7-1, params=null]
|
||||||
|
2025-02-09T21:25:49.496+01:00 INFO 95411 --- [reactor-http-nio-4] o.s.ai.mcp.spec.DefaultMcpSession : Received request: JSONRPCRequest[jsonrpc=2.0, method=tools/list, id=12e95de7-2, params={}]
|
||||||
|
2025-02-09T21:25:49.508+01:00 INFO 95411 --- [reactor-http-nio-3] o.s.ai.mcp.spec.DefaultMcpSession : Received request: JSONRPCRequest[jsonrpc=2.0, method=tools/call, id=12e95de7-3, params={name=toUpperCase, arguments={input=accountName}}]
|
||||||
|
2025-02-09T21:25:49.527+01:00 INFO 95411 --- [reactor-http-nio-4] o.s.ai.mcp.spec.DefaultMcpSession : Received request: JSONRPCRequest[jsonrpc=2.0, method=tools/call, id=12e95de7-4, params={name=getBooks, arguments={title=Spring Framework}}]
|
||||||
|
2025-02-09T21:25:50.384+01:00 INFO 95411 --- [reactor-http-nio-3] o.s.ai.mcp.spec.DefaultMcpSession : Received request: JSONRPCRequest[jsonrpc=2.0, method=resources/list, id=12e95de7-5, params={}]
|
||||||
|
2025-02-09T21:25:50.396+01:00 INFO 95411 --- [reactor-http-nio-4] o.s.ai.mcp.spec.DefaultMcpSession : Received request: JSONRPCRequest[jsonrpc=2.0, method=resources/read, id=12e95de7-6, params={uri=system://info}]
|
||||||
|
2025-02-09T21:25:50.408+01:00 INFO 95411 --- [reactor-http-nio-3] o.s.ai.mcp.spec.DefaultMcpSession : Received request: JSONRPCRequest[jsonrpc=2.0, method=prompts/list, id=12e95de7-7, params={}]
|
||||||
|
2025-02-09T21:25:50.417+01:00 INFO 95411 --- [reactor-http-nio-4] o.s.ai.mcp.spec.DefaultMcpSession : Received request: JSONRPCRequest[jsonrpc=2.0, method=prompts/get, id=12e95de7-8, params={name=greeting, arguments={name=Spring}}]
|
||||||
|
2025-02-09T21:25:54.383+01:00 INFO 95411 --- [SpringApplicationShutdownHook] o.s.a.m.s.t.WebFluxSseServerTransport : Graceful shutdown completed
|
||||||
|
2025-02-09T21:25:54.384+01:00 INFO 95411 --- [SpringApplicationShutdownHook] o.s.a.m.s.t.WebFluxSseServerTransport : Graceful shutdown completed
|
||||||
50
mcp.webmvc.log
Normal file
50
mcp.webmvc.log
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
2025-02-09T21:21:11.760+01:00 INFO 93310 --- [main] o.s.a.m.s.w.s.McpMvcServerApplication : Starting McpMvcServerApplication using Java 17.0.12 with PID 93310 (/Users/christiantzolov/Dev/projects/spring-ai-examples/model-context-protocol/book-library/manual-webmvc-server/target/classes started by christiantzolov in /Users/christiantzolov/Dev/projects/spring-ai-examples)
|
||||||
|
2025-02-09T21:21:11.761+01:00 INFO 93310 --- [main] o.s.a.m.s.w.s.McpMvcServerApplication : No active profile set, falling back to 1 default profile: "default"
|
||||||
|
2025-02-09T21:21:12.089+01:00 INFO 93310 --- [main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port 8080 (http)
|
||||||
|
2025-02-09T21:21:12.095+01:00 INFO 93310 --- [main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
|
||||||
|
2025-02-09T21:21:12.095+01:00 INFO 93310 --- [main] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/10.1.33]
|
||||||
|
2025-02-09T21:21:12.125+01:00 INFO 93310 --- [main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
|
||||||
|
2025-02-09T21:21:12.125+01:00 INFO 93310 --- [main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 344 ms
|
||||||
|
2025-02-09T21:21:12.481+01:00 INFO 93310 --- [main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port 8080 (http) with context path '/'
|
||||||
|
2025-02-09T21:21:12.487+01:00 INFO 93310 --- [main] o.s.a.m.s.w.s.McpMvcServerApplication : Started McpMvcServerApplication in 0.895 seconds (process running for 1.022)
|
||||||
|
2025-02-09T21:21:36.802+01:00 INFO 93310 --- [SpringApplicationShutdownHook] o.s.a.m.s.t.WebMvcSseServerTransport : Graceful shutdown completed
|
||||||
|
2025-02-09T21:21:36.803+01:00 INFO 93310 --- [SpringApplicationShutdownHook] o.s.a.m.s.t.WebMvcSseServerTransport : Graceful shutdown completed
|
||||||
|
2025-02-09T21:22:52.834+01:00 INFO 93938 --- [main] o.s.a.m.s.w.s.McpMvcServerApplication : Starting McpMvcServerApplication using Java 17.0.12 with PID 93938 (/Users/christiantzolov/Dev/projects/spring-ai-examples/model-context-protocol/book-library/manual-webmvc-server/target/classes started by christiantzolov in /Users/christiantzolov/Dev/projects/spring-ai-examples)
|
||||||
|
2025-02-09T21:22:52.835+01:00 INFO 93938 --- [main] o.s.a.m.s.w.s.McpMvcServerApplication : No active profile set, falling back to 1 default profile: "default"
|
||||||
|
2025-02-09T21:22:53.140+01:00 INFO 93938 --- [main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port 8080 (http)
|
||||||
|
2025-02-09T21:22:53.145+01:00 INFO 93938 --- [main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
|
||||||
|
2025-02-09T21:22:53.145+01:00 INFO 93938 --- [main] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/10.1.33]
|
||||||
|
2025-02-09T21:22:53.167+01:00 INFO 93938 --- [main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
|
||||||
|
2025-02-09T21:22:53.167+01:00 INFO 93938 --- [main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 313 ms
|
||||||
|
2025-02-09T21:22:53.484+01:00 INFO 93938 --- [main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port 8080 (http) with context path '/'
|
||||||
|
2025-02-09T21:22:53.490+01:00 INFO 93938 --- [main] o.s.a.m.s.w.s.McpMvcServerApplication : Started McpMvcServerApplication in 0.82 seconds (process running for 0.943)
|
||||||
|
2025-02-09T21:23:04.979+01:00 INFO 93938 --- [SpringApplicationShutdownHook] o.s.a.m.s.t.WebMvcSseServerTransport : Graceful shutdown completed
|
||||||
|
2025-02-09T21:23:04.979+01:00 INFO 93938 --- [SpringApplicationShutdownHook] o.s.a.m.s.t.WebMvcSseServerTransport : Graceful shutdown completed
|
||||||
|
2025-02-09T21:24:24.073+01:00 INFO 94676 --- [main] o.s.a.m.s.w.s.McpMvcServerApplication : Starting McpMvcServerApplication using Java 17.0.12 with PID 94676 (/Users/christiantzolov/Dev/projects/spring-ai-examples/model-context-protocol/book-library/manual-webmvc-server/target/classes started by christiantzolov in /Users/christiantzolov/Dev/projects/spring-ai-examples)
|
||||||
|
2025-02-09T21:24:24.074+01:00 INFO 94676 --- [main] o.s.a.m.s.w.s.McpMvcServerApplication : No active profile set, falling back to 1 default profile: "default"
|
||||||
|
2025-02-09T21:24:24.425+01:00 INFO 94676 --- [main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port 8080 (http)
|
||||||
|
2025-02-09T21:24:24.430+01:00 INFO 94676 --- [main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
|
||||||
|
2025-02-09T21:24:24.431+01:00 INFO 94676 --- [main] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/10.1.33]
|
||||||
|
2025-02-09T21:24:24.455+01:00 INFO 94676 --- [main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
|
||||||
|
2025-02-09T21:24:24.456+01:00 INFO 94676 --- [main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 362 ms
|
||||||
|
2025-02-09T21:24:24.789+01:00 INFO 94676 --- [main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port 8080 (http) with context path '/'
|
||||||
|
2025-02-09T21:24:24.795+01:00 INFO 94676 --- [main] o.s.a.m.s.w.s.McpMvcServerApplication : Started McpMvcServerApplication in 0.896 seconds (process running for 1.022)
|
||||||
|
2025-02-09T21:24:27.528+01:00 INFO 94676 --- [http-nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
|
||||||
|
2025-02-09T21:24:27.529+01:00 INFO 94676 --- [http-nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
|
||||||
|
2025-02-09T21:24:27.529+01:00 INFO 94676 --- [http-nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 0 ms
|
||||||
|
2025-02-09T21:24:27.578+01:00 INFO 94676 --- [http-nio-8080-exec-2] o.s.ai.mcp.spec.DefaultMcpSession : Received request: JSONRPCRequest[jsonrpc=2.0, method=initialize, id=1f83bbd8-0, params={protocolVersion=2024-11-05, capabilities={}, clientInfo={name=Spring AI MCP Client, version=1.0.0}}]
|
||||||
|
2025-02-09T21:24:27.582+01:00 INFO 94676 --- [http-nio-8080-exec-2] o.s.ai.mcp.server.McpAsyncServer : Client initialize request - Protocol: 2024-11-05, Capabilities: ClientCapabilities[experimental=null, roots=null, sampling=null], Info: Implementation[name=Spring AI MCP Client, version=1.0.0]
|
||||||
|
2025-02-09T21:24:27.630+01:00 INFO 94676 --- [http-nio-8080-exec-3] o.s.ai.mcp.spec.DefaultMcpSession : Received notification: JSONRPCNotification[jsonrpc=2.0, method=notifications/initialized, params=null]
|
||||||
|
2025-02-09T21:24:27.633+01:00 INFO 94676 --- [http-nio-8080-exec-4] o.s.ai.mcp.spec.DefaultMcpSession : Received request: JSONRPCRequest[jsonrpc=2.0, method=ping, id=1f83bbd8-1, params=null]
|
||||||
|
2025-02-09T21:24:27.637+01:00 INFO 94676 --- [http-nio-8080-exec-5] o.s.ai.mcp.spec.DefaultMcpSession : Received request: JSONRPCRequest[jsonrpc=2.0, method=tools/list, id=1f83bbd8-2, params={}]
|
||||||
|
2025-02-09T21:24:27.649+01:00 INFO 94676 --- [http-nio-8080-exec-6] o.s.ai.mcp.spec.DefaultMcpSession : Received request: JSONRPCRequest[jsonrpc=2.0, method=tools/call, id=1f83bbd8-3, params={name=toUpperCase, arguments={input=accountName}}]
|
||||||
|
2025-02-09T21:24:27.672+01:00 INFO 94676 --- [http-nio-8080-exec-7] o.s.ai.mcp.spec.DefaultMcpSession : Received request: JSONRPCRequest[jsonrpc=2.0, method=tools/call, id=1f83bbd8-4, params={name=getBooks, arguments={title=Spring Framework}}]
|
||||||
|
2025-02-09T21:24:28.635+01:00 INFO 94676 --- [http-nio-8080-exec-8] o.s.ai.mcp.spec.DefaultMcpSession : Received request: JSONRPCRequest[jsonrpc=2.0, method=resources/list, id=1f83bbd8-5, params={}]
|
||||||
|
2025-02-09T21:24:28.645+01:00 INFO 94676 --- [http-nio-8080-exec-9] o.s.ai.mcp.spec.DefaultMcpSession : Received request: JSONRPCRequest[jsonrpc=2.0, method=resources/read, id=1f83bbd8-6, params={uri=system://info}]
|
||||||
|
2025-02-09T21:24:28.657+01:00 INFO 94676 --- [http-nio-8080-exec-10] o.s.ai.mcp.spec.DefaultMcpSession : Received request: JSONRPCRequest[jsonrpc=2.0, method=prompts/list, id=1f83bbd8-7, params={}]
|
||||||
|
2025-02-09T21:24:28.665+01:00 INFO 94676 --- [http-nio-8080-exec-1] o.s.ai.mcp.spec.DefaultMcpSession : Received request: JSONRPCRequest[jsonrpc=2.0, method=prompts/get, id=1f83bbd8-8, params={name=greeting, arguments={name=Spring}}]
|
||||||
|
2025-02-09T21:24:57.797+01:00 WARN 94676 --- [http-nio-8080-exec-3] .w.s.m.s.DefaultHandlerExceptionResolver : Ignoring exception, response committed already: org.springframework.web.context.request.async.AsyncRequestTimeoutException
|
||||||
|
2025-02-09T21:24:57.798+01:00 WARN 94676 --- [http-nio-8080-exec-3] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.context.request.async.AsyncRequestTimeoutException]
|
||||||
|
2025-02-09T21:25:37.487+01:00 WARN 94676 --- [SpringApplicationShutdownHook] o.s.a.m.s.t.WebMvcSseServerTransport : Failed to complete SSE emitter for session 76fdc444-38d2-4884-9e75-dc747611b756: The response object has been recycled and is no longer associated with this facade
|
||||||
|
2025-02-09T21:25:37.487+01:00 INFO 94676 --- [SpringApplicationShutdownHook] o.s.a.m.s.t.WebMvcSseServerTransport : Graceful shutdown completed
|
||||||
|
2025-02-09T21:25:37.487+01:00 INFO 94676 --- [SpringApplicationShutdownHook] o.s.a.m.s.t.WebMvcSseServerTransport : Graceful shutdown completed
|
||||||
@@ -1,147 +0,0 @@
|
|||||||
# Spring AI Model Context Protocol (MCP) Examples
|
|
||||||
|
|
||||||
This directory contains various examples demonstrating the usage of Spring AI's Model Context Protocol (MCP). Each example showcases different aspects of MCP implementation, including various transport methods and client-server configurations.
|
|
||||||
|
|
||||||
|
|
||||||
## Transport Types
|
|
||||||
|
|
||||||
The examples demonstrate two main types of transport:
|
|
||||||
|
|
||||||
1. **STDIO Transport**
|
|
||||||
- Process-based communication
|
|
||||||
- Synchronous communication
|
|
||||||
- Used in all client examples
|
|
||||||
- Available in all server implementations
|
|
||||||
|
|
||||||
2. **HTTP SSE (Server-Sent Events) Transport**
|
|
||||||
- HTTP-based streaming communication
|
|
||||||
- Asynchronous communication
|
|
||||||
- Available in server implementations
|
|
||||||
- Implemented in three variants:
|
|
||||||
- Servlet-based (Spring MVC)
|
|
||||||
- WebFlux-based (Reactive)
|
|
||||||
- WebMVC-based
|
|
||||||
|
|
||||||
## API Types
|
|
||||||
|
|
||||||
The examples demonstrate both synchronous and asynchronous API usage:
|
|
||||||
|
|
||||||
- **Synchronous API**: Used in STDIO transport implementations
|
|
||||||
- **Asynchronous API**: Used in SSE transport implementations
|
|
||||||
|
|
||||||
## Getting Started
|
|
||||||
|
|
||||||
Each example project can be built using Maven:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
./mvnw clean install
|
|
||||||
```
|
|
||||||
|
|
||||||
For running the examples:
|
|
||||||
1. For STDIO transport: Run the client application directly
|
|
||||||
2. For SSE transport: Start the server first, then run the client
|
|
||||||
|
|
||||||
## Note
|
|
||||||
|
|
||||||
- All server implementations support both STDIO and SSE transport modes
|
|
||||||
- Transport mode can be configured using the `transport.mode` property
|
|
||||||
- Client examples primarily use STDIO transport for simplicity
|
|
||||||
- Server starters provide auto-configuration support for easier integration
|
|
||||||
## Example Projects Overview
|
|
||||||
|
|
||||||
### Current Implementations
|
|
||||||
These projects use current Spring AI MCP dependencies:
|
|
||||||
|
|
||||||
#### Spring Boot Starter Projects
|
|
||||||
These use the `spring-ai-mcp-spring-boot-starter` dependency:
|
|
||||||
|
|
||||||
#### `brave-chatbot`
|
|
||||||
- **Type**: Client
|
|
||||||
- **Transport**: STDIO
|
|
||||||
- **Framework**: Spring Boot with MCP Starter
|
|
||||||
- **Description**: Enhanced version of the Brave client with chatbot capabilities.
|
|
||||||
|
|
||||||
#### `brave-starter`
|
|
||||||
- **Type**: Client Starter
|
|
||||||
- **Transport**: STDIO
|
|
||||||
- **Framework**: Spring Boot with MCP Starter
|
|
||||||
- **Description**: Spring Boot starter version of the Brave client.
|
|
||||||
|
|
||||||
#### `mcp-webflux-server-starter`
|
|
||||||
- **Type**: Server Starter
|
|
||||||
- **Transport**: Supports both HTTP SSE and STDIO
|
|
||||||
- **Framework**: Spring WebFlux with MCP Starter
|
|
||||||
- **Description**: Spring Boot starter for WebFlux server with auto-configuration support.
|
|
||||||
|
|
||||||
#### `mcp-weather-server-quickstart`
|
|
||||||
- **Type**: Server Quickstart
|
|
||||||
- **Transport**: Supports both HTTP SSE and STDIO
|
|
||||||
- **Framework**: Spring Boot with MCP Starter
|
|
||||||
- **Description**: Simplified version of the weather server for quick start purposes.
|
|
||||||
|
|
||||||
#### `mcp-weather-server-starter`
|
|
||||||
- **Type**: Server Starter
|
|
||||||
- **Transport**: Supports both HTTP SSE and STDIO
|
|
||||||
- **Framework**: Spring Boot with MCP Starter
|
|
||||||
- **Description**: Spring Boot starter version of the weather server, with auto-configuration support.
|
|
||||||
|
|
||||||
#### Manual Configuration Examples
|
|
||||||
These demonstrate how to create MCP applications without Spring Boot auto-configuration:
|
|
||||||
|
|
||||||
#### `mcp-weather-server`
|
|
||||||
- **Type**: Server
|
|
||||||
- **Transport**: Supports both HTTP SSE and STDIO
|
|
||||||
- **Framework**: Spring Boot with WebFlux
|
|
||||||
- **Dependencies**: Uses `spring-ai-bom` and `mcp-bom` for dependency management
|
|
||||||
- **Description**: Weather service implementation showing how to manually configure an MCP application without using spring-boot-starter. Demonstrates manual configuration patterns while maintaining clean dependency management through BOMs.
|
|
||||||
|
|
||||||
### Legacy Projects (Using Experimental Dependency)
|
|
||||||
These projects use the experimental dependency `org.springframework.experimental:spring-ai-mcp:0.6.0` and need updating:
|
|
||||||
|
|
||||||
#### Server Implementations
|
|
||||||
|
|
||||||
#### `mcp-servlet-server`
|
|
||||||
- **Type**: Server
|
|
||||||
- **Transport**: Supports both HTTP SSE and STDIO
|
|
||||||
- **Framework**: Spring MVC
|
|
||||||
- **Status**: Uses experimental dependency
|
|
||||||
- **Description**: Demonstrates a server implementation using Spring MVC with servlet-based SSE transport. Includes OpenLibrary integration.
|
|
||||||
|
|
||||||
#### `mcp-webflux-server`
|
|
||||||
- **Type**: Server
|
|
||||||
- **Transport**: Supports both HTTP SSE and STDIO
|
|
||||||
- **Framework**: Spring WebFlux
|
|
||||||
- **Status**: Uses experimental dependency
|
|
||||||
- **Description**: Shows a reactive server implementation using Spring WebFlux with SSE transport. Includes OpenLibrary integration.
|
|
||||||
|
|
||||||
#### `mcp-webmvc-server`
|
|
||||||
- **Type**: Server
|
|
||||||
- **Transport**: Supports both HTTP SSE and STDIO
|
|
||||||
- **Framework**: Spring WebMVC
|
|
||||||
- **Status**: Uses experimental dependency
|
|
||||||
- **Description**: Another server implementation using Spring WebMVC, demonstrating SSE transport integration.
|
|
||||||
|
|
||||||
#### Client Examples
|
|
||||||
|
|
||||||
#### `brave`
|
|
||||||
- **Type**: Client
|
|
||||||
- **Transport**: STDIO
|
|
||||||
- **Framework**: Spring Boot
|
|
||||||
- **Status**: Uses experimental dependency
|
|
||||||
- **Description**: Client implementation for Brave Search integration.
|
|
||||||
|
|
||||||
#### `filesystem`
|
|
||||||
- **Type**: Client
|
|
||||||
- **Transport**: STDIO
|
|
||||||
- **Framework**: Spring Boot
|
|
||||||
- **Status**: Uses experimental dependency
|
|
||||||
- **Description**: Example showing filesystem operations through MCP.
|
|
||||||
|
|
||||||
#### `sqlite`
|
|
||||||
- **Type**: Client
|
|
||||||
- **Transport**: STDIO
|
|
||||||
- **Framework**: Spring Boot
|
|
||||||
- **Status**: Uses experimental dependency
|
|
||||||
- **Description**: Demonstrates SQLite database integration through MCP (includes both simple and chatbot variants).
|
|
||||||
|
|
||||||
|
|
||||||
@@ -18,15 +18,15 @@
|
|||||||
<description>Sample application demonstrating MCP Servlet server usage</description>
|
<description>Sample application demonstrating MCP Servlet server usage</description>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<spring-ai-mcp.version>0.6.0</spring-ai-mcp.version>
|
<sprign-ai.version>1.0.0-SNAPSHOT</sprign-ai.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencyManagement>
|
<dependencyManagement>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.experimental</groupId>
|
<groupId>org.springframework.ai</groupId>
|
||||||
<artifactId>mcp-bom</artifactId>
|
<artifactId>spring-ai-bom</artifactId>
|
||||||
<version>${spring-ai-mcp.version}</version>
|
<version>${sprign-ai.version}</version>
|
||||||
<type>pom</type>
|
<type>pom</type>
|
||||||
<scope>import</scope>
|
<scope>import</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
@@ -35,7 +35,7 @@
|
|||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.experimental</groupId>
|
<groupId>org.springframework.ai</groupId>
|
||||||
<artifactId>spring-ai-mcp</artifactId>
|
<artifactId>spring-ai-mcp</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
@@ -43,12 +43,6 @@
|
|||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-web</artifactId>
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-test</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
@@ -56,27 +50,6 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<goals>
|
|
||||||
<goal>repackage</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<groupId>io.spring.javaformat</groupId>
|
|
||||||
<artifactId>spring-javaformat-maven-plugin</artifactId>
|
|
||||||
<version>0.0.43</version>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<phase>validate</phase>
|
|
||||||
<inherited>true</inherited>
|
|
||||||
<goals>
|
|
||||||
<goal>validate</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
@@ -5,29 +5,30 @@ import java.util.Map;
|
|||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import io.modelcontextprotocol.server.McpServer;
|
||||||
|
import io.modelcontextprotocol.server.McpServerFeatures.SyncPromptRegistration;
|
||||||
|
import io.modelcontextprotocol.server.McpServerFeatures.SyncResourceRegistration;
|
||||||
|
import io.modelcontextprotocol.server.McpServerFeatures.SyncToolRegistration;
|
||||||
|
import io.modelcontextprotocol.server.McpSyncServer;
|
||||||
|
import io.modelcontextprotocol.server.transport.HttpServletSseServerTransport;
|
||||||
|
import io.modelcontextprotocol.server.transport.StdioServerTransport;
|
||||||
|
import io.modelcontextprotocol.spec.McpSchema;
|
||||||
|
import io.modelcontextprotocol.spec.McpSchema.GetPromptResult;
|
||||||
|
import io.modelcontextprotocol.spec.McpSchema.PromptMessage;
|
||||||
|
import io.modelcontextprotocol.spec.McpSchema.Role;
|
||||||
|
import io.modelcontextprotocol.spec.McpSchema.TextContent;
|
||||||
|
import io.modelcontextprotocol.spec.ServerMcpTransport;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import org.springframework.ai.mcp.server.McpServer;
|
import org.springframework.ai.mcp.McpToolUtils;
|
||||||
import org.springframework.ai.mcp.server.McpServerFeatures.SyncPromptRegistration;
|
import org.springframework.ai.tool.ToolCallback;
|
||||||
import org.springframework.ai.mcp.server.McpServerFeatures.SyncResourceRegistration;
|
import org.springframework.ai.tool.ToolCallbacks;
|
||||||
import org.springframework.ai.mcp.server.McpServerFeatures.SyncToolRegistration;
|
import org.springframework.ai.tool.function.FunctionToolCallback;
|
||||||
import org.springframework.ai.mcp.server.McpSyncServer;
|
|
||||||
import org.springframework.ai.mcp.server.transport.HttpServletSseServerTransport;
|
|
||||||
import org.springframework.ai.mcp.server.transport.StdioServerTransport;
|
|
||||||
import org.springframework.ai.mcp.spec.McpSchema;
|
|
||||||
import org.springframework.ai.mcp.spec.McpSchema.GetPromptResult;
|
|
||||||
import org.springframework.ai.mcp.spec.McpSchema.PromptMessage;
|
|
||||||
import org.springframework.ai.mcp.spec.McpSchema.Role;
|
|
||||||
import org.springframework.ai.mcp.spec.McpSchema.TextContent;
|
|
||||||
import org.springframework.ai.mcp.spec.ServerMcpTransport;
|
|
||||||
import org.springframework.ai.mcp.spring.ToolHelper;
|
|
||||||
import org.springframework.ai.model.function.FunctionCallback;
|
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
import org.springframework.boot.web.servlet.ServletRegistrationBean;
|
import org.springframework.boot.web.servlet.ServletRegistrationBean;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.web.client.RestClient;
|
|
||||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
|
|
||||||
@@ -77,9 +78,8 @@ public class McpServerConfig implements WebMvcConfigurer {
|
|||||||
.resources(systemInfoResourceRegistration())
|
.resources(systemInfoResourceRegistration())
|
||||||
.prompts(greetingPromptRegistration())
|
.prompts(greetingPromptRegistration())
|
||||||
.tools(
|
.tools(
|
||||||
ToolHelper.toSyncToolRegistration(
|
McpToolUtils.toSyncToolRegistration(
|
||||||
FunctionCallback.builder()
|
FunctionToolCallback.builder("toUpperCase", (Function<ToUpperCaseInput, String>) s -> s.input().toUpperCase())
|
||||||
.function("toUpperCase", (Function<ToUpperCaseInput, String>) s -> s.input().toUpperCase())
|
|
||||||
.description("To upper case")
|
.description("To upper case")
|
||||||
.inputType(ToUpperCaseInput.class)
|
.inputType(ToUpperCaseInput.class)
|
||||||
.build()))
|
.build()))
|
||||||
@@ -89,20 +89,8 @@ public class McpServerConfig implements WebMvcConfigurer {
|
|||||||
} // @formatter:on
|
} // @formatter:on
|
||||||
|
|
||||||
public static List<SyncToolRegistration> openLibraryToolRegistrations(OpenLibrary openLibrary) {
|
public static List<SyncToolRegistration> openLibraryToolRegistrations(OpenLibrary openLibrary) {
|
||||||
|
ToolCallback[] tools = ToolCallbacks.from(openLibrary);
|
||||||
var books = FunctionCallback.builder()
|
return McpToolUtils.toSyncToolRegistration(tools);
|
||||||
.method("getBooks", String.class)
|
|
||||||
.description("Get list of Books by title")
|
|
||||||
.targetObject(openLibrary)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
var bookTitlesByAuthor = FunctionCallback.builder()
|
|
||||||
.method("getBookTitlesByAuthor", String.class)
|
|
||||||
.description("Get book titles by author")
|
|
||||||
.targetObject(openLibrary)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
return ToolHelper.toSyncToolRegistration(books, bookTitlesByAuthor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static SyncResourceRegistration systemInfoResourceRegistration() {
|
private static SyncResourceRegistration systemInfoResourceRegistration() {
|
||||||
@@ -156,10 +144,4 @@ public class McpServerConfig implements WebMvcConfigurer {
|
|||||||
return new GetPromptResult("A personalized greeting message", List.of(userMessage));
|
return new GetPromptResult("A personalized greeting message", List.of(userMessage));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
|
||||||
public OpenLibrary openLibrary() {
|
|
||||||
return new OpenLibrary(RestClient.builder());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -18,12 +18,14 @@ package org.springframework.ai.mcp.sample.servlet.server;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.springframework.ai.tool.annotation.Tool;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.web.client.RestClient;
|
import org.springframework.web.client.RestClient;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Christian Tzolov
|
* @author Christian Tzolov
|
||||||
*/
|
*/
|
||||||
|
@Service
|
||||||
public class OpenLibrary {
|
public class OpenLibrary {
|
||||||
|
|
||||||
private RestClient restClient;
|
private RestClient restClient;
|
||||||
@@ -38,6 +40,7 @@ public class OpenLibrary {
|
|||||||
public record Book(List<String> isbn, String title, List<String> authorName) {
|
public record Book(List<String> isbn, String title, List<String> authorName) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Tool(description = "Search for books by title")
|
||||||
public List<Book> getBooks(String title) {
|
public List<Book> getBooks(String title) {
|
||||||
Books books = restClient.get()
|
Books books = restClient.get()
|
||||||
.uri(uriBuilder -> uriBuilder.path("/search.json").queryParam("q", title).build())
|
.uri(uriBuilder -> uriBuilder.path("/search.json").queryParam("q", title).build())
|
||||||
@@ -52,6 +55,7 @@ public class OpenLibrary {
|
|||||||
.toList();
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Tool(description = "Search for books by author")
|
||||||
public List<String> getBookTitlesByAuthor(String authorName) {
|
public List<String> getBookTitlesByAuthor(String authorName) {
|
||||||
var books = restClient.get()
|
var books = restClient.get()
|
||||||
.uri(uriBuilder -> uriBuilder.path("/search/authors.json").queryParam("q", authorName).build())
|
.uri(uriBuilder -> uriBuilder.path("/search/authors.json").queryParam("q", authorName).build())
|
||||||
@@ -15,8 +15,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.ai.mcp.sample.servlet.client;
|
package org.springframework.ai.mcp.sample.servlet.client;
|
||||||
|
|
||||||
import org.springframework.ai.mcp.client.transport.ServerParameters;
|
import io.modelcontextprotocol.client.transport.ServerParameters;
|
||||||
import org.springframework.ai.mcp.client.transport.StdioClientTransport;
|
import io.modelcontextprotocol.client.transport.StdioClientTransport;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* With stdio transport, the MCP server is automatically started by the client. But you
|
* With stdio transport, the MCP server is automatically started by the client. But you
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.ai.mcp.sample.servlet.client;
|
package org.springframework.ai.mcp.sample.servlet.client;
|
||||||
|
|
||||||
import org.springframework.ai.mcp.client.transport.HttpClientSseClientTransport;
|
import io.modelcontextprotocol.client.transport.HttpClientSseClientTransport;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Christian Tzolov
|
* @author Christian Tzolov
|
||||||
@@ -17,14 +17,15 @@ package org.springframework.ai.mcp.sample.servlet.client;
|
|||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.springframework.ai.mcp.client.McpClient;
|
import io.modelcontextprotocol.client.McpClient;
|
||||||
import org.springframework.ai.mcp.spec.ClientMcpTransport;
|
import io.modelcontextprotocol.spec.ClientMcpTransport;
|
||||||
import org.springframework.ai.mcp.spec.McpSchema.CallToolRequest;
|
import io.modelcontextprotocol.spec.McpSchema.CallToolResult;
|
||||||
import org.springframework.ai.mcp.spec.McpSchema.CallToolResult;
|
import io.modelcontextprotocol.spec.McpSchema.ListPromptsResult;
|
||||||
import org.springframework.ai.mcp.spec.McpSchema.GetPromptRequest;
|
import io.modelcontextprotocol.spec.McpSchema.ListToolsResult;
|
||||||
import org.springframework.ai.mcp.spec.McpSchema.ListPromptsResult;
|
import io.modelcontextprotocol.spec.McpSchema.CallToolRequest;
|
||||||
import org.springframework.ai.mcp.spec.McpSchema.ListToolsResult;
|
import io.modelcontextprotocol.spec.McpSchema.GetPromptRequest;
|
||||||
import org.springframework.ai.mcp.spec.McpSchema.ReadResourceRequest;
|
import io.modelcontextprotocol.spec.McpSchema.ReadResourceRequest;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Christian Tzolov
|
* @author Christian Tzolov
|
||||||
@@ -19,7 +19,6 @@
|
|||||||
<description>Sample Spring Boot application demonstrating MCP server usage</description>
|
<description>Sample Spring Boot application demonstrating MCP server usage</description>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<mcp.version>0.7.0-SNAPSHOT</mcp.version>
|
|
||||||
<sprign-ai.version>1.0.0-SNAPSHOT</sprign-ai.version>
|
<sprign-ai.version>1.0.0-SNAPSHOT</sprign-ai.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
@@ -32,33 +31,14 @@
|
|||||||
<type>pom</type>
|
<type>pom</type>
|
||||||
<scope>import</scope>
|
<scope>import</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>io.modelcontextprotocol.sdk</groupId>
|
|
||||||
<artifactId>mcp-bom</artifactId>
|
|
||||||
<version>${mcp.version}</version>
|
|
||||||
<type>pom</type>
|
|
||||||
<scope>import</scope>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</dependencyManagement>
|
</dependencyManagement>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.modelcontextprotocol.sdk</groupId>
|
|
||||||
<artifactId>mcp-spring-webflux</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.ai</groupId>
|
<groupId>org.springframework.ai</groupId>
|
||||||
<artifactId>spring-ai-mcp-spring-boot-starter</artifactId>
|
<artifactId>spring-ai-mcp-server-webflux-spring-boot-starter</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-webflux</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
@@ -66,27 +46,6 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<goals>
|
|
||||||
<goal>repackage</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<groupId>io.spring.javaformat</groupId>
|
|
||||||
<artifactId>spring-javaformat-maven-plugin</artifactId>
|
|
||||||
<version>0.0.43</version>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<phase>validate</phase>
|
|
||||||
<inherited>true</inherited>
|
|
||||||
<goals>
|
|
||||||
<goal>validate</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
@@ -1,10 +1,9 @@
|
|||||||
# NOTE: You must disable the banner and the console logging
|
# NOTE: You must disable the banner and the console logging
|
||||||
# to allow the STDIO transport to work !!!
|
# to allow the STDIO transport to work !!!
|
||||||
spring.main.banner-mode=off
|
spring.main.banner-mode=off
|
||||||
logging.pattern.console=
|
# logging.pattern.console=
|
||||||
logging.file.name=./model-context-protocol/mcp-webflux-server-starter/target/mcp.webflux-server-starter.log
|
logging.file.name=./model-context-protocol/mcp-webflux-server-starter/target/mcp.webflux-server-starter.log
|
||||||
|
|
||||||
spring.ai.mcp.server.enabled=true
|
|
||||||
spring.ai.mcp.server.name=my-webflux-server-starter
|
spring.ai.mcp.server.name=my-webflux-server-starter
|
||||||
spring.ai.mcp.server.version=0.0.1
|
spring.ai.mcp.server.version=0.0.1
|
||||||
spring.ai.mcp.server.transport=WEBFLUX
|
|
||||||
@@ -31,7 +31,7 @@ public class ClientStdio {
|
|||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
|
|
||||||
var stdioParams = ServerParameters.builder("java")
|
var stdioParams = ServerParameters.builder("java")
|
||||||
.args("-Dspring.ai.mcp.server.transport=STDIO", "-Dspring.main.web-application-type=none",
|
.args("-Dspring.ai.mcp.server.stdio=true", "-Dspring.main.web-application-type=none",
|
||||||
"-Dlogging.pattern.console=", "-jar",
|
"-Dlogging.pattern.console=", "-jar",
|
||||||
"model-context-protocol/mcp-webflux-server-starter/target/mcp-webflux-server-starter-0.0.1-SNAPSHOT.jar")
|
"model-context-protocol/mcp-webflux-server-starter/target/mcp-webflux-server-starter-0.0.1-SNAPSHOT.jar")
|
||||||
.build();
|
.build();
|
||||||
@@ -14,6 +14,7 @@
|
|||||||
<version>0.0.1-SNAPSHOT</version>
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
<name>Spring AI - Model Context Protocol - Brave</name>
|
<name>Spring AI - Model Context Protocol - Brave</name>
|
||||||
<description>Simple AI Application using MCP client to use Brave for Internet search</description>
|
<description>Simple AI Application using MCP client to use Brave for Internet search</description>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<java.version>17</java.version>
|
<java.version>17</java.version>
|
||||||
</properties>
|
</properties>
|
||||||
@@ -31,14 +32,10 @@
|
|||||||
</dependencyManagement>
|
</dependencyManagement>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.ai</groupId>
|
<groupId>org.springframework.ai</groupId>
|
||||||
<artifactId>spring-ai-mcp-spring-boot-starter</artifactId>
|
<artifactId>spring-ai-mcp-client-spring-boot-starter</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|||||||
@@ -3,5 +3,4 @@ spring.main.web-application-type=none
|
|||||||
|
|
||||||
spring.ai.anthropic.api-key=${ANTHROPIC_API_KEY}
|
spring.ai.anthropic.api-key=${ANTHROPIC_API_KEY}
|
||||||
|
|
||||||
spring.ai.mcp.client.stdio.enabled=true
|
|
||||||
spring.ai.mcp.client.stdio.servers-configuration=classpath:/mcp-servers-config.json
|
spring.ai.mcp.client.stdio.servers-configuration=classpath:/mcp-servers-config.json
|
||||||
@@ -31,14 +31,10 @@
|
|||||||
</dependencyManagement>
|
</dependencyManagement>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.ai</groupId>
|
<groupId>org.springframework.ai</groupId>
|
||||||
<artifactId>spring-ai-mcp-spring-boot-starter</artifactId>
|
<artifactId>spring-ai-mcp-client-spring-boot-starter</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
@@ -46,11 +42,6 @@
|
|||||||
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
|
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.ai</groupId>
|
|
||||||
<artifactId>spring-ai-mcp</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|||||||
@@ -1,3 +1,18 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2025-2025 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
package org.springframework.ai.mcp.samples.brave;
|
package org.springframework.ai.mcp.samples.brave;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|||||||
@@ -4,5 +4,8 @@ spring.main.web-application-type=none
|
|||||||
spring.ai.openai.api-key=${OPENAI_API_KEY}
|
spring.ai.openai.api-key=${OPENAI_API_KEY}
|
||||||
spring.ai.anthropic.api-key=${ANTHROPIC_API_KEY}
|
spring.ai.anthropic.api-key=${ANTHROPIC_API_KEY}
|
||||||
|
|
||||||
spring.ai.mcp.client.stdio.enabled=true
|
# spring.ai.mcp.client.stdio.servers-configuration=classpath:/mcp-servers-config.json
|
||||||
spring.ai.mcp.client.stdio.servers-configuration=classpath:/mcp-servers-config.json
|
|
||||||
|
spring.ai.mcp.client.stdio.connections.brave-search.command=npx
|
||||||
|
spring.ai.mcp.client.stdio.connections.brave-search.args=-y,@modelcontextprotocol/server-brave-search
|
||||||
|
spring.ai.mcp.client.stdio.connections.brave-search.env.FOO=BAAR
|
||||||
|
|||||||
BIN
model-context-protocol/client-starter/starter-default-client/.mvn/wrapper/maven-wrapper.jar
vendored
Normal file
BIN
model-context-protocol/client-starter/starter-default-client/.mvn/wrapper/maven-wrapper.jar
vendored
Normal file
Binary file not shown.
@@ -0,0 +1,2 @@
|
|||||||
|
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.4/apache-maven-3.8.4-bin.zip
|
||||||
|
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar
|
||||||
305
model-context-protocol/client-starter/starter-default-client/mvnw
vendored
Executable file
305
model-context-protocol/client-starter/starter-default-client/mvnw
vendored
Executable file
@@ -0,0 +1,305 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
# Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
# or more contributor license agreements. See the NOTICE file
|
||||||
|
# distributed with this work for additional information
|
||||||
|
# regarding copyright ownership. The ASF licenses this file
|
||||||
|
# to you under the Apache License, Version 2.0 (the
|
||||||
|
# "License"); you may not use this file except in compliance
|
||||||
|
# with the License. You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing,
|
||||||
|
# software distributed under the License is distributed on an
|
||||||
|
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
# KIND, either express or implied. See the License for the
|
||||||
|
# specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
# Maven2 Start Up Batch script
|
||||||
|
#
|
||||||
|
# Required ENV vars:
|
||||||
|
# ------------------
|
||||||
|
# JAVA_HOME - location of a JDK home dir
|
||||||
|
#
|
||||||
|
# Optional ENV vars
|
||||||
|
# -----------------
|
||||||
|
# M2_HOME - location of maven2's installed home dir
|
||||||
|
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
||||||
|
# e.g. to debug Maven itself, use
|
||||||
|
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
||||||
|
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
if [ -z "$MAVEN_SKIP_RC" ] ; then
|
||||||
|
|
||||||
|
if [ -f /etc/mavenrc ] ; then
|
||||||
|
. /etc/mavenrc
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f "$HOME/.mavenrc" ] ; then
|
||||||
|
. "$HOME/.mavenrc"
|
||||||
|
fi
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
# OS specific support. $var _must_ be set to either true or false.
|
||||||
|
cygwin=false;
|
||||||
|
darwin=false;
|
||||||
|
mingw=false
|
||||||
|
case "`uname`" in
|
||||||
|
CYGWIN*) cygwin=true ;;
|
||||||
|
MINGW*) mingw=true;;
|
||||||
|
Darwin*) darwin=true
|
||||||
|
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
|
||||||
|
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
|
||||||
|
if [ -z "$JAVA_HOME" ]; then
|
||||||
|
if [ -x "/usr/libexec/java_home" ]; then
|
||||||
|
export JAVA_HOME="`/usr/libexec/java_home`"
|
||||||
|
else
|
||||||
|
export JAVA_HOME="/Library/Java/Home"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [ -z "$JAVA_HOME" ] ; then
|
||||||
|
if [ -r /etc/gentoo-release ] ; then
|
||||||
|
JAVA_HOME=`java-config --jre-home`
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$M2_HOME" ] ; then
|
||||||
|
## resolve links - $0 may be a link to maven's home
|
||||||
|
PRG="$0"
|
||||||
|
|
||||||
|
# need this for relative symlinks
|
||||||
|
while [ -h "$PRG" ] ; do
|
||||||
|
ls=`ls -ld "$PRG"`
|
||||||
|
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||||
|
if expr "$link" : '/.*' > /dev/null; then
|
||||||
|
PRG="$link"
|
||||||
|
else
|
||||||
|
PRG="`dirname "$PRG"`/$link"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
saveddir=`pwd`
|
||||||
|
|
||||||
|
M2_HOME=`dirname "$PRG"`/..
|
||||||
|
|
||||||
|
# make it fully qualified
|
||||||
|
M2_HOME=`cd "$M2_HOME" && pwd`
|
||||||
|
|
||||||
|
cd "$saveddir"
|
||||||
|
# echo Using m2 at $M2_HOME
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Cygwin, ensure paths are in UNIX format before anything is touched
|
||||||
|
if $cygwin ; then
|
||||||
|
[ -n "$M2_HOME" ] &&
|
||||||
|
M2_HOME=`cygpath --unix "$M2_HOME"`
|
||||||
|
[ -n "$JAVA_HOME" ] &&
|
||||||
|
JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
|
||||||
|
[ -n "$CLASSPATH" ] &&
|
||||||
|
CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Mingw, ensure paths are in UNIX format before anything is touched
|
||||||
|
if $mingw ; then
|
||||||
|
[ -n "$M2_HOME" ] &&
|
||||||
|
M2_HOME="`(cd "$M2_HOME"; pwd)`"
|
||||||
|
[ -n "$JAVA_HOME" ] &&
|
||||||
|
JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$JAVA_HOME" ]; then
|
||||||
|
javaExecutable="`which javac`"
|
||||||
|
if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
|
||||||
|
# readlink(1) is not available as standard on Solaris 10.
|
||||||
|
readLink=`which readlink`
|
||||||
|
if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
|
||||||
|
if $darwin ; then
|
||||||
|
javaHome="`dirname \"$javaExecutable\"`"
|
||||||
|
javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
|
||||||
|
else
|
||||||
|
javaExecutable="`readlink -f \"$javaExecutable\"`"
|
||||||
|
fi
|
||||||
|
javaHome="`dirname \"$javaExecutable\"`"
|
||||||
|
javaHome=`expr "$javaHome" : '\(.*\)/bin'`
|
||||||
|
JAVA_HOME="$javaHome"
|
||||||
|
export JAVA_HOME
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$JAVACMD" ] ; then
|
||||||
|
if [ -n "$JAVA_HOME" ] ; then
|
||||||
|
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||||
|
# IBM's JDK on AIX uses strange locations for the executables
|
||||||
|
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||||
|
else
|
||||||
|
JAVACMD="$JAVA_HOME/bin/java"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
JAVACMD="`which java`"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -x "$JAVACMD" ] ; then
|
||||||
|
echo "Error: JAVA_HOME is not defined correctly." >&2
|
||||||
|
echo " We cannot execute $JAVACMD" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$JAVA_HOME" ] ; then
|
||||||
|
echo "Warning: JAVA_HOME environment variable is not set."
|
||||||
|
fi
|
||||||
|
|
||||||
|
CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
|
||||||
|
|
||||||
|
# traverses directory structure from process work directory to filesystem root
|
||||||
|
# first directory with .mvn subdirectory is considered project base directory
|
||||||
|
find_maven_basedir() {
|
||||||
|
|
||||||
|
if [ -z "$1" ]
|
||||||
|
then
|
||||||
|
echo "Path not specified to find_maven_basedir"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
basedir="$1"
|
||||||
|
wdir="$1"
|
||||||
|
while [ "$wdir" != '/' ] ; do
|
||||||
|
if [ -d "$wdir"/.mvn ] ; then
|
||||||
|
basedir=$wdir
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
|
||||||
|
if [ -d "${wdir}" ]; then
|
||||||
|
wdir=`cd "$wdir/.."; pwd`
|
||||||
|
fi
|
||||||
|
# end of workaround
|
||||||
|
done
|
||||||
|
echo "${basedir}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# concatenates all lines of a file
|
||||||
|
concat_lines() {
|
||||||
|
if [ -f "$1" ]; then
|
||||||
|
echo "$(tr -s '\n' ' ' < "$1")"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
BASE_DIR=`find_maven_basedir "$(pwd)"`
|
||||||
|
if [ -z "$BASE_DIR" ]; then
|
||||||
|
exit 1;
|
||||||
|
fi
|
||||||
|
|
||||||
|
##########################################################################################
|
||||||
|
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
|
||||||
|
# This allows using the maven wrapper in projects that prohibit checking in binary data.
|
||||||
|
##########################################################################################
|
||||||
|
if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
|
||||||
|
if [ "$MVNW_VERBOSE" = true ]; then
|
||||||
|
echo "Found .mvn/wrapper/maven-wrapper.jar"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if [ "$MVNW_VERBOSE" = true ]; then
|
||||||
|
echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
|
||||||
|
fi
|
||||||
|
if [ "$MVNW_REPOURL" = true]; then
|
||||||
|
jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.2/maven-wrapper-0.5.2.jar"
|
||||||
|
else
|
||||||
|
jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.2/maven-wrapper-0.5.2.jar"
|
||||||
|
fi
|
||||||
|
while IFS="=" read key value; do
|
||||||
|
case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
|
||||||
|
esac
|
||||||
|
done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
|
||||||
|
if [ "$MVNW_VERBOSE" = true ]; then
|
||||||
|
echo "Downloading from: $jarUrl"
|
||||||
|
fi
|
||||||
|
wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
|
||||||
|
if $cygwin; then
|
||||||
|
wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
|
||||||
|
fi
|
||||||
|
|
||||||
|
if command -v wget > /dev/null; then
|
||||||
|
if [ "$MVNW_VERBOSE" = true ]; then
|
||||||
|
echo "Found wget ... using wget"
|
||||||
|
fi
|
||||||
|
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
|
||||||
|
wget "$jarUrl" -O "$wrapperJarPath"
|
||||||
|
else
|
||||||
|
wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
|
||||||
|
fi
|
||||||
|
elif command -v curl > /dev/null; then
|
||||||
|
if [ "$MVNW_VERBOSE" = true ]; then
|
||||||
|
echo "Found curl ... using curl"
|
||||||
|
fi
|
||||||
|
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
|
||||||
|
curl -o "$wrapperJarPath" "$jarUrl" -f
|
||||||
|
else
|
||||||
|
curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
|
||||||
|
fi
|
||||||
|
|
||||||
|
else
|
||||||
|
if [ "$MVNW_VERBOSE" = true ]; then
|
||||||
|
echo "Falling back to using Java to download"
|
||||||
|
fi
|
||||||
|
javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
|
||||||
|
# For Cygwin, switch paths to Windows format before running javac
|
||||||
|
if $cygwin; then
|
||||||
|
javaClass=`cygpath --path --windows "$javaClass"`
|
||||||
|
fi
|
||||||
|
if [ -e "$javaClass" ]; then
|
||||||
|
if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
|
||||||
|
if [ "$MVNW_VERBOSE" = true ]; then
|
||||||
|
echo " - Compiling MavenWrapperDownloader.java ..."
|
||||||
|
fi
|
||||||
|
# Compiling the Java class
|
||||||
|
("$JAVA_HOME/bin/javac" "$javaClass")
|
||||||
|
fi
|
||||||
|
if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
|
||||||
|
# Running the downloader
|
||||||
|
if [ "$MVNW_VERBOSE" = true ]; then
|
||||||
|
echo " - Running MavenWrapperDownloader.java ..."
|
||||||
|
fi
|
||||||
|
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
##########################################################################################
|
||||||
|
# End of extension
|
||||||
|
##########################################################################################
|
||||||
|
|
||||||
|
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
|
||||||
|
if [ "$MVNW_VERBOSE" = true ]; then
|
||||||
|
echo $MAVEN_PROJECTBASEDIR
|
||||||
|
fi
|
||||||
|
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
|
||||||
|
|
||||||
|
# For Cygwin, switch paths to Windows format before running java
|
||||||
|
if $cygwin; then
|
||||||
|
[ -n "$M2_HOME" ] &&
|
||||||
|
M2_HOME=`cygpath --path --windows "$M2_HOME"`
|
||||||
|
[ -n "$JAVA_HOME" ] &&
|
||||||
|
JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
|
||||||
|
[ -n "$CLASSPATH" ] &&
|
||||||
|
CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
|
||||||
|
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
|
||||||
|
MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
|
||||||
|
fi
|
||||||
|
|
||||||
|
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||||
|
|
||||||
|
exec "$JAVACMD" \
|
||||||
|
$MAVEN_OPTS \
|
||||||
|
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
|
||||||
|
"-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
|
||||||
|
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
|
||||||
172
model-context-protocol/client-starter/starter-default-client/mvnw.cmd
vendored
Executable file
172
model-context-protocol/client-starter/starter-default-client/mvnw.cmd
vendored
Executable file
@@ -0,0 +1,172 @@
|
|||||||
|
@REM ----------------------------------------------------------------------------
|
||||||
|
@REM Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
@REM or more contributor license agreements. See the NOTICE file
|
||||||
|
@REM distributed with this work for additional information
|
||||||
|
@REM regarding copyright ownership. The ASF licenses this file
|
||||||
|
@REM to you under the Apache License, Version 2.0 (the
|
||||||
|
@REM "License"); you may not use this file except in compliance
|
||||||
|
@REM with the License. You may obtain a copy of the License at
|
||||||
|
@REM
|
||||||
|
@REM http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
@REM
|
||||||
|
@REM Unless required by applicable law or agreed to in writing,
|
||||||
|
@REM software distributed under the License is distributed on an
|
||||||
|
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
@REM KIND, either express or implied. See the License for the
|
||||||
|
@REM specific language governing permissions and limitations
|
||||||
|
@REM under the License.
|
||||||
|
@REM ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@REM ----------------------------------------------------------------------------
|
||||||
|
@REM Maven2 Start Up Batch script
|
||||||
|
@REM
|
||||||
|
@REM Required ENV vars:
|
||||||
|
@REM JAVA_HOME - location of a JDK home dir
|
||||||
|
@REM
|
||||||
|
@REM Optional ENV vars
|
||||||
|
@REM M2_HOME - location of maven2's installed home dir
|
||||||
|
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
|
||||||
|
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
|
||||||
|
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
||||||
|
@REM e.g. to debug Maven itself, use
|
||||||
|
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
||||||
|
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
||||||
|
@REM ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
|
||||||
|
@echo off
|
||||||
|
@REM set title of command window
|
||||||
|
title %0
|
||||||
|
@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
|
||||||
|
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
|
||||||
|
|
||||||
|
@REM set %HOME% to equivalent of $HOME
|
||||||
|
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
|
||||||
|
|
||||||
|
@REM Execute a user defined script before this one
|
||||||
|
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
|
||||||
|
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
|
||||||
|
if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
|
||||||
|
if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
|
||||||
|
:skipRcPre
|
||||||
|
|
||||||
|
@setlocal
|
||||||
|
|
||||||
|
set ERROR_CODE=0
|
||||||
|
|
||||||
|
@REM To isolate internal variables from possible post scripts, we use another setlocal
|
||||||
|
@setlocal
|
||||||
|
|
||||||
|
@REM ==== START VALIDATION ====
|
||||||
|
if not "%JAVA_HOME%" == "" goto OkJHome
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo Error: JAVA_HOME not found in your environment. >&2
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||||
|
echo location of your Java installation. >&2
|
||||||
|
echo.
|
||||||
|
goto error
|
||||||
|
|
||||||
|
:OkJHome
|
||||||
|
if exist "%JAVA_HOME%\bin\java.exe" goto init
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo Error: JAVA_HOME is set to an invalid directory. >&2
|
||||||
|
echo JAVA_HOME = "%JAVA_HOME%" >&2
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||||
|
echo location of your Java installation. >&2
|
||||||
|
echo.
|
||||||
|
goto error
|
||||||
|
|
||||||
|
@REM ==== END VALIDATION ====
|
||||||
|
|
||||||
|
:init
|
||||||
|
|
||||||
|
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
|
||||||
|
@REM Fallback to current working directory if not found.
|
||||||
|
|
||||||
|
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
|
||||||
|
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
|
||||||
|
|
||||||
|
set EXEC_DIR=%CD%
|
||||||
|
set WDIR=%EXEC_DIR%
|
||||||
|
:findBaseDir
|
||||||
|
IF EXIST "%WDIR%"\.mvn goto baseDirFound
|
||||||
|
cd ..
|
||||||
|
IF "%WDIR%"=="%CD%" goto baseDirNotFound
|
||||||
|
set WDIR=%CD%
|
||||||
|
goto findBaseDir
|
||||||
|
|
||||||
|
:baseDirFound
|
||||||
|
set MAVEN_PROJECTBASEDIR=%WDIR%
|
||||||
|
cd "%EXEC_DIR%"
|
||||||
|
goto endDetectBaseDir
|
||||||
|
|
||||||
|
:baseDirNotFound
|
||||||
|
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
|
||||||
|
cd "%EXEC_DIR%"
|
||||||
|
|
||||||
|
:endDetectBaseDir
|
||||||
|
|
||||||
|
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
|
||||||
|
|
||||||
|
@setlocal EnableExtensions EnableDelayedExpansion
|
||||||
|
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
|
||||||
|
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
|
||||||
|
|
||||||
|
:endReadAdditionalConfig
|
||||||
|
|
||||||
|
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
|
||||||
|
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
|
||||||
|
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||||
|
|
||||||
|
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.2/maven-wrapper-0.5.2.jar"
|
||||||
|
|
||||||
|
FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
|
||||||
|
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
|
||||||
|
)
|
||||||
|
|
||||||
|
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
|
||||||
|
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
|
||||||
|
if exist %WRAPPER_JAR% (
|
||||||
|
echo Found %WRAPPER_JAR%
|
||||||
|
) else (
|
||||||
|
if not "%MVNW_REPOURL%" == "" (
|
||||||
|
SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.2/maven-wrapper-0.5.2.jar"
|
||||||
|
)
|
||||||
|
echo Couldn't find %WRAPPER_JAR%, downloading it ...
|
||||||
|
echo Downloading from: %DOWNLOAD_URL%
|
||||||
|
|
||||||
|
powershell -Command "&{"^
|
||||||
|
"$webclient = new-object System.Net.WebClient;"^
|
||||||
|
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
|
||||||
|
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
|
||||||
|
"}"^
|
||||||
|
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
|
||||||
|
"}"
|
||||||
|
echo Finished downloading %WRAPPER_JAR%
|
||||||
|
)
|
||||||
|
@REM End of extension
|
||||||
|
|
||||||
|
%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
|
||||||
|
if ERRORLEVEL 1 goto error
|
||||||
|
goto end
|
||||||
|
|
||||||
|
:error
|
||||||
|
set ERROR_CODE=1
|
||||||
|
|
||||||
|
:end
|
||||||
|
@endlocal & set ERROR_CODE=%ERROR_CODE%
|
||||||
|
|
||||||
|
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
|
||||||
|
@REM check for post script, once with legacy .bat ending and once with .cmd ending
|
||||||
|
if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
|
||||||
|
if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
|
||||||
|
:skipRcPost
|
||||||
|
|
||||||
|
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
|
||||||
|
if "%MAVEN_BATCH_PAUSE%" == "on" pause
|
||||||
|
|
||||||
|
if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
|
||||||
|
|
||||||
|
exit /B %ERROR_CODE%
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-parent</artifactId>
|
||||||
|
<version>3.3.6</version>
|
||||||
|
<relativePath /> <!-- lookup parent from repository -->
|
||||||
|
</parent>
|
||||||
|
<groupId>com.example</groupId>
|
||||||
|
<artifactId>mcp-starter-default-client</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<name>Spring AI - MCP Starter Default Client</name>
|
||||||
|
<description>Spring AI - MCP Starter Default Client</description>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<java.version>17</java.version>
|
||||||
|
<spring-ai.version>1.0.0-SNAPSHOT</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-mcp-client-spring-boot-starter</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- <dependency>
|
||||||
|
<groupId>org.springframework.ai</groupId>
|
||||||
|
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
|
||||||
|
</dependency> -->
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.ai</groupId>
|
||||||
|
<artifactId>spring-ai-anthropic-spring-boot-starter</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<name>Central Portal Snapshots</name>
|
||||||
|
<id>central-portal-snapshots</id>
|
||||||
|
<url>https://central.sonatype.com/repository/maven-snapshots/</url>
|
||||||
|
<releases>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</releases>
|
||||||
|
<snapshots>
|
||||||
|
<enabled>true</enabled>
|
||||||
|
</snapshots>
|
||||||
|
</repository>
|
||||||
|
<repository>
|
||||||
|
<id>spring-milestones</id>
|
||||||
|
<name>Spring Milestones</name>
|
||||||
|
<url>https://repo.spring.io/libs-milestone-local</url>
|
||||||
|
<snapshots>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</snapshots>
|
||||||
|
</repository>
|
||||||
|
<repository>
|
||||||
|
<id>spring-snapshots</id>
|
||||||
|
<name>Spring Snapshots</name>
|
||||||
|
<url>https://repo.spring.io/snapshot</url>
|
||||||
|
<releases>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</releases>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
|
||||||
|
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2025-2025 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.springframework.ai.mcp.samples.client;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.springframework.ai.chat.client.ChatClient;
|
||||||
|
import org.springframework.ai.tool.ToolCallback;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.boot.CommandLineRunner;
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
public class Application {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(Application.class, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Value("${spring.ai.mcp.client.demo.user.input}")
|
||||||
|
private String userInput;
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public CommandLineRunner predefinedQuestions(ChatClient.Builder chatClientBuilder, List<ToolCallback> tools,
|
||||||
|
ConfigurableApplicationContext context) {
|
||||||
|
|
||||||
|
return args -> {
|
||||||
|
|
||||||
|
var chatClient = chatClientBuilder
|
||||||
|
.defaultTools(tools)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
System.out.println("\n>>> QUESTION: " + userInput);
|
||||||
|
System.out.println("\n>>> ASSISTANT: " + chatClient.prompt(userInput).call().content());
|
||||||
|
|
||||||
|
context.close();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
spring.application.name=mcp
|
||||||
|
spring.main.web-application-type=none
|
||||||
|
|
||||||
|
spring.ai.openai.api-key=${OPENAI_API_KEY}
|
||||||
|
spring.ai.anthropic.api-key=${ANTHROPIC_API_KEY}
|
||||||
|
|
||||||
|
# spring.ai.mcp.client.stdio.servers-configuration=classpath:/mcp-servers-config.json
|
||||||
|
|
||||||
|
spring.ai.mcp.client.stdio.connections.brave-search.command=npx
|
||||||
|
spring.ai.mcp.client.stdio.connections.brave-search.args=-y,@modelcontextprotocol/server-brave-search
|
||||||
|
# spring.ai.mcp.client.stdio.connections.brave-search.env.FOO=BAAR
|
||||||
|
|
||||||
|
|
||||||
|
spring.ai.mcp.client.demo.user.input=What tools are available?
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"mcpServers": {
|
||||||
|
"brave-search": {
|
||||||
|
"command": "npx",
|
||||||
|
"args": [
|
||||||
|
"-y",
|
||||||
|
"@modelcontextprotocol/server-brave-search"
|
||||||
|
],
|
||||||
|
"env": {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
model-context-protocol/client-starter/starter-webflux-client/.mvn/wrapper/maven-wrapper.jar
vendored
Normal file
BIN
model-context-protocol/client-starter/starter-webflux-client/.mvn/wrapper/maven-wrapper.jar
vendored
Normal file
Binary file not shown.
@@ -0,0 +1,2 @@
|
|||||||
|
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.4/apache-maven-3.8.4-bin.zip
|
||||||
|
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar
|
||||||
305
model-context-protocol/client-starter/starter-webflux-client/mvnw
vendored
Executable file
305
model-context-protocol/client-starter/starter-webflux-client/mvnw
vendored
Executable file
@@ -0,0 +1,305 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
# Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
# or more contributor license agreements. See the NOTICE file
|
||||||
|
# distributed with this work for additional information
|
||||||
|
# regarding copyright ownership. The ASF licenses this file
|
||||||
|
# to you under the Apache License, Version 2.0 (the
|
||||||
|
# "License"); you may not use this file except in compliance
|
||||||
|
# with the License. You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing,
|
||||||
|
# software distributed under the License is distributed on an
|
||||||
|
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
# KIND, either express or implied. See the License for the
|
||||||
|
# specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
# Maven2 Start Up Batch script
|
||||||
|
#
|
||||||
|
# Required ENV vars:
|
||||||
|
# ------------------
|
||||||
|
# JAVA_HOME - location of a JDK home dir
|
||||||
|
#
|
||||||
|
# Optional ENV vars
|
||||||
|
# -----------------
|
||||||
|
# M2_HOME - location of maven2's installed home dir
|
||||||
|
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
||||||
|
# e.g. to debug Maven itself, use
|
||||||
|
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
||||||
|
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
if [ -z "$MAVEN_SKIP_RC" ] ; then
|
||||||
|
|
||||||
|
if [ -f /etc/mavenrc ] ; then
|
||||||
|
. /etc/mavenrc
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f "$HOME/.mavenrc" ] ; then
|
||||||
|
. "$HOME/.mavenrc"
|
||||||
|
fi
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
# OS specific support. $var _must_ be set to either true or false.
|
||||||
|
cygwin=false;
|
||||||
|
darwin=false;
|
||||||
|
mingw=false
|
||||||
|
case "`uname`" in
|
||||||
|
CYGWIN*) cygwin=true ;;
|
||||||
|
MINGW*) mingw=true;;
|
||||||
|
Darwin*) darwin=true
|
||||||
|
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
|
||||||
|
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
|
||||||
|
if [ -z "$JAVA_HOME" ]; then
|
||||||
|
if [ -x "/usr/libexec/java_home" ]; then
|
||||||
|
export JAVA_HOME="`/usr/libexec/java_home`"
|
||||||
|
else
|
||||||
|
export JAVA_HOME="/Library/Java/Home"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [ -z "$JAVA_HOME" ] ; then
|
||||||
|
if [ -r /etc/gentoo-release ] ; then
|
||||||
|
JAVA_HOME=`java-config --jre-home`
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$M2_HOME" ] ; then
|
||||||
|
## resolve links - $0 may be a link to maven's home
|
||||||
|
PRG="$0"
|
||||||
|
|
||||||
|
# need this for relative symlinks
|
||||||
|
while [ -h "$PRG" ] ; do
|
||||||
|
ls=`ls -ld "$PRG"`
|
||||||
|
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||||
|
if expr "$link" : '/.*' > /dev/null; then
|
||||||
|
PRG="$link"
|
||||||
|
else
|
||||||
|
PRG="`dirname "$PRG"`/$link"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
saveddir=`pwd`
|
||||||
|
|
||||||
|
M2_HOME=`dirname "$PRG"`/..
|
||||||
|
|
||||||
|
# make it fully qualified
|
||||||
|
M2_HOME=`cd "$M2_HOME" && pwd`
|
||||||
|
|
||||||
|
cd "$saveddir"
|
||||||
|
# echo Using m2 at $M2_HOME
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Cygwin, ensure paths are in UNIX format before anything is touched
|
||||||
|
if $cygwin ; then
|
||||||
|
[ -n "$M2_HOME" ] &&
|
||||||
|
M2_HOME=`cygpath --unix "$M2_HOME"`
|
||||||
|
[ -n "$JAVA_HOME" ] &&
|
||||||
|
JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
|
||||||
|
[ -n "$CLASSPATH" ] &&
|
||||||
|
CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Mingw, ensure paths are in UNIX format before anything is touched
|
||||||
|
if $mingw ; then
|
||||||
|
[ -n "$M2_HOME" ] &&
|
||||||
|
M2_HOME="`(cd "$M2_HOME"; pwd)`"
|
||||||
|
[ -n "$JAVA_HOME" ] &&
|
||||||
|
JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$JAVA_HOME" ]; then
|
||||||
|
javaExecutable="`which javac`"
|
||||||
|
if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
|
||||||
|
# readlink(1) is not available as standard on Solaris 10.
|
||||||
|
readLink=`which readlink`
|
||||||
|
if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
|
||||||
|
if $darwin ; then
|
||||||
|
javaHome="`dirname \"$javaExecutable\"`"
|
||||||
|
javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
|
||||||
|
else
|
||||||
|
javaExecutable="`readlink -f \"$javaExecutable\"`"
|
||||||
|
fi
|
||||||
|
javaHome="`dirname \"$javaExecutable\"`"
|
||||||
|
javaHome=`expr "$javaHome" : '\(.*\)/bin'`
|
||||||
|
JAVA_HOME="$javaHome"
|
||||||
|
export JAVA_HOME
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$JAVACMD" ] ; then
|
||||||
|
if [ -n "$JAVA_HOME" ] ; then
|
||||||
|
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||||
|
# IBM's JDK on AIX uses strange locations for the executables
|
||||||
|
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||||
|
else
|
||||||
|
JAVACMD="$JAVA_HOME/bin/java"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
JAVACMD="`which java`"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -x "$JAVACMD" ] ; then
|
||||||
|
echo "Error: JAVA_HOME is not defined correctly." >&2
|
||||||
|
echo " We cannot execute $JAVACMD" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$JAVA_HOME" ] ; then
|
||||||
|
echo "Warning: JAVA_HOME environment variable is not set."
|
||||||
|
fi
|
||||||
|
|
||||||
|
CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
|
||||||
|
|
||||||
|
# traverses directory structure from process work directory to filesystem root
|
||||||
|
# first directory with .mvn subdirectory is considered project base directory
|
||||||
|
find_maven_basedir() {
|
||||||
|
|
||||||
|
if [ -z "$1" ]
|
||||||
|
then
|
||||||
|
echo "Path not specified to find_maven_basedir"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
basedir="$1"
|
||||||
|
wdir="$1"
|
||||||
|
while [ "$wdir" != '/' ] ; do
|
||||||
|
if [ -d "$wdir"/.mvn ] ; then
|
||||||
|
basedir=$wdir
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
|
||||||
|
if [ -d "${wdir}" ]; then
|
||||||
|
wdir=`cd "$wdir/.."; pwd`
|
||||||
|
fi
|
||||||
|
# end of workaround
|
||||||
|
done
|
||||||
|
echo "${basedir}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# concatenates all lines of a file
|
||||||
|
concat_lines() {
|
||||||
|
if [ -f "$1" ]; then
|
||||||
|
echo "$(tr -s '\n' ' ' < "$1")"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
BASE_DIR=`find_maven_basedir "$(pwd)"`
|
||||||
|
if [ -z "$BASE_DIR" ]; then
|
||||||
|
exit 1;
|
||||||
|
fi
|
||||||
|
|
||||||
|
##########################################################################################
|
||||||
|
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
|
||||||
|
# This allows using the maven wrapper in projects that prohibit checking in binary data.
|
||||||
|
##########################################################################################
|
||||||
|
if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
|
||||||
|
if [ "$MVNW_VERBOSE" = true ]; then
|
||||||
|
echo "Found .mvn/wrapper/maven-wrapper.jar"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if [ "$MVNW_VERBOSE" = true ]; then
|
||||||
|
echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
|
||||||
|
fi
|
||||||
|
if [ "$MVNW_REPOURL" = true]; then
|
||||||
|
jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.2/maven-wrapper-0.5.2.jar"
|
||||||
|
else
|
||||||
|
jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.2/maven-wrapper-0.5.2.jar"
|
||||||
|
fi
|
||||||
|
while IFS="=" read key value; do
|
||||||
|
case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
|
||||||
|
esac
|
||||||
|
done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
|
||||||
|
if [ "$MVNW_VERBOSE" = true ]; then
|
||||||
|
echo "Downloading from: $jarUrl"
|
||||||
|
fi
|
||||||
|
wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
|
||||||
|
if $cygwin; then
|
||||||
|
wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
|
||||||
|
fi
|
||||||
|
|
||||||
|
if command -v wget > /dev/null; then
|
||||||
|
if [ "$MVNW_VERBOSE" = true ]; then
|
||||||
|
echo "Found wget ... using wget"
|
||||||
|
fi
|
||||||
|
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
|
||||||
|
wget "$jarUrl" -O "$wrapperJarPath"
|
||||||
|
else
|
||||||
|
wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
|
||||||
|
fi
|
||||||
|
elif command -v curl > /dev/null; then
|
||||||
|
if [ "$MVNW_VERBOSE" = true ]; then
|
||||||
|
echo "Found curl ... using curl"
|
||||||
|
fi
|
||||||
|
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
|
||||||
|
curl -o "$wrapperJarPath" "$jarUrl" -f
|
||||||
|
else
|
||||||
|
curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
|
||||||
|
fi
|
||||||
|
|
||||||
|
else
|
||||||
|
if [ "$MVNW_VERBOSE" = true ]; then
|
||||||
|
echo "Falling back to using Java to download"
|
||||||
|
fi
|
||||||
|
javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
|
||||||
|
# For Cygwin, switch paths to Windows format before running javac
|
||||||
|
if $cygwin; then
|
||||||
|
javaClass=`cygpath --path --windows "$javaClass"`
|
||||||
|
fi
|
||||||
|
if [ -e "$javaClass" ]; then
|
||||||
|
if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
|
||||||
|
if [ "$MVNW_VERBOSE" = true ]; then
|
||||||
|
echo " - Compiling MavenWrapperDownloader.java ..."
|
||||||
|
fi
|
||||||
|
# Compiling the Java class
|
||||||
|
("$JAVA_HOME/bin/javac" "$javaClass")
|
||||||
|
fi
|
||||||
|
if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
|
||||||
|
# Running the downloader
|
||||||
|
if [ "$MVNW_VERBOSE" = true ]; then
|
||||||
|
echo " - Running MavenWrapperDownloader.java ..."
|
||||||
|
fi
|
||||||
|
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
##########################################################################################
|
||||||
|
# End of extension
|
||||||
|
##########################################################################################
|
||||||
|
|
||||||
|
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
|
||||||
|
if [ "$MVNW_VERBOSE" = true ]; then
|
||||||
|
echo $MAVEN_PROJECTBASEDIR
|
||||||
|
fi
|
||||||
|
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
|
||||||
|
|
||||||
|
# For Cygwin, switch paths to Windows format before running java
|
||||||
|
if $cygwin; then
|
||||||
|
[ -n "$M2_HOME" ] &&
|
||||||
|
M2_HOME=`cygpath --path --windows "$M2_HOME"`
|
||||||
|
[ -n "$JAVA_HOME" ] &&
|
||||||
|
JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
|
||||||
|
[ -n "$CLASSPATH" ] &&
|
||||||
|
CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
|
||||||
|
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
|
||||||
|
MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
|
||||||
|
fi
|
||||||
|
|
||||||
|
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||||
|
|
||||||
|
exec "$JAVACMD" \
|
||||||
|
$MAVEN_OPTS \
|
||||||
|
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
|
||||||
|
"-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
|
||||||
|
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
|
||||||
172
model-context-protocol/client-starter/starter-webflux-client/mvnw.cmd
vendored
Executable file
172
model-context-protocol/client-starter/starter-webflux-client/mvnw.cmd
vendored
Executable file
@@ -0,0 +1,172 @@
|
|||||||
|
@REM ----------------------------------------------------------------------------
|
||||||
|
@REM Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
@REM or more contributor license agreements. See the NOTICE file
|
||||||
|
@REM distributed with this work for additional information
|
||||||
|
@REM regarding copyright ownership. The ASF licenses this file
|
||||||
|
@REM to you under the Apache License, Version 2.0 (the
|
||||||
|
@REM "License"); you may not use this file except in compliance
|
||||||
|
@REM with the License. You may obtain a copy of the License at
|
||||||
|
@REM
|
||||||
|
@REM http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
@REM
|
||||||
|
@REM Unless required by applicable law or agreed to in writing,
|
||||||
|
@REM software distributed under the License is distributed on an
|
||||||
|
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
@REM KIND, either express or implied. See the License for the
|
||||||
|
@REM specific language governing permissions and limitations
|
||||||
|
@REM under the License.
|
||||||
|
@REM ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@REM ----------------------------------------------------------------------------
|
||||||
|
@REM Maven2 Start Up Batch script
|
||||||
|
@REM
|
||||||
|
@REM Required ENV vars:
|
||||||
|
@REM JAVA_HOME - location of a JDK home dir
|
||||||
|
@REM
|
||||||
|
@REM Optional ENV vars
|
||||||
|
@REM M2_HOME - location of maven2's installed home dir
|
||||||
|
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
|
||||||
|
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
|
||||||
|
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
||||||
|
@REM e.g. to debug Maven itself, use
|
||||||
|
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
||||||
|
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
||||||
|
@REM ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
|
||||||
|
@echo off
|
||||||
|
@REM set title of command window
|
||||||
|
title %0
|
||||||
|
@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
|
||||||
|
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
|
||||||
|
|
||||||
|
@REM set %HOME% to equivalent of $HOME
|
||||||
|
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
|
||||||
|
|
||||||
|
@REM Execute a user defined script before this one
|
||||||
|
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
|
||||||
|
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
|
||||||
|
if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
|
||||||
|
if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
|
||||||
|
:skipRcPre
|
||||||
|
|
||||||
|
@setlocal
|
||||||
|
|
||||||
|
set ERROR_CODE=0
|
||||||
|
|
||||||
|
@REM To isolate internal variables from possible post scripts, we use another setlocal
|
||||||
|
@setlocal
|
||||||
|
|
||||||
|
@REM ==== START VALIDATION ====
|
||||||
|
if not "%JAVA_HOME%" == "" goto OkJHome
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo Error: JAVA_HOME not found in your environment. >&2
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||||
|
echo location of your Java installation. >&2
|
||||||
|
echo.
|
||||||
|
goto error
|
||||||
|
|
||||||
|
:OkJHome
|
||||||
|
if exist "%JAVA_HOME%\bin\java.exe" goto init
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo Error: JAVA_HOME is set to an invalid directory. >&2
|
||||||
|
echo JAVA_HOME = "%JAVA_HOME%" >&2
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||||
|
echo location of your Java installation. >&2
|
||||||
|
echo.
|
||||||
|
goto error
|
||||||
|
|
||||||
|
@REM ==== END VALIDATION ====
|
||||||
|
|
||||||
|
:init
|
||||||
|
|
||||||
|
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
|
||||||
|
@REM Fallback to current working directory if not found.
|
||||||
|
|
||||||
|
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
|
||||||
|
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
|
||||||
|
|
||||||
|
set EXEC_DIR=%CD%
|
||||||
|
set WDIR=%EXEC_DIR%
|
||||||
|
:findBaseDir
|
||||||
|
IF EXIST "%WDIR%"\.mvn goto baseDirFound
|
||||||
|
cd ..
|
||||||
|
IF "%WDIR%"=="%CD%" goto baseDirNotFound
|
||||||
|
set WDIR=%CD%
|
||||||
|
goto findBaseDir
|
||||||
|
|
||||||
|
:baseDirFound
|
||||||
|
set MAVEN_PROJECTBASEDIR=%WDIR%
|
||||||
|
cd "%EXEC_DIR%"
|
||||||
|
goto endDetectBaseDir
|
||||||
|
|
||||||
|
:baseDirNotFound
|
||||||
|
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
|
||||||
|
cd "%EXEC_DIR%"
|
||||||
|
|
||||||
|
:endDetectBaseDir
|
||||||
|
|
||||||
|
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
|
||||||
|
|
||||||
|
@setlocal EnableExtensions EnableDelayedExpansion
|
||||||
|
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
|
||||||
|
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
|
||||||
|
|
||||||
|
:endReadAdditionalConfig
|
||||||
|
|
||||||
|
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
|
||||||
|
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
|
||||||
|
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||||
|
|
||||||
|
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.2/maven-wrapper-0.5.2.jar"
|
||||||
|
|
||||||
|
FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
|
||||||
|
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
|
||||||
|
)
|
||||||
|
|
||||||
|
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
|
||||||
|
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
|
||||||
|
if exist %WRAPPER_JAR% (
|
||||||
|
echo Found %WRAPPER_JAR%
|
||||||
|
) else (
|
||||||
|
if not "%MVNW_REPOURL%" == "" (
|
||||||
|
SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.2/maven-wrapper-0.5.2.jar"
|
||||||
|
)
|
||||||
|
echo Couldn't find %WRAPPER_JAR%, downloading it ...
|
||||||
|
echo Downloading from: %DOWNLOAD_URL%
|
||||||
|
|
||||||
|
powershell -Command "&{"^
|
||||||
|
"$webclient = new-object System.Net.WebClient;"^
|
||||||
|
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
|
||||||
|
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
|
||||||
|
"}"^
|
||||||
|
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
|
||||||
|
"}"
|
||||||
|
echo Finished downloading %WRAPPER_JAR%
|
||||||
|
)
|
||||||
|
@REM End of extension
|
||||||
|
|
||||||
|
%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
|
||||||
|
if ERRORLEVEL 1 goto error
|
||||||
|
goto end
|
||||||
|
|
||||||
|
:error
|
||||||
|
set ERROR_CODE=1
|
||||||
|
|
||||||
|
:end
|
||||||
|
@endlocal & set ERROR_CODE=%ERROR_CODE%
|
||||||
|
|
||||||
|
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
|
||||||
|
@REM check for post script, once with legacy .bat ending and once with .cmd ending
|
||||||
|
if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
|
||||||
|
if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
|
||||||
|
:skipRcPost
|
||||||
|
|
||||||
|
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
|
||||||
|
if "%MAVEN_BATCH_PAUSE%" == "on" pause
|
||||||
|
|
||||||
|
if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
|
||||||
|
|
||||||
|
exit /B %ERROR_CODE%
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-parent</artifactId>
|
||||||
|
<version>3.3.6</version>
|
||||||
|
<relativePath /> <!-- lookup parent from repository -->
|
||||||
|
</parent>
|
||||||
|
<groupId>com.example</groupId>
|
||||||
|
<artifactId>mcp-starter-webflux-client</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<name>Spring AI - MCP Starter WebFlux Client</name>
|
||||||
|
<description>Spring AI - MCP Starter WebFlux Client</description>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<java.version>17</java.version>
|
||||||
|
<spring-ai.version>1.0.0-SNAPSHOT</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-mcp-server-webmvc-spring-boot-starter</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- <dependency>
|
||||||
|
<groupId>org.springframework.ai</groupId>
|
||||||
|
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
|
||||||
|
</dependency> -->
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.ai</groupId>
|
||||||
|
<artifactId>spring-ai-anthropic-spring-boot-starter</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<name>Central Portal Snapshots</name>
|
||||||
|
<id>central-portal-snapshots</id>
|
||||||
|
<url>https://central.sonatype.com/repository/maven-snapshots/</url>
|
||||||
|
<releases>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</releases>
|
||||||
|
<snapshots>
|
||||||
|
<enabled>true</enabled>
|
||||||
|
</snapshots>
|
||||||
|
</repository>
|
||||||
|
<repository>
|
||||||
|
<id>spring-milestones</id>
|
||||||
|
<name>Spring Milestones</name>
|
||||||
|
<url>https://repo.spring.io/libs-milestone-local</url>
|
||||||
|
<snapshots>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</snapshots>
|
||||||
|
</repository>
|
||||||
|
<repository>
|
||||||
|
<id>spring-snapshots</id>
|
||||||
|
<name>Spring Snapshots</name>
|
||||||
|
<url>https://repo.spring.io/snapshot</url>
|
||||||
|
<releases>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</releases>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
|
||||||
|
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2025-2025 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.springframework.ai.mcp.samples.client;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.springframework.ai.chat.client.ChatClient;
|
||||||
|
import org.springframework.ai.tool.ToolCallback;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.boot.CommandLineRunner;
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
public class Application {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(Application.class, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Value("${spring.ai.mcp.client.demo.user.input}")
|
||||||
|
private String userInput;
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public CommandLineRunner predefinedQuestions(ChatClient.Builder chatClientBuilder, List<ToolCallback> tools,
|
||||||
|
ConfigurableApplicationContext context) {
|
||||||
|
|
||||||
|
return args -> {
|
||||||
|
|
||||||
|
var chatClient = chatClientBuilder
|
||||||
|
.defaultTools(tools)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
System.out.println("\n>>> QUESTION: " + userInput);
|
||||||
|
System.out.println("\n>>> ASSISTANT: " + chatClient.prompt(userInput).call().content());
|
||||||
|
|
||||||
|
context.close();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
spring.application.name=mcp
|
||||||
|
spring.main.web-application-type=none
|
||||||
|
|
||||||
|
spring.ai.openai.api-key=${OPENAI_API_KEY}
|
||||||
|
spring.ai.anthropic.api-key=${ANTHROPIC_API_KEY}
|
||||||
|
|
||||||
|
# spring.ai.mcp.client.stdio.servers-configuration=classpath:/mcp-servers-config.json
|
||||||
|
|
||||||
|
spring.ai.mcp.client.stdio.connections.brave-search.command=npx
|
||||||
|
spring.ai.mcp.client.stdio.connections.brave-search.args=-y,@modelcontextprotocol/server-brave-search
|
||||||
|
# spring.ai.mcp.client.stdio.connections.brave-search.env.FOO=BAAR
|
||||||
|
|
||||||
|
|
||||||
|
spring.ai.mcp.client.demo.user.input=What tools are available?
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"mcpServers": {
|
||||||
|
"brave-search": {
|
||||||
|
"command": "npx",
|
||||||
|
"args": [
|
||||||
|
"-y",
|
||||||
|
"@modelcontextprotocol/server-brave-search"
|
||||||
|
],
|
||||||
|
"env": {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,176 +0,0 @@
|
|||||||
# Spring AI MCP Quick Weather Server Sample
|
|
||||||
|
|
||||||
This sample project demonstrates a simplified implementation of the Spring AI Model Context Protocol (MCP). It shows how to create an MCP server that exposes weather-related tools using the National Weather Service API.
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
|
|
||||||
The sample provides:
|
|
||||||
- A Spring Boot application implementing an MCP server
|
|
||||||
- Two transport mode implementations: Stdio and SSE (Server-Sent Events)
|
|
||||||
- Two weather-related tools:
|
|
||||||
- Get weather forecast by location (latitude/longitude)
|
|
||||||
- Get weather alerts by US state
|
|
||||||
|
|
||||||
## Building the Project
|
|
||||||
|
|
||||||
```bash
|
|
||||||
./mvnw clean package
|
|
||||||
```
|
|
||||||
|
|
||||||
## Running the Server
|
|
||||||
|
|
||||||
The server can be started in two transport modes, controlled by the `transport.mode` property:
|
|
||||||
|
|
||||||
### Stdio Mode (Default)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
java -Dspring.ai.mcp.server.transport=STDIO -Dspring.main.web-application-type=none -Dlogging.pattern.console= -jar target/mcp-weather-server-quick-0.0.1-SNAPSHOT.jar
|
|
||||||
```
|
|
||||||
|
|
||||||
The Stdio mode server is automatically started by the client - no explicit server startup is needed.
|
|
||||||
But you have to build the server jar first: `./mvnw clean install -DskipTests`.
|
|
||||||
|
|
||||||
In Stdio mode the server must not emit any messages/logs to the console (e.g. standard out) but the JSON messages produced by the server.
|
|
||||||
|
|
||||||
### SSE Mode
|
|
||||||
```bash
|
|
||||||
java -Dspring.ai.mcp.server.transport=WEBFLUX -jar target/mcp-weather-server-quick-0.0.1-SNAPSHOT.jar
|
|
||||||
```
|
|
||||||
|
|
||||||
## Sample Clients
|
|
||||||
|
|
||||||
The project includes example clients for both transport modes:
|
|
||||||
|
|
||||||
### Stdio Client (ClientStdio.java)
|
|
||||||
```java
|
|
||||||
var stdioParams = ServerParameters.builder("java")
|
|
||||||
.args("-Dspring.ai.mcp.server.transport=STDIO", "-Dspring.main.web-application-type=none",
|
|
||||||
"-Dlogging.pattern.console=", "-jar",
|
|
||||||
"model-context-protocol/mcp-weather-server-quick/target/mcp-weather-server-quick-0.0.1-SNAPSHOT.jar")
|
|
||||||
.build();
|
|
||||||
|
|
||||||
var transport = new StdioClientTransport(stdioParams);
|
|
||||||
var client = McpClient.sync(transport).build();
|
|
||||||
```
|
|
||||||
|
|
||||||
### SSE Client (ClientSse.java)
|
|
||||||
```java
|
|
||||||
var transport = new WebFluxSseClientTransport(WebClient.builder().baseUrl("http://localhost:8080"));
|
|
||||||
var client = McpClient.using(transport).sync();
|
|
||||||
```
|
|
||||||
|
|
||||||
### Claud Destop
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"mcpServers": {
|
|
||||||
"spring-ai-mcp-weather": {
|
|
||||||
"command": "java",
|
|
||||||
"args": [
|
|
||||||
"-Dspring.ai.mcp.server.transport=STDIO",
|
|
||||||
"-Dspring.main.web-application-type=none",
|
|
||||||
"-Dlogging.pattern.console=",
|
|
||||||
"-jar",
|
|
||||||
"<YOUR ABSOLUTE PATH TO>/mcp-weather-server-quick-0.0.1-SNAPSHOT.jar"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Available Tools
|
|
||||||
|
|
||||||
### Weather Forecast Tool
|
|
||||||
- Name: `getWeatherForecastByLocation`
|
|
||||||
- Description: Get weather forecast for a specific latitude/longitude
|
|
||||||
- Parameters:
|
|
||||||
- `latitude`: double - Latitude coordinate
|
|
||||||
- `longitude`: double - Longitude coordinate
|
|
||||||
- Example:
|
|
||||||
```java
|
|
||||||
CallToolResult forecastResult = client.callTool(new CallToolRequest("getWeatherForecastByLocation",
|
|
||||||
Map.of("latitude", 47.6062, "longitude", -122.3321)));
|
|
||||||
```
|
|
||||||
|
|
||||||
### Weather Alerts Tool
|
|
||||||
- Name: `getAlerts`
|
|
||||||
- Description: Get weather alerts for a US state
|
|
||||||
- Parameters:
|
|
||||||
- `state`: String - Two-letter US state code (e.g. CA, NY)
|
|
||||||
- Example:
|
|
||||||
```java
|
|
||||||
CallToolResult alertResult = client.callTool(new CallToolRequest("getAlerts",
|
|
||||||
Map.of("state", "NY")));
|
|
||||||
```
|
|
||||||
|
|
||||||
## Client Usage Example
|
|
||||||
|
|
||||||
```java
|
|
||||||
// Initialize client
|
|
||||||
client.initialize();
|
|
||||||
|
|
||||||
// Test connection
|
|
||||||
client.ping();
|
|
||||||
|
|
||||||
// List available tools
|
|
||||||
ListToolsResult tools = client.listTools();
|
|
||||||
System.out.println("Available tools: " + tools);
|
|
||||||
|
|
||||||
// Get weather forecast for Seattle
|
|
||||||
CallToolResult weatherForcastResult = client.callTool(new CallToolRequest("getWeatherForecastByLocation",
|
|
||||||
Map.of("latitude", "47.6062", "longitude", "-122.3321")));
|
|
||||||
System.out.println("Weather Forcast: " + weatherForcastResult);
|
|
||||||
|
|
||||||
// Get weather alerts for New York
|
|
||||||
CallToolResult alertResult = client.callTool(new CallToolRequest("getAlerts", Map.of("state", "NY")));
|
|
||||||
System.out.println("Alert Response = " + alertResult);
|
|
||||||
|
|
||||||
// Close client
|
|
||||||
client.closeGracefully();
|
|
||||||
```
|
|
||||||
|
|
||||||
## Server Implementation
|
|
||||||
|
|
||||||
The server is implemented using Spring Boot and Spring AI's tool annotations:
|
|
||||||
|
|
||||||
```java
|
|
||||||
@SpringBootApplication
|
|
||||||
public class McpServerApplication {
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
SpringApplication.run(McpServerApplication.class, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public List<ToolCallback> weatherTools(WeatherService weatherService) {
|
|
||||||
return List.of(ToolCallbacks.from(weatherService));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
The `WeatherService` class provides the tool implementations using the `@Tool` annotation:
|
|
||||||
|
|
||||||
```java
|
|
||||||
@Service
|
|
||||||
public class WeatherService {
|
|
||||||
@Tool(description = "Get weather forecast for a specific latitude/longitude")
|
|
||||||
public String getWeatherForecastByLocation(double latitude, double longitude) {
|
|
||||||
// Implementation using weather.gov API
|
|
||||||
}
|
|
||||||
|
|
||||||
@Tool(description = "Get weather alerts for a US state. Input is Two-letter US state code (e.g. CA, NY)")
|
|
||||||
public String getAlerts(String state) {
|
|
||||||
// Implementation using weather.gov API
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Configuration
|
|
||||||
|
|
||||||
The application can be configured through `application.properties`:
|
|
||||||
|
|
||||||
- `spring.ai.mcp.server.transport`: Transport mode to use (STDIO/WEBFLUX)
|
|
||||||
- `server.port`: Server port for WEBFLUX mode (default: 8080)
|
|
||||||
- `spring.main.banner-mode`: Set to 'off' for STDIO mode
|
|
||||||
- `logging.pattern.console`: Clear this property for STDIO mode
|
|
||||||
- `logging.file.name`: Path to log file (useful when console logging is disabled)
|
|
||||||
@@ -1,175 +0,0 @@
|
|||||||
# Spring AI MCP Quick Weather Server Sample
|
|
||||||
|
|
||||||
This sample project demonstrates a simplified implementation of the Spring AI Model Context Protocol (MCP). It shows how to create an MCP server that exposes weather-related tools using the National Weather Service API.
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
|
|
||||||
The sample provides:
|
|
||||||
- A Spring Boot application implementing an MCP server
|
|
||||||
- Two transport mode implementations: Stdio and SSE (Server-Sent Events)
|
|
||||||
- Two weather-related tools:
|
|
||||||
- Get weather forecast by location (latitude/longitude)
|
|
||||||
- Get weather alerts by US state
|
|
||||||
|
|
||||||
## Building the Project
|
|
||||||
|
|
||||||
```bash
|
|
||||||
./mvnw clean install -DskipTests
|
|
||||||
```
|
|
||||||
|
|
||||||
## Running the Server
|
|
||||||
|
|
||||||
The server can be started in two transport modes, controlled by the `transport.mode` property:
|
|
||||||
|
|
||||||
### Stdio Mode (Default)
|
|
||||||
|
|
||||||
The Stdio mode server is automatically started by the client - no explicit server startup is needed.
|
|
||||||
But you have to build the server jar first: `./mvnw clean install -DskipTests`.
|
|
||||||
|
|
||||||
In Stdio mode the server must not emit any messages/logs to the console (e.g. standard out) but the JSON messages produced by the server.
|
|
||||||
|
|
||||||
### SSE Mode
|
|
||||||
```bash
|
|
||||||
java -Dspring.ai.mcp.server.transport=WEBFLUX -jar target/mcp-weather-server-quick-0.0.1-SNAPSHOT.jar
|
|
||||||
```
|
|
||||||
|
|
||||||
## Sample Clients
|
|
||||||
|
|
||||||
The project includes example clients for both transport modes:
|
|
||||||
|
|
||||||
### Stdio Client (ClientStdio.java)
|
|
||||||
|
|
||||||
**Note:** When running via command line, you may need to specify the full path to your Java executable since the shell environment (including `.bashrc`) might not be loaded. For example, instead of `"java"`, you might need to use the full path like `"/home/user/.sdkman/candidates/java/current/bin/java"`. You can find your Java path by running `which java` in your terminal.
|
|
||||||
|
|
||||||
```java
|
|
||||||
var stdioParams = ServerParameters.builder("java") // You may need to use full path to Java executable
|
|
||||||
.args("-Dspring.ai.mcp.server.transport=STDIO", "-Dspring.main.web-application-type=none",
|
|
||||||
"-Dlogging.pattern.console=", "-jar",
|
|
||||||
"model-context-protocol/mcp-weather-server-quick/target/mcp-weather-server-quick-0.0.1-SNAPSHOT.jar")
|
|
||||||
.build();
|
|
||||||
|
|
||||||
var transport = new StdioClientTransport(stdioParams);
|
|
||||||
var client = McpClient.sync(transport).build();
|
|
||||||
```
|
|
||||||
|
|
||||||
### SSE Client (ClientSse.java)
|
|
||||||
```java
|
|
||||||
var transport = new WebFluxSseClientTransport(WebClient.builder().baseUrl("http://localhost:8080"));
|
|
||||||
var client = McpClient.using(transport).sync();
|
|
||||||
```
|
|
||||||
|
|
||||||
### Claude Desktop
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"mcpServers": {
|
|
||||||
"spring-ai-mcp-weather": {
|
|
||||||
"command": "java",
|
|
||||||
"args": [
|
|
||||||
"-Dspring.ai.mcp.server.transport=STDIO",
|
|
||||||
"-Dspring.main.web-application-type=none",
|
|
||||||
"-Dlogging.pattern.console=",
|
|
||||||
"-jar",
|
|
||||||
"<YOUR ABSOLUTE PATH TO>/mcp-weather-server-quick-0.0.1-SNAPSHOT.jar"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Available Tools
|
|
||||||
|
|
||||||
### Weather Forecast Tool
|
|
||||||
- Name: `getWeatherForecastByLocation`
|
|
||||||
- Description: Get weather forecast for a specific latitude/longitude
|
|
||||||
- Parameters:
|
|
||||||
- `latitude`: double - Latitude coordinate
|
|
||||||
- `longitude`: double - Longitude coordinate
|
|
||||||
- Example:
|
|
||||||
```java
|
|
||||||
CallToolResult forecastResult = client.callTool(new CallToolRequest("getWeatherForecastByLocation",
|
|
||||||
Map.of("latitude", 47.6062, "longitude", -122.3321)));
|
|
||||||
```
|
|
||||||
|
|
||||||
### Weather Alerts Tool
|
|
||||||
- Name: `getAlerts`
|
|
||||||
- Description: Get weather alerts for a US state
|
|
||||||
- Parameters:
|
|
||||||
- `state`: String - Two-letter US state code (e.g. CA, NY)
|
|
||||||
- Example:
|
|
||||||
```java
|
|
||||||
CallToolResult alertResult = client.callTool(new CallToolRequest("getAlerts",
|
|
||||||
Map.of("state", "NY")));
|
|
||||||
```
|
|
||||||
|
|
||||||
## Client Usage Example (SampleClient.java)
|
|
||||||
|
|
||||||
```java
|
|
||||||
// Initialize client
|
|
||||||
client.initialize();
|
|
||||||
|
|
||||||
// Test connection
|
|
||||||
client.ping();
|
|
||||||
|
|
||||||
// List available tools
|
|
||||||
ListToolsResult tools = client.listTools();
|
|
||||||
System.out.println("Available tools: " + tools);
|
|
||||||
|
|
||||||
// Get weather forecast for Seattle
|
|
||||||
CallToolResult weatherForcastResult = client.callTool(new CallToolRequest("getWeatherForecastByLocation",
|
|
||||||
Map.of("latitude", "47.6062", "longitude", "-122.3321")));
|
|
||||||
System.out.println("Weather Forcast: " + weatherForcastResult);
|
|
||||||
|
|
||||||
// Get weather alerts for New York
|
|
||||||
CallToolResult alertResult = client.callTool(new CallToolRequest("getAlerts", Map.of("state", "NY")));
|
|
||||||
System.out.println("Alert Response = " + alertResult);
|
|
||||||
|
|
||||||
// Close client
|
|
||||||
client.closeGracefully();
|
|
||||||
```
|
|
||||||
|
|
||||||
## Server Implementation
|
|
||||||
|
|
||||||
The server is implemented using Spring Boot and Spring AI's tool annotations:
|
|
||||||
|
|
||||||
```java
|
|
||||||
@SpringBootApplication
|
|
||||||
public class McpServerApplication {
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
SpringApplication.run(McpServerApplication.class, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public List<ToolCallback> weatherTools(WeatherService weatherService) {
|
|
||||||
return List.of(ToolCallbacks.from(weatherService));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
The `WeatherService` class provides the tool implementations using the `@Tool` annotation:
|
|
||||||
|
|
||||||
```java
|
|
||||||
@Service
|
|
||||||
public class WeatherService {
|
|
||||||
@Tool(description = "Get weather forecast for a specific latitude/longitude")
|
|
||||||
public String getWeatherForecastByLocation(double latitude, double longitude) {
|
|
||||||
// Implementation using weather.gov API
|
|
||||||
}
|
|
||||||
|
|
||||||
@Tool(description = "Get weather alerts for a US state. Input is Two-letter US state code (e.g. CA, NY)")
|
|
||||||
public String getAlerts(String state) {
|
|
||||||
// Implementation using weather.gov API
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Configuration
|
|
||||||
|
|
||||||
The application can be configured through `application.properties`:
|
|
||||||
|
|
||||||
- `spring.ai.mcp.server.transport`: Transport mode to use (STDIO/WEBFLUX)
|
|
||||||
- `server.port`: Server port for WEBFLUX mode (default: 8080)
|
|
||||||
- `spring.main.banner-mode`: Set to 'off' for STDIO mode
|
|
||||||
- `logging.pattern.console`: Clear this property for STDIO mode
|
|
||||||
- `logging.file.name`: Path to log file (useful when console logging is disabled)
|
|
||||||
214
model-context-protocol/weather/starter-stdio-server/README.md
Normal file
214
model-context-protocol/weather/starter-stdio-server/README.md
Normal file
@@ -0,0 +1,214 @@
|
|||||||
|
# Spring AI MCP Weather STDIO Server
|
||||||
|
|
||||||
|
A Spring Boot starter project demonstrating how to build a Model Context Protocol (MCP) server that provides weather-related tools using the National Weather Service (weather.gov) API. This project showcases the Spring AI MCP Server Boot Starter capabilities with STDIO transport implementation.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- Java 17 or later
|
||||||
|
- Maven 3.6+
|
||||||
|
- Basic understanding of Spring Boot and Spring AI
|
||||||
|
- (Optional) Claude Desktop for AI assistant integration
|
||||||
|
|
||||||
|
## About Spring AI MCP Server Boot Starter
|
||||||
|
|
||||||
|
This project uses `spring-ai-mcp-server-spring-boot-starter`, which provides:
|
||||||
|
- Automatic configuration of MCP server components
|
||||||
|
- Support for both synchronous and asynchronous operation modes
|
||||||
|
- STDIO transport layer implementation
|
||||||
|
- Flexible tool registration through Spring beans
|
||||||
|
- Change notification capabilities
|
||||||
|
|
||||||
|
## Project Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
src/
|
||||||
|
├── main/
|
||||||
|
│ ├── java/
|
||||||
|
│ │ └── org/springframework/ai/mcp/sample/server/
|
||||||
|
│ │ ├── McpServerApplication.java # Main application class with tool registration
|
||||||
|
│ │ └── WeatherService.java # Weather service implementation with MCP tools
|
||||||
|
│ └── resources/
|
||||||
|
│ └── application.properties # Server and transport configuration
|
||||||
|
└── test/
|
||||||
|
└── java/
|
||||||
|
└── org/springframework/ai/mcp/sample/client/
|
||||||
|
└── ClientStdio.java # Test client implementation
|
||||||
|
```
|
||||||
|
|
||||||
|
## Building and Running
|
||||||
|
|
||||||
|
The server uses STDIO transport mode and is typically started automatically by the client. You only need to build the server jar:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./mvnw clean install -DskipTests
|
||||||
|
```
|
||||||
|
|
||||||
|
## Tool Implementation
|
||||||
|
|
||||||
|
The project demonstrates how to implement and register MCP tools using Spring's dependency injection and auto-configuration:
|
||||||
|
|
||||||
|
```java
|
||||||
|
@Service
|
||||||
|
public class WeatherService {
|
||||||
|
|
||||||
|
@Tool(description = "Get weather forecast for a specific latitude/longitude")
|
||||||
|
public String getWeatherForecastByLocation(
|
||||||
|
double latitude, // Latitude coordinate
|
||||||
|
double longitude // Longitude coordinate
|
||||||
|
) {
|
||||||
|
// Implementation
|
||||||
|
}
|
||||||
|
|
||||||
|
@Tool(description = "Get weather alerts for a US state")
|
||||||
|
public String getAlerts(
|
||||||
|
String state // Two-letter US state code (e.g. CA, NY)
|
||||||
|
) {
|
||||||
|
// Implementation
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
public class McpServerApplication {
|
||||||
|
@Bean
|
||||||
|
public List<ToolCallback> weatherTools(WeatherService weatherService) {
|
||||||
|
return ToolCallbacks.from(weatherService);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The auto-configuration will automatically register these tools with the MCP server. You can have multiple beans producing lists of ToolCallbacks, and the auto-configuration will merge them.
|
||||||
|
|
||||||
|
## Available Tools
|
||||||
|
|
||||||
|
### 1. Weather Forecast Tool
|
||||||
|
```java
|
||||||
|
@Tool(description = "Get weather forecast for a specific latitude/longitude")
|
||||||
|
public String getWeatherForecastByLocation(
|
||||||
|
double latitude, // Latitude coordinate
|
||||||
|
double longitude // Longitude coordinate
|
||||||
|
) {
|
||||||
|
// Returns detailed forecast including:
|
||||||
|
// - Temperature and unit
|
||||||
|
// - Wind speed and direction
|
||||||
|
// - Detailed forecast description
|
||||||
|
}
|
||||||
|
|
||||||
|
// Example usage:
|
||||||
|
CallToolResult forecast = client.callTool(
|
||||||
|
new CallToolRequest("getWeatherForecastByLocation",
|
||||||
|
Map.of(
|
||||||
|
"latitude", 47.6062, // Seattle coordinates
|
||||||
|
"longitude", -122.3321
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Weather Alerts Tool
|
||||||
|
```java
|
||||||
|
@Tool(description = "Get weather alerts for a US state")
|
||||||
|
public String getAlerts(
|
||||||
|
String state // Two-letter US state code (e.g. CA, NY)
|
||||||
|
) {
|
||||||
|
// Returns active alerts including:
|
||||||
|
// - Event type
|
||||||
|
// - Affected area
|
||||||
|
// - Severity
|
||||||
|
// - Description
|
||||||
|
// - Safety instructions
|
||||||
|
}
|
||||||
|
|
||||||
|
// Example usage:
|
||||||
|
CallToolResult alerts = client.callTool(
|
||||||
|
new CallToolRequest("getAlerts",
|
||||||
|
Map.of("state", "NY")
|
||||||
|
)
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Client Integration
|
||||||
|
|
||||||
|
### Java Client Example
|
||||||
|
|
||||||
|
```java
|
||||||
|
// Create server parameters
|
||||||
|
ServerParameters stdioParams = ServerParameters.builder("java")
|
||||||
|
.args("-Dspring.ai.mcp.server.transport=STDIO",
|
||||||
|
"-Dspring.main.web-application-type=none",
|
||||||
|
"-Dlogging.pattern.console=",
|
||||||
|
"-jar",
|
||||||
|
"target/mcp-weather-stdio-server-0.0.1-SNAPSHOT.jar")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// Initialize transport and client
|
||||||
|
var transport = new StdioClientTransport(stdioParams);
|
||||||
|
var client = McpClient.sync(transport).build();
|
||||||
|
```
|
||||||
|
|
||||||
|
### Claude Desktop Integration
|
||||||
|
|
||||||
|
To integrate with Claude Desktop, add the following configuration to your Claude Desktop settings:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mcpServers": {
|
||||||
|
"spring-ai-mcp-weather": {
|
||||||
|
"command": "java",
|
||||||
|
"args": [
|
||||||
|
"-Dspring.ai.mcp.server.transport=STDIO",
|
||||||
|
"-Dspring.main.web-application-type=none",
|
||||||
|
"-Dlogging.pattern.console=",
|
||||||
|
"-jar",
|
||||||
|
"/absolute/path/to/mcp-weather-stdio-server-0.0.1-SNAPSHOT.jar"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Replace `/absolute/path/to/` with the actual path to your built jar file.
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
### Application Properties
|
||||||
|
|
||||||
|
All properties are prefixed with `spring.ai.mcp.server`
|
||||||
|
|
||||||
|
|
||||||
|
```properties
|
||||||
|
# Required STDIO Configuration
|
||||||
|
spring.main.web-application-type=none
|
||||||
|
spring.main.banner-mode=off
|
||||||
|
logging.pattern.console=
|
||||||
|
|
||||||
|
# Server Configuration
|
||||||
|
spring.ai.mcp.server.enabled=true
|
||||||
|
spring.ai.mcp.server.name=my-weather-server
|
||||||
|
spring.ai.mcp.server.version=0.0.1
|
||||||
|
# SYNC or ASYNC
|
||||||
|
spring.ai.mcp.server.type=SYNC
|
||||||
|
spring.ai.mcp.server.resource-change-notification=true
|
||||||
|
spring.ai.mcp.server.tool-change-notification=true
|
||||||
|
spring.ai.mcp.server.prompt-change-notification=true
|
||||||
|
|
||||||
|
# Optional file logging
|
||||||
|
logging.file.name=mcp-weather-stdio-server.log
|
||||||
|
```
|
||||||
|
|
||||||
|
### Key Configuration Notes
|
||||||
|
|
||||||
|
1. **STDIO Mode Requirements**:
|
||||||
|
- Disable web application type (`spring.main.web-application-type=none`)
|
||||||
|
- Disable Spring banner (`spring.main.banner-mode=off`)
|
||||||
|
- Clear console logging pattern (`logging.pattern.console=`)
|
||||||
|
|
||||||
|
2. **Server Type**:
|
||||||
|
- `SYNC` (default): Uses `McpSyncServer` for straightforward request-response patterns
|
||||||
|
- `ASYNC`: Uses `McpAsyncServer` for non-blocking operations with Project Reactor support
|
||||||
|
|
||||||
|
## Additional Resources
|
||||||
|
|
||||||
|
- [Spring AI Documentation](https://docs.spring.io/spring-ai/reference/)
|
||||||
|
- [Model Context Protocol Specification](https://modelcontextprotocol.github.io/specification/)
|
||||||
|
- [Spring Boot Auto-configuration](https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.developing-auto-configuration)
|
||||||
|
|
||||||
@@ -12,15 +12,12 @@
|
|||||||
|
|
||||||
<groupId>com.example</groupId>
|
<groupId>com.example</groupId>
|
||||||
|
|
||||||
<artifactId>mcp-weather-server-quickstart</artifactId>
|
<artifactId>mcp-weather-stdio-server</artifactId>
|
||||||
<version>0.0.1-SNAPSHOT</version>
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
|
||||||
<name>Spring AI MCP Weather Sample</name>
|
<name>Spring AI MCP Weather STDIO server</name>
|
||||||
<description>Sample Spring Boot application demonstrating MCP client and server usage</description>
|
<description>Sample Spring Boot application demonstrating MCP stdio server usage</description>
|
||||||
|
|
||||||
<properties>
|
|
||||||
<mcp.version>0.7.0-SNAPSHOT</mcp.version>
|
|
||||||
</properties>
|
|
||||||
|
|
||||||
<dependencyManagement>
|
<dependencyManagement>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
@@ -31,34 +28,19 @@
|
|||||||
<type>pom</type>
|
<type>pom</type>
|
||||||
<scope>import</scope>
|
<scope>import</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.modelcontextprotocol.sdk</groupId>
|
|
||||||
<artifactId>mcp-bom</artifactId>
|
|
||||||
<version>${mcp.version}</version>
|
|
||||||
<type>pom</type>
|
|
||||||
<scope>import</scope>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</dependencyManagement>
|
</dependencyManagement>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.ai</groupId>
|
<groupId>org.springframework.ai</groupId>
|
||||||
<artifactId>spring-ai-mcp-spring-boot-starter</artifactId>
|
<artifactId>spring-ai-mcp-server-spring-boot-starter</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework</groupId>
|
<groupId>org.springframework</groupId>
|
||||||
<artifactId>spring-web</artifactId>
|
<artifactId>spring-web</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
@@ -66,27 +48,6 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<goals>
|
|
||||||
<goal>repackage</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<groupId>io.spring.javaformat</groupId>
|
|
||||||
<artifactId>spring-javaformat-maven-plugin</artifactId>
|
|
||||||
<version>0.0.43</version>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<phase>validate</phase>
|
|
||||||
<inherited>true</inherited>
|
|
||||||
<goals>
|
|
||||||
<goal>validate</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
@@ -10,5 +10,5 @@ spring.ai.mcp.server.enabled=true
|
|||||||
spring.ai.mcp.server.name=my-weather-server
|
spring.ai.mcp.server.name=my-weather-server
|
||||||
spring.ai.mcp.server.version=0.0.1
|
spring.ai.mcp.server.version=0.0.1
|
||||||
|
|
||||||
logging.file.name=./model-context-protocol/mcp-weather-server-quickstart/target/mcp.weather-quickstart.log
|
logging.file.name=./model-context-protocol/weather/mcp-weather-stdio-server/mcp-weather-server-quickstart/target/mcp-weather-stdio-server.log
|
||||||
|
|
||||||
@@ -15,7 +15,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.ai.mcp.sample.client;
|
package org.springframework.ai.mcp.sample.client;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import io.modelcontextprotocol.client.McpClient;
|
import io.modelcontextprotocol.client.McpClient;
|
||||||
@@ -39,7 +38,7 @@ public class ClientStdio {
|
|||||||
|
|
||||||
var stdioParams = ServerParameters.builder("java")
|
var stdioParams = ServerParameters.builder("java")
|
||||||
.args("-jar",
|
.args("-jar",
|
||||||
"model-context-protocol/mcp-weather-server-quickstart/target/mcp-weather-server-quickstart-0.0.1-SNAPSHOT.jar")
|
"model-context-protocol/weather/starter-stdio-server/target/mcp-weather-stdio-server-0.0.1-SNAPSHOT.jar")
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
var transport = new StdioClientTransport(stdioParams);
|
var transport = new StdioClientTransport(stdioParams);
|
||||||
213
model-context-protocol/weather/starter-webflux-server/README.md
Normal file
213
model-context-protocol/weather/starter-webflux-server/README.md
Normal file
@@ -0,0 +1,213 @@
|
|||||||
|
# Spring AI MCP Weather Server Sample with WebFlux Starter
|
||||||
|
|
||||||
|
This sample project demonstrates how to create an MCP server using the Spring AI MCP Server Boot Starter with WebFlux transport. It implements a weather service that exposes tools for retrieving weather information using the National Weather Service API.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
The sample showcases:
|
||||||
|
- Integration with `spring-ai-mcp-server-webflux-spring-boot-starter`
|
||||||
|
- Support for both SSE (Server-Sent Events) and STDIO transports
|
||||||
|
- Automatic tool registration using Spring AI's `@Tool` annotation
|
||||||
|
- Two weather-related tools:
|
||||||
|
- Get weather forecast by location (latitude/longitude)
|
||||||
|
- Get weather alerts by US state
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
|
||||||
|
The project uses the Spring AI MCP Server WebFlux Boot Starter:
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.ai</groupId>
|
||||||
|
<artifactId>spring-ai-mcp-server-webflux-spring-boot-starter</artifactId>
|
||||||
|
</dependency>
|
||||||
|
```
|
||||||
|
|
||||||
|
This starter provides:
|
||||||
|
- Reactive transport using Spring WebFlux (`WebFluxSseServerTransport`)
|
||||||
|
- Automatically configured reactive SSE endpoints
|
||||||
|
- Optional STDIO transport
|
||||||
|
- Included `spring-boot-starter-webflux` and `mcp-spring-webflux` dependencies
|
||||||
|
|
||||||
|
## Building the Project
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./mvnw clean install -DskipTests
|
||||||
|
```
|
||||||
|
|
||||||
|
## Running the Server
|
||||||
|
|
||||||
|
The server supports two transport modes:
|
||||||
|
|
||||||
|
### WebFlux SSE Mode (Default)
|
||||||
|
```bash
|
||||||
|
java -jar target/mcp-weather-starter-webflux-server-0.0.1-SNAPSHOT.jar
|
||||||
|
```
|
||||||
|
|
||||||
|
### STDIO Mode
|
||||||
|
Enable STDIO transport by setting the appropriate properties:
|
||||||
|
```bash
|
||||||
|
java -Dspring.ai.mcp.server.stdio=true -Dspring.main.web-application-type=none -jar target/mcp-weather-starter-webflux-server-0.0.1-SNAPSHOT.jar
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
The server can be configured through `application.properties`:
|
||||||
|
|
||||||
|
```properties
|
||||||
|
# Server identification
|
||||||
|
spring.ai.mcp.server.name=my-weather-server
|
||||||
|
spring.ai.mcp.server.version=0.0.1
|
||||||
|
|
||||||
|
# Server type (SYNC/ASYNC)
|
||||||
|
spring.ai.mcp.server.type=SYNC
|
||||||
|
|
||||||
|
# Transport configuration
|
||||||
|
spring.ai.mcp.server.stdio=false
|
||||||
|
spring.ai.mcp.server.sse-message-endpoint=/mcp/message
|
||||||
|
|
||||||
|
# Change notifications
|
||||||
|
spring.ai.mcp.server.resource-change-notification=true
|
||||||
|
spring.ai.mcp.server.tool-change-notification=true
|
||||||
|
spring.ai.mcp.server.prompt-change-notification=true
|
||||||
|
|
||||||
|
# Logging (required for STDIO transport)
|
||||||
|
spring.main.banner-mode=off
|
||||||
|
logging.file.name=./target/starter-webflux-server.log
|
||||||
|
```
|
||||||
|
|
||||||
|
## Sample Clients
|
||||||
|
|
||||||
|
### WebFlux SSE Client
|
||||||
|
```java
|
||||||
|
var transport = new WebFluxSseClientTransport(WebClient.builder().baseUrl("http://localhost:8080"));
|
||||||
|
var client = McpClient.sync(transport).build();
|
||||||
|
```
|
||||||
|
|
||||||
|
### STDIO Client
|
||||||
|
```java
|
||||||
|
var stdioParams = ServerParameters.builder("java")
|
||||||
|
.args("-Dspring.ai.mcp.server.stdio=true",
|
||||||
|
"-Dspring.main.web-application-type=none",
|
||||||
|
"-Dspring.main.banner-mode=off",
|
||||||
|
"-Dlogging.pattern.console=",
|
||||||
|
"-jar",
|
||||||
|
"target/mcp-weather-starter-webflux-server-0.0.1-SNAPSHOT.jar")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
var transport = new StdioClientTransport(stdioParams);
|
||||||
|
var client = McpClient.sync(transport).build();
|
||||||
|
```
|
||||||
|
|
||||||
|
### Claude Desktop Configuration
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mcpServers": {
|
||||||
|
"spring-ai-mcp-weather": {
|
||||||
|
"command": "java",
|
||||||
|
"args": [
|
||||||
|
"-Dspring.ai.mcp.server.stdio=true",
|
||||||
|
"-Dspring.main.web-application-type=none",
|
||||||
|
"-Dspring.main.banner-mode=off",
|
||||||
|
"-Dlogging.pattern.console=",
|
||||||
|
"-jar",
|
||||||
|
"<YOUR ABSOLUTE PATH TO>/mcp-weather-starter-webflux-server-0.0.1-SNAPSHOT.jar"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Available Tools
|
||||||
|
|
||||||
|
### Weather Forecast Tool
|
||||||
|
- Name: `getWeatherForecastByLocation`
|
||||||
|
- Description: Get weather forecast for a specific latitude/longitude
|
||||||
|
- Parameters:
|
||||||
|
- `latitude`: double - Latitude coordinate
|
||||||
|
- `longitude`: double - Longitude coordinate
|
||||||
|
- Example:
|
||||||
|
```java
|
||||||
|
CallToolResult forecastResult = client.callTool(new CallToolRequest("getWeatherForecastByLocation",
|
||||||
|
Map.of("latitude", 47.6062, "longitude", -122.3321)));
|
||||||
|
```
|
||||||
|
|
||||||
|
### Weather Alerts Tool
|
||||||
|
- Name: `getAlerts`
|
||||||
|
- Description: Get weather alerts for a US state
|
||||||
|
- Parameters:
|
||||||
|
- `state`: String - Two-letter US state code (e.g. CA, NY)
|
||||||
|
- Example:
|
||||||
|
```java
|
||||||
|
CallToolResult alertResult = client.callTool(new CallToolRequest("getAlerts",
|
||||||
|
Map.of("state", "NY")));
|
||||||
|
```
|
||||||
|
|
||||||
|
## Server Implementation
|
||||||
|
|
||||||
|
The server uses Spring Boot and Spring AI's tool annotations for automatic tool registration:
|
||||||
|
|
||||||
|
```java
|
||||||
|
@SpringBootApplication
|
||||||
|
public class McpServerApplication {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(McpServerApplication.class, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public List<ToolCallback> weatherTools(WeatherService weatherService) {
|
||||||
|
return List.of(ToolCallbacks.from(weatherService));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `WeatherService` implements the weather tools using the `@Tool` annotation:
|
||||||
|
|
||||||
|
```java
|
||||||
|
@Service
|
||||||
|
public class WeatherService {
|
||||||
|
@Tool(description = "Get weather forecast for a specific latitude/longitude")
|
||||||
|
public String getWeatherForecastByLocation(double latitude, double longitude) {
|
||||||
|
// Implementation using weather.gov API
|
||||||
|
}
|
||||||
|
|
||||||
|
@Tool(description = "Get weather alerts for a US state. Input is Two-letter US state code (e.g. CA, NY)")
|
||||||
|
public String getAlerts(String state) {
|
||||||
|
// Implementation using weather.gov API
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Client Usage Example
|
||||||
|
|
||||||
|
```java
|
||||||
|
// Initialize client
|
||||||
|
client.initialize();
|
||||||
|
|
||||||
|
// Test connection
|
||||||
|
client.ping();
|
||||||
|
|
||||||
|
// List available tools
|
||||||
|
ListToolsResult tools = client.listTools();
|
||||||
|
System.out.println("Available tools: " + tools);
|
||||||
|
|
||||||
|
// Get weather forecast for Seattle
|
||||||
|
CallToolResult weatherForcastResult = client.callTool(new CallToolRequest("getWeatherForecastByLocation",
|
||||||
|
Map.of("latitude", 47.6062, "longitude", -122.3321)));
|
||||||
|
System.out.println("Weather Forecast: " + weatherForcastResult);
|
||||||
|
|
||||||
|
// Get weather alerts for New York
|
||||||
|
CallToolResult alertResult = client.callTool(new CallToolRequest("getAlerts", Map.of("state", "NY")));
|
||||||
|
System.out.println("Alert Response = " + alertResult);
|
||||||
|
|
||||||
|
// Close client
|
||||||
|
client.closeGracefully();
|
||||||
|
```
|
||||||
|
|
||||||
|
## Additional Resources
|
||||||
|
|
||||||
|
* [Spring AI Documentation](https://docs.spring.io/spring-ai/reference/)
|
||||||
|
* [Model Context Protocol Specification](https://modelcontextprotocol.github.io/specification/)
|
||||||
|
* [Spring Boot Auto-configuration](https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.developing-auto-configuration)
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user