github / github/copilot-sdk

Rust: ergonomic SamplingHandler + typed MCP sampling request on sampling.requested

未关闭
#1,942 1 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

enhancement wishlist
主要语言
Java
星标
10.5k
派生
1.5k
平均合并
1 天 14 小时
30 天内合并 PR
129

描述

## Summary

The Rust binding exposes MCP **sampling** on the wire — the `sampling.requested` / `sampling.completed` events and the `handle_pending_sampling` (and `execute_sampling` / `cancel_sampling_execution`) methods — but there are two gaps for a consumer that wants to **service MCP sampling requests itself** (i.e. answer an MCP server's `sampling/createMessage` with its own model):

1. **The request content isn't on the typed event.** `SamplingRequestedData` carries only `{ requestId, serverName, mcpRequestId }` — not the MCP `CreateMessageRequest` params (the `messages`, `modelPreferences`, `systemPrompt`, `maxTokens`, etc.) that a handler needs to actually produce a completion. So a consumer receives "a sampling request happened" but not *what to sample*.
2. **There's no ergonomic handler.** Every other consumer-serviced request has a first-class handler trait (`PermissionHandler`, `ElicitationHandler`, `McpAuthHandler`, `UserInputHandler`, …) wired on the session builder. Sampling has none — a consumer must subscribe to the raw `sampling.requested` event and call the low-level, Experimental `handle_pending_sampling` by hand.

## Current state (public Rust binding)

- `rust/src/generated/session_events.rs`:
```rust
pub struct SamplingRequestedData {
pub mcp_request_id: serde_json::Value,
pub request_id: RequestId,
pub server_name: String,
}
pub struct SamplingCompletedData { pub request_id: RequestId }
```
No sampling request params (messages / model preferences) are present.
- `rust/src/generated/rpc.rs`: `handle_pending_sampling(UIHandlePendingSamplingRequest) -> UIHandlePendingResult`, `execute_sampling(...)`, `cancel_sampling_execution(...)` — all marked **Experimental**.
- `rust/src/handler.rs`: ergonomic handler traits exist for permission, elicitation, MCP auth, user input, exit-plan-mode, auto-mode-switch — **but not sampling**.
- `rust/src/session.rs`: those handlers are wired on the builder (e.g. `mcp_auth_handler`); there is no sampling equivalent.

## Why this is needed

This is a developer-experience / completeness improvement for consumers that want to fulfill MCP sampling requests with their own inference instead of the default behavior. Today such a consumer:

- can't get the request content from the typed event (has to reach past `SamplingRequestedData`), and
- has to hand-wire the raw event + Experimental RPC instead of implementing one trait.

It is not a capability blocker (the low-level RPCs exist), so this is a quality-of-life ask, not urgent.

## Proposed change

1. **Expose the MCP sampling request params on `SamplingRequestedData`** as a typed field (the `CreateMessageRequest` params: `messages`, `modelPreferences`, `systemPrompt`, `includeContext`, `maxTokens`, `temperature`, `stopSequences`, `metadata`), so a handler can read what to sample directly from the event.
2. **Add an ergonomic `SamplingHandler` trait** in `rust/src/handler.rs` mirroring `McpAuthHandler`:
```rust
#[async_trait]
pub trait SamplingHandler: Send + Sync + 'static {
async fn handle(
&self,
session_id: SessionId,
request_id: RequestId,
request: SamplingRequest, // typed CreateMessageRequest params
) -> SamplingResult; // completion, or None/err to reject
}
```
Wire it on the session builder alongside the other handlers, and have the binding translate the trait's result into the existing `handle_pending_sampling` call (and reject/cancel when the handler declines), so consumers never touch the raw event or the Experimental RPC directly.

## Acceptance criteria

- A consumer can register one `SamplingHandler` on the session builder and receive the typed MCP sampling request (messages + model preferences), returning a completion or a rejection.
- The sampling request params are available as typed data (not only reachable via the untyped/low-level path).
- The existing low-level `handle_pending_sampling` / `execute_sampling` methods continue to work for consumers that prefer them.

## References

- `rust/src/handler.rs` — existing handler-trait pattern (`McpAuthHandler` et al.) to mirror.
- `rust/src/generated/session_events.rs` — `SamplingRequestedData` / `SamplingCompletedData`.
- `rust/src/generated/rpc.rs` — `handle_pending_sampling`, `execute_sampling`, `cancel_sampling_execution`.
- MCP spec — `sampling/createMessage` and its `CreateMessageRequest` params.

贡献指南

打开贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

调研方向

从 rust/src/generated/session_events.rs 和 rust/src/handler.rs 开始,将 SamplingRequestedData 与现有的 handler traits 进行比较。然后跟踪 rust/src/session.rs 中的 session-builder wiring,以及 rust/src/generated/rpc.rs 中的 sampling RPCs。当一个 typed sampling request 和已注册的 SamplingHandler 能够协同工作,同时现有的 low-level methods 仍可使用时,即表示完成。

由索引模型根据 Issue 内容生成。

评估

技术栈
rust
领域
api, developer-experience
Issue 类型
功能
难度
4/5
预计耗时
3-5 天
活跃度
活跃
描述清晰度
基本清楚
新手友好度
52/100

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。