Cookbook
Copy-paste recipes for common tasks.
Short, focused code snippets. Each recipe solves one problem. See Tutorials for full walkthroughs.
Server
Minimal stdio server (one-liner)
The shortest possible MCP server.
#include <cxxmcp/peer.hpp>
#include <cxxmcp/run.hpp>
int main() {
return mcp::ServerPeer::builder()
.name("minimal").version("1.0.0").stdio()
.tool<mcp::protocol::Json, mcp::protocol::Json>(
"echo", [](const mcp::protocol::Json& in) { return in; })
.run();
}
HTTP server
Serve over Streamable HTTP. Requires CXXMCP_ENABLE_HTTP=ON.
auto server = mcp::ServerPeer::builder()
.name("http-server").version("1.0.0")
.streamable_http("127.0.0.1", 3000, "/mcp")
.tool<Json, Json>("echo", [](const Json& in) { return in; })
.build();
auto running = mcp::serve(std::move(*server));
running->wait_until_ready();
running->wait();
Add a typed tool with reflection
Auto-serialize args and results with CXXMCP_REFLECT.
struct Args { std::string query; int limit; };
struct Result { std::vector<std::string> items; };
CXXMCP_REFLECT(Args, query, limit)
CXXMCP_REFLECT(Result, items)
// In builder:
.tool(mcp::server::tool<Args, Result>("search")
.description("Search items.")
.handler([](Args args, const mcp::server::ToolContext&) {
Result r;
for (int i = 0; i < args.limit; ++i)
r.items.push_back(args.query + "_" + std::to_string(i));
return r;
}))
Add a prompt
.prompt(mcp::protocol::Prompt{
.name = "summarize",
.description = "Summarize text",
.arguments = {mcp::protocol::PromptArgument{
.name = "text", .required = true,
}},
},
[](const mcp::server::PromptContext& ctx) {
auto text = ctx.arguments.at("text").get<std::string>();
mcp::protocol::PromptsGetResult result;
result.messages.push_back(mcp::protocol::PromptMessage{
.role = "user",
.content = mcp::protocol::ContentBlock{
.type = "text", .text = "Summarize: " + text},
});
return result;
})
Add a static resource
.resource("file:///data/config.json", [] {
return mcp::protocol::ResourceContents{
.uri = "file:///data/config.json",
.mime_type = "application/json",
.text = R"({"version": 1})",
};
})
Add a resource template
.resource_template("file:///workspace/{path}", [] {
return mcp::protocol::ResourceTemplate{
.uri_template = "file:///workspace/{path}",
.name = "Workspace files",
};
})
Handle raw JSON-RPC requests
For custom methods or vendor extensions.
.raw_request([](const mcp::protocol::JsonRpcRequest& req)
-> std::optional<mcp::protocol::JsonRpcResponse> {
if (req.method == "myapp/health") {
return mcp::protocol::make_response(
req.id, mcp::protocol::Json{{"ok", true}});
}
return std::nullopt; // unhandled, let SDK return method-not-found
})
Client
Connect to a stdio server
return mcp::ClientPeer::builder()
.process_stdio("./my-server")
.run([](auto& svc) {
svc.peer().initialize();
auto result = svc.peer().call_tool(
"echo", Json{{"value", "hello"}});
});
Connect to an HTTP server
auto client = mcp::ClientPeer::builder()
.streamable_http("http://127.0.0.1:3000/mcp")
.build();
auto svc = mcp::serve(std::move(*client));
svc->peer().initialize();
List all tools
auto tools = svc.peer().list_all_tools();
for (const auto& tool : tools) {
std::cout << tool.name << ": " << tool.description << "\n";
}
Read a resource
auto contents = svc.peer().read_resource("file:///data/config.json");
for (const auto& c : *contents) {
std::cout << c.text << "\n";
}
Get a prompt
mcp::protocol::Json args{{"text", "The quick brown fox."}};
auto result = svc.peer().get_prompt("summarize", args);
Auth
Bearer token server + client
// Server
auto auth = std::make_unique<mcp::server::StaticBearerAuthProvider>();
auth->add_token("my-token", mcp::server::AuthIdentity{"alice", {}});
auto server = mcp::ServerPeer::builder()
.name("auth-demo").version("1.0.0")
.auth_provider(std::move(auth))
.streamable_http("127.0.0.1", 3001, "/mcp")
.tool<Json, Json>("whoami", [](const Json&, const auto& ctx) {
return Json{{"subject",
ctx.auth_identity ? ctx.auth_identity->subject : "anon"}};
})
.build();
// Client
auto client = mcp::ClientPeer::builder()
.streamable_http("http://127.0.0.1:3001/mcp")
.bearer_token("my-token")
.build();
CMake flags for auth
# Auth contracts only (no OpenSSL)
cmake -S . -B build -DCXXMCP_ENABLE_AUTH=ON
# With OpenSSL crypto (DPoP, JWT, JWKS)
cmake -S . -B build -DCXXMCP_ENABLE_AUTH=ON -DCXXMCP_AUTH_CRYPTO=OpenSSL
# vcpkg
vcpkg install "cxxmcp-sdk[auth]"
Tasks and Async
Task-aware tool
.task_manager(mcp::server::TaskOperationProcessorOptions{
.worker_count = 2, .queue_size = 16,
})
.tool(mcp::server::tool<Json, Json>("heavy")
.task_support(mcp::protocol::TaskSupport::Optional)
.handler([](const Json& args, const auto& ctx) {
// runs in background task
return Json{{"done", true}};
}))
Request timeout
// Client-side timeout
auto result = svc.peer().call_tool(
"slow-tool", Json{{"data", "x"}},
std::chrono::seconds(30));
Cancel a task
auto task = svc.peer().call_tool("heavy", Json{{}});
svc.peer().cancel_task(task->task_id);
CMake
Minimum CMakeLists.txt
cmake_minimum_required(VERSION 3.16)
project(my-app LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
find_package(cxxmcp CONFIG REQUIRED)
add_executable(server server.cpp)
target_link_libraries(server PRIVATE cxxmcp::server)
All CMake options
cmake -S . -B build \
-DCXXMCP_BUILD_SDK=ON \ # aggregate SDK (default ON)
-DCXXMCP_BUILD_CLIENT=ON \ # client library
-DCXXMCP_BUILD_SERVER=ON \ # server library
-DCXXMCP_BUILD_EXAMPLES=ON \ # example executables
-DCXXMCP_BUILD_TESTS=ON \ # tests
-DCXXMCP_ENABLE_HTTP=ON \ # HTTP transport (cpp-httplib)
-DCXXMCP_ENABLE_AUTH=ON \ # OAuth 2.1 / DPoP contracts
-DCXXMCP_AUTH_CRYPTO=OpenSSL # OpenSSL crypto backend
FetchContent consumption
include(FetchContent)
FetchContent_Declare(cxxmcp
URL https://github.com/caomengxuan666/cxxmcp/releases/download/v1.1.6/cxxmcp-sdk-source-v1.1.6.tar.gz
URL_HASH SHA256=7d321ee1e48f71666659949c98b5e3c81b273db98607b21d7b3d9301f5bf42e2
)
FetchContent_MakeAvailable(cxxmcp)
target_link_libraries(my_app PRIVATE cxxmcp::server)
Next Steps
- Tutorials — full walkthroughs with explanations
- Concepts — understand the architecture
- Getting Started — install and build
- API Reference — every type and function