MCP 协议在 Android 端的应用:AI 工具调用新范式
2025 年底,Anthropic 推出了 Model Context Protocol (MCP)——一种开放协议,用于为 AI 模型提供标准化的工具和资源访问接口。经过大半年的发展,MCP 已经从一个概念成长为 AI 应用开发的主流协议标准。
本文将深入探讨 MCP 协议在 Android 端的应用场景、架构设计,并通过一个完整的 Kotlin 实现,展示如何在 Android 应用中通过 MCP 协议调用 AI 工具。
什么是 MCP?
MCP(Model Context Protocol)是一种开放协议,旨在标准化 AI 模型与外部工具和数据源的交互方式。你可以把它理解为「AI 世界的 USB-C 接口」——它为 AI 模型提供了一种统一的方式来使用各种工具和访问各种数据源。
核心概念
| 组件 | 角色 | 举例 |
|---|---|---|
| Host | AI 应用 | Android App、IDE 插件 |
| Server | 工具/资源提供者 | 文件系统、数据库、日历 API |
| Client | 协议客户端(Host 内部) | 维护与 Server 的连接 |
| Tool | 可调用的具体能力 | 搜索文件、发送邮件、查询天气 |
| Resource | 可查询的数据源 | 数据库表、API 返回结果 |
协议流程
┌─────────────┐ discover tools ┌─────────────┐
│ Android │ ──────────────────> │ MCP │
│ App │ │ Server │
│ (Host) │ <────────────────── │ │
│ │ tool list │ │
│ ┌─────┐ │ │ │
│ │MCP │ │ call tool │ ┌────────┐ │
│ │Client│ │ ──────────────────> │ │ Tool A │ │
│ └─────┘ │ │ │ Tool B │ │
│ │ tool result │ │ Tool C │ │
│ │ <────────────────── │ └────────┘ │
└─────────────┘ └─────────────┘
为什么 Android 需要 MCP?
传统上,在 Android 中集成 AI 功能有两种方式:
- 硬编码 Function Calling:手动定义每个工具的 JSON Schema,模型调用后自己解析结果
- 自建工具链:自行实现工具注册、调用、结果返回的整个框架
这两种方式都不够灵活——每增加一个新工具,都要改代码。而且不同应用之间的工具无法复用。
MCP 带来三个核心好处:
- 标准化:所有工具遵循统一的接口协议
- 动态发现:Host 可以动态发现 Server 提供的所有工具,无需硬编码
- 可组合:一个 Android 应用可以同时连接多个 MCP Server,组合使用多种能力
Android MCP 架构设计
在 Android 上实现 MCP,我们需要考虑移动端的特殊性:
- 资源受限(特别是端侧模型推理)
- 网络不稳定(云端模型调用)
- 隐私敏感(工具可能访问本地数据)
- 生命周期复杂(Activity/Fragment 销毁重建)
以下是推荐的 Android MCP 架构:
整体架构
┌─────────────────────────────────────┐
│ Android App │
│ ┌─────────────────────────────┐ │
│ │ MCP Host Manager │ │
│ │ ┌─────┐ ┌─────┐ ┌─────┐ │ │
│ │ │MCP C│ │MCP C│ │MCP C│ │ │
│ │ │lient│ │lient│ │lient│ │ │
│ │ └──┬──┘ └──┬──┘ └──┬──┘ │ │
│ └─────┼───────┼───────┼─────┘ │
│ │ │ │ │
│ ┌─────▼──┐ ┌──▼────┐ ┌▼──────┐ │
│ │端侧 MCP│ │云 MCP │ │本地 │ │
│ │ Server │ │Server │ │Service│ │
│ │(AICore)│ │(HTTP) │ │(Binder)│ │
│ └────────┘ └───────┘ └───────┘ │
└─────────────────────────────────────┘
核心组件
MCP Host Manager:管理多个 MCP Client 连接的生命周期,提供统一的工具调用接口。
MCP Client:每个 Server 对应一个 Client,负责协议通信、工具列表缓存、调用路由。
MCP Server:可以在本地(Service)、云端(HTTP)或 AICore 上运行。
Kotlin 实现:一个 MCP 客户端
下面是基于 Kotlin + Ktor 的 MCP 客户端核心实现:
MCP 协议消息定义
// MCP 协议基类
@Serializable
data class McpMessage(
val jsonrpc: String = "2.0",
val id: String,
val method: String,
val params: JsonObject? = null
)
@Serializable
data class McpResponse(
val jsonrpc: String = "2.0",
val id: String,
val result: JsonObject? = null,
val error: McpError? = null
)
@Serializable
data class McpError(
val code: Int,
val message: String
)
// 工具定义
@Serializable
data class ToolDefinition(
val name: String,
val description: String,
@SerialName("input_schema")
val inputSchema: JsonObject
)
MCP Client 实现
class McpClient(
private val endpoint: String,
private val client: HttpClient = HttpClient(CIO)
) {
private var tools: List<ToolDefinition> = emptyList()
private var requestId = 0
// 初始化:发现并缓存工具列表
suspend fun initialize(): List<ToolDefinition> {
val response = sendRequest("initialize", buildJsonObject {
put("protocolVersion", "2025-03-26")
put("capabilities", buildJsonObject {
put("tools", buildJsonObject {})
})
})
// 获取工具列表
val toolsResponse = sendRequest("tools/list", null)
tools = parseTools(toolsResponse)
return tools
}
// 调用某个工具
suspend fun callTool(name: String, args: JsonObject): JsonObject {
val response = sendRequest("tools/call", buildJsonObject {
put("name", name)
put("arguments", args)
})
return response.result ?: error("Tool call failed")
}
// 发送 JSON-RPC 请求
private suspend fun sendRequest(
method: String,
params: JsonObject?
): McpResponse {
val message = McpMessage(
id = (++requestId).toString(),
method = method,
params = params
)
return client.post(endpoint) {
contentType(ContentType.Application.Json)
setBody(message)
}.body()
}
private fun parseTools(response: McpResponse): List<ToolDefinition> {
val toolsArray = response.result
?.getJSONArray("tools") ?: return emptyList()
return Json.decodeFromJsonElement(toolsArray)
}
}
在 ViewModel 中集成
class McpViewModel : ViewModel() {
private val mcpClients = mutableMapOf<String, McpClient>()
private val _tools = MutableStateFlow<List<ToolDefinition>>(emptyList())
val tools: StateFlow<List<ToolDefinition>> = _tools.asStateFlow()
// 注册 MCP Server
fun registerServer(id: String, endpoint: String) {
viewModelScope.launch {
val client = McpClient(endpoint)
try {
val serverTools = client.initialize()
mcpClients[id] = client
_tools.update { it + serverTools }
} catch (e: Exception) {
Log.e("MCP", "Failed to connect server $id", e)
}
}
}
// AI 模型调用工具
fun processWithTools(userQuery: String, aiClient: AiClient) {
viewModelScope.launch {
// 1. 将工具定义发送给 AI 模型
val aiResponse = aiClient.chat(
userQuery,
tools = _tools.value
)
// 2. AI 模型决定调用哪个工具
if (aiResponse.hasToolCall()) {
val toolCall = aiResponse.toolCall
val targetClient = findClient(toolCall.name)
// 3. 执行工具调用
val result = targetClient?.callTool(
toolCall.name,
toolCall.arguments
)
// 4. 将结果返回给 AI 继续处理
val finalResponse = aiClient.chat(
userQuery,
toolResult = result
)
// 展示最终回复
}
}
}
}
端侧 MCP Server:AICore 集成
Android 16+ 的 AICore 可以作为端侧 MCP Server,提供本地 AI 工具:
class OnDeviceMcpServer(private val context: Context) {
private val aicoreManager = AICoreManager(context)
// 注册的工具列表
val tools = listOf(
ToolDefinition(
name = "text_summarize",
description = "对文本进行智能摘要",
inputSchema = buildJsonObject {
put("type", "object")
put("properties", buildJsonObject {
put("text", buildJsonObject {
put("type", "string")
put("description", "要摘要的文本")
})
put("maxLength", buildJsonObject {
put("type", "number")
put("description", "摘要最大长度")
})
})
put("required", buildJsonArray {
add("text")
})
}
),
ToolDefinition(
name = "text_classify",
description = "对文本进行情感分类",
inputSchema = buildJsonObject {
put("type", "object")
put("properties", buildJsonObject {
put("text", buildJsonObject {
put("type", "string")
})
})
put("required", buildJsonArray { add("text") })
}
)
)
// 处理工具调用
suspend fun handleToolCall(name: String, args: JsonObject): JsonObject {
return when (name) {
"text_summarize" -> {
val text = args["text"]!!.jsonPrimitive.content
val maxLen = args["maxLength"]?.jsonPrimitive?.int ?: 100
val summary = aicoreManager.generate(text) {
maxOutputTokens = maxLen
temperature = 0.3f
}
buildJsonObject { put("summary", summary) }
}
"text_classify" -> {
val text = args["text"]!!.jsonPrimitive.content
val result = aicoreManager.classify(text)
buildJsonObject { put("label", result.label) }
}
else -> error("Unknown tool: $name")
}
}
}
实际应用场景
1. 智能便签应用
用户说「帮我整理这周的购物记录」,App 通过 MCP 调用数据库查询工具、AI 摘要工具、日历工具,自动完成数据提取 -> 智能分析 -> 结果展示的完整流程。
2. 代码助手
Android Studio 插件集成 MCP Client,连接到项目分析 Server、Git 历史 Server、文档搜索 Server。开发者一句话就能完成代码审查、提交信息生成、问题定位。
3. 自动化工具
Tasker 类应用通过 MCP 协议暴露���统能力(WiFi 控制、短信发送、文件操作),用户可以用自然语言编排自动化流程。
最佳实践与注意事项
- 超时管理:端侧工具设置 5-10 秒超时,云端工具设置 15-30 秒超时
- 重试策略:网络请求使用指数退避重试,端侧调用可以不重试
- 权限控制:敏感工具需要用户显式授权
- 错误处理:工具调用失败后,给 AI 模型提供有意义的错误信息,让它能重新规划
- 生命周期:MCP Client 在 ViewModelScope 中管理,随 UI 生命周期自动清理
总结与展望
MCP 协议正在重塑 AI 应用的开发方式。对于 Android 开发者来说,这并不是一个「要不要用」的问题,而是「什么时候开始用」的问题。
核心结论:
- MCP 提供了一套标准化的 AI 工具接口,比自行实现 Function Calling 更灵活、更可扩展
- 端侧 AI 模型(Gemini Nano)可以作为 MCP Server 运行,实现完全离线的工具调用
- Kotlin + Ktor 的组合可以方便地在 Android 上实现 MCP Client 和 Server
- 随着 Google 在 Android 17 中进一步强化 AI 能力,MCP 将会成为 Android AI 应用的标准组件
我已经将本文的完整示例代码整理为一个 Android 项目模板,你可以在 GitHub 上找到。欢迎 Star 和 PR。