Skip to content

Commit cc1be9c

Browse files
authored
[FEL] MCP SSE server implemented with MCP SDK (#380)
* 添加McpSseServerConfig * 添加FitMcpSseServerTransportProvider * 更新bean按名称注入 * 修改DefaultMcpServer * 修改日志格式 * 修改注释 * 所有添加this * 修改注释 * 更新readme * 修改notnull检查 * keepAliveInterval修改为可配置 * 抽取FitMcpServerTransportProvider基类 * 重构DefaultMcpServer * 优化异常抛出逻辑 * 添加工具仓库注册逻辑 * 修改注册表工具增删捕获异常 * 更新readme * 修改配置为false
1 parent f108df0 commit cc1be9c

File tree

12 files changed

+1384
-679
lines changed

12 files changed

+1384
-679
lines changed

framework/fel/java/plugins/tool-mcp-server/README.md

Lines changed: 311 additions & 200 deletions
Large diffs are not rendered by default.

framework/fel/java/plugins/tool-mcp-server/src/main/java/modelengine/fel/tool/mcp/server/support/DefaultMcpStreamableServer.java renamed to framework/fel/java/plugins/tool-mcp-server/src/main/java/modelengine/fel/tool/mcp/server/FitMcpServer.java

Lines changed: 26 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* Licensed under the MIT License. See License.txt in the project root for license information.
55
*--------------------------------------------------------------------------------------------*/
66

7-
package modelengine.fel.tool.mcp.server.support;
7+
package modelengine.fel.tool.mcp.server;
88

99
import static modelengine.fel.tool.info.schema.PluginSchema.TYPE;
1010
import static modelengine.fel.tool.info.schema.ToolsSchema.PROPERTIES;
@@ -15,56 +15,53 @@
1515
import io.modelcontextprotocol.server.McpSyncServer;
1616
import io.modelcontextprotocol.spec.McpSchema;
1717
import modelengine.fel.tool.mcp.entity.Tool;
18-
import modelengine.fel.tool.mcp.server.McpServer;
1918
import modelengine.fel.tool.service.ToolChangedObserver;
19+
import modelengine.fel.tool.service.ToolChangedObserverRegistry;
2020
import modelengine.fel.tool.service.ToolExecuteService;
21-
import modelengine.fitframework.annotation.Component;
21+
import modelengine.fitframework.ioc.annotation.PreDestroy;
2222
import modelengine.fitframework.log.Logger;
2323
import modelengine.fitframework.util.MapUtils;
2424
import modelengine.fitframework.util.StringUtils;
2525

26-
import java.util.ArrayList;
2726
import java.util.HashMap;
2827
import java.util.List;
2928
import java.util.Map;
3029
import java.util.stream.Collectors;
3130

3231
/**
33-
* Mcp Server implementing interface {@link McpServer}, {@link ToolChangedObserver}
34-
* with MCP Server Bean {@link McpSyncServer}.
32+
* Mcp Server implementing interface {@link ToolChangedObserver}
33+
* with MCP Server {@link McpSyncServer} implemented with SDK.
3534
*
3635
* @author 季聿阶
3736
* @since 2025-05-15
3837
*/
39-
@Component
40-
public class DefaultMcpStreamableServer implements McpServer, ToolChangedObserver {
41-
private static final Logger log = Logger.get(DefaultMcpStreamableServer.class);
38+
public class FitMcpServer implements ToolChangedObserver {
39+
private static final Logger log = Logger.get(FitMcpServer.class);
4240
private final McpSyncServer mcpSyncServer;
43-
4441
private final ToolExecuteService toolExecuteService;
45-
private final List<ToolsChangedObserver> toolsChangedObservers = new ArrayList<>();
42+
private final ToolChangedObserverRegistry toolChangedObserverRegistry;
4643

4744
/**
48-
* Constructs a new instance of the DefaultMcpServer class.
45+
* Constructs a new instance of the FitMcpServer class.
4946
*
5047
* @param toolExecuteService The service used to execute tools when handling tool call requests.
51-
* @throws IllegalArgumentException If {@code toolExecuteService} is null.
48+
* @param mcpSyncServer The MCP sync server.
5249
*/
53-
public DefaultMcpStreamableServer(ToolExecuteService toolExecuteService, McpSyncServer mcpSyncServer) {
50+
public FitMcpServer(ToolExecuteService toolExecuteService, McpSyncServer mcpSyncServer,
51+
ToolChangedObserverRegistry toolChangedObserverRegistry) {
5452
this.toolExecuteService = notNull(toolExecuteService, "The tool execute service cannot be null.");
5553
this.mcpSyncServer = mcpSyncServer;
54+
this.toolChangedObserverRegistry = toolChangedObserverRegistry;
55+
this.toolChangedObserverRegistry.register(this);
5656
}
5757

58-
@Override
59-
public List<Tool> getTools() {
60-
return this.mcpSyncServer.listTools().stream().map(this::convertToFelTool).collect(Collectors.toList());
58+
@PreDestroy
59+
public void onDestroy() {
60+
this.toolChangedObserverRegistry.unregister(this);
6161
}
6262

63-
@Override
64-
public void registerToolsChangedObserver(ToolsChangedObserver observer) {
65-
if (observer != null) {
66-
this.toolsChangedObservers.add(observer);
67-
}
63+
public List<Tool> getTools() {
64+
return this.mcpSyncServer.listTools().stream().map(this::convertToFelTool).collect(Collectors.toList());
6865
}
6966

7067
@Override
@@ -88,10 +85,13 @@ public void onToolAdded(String name, String description, Map<String, Object> par
8885

8986
McpServerFeatures.SyncToolSpecification toolSpecification =
9087
createToolSpecification(name, description, parameters);
91-
92-
this.mcpSyncServer.addTool(toolSpecification);
88+
try {
89+
this.mcpSyncServer.addTool(toolSpecification);
90+
} catch (Exception e) {
91+
log.error("Failed to added tool to MCP server. [toolName={}, error={}]", name, e.getMessage());
92+
throw e;
93+
}
9394
log.info("Tool added to MCP server. [toolName={}, description={}, schema={}]", name, description, parameters);
94-
this.toolsChangedObservers.forEach(ToolsChangedObserver::onToolsChanged);
9595
}
9696

9797
@Override
@@ -102,22 +102,15 @@ public void onToolRemoved(String name) {
102102
}
103103
this.mcpSyncServer.removeTool(name);
104104
log.info("Tool removed from MCP server. [toolName={}]", name);
105-
this.toolsChangedObservers.forEach(ToolsChangedObserver::onToolsChanged);
106105
}
107106

108107
/**
109108
* Creates a tool specification for the MCP server.
110-
* <p>
111-
* This method constructs a {@link McpServerFeatures.SyncToolSpecification} that includes:
112-
* <ul>
113-
* <li>Tool metadata (name, description, input schema)</li>
114-
* <li>Call handler that executes the tool and handles exceptions</li>
115-
* </ul>
116109
*
117110
* @param name The name of the tool.
118111
* @param description The description of the tool.
119112
* @param parameters The parameter schema containing type, properties, and required fields.
120-
* @return A fully configured {@link McpServerFeatures.SyncToolSpecification}.
113+
* @return A configured {@link McpServerFeatures.SyncToolSpecification}.
121114
*/
122115
private McpServerFeatures.SyncToolSpecification createToolSpecification(String name, String description,
123116
Map<String, Object> parameters) {
@@ -137,12 +130,6 @@ private McpServerFeatures.SyncToolSpecification createToolSpecification(String n
137130

138131
/**
139132
* Executes a tool and handles any exceptions that may occur.
140-
* <p>
141-
* This method handles two types of exceptions:
142-
* <ul>
143-
* <li>{@link IllegalArgumentException}: Invalid tool arguments (logged as warning)</li>
144-
* <li>{@link Exception}: Any other execution failure (logged as error)</li>
145-
* </ul>
146133
*
147134
* @param toolName The name of the tool to execute.
148135
* @param request The tool call request containing arguments.

0 commit comments

Comments
 (0)