22
33import com .fasterxml .jackson .databind .ObjectMapper ;
44import com .github .codeboyzhou .mcp .declarative .annotation .McpComponentScan ;
5- import com .github .codeboyzhou .mcp .declarative .annotation . McpResource ;
6- import com .github .codeboyzhou .mcp .declarative .annotation . McpResources ;
7- import com .github .codeboyzhou .mcp .declarative .annotation . McpTool ;
8- import com .github .codeboyzhou .mcp .declarative .annotation . McpToolParam ;
9- import com .github .codeboyzhou .mcp .declarative .annotation . McpTools ;
10- import com .github .codeboyzhou .mcp .declarative .util . ReflectionHelper ;
11- import io . modelcontextprotocol . server .McpServer ;
12- import io . modelcontextprotocol . server .McpServerFeatures ;
5+ import com .github .codeboyzhou .mcp .declarative .listener . DefaultMcpSyncHttpServerStatusListener ;
6+ import com .github .codeboyzhou .mcp .declarative .listener . McpHttpServerStatusListener ;
7+ import com .github .codeboyzhou .mcp .declarative .server . McpHttpServer ;
8+ import com .github .codeboyzhou .mcp .declarative .server . McpServerComponentRegisters ;
9+ import com .github .codeboyzhou .mcp .declarative .server . McpServerFactory ;
10+ import com .github .codeboyzhou .mcp .declarative .server . McpServerInfo ;
11+ import com . github . codeboyzhou . mcp . declarative . server .McpSseServerInfo ;
12+ import com . github . codeboyzhou . mcp . declarative . server .McpSyncServerFactory ;
1313import io .modelcontextprotocol .server .McpSyncServer ;
1414import io .modelcontextprotocol .server .transport .HttpServletSseServerTransportProvider ;
1515import io .modelcontextprotocol .server .transport .StdioServerTransportProvider ;
16- import io .modelcontextprotocol .spec .McpSchema ;
17- import org .eclipse .jetty .ee10 .servlet .ServletContextHandler ;
18- import org .eclipse .jetty .ee10 .servlet .ServletHolder ;
19- import org .eclipse .jetty .server .Server ;
16+ import io .modelcontextprotocol .spec .McpServerTransportProvider ;
2017import org .reflections .Reflections ;
21- import org .slf4j .Logger ;
22- import org .slf4j .LoggerFactory ;
23-
24- import java .lang .reflect .Method ;
25- import java .lang .reflect .Parameter ;
26- import java .util .ArrayList ;
27- import java .util .HashMap ;
28- import java .util .List ;
29- import java .util .Map ;
30- import java .util .Set ;
3118
3219public class McpServers {
3320
34- private static final Logger logger = LoggerFactory .getLogger (McpServers .class );
35-
3621 private static final McpServers INSTANCE = new McpServers ();
3722
38- private static final McpSchema .ServerCapabilities DEFAULT_SERVER_CAPABILITIES = McpSchema .ServerCapabilities
39- .builder ()
40- .resources (true , true )
41- .prompts (true )
42- .tools (true )
43- .build ();
44-
4523 private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper ();
4624
47- private static final String OBJECT_TYPE_NAME = Object .class .getSimpleName ().toLowerCase ();
48-
4925 private static final String DEFAULT_MESSAGE_ENDPOINT = "/message" ;
5026
5127 private static final String DEFAULT_SSE_ENDPOINT = "/sse" ;
@@ -72,150 +48,64 @@ private static String determineBasePackage(McpComponentScan scan, Class<?> appli
7248 return applicationMainClass .getPackageName ();
7349 }
7450
75- public void startSyncStdioServer (String name , String version ) {
76- McpSyncServer server = McpServer .sync (new StdioServerTransportProvider ())
77- .capabilities (DEFAULT_SERVER_CAPABILITIES )
78- .serverInfo (name , version )
79- .build ();
51+ public void startSyncStdioServer (String name , String version , String instructions ) {
52+ McpServerFactory <McpSyncServer > factory = new McpSyncServerFactory ();
53+ McpServerInfo serverInfo = McpServerInfo .builder ().name (name ).version (version ).instructions (instructions ).build ();
54+ McpServerTransportProvider transportProvider = new StdioServerTransportProvider ();
55+ McpSyncServer server = factory .create (serverInfo , transportProvider );
56+ McpServerComponentRegisters .registerAllTo (server , reflections );
57+ }
8058
81- registerResources (server );
82- registerTools (server );
59+ @ Deprecated (since = "0.2.0" )
60+ public void startSyncStdioServer (String name , String version ) {
61+ startSyncStdioServer (name , version , "You are using a deprecated API with default server instructions" );
8362 }
8463
85- public void startSyncSseServer (String name , String version ) {
86- startSyncSseServer (name , version , DEFAULT_MESSAGE_ENDPOINT , DEFAULT_SSE_ENDPOINT , DEFAULT_HTTP_SERVER_PORT );
64+ public void startSyncSseServer (McpSseServerInfo serverInfo , McpHttpServerStatusListener <McpSyncServer > listener ) {
65+ McpServerFactory <McpSyncServer > factory = new McpSyncServerFactory ();
66+ HttpServletSseServerTransportProvider transportProvider = new HttpServletSseServerTransportProvider (
67+ OBJECT_MAPPER , serverInfo .baseUrl (), serverInfo .messageEndpoint (), serverInfo .sseEndpoint ()
68+ );
69+ McpSyncServer server = factory .create (serverInfo , transportProvider );
70+ McpServerComponentRegisters .registerAllTo (server , reflections );
71+ McpHttpServer <McpSyncServer > httpServer = new McpHttpServer <>();
72+ httpServer .with (transportProvider ).with (serverInfo ).with (listener ).attach (server ).start ();
8773 }
8874
89- public void startSyncSseServer (String name , String version , int port ) {
90- startSyncSseServer (name , version , DEFAULT_MESSAGE_ENDPOINT , DEFAULT_SSE_ENDPOINT , port );
75+ public void startSyncSseServer (McpSseServerInfo serverInfo ) {
76+ startSyncSseServer (serverInfo , new DefaultMcpSyncHttpServerStatusListener () );
9177 }
9278
79+ @ Deprecated (since = "0.2.0" )
9380 public void startSyncSseServer (String name , String version , String messageEndpoint , String sseEndpoint , int port ) {
94- HttpServletSseServerTransportProvider transport = new HttpServletSseServerTransportProvider (
95- OBJECT_MAPPER , messageEndpoint , sseEndpoint
96- );
97-
98- McpSyncServer server = McpServer .sync (transport )
99- .capabilities (DEFAULT_SERVER_CAPABILITIES )
100- .serverInfo (name , version )
81+ McpSseServerInfo serverInfo = McpSseServerInfo .builder ().name (name ).version (version )
82+ .instructions ("You are using a deprecated API with default server instructions" )
83+ .baseUrl ("" ).messageEndpoint (messageEndpoint ).sseEndpoint (sseEndpoint ).port (port )
10184 .build ();
10285
103- registerResources (server );
104- registerTools (server );
105-
106- startHttpServer (server , transport , port );
86+ startSyncSseServer (serverInfo );
10787 }
10888
109- private void startHttpServer (McpSyncServer server , HttpServletSseServerTransportProvider transport , int port ) {
110- ServletContextHandler servletContextHandler = new ServletContextHandler (ServletContextHandler .SESSIONS );
111- servletContextHandler .setContextPath ("/" );
112-
113- ServletHolder servletHolder = new ServletHolder (transport );
114- servletContextHandler .addServlet (servletHolder , "/*" );
115-
116- Server httpserver = new Server (port );
117- httpserver .setHandler (servletContextHandler );
118-
119- try {
120- httpserver .start ();
121- logger .info ("Jetty-based HTTP server started on http://127.0.0.1:{}" , port );
122-
123- Runtime .getRuntime ().addShutdownHook (new Thread (() -> {
124- try {
125- logger .info ("Shutting down HTTP server" );
126- httpserver .stop ();
127- server .close ();
128- } catch (Exception e ) {
129- logger .error ("Error stopping HTTP server" , e );
130- }
131- }));
132-
133- // Wait for the HTTP server to stop
134- httpserver .join ();
135- } catch (Exception e ) {
136- logger .error ("Error starting HTTP server on http://127.0.0.1:{}" , port , e );
137- server .close ();
138- }
139- }
140-
141- private void registerResources (McpSyncServer server ) {
142- Set <Class <?>> resourceClasses = reflections .getTypesAnnotatedWith (McpResources .class );
143- for (Class <?> resourceClass : resourceClasses ) {
144- Set <Method > methods = ReflectionHelper .getMethodsAnnotatedWith (resourceClass , McpResource .class );
145- for (Method method : methods ) {
146- McpResource resourceMethod = method .getAnnotation (McpResource .class );
147- McpSchema .Resource resource = new McpSchema .Resource (
148- resourceMethod .uri (),
149- resourceMethod .name ().isBlank () ? method .getName () : resourceMethod .name (),
150- resourceMethod .description (),
151- resourceMethod .mimeType (),
152- new McpSchema .Annotations (List .of (resourceMethod .roles ()), resourceMethod .priority ())
153- );
154- server .addResource (new McpServerFeatures .SyncResourceSpecification (resource , (exchange , request ) -> {
155- Object result ;
156- try {
157- result = ReflectionHelper .invokeMethod (resourceClass , method );
158- } catch (Throwable e ) {
159- logger .error ("Error invoking resource method" , e );
160- result = e + ": " + e .getMessage ();
161- }
162- McpSchema .ResourceContents contents = new McpSchema .TextResourceContents (
163- resource .uri (), resource .mimeType (), result .toString ()
164- );
165- return new McpSchema .ReadResourceResult (List .of (contents ));
166- }));
167- }
168- }
169- }
89+ @ Deprecated (since = "0.2.0" )
90+ public void startSyncSseServer (String name , String version , int port ) {
91+ McpSseServerInfo serverInfo = McpSseServerInfo .builder ().name (name ).version (version )
92+ .instructions ("You are using a deprecated API with default server instructions" )
93+ .baseUrl ("" ).messageEndpoint (DEFAULT_MESSAGE_ENDPOINT ).sseEndpoint (DEFAULT_SSE_ENDPOINT )
94+ .port (port )
95+ .build ();
17096
171- private void registerTools (McpSyncServer server ) {
172- Set <Class <?>> toolClasses = reflections .getTypesAnnotatedWith (McpTools .class );
173- for (Class <?> toolClass : toolClasses ) {
174- Set <Method > methods = ReflectionHelper .getMethodsAnnotatedWith (toolClass , McpTool .class );
175- for (Method method : methods ) {
176- McpTool toolMethod = method .getAnnotation (McpTool .class );
177- McpSchema .JsonSchema paramSchema = createJsonSchema (method );
178- final String toolName = toolMethod .name ().isBlank () ? method .getName () : toolMethod .name ();
179- McpSchema .Tool tool = new McpSchema .Tool (toolName , toolMethod .description (), paramSchema );
180- server .addTool (new McpServerFeatures .SyncToolSpecification (tool , (exchange , params ) -> {
181- Object result ;
182- boolean isError = false ;
183- try {
184- result = ReflectionHelper .invokeMethod (toolClass , method , paramSchema , params );
185- } catch (Throwable e ) {
186- logger .error ("Error invoking tool method" , e );
187- result = e + ": " + e .getMessage ();
188- isError = true ;
189- }
190- McpSchema .Content content = new McpSchema .TextContent (result .toString ());
191- return new McpSchema .CallToolResult (List .of (content ), isError );
192- }));
193- }
194- }
97+ startSyncSseServer (serverInfo );
19598 }
19699
197- private McpSchema .JsonSchema createJsonSchema (Method method ) {
198- Map <String , Object > properties = new HashMap <>();
199- List <String > required = new ArrayList <>();
200-
201- Set <Parameter > parameters = ReflectionHelper .getParametersAnnotatedWith (method , McpToolParam .class );
202- for (Parameter parameter : parameters ) {
203- McpToolParam toolParam = parameter .getAnnotation (McpToolParam .class );
204- final String parameterName = toolParam .name ();
205- final String parameterType = parameter .getType ().getName ().toLowerCase ();
206-
207- Map <String , String > parameterProperties = Map .of (
208- "type" , parameterType ,
209- "description" , toolParam .description ()
210- );
211- properties .put (parameterName , parameterProperties );
212-
213- if (toolParam .required ()) {
214- required .add (parameterName );
215- }
216- }
100+ @ Deprecated (since = "0.2.0" )
101+ public void startSyncSseServer (String name , String version ) {
102+ McpSseServerInfo serverInfo = McpSseServerInfo .builder ().name (name ).version (version )
103+ .instructions ("You are using a deprecated API with default server instructions" )
104+ .baseUrl ("" ).messageEndpoint (DEFAULT_MESSAGE_ENDPOINT ).sseEndpoint (DEFAULT_SSE_ENDPOINT )
105+ .port (DEFAULT_HTTP_SERVER_PORT )
106+ .build ();
217107
218- return new McpSchema . JsonSchema ( OBJECT_TYPE_NAME , properties , required , false );
108+ startSyncSseServer ( serverInfo );
219109 }
220110
221111}
0 commit comments