@@ -382,6 +382,76 @@ void test_error_handling()
382382 server.stop ();
383383}
384384
385+ void test_default_timeout_allows_slow_tool ()
386+ {
387+ std::cout << " test_default_timeout_allows_slow_tool... " << std::flush;
388+
389+ const int port = 18355 ;
390+ const std::string host = " 127.0.0.1" ;
391+
392+ tools::ToolManager tool_mgr;
393+ tools::Tool slow_tool{" slow_tool" ,
394+ Json{{" type" , " object" },
395+ {" properties" , Json{{" duration" , Json{{" type" , " integer" }}}}},
396+ {" required" , Json::array ({" duration" })}},
397+ Json{{" type" , " string" }}, [](const Json& input) -> Json
398+ {
399+ int duration = input.value (" duration" , 6 );
400+ std::this_thread::sleep_for (std::chrono::seconds (duration));
401+ return " Completed in " + std::to_string (duration) + " seconds" ;
402+ }};
403+ tool_mgr.register_tool (slow_tool);
404+
405+ std::unordered_map<std::string, std::string> descriptions = {{" slow_tool" , " Slow tool" }};
406+ auto handler = mcp::make_mcp_handler (" timeout_test" , " 1.0.0" , tool_mgr, descriptions);
407+
408+ server::StreamableHttpServerWrapper server (handler, host, port, " /mcp" );
409+ bool started = server.start ();
410+ std::cout << " (server.start=" << started << " , running=" << server.running () << " ) "
411+ << std::flush;
412+ assert (started && " Server failed to start" );
413+
414+ std::this_thread::sleep_for (std::chrono::milliseconds (500 ));
415+
416+ std::cout << " (testing direct client) " << std::flush;
417+ httplib::Client direct_cli (host, port);
418+ direct_cli.set_connection_timeout (5 , 0 );
419+ direct_cli.set_read_timeout (5 , 0 );
420+ auto direct_res = direct_cli.Get (" /mcp" );
421+ std::cout << " (GET result: " << (direct_res ? std::to_string (direct_res->status ) : " null" )
422+ << " ) " << std::flush;
423+
424+ try
425+ {
426+ client::StreamableHttpTransport transport (" http://" + host + " :" + std::to_string (port));
427+
428+ Json init_params = {{" protocolVersion" , " 2024-11-05" },
429+ {" capabilities" , Json::object ()},
430+ {" clientInfo" , {{" name" , " test" }, {" version" , " 1.0" }}}};
431+
432+ transport.request (" initialize" , init_params);
433+
434+ Json call_params = {{" name" , " slow_tool" }, {" arguments" , {{" duration" , 6 }}}};
435+ auto call_result = transport.request (" tools/call" , call_params);
436+
437+ assert (call_result.contains (" content" ) && " Should have content" );
438+ auto & content = call_result[" content" ];
439+ assert (content.is_array () && content.size () > 0 && " Should have content array" );
440+ assert (content[0 ][" type" ] == " text" && " Content should be text" );
441+ assert (content[0 ][" text" ] == " Completed in 6 seconds" && " Slow tool should complete" );
442+
443+ std::cout << " PASSED\n " ;
444+ }
445+ catch (const std::exception& e)
446+ {
447+ std::cout << " FAILED: " << e.what () << " \n " ;
448+ server.stop ();
449+ throw ;
450+ }
451+
452+ server.stop ();
453+ }
454+
385455int main ()
386456{
387457 std::cout << " Streamable HTTP Integration Tests\n " ;
@@ -394,6 +464,7 @@ int main()
394464 test_session_management ();
395465 test_server_info ();
396466 test_error_handling ();
467+ test_default_timeout_allows_slow_tool ();
397468
398469 std::cout << " \n All tests passed!\n " ;
399470 return 0 ;
0 commit comments