Summary Add support for tool use within sampling requests, as described in the MCP 2025-11-25 spec's sampling.tools capability. New types Content types: - ToolUseContent — represents a tool invocation request from the assistant - ToolResultContent — represents the result of a tool invocation, with nested []Content for the result blocks Capability types: - SamplingCapabilities gains Tools and Context sub-fields - SamplingToolsCapabilities, SamplingContextCapabilities Tool-enabled sampling (parallel tool calls): - CreateMessageWithToolsParams with SamplingMessageV2 (supports array content) - CreateMessageWithToolsResult (supports array content) - ToolChoice — controls tool invocation mode (auto, required, none) - ServerSession.CreateMessageWithTools - ClientOptions.CreateMessageWithToolsHandler Design Following the TypeScript SDK's pattern, tool-enabled sampling uses separate types from basic sampling to avoid breaking the existing API. The basic CreateMessage/CreateMessageResult path is unchanged. Both paths share the same wire method (sampling/createMessage) and go through the method info table. The table uses the broader CreateMessageWithToolsResult type internally; CreateMessage downconverts (erroring if multiple content blocks are returned). This is documented as a rough edge to unify in v2. Setting CreateMessageWithToolsHandler automatically infers the sampling.tools capability. It is a panic to set both CreateMessageHandler and CreateMessageWithToolsHandler. References - https://modelcontextprotocol.io/specification/2025-11-25/client/sampling - TypeScript SDK: CreateMessageResultWithToolsSchema / CreateMessageRequestParamsWithTools --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2.9 KiB
Rough edges: API decisions to reconsider for v2
This file collects a list of API oversights or rough edges that we've uncovered post v1.0.0, along with their current workarounds. These issues can't be addressed without breaking backward compatibility, but we'll revisit them for v2.
-
EventStore.Openis unnecessary. This was an artifact of an earlier version of the SDK where event persistence and delivery were combined.Workaround:
Openmay be implemented as a no-op. -
Eventneed not have been exported: it's an implementation detail of the SSE and streamable transports. Also the 'Name' field is a misnomer: it should be 'event'. -
Enforcing valid tool names: with SEP-986 landing after the SDK was at v1, we missed an opportunity to panic on invalid tool names. Instead, we have to simply produce an error log. In v2, we should panic.
-
Inconsistent naming.
ResourceUpdatedNotificationsParamsshould probably have just beenResourceUpdatedParams, as we don't include the word 'notification' in other notification param types.- Similarly,
ProgressNotificationParamsshould probably have beenProgressParams.
-
AudioContent.MarshalJSONshould have had a pointer receiver, to be consistent with other content types. -
ClientCapabilities.Rootsshould have been a distinguished struct pointer (see #607).Workaround: use
ClientCapabilities.RootsV2, which aligns with the semantics of other capability fields. -
Default capabilities should have been empty. Instead, servers default to advertising
logging, and clients default to advertisingrootswithlistChanged: true. This is confusing because a nilCapabilitiesfield does not mean "no capabilities".Workaround: to advertise no capabilities, set
ServerOptions.CapabilitiesorClientOptions.Capabilitiesto an empty&ServerCapabilities{}or&ClientCapabilities{}respectively. -
CreateMessageResult.Contentis singularContent, but the 2025-11-25 spec allowscontentto be a single block or an array (for parallel tool calls). We addedCreateMessageResultWithTools(withContent []Content) as a workaround, matching the TypeScript SDK's approach. In v2,CreateMessageResultshould use[]Contentdirectly. Similarly,SamplingMessage.Contentshould become[]Contentto support sending multiple tool_result blocks in a single user message. -
We didn't actually need CallToolParams and CallToolParamsRaw, since even when we're unmarshalling into a custom Go type (for the mcp.AddTool convenience wrapper) we need to first unmarshal into a
map[string]anyin order to do server-side validation of required fields. CallToolParams could have just had a map[string]any.