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