feat(mcp): Add sampling capabilities to MCP server

Implement client-side sampling features in the Model Context Protocol (MCP) server:
- Add createMessage method to McpAsyncServer and McpSyncServer for LLM sampling
- Move MockMcpTransport to separate file for reusability
- Add integration tests for sampling functionality
- Test error handling for uninitialized clients and missing capabilities

The sampling implementation allows servers to request LLM completions from
clients while maintaining client-side control over model access and permissions.

Resolves #42
This commit is contained in:
Christian Tzolov 2025-01-02 15:45:17 +01:00
commit 07769a651d
2 changed files with 331 additions and 153 deletions

View file

@ -603,4 +603,41 @@ public class McpAsyncServer {
};
}
// ---------------------------------------
// Sampling
// ---------------------------------------
private static TypeReference<McpSchema.CreateMessageResult> CREATE_MESSAGE_RESULT_TYPE_REF = new TypeReference<>() {
};
/**
* Create a new message using the sampling capabilities of the client. The Model
* Context Protocol (MCP) provides a standardized way for servers to request LLM
* sampling (“completions” or “generations”) from language models via clients. This
* flow allows clients to maintain control over model access, selection, and
* permissions while enabling servers to leverage AI capabilities—with no server API
* keys necessary. Servers can request text or image-based interactions and optionally
* include context from MCP servers in their prompts.
* @param createMessageRequest The request to create a new message
* @return A Mono that completes when the message has been created
* @throws McpError if the client has not been initialized or does not support
* sampling capabilities
* @throws McpError if the client does not support the createMessage method
* @see McpSchema.CreateMessageRequest
* @see McpSchema.CreateMessageResult
* @see <a href=
* "https://spec.modelcontextprotocol.io/specification/client/sampling/">Sampling
* Specification</a>
*/
public Mono<McpSchema.CreateMessageResult> createMessage(McpSchema.CreateMessageRequest createMessageRequest) {
if (this.clientCapabilities == null) {
return Mono.error(new McpError("Client must be initialized. Call the initialize method first!"));
}
if (this.clientCapabilities.sampling() == null) {
return Mono.error(new McpError("Client must be configured with sampling capabilities"));
}
return this.mcpSession.sendRequest(McpSchema.METHOD_SAMPLING_CREATE_MESSAGE, createMessageRequest,
CREATE_MESSAGE_RESULT_TYPE_REF);
}
}

View file

@ -178,4 +178,27 @@ public class McpSyncServer {
return this.asyncServer;
}
/**
* Create a new message using the sampling capabilities of the client. The Model
* Context Protocol (MCP) provides a standardized way for servers to request LLM
* sampling (“completions” or “generations”) from language models via clients. This
* flow allows clients to maintain control over model access, selection, and
* permissions while enabling servers to leverage AI capabilities—with no server API
* keys necessary. Servers can request text or image-based interactions and optionally
* include context from MCP servers in their prompts.
* @param createMessageRequest The request to create a new message
* @return A Mono that completes when the message has been created
* @throws McpError if the client has not been initialized or does not support
* sampling capabilities
* @throws McpError if the client does not support the createMessage method
* @see McpSchema.CreateMessageRequest
* @see McpSchema.CreateMessageResult
* @see <a href=
* "https://spec.modelcontextprotocol.io/specification/client/sampling/">Sampling
* Specification</a>
*/
public McpSchema.CreateMessageResult createMessage(McpSchema.CreateMessageRequest createMessageRequest) {
return this.asyncServer.createMessage(createMessageRequest).block();
}
}