23namespace mcp::client {
27inline core::Error adapter_error(std::string_view message) {
28 return errors::make(protocol::ErrorCode::InvalidRequest, std::string(message),
45 : transport_(&transport) {}
48 std::unique_ptr<mcp::client::Transport> transport)
49 : owned_(std::move(transport)), transport_(owned_.get()) {}
55 : owned_(std::move(other.owned_)),
56 transport_(owned_ ? owned_.get() : other.transport_),
57 received_(std::move(other.received_)) {
58 other.transport_ =
nullptr;
64 owned_ = std::move(other.owned_);
65 transport_ = owned_ ? owned_.get() : other.transport_;
66 received_ = std::move(other.received_);
67 other.transport_ =
nullptr;
72 std::string_view
name() const noexcept
override {
73 return "client-transport-adapter";
77 if (transport_ ==
nullptr) {
78 return mcp::core::unexpected(
79 detail::adapter_error(
"client transport is null"));
82 if (
const auto* request = std::get_if<protocol::JsonRpcRequest>(&message)) {
83 auto response = transport_->
send(*request);
85 return mcp::core::unexpected(response.error());
87 received_.push_back(std::move(*response));
91 if (
const auto* notification =
92 std::get_if<protocol::JsonRpcNotification>(&message)) {
97 "client transport adapter cannot send responses"));
101 if (received_.empty()) {
104 auto message = std::move(received_.front());
105 received_.pop_front();
110 if (transport_ !=
nullptr) {
117 std::unique_ptr<mcp::client::Transport> owned_;
119 std::deque<RxMessage> received_;
133 : transport_(&transport) {}
136 std::unique_ptr<transport::ClientTransport> transport)
137 : owned_(std::move(transport)), transport_(owned_.get()) {}
143 : owned_(std::move(other.owned_)),
144 transport_(owned_ ? owned_.get() : other.transport_),
145 request_handler_(std::move(other.request_handler_)),
146 notification_handler_(std::move(other.notification_handler_)) {
147 other.transport_ =
nullptr;
152 if (
this != &other) {
153 owned_ = std::move(other.owned_);
154 transport_ = owned_ ? owned_.get() : other.transport_;
155 request_handler_ = std::move(other.request_handler_);
156 notification_handler_ = std::move(other.notification_handler_);
157 other.transport_ =
nullptr;
164 if (transport_ ==
nullptr) {
165 return mcp::core::unexpected(
166 detail::adapter_error(
"client contract transport is null"));
171 return mcp::core::unexpected(sent.error());
175 auto received = transport_->
receive();
177 return mcp::core::unexpected(received.error());
179 if (!received->has_value()) {
180 return mcp::core::unexpected(detail::adapter_error(
181 "client contract transport closed before response"));
185 std::get_if<protocol::JsonRpcResponse>(&received->value())) {
186 if (response->id.has_value() && *response->id == request.
id) {
189 return mcp::core::unexpected(detail::adapter_error(
190 "client contract transport received unexpected response id"));
193 if (
auto* notification =
194 std::get_if<protocol::JsonRpcNotification>(&received->value())) {
195 const auto handled = handle_notification(*notification);
197 return mcp::core::unexpected(handled.error());
202 if (
auto* inbound_request =
203 std::get_if<protocol::JsonRpcRequest>(&received->value())) {
204 const auto handled = handle_request(*inbound_request);
206 return mcp::core::unexpected(handled.error());
215 if (transport_ ==
nullptr) {
216 return mcp::core::unexpected(
217 detail::adapter_error(
"client contract transport is null"));
225 request_handler_ = std::move(request_handler);
226 notification_handler_ = std::move(notification_handler);
230 void stop() noexcept
override {
231 if (transport_ !=
nullptr) {
232 (void)transport_->
close();
239 if (!notification_handler_) {
243 return notification_handler_(notification);
244 }
catch (
const std::exception& ex) {
251 core::Result<core::Unit> handle_request(
252 const protocol::JsonRpcRequest& request) {
253 protocol::JsonRpcResponse response;
254 if (request_handler_) {
256 auto handled = request_handler_(request);
258 response = protocol::make_error_response(
259 request.id, error_object_from_core_error(handled.error()));
261 response = std::move(*handled);
263 }
catch (
const std::exception& ex) {
264 response = protocol::make_error_response(
266 error_object_from_core_error(errors::handler_failed(ex.what())));
268 response = protocol::make_error_response(
270 error_object_from_core_error(errors::handler_unknown_exception()));
273 response = protocol::make_error_response(
275 protocol::make_error(protocol::ErrorCode::MethodNotFound,
276 "client request handler is not set"));
279 auto sent = transport_->
send(protocol::JsonRpcMessage{std::move(response)});
286 static protocol::ErrorObject error_object_from_core_error(
287 const core::Error& error) {
288 return errors::to_json_rpc_error(error);
291 std::unique_ptr<transport::ClientTransport> owned_;
292 transport::ClientTransport* transport_ =
nullptr;
Adapts a transport::ClientTransport to the existing client::Transport API.
Definition transport_adapter.hpp:130
void stop() noexcept override
Requests transport shutdown.
Definition transport_adapter.hpp:230
core::Result< core::Unit > send_notification(const protocol::JsonRpcNotification ¬ification) override
Sends a JSON-RPC notification without waiting for a response.
Definition transport_adapter.hpp:213
core::Result< protocol::JsonRpcResponse > send(const protocol::JsonRpcRequest &request) override
Sends a JSON-RPC request and waits for the corresponding response.
Definition transport_adapter.hpp:162
core::Result< core::Unit > start(TransportRequestHandler request_handler, TransportNotificationHandler notification_handler={}) override
Starts receiving inbound messages for transports that need an active loop.
Definition transport_adapter.hpp:222
Adapts an existing client::Transport to transport::ClientTransport.
Definition transport_adapter.hpp:42
core::Result< core::Unit > close() override
Closes the transport and unblocks receive() where possible.
Definition transport_adapter.hpp:109
core::Result< std::optional< RxMessage > > receive() override
Receives the next JSON-RPC message from the peer.
Definition transport_adapter.hpp:100
std::string_view name() const noexcept override
Human-readable transport name for diagnostics.
Definition transport_adapter.hpp:72
Abstract client transport used by Client to exchange JSON-RPC messages.
Definition client.hpp:83
virtual core::Result< core::Unit > send_notification(const protocol::JsonRpcNotification ¬ification)
Sends a JSON-RPC notification without waiting for a response.
virtual core::Result< protocol::JsonRpcResponse > send(const protocol::JsonRpcRequest &request)=0
Sends a JSON-RPC request and waits for the corresponding response.
virtual void stop() noexcept
Requests transport shutdown.
Definition client.hpp:120
Minimal message-level transport contract shared by MCP roles.
Definition transport.hpp:38
virtual core::Result< std::optional< RxMessage > > receive()=0
Receives the next JSON-RPC message from the peer.
virtual core::Result< core::Unit > send(TxMessage message)=0
Sends one JSON-RPC message to the peer.
virtual core::Result< core::Unit > close()=0
Closes the transport and unblocks receive() where possible.
Core client compatibility API and transport interface for MCP clients.
std::function< core::Result< core::Unit >(const protocol::JsonRpcNotification &)> TransportNotificationHandler
Handles JSON-RPC notifications sent by the server to this client.
Definition client.hpp:75
std::function< core::Result< protocol::JsonRpcResponse >(const protocol::JsonRpcRequest &)> TransportRequestHandler
Handles JSON-RPC requests sent by the server to this client.
Definition client.hpp:68
Stable public error helpers for SDK request and dispatch paths.
std::variant< JsonRpcRequest, JsonRpcResponse, JsonRpcNotification > JsonRpcMessage
Variant over the JSON-RPC message shapes accepted by MCP transports.
Definition types.hpp:148
std::monostate Unit
Success value for operations that only need to report failure.
Definition result.hpp:55
tl::expected< T, Error > Result
Alias for the SDK result type.
Definition result.hpp:64
constexpr auto unexpected(E &&value)
Creates an unexpected result value for the active expected backend.
Definition result.hpp:24
JSON-RPC method names and message construction/parsing helpers.
JSON-RPC notification envelope for one-way MCP messages.
Definition types.hpp:137
JSON-RPC request envelope carrying an MCP method invocation.
Definition types.hpp:99
RequestId id
Request id that must be echoed by the response.
Definition types.hpp:105
Role-generic MCP transport contract for SDK peer/service layers.