28#include <condition_variable>
43 mutable std::mutex mutex;
44 std::mutex join_mutex;
45 std::condition_variable cv;
49 std::optional<core::Error> failure;
52inline bool service_running(
53 const std::shared_ptr<ServiceLifecycleState>& state)
noexcept {
57 std::lock_guard lock(state->mutex);
58 return state->running;
61inline CancellationToken service_cancellation_token(
62 const std::shared_ptr<ServiceLifecycleState>& state)
noexcept {
63 return state ? state->cancellation.token() : CancellationToken{};
67inline core::Result<core::Unit> stop_service(
68 const std::shared_ptr<ServiceLifecycleState>& state, Stop stop)
noexcept {
74 std::unique_lock lock(state->mutex);
75 if (!state->running) {
79 state->cv.wait(lock, [&] {
return !state->running; });
82 state->closing =
true;
83 state->cancellation.cancel();
89 std::lock_guard lock(state->mutex);
90 state->running =
false;
91 state->closing =
false;
93 state->cv.notify_all();
97inline core::Result<core::Unit> wait_service(
98 const std::shared_ptr<ServiceLifecycleState>& state)
noexcept {
102 std::unique_lock lock(state->mutex);
103 state->cv.wait(lock, [&] {
return !state->running; });
107inline void finish_service(
const std::shared_ptr<ServiceLifecycleState>& state,
108 std::optional<core::Error> failure = {})
noexcept {
113 std::lock_guard lock(state->mutex);
114 state->running =
false;
115 state->closing =
false;
116 state->failure = std::move(failure);
118 state->cv.notify_all();
136 : peer_(std::make_shared<ClientPeer>(std::move(peer))) {
143 : peer_(std::move(other.peer_)),
144 state_(std::move(other.state_)),
145 loop_(std::move(other.loop_)) {}
147 if (
this != &other) {
149 peer_ = std::move(other.peer_);
150 state_ = std::move(other.state_);
151 loop_ = std::move(other.loop_);
158 ClientPeer& peer()
noexcept {
return *peer_; }
160 const ClientPeer& peer()
const noexcept {
return *peer_; }
162 bool running()
const noexcept {
return detail::service_running(state_); }
166 return detail::service_cancellation_token(state_);
176 const auto waited = detail::wait_service(state_);
179 return mcp::core::unexpected(waited.error());
182 std::lock_guard lock(state_->mutex);
183 if (state_->failure.has_value()) {
184 return mcp::core::unexpected(*state_->failure);
195 std::unique_lock lock(state_->mutex);
196 if (!state_->running) {
200 if (state_->closing) {
204 state_->closing =
true;
205 state_->cancellation.cancel();
210 if (!peer_ || !peer_->uses_native_transport()) {
211 detail::finish_service(state_);
219 detail::finish_service(state_);
222 if (!peer_->uses_native_transport()) {
223 const auto started = peer_->start(state_->cancellation.token());
225 detail::finish_service(state_, started.error());
232 auto cancellation = state_->cancellation.token();
233 loop_ = std::thread([state, peer, cancellation]()
noexcept {
234 const auto started = peer->start(cancellation);
236 detail::finish_service(state, started.error());
238 detail::finish_service(state);
243 void join_loop() noexcept {
247 std::lock_guard lock(state_->join_mutex);
248 if (loop_.joinable() && loop_.get_id() != std::this_thread::get_id()) {
253 std::shared_ptr<ClientPeer> peer_;
254 std::shared_ptr<detail::ServiceLifecycleState> state_ =
255 std::make_shared<detail::ServiceLifecycleState>();
264 : peer_(std::make_shared<ServerPeer>(std::move(peer))) {
269 std::unique_ptr<transport::ServerTransport> transport,
271 : peer_(std::make_shared<ServerPeer>(std::move(peer))),
272 transport_(std::move(transport)),
273 context_(std::move(context)) {
280 : peer_(std::move(other.peer_)),
281 transport_(std::move(other.transport_)),
282 context_(std::move(other.context_)),
283 state_(std::move(other.state_)),
284 loop_(std::move(other.loop_)) {}
286 if (
this != &other) {
288 peer_ = std::move(other.peer_);
289 transport_ = std::move(other.transport_);
290 context_ = std::move(other.context_);
291 state_ = std::move(other.state_);
292 loop_ = std::move(other.loop_);
299 ServerPeer& peer()
noexcept {
return *peer_; }
301 const ServerPeer& peer()
const noexcept {
return *peer_; }
309 peer_->wait_until_ready();
313 bool running() const noexcept {
return detail::service_running(state_); }
317 return detail::service_cancellation_token(state_);
327 const auto waited = detail::wait_service(state_);
330 return mcp::core::unexpected(waited.error());
333 std::lock_guard lock(state_->mutex);
334 if (state_->failure.has_value()) {
335 return mcp::core::unexpected(*state_->failure);
346 std::unique_lock lock(state_->mutex);
347 if (!state_->running) {
351 if (state_->closing) {
355 state_->closing =
true;
356 state_->cancellation.cancel();
359 (void)transport_->close();
371 auto transport = transport_;
372 auto context = context_;
373 auto cancellation = state_->cancellation.token();
375 std::thread([state, peer, transport, context, cancellation]()
noexcept {
379 : peer->start(cancellation);
381 detail::finish_service(state, started.error());
383 detail::finish_service(state);
388 void join_loop() noexcept {
392 std::lock_guard lock(state_->join_mutex);
393 if (loop_.joinable() && loop_.get_id() != std::this_thread::get_id()) {
398 std::shared_ptr<ServerPeer> peer_;
399 std::shared_ptr<transport::ServerTransport> transport_;
400 server::SessionContext context_;
401 std::shared_ptr<detail::ServiceLifecycleState> state_ =
402 std::make_shared<detail::ServiceLifecycleState>();
414 const ClientPeer& peer()
const noexcept {
return peer_; }
431 std::unique_ptr<transport::ServerTransport> transport,
433 : peer_(std::move(peer)),
434 transport_(std::move(transport)),
435 context_(std::move(context)) {}
439 const ServerPeer& peer()
const noexcept {
return peer_; }
444 std::move(context_));
451 std::unique_ptr<transport::ServerTransport> transport_;
467 ServerPeer peer, std::unique_ptr<transport::ServerTransport> transport,
469 return Service<RoleServer>(std::move(peer), std::move(transport),
485 ServerPeer peer, std::unique_ptr<transport::ServerTransport> transport,
487 return make_service(std::move(peer), std::move(transport), std::move(context))
496 auto running =
serve(std::move(*peer));
500 return running->wait().has_value() ? 0 : 1;
514 (void)running->stop();
Cooperative cancellation primitives shared by SDK lifecycle APIs.
Owner side of a cooperative cancellation token.
Definition cancellation.hpp:212
Copyable token observed by cancellation-aware SDK operations.
Definition cancellation.hpp:104
Client-side peer boundary for talking to an MCP server.
Definition peer.hpp:319
Server-side peer boundary for exposing MCP capabilities.
Definition peer.hpp:2995
core::Result< core::Unit > serve_transport(transport::ServerTransport &transport, const server::SessionContext &context={}, CancellationToken cancellation=CancellationToken::none())
Runs a sequential receive loop over a role-generic server transport.
Definition peer.hpp:3898
Role-specialized MCP peer boundary.
Definition peer.hpp:310
core::Result< core::Unit > wait() noexcept
Waits for service shutdown.
Definition service.hpp:175
CancellationToken cancellation_token() const noexcept
Returns the service cancellation token.
Definition service.hpp:165
core::Result< core::Unit > close() noexcept
Explicitly closes the running service.
Definition service.hpp:170
void wait_until_ready()
Blocks until the server is ready to accept connections.
Definition service.hpp:307
core::Result< core::Unit > wait() noexcept
Waits for service shutdown.
Definition service.hpp:326
CancellationToken cancellation_token() const noexcept
Returns the service cancellation token.
Definition service.hpp:316
core::Result< core::Unit > close() noexcept
Explicitly closes the running service.
Definition service.hpp:321
Role-specialized running MCP service.
Definition service.hpp:129
Role-specialized MCP service before it is running.
Definition service.hpp:125
Role-aware peer execution boundaries for MCP client and server SDK users.
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
core::Result< RunningService< RoleClient > > serve(ClientPeer peer)
Starts a client service and returns its running handle.
Definition service.hpp:474
Service< RoleClient > make_service(ClientPeer peer)
Creates a client service from a role-aware peer.
Definition service.hpp:456
Marker for a client-side MCP role.
Definition roles.hpp:11
Marker for a server-side MCP role.
Definition roles.hpp:14
Definition service.hpp:42
Per-message connection metadata supplied to server handlers.
Definition transport.hpp:42