Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions MCP/cpp-sdk/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@

# Build directories
build/
build-*/
output/

# Test directories
Expand Down
16 changes: 12 additions & 4 deletions MCP/cpp-sdk/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,21 @@ set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g -D_FORTIFY_SOURCE=2")
set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG")

# Common compiler flags
add_compile_options(-Wall -Werror -Wno-error=unused-variable -Wfloat-equal -Wtrampolines -fno-strict-aliasing -fstack-protector-strong)
if(APPLE)
add_compile_options(-Wall -Werror -Wno-error=unused-variable -Wfloat-equal -fno-strict-aliasing -fstack-protector-strong)
else()
add_compile_options(-Wall -Werror -Wno-error=unused-variable -Wfloat-equal -Wtrampolines -fno-strict-aliasing -fstack-protector-strong)
endif()

# Linker flags for security hardening
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-z,noexecstack,-z,relro,-z,now -rdynamic -pie")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,noexecstack,-z,relro,-z,now -rdynamic")
if(APPLE)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-pie")
else()
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-z,noexecstack,-z,relro,-z,now -rdynamic -pie")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,noexecstack,-z,relro,-z,now -rdynamic")
endif()

if( CMAKE_BUILD_TYPE STREQUAL "Release")
if(CMAKE_BUILD_TYPE STREQUAL "Release" AND NOT APPLE)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -s")
endif()
Expand Down
11 changes: 9 additions & 2 deletions MCP/cpp-sdk/example/client_example/prompt_example/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,17 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)

add_executable(PromptExample prompt_example.cpp)

set(MCP_OUTPUT_DIR "${CMAKE_CURRENT_LIST_DIR}/../../../output")
set(MCP_LIBRARY "${MCP_OUTPUT_DIR}/libmcp${CMAKE_SHARED_LIBRARY_SUFFIX}")

target_include_directories(PromptExample PRIVATE
${CMAKE_CURRENT_LIST_DIR}/../../../output/mcp
${MCP_OUTPUT_DIR}/mcp
)

target_link_libraries(PromptExample PRIVATE
${CMAKE_CURRENT_LIST_DIR}/../../../output/libmcp.so
${MCP_LIBRARY}
)

set_target_properties(PromptExample PROPERTIES
BUILD_RPATH "${MCP_OUTPUT_DIR}"
)
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,17 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)

add_executable(ResourceExample resource_example.cpp)

set(MCP_OUTPUT_DIR "${CMAKE_CURRENT_LIST_DIR}/../../../output")
set(MCP_LIBRARY "${MCP_OUTPUT_DIR}/libmcp${CMAKE_SHARED_LIBRARY_SUFFIX}")

target_include_directories(ResourceExample PRIVATE
${CMAKE_CURRENT_LIST_DIR}/../../../output/mcp
${MCP_OUTPUT_DIR}/mcp
)

target_link_libraries(ResourceExample PRIVATE
${CMAKE_CURRENT_LIST_DIR}/../../../output/libmcp.so
${MCP_LIBRARY}
)

set_target_properties(ResourceExample PROPERTIES
BUILD_RPATH "${MCP_OUTPUT_DIR}"
)
11 changes: 9 additions & 2 deletions MCP/cpp-sdk/example/client_example/tool_example/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,17 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)

add_executable(ToolExample tool_example.cpp)

set(MCP_OUTPUT_DIR "${CMAKE_CURRENT_LIST_DIR}/../../../output")
set(MCP_LIBRARY "${MCP_OUTPUT_DIR}/libmcp${CMAKE_SHARED_LIBRARY_SUFFIX}")

target_include_directories(ToolExample PRIVATE
${CMAKE_CURRENT_LIST_DIR}/../../../output/mcp
${MCP_OUTPUT_DIR}/mcp
)

target_link_libraries(ToolExample PRIVATE
${CMAKE_CURRENT_LIST_DIR}/../../../output/libmcp.so
${MCP_LIBRARY}
)

set_target_properties(ToolExample PROPERTIES
BUILD_RPATH "${MCP_OUTPUT_DIR}"
)
13 changes: 10 additions & 3 deletions MCP/cpp-sdk/example/server_example/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,17 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)

add_executable(ServerExample server_example.cpp)

set(MCP_OUTPUT_DIR "${CMAKE_CURRENT_LIST_DIR}/../../output")
set(MCP_LIBRARY "${MCP_OUTPUT_DIR}/libmcp${CMAKE_SHARED_LIBRARY_SUFFIX}")

target_include_directories(ServerExample PRIVATE
${CMAKE_CURRENT_LIST_DIR}/../../output/mcp
${MCP_OUTPUT_DIR}/mcp
)

target_link_libraries(ServerExample PRIVATE
${CMAKE_CURRENT_LIST_DIR}/../../output/libmcp.so
)
${MCP_LIBRARY}
)

set_target_properties(ServerExample PROPERTIES
BUILD_RPATH "${MCP_OUTPUT_DIR}"
)
Empty file modified MCP/cpp-sdk/example/server_example/run_example.sh
100644 → 100755
Empty file.
22 changes: 20 additions & 2 deletions MCP/cpp-sdk/include/mcp/mcp_log.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,16 @@
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>

#if defined(__APPLE__)
#include <pthread.h>
#elif defined(__linux__)
#include <sys/syscall.h>
#endif

#ifdef __cplusplus
extern "C" {
#endif
Expand Down Expand Up @@ -51,14 +56,27 @@ static inline void GetCurrentTimeStamp(char* buffer, size_t bufferSize)
snprintf(buffer + len, bufferSize - len, ".%03ld", ts.tv_nsec / 1000000);
}

static inline long long McpGetCurrentThreadId(void)
{
#if defined(__APPLE__)
uint64_t tid = 0;
pthread_threadid_np(NULL, &tid);
return (long long)tid;
#elif defined(__linux__)
return (long long)syscall(SYS_gettid);
#else
return (long long)getpid();
#endif
}

#define MCP_LOG_COMMON(logLevel, format, ...) \
do { \
if (g_logCallback != NULL) { \
char timestamp[32]; \
GetCurrentTimeStamp(timestamp, sizeof(timestamp)); \
const char* filename = strrchr(__FILE__, '/'); \
filename = filename ? filename + 1 : __FILE__; \
g_logCallback(logLevel, "[%s] [%ld] %s::%s:[%d] " format "\n", timestamp, syscall(SYS_gettid), filename, \
g_logCallback(logLevel, "[%s] [%lld] %s::%s:[%d] " format "\n", timestamp, McpGetCurrentThreadId(), filename, \
__FUNCTION__, __LINE__, ##__VA_ARGS__); \
} \
} while (0)
Expand Down
22 changes: 20 additions & 2 deletions MCP/cpp-sdk/scripts/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,15 @@ if [[ ${WITH_COVERAGE} -eq 1 && "${BUILD_TYPE}" != "Debug" ]]; then
echo "[INFO] Continuing with ${BUILD_TYPE}..."
fi

# Determine optimal job count for Linux (CPU cores + 1, but max 8 to avoid memory issues)
CPU_CORES=$(nproc)
# Determine optimal job count (CPU cores + 1, but max 8 to avoid memory issues)
if command -v nproc >/dev/null 2>&1; then
CPU_CORES=$(nproc)
elif command -v sysctl >/dev/null 2>&1; then
CPU_CORES=$(sysctl -n hw.ncpu)
else
CPU_CORES=4
fi

OPTIMAL_JOBS=$((CPU_CORES + 1))
if [[ ${OPTIMAL_JOBS} -gt 8 ]]; then
OPTIMAL_JOBS=8
Expand All @@ -112,6 +119,17 @@ cd "${BUILD_DIR_ABS}"

CMAKE_ARGS=("${SOURCE_DIR}" "-DCMAKE_BUILD_TYPE=${BUILD_TYPE}")

if [[ "$(uname -s)" == "Darwin" ]] && command -v brew >/dev/null 2>&1; then
HOMEBREW_PREFIXES=(
"$(brew --prefix openssl@3)"
"$(brew --prefix curl)"
"$(brew --prefix libevent)"
"$(brew --prefix nlohmann-json)"
)
CMAKE_PREFIX_PATH=$(IFS=';'; echo "${HOMEBREW_PREFIXES[*]}")
CMAKE_ARGS+=("-DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH}")
fi

if [[ ${WITH_TESTS} -eq 1 ]]; then
CMAKE_ARGS+=("-DMCP_ENABLE_TESTS=ON")
else
Expand Down
61 changes: 59 additions & 2 deletions MCP/cpp-sdk/scripts/install_deps.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ set -euo pipefail
echo "==> Checking system dependencies for mcp_cpp..."

# Detect OS type
if [ -f /etc/os-release ]; then
if [ "$(uname -s)" = "Darwin" ]; then
OS="macos"
OS_VERSION="$(sw_vers -productVersion)"
elif [ -f /etc/os-release ]; then
. /etc/os-release
OS=$ID
OS_VERSION=$VERSION_ID
Expand Down Expand Up @@ -136,6 +139,40 @@ install_dependencies() {
fi
;;

macos)
if ! command_exists brew; then
echo " - Homebrew: NOT FOUND"
echo "Please install Homebrew first: https://brew.sh/"
exit 1
fi

if brew list --versions curl >/dev/null 2>&1; then
echo " - curl (Homebrew): OK"
else
echo " - curl (Homebrew): NOT FOUND"
need_curl=1
fi

if brew list --versions openssl@3 >/dev/null 2>&1; then
echo " - openssl@3: OK"
else
echo " - openssl@3: NOT FOUND"
need_openssl=1
fi

if brew list --versions cmake >/dev/null 2>&1; then
echo " - cmake: OK"
else
echo " - cmake: NOT FOUND"
fi

if brew list --versions pkgconf >/dev/null 2>&1; then
echo " - pkgconf: OK"
else
echo " - pkgconf: NOT FOUND"
fi
;;

*)
# Fallback: check for header files
if command_exists curl-config; then
Expand Down Expand Up @@ -215,6 +252,21 @@ install_dependencies() {
fi
;;

macos)
echo "Detected macOS system"

local packages=(cmake pkgconf libevent nlohmann-json)
if [ $need_curl -eq 1 ]; then
packages+=(curl)
fi
if [ $need_openssl -eq 1 ]; then
packages+=(openssl@3)
fi

echo "Installing Homebrew packages: ${packages[*]}"
brew install "${packages[@]}"
;;

*)
echo "Error: Unsupported OS: $OS"
echo "Please install libcurl-devel and openssl manually"
Expand All @@ -232,7 +284,12 @@ install_dependencies
# Verify installation
echo ""
echo "==> Verifying installation..."
if command_exists curl-config && command_exists openssl; then
if [ "$OS" = "macos" ]; then
if brew list --versions cmake pkgconf curl openssl@3 libevent nlohmann-json >/dev/null 2>&1; then
echo "✓ All dependencies verified successfully!"
exit 0
fi
elif command_exists curl-config && command_exists openssl; then
echo "✓ All dependencies verified successfully!"
exit 0
else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
namespace Mcp {

// SSE field prefix lengths
constexpr size_t SSE_EVENT_PREFIX_LEN = std::strlen("event:"); // "event:"
constexpr size_t SSE_ID_PREFIX_LEN = std::strlen("id:"); // "id:"
constexpr size_t SSE_DATA_PREFIX_LEN = std::strlen("data:"); // "data:"
constexpr size_t SSE_EVENT_PREFIX_LEN = sizeof("event:") - 1;
constexpr size_t SSE_ID_PREFIX_LEN = sizeof("id:") - 1;
constexpr size_t SSE_DATA_PREFIX_LEN = sizeof("data:") - 1;
constexpr std::chrono::milliseconds MAX_TIMEOUT_MS{30 * 60 * 1000}; // 30 minutes in milliseconds

StreamableHttpClientTransport::StreamableHttpClientTransport(std::string url,
Expand Down Expand Up @@ -301,7 +301,7 @@ void StreamableHttpClientTransport::HandleSseResponse(const HttpResponse& respon

// Empty line indicates end of event
if (line.empty()) {
if (!currentEvent.data.index() == 0 || !currentEvent.event.empty()) {
if (currentEvent.data.index() != 0 || !currentEvent.event.empty()) {
HandleSseEvent(currentEvent, isInitialization);
}
currentEvent = EventData();
Expand Down
Loading