23namespace mcp::server {
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::server::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 transport_ ==
nullptr ?
"server-transport-adapter"
78 if (transport_ ==
nullptr) {
79 return mcp::core::unexpected(
80 detail::adapter_error(
"server transport is null"));
83 if (
const auto* request = std::get_if<protocol::JsonRpcRequest>(&message)) {
86 return mcp::core::unexpected(response.error());
88 received_.push_back(std::move(*response));
92 if (
const auto* notification =
93 std::get_if<protocol::JsonRpcNotification>(&message)) {
98 "server transport adapter cannot send responses"));
102 if (received_.empty()) {
105 auto message = std::move(received_.front());
106 received_.pop_front();
112 if (transport_ !=
nullptr) {
118 if (transport_ !=
nullptr) {
125 std::unique_ptr<mcp::server::Transport> owned_;
127 std::deque<RxMessage> received_;
141 : transport_(&transport) {}
144 std::unique_ptr<transport::ServerTransport> transport)
145 : owned_(std::move(transport)), transport_(owned_.get()) {}
151 : owned_(std::move(other.owned_)),
152 transport_(owned_ ? owned_.get() : other.transport_),
153 request_handler_(std::move(other.request_handler_)),
154 notification_handler_(std::move(other.notification_handler_)),
155 client_capabilities_(std::move(other.client_capabilities_)),
156 stopped_(other.stopped_) {
157 other.transport_ =
nullptr;
158 other.stopped_ =
true;
163 if (
this != &other) {
164 owned_ = std::move(other.owned_);
165 transport_ = owned_ ? owned_.get() : other.transport_;
166 request_handler_ = std::move(other.request_handler_);
167 notification_handler_ = std::move(other.notification_handler_);
168 client_capabilities_ = std::move(other.client_capabilities_);
169 stopped_ = other.stopped_;
170 other.transport_ =
nullptr;
171 other.stopped_ =
true;
179 request_handler_ = std::move(handler);
180 notification_handler_ = std::move(notification_handler);
181 if (transport_ ==
nullptr) {
182 return mcp::core::unexpected(
183 detail::adapter_error(
"server contract transport is null"));
188 auto received = transport_->
receive();
190 return mcp::core::unexpected(received.error());
192 if (!received->has_value()) {
196 const auto handled = handle_inbound(received->value());
206 if (transport_ ==
nullptr) {
207 return mcp::core::unexpected(
208 detail::adapter_error(
"server contract transport is null"));
213 return mcp::core::unexpected(sent.error());
224 if (!routed->has_value()) {
225 return mcp::core::unexpected(detail::adapter_error(
226 "server contract transport closed before response"));
229 std::get_if<protocol::JsonRpcResponse>(&routed->value())) {
230 if (response->id.has_value() && *response->id == request.
id) {
239 auto received = transport_->
receive();
241 return mcp::core::unexpected(received.error());
243 if (!received->has_value()) {
244 return mcp::core::unexpected(detail::adapter_error(
245 "server contract transport closed before response"));
249 std::get_if<protocol::JsonRpcResponse>(&received->value())) {
250 if (response->id.has_value() && *response->id == request.
id) {
253 return mcp::core::unexpected(detail::adapter_error(
254 "server contract transport received unexpected response id"));
257 const auto handled = handle_inbound(received->value());
259 return mcp::core::unexpected(handled.error());
266 if (transport_ ==
nullptr) {
267 return mcp::core::unexpected(
268 detail::adapter_error(
"server contract transport is null"));
275 return client_capabilities_;
280 if (transport_ !=
nullptr) {
285 void stop() noexcept
override {
287 if (transport_ !=
nullptr) {
288 (void)transport_->
close();
292 std::string_view
name() const noexcept
override {
293 return transport_ ==
nullptr ?
"server-contract-transport-adapter"
294 : transport_->
name();
300 if (
auto* request = std::get_if<protocol::JsonRpcRequest>(&message)) {
301 return handle_request(*request);
303 if (
auto* notification =
304 std::get_if<protocol::JsonRpcNotification>(&message)) {
305 return handle_notification(*notification);
310 core::Result<core::Unit> handle_request(
311 const protocol::JsonRpcRequest& request) {
312 protocol::JsonRpcResponse response;
313 if (request_handler_) {
315 auto handled = request_handler_(request, session_context());
317 response = protocol::make_error_response(
318 request.id, error_object_from_core_error(handled.error()));
320 response = std::move(*handled);
322 }
catch (
const std::exception& ex) {
323 response = protocol::make_error_response(
325 error_object_from_core_error(errors::handler_failed(ex.what())));
327 response = protocol::make_error_response(
329 error_object_from_core_error(errors::handler_unknown_exception()));
332 response = protocol::make_error_response(
334 protocol::make_error(protocol::ErrorCode::MethodNotFound,
335 "server request handler is not set"));
338 if (request.method == protocol::InitializeMethod) {
339 if (request.params.is_object() &&
340 request.params.contains(
"capabilities")) {
341 client_capabilities_ = protocol::client_capabilities_from_json(
342 request.params.at(
"capabilities"));
344 client_capabilities_.reset();
348 auto sent = transport_->
send(protocol::JsonRpcMessage{std::move(response)});
355 core::Result<core::Unit> handle_notification(
356 const protocol::JsonRpcNotification& notification) {
357 if (!notification_handler_) {
361 return notification_handler_(notification, session_context());
362 }
catch (
const std::exception& ex) {
369 SessionContext session_context() noexcept {
370 SessionContext context;
371 context.remote_address = std::string(
name());
372 context.transport =
this;
377 static protocol::ErrorObject error_object_from_core_error(
378 const core::Error& error) {
379 return errors::to_json_rpc_error(error);
382 std::unique_ptr<transport::ServerTransport> owned_;
383 transport::ServerTransport* transport_ =
nullptr;
386 std::optional<protocol::ClientCapabilities> client_capabilities_;
387 bool stopped_ =
false;
Adapts a transport::ServerTransport to the existing server::Transport API.
Definition transport_adapter.hpp:138
std::string_view name() const noexcept override
Human-readable transport name for diagnostics.
Definition transport_adapter.hpp:292
core::Result< core::Unit > start(RequestHandler handler, NotificationHandler notification_handler={}) override
Start accepting inbound messages and dispatch them to handlers.
Definition transport_adapter.hpp:176
void stop() noexcept override
Request transport shutdown.
Definition transport_adapter.hpp:285
core::Result< protocol::JsonRpcResponse > send_request(const protocol::JsonRpcRequest &request) override
Send a JSON-RPC request from the server to the connected client.
Definition transport_adapter.hpp:204
core::Result< core::Unit > send_notification(const protocol::JsonRpcNotification ¬ification) override
Send a JSON-RPC notification from the server to the client.
Definition transport_adapter.hpp:264
void publish_subscription_notification(std::string_view method, protocol::Json params) override
Publish a notification to open subscriptions/listen streams (SEP-2575).
Definition transport_adapter.hpp:278
std::optional< protocol::ClientCapabilities > client_capabilities() const override
Return capabilities learned from the client's initialize request.
Definition transport_adapter.hpp:273
Adapts an existing server::Transport to transport::ServerTransport.
Definition transport_adapter.hpp:42
core::Result< core::Unit > close() override
Closes the transport and unblocks receive() where possible.
Definition transport_adapter.hpp:117
void publish_subscription_notification(std::string_view method, protocol::Json params) override
Publishes a notification to active subscription listen streams.
Definition transport_adapter.hpp:110
std::string_view name() const noexcept override
Human-readable transport name for diagnostics.
Definition transport_adapter.hpp:72
core::Result< std::optional< RxMessage > > receive() override
Receives the next JSON-RPC message from the peer.
Definition transport_adapter.hpp:101
Abstract server transport for receiving client JSON-RPC messages.
Definition transport.hpp:154
std::weak_ptr< void > lifetime_token() const noexcept
Weak lifetime token for SessionContext and ClientPeer guards.
Definition transport.hpp:159
virtual void stop() noexcept=0
Request transport shutdown.
virtual core::Result< core::Unit > send_notification(const protocol::JsonRpcNotification ¬ification)=0
Send a JSON-RPC notification from the server to the client.
virtual void publish_subscription_notification(std::string_view method, protocol::Json params)
Publish a notification to open subscriptions/listen streams (SEP-2575).
Definition transport.hpp:249
virtual std::string_view name() const noexcept=0
Human-readable transport name for diagnostics.
virtual core::Result< protocol::JsonRpcResponse > send_request(const protocol::JsonRpcRequest &request)
Send a JSON-RPC request from the server to the connected client.
Definition transport.hpp:179
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< std::optional< RxMessage > > receive_response(const protocol::RequestId &id)
Waits for the response to one specific outbound request.
Definition transport.hpp:84
virtual std::string_view name() const noexcept=0
Human-readable transport name for diagnostics.
virtual core::Result< core::Unit > send(TxMessage message)=0
Sends one JSON-RPC message to the peer.
virtual void publish_subscription_notification(std::string_view method, protocol::Json params)
Publishes a notification to active subscription listen streams.
Definition transport.hpp:98
virtual core::Result< core::Unit > close()=0
Closes the transport and unblocks receive() where possible.
Stable public error helpers for SDK request and dispatch paths.
nlohmann::json Json
JSON value type used by all protocol DTOs.
Definition types.hpp:28
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.
Server-side transport abstraction for MCP JSON-RPC traffic.
std::function< core::Result< protocol::JsonRpcResponse >(const protocol::JsonRpcRequest &, const SessionContext &)> RequestHandler
Callback used by transports to dispatch inbound JSON-RPC requests.
Definition transport.hpp:75
std::function< core::Result< core::Unit >(const protocol::JsonRpcNotification &, const SessionContext &)> NotificationHandler
Callback used by transports to dispatch inbound JSON-RPC notifications.
Definition transport.hpp:139
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.