Skip to content

Commit 0797ad5

Browse files
author
polaon
committed
Streamable HTTP server wrapper fixes.
1 parent 88dca2f commit 0797ad5

1 file changed

Lines changed: 34 additions & 4 deletions

File tree

src/server/streamable_http_server.cpp

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,8 @@ bool StreamableHttpServerWrapper::start()
117117
svr_->Options(mcp_path_,
118118
[this](const httplib::Request&, httplib::Response& res)
119119
{
120-
res.set_header("Access-Control-Allow-Methods", "POST, OPTIONS");
120+
res.set_header("Access-Control-Allow-Methods",
121+
"GET, POST, DELETE, OPTIONS");
121122
res.set_header("Access-Control-Allow-Headers",
122123
"Content-Type, Authorization, Mcp-Session-Id");
123124
apply_additional_response_headers(res);
@@ -129,6 +130,11 @@ bool StreamableHttpServerWrapper::start()
129130
mcp_path_,
130131
[this](const httplib::Request& req, httplib::Response& res)
131132
{
133+
// Apply CORS / additional headers up-front so they are present on every
134+
// response, including early returns (401, 503, 400, 404) and any exception
135+
// propagated to the catch handlers below.
136+
apply_additional_response_headers(res);
137+
132138
try
133139
{
134140
// Security: Check authentication if configured
@@ -143,8 +149,6 @@ bool StreamableHttpServerWrapper::start()
143149
}
144150
}
145151

146-
apply_additional_response_headers(res);
147-
148152
// Parse JSON-RPC message
149153
auto message = fastmcpp::util::json::parse(req.body);
150154

@@ -336,8 +340,13 @@ bool StreamableHttpServerWrapper::start()
336340

337341
// Handle GET request to return 405 Method Not Allowed
338342
svr_->Get(mcp_path_,
339-
[](const httplib::Request&, httplib::Response& res)
343+
[this](const httplib::Request&, httplib::Response& res)
340344
{
345+
// CORS / additional headers must be applied on every response, including
346+
// this 405. Without this, browsers reject the response with a misleading
347+
// "No 'Access-Control-Allow-Origin' header is present" error.
348+
apply_additional_response_headers(res);
349+
341350
res.status = 405;
342351
res.set_header("Allow", "POST");
343352
res.set_header("Content-Type", "application/json");
@@ -349,6 +358,27 @@ bool StreamableHttpServerWrapper::start()
349358
res.set_content(error_response.dump(), "application/json");
350359
});
351360

361+
// Handle DELETE request for session termination (MCP Streamable HTTP spec).
362+
// Without this handler, httplib would fall back to its default 404 response,
363+
// which does not carry the configured CORS headers - causing browsers to report
364+
// a "No 'Access-Control-Allow-Origin' header is present" error.
365+
svr_->Delete(mcp_path_,
366+
[this](const httplib::Request& req, httplib::Response& res)
367+
{
368+
apply_additional_response_headers(res);
369+
370+
// If an Mcp-Session-Id header is provided, terminate that session.
371+
auto session_it = req.headers.find("Mcp-Session-Id");
372+
if (session_it != req.headers.end())
373+
{
374+
const std::string& session_id = session_it->second;
375+
std::lock_guard<std::mutex> lock(sessions_mutex_);
376+
sessions_.erase(session_id);
377+
}
378+
379+
res.status = 204; // No Content
380+
});
381+
352382
running_ = true;
353383

354384
thread_ = std::thread([this]() { run_server(); });

0 commit comments

Comments
 (0)