22
33import com .fasterxml .jackson .databind .ObjectMapper ;
44import com .taobao .arthas .mcp .server .protocol .config .McpServerProperties ;
5+ import com .taobao .arthas .mcp .server .protocol .config .McpServerProperties .ServerProtocol ;
56import com .taobao .arthas .mcp .server .protocol .server .McpNettyServer ;
67import com .taobao .arthas .mcp .server .protocol .server .McpServer ;
78import com .taobao .arthas .mcp .server .protocol .server .McpStatelessNettyServer ;
@@ -35,6 +36,7 @@ public class ArthasMcpServer {
3536 private McpStatelessNettyServer statelessServer ;
3637
3738 private final String mcpEndpoint ;
39+ private final ServerProtocol protocol ;
3840
3941 private final CommandExecutor commandExecutor ;
4042
@@ -46,9 +48,19 @@ public class ArthasMcpServer {
4648
4749 public static final String DEFAULT_MCP_ENDPOINT = "/mcp" ;
4850
49- public ArthasMcpServer (String mcpEndpoint , CommandExecutor commandExecutor ) {
51+ public ArthasMcpServer (String mcpEndpoint , CommandExecutor commandExecutor , String protocol ) {
5052 this .mcpEndpoint = mcpEndpoint != null ? mcpEndpoint : DEFAULT_MCP_ENDPOINT ;
5153 this .commandExecutor = commandExecutor ;
54+
55+ ServerProtocol resolvedProtocol = ServerProtocol .STATELESS ;
56+ if (protocol != null && !protocol .trim ().isEmpty ()) {
57+ try {
58+ resolvedProtocol = ServerProtocol .valueOf (protocol .toUpperCase ());
59+ } catch (IllegalArgumentException e ) {
60+ logger .warn ("Invalid MCP protocol: {}. Using default: STATELESS" , protocol );
61+ }
62+ }
63+ this .protocol = resolvedProtocol ;
5264 }
5365
5466 public McpHttpRequestHandler getMcpRequestHandler () {
@@ -68,6 +80,7 @@ public void start() {
6880 .resourceChangeNotification (true )
6981 .promptChangeNotification (true )
7082 .objectMapper (JsonParser .getObjectMapper ())
83+ .protocol (this .protocol )
7184 .build ();
7285
7386 ToolCallbackProvider toolCallbackProvider = new DefaultToolCallbackProvider ();
@@ -76,50 +89,51 @@ public void start() {
7689 .filter (Objects ::nonNull )
7790 .collect (Collectors .toList ());
7891
79- // Create transport for both streamable and stateless servers
80- McpStreamableServerTransportProvider transportProvider = createStreamableHttpTransportProvider (properties );
81- streamableHandler = transportProvider .getMcpRequestHandler ();
82-
83- NettyStatelessServerTransport statelessTransport = createStatelessHttpTransport (properties );
84- statelessHandler = statelessTransport .getMcpRequestHandler ();
85-
8692 unifiedMcpHandler = McpHttpRequestHandler .builder ()
8793 .mcpEndpoint (properties .getMcpEndpoint ())
8894 .objectMapper (properties .getObjectMapper ())
89- .tools ( Arrays . asList ( callbacks ))
95+ .protocol ( properties . getProtocol ( ))
9096 .build ();
91- unifiedMcpHandler .setStreamableHandler (streamableHandler );
92- unifiedMcpHandler .setStatelessHandler (statelessHandler );
93-
94- // Set up unified MCP handler for both streamable and stateless servers
95- McpServer .StreamableServerNettySpecification streamableServerNettySpecification = McpServer .netty (transportProvider )
96- .serverInfo (new Implementation (properties .getName (), properties .getVersion ()))
97- .capabilities (buildServerCapabilities (properties ))
98- .instructions (properties .getInstructions ())
99- .requestTimeout (properties .getRequestTimeout ())
100- .commandExecutor (commandExecutor )
101- .objectMapper (properties .getObjectMapper () != null ? properties .getObjectMapper () : JsonParser .getObjectMapper ());
102-
103- // Set up unified MCP handler for both streamable and stateless servers
104- McpServer .StatelessServerNettySpecification statelessServerNettySpecification = McpServer .netty (statelessTransport )
105- .serverInfo (new Implementation (properties .getName (), properties .getVersion ()))
106- .capabilities (buildServerCapabilities (properties ))
107- .instructions (properties .getInstructions ())
108- .requestTimeout (properties .getRequestTimeout ())
109- .commandExecutor (commandExecutor )
110- .objectMapper (properties .getObjectMapper () != null ? properties .getObjectMapper () : JsonParser .getObjectMapper ());
111-
112- streamableServerNettySpecification .tools (
113- McpToolUtils .toStreamableToolSpecifications (providerToolCallbacks ));
114- statelessServerNettySpecification .tools (
115- McpToolUtils .toStatelessToolSpecifications (providerToolCallbacks ));
116-
117- streamableServer = streamableServerNettySpecification .build ();
118- statelessServer = statelessServerNettySpecification .build ();
119-
97+
98+ if (properties .getProtocol () == ServerProtocol .STREAMABLE ) {
99+ McpStreamableServerTransportProvider transportProvider = createStreamableHttpTransportProvider (properties );
100+ streamableHandler = transportProvider .getMcpRequestHandler ();
101+ unifiedMcpHandler .setStreamableHandler (streamableHandler );
102+
103+ McpServer .StreamableServerNettySpecification streamableServerNettySpecification = McpServer .netty (transportProvider )
104+ .serverInfo (new Implementation (properties .getName (), properties .getVersion ()))
105+ .capabilities (buildServerCapabilities (properties ))
106+ .instructions (properties .getInstructions ())
107+ .requestTimeout (properties .getRequestTimeout ())
108+ .commandExecutor (commandExecutor )
109+ .objectMapper (properties .getObjectMapper () != null ? properties .getObjectMapper () : JsonParser .getObjectMapper ());
110+
111+ streamableServerNettySpecification .tools (
112+ McpToolUtils .toStreamableToolSpecifications (providerToolCallbacks ));
113+
114+ streamableServer = streamableServerNettySpecification .build ();
115+ } else {
116+ NettyStatelessServerTransport statelessTransport = createStatelessHttpTransport (properties );
117+ statelessHandler = statelessTransport .getMcpRequestHandler ();
118+ unifiedMcpHandler .setStatelessHandler (statelessHandler );
119+
120+ McpServer .StatelessServerNettySpecification statelessServerNettySpecification = McpServer .netty (statelessTransport )
121+ .serverInfo (new Implementation (properties .getName (), properties .getVersion ()))
122+ .capabilities (buildServerCapabilities (properties ))
123+ .instructions (properties .getInstructions ())
124+ .requestTimeout (properties .getRequestTimeout ())
125+ .commandExecutor (commandExecutor )
126+ .objectMapper (properties .getObjectMapper () != null ? properties .getObjectMapper () : JsonParser .getObjectMapper ());
127+
128+ statelessServerNettySpecification .tools (
129+ McpToolUtils .toStatelessToolSpecifications (providerToolCallbacks ));
130+
131+ statelessServer = statelessServerNettySpecification .build ();
132+ }
133+
120134 logger .info ("Arthas MCP server started successfully" );
121135 logger .info ("- MCP Endpoint: {}" , properties .getMcpEndpoint ());
122- logger .info ("- Transport modes: Streamable + Stateless" );
136+ logger .info ("- Transport mode: {}" , properties . getProtocol () );
123137 logger .info ("- Available tools: {}" , providerToolCallbacks .size ());
124138 logger .info ("- Server ready to accept connections" );
125139 } catch (Exception e ) {
0 commit comments