Skip to content

Commit 4dfeafb

Browse files
committed
docs(adr): ADR-008 引入 MCP v3 elicitation + sampling
记录 v0.2.2 引入 mcp_apps/elicitation.py + mcp_apps/sampling.py 的决策: - elicitation 解决"缺参数时来回 3-4 轮问"的体验问题 - sampling 解决"服务端强依赖 ANTHROPIC_API_KEY"的能力解耦问题 - 通过 _meta 字段对老客户端 (Cursor / Continue.dev) 完全向后兼容 对比了"等客户端全支持再做" / "自定义协议" / "只做 elicitation"三个替代方案。
1 parent 5227c89 commit 4dfeafb

1 file changed

Lines changed: 93 additions & 0 deletions

File tree

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
# ADR-008: 引入 MCP v3 elicitation + sampling
2+
3+
**状态**: Accepted (v0.2.2 落地, 2026-06)
4+
**关联**: `src/dbjavagenix/mcp_apps/elicitation.py`, `src/dbjavagenix/mcp_apps/sampling.py`
5+
**规范**: MCP spec 2025-06-18 (v3) + 2025-11-25 anniversary spec
6+
7+
## 背景
8+
9+
DBJavaGenix 早期(v0.1, 2025-09)定的 MCP 协议是 2024 老版本,只有 tools。带来两个问题:
10+
11+
### 问题 1:缺参数时的体验差
12+
13+
`db_connect_test` 需要 `host / port / user / password / database` 五个参数。
14+
v0.1 行为:如果用户漏了 `password`,工具返回 `{"error": "password is required"}`,
15+
让客户端/LLM 自己组装"请补充 password"。
16+
17+
实际体验:
18+
- LLM 可能误以为是"密码错了"而不是"没填"
19+
- 用户在 Claude Desktop 里没有标准化的"补缺表单"UI,只能纯文字交互
20+
- 多个参数缺失时,LLM 一次问一个,来回 3-4 轮
21+
22+
### 问题 2:LLM 调用强依赖 ANTHROPIC_API_KEY
23+
24+
`ai_infer_business_names` (P4.1) 直接调 Anthropic API,需要服务端有 ANTHROPIC_API_KEY。
25+
CI 环境 / 离线环境 / 用户自己付费用 Claude Desktop 但不想再开一份 API key — 都用不上。
26+
27+
## 决定
28+
29+
按 MCP v3 (2025-06-18) + 2025-11-25 anniversary 规范引入两类 server-initiated 调用:
30+
31+
### elicitation/create:服务器要求客户端弹表单
32+
33+
```python
34+
# src/dbjavagenix/mcp_apps/elicitation.py
35+
build_elicitation_request(message, requested_schema)
36+
missing_params_to_elicitation(tool_name, received, schema) # 自动比对 required
37+
to_meta_hint(elicitation_request) # 包成 _meta 字段供老客户端降级
38+
```
39+
40+
工具调用前 check 缺参,缺就返回 elicitation 请求(包在 `_meta["mcp-apps/elicitation"]`),
41+
客户端识别后弹原生表单。老客户端忽略 `_meta` 走原来的 error path,**完全向后兼容**
42+
43+
### sampling/createMessage:服务器借客户端 LLM
44+
45+
```python
46+
# src/dbjavagenix/mcp_apps/sampling.py
47+
build_sampling_request(user_message, system_prompt=None, max_tokens=1024, model_prefs=ModelPreferences(...))
48+
SamplingClient(dispatcher).complete(...) # 异步 / 同步 dispatcher 都支持
49+
```
50+
51+
`ai_infer_business_names` 拿不到 ANTHROPIC_API_KEY 时,降级路径从"纯规则"
52+
升级为"sampling → 客户端 LLM → 规则"三级。
53+
54+
## 替代方案
55+
56+
### A. 等所有客户端都支持 v3 再做
57+
58+
**否决**:Cherry Studio / Cursor / Continue.dev 目前(2026-05)还没支持 sampling。
59+
但我们的 `_meta` 降级方案对老客户端零影响,可以早做。
60+
61+
### B. 自己定义私有协议
62+
63+
**否决**:MCP 是开放标准,2025-11 anniversary 后社区生态快速形成
64+
(agentskills.io, 多家 vendor 实现),自定义协议是反潮流。
65+
66+
### C. 只做 elicitation,不做 sampling
67+
68+
**否决**:sampling 才是真正解决"API key 强依赖"的关键。elicitation 是体验优化,
69+
sampling 是能力解耦。两个一起做工作量增加不大(各 ~120 行)。
70+
71+
## 后果
72+
73+
****:
74+
- `mcp_apps/` 模块独立可测,27 个 unit test 100% 覆盖
75+
- 老客户端零影响(通过 `_meta` 降级)
76+
- 新客户端拿到原生表单 + LLM 借用能力
77+
- 为后续 ADR-010 (agentic-runner) 打基础 — runner 本身就是 sampling client
78+
79+
****:
80+
- 客户端兼容矩阵需要文档化(README 加了一张表)
81+
- `SamplingClient` 的 dispatcher 必须由 transport 注入,本地直接调测试用例
82+
需要 mock(影响测试组织)
83+
84+
**实测**(2026-06 在 Claude Desktop 4.6 上):
85+
- 缺 password 调 `db_connect_test`,Desktop 直接弹密码框,1 步搞定 vs 之前 3 轮文字
86+
- 不设 ANTHROPIC_API_KEY 调 `ai_infer_business_names`,Desktop 自己用 Sonnet 4.6 跑完,
87+
结果质量和服务器直连一致
88+
89+
## 叙事意义
90+
91+
MCP 从 "tools 单向调用" 演进到 "服务器/客户端双向请求" 是 2025-2026
92+
最重要的协议变更。早期 MCP 项目(v0.1 时期)绕不开"服务端必须自带 API key"的痛点,
93+
v3 sampling 是优雅解法。我们 v0.2.2 跟上 — 既是技术升级,也是对协议生态的投票。

0 commit comments

Comments
 (0)