基于 Vert.x 的传输实现,用于 Model Context Protocol (MCP) Java SDK。该项目提供了一个轻量级、非阻塞的传输层,用于将 MCP 服务器与 Vert.x 应用程序集成。
Vert.x MCP 服务器提供了以下功能:
VertxMcpTransport 接口,提供了一个 Vert.x 路由器,以便将其集成到您的 Vert.x 应用程序中。McpVerticle,便于部署。此项目目前处于实验阶段,尚未在生产环境中进行全面测试。
<dependency>
<groupId>org.kinotic</groupId>
<artifactId>vertx-mcp</artifactId>
<version>4.5.1</version>
</dependency>
dependencies {
implementation 'org.kinotic:vertx-mcp:4.5.1'
}
首先,使用官方 Java MCP SDK 创建您的 MCP 服务器:
import io.modelcontextprotocol.server.McpServer;
import io.modelcontextprotocol.server.McpServerFeatures;
import io.modelcontextprotocol.spec.McpSchema;
import io.modelcontextprotocol.spec.ServerCapabilities;
import java.util.List;
import reactor.core.publisher.Mono;
// 创建一个简单的计算器工具
var calculatorTool = McpServerFeatures.AsyncToolSpecification.builder()
.tool(McpSchema.Tool.builder()
.name("calculator")
.description("基本计算器")
.inputSchema("""
{
"type": "object",
"properties": {
"operation": {"type": "string", "enum": ["add", "subtract", "multiply", "divide"]},
"a": {"type": "number"},
"b": {"type": "number"}
},
"required": ["operation", "a", "b"]
}
""")
.build())
.callHandler((exchange, toolReq) -> {
String operation = (String) toolReq.arguments().get("operation");
double a = ((Number) toolReq.arguments().get("a")).doubleValue();
double b = ((Number) toolReq.arguments().get("b")).doubleValue();
double result = switch (operation) {
case "add" -> a + b;
case "subtract" -> a - b;
case "multiply" -> a * b;
case "divide" -> a / b;
default -> throw new IllegalArgumentException("未知操作:" + operation);
};
return Mono.just(McpSchema.CallToolResult.builder()
.textContent(List.of(String.valueOf(result)))
.isError(false)
.build());
})
.build();
// 创建 MCP 服务器规范(暂不调用 .build())
var mcpServerSpec = McpServer.async(transportProvider)
.serverInfo("calculator-server", "1.0.0")
.capabilities(ServerCapabilities.builder()
.tools(true)
.build())
.tools(calculatorTool);
import io.vertx.ext.mcp.transport.VertxMcpSseServerTransportProvider;
import com.fasterxml.jackson.databind.ObjectMapper;
// 创建传输
var transport = VertxMcpSseServerTransportProvider.builder()
.baseUrl("http://localhost:8080")
.messageEndpoint("/mcp/message")
.sseEndpoint("/mcp/sse")
.keepAliveInterval(Duration.ofSeconds(30))
.objectMapper(new ObjectMapper())
.vertx(vertx)
.build();
import io.vertx.ext.mcp.transport.VertxMcpStreamableServerTransportProvider;
import com.fasterxml.jackson.databind.ObjectMapper;
// 创建可流式传输的 HTTP 传输
var transport = VertxMcpStreamableServerTransportProvider.builder()
.objectMapper(new ObjectMapper())
.mcpEndpoint("/mcp")
.disallowDelete(false)
.vertx(vertx)
.build();
使用提供的 Verticle 进行轻松集成:
import io.vertx.ext.mcp.McpVerticle;
// 部署 MCP verticle(传递传输和服务器规范)
vertx.deployVerticle(new McpVerticle(8080, transport, mcpServerSpec), ar -> {
if (ar.succeeded()) {
System.out.println("MCP Verticle 部署成功");
} else {
System.err.println("无法部署 MCP Verticle:" + ar.cause());
}
});
这是一个使用旧版 HTTP+SSE 传输的完整工作示例:
import io.vertx.core.Vertx;
import io.vertx.ext.mcp.McpVerticle;
import io.vertx.ext.mcp.transport.VertxMcpSseServerTransportProvider;
import io.modelcontextprotocol.server.McpServer;
import io.modelcontextprotocol.server.McpServerFeatures;
import io.modelcontextprotocol.spec.McpSchema;
import io.modelcontextprotocol.spec.ServerCapabilities;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.time.Duration;
import java.util.List;
import reactor.core.publisher.Mono;
public class LegacyMcpServerExample {
public static void main(String[] args) {
Vertx vertx = Vertx.vertx();
// 创建带有简单计算器工具的 MCP 服务器
var calculatorTool = McpServerFeatures.AsyncToolSpecification.builder()
.tool(McpSchema.Tool.builder()
.name("calculator")
.description("基本计算器")
.inputSchema("""
{
"type": "object",
"properties": {
"operation": {"type": "string", "enum": ["add", "subtract", "multiply", "divide"]},
"a": {"type": "number"},
"b": {"type": "number"}
},
"required": ["operation", "a", "b"]
}
""")
.build())
.callHandler((exchange, toolReq) -> {
String operation = (String) toolReq.arguments().get("operation");
double a = ((Number) toolReq.arguments().get("a")).doubleValue();
double b = ((Number) toolReq.arguments().get("b")).doubleValue();
double result = switch (operation) {
case "add" -> a + b;
case "subtract" -> a - b;
case "multiply" -> a * b;
case "divide" -> a / b;
default -> throw new IllegalArgumentException("未知操作:" + operation);
};
return Mono.just(McpSchema.CallToolResult.builder()
.textContent(List.of(String.valueOf(result)))
.isError(false)
.build());
})
.build();
// 创建旧版 HTTP+SSE 传输
var transport = VertxMcpSseServerTransportProvider.builder()
.baseUrl("http://localhost:8080")
.messageEndpoint("/mcp/message")
.sseEndpoint("/mcp/sse")
.keepAliveInterval(Duration.ofSeconds(30))
.objectMapper(new ObjectMapper())
.vertx(vertx)
.build();
// 创建 MCP 服务器规范(暂不调用 .build())
var mcpServerSpec = McpServer.async(transport)
.serverInfo("calculator-server", "1.0.0")
.capabilities(ServerCapabilities.builder()
.tools(true)
.build())
.tools(calculatorTool);
// 部署 MCP verticle(传递传输和服务器规范)
vertx.deployVerticle(new McpVerticle(8080, transport, mcpServerSpec), ar -> {
if (ar.succeeded()) {
System.out.println("MCP 服务器已在 8080 端口启动");
System.out.println("SSE 端点:http://localhost:8080/mcp/sse");
System.out.println("消息端点:http://localhost:8080/mcp/message");
} else {
System.err.println("无法启动 MCP 服务器:" + ar.cause());
}
});
}
}
这是一个使用新版 MCP 2025-06-18 可流式传输的 HTTP 传输的完整工作示例:
import io.vertx.core.Vertx;
import io.vertx.ext.mcp.McpVerticle;
import io.vertx.ext.mcp.transport.VertxMcpStreamableServerTransportProvider;
import io.modelcontextprotocol.server.McpServer;
import io.modelcontextprotocol.server.McpServerFeatures;
import io.modelcontextprotocol.spec.McpSchema;
import io.modelcontextprotocol.spec.ServerCapabilities;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.time.Duration;
import java.util.List;
import reactor.core.publisher.Mono;
public class StreamableMcpServerExample {
public static void main(String[] args) {
Vertx vertx = Vertx.vertx();
// 创建带有简单计算器工具的 MCP 服务器
var calculatorTool = McpServerFeatures.AsyncToolSpecification.builder()
.tool(McpSchema.Tool.builder()
.name("calculator")
.description("基本计算器")
.inputSchema("""
{
"type": "object",
"properties": {
"operation": {"type": "string", "enum": ["add", "subtract", "multiply", "divide"]},
"a": {"type": "number"},
"b": {"type": "number"}
},
"required": ["operation", "a", "b"]
}
""")
.build())
.callHandler((exchange, toolReq) -> {
String operation = (String) toolReq.arguments().get("operation");
double a = ((Number) toolReq.arguments().get("a")).doubleValue();
double b = ((Number) toolReq.arguments().get("b")).doubleValue();
double result = switch (operation) {
case "add" -> a + b;
case "subtract" -> a - b;
case "multiply" -> a * b;
case "divide" -> a / b;
default -> throw new IllegalArgumentException("未知操作:" + operation);
};
return Mono.just(McpSchema.CallToolResult.builder()
.textContent(List.of(String.valueOf(result)))
.isError(false)
.build());
})
.build();
// 创建可流式传输的 HTTP 传输
var transport = VertxMcpStreamableServerTransportProvider.builder()
.objectMapper(new ObjectMapper())
.mcpEndpoint("/mcp")
.disallowDelete(false)
.vertx(vertx)
.keepAliveInterval(Duration.ofSeconds(30))
.build();
// 创建 MCP 服务器规范(暂不调用 .build())
var mcpServerSpec = McpServer.async(transport)
.serverInfo("calculator-server", "1.0.0")
.capabilities(ServerCapabilities.builder()
.tools(true)
.build())
.tools(calculatorTool);
// 部署 MCP verticle(传递传输和服务器规范)
vertx.deployVerticle(new McpVerticle(8080, transport, mcpServerSpec), ar -> {
if (ar.succeeded()) {
System.out.println("MCP 服务器已在 8080 端口启动");
System.out.println("可流式传输的 HTTP 端点:http://localhost:8080/mcp");
System.out.println("支持:GET(SSE),POST(消息),DELETE(会话)");
} else {
System.err.println("无法启动 MCP 服务器:" + ar.cause());
}
});
}
}
VertxMcpSseServerTransportProvider 支持以下配置选项:
baseUrl:服务器的基础 URL(必需)messageEndpoint:接收 JSON-RPC 消息的端点(默认:/message)sseEndpoint:SSE 连接的端点(默认:/sse)keepAliveInterval:保持连接的间隔时间(默认:30 秒)objectMapper:Jackson ObjectMapper 用于 JSON 序列化vertx:Vert.x 实例VertxMcpStreamableServerTransportProvider 支持以下配置选项:
objectMapper:Jackson ObjectMapper 用于 JSON 处理(必需)mcpEndpoint:MCP 端点路径(默认:/mcp)disallowDelete:是否禁用会话删除(默认:false)vertx:Vert.x 实例(必需)keepAliveInterval:保持连接的间隔时间(默认:30 秒)传输通过以下方式实现 MCP 协议:
/sse):建立 Server-Sent Events 连接,用于服务器到客户端的通信。/message):接收来自客户端的 JSON-RPC 消息。新的可流式传输的 HTTP 传输遵循 MCP 2025-06-18 规范:
/mcp):处理所有 HTTP 方法(GET、POST、DELETE)。您可以使用任何 MCP 客户端测试您的 MCP 服务器:
http://localhost:8080/mcp/sse 用于建立连接。http://localhost:8080/mcp/message?sessionId=<id> 用于发送请求。http://localhost:8080/mcp 用于所有操作。传输支持优雅关闭:
// 优雅地关闭传输
transport.closeGracefully()
.doOnSuccess(v -> System.out.println("传输已成功关闭"))
.doOnError(e -> System.err.println("关闭传输时出错:" + e))
.subscribe();
计划在未来版本中添加以下功能:
支持 Vert.x 5.x 版本,包括:
实现 MCP 授权 功能,包括:
欢迎贡献!请随时提交拉取请求或打开问题报告错误和功能请求。
本项目根据 Apache 许可证,版本 2.0 授权。