Concepts

Understand the cxxmcp architecture.

The SDK is organized in layers: Protocol, Transport, Handler, Peer, and Service. This page explains how they fit together.

Layer Architecture

cxxmcp follows the RMCP-style role-aware design. Each layer has a specific responsibility and a corresponding CMake target:

Layer Target Responsibility
protocol cxxmcp::protocol MCP data models, JSON-RPC serialization, reflection, schema
transport cxxmcp::transport Role-generic transport contracts (stdio, HTTP, custom)
handler cxxmcp::handler Client/server handler interfaces
peer cxxmcp::peer Role-aware execution boundary (ServerPeer, ClientPeer)
service cxxmcp::service Service lifecycle (start, stop, wait)
server cxxmcp::server Server SDK: registries, builders, auth providers
client cxxmcp::client Client SDK: connection, request helpers
auth cxxmcp::auth Optional OAuth 2.1 / DPoP contracts

Peer and Service

Peer is the execution boundary. It owns the server or client state and routes incoming requests to registered handlers. Service wraps a Peer with a transport and manages the lifecycle (start, run, stop).

ServerPeer

Owns tool/prompt/resource registries, auth provider, and request dispatch. Built via ServerPeer::builder().

ClientPeer

Owns connection state, sends requests to a server, handles notifications. Built via ClientPeer::builder().

// Server lifecycle
auto server = mcp::ServerPeer::builder()
    .name("my-server").version("1.0.0")
    .stdio()
    .tool<Json, Json>("echo", handler)
    .build();

auto running = mcp::serve(std::move(*server));
running->wait();  // blocks until shutdown

// Client lifecycle
auto client = mcp::ClientPeer::builder()
    .streamable_http("http://localhost:3000/mcp")
    .build();

auto svc = mcp::serve(std::move(*client));
svc->peer().initialize();
svc->peer().call_tool("echo", Json{{"value", "hi"}});

Transports

A transport moves JSON-RPC messages between client and server. cxxmcp ships several built-in transports and lets you write custom ones.

Transport Builder Method CMake Flag Use Case
stdio .stdio() default CLI tools, local subprocess
Process stdio .process_stdio(cmd) default Launch a server process and talk to it
Streamable HTTP .streamable_http(host, port, path) CXXMCP_ENABLE_HTTP Web services, remote access
WebSocket .websocket(...) CXXMCP_ENABLE_HTTP + CXXMCP_ENABLE_WEBSOCKET Full-duplex remote access
Custom implement mcp::transport::Transport Unix socket, in-memory loopback, etc.

Capability Negotiation

During initialize, client and server exchange capability declarations. This tells each side what the other supports.

// Server declares capabilities via builder
auto server = mcp::ServerPeer::builder()
    .name("my-server")
    .version("1.0.0")
    .stdio()
    .tool(...)         // enables tools capability
    .prompt(...)       // enables prompts capability
    .resource(...)     // enables resources capability
    .build();

// Client discovers capabilities after initialize
auto& caps = svc.peer().server_capabilities();
if (caps.tools) {
    auto tools = svc.peer().list_all_tools();
    // ...
}

Server Capabilities

tools, resources, prompts, logging, completions, tasks, experimental, extensions

Client Capabilities

roots, sampling, elicitation, tasks, experimental, extensions

Protocol Model

All MCP messages are JSON-RPC 2.0. The SDK provides typed C++ structs for every protocol object:

  • ToolDefinition, ToolResult
  • Prompt, PromptMessage, PromptsGetResult
  • Resource, ResourceContents, ResourceTemplate
  • ContentBlock (text, image, audio, embedded resource)
  • JsonRpcRequest, JsonRpcResponse, JsonRpcNotification

Use CXXMCP_REFLECT on your own types to get automatic JSON serialization and JSON Schema generation. See Tutorials for examples.

Reflection System

The reflection system gives you zero-boilerplate DTO serialization. One macro replaces hand-written to_json/from_json for every struct.

#include <cxxmcp/protocol/reflect.hpp>

struct MyInput {
    std::string name;
    int count;
    std::optional<std::string> tag;
};

CXXMCP_REFLECT(MyInput, name, count, tag)

This gives you:

  • reflect_to_json<MyInput>(value) — serialize to JSON
  • reflect_from_json<MyInput>(json) — deserialize from JSON
  • schema_for<MyInput>() — auto-generated JSON Schema
  • has_reflect_v<MyInput> — compile-time trait (true)

Supported field types: scalars, std::string, std::optional<T>, std::vector<T>, std::variant, std::map, nested reflected types, and raw Json.

Next Steps