Hello all, I would like to gauge interest in Boost.Taar, a C++20 header-only library for writing HTTP services on top of Boost.Asio, Boost.Beast, Boost.JSON and Boost.URL. How it started In 2021 a colleague challenged me: "In Python you can serve HTTP in one line (python -m http.server). Can you do that in C++?" With Beast you can build anything, but even a small JSON endpoint means writing your own routing, argument parsing, error mapping and connection loop. Taar is my answer to that challenge. It went through several shapes before I settled on the current design in 2024, and it has grown into a library since. The gap it fills Beast is deliberately low level: it gives you HTTP messages, parsers and streams, and leaves routing, parameter extraction, conversions, sessions, static files and protocol handling to the application. Every non-trivial Beast server rewrites those layers. Outside Boost there are frameworks (Crow, Drogon, Oat++, cpp-httplib, userver), but they bring their own networking, threading and JSON models and do not compose with Asio executors, coroutines, Boost.JSON or Boost.URL. Boost has nothing at the application level. Taar is that layer, built only from Boost components and in their idiom: - the server and every connection are Asio coroutines; handlers may be plain functions or awaitables; it runs on any Asio executor, with a strand per connection on a multi-threaded io_context; - a composable matcher DSL selects routes (method, path templates with placeholders, headers, cookies, version); - handlers are ordinary callables: arguments are extracted from the path, query, headers, cookies or body and converted to the parameter types, and return values are converted to responses (both through tag_invoke customisation points); - HTTP protocols sit on top of the same callables: a JSON-RPC 2.0 endpoint, a Model Context Protocol (MCP) server so C++ applications can expose tools and resources to AI agents, and an OpenAPI 3.1 document generated from the registered routes. The layering is strict: Asio/Beast/JSON/URL at the bottom, the HTTP framework above them, and JSON-RPC, MCP and OpenAPI as optional layers on the HTTP framework that do not affect users who only need REST. What it looks like The answer to the challenge, a static file server for the current directory: taar::session::http session; session.register_request_handler( method == http::verb::get && target == "/{*path}", taar::handler::htdocs {"."}); boost::asio::io_context io; taar::cancellation_signals signals; boost::asio::co_spawn(io, taar::server::tcp("0.0.0.0", "8080", session, signals), boost::asio::detached); io.run(); And one function served three ways: int add(int a, int b) { return a + b; } // REST: GET /add/2/3 -> 5, documented in the generated OpenAPI file session.register_request_handler( method == http::verb::get && target == "/add/{a}/{b}", taar::handler::rest(&add, path_arg("a"), path_arg("b")), openapi.describe("Add two numbers")); // JSON-RPC 2.0: {"method": "add", "params": {"a": 2, "b": 3}} rpc.method("add", &add, rpc_arg("a"), rpc_arg("b")); // MCP: a tool whose input schema is derived from the parameter types mcp.tool("add", "Add two numbers", &add, mcp_arg("a"), mcp_arg("b")); Beyond that - static files with ETag/Last-Modified and conditional requests, byte ranges, precompressed variants, cache rules and caches; - streaming responses (chunked, server-sent events) and streaming request bodies, multipart forms; - per-connection state, cookie or header keyed sessions, interceptors and route guards, CORS, TLS, connection timeouts, graceful shutdown; - one error model: taar::failure with nested causes, taar::result<T> (boost::system::result with a rich error) that throws on access, mapped per surface to HTTP statuses, JSON-RPC errors and MCP results; - MCP over Streamable HTTP and stdio, with sessions, progress, cancellation, server-to-client requests and resource subscriptions. Status Version 1.0 is released. The library has about 480 test cases (unit and end-to-end over TCP and TLS). C++20 is the minimum; CI runs the tests as C++20 on GCC 13, Clang 17 and 18 (libstdc++ and libc++), MSVC 2022 and Apple Clang, as C++23 on newer GCC, Clang, MSVC and Apple Clang, as C++26 on GCC 15 and Clang 22, and under ASan, UBSan and TSan. It builds with b2 in the Boost superproject and with CMake (including the Boost CMake integration tests), and has QuickBook documentation with a reference and quick reference. Questions I would value the list's opinion on - Is MCP appropriate inside a Boost library given how young the specification is? It is an optional layer and versioned by protocol revision, but I would like to hear concerns. - I plan to replace much of the type introspection with C++26 reflection once compilers ship it (parameter names, schemas without BOOST_DESCRIBE, annotations for descriptions and constraints), keeping the C++20 path. Is that a reasonable direction? - The name: "taar" is Persian for a strand or thread, as in a spider's web, and is also the name of a long-necked lute; a library of strands for the web seemed fitting. Is it acceptable as a Boost name? Links - Repository: https://github.com/rjahanbakhshi/boost.taar - Documentation: https://rjahanbakhshi.github.io/boost.taar/ - Examples: https://github.com/rjahanbakhshi/boost.taar/tree/master/example - Known gaps and roadmap: https://github.com/rjahanbakhshi/boost.taar/blob/master/ROADMAP.md If there is interest, I would be grateful for feedback on the design and API, and I am looking for a review manager. Thank you, Reza Jahanbakhshi