2
2
3
3
import com .fasterxml .jackson .databind .ObjectMapper ;
4
4
import 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 ;
13
13
import io .modelcontextprotocol .server .McpSyncServer ;
14
14
import io .modelcontextprotocol .server .transport .HttpServletSseServerTransportProvider ;
15
15
import 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 ;
20
17
import 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 ;
31
18
32
19
public class McpServers {
33
20
34
- private static final Logger logger = LoggerFactory .getLogger (McpServers .class );
35
-
36
21
private static final McpServers INSTANCE = new McpServers ();
37
22
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
-
45
23
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper ();
46
24
47
- private static final String OBJECT_TYPE_NAME = Object .class .getSimpleName ().toLowerCase ();
48
-
49
25
private static final String DEFAULT_MESSAGE_ENDPOINT = "/message" ;
50
26
51
27
private static final String DEFAULT_SSE_ENDPOINT = "/sse" ;
@@ -72,150 +48,64 @@ private static String determineBasePackage(McpComponentScan scan, Class<?> appli
72
48
return applicationMainClass .getPackageName ();
73
49
}
74
50
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
+ }
80
58
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" );
83
62
}
84
63
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 ();
87
73
}
88
74
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 () );
91
77
}
92
78
79
+ @ Deprecated (since = "0.2.0" )
93
80
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 )
101
84
.build ();
102
85
103
- registerResources (server );
104
- registerTools (server );
105
-
106
- startHttpServer (server , transport , port );
86
+ startSyncSseServer (serverInfo );
107
87
}
108
88
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 ();
170
96
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 );
195
98
}
196
99
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 ();
217
107
218
- return new McpSchema . JsonSchema ( OBJECT_TYPE_NAME , properties , required , false );
108
+ startSyncSseServer ( serverInfo );
219
109
}
220
110
221
111
}
0 commit comments