Skip to content

Commit 218be36

Browse files
committed
feat: replace tiny-process-library with SDK process code (CreateProcessW)
Replace the FetchContent dependency on tiny-process-library with internal cross-platform process code adapted from copilot-sdk-cpp. This eliminates an external dependency that was transitively inherited by downstream projects (libagents -> fastmcpp_core). Win32 implementation upgraded from CreateProcessA to CreateProcessW: - UTF-8/UTF-16 conversion via utf8_to_wide() helper - STARTUPINFOEXW with explicit handle inheritance (PROC_THREAD_ATTRIBUTE_HANDLE_LIST) - Job Object for automatic child cleanup - CREATE_NO_WINDOW to prevent console popups - Stderr redirected to NUL when not captured StdioTransport rewritten from callback-based (deque + condition_variable) to synchronous pipe model (direct read_line on stdout pipe), with a background stderr reader thread in keep-alive mode to prevent pipe buffer deadlock. Process liveness is checked during timeout polling (200ms intervals) for fast failure detection when servers crash. Also fixes two CI issues from PR #31: - openapi_provider.hpp: brace-init default param -> explicit Options{} - transports.hpp: add missing override on session_id/has_session New tests: stdio_lifecycle, stdio_stderr, stdio_timeout. All 89 tests pass.
1 parent e7220b8 commit 218be36

12 files changed

Lines changed: 2082 additions & 162 deletions

File tree

CMakeLists.txt

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -169,24 +169,8 @@ if(FASTMCPP_ENABLE_POST_STREAMING OR FASTMCPP_ENABLE_SAMPLING_HTTP_HANDLERS)
169169
endif()
170170
endif()
171171

172-
# TinyProcessLib for cross-platform subprocess (header-only)
173-
FetchContent_Declare(
174-
tiny_process_lib
175-
GIT_REPOSITORY https://github.com/eidheim/tiny-process-library.git
176-
GIT_TAG master
177-
)
178-
FetchContent_GetProperties(tiny_process_lib)
179-
if(NOT tiny_process_lib_POPULATED)
180-
FetchContent_Populate(tiny_process_lib)
181-
endif()
182-
target_include_directories(fastmcpp_core PUBLIC ${tiny_process_lib_SOURCE_DIR})
183-
target_compile_definitions(fastmcpp_core PUBLIC TINY_PROCESS_LIB_AVAILABLE)
184-
target_sources(fastmcpp_core PRIVATE ${tiny_process_lib_SOURCE_DIR}/process.cpp)
185-
if(UNIX)
186-
target_sources(fastmcpp_core PRIVATE ${tiny_process_lib_SOURCE_DIR}/process_unix.cpp)
187-
elseif(WIN32)
188-
target_sources(fastmcpp_core PRIVATE ${tiny_process_lib_SOURCE_DIR}/process_win.cpp)
189-
endif()
172+
# Cross-platform subprocess management (replaces tiny-process-library)
173+
target_sources(fastmcpp_core PRIVATE src/internal/process.cpp)
190174
find_package(Threads REQUIRED)
191175
target_link_libraries(fastmcpp_core PRIVATE Threads::Threads)
192176

@@ -466,6 +450,26 @@ if(FASTMCPP_BUILD_TESTS)
466450
target_link_libraries(fastmcpp_stdio_failure PRIVATE fastmcpp_core)
467451
add_test(NAME fastmcpp_stdio_failure COMMAND fastmcpp_stdio_failure)
468452

453+
add_executable(fastmcpp_stdio_lifecycle tests/transports/stdio_lifecycle.cpp)
454+
target_link_libraries(fastmcpp_stdio_lifecycle PRIVATE fastmcpp_core)
455+
add_test(NAME fastmcpp_stdio_lifecycle COMMAND fastmcpp_stdio_lifecycle)
456+
set_tests_properties(fastmcpp_stdio_lifecycle PROPERTIES
457+
WORKING_DIRECTORY "$<TARGET_FILE_DIR:fastmcpp_stdio_lifecycle>"
458+
)
459+
460+
add_executable(fastmcpp_stdio_stderr tests/transports/stdio_stderr.cpp)
461+
target_link_libraries(fastmcpp_stdio_stderr PRIVATE fastmcpp_core)
462+
add_test(NAME fastmcpp_stdio_stderr COMMAND fastmcpp_stdio_stderr)
463+
set_tests_properties(fastmcpp_stdio_stderr PROPERTIES
464+
WORKING_DIRECTORY "$<TARGET_FILE_DIR:fastmcpp_stdio_stderr>"
465+
)
466+
467+
add_executable(fastmcpp_stdio_timeout tests/transports/stdio_timeout.cpp)
468+
target_link_libraries(fastmcpp_stdio_timeout PRIVATE fastmcpp_core)
469+
add_test(NAME fastmcpp_stdio_timeout COMMAND fastmcpp_stdio_timeout)
470+
# Timeout test can take up to ~35 seconds
471+
set_tests_properties(fastmcpp_stdio_timeout PROPERTIES TIMEOUT 60)
472+
469473
# App mounting tests
470474
add_executable(fastmcpp_app_mounting tests/app/mounting.cpp)
471475
target_link_libraries(fastmcpp_app_mounting PRIVATE fastmcpp_core)

include/fastmcpp/client/transports.hpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -132,10 +132,10 @@ class SseClientTransport : public ITransport,
132132
bool is_connected() const;
133133

134134
/// Get the current MCP session ID (from the SSE "endpoint" event).
135-
std::string session_id() const;
135+
std::string session_id() const override;
136136

137137
/// Check if a session ID has been set.
138-
bool has_session() const;
138+
bool has_session() const override;
139139

140140
void set_server_request_handler(ServerRequestHandler handler) override;
141141

@@ -195,10 +195,10 @@ class StreamableHttpTransport : public ITransport,
195195
fastmcpp::Json request(const std::string& route, const fastmcpp::Json& payload) override;
196196

197197
/// Get the session ID (set after successful initialize)
198-
std::string session_id() const;
198+
std::string session_id() const override;
199199

200200
/// Check if a session ID has been set
201-
bool has_session() const;
201+
bool has_session() const override;
202202

203203
/// Set callback for handling server-initiated notifications during streaming responses
204204
void set_notification_callback(std::function<void(const fastmcpp::Json&)> callback);

include/fastmcpp/providers/openapi_provider.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,16 @@ class OpenAPIProvider : public Provider
1515
public:
1616
struct Options
1717
{
18-
bool validate_output{true};
18+
bool validate_output = true;
1919
std::map<std::string, std::string> mcp_names; // operationId -> component name
2020
};
2121

2222
explicit OpenAPIProvider(Json openapi_spec, std::optional<std::string> base_url = std::nullopt,
23-
Options options = {});
23+
Options options = Options{});
2424

2525
static OpenAPIProvider from_file(const std::string& file_path,
2626
std::optional<std::string> base_url = std::nullopt,
27-
Options options = {});
27+
Options options = Options{});
2828

2929
std::vector<tools::Tool> list_tools() const override;
3030
std::optional<tools::Tool> get_tool(const std::string& name) const override;

0 commit comments

Comments
 (0)