开发者中心 › 接口参考

接口参考(字段级)

两部分:MCP 协议端(你的服务器要实现的)与市场动作面(app 侧 market.* 工具,了解用户侧发生什么)。本文与 McpClient.kt / McpExtDiscovery.kt / McpMarket.kt 实现一致。

要点(30 秒)

  • MCP 协议端(你的服务器要实现):tools/list、tools/call、鉴权、超时。
  • 市场动作面(app 内 market.* 工具)。
  • 错误码表(MARKET_*)。
  • 安全约束(不可协商)。
展开全文(完整表格 / 代码 / 细节)

一、MCP 协议端(你的服务器要实现的)

传输

  • 仅 HTTP POST;Content-Type: application/json;建议同时带 Accept: application/json, text/event-stream;
  • body 为 JSON-RPC 2.0;响应可以是纯 JSON,也可以是 SSE(data: {...} 行),两种都收;
  • 超时预算:连接 5s、读取 30s(McpClient.kt 常量);长任务请先应答再异步执行。

健康检查(安装 / 启用时必调)

POST <你的URL>        body: {}

返回 200 或 405 即视为存活;其它状态码 / 超时 = 不可达,安装报 MARKET_SERVER_UNREACHABLE(配置保留,可重试)。

tools/list(发现)

→ {"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}
← {"jsonrpc":"2.0","id":1,"result":{"tools":[ { ... } ]}}
tools[] 字段必填说明
name✅工具名,建议 领域.动作。命中保留黑名单(sms.read 等 7 个)不会被挂出。
description✅ 必须给 AI 的工具说明。禁止占位——空/占位描述上架审核即打回。
inputSchema✅ 必须参数 JSON Schema(类型/必填/描述),给 AI 的。空 Schema 上架审核即打回;MOV 内置面自 2026-08-29 起全量携带。
level—"readonly"(缺省)或 "write"。当前版本 write 不挂出(只读先行)。

tools/call(调用)

→ {"jsonrpc":"2.0","id":2,"method":"tools/call",
   "params":{"name":"weather.now","arguments":{"city":"北京"}}}
← {"jsonrpc":"2.0","id":2,"result":{"content":[{"type":"text","text":"..."}],"isError":false}}

建议返回 result.content(MCP 标准内容数组);result 内结构化数据会原样转给 AI。失败可返回 "isError": true + 文本说明。

鉴权(可选)

需要鉴权的服务:用户安装后在 app 内填 token,之后每个请求带 Authorization: Bearer <token>。目录登记 server.token 留空,不要把真实 token 写进目录。

二、市场动作面(app 内 market.* 工具)

全部经 app 工具面 tools/call 调用(调试:adb forward tcp:8389 tcp:8389 + Bearer token)。返回统一 {"ok": Boolean, ...},失败带 {"ok": false, "error": "<CODE>: <message>"}。

动作入参返回 / 行为
market.refresh{"force": false}拉取/刷新目录;距上次成功拉取 <1h 直接回缓存(force 绕过)。→ {"ok":true,"packageCount":12,"fromCache":false,"updatedAt":"..."}
market.list{"cat": "可选筛选"}目录列表(含安装状态 installed/enabled 与 ui 值)。
market.install{"id": "weather-demo"}健康检查 + 发现 + 热挂 ext.* 工具(同步调用,发现可能数秒)。→ {"ok":true,"serverId":"...","tools":["ext.xxx.a"]};不可达 → ok:false + MARKET_SERVER_UNREACHABLE(配置已写入,可重试)。
market.uninstall{"id": "..."}仅 origin="market" 条目可卸(手动添加的拒绝)→ 删除 + 热摘除该服务器全部工具。→ {"ok":true,"removed":3}
market.enable / market.disable{"id": "..."}启停 = 重新发现热挂 / 热摘除。→ {"ok":true,"enabled":true,"tools":[...]}
market.status{"id": "可选"}健康状态(可达性 / 工具数 / 最近错误 / 检查时间)。
market.submit条目字段 + confirm:true提交上架(确认前不会提交)。网页提交见上架流程。
market.submitStatus{"id": "..."}→ pending / rejected(附理由)/ approved。

命名细节:外部工具前缀 ext.<tag>.<name> 的 tag = 目录 name(空则用 id),非 [A-Za-z0-9_-] 字符转下划线。

三、错误码表(MARKET_*)

code含义 / 触发
MARKET_REGISTRY_UNAVAILABLE目录拉取失败且无本地缓存
MARKET_PACKAGE_NOT_FOUNDinstall 的 id 不在目录里(declarative 缺剧本同码)
MARKET_ID_CONFLICT与既有服务器 id 冲突(含手动添加的)
MARKET_SERVER_UNREACHABLE健康检查失败或发现失败(配置保留,enable/重试可恢复)
MARKET_NOT_MARKET_ORIGINuninstall 目标是手动添加的服务器
MARKET_NOT_INSTALLEDenable/disable/status 的 id 未安装

工具执行层通用错误(16 类单源表)见开发规范 · 四。

四、安全约束(不可协商)

  • 目录与你的服务必须 https(app 全局禁明文,仅放行回环供调试);
  • 外部工具继承权限分级:readonly 默认放行;write 需用户显式开启(当前版本 write 不挂出);
  • 保留黑名单工具外部服务器永远不可达;
  • token 仅存用户本地,market.list/status 等任何响应不含 token。