package engine // elicitation.go - MCP Elicitation(服务器向客户端请求用户输入)接口定义. // // MCP 2025-03-26 规范新增了 elicitation/create 请求: // 服务器在工具执行过程中可以主动请求客户端向用户收集额外信息. // 典型场景:数据库工具需要表名,文件工具需要确认覆盖,调试工具需要断点条件. // // 升华改进(ELEVATED): 早期实现 无此接口--遇到服务器主动请求时直接挂起, // 用户侧表现为"工具卡住",无任何提示. // 我们定义 ElicitationHandler 接口,消费层(CLI/SDK/HTTP)各自实现: // - CLI 层:渲染交互式输入表单 // - HTTP 层:推送 SSE 事件等待前端回复 // - 测试层:注入固定回复,不阻塞 // // 替代方案:<在 Engine 内部阻塞等待 channel> - 否决:CLI/SDK/HTTP 的 UI 交互完全不同, // 引擎不该假设 UI 形态. // ElicitationField 描述用户需要填写的单个字段. // 对应 MCP 规范中 elicitation/create 请求的 schema.properties 条目. type ElicitationField struct { // Name 字段名称(对应 JSON schema property key) Name string // Type 字段类型("string" / "number" / "boolean") Type string // Title 显示给用户的标题(可选) Title string // Description 字段描述(可选,展示为输入框 placeholder 或 tooltip) Description string // Required 是否必填 Required bool // Default 默认值(字符串表示,消费层负责类型转换) Default string } // ElicitationRequest 是服务器发出的用户输入请求. // 对应 MCP 规范 elicitation/create 请求的完整 params. type ElicitationRequest struct { // ServerName 发起请求的 MCP 服务器名称 ServerName string // Message 展示给用户的问题或说明文字(Markdown 格式) Message string // Fields 需要用户填写的字段列表(按声明顺序) Fields []ElicitationField } // ElicitationResponse 是用户对 elicitation 请求的回复. type ElicitationResponse struct { // Action 用户操作: // "accept" - 用户确认并提交了数据 // "decline" - 用户明确拒绝(服务器应该放弃该操作) // "cancel" - 用户取消(服务器可以重试或使用默认值) Action string // Values 用户填写的字段值(仅 Action=="accept" 时有意义) // key 为 ElicitationField.Name,value 为用户输入的字符串 // 消费层负责类型校验;服务器负责最终语义解析 Values map[string]string } // ElicitationHandler 处理服务器发出的用户输入请求. // // 实现要求: // - 必须是线程安全的(可能被多个 MCP 服务器并发调用) // - 必须在合理时间内返回(不应无限阻塞) // - 若无法显示 UI,可返回 Action=="cancel" // // 精妙之处(CLEVER): 接口只有一个方法,消费层实现极简-- // CLI 层 4 行代码,HTTP 层 10 行代码,测试桩 1 行代码. // 叠加而非替换:多个 ElicitationHandler 可通过 CompositeElicitationHandler 组合. // // Shape: synchronous callback. Engine passes ElicitationRequest to the // consumer and blocks for an ElicitationResponse (accept / decline / cancel). // // 形态: 同步回调. 引擎把 ElicitationRequest 交给消费者, 阻塞等 // ElicitationResponse (accept / decline / cancel). type ElicitationHandler interface { HandleElicitation(req ElicitationRequest) (ElicitationResponse, error) } // ElicitationHandlerFunc 是 ElicitationHandler 的函数适配器. // 方便消费层用闭包实现简单的处理逻辑,无需定义新类型. type ElicitationHandlerFunc func(req ElicitationRequest) (ElicitationResponse, error) // HandleElicitation 实现 ElicitationHandler 接口. func (f ElicitationHandlerFunc) HandleElicitation(req ElicitationRequest) (ElicitationResponse, error) { return f(req) } // NoopElicitationHandler 是默认的空操作处理器. // 引擎未配置 ElicitationHandler 时使用,直接返回 cancel-- // 让服务器知道客户端无法收集用户输入,服务器自行决策. // // 精妙之处(CLEVER): cancel 而非 decline,语义上"无法响应"而非"用户拒绝"-- // 服务器可以据此走默认值路径,而不是中止操作. type NoopElicitationHandler struct{} // HandleElicitation 永远返回 cancel(无 UI 消费层的通用兜底). func (NoopElicitationHandler) HandleElicitation(_ ElicitationRequest) (ElicitationResponse, error) { return ElicitationResponse{Action: "cancel"}, nil }