Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
9b71eed
Change RequestId and ProgressToken to use int64_t instead of int (#121)
Oct 5, 2025
600eca5
Fix constructor initialization order warning in Logger class (#122)
Oct 5, 2025
bb74b90
Add virtual destructor to ConnectionStateMachine class (#122)
Oct 5, 2025
c7caf0f
Fix C++17 compatibility by using std functions directly (#120)
Oct 5, 2025
4065d80
Add missing string header to io_result.h (#122)
Oct 5, 2025
47173d0
Add make_overload helper function for variant visitation (#120)
Oct 5, 2025
3b97c6b
Use compat.h instead of direct optional.h include (#120)
Oct 5, 2025
ea9b890
Change RequestId and ProgressToken to use int64_t instead of int -- m…
Oct 5, 2025
18e944b
make format CPP code to apply clang-format (#122)
Oct 5, 2025
5d9f6ea
Update C API to use int64_t for RequestId and ProgressToken (#121)
Oct 6, 2025
484c41b
Reduce test output verbosity in build script (#122)
Oct 7, 2025
27d5d11
Add format-cpp target for C++ only formatting (#122)
Oct 7, 2025
7c589af
Linux build fix: MCP_SO_ATTACH_REUSEPORT_CBPF declaration order (#122)
Oct 7, 2025
a558fb4
Linux build fix: Remove unused C++17 filesystem include from log_sink…
Oct 7, 2025
490feb4
Linux build fix: Replace designated initializers with field assignmen…
Oct 7, 2025
5343cd4
Linux build fix: Fix designated initializers and reference type issue…
Oct 7, 2025
ba27380
Linux build fix: Fix remaining designated initializer in tcp_server_…
Oct 7, 2025
878ff55
Linux build fix: Fix missing headers and C++17 structured bindings (#…
Oct 7, 2025
7b447fc
Linux build fix: Replace C++17 structured bindings with traditional p…
Oct 7, 2025
6dc98e1
Linux build fix: Enable position-independent code for llhttp static l…
Oct 7, 2025
3fcd07d
Linux build fix: Replace filesystem header with C functions in test_l…
Oct 7, 2025
1afe8bd
Linux build fix: Enable position-independent code for nghttp2 static …
Oct 7, 2025
4481de8
Linux build fix: Fix string_literal for C++14 compatibility (#122)
Oct 7, 2025
94d5ca6
Linux build fix: Fix atomic time_point initialization in test_event_l…
Oct 7, 2025
6b40fbe
Linux build fix: Replace designated initializers in test_tcp_listener…
Oct 7, 2025
6d80aeb
Linux build fix: Remove nothrow attribute for GCC/Clang (#122)
Oct 7, 2025
68d999c
Linux build fix: Add missing cstring header (#122)
Oct 7, 2025
632c8ac
Linux build fix: Guard SO_NOSIGPIPE with ifdef (#122)
Oct 7, 2025
cfb6e7e
Linux build fix: Use int64_t instead of long long in example (#121)
Oct 7, 2025
a4c56f1
Linux build fix: Add missing csignal header to event_loop_example (#122)
Oct 7, 2025
3dff7b7
Linux build fix: Add algorithm header and explicit lambda return type…
Oct 7, 2025
29241ad
Linux build fix: Replace filesystem header with C functions in loggin…
Oct 7, 2025
93ea3ee
make format CPP code to apply clang-format (#122)
Oct 7, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,10 @@ if(MCP_USE_LLHTTP)

add_library(llhttp STATIC ${LLHTTP_SOURCES})
target_include_directories(llhttp PUBLIC ${llhttp_SOURCE_DIR}/include)


# Enable position-independent code for shared library linking
set_target_properties(llhttp PROPERTIES POSITION_INDEPENDENT_CODE ON)

# Disable warnings for third-party code
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
target_compile_options(llhttp PRIVATE -w)
Expand Down Expand Up @@ -245,7 +248,12 @@ if(MCP_USE_NGHTTP2)
message(STATUS "nghttp2 is a larger dependency and requires compilation. Please be patient.")
FetchContent_MakeAvailable(nghttp2)
message(STATUS "nghttp2 download and configuration complete.")


# Enable position-independent code for shared library linking
if(TARGET nghttp2_static)
set_target_properties(nghttp2_static PROPERTIES POSITION_INDEPENDENT_CODE ON)
endif()

set(NGHTTP2_FOUND TRUE)
set(NGHTTP2_INCLUDE_DIRS
${nghttp2_SOURCE_DIR}/lib/includes
Expand Down
12 changes: 12 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,16 @@ verbose:
@./build.sh --verbose

# Format all source files (C++ and TypeScript)
format-cpp:
@echo "Formatting C++ files with clang-format..."
@if command -v clang-format >/dev/null 2>&1; then \
find . -path "./build*" -prune -o \( -name "*.h" -o -name "*.cpp" -o -name "*.cc" \) -print | xargs clang-format -i; \
echo "C++ formatting complete."; \
else \
echo "Warning: clang-format not found, skipping C++ formatting."; \
echo "Install clang-format to format C++ files: brew install clang-format (macOS) or apt-get install clang-format (Ubuntu)"; \
fi

format:
@echo "Formatting all source files..."
@echo "Formatting C++ files with clang-format..."
Expand Down Expand Up @@ -709,6 +719,7 @@ help:
@echo ""
@echo "┌─ CODE QUALITY TARGETS ──────────────────────────────────────────────┐"
@echo "│ make format Auto-format all source files (C++, TypeScript, Python, Rust, Ruby, C#, Go, Java) │"
@echo "│ make format-cpp Format only C++ files with clang-format │"
@echo "│ make format-ts Format only TypeScript files with prettier │"
@echo "│ make format-python Format only Python files with black │"
@echo "│ make format-rust Format only Rust files with rustfmt │"
Expand All @@ -734,6 +745,7 @@ help:
@echo "│ │"
@echo "│ Development workflow: │"
@echo "│ $$ make format # Format all code (C++, TypeScript, Python, Rust, Ruby, C#, Go, Java) │"
@echo "│ $$ make format-cpp # Format only C++ files │"
@echo "│ $$ make format-ts # Format only TypeScript files │"
@echo "│ $$ make format-python # Format only Python files │"
@echo "│ $$ make format-rust # Format only Rust files │"
Expand Down
4 changes: 2 additions & 2 deletions build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -134,9 +134,9 @@ fi
# Run tests if requested
if [ "$RUN_TESTS" = true ]; then
print_status "Running tests..."

# Run all tests using ctest
if GTEST_COLOR=1 ctest --output-on-failure --verbose -C $BUILD_TYPE; then
if GTEST_COLOR=1 ctest --output-on-failure -C $BUILD_TYPE; then
print_success "All tests passed!"
else
print_error "Some tests failed"
Expand Down
1 change: 1 addition & 0 deletions examples/event_loop_example.cc
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include <atomic>
#include <chrono>
#include <csignal>
#include <fcntl.h>
#include <iostream>
#include <thread>
Expand Down
8 changes: 4 additions & 4 deletions examples/mcp/mcp_example_server.cc
Original file line number Diff line number Diff line change
Expand Up @@ -251,13 +251,13 @@ CallToolResult executeSampleTool(const std::string& name,
: "";
double a = holds_alternative<double>(a_it->second)
? get<double>(a_it->second)
: (holds_alternative<long long>(a_it->second)
? static_cast<double>(get<long long>(a_it->second))
: (holds_alternative<int64_t>(a_it->second)
? static_cast<double>(get<int64_t>(a_it->second))
: 0.0);
double b = holds_alternative<double>(b_it->second)
? get<double>(b_it->second)
: (holds_alternative<long long>(b_it->second)
? static_cast<double>(get<long long>(b_it->second))
: (holds_alternative<int64_t>(b_it->second)
? static_cast<double>(get<int64_t>(b_it->second))
: 0.0);

double calc_result = 0;
Expand Down
6 changes: 3 additions & 3 deletions include/mcp/c_api/mcp_c_bridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -648,20 +648,20 @@ inline mcp_request_id_t to_c_request_id_safe(const mcp::RequestId& id) {
const auto& str = mcp::get<std::string>(id);
return mcp_request_id_create_string(str.c_str());
} else {
return mcp_request_id_create_number(mcp::get<int>(id));
return mcp_request_id_create_number(mcp::get<int64_t>(id));
}
}

inline mcp::RequestId to_cpp_request_id_safe(mcp_request_id_t id) {
if (!id) {
return mcp::RequestId(0);
return mcp::RequestId(static_cast<int64_t>(0));
}

if (mcp_request_id_is_string(id)) {
const char* str = mcp_request_id_get_string(id);
return mcp::RequestId(str ? std::string(str) : std::string());
} else {
return mcp::RequestId(static_cast<int>(mcp_request_id_get_number(id)));
return mcp::RequestId(static_cast<int64_t>(mcp_request_id_get_number(id)));
}
}

Expand Down
8 changes: 4 additions & 4 deletions include/mcp/c_api/mcp_c_type_conversions.h
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ inline RequestId to_cpp_request_id(const mcp_request_id_t& id) {
if (id.type == mcp_request_id::MCP_REQUEST_ID_STRING) {
return RequestId(to_cpp_string(id.value.string_value));
} else {
return RequestId(static_cast<int>(id.value.number_value));
return RequestId(static_cast<int64_t>(id.value.number_value));
}
}

Expand All @@ -305,7 +305,7 @@ inline mcp_request_id_t to_c_request_id(const RequestId& id) {
result.value.string_value = to_c_string(mcp::get<std::string>(id));
} else {
result.type = mcp_request_id::MCP_REQUEST_ID_NUMBER;
result.value.number_value = mcp::get<int>(id);
result.value.number_value = mcp::get<int64_t>(id);
}
return result;
}
Expand All @@ -322,7 +322,7 @@ inline ProgressToken to_cpp_progress_token(const mcp_progress_token_t& token) {
if (token.type == mcp_progress_token::MCP_PROGRESS_TOKEN_STRING) {
return ProgressToken(to_cpp_string(token.value.string_value));
} else {
return ProgressToken(static_cast<int>(token.value.number_value));
return ProgressToken(static_cast<int64_t>(token.value.number_value));
}
}

Expand All @@ -336,7 +336,7 @@ inline mcp_progress_token_t to_c_progress_token(const ProgressToken& token) {
result.value.string_value = to_c_string(mcp::get<std::string>(token));
} else {
result.type = mcp_progress_token::MCP_PROGRESS_TOKEN_NUMBER;
result.value.number_value = mcp::get<int>(token);
result.value.number_value = mcp::get<int64_t>(token);
}
return result;
}
Expand Down
2 changes: 1 addition & 1 deletion include/mcp/c_api/mcp_c_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ extern "C" {
#define MCP_API_EXPORT __attribute__((visibility("default")))
#define MCP_API_IMPORT
#define MCP_CALLBACK
#define MCP_NOEXCEPT __attribute__((nothrow))
#define MCP_NOEXCEPT // GCC 7 doesn't allow attributes on function definitions
#else
#define MCP_API_EXPORT
#define MCP_API_IMPORT
Expand Down
15 changes: 9 additions & 6 deletions include/mcp/client/mcp_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -293,15 +293,16 @@ class RequestTracker {
// Add request to tracking
void trackRequest(RequestPtr request) {
std::lock_guard<std::mutex> lock(mutex_);
// Extract int ID from RequestId
int id = holds_alternative<int>(request->id) ? get<int>(request->id) : 0;
// Extract int64_t ID from RequestId
int64_t id =
holds_alternative<int64_t>(request->id) ? get<int64_t>(request->id) : 0;
pending_requests_[id] = request;
}

// Get request by ID without removing
RequestPtr getRequest(const RequestId& id) {
std::lock_guard<std::mutex> lock(mutex_);
int int_id = holds_alternative<int>(id) ? get<int>(id) : 0;
int64_t int_id = holds_alternative<int64_t>(id) ? get<int64_t>(id) : 0;
auto it = pending_requests_.find(int_id);
if (it != pending_requests_.end()) {
return it->second;
Expand All @@ -312,7 +313,7 @@ class RequestTracker {
// Remove and return request
RequestPtr removeRequest(const RequestId& id) {
std::lock_guard<std::mutex> lock(mutex_);
int int_id = holds_alternative<int>(id) ? get<int>(id) : 0;
int64_t int_id = holds_alternative<int64_t>(id) ? get<int64_t>(id) : 0;
auto it = pending_requests_.find(int_id);
if (it != pending_requests_.end()) {
auto request = it->second;
Expand All @@ -336,7 +337,9 @@ class RequestTracker {

// Remove timed out requests from tracking
for (const auto& request : timed_out) {
int id = holds_alternative<int>(request->id) ? get<int>(request->id) : 0;
int64_t id = holds_alternative<int64_t>(request->id)
? get<int64_t>(request->id)
: 0;
pending_requests_.erase(id);
}

Expand All @@ -352,7 +355,7 @@ class RequestTracker {
mutable std::mutex mutex_;
std::chrono::milliseconds timeout_;
// Store using int ID extracted from RequestId
std::unordered_map<int, RequestPtr> pending_requests_;
std::unordered_map<int64_t, RequestPtr> pending_requests_;
};

/**
Expand Down
94 changes: 7 additions & 87 deletions include/mcp/core/compat.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,22 +48,8 @@ inline constexpr auto in_place = std::in_place;

using bad_optional_access = std::bad_optional_access;

// make_optional helpers
template <typename T>
constexpr optional<typename std::decay<T>::type> make_optional(T&& value) {
return std::make_optional(std::forward<T>(value));
}

template <typename T, typename... Args>
constexpr optional<T> make_optional(Args&&... args) {
return std::make_optional<T>(std::forward<Args>(args)...);
}

template <typename T, typename U, typename... Args>
constexpr optional<T> make_optional(std::initializer_list<U> il,
Args&&... args) {
return std::make_optional<T>(il, std::forward<Args>(args)...);
}
// Import std functions into mcp namespace
using std::make_optional;
#else
// Use mcp:: implementations (already defined in optional.h)
// Just need to ensure they're in the mcp namespace
Expand All @@ -75,77 +61,11 @@ using variant = std::variant<Types...>;

using bad_variant_access = std::bad_variant_access;

template <typename T, typename... Types>
constexpr T* get_if(variant<Types...>* v) noexcept {
return std::get_if<T>(v);
}

template <typename T, typename... Types>
constexpr const T* get_if(const variant<Types...>* v) noexcept {
return std::get_if<T>(v);
}

template <typename T, typename... Types>
constexpr T& get(variant<Types...>& v) {
return std::get<T>(v);
}

template <typename T, typename... Types>
constexpr const T& get(const variant<Types...>& v) {
return std::get<T>(v);
}

template <typename T, typename... Types>
constexpr T&& get(variant<Types...>&& v) {
return std::get<T>(std::move(v));
}

template <typename T, typename... Types>
constexpr const T&& get(const variant<Types...>&& v) {
return std::get<T>(std::move(v));
}

template <typename T, typename... Types>
constexpr bool holds_alternative(const variant<Types...>& v) noexcept {
return std::holds_alternative<T>(v);
}

template <typename Visitor, typename... Variants>
constexpr decltype(auto) visit(Visitor&& vis, Variants&&... vars) {
return std::visit(std::forward<Visitor>(vis),
std::forward<Variants>(vars)...);
}

// Helper for index-based operations
template <std::size_t I, typename... Types>
constexpr auto& get(variant<Types...>& v) {
return std::get<I>(v);
}

template <std::size_t I, typename... Types>
constexpr const auto& get(const variant<Types...>& v) {
return std::get<I>(v);
}

template <std::size_t I, typename... Types>
constexpr auto&& get(variant<Types...>&& v) {
return std::get<I>(std::move(v));
}

template <std::size_t I, typename... Types>
constexpr const auto&& get(const variant<Types...>&& v) {
return std::get<I>(std::move(v));
}

template <std::size_t I, typename... Types>
constexpr auto* get_if(variant<Types...>* v) noexcept {
return std::get_if<I>(v);
}

template <std::size_t I, typename... Types>
constexpr const auto* get_if(const variant<Types...>* v) noexcept {
return std::get_if<I>(v);
}
// Import std functions into mcp namespace for ADL
using std::get;
using std::get_if;
using std::holds_alternative;
using std::visit;
#else
// Use mcp:: implementations and provide std-like free functions

Expand Down
19 changes: 17 additions & 2 deletions include/mcp/core/type_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -234,16 +234,26 @@ template <size_t N>
struct string_literal {
char value[N];

#if __cplusplus >= 201703L
// C++17 and later: can use constexpr with loops
constexpr string_literal(const char (&str)[N]) {
for (size_t i = 0; i < N; ++i) {
value[i] = str[i];
}
}
#else
// C++14: constexpr constructors can't have loops
string_literal(const char (&str)[N]) {
for (size_t i = 0; i < N; ++i) {
value[i] = str[i];
}
}
#endif

constexpr const char* c_str() const { return value; }
constexpr size_t size() const { return N - 1; }

constexpr bool operator==(const string_literal& other) const {
bool operator==(const string_literal& other) const {
for (size_t i = 0; i < N; ++i) {
if (value[i] != other.value[i])
return false;
Expand All @@ -254,7 +264,7 @@ struct string_literal {

// Deduction guide for C++17, but we'll use make function for C++14
template <size_t N>
constexpr string_literal<N> make_string_literal(const char (&str)[N]) {
inline string_literal<N> make_string_literal(const char (&str)[N]) {
return string_literal<N>(str);
}

Expand All @@ -277,6 +287,11 @@ struct overload : Fs... {
template <typename... Fs>
overload(Fs...) -> overload<Fs...>;

template <typename... Fs>
constexpr auto make_overload(Fs&&... fs) {
return overload<Fs...>{std::forward<Fs>(fs)...};
}

template <typename Variant, typename... Visitors>
auto match(Variant&& v, Visitors&&... visitors) {
return std::visit(overload{std::forward<Visitors>(visitors)...},
Expand Down
4 changes: 2 additions & 2 deletions include/mcp/echo/echo_basic.h
Original file line number Diff line number Diff line change
Expand Up @@ -651,8 +651,8 @@ class EchoClientBase {
std::lock_guard<std::mutex> lock(pending_mutex_);

int id = 0;
if (holds_alternative<int>(response.id)) {
id = get<int>(response.id);
if (holds_alternative<int64_t>(response.id)) {
id = get<int64_t>(response.id);
}

auto it = pending_requests_.find(id);
Expand Down
2 changes: 1 addition & 1 deletion include/mcp/filter/metrics_filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ class MetricsFilter : public network::NetworkFilterBase,
}

// Start tracking request latency
if (holds_alternative<int>(request.id) ||
if (holds_alternative<int64_t>(request.id) ||
holds_alternative<std::string>(request.id)) {
std::lock_guard<std::mutex> lock(request_mutex_);
pending_requests_[requestIdToString(request.id)] =
Expand Down
1 change: 1 addition & 0 deletions include/mcp/io_result.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include <cerrno>
#include <cstring>
#include <string>

#ifdef _WIN32
#include <winsock2.h>
Expand Down
Loading
Loading