一、MCP协议核心解析
我是lenz,很高兴在这里分享我的第一篇文章。近期工作中接触到了MCP的学习机会,作为一名主要使用Kotlin的后端开发者,我计划撰写MCP相关的文章。本文基于我的实际开发经验和个人理解整理而成,如有不足之处欢迎指正交流。
参考资料:
1.1 协议定位
MCP(Model Context Protocol)作为开放协议,其核心价值在于标准化LLM的上下文交互方式。官方将其类比为"AI领域的USB-C接口"——正如USB-C统一了设备连接标准,MCP为AI模型提供了统一的数据源和工具接入规范。
1.2 技术本质
从实现层面看,MCP实质上是对LLM Function Call功能的标准化封装,其架构包含两个关键组件:
- 服务端:实现标准化Function Call接口
- 客户端:动态发现并调用服务端能力
1.3 架构类比
采用前后端分离架构的类比理解:
组件 | 类比角色 | 功能对应 |
---|---|---|
MCP服务端 | 后端API | 提供标准化能力接口 |
MCP客户端 | 前端应用 | 交互调度层 |
LLM | 用户操作行为 | 动态触发功能调用 |
二、Kotlin服务端实现方案
2.1 实现选型建议
推荐技术组合:
- 传输协议:SSE(Server-Sent Events)
- 开发语言:Kotlin
- 框架选择:Ktor
协议选型对比:
传输方式 | 启动方式 | 适用场景 |
---|---|---|
STDIO | 子进程模式(java -jar) | 嵌入式部署 |
SSE | 独立HTTP服务 | 云原生部署 |
2.2 环境配置清单
- JDK:≥17(推荐Amazon Corretto 17) - 构建工具:Gradle 8.5+ - 关键依赖: io.modelcontextprotocol:kotlin-sdk:0.4.0 kotlinx-serialization-json:1.7.x
版本适配警告:务必确保kotlin("jvm")插件与序列化插件版本严格匹配(推荐2.1.0),否则可能引发运行时异常。
2.3 服务端核心实现
启动配置示例:
fun runSseMcpServerUsingKtorPlugin(port: Int): Unit = runBlocking {
println("Starting sse server on port $port")
println("Use inspector to connect to the http://localhost:$port/sse")
embeddedServer(CIO, host = "0.0.0.0", port = port) {
mcp {
return@mcp configureServer()
}
}.start(wait = true)
}
能力注册模板:
fun configureServer(): Server {
val server = Server(
Implementation(
name = "mcp-kotlin test server",
version = "0.1.0"
),
ServerOptions(
capabilities = ServerCapabilities(
prompts = ServerCapabilities.Prompts(listChanged = true),
resources = ServerCapabilities.Resources(subscribe = true, listChanged = true),
tools = ServerCapabilities.Tools(listChanged = true),
)
)
)
// Add a tool
server.addTool(
name = "kotlin-sdk-tool",
description = "A test tool",
inputSchema = Tool.Input()
) { _ ->
CallToolResult(
content = listOf(TextContent("Hello, world!"))
)
}
return server
}
三、实战:业务API智能接入
以下业务API智能接入方案由
提供,敬礼!( ` ・´)73.1 三阶能力暴露方案
1.接口目录服务
// 1. 基础元工具:获取所有可用API列表
server.addTool(
name = "listAllApis",
description = "列出所有可用的API接口",
inputSchema = Tool.Input()
) {
try {
// 模拟数据
val responseBuilder = StringBuilder("可用API列表(apiId-Name-Description):\n\n")
.append("用户查询:\n").append(" • getUserInfo-获取用户信息-根据用户名称获取用户信息\n")
.append("可使用 getApiDetails 工具获取特定API的详细信息,其中source表示来源")
CallToolResult(content = listOf(TextContent(responseBuilder.toString())))
} catch (e: Exception) {
CallToolResult(content = listOf(TextContent("错误: 获取API列表失败 - ${e.message}")))
}
}
2.详情查询服务
// 2. 基础元工具:获取特定API的详细信息
server.addTool(
name = "getApiDetails",
description = "获取特定API的详细信息和使用方法",
inputSchema = Tool.Input(
properties = buildJsonObject {
putJsonObject("apiId") {
put("type", "string")
put("description", "API的唯一标识符")
}
},
required = listOf("apiId")
)
) { request ->
val apiId = request.arguments["apiId"]?.jsonPrimitive?.content
?: return@addTool CallToolResult(content = listOf(TextContent("错误: 缺少参数 apiId")))
// 模拟数据
val api = "{\"id\":\"getUserInfo\",\"name\":\"获取用户信息\",\"description\":\"根据用户名称获取用户信息\",\"category\":\"用户查询\",\"params\":[{\"name\":\"username\",\"type\":\"String\",\"description\":\"用户名称\",\"required\":true,\"defaultValue\":\"\",\"source\":\"\"}]}"
CallToolResult(content = listOf(TextContent(api)))
}
3.执行代理服务
// 3. 基础元工具:执行指定API
server.addTool(
name = "executeApi",
description = "执行指定的API,需要提供API的ID和参数",
inputSchema = Tool.Input(
properties = buildJsonObject {
putJsonObject("apiId") {
put("type", "string")
put("description", "要执行的API的唯一标识符")
}
putJsonObject("params") {
put("type", "object")
put("description", "API的参数")
}
},
required = listOf("apiId")
)
) { request ->
val apiId = request.arguments["apiId"]?.jsonPrimitive?.content
val params = request.arguments["params"]?.let { jsonElement ->
if (jsonElement is JsonPrimitive)
jsonElement.jsonPrimitive.content
else
jsonElement.toString()
} ?: "{}"
if (apiId == null) {
return@addTool CallToolResult(content = listOf(TextContent("错误: 缺少参数 apiId")))
}
// 模拟调用接口响应数据
val map = mutableMapOf("lenz" to "lenz是一名使用Kotlin的后端开发者")
CallToolResult(content = listOf(TextContent(map[Gson().fromJson(params, Map::class.java).getOrDefault("username", "")])))
}
3.2 测试验证流程
1.环境准备
安装(最新版)+ 有效API Key
2.服务配置
设置 → MCP服务器 → 新增: - 类型:SSE - 地址:http://localhost:3001/sse

3.对话测试
用户:询问用户lenz的信息 → LLM自动选择list_apis工具 → 定位用户信息API → 调用执行代理获取结果

总结
感谢您阅读本文!实现MCP服务器的核心逻辑并不复杂,但需要注意开发环境与依赖库版本的兼容性问题。我已将完整的业务API集成代码开源在GitHub仓库(
),其中包含了可复用的配置方案和版本管理建议。后续我将持续更新该系列文章,下一篇将重点讲解客户端实现的关键技术与实战演示。
Lenz
想下班
热知识,今晚八点第三批MB神高开抢。会赢吗?会赢的。
2 Comments
楚雨荨 Lau
April 18, 2025
是Kotlin,这才是真正的MCP!
An*l
April 18, 2025
博主,你觉得Java和Kotlin哪个更好用?
Lenz
April 18, 2025
我觉得Idea + Coplilot更好用。