Kotlin SDK
本指南将使用支持 MCP over MQTT 的 Kotlin SDK,创建一个简单的 MCP 服务器。
环境准备
安装 Kotlin 编译环境
确保你已经安装了 JDK 21+,Kotlin 2.2+,以及 Gradle 9.2+。使用 SDKMAN 是安装和管理这些工具的推荐方式:
bash
curl -s "https://get.sdkman.io" | bash
source "$HOME/.sdkman/bin/sdkman-init.sh"
sdk install java 21.0.9-tem
sdk install kotlin 2.2.21
sdk install gradle 9.2.1安装和运行 EMQX
请参考 快速开始 文档,安装并运行 EMQX 服务器。
下载并运行 MCP Server 示例源码
克隆示例程序的源码:
bash
git clone https://github.com/terry-xiaoyu/kotlin-mcp-server-demo.git
cd kotlin-mcp-server-demo该示例程序中注册了两个 MCP 工具:一个计算器工具,一个电灯控制工具。
- 计算器工具:提供基本的加减乘除运算。
- 电灯控制工具:可以控制电灯的开关状态、亮度等。
kotlin
// Add a calculator tool
server.addTool(
name = "calculator",
description = "This tool can perform basic math operations: addition, subtraction, multiplication, and division.",
inputSchema = ToolSchema(
properties = buildJsonObject {
putJsonObject("num1") {
put("type", JsonPrimitive("number"))
put("description", JsonPrimitive("The first number"))
}
putJsonObject("num2") {
put("type", JsonPrimitive("number"))
put("description", JsonPrimitive("The second number"))
}
putJsonObject("op") {
put("type", JsonPrimitive("string"))
put("description", JsonPrimitive("The operation to perform: +, -, *, /"))
}
},
required = listOf("num1", "num2", "op"),
),
) { request : CallToolRequest ->
val num1 = request.params.arguments?.get("num1")?.jsonPrimitive?.content?.toDoubleOrNull()
?: throw IllegalArgumentException("Invalid or missing argument: num1")
val num2 = request.params.arguments?.get("num2")?.jsonPrimitive?.content?.toDoubleOrNull()
?: throw IllegalArgumentException("Invalid or missing argument: num2")
val op = request.params.arguments?.get("op")?.jsonPrimitive?.content?.firstOrNull()
?: throw IllegalArgumentException("Invalid or missing argument: op")
val x = num1.toDouble()
val y = num2.toDouble()
val result = when(op) {
'+' -> x + y
'-' -> x - y
'*' -> x * y
'/' -> if (y == 0.0) throw ArithmeticException("Division by zero") else x / y
else -> throw IllegalArgumentException("Don't support Operator: $op")
}
CallToolResult(
content = listOf(TextContent("The result is: $result")),
)
}
// Add a light control tool
server.addTool(
name = "set_light_brightness",
description = "Control the light on the panel. You can change the brightness, if you want to off the light, set brightness to 0. Set brightness value to 'last_value' to restore the previous brightness, which is useful when the light is off and you want to turn it back on.",
inputSchema = ToolSchema(
properties = buildJsonObject {
putJsonObject("value") {
put("type", JsonArray(listOf(JsonPrimitive("number"), JsonPrimitive("string"))))
put("description", JsonPrimitive("Brightness value between 0 and 100, or 'last_value' to restore previous brightness"))
}
},
required = listOf("value")
),
) { request ->
val value = request.params.arguments?.get("value")?.jsonPrimitive?.content
// Handle the request and control the light brightness
CallToolResult(
content = listOf(TextContent("Light brightness set to: ${value}%")),
)
}最后使用下面的命令,启动 MCP 服务器示例程序:
bash
./gradlew run --args="--mqtt kt001 demo/kotlin-mcp-server"其中参数说明如下:
- MQTT Client ID =
kt001 - MCP Server Name =
demo/kotlin-mcp-server
使用 MCP 客户端测试
目前 Kotlin SDK 还没有提供 MCP 客户端的实现,可以使用 Python SDK 创建一个简单的 MCP 客户端进行测试。
python
uv init light_controller
cd light_controller
uv add git+https://github.com/emqx/mcp-python-sdk --branch main
uv add "mcp[cli]"
source .venv/bin/activate添加一个 light_controller.py 文件,内容如下:
python
# light_controller.py
import logging
import anyio
import mcp.client.mqtt as mcp_mqtt
from mcp.shared.mqtt import configure_logging
configure_logging(level="INFO")
logger = logging.getLogger(__name__)
async def on_mcp_server_discovered(client, server_name):
logger.info(f"Discovered {server_name}, connecting ...")
await client.initialize_mcp_server(server_name)
async def on_mcp_connect(client, server_name, connect_result):
success, init_result = connect_result
if success == 'error':
logger.error(f"Failed to connect to {server_name}: {init_result}")
return
logger.info(f"Connected to {server_name}, success={success}, init_result={init_result}")
capabilities = init_result.capabilities
if capabilities.tools:
toolsResult = await client.list_tools(server_name)
tools = toolsResult.tools
logger.info(f"Tools of {server_name}: {tools}")
for tool in tools:
logger.info(f" - {tool.name}: {tool.description}")
if tool.name == "set_light_brightness":
result = await client.call_tool(server_name, name = tool.name, arguments={"value": 50})
logger.info(f"Calling the tool as set_light_brightness(value=50), result: {result}")
async def main():
async with mcp_mqtt.MqttTransportClient(
"test_client",
server_name_filter = "demo/kotlin-mcp-server",
auto_connect_to_mcp_server = True,
on_mcp_server_discovered = on_mcp_server_discovered,
on_mcp_connect = on_mcp_connect,
mqtt_options = mcp_mqtt.MqttOptions(
host="localhost",
)
) as client:
await client.start()
while True:
## Simulate other works while the MQTT transport client is running in the background...
await anyio.sleep(20)
if __name__ == "__main__":
anyio.run(main)这个 Python 客户端会自动发现名为 demo/kotlin-mcp-server 的 MCP 服务器,并调用 set_light_brightness 工具将电灯亮度设置为 50:
bash
INFO 2025-12-19 13:07:44,445 - Calling the tool as set_light_brightness(value=50), result: meta=None
content=[TextContent(type='text', text='Light brightness set to: 50%',
annotations=None)] isError=False