cxxmcp 1.1.6
C++ MCP SDK
Loading...
Searching...
No Matches
http_transport.hpp
Go to the documentation of this file.
1// Copyright (c) 2025 [caomengxuan666]
2
3#pragma once
4
5#include <chrono>
6#include <condition_variable>
7#include <cstddef>
8#include <cstdint>
9#include <deque>
10#include <memory>
11#include <mutex>
12#include <optional>
13#include <string>
14#include <string_view>
15#include <unordered_map>
16#include <vector>
17
18#if defined(CXXMCP_ENABLE_AUTH)
20#endif
21
23
26
27namespace mcp::server {
28
37 std::string resource;
39 std::vector<std::string> authorization_servers;
41 std::vector<std::string> scopes_supported;
43 std::optional<std::string> resource_name;
45 std::optional<std::string> resource_documentation;
46};
47
51 std::string scheme = "Bearer";
54 std::optional<std::string> resource_metadata_url;
57 std::optional<std::string> scope;
58};
59
63 std::string listen_host = "127.0.0.1";
65 int listen_port = 0;
67 std::string path = "/mcp";
69 std::optional<std::chrono::milliseconds> sse_retry;
73 bool enable_sse_polling = false;
76 std::chrono::milliseconds sse_disconnect_retry{5000};
78 std::vector<std::string> allowed_origins;
81 std::vector<std::string> allowed_hosts = {"localhost", "127.0.0.1", "::1"};
83 std::size_t max_pending_sse_events = 1024;
85 std::size_t max_pending_sse_bytes = 4 * 1024 * 1024;
87 std::size_t max_sse_replay_events = 256;
90 std::chrono::milliseconds request_timeout{30000};
93 std::size_t max_request_body_bytes = 10 * 1024 * 1024;
95 std::chrono::milliseconds read_timeout{30000};
97 std::chrono::milliseconds write_timeout{30000};
100 std::size_t max_sessions = 1024;
104 bool stateless = false;
109 std::string auth_challenge = std::string(DefaultAuthChallenge);
117#if defined(CXXMCP_ENABLE_AUTH)
120 ::mcp::auth::AuthorizationServerConfig authorization_server;
121#endif
122};
123
155class HttpTransport final : public Transport {
156 public:
160
162 ~HttpTransport() override;
163
164 HttpTransport(const HttpTransport&) = delete;
165 HttpTransport& operator=(const HttpTransport&) = delete;
166
176 RequestHandler handler,
177 NotificationHandler notification_handler = {}) override;
178
185 const protocol::JsonRpcRequest& request) override;
186
189 std::string_view session_id,
190 const protocol::JsonRpcRequest& request) override;
191
193 std::optional<protocol::ClientCapabilities> client_capabilities()
194 const override;
195
197 std::optional<protocol::ClientCapabilities> client_capabilities_for_session(
198 std::string_view session_id) const override;
199
205 const protocol::JsonRpcNotification& notification) override;
206
209 std::string_view session_id,
210 const protocol::JsonRpcNotification& notification) override;
211
213 void stop() noexcept override;
214
221 void disconnect_session_sse(std::string_view session_id);
222
224 std::string_view name() const noexcept override;
225
227 void wait_until_ready() override;
228
229 private:
230 struct HttpServerHolder;
231
232 struct PendingRequest {
233 std::mutex mutex;
234 std::condition_variable cv;
235 bool ready = false;
236 std::optional<protocol::JsonRpcResponse> response;
237 std::optional<core::Error> error;
238 };
239
240 struct QueuedEvent {
241 std::optional<std::uint64_t> event_id;
242 std::string payload;
243 };
244
245 struct ProgressResponseSink {
246 std::mutex mutex;
247 std::condition_variable cv;
248 std::deque<std::string> events;
249 bool done = false;
250 };
251
252 struct SessionState {
253 std::string session_id;
254 bool initialized = false;
255 std::optional<protocol::ClientCapabilities> client_capabilities;
256 std::deque<QueuedEvent> pending_notifications;
257 std::size_t pending_notification_bytes = 0;
258 std::deque<QueuedEvent> replay_notifications;
259 std::unordered_map<std::string, std::shared_ptr<PendingRequest>>
260 pending_requests;
261 std::uint64_t next_notification_event_id = 1;
262 std::size_t active_sse_streams = 0;
263 bool sse_disconnect_requested = false;
264 std::shared_ptr<ProgressResponseSink> active_progress_sink;
265 };
266
267 void abort_pending_requests_locked(SessionState& session,
268 std::string message);
269 void clear_outbound_events_locked(SessionState& session);
270 core::Result<core::Unit> enqueue_outbound_event_locked(SessionState& session,
271 QueuedEvent event);
272 void remember_replay_event_locked(SessionState& session,
273 const QueuedEvent& event);
274 SessionState* find_session_locked(std::string_view session_id);
275 const SessionState* find_session_locked(std::string_view session_id) const;
276 SessionState* select_default_session_locked();
277 void close_sse_stream(std::string_view session_id) noexcept;
278
279 static std::optional<protocol::ProgressToken> extract_progress_token(
280 const protocol::JsonRpcRequest& request);
281
282 HttpTransportOptions options_;
283 std::unique_ptr<HttpServerHolder> server_;
284 mutable std::mutex mutex_;
285 std::condition_variable notification_cv_;
286 std::condition_variable startup_cv_;
287 std::unordered_map<std::string, SessionState> sessions_;
288 std::uint64_t next_session_id_ = 1;
289 bool stopped_ = false;
290 bool stop_requested_ = false;
291 bool startup_finished_ = false;
292 bool initialized_ = false;
293 std::string default_session_id_;
294};
295
296} // namespace mcp::server
MCP streamable HTTP transport with session-aware SSE delivery.
Definition http_transport.hpp:155
std::string_view name() const noexcept override
Return the diagnostic transport name "http".
std::optional< protocol::ClientCapabilities > client_capabilities_for_session(std::string_view session_id) const override
Return capabilities from a specific initialized HTTP session.
std::optional< protocol::ClientCapabilities > client_capabilities() const override
Return capabilities from the active initialized HTTP session.
core::Result< core::Unit > start(RequestHandler handler, NotificationHandler notification_handler={}) override
Start the HTTP server and serve the configured MCP endpoint.
core::Result< protocol::JsonRpcResponse > send_request(const protocol::JsonRpcRequest &request) override
Queue a server-to-client request on the active SSE stream.
core::Result< protocol::JsonRpcResponse > send_request_to_session(std::string_view session_id, const protocol::JsonRpcRequest &request) override
Queue a server-to-client request for a specific HTTP session.
void stop() noexcept override
Stop the HTTP server and fail pending outbound requests.
void disconnect_session_sse(std::string_view session_id)
Request a server-initiated SSE stream disconnect for a session.
~HttpTransport() override
Destroy the transport and its underlying server state.
void wait_until_ready() override
Blocks until the underlying HTTP server socket is bound.
core::Result< core::Unit > send_notification_to_session(std::string_view session_id, const protocol::JsonRpcNotification &notification) override
Queue an outbound notification for a specific HTTP session.
HttpTransport(HttpTransportOptions options)
Construct a transport with normalized HTTP options.
core::Result< core::Unit > send_notification(const protocol::JsonRpcNotification &notification) override
Queue an outbound notification for the active SSE stream.
Abstract server transport for receiving client JSON-RPC messages.
Definition transport.hpp:99
tl::expected< T, Error > Result
Alias for the SDK result type.
Definition result.hpp:64
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:74
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:84
Abstract interfaces for server-side OAuth 2.1 endpoint handlers.
OAuth authorization server endpoint wiring owned by the auth layer.
Definition server_auth_endpoints.hpp:180
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
Configuration for the HTTP WWW-Authenticate challenge header.
Definition http_transport.hpp:49
std::string scheme
Authentication scheme (default: "Bearer").
Definition http_transport.hpp:51
std::optional< std::string > resource_metadata_url
URL of the RFC 9728 Protected Resource Metadata document.
Definition http_transport.hpp:54
std::optional< std::string > scope
Scopes required to access the resource.
Definition http_transport.hpp:57
Configuration for HttpTransport.
Definition http_transport.hpp:61
ProtectedResourceMetadataConfig protected_resource_metadata
RFC 9728 Protected Resource Metadata.
Definition http_transport.hpp:116
std::size_t max_sse_replay_events
Number of delivered SSE events retained for Last-Event-ID replay.
Definition http_transport.hpp:87
std::chrono::milliseconds read_timeout
Socket read timeout for HTTP request handling.
Definition http_transport.hpp:95
std::vector< std::string > allowed_origins
Optional Origin allow-list. Empty means Origin is not restricted.
Definition http_transport.hpp:78
int listen_port
TCP port to listen on. Must be in the range 1..65535.
Definition http_transport.hpp:65
std::vector< std::string > allowed_hosts
Host allow-list used to reject DNS-rebinding attempts.
Definition http_transport.hpp:81
std::chrono::milliseconds request_timeout
Maximum time to wait for a client response to a server-to-client request.
Definition http_transport.hpp:90
std::size_t max_pending_sse_events
Maximum server-to-client events waiting for an SSE stream.
Definition http_transport.hpp:83
std::size_t max_sessions
Maximum active HTTP sessions accepted by this transport.
Definition http_transport.hpp:100
std::chrono::milliseconds write_timeout
Socket write timeout for HTTP response handling.
Definition http_transport.hpp:97
bool stateless
Enable stateless MCP mode (SEP-2575).
Definition http_transport.hpp:104
std::size_t max_pending_sse_bytes
Maximum serialized bytes waiting for an SSE stream.
Definition http_transport.hpp:85
std::chrono::milliseconds sse_disconnect_retry
Retry hint (ms) sent to the client before a server-initiated SSE disconnect.
Definition http_transport.hpp:76
bool enable_sse_polling
Enable SEP-1699 SSE polling: always send a priming event with id on SSE streams and allow server-init...
Definition http_transport.hpp:73
std::string path
HTTP path for POST, GET/SSE, and DELETE session requests.
Definition http_transport.hpp:67
AuthChallengeConfig auth_challenge_config
Structured auth challenge configuration.
Definition http_transport.hpp:113
std::size_t max_request_body_bytes
Maximum HTTP request body size accepted by the underlying server.
Definition http_transport.hpp:93
std::string listen_host
Interface address passed to the underlying HTTP server.
Definition http_transport.hpp:63
std::string auth_challenge
HTTP WWW-Authenticate challenge emitted when authentication fails.
Definition http_transport.hpp:109
std::optional< std::chrono::milliseconds > sse_retry
Optional SSE retry interval hint for the priming event.
Definition http_transport.hpp:69
RFC 9728 Protected Resource Metadata configuration for the server.
Definition http_transport.hpp:35
std::vector< std::string > authorization_servers
Authorization server issuers that can issue tokens for this resource.
Definition http_transport.hpp:39
std::vector< std::string > scopes_supported
Scopes that may be requested to access this resource.
Definition http_transport.hpp:41
std::string resource
Resource identifier URL (e.g. "https://example.com/mcp").
Definition http_transport.hpp:37
std::optional< std::string > resource_documentation
URL of human-readable documentation for the resource.
Definition http_transport.hpp:45
std::optional< std::string > resource_name
Human-readable name of the resource.
Definition http_transport.hpp:43