Getting Started

This guide will help you get started with the mcp-cpp-sdk, from installation to building your first MCP server and client.

Prerequisites

Before installing mcp-cpp-sdk, ensure you have the following:

  • C++20 compiler: GCC 11+, Clang 14+, AppleClang 15+, or MSVC 2022

  • CMake: Version 3.20 or higher

  • Boost: Recent version with Asio and Beast support (managed via Conan for source builds)

  • nlohmann_json: Installed automatically for source builds via Conan

  • Conan: Version 2.0+ (for dependency management)

  • Chocolatey (Windows only): Required for dependency installation via scripts/init.py. Install from chocolatey.org.

Installation

See Installation for package-manager commands, supported platforms, shared/static target selection, verification, and uninstall instructions. GitHub, Cloudsmith (APT/RPM), and AUR publication is read back before the workflow reports success. ConanCenter, Homebrew, and Chocolatey remain pending during provider review or moderation. Install only after the requested version appears at the destination; until then, build from a reviewed source revision.

Using CMake FetchContent

Add mcp-cpp-sdk to your CMakeLists.txt:

include(FetchContent)
FetchContent_Declare(
  mcp-cpp-sdk
  GIT_REPOSITORY https://github.com/yurirocha15/mcp-cpp-sdk.git
  # Replace with a verified release tag or full 40-character commit.
  GIT_TAG <verified-tag-or-commit>
)
FetchContent_MakeAvailable(mcp-cpp-sdk)

target_link_libraries(your_target PRIVATE mcp::sdk)

Using Git Submodule

Clone the repository as a submodule:

git submodule add https://github.com/yurirocha15/mcp-cpp-sdk.git third_party/mcp-cpp-sdk
git submodule update --init --recursive

Then in your CMakeLists.txt:

add_subdirectory(third_party/mcp-cpp-sdk)
target_link_libraries(your_target PRIVATE mcp::sdk)

Building from Source

To build the SDK and examples from source:

# Clone the repository
git clone https://github.com/yurirocha15/mcp-cpp-sdk.git
cd mcp-cpp-sdk

# Initialize development environment
python scripts/init.py

# Build the project
python scripts/build.py

# Run tests
python scripts/build.py --test

Quick Start: Minimal Server

Here’s a minimal MCP server that exposes a single tool over stdio.

#include <mcp/mcp.hpp>

int main() {
    mcp::ServerCapabilities caps;
    caps.tools = mcp::ServerCapabilities::ToolsCapability{};

    mcp::Implementation info{"hello-server", "1.0.0"};
    mcp::Server server(std::move(info), std::move(caps));

    nlohmann::json schema = {
        {"type", "object"},
        {"properties", {{"name", {{"type", "string"}}}}},
        {"required", nlohmann::json::array({"name"})}};

    server.add_tool("hello", "Greets the user", std::move(schema),
                    [](const nlohmann::json& args) -> nlohmann::json {
                        return {{"message", "Hello, " + args.at("name").get<std::string>() + "!"}};
                    });

    server.run_stdio();
}

server.run_stdio() blocks until the client closes the connection or the process receives SIGINT/SIGTERM. The runtime, transport, and event loop are all managed internally.

Advanced: Manual Transport Setup

If you need direct control over the io_context — for example, to share it with other async work — you can wire up the transport manually:

#include <mcp/server/server.hpp>
#include <mcp/transport/stdio.hpp>
#include <boost/asio/co_spawn.hpp>
#include <boost/asio/detached.hpp>
#include <boost/asio/io_context.hpp>

int main() {
    mcp::ServerCapabilities caps;
    caps.tools = mcp::ServerCapabilities::ToolsCapability{};

    mcp::Implementation info{"math-server", "1.0.0"};
    mcp::Server server(std::move(info), std::move(caps));

    nlohmann::json schema = {
        {"type", "object"},
        {"properties", {{"a", {{"type", "number"}}}, {"b", {{"type", "number"}}}}}};

    server.add_tool<nlohmann::json, nlohmann::json>(
        "add", "Add two numbers", std::move(schema),
        [](const nlohmann::json& params) -> mcp::Task<nlohmann::json> {
            double result = params["a"].get<double>() + params["b"].get<double>();
            co_return nlohmann::json{{"result", result}};
        });

    boost::asio::io_context io;
    auto transport = std::make_shared<mcp::StdioTransport>(io.get_executor());
    boost::asio::co_spawn(
        io,
        [&]() -> mcp::Task<void> {
            co_await server.run(transport, io.get_executor());
        },
        boost::asio::detached);
    io.run();
}

Quick Start: Minimal Client

Note

A convenience client.run_stdio() API is planned. For now, clients require manual io_context setup as shown below.

Here’s a minimal MCP client that connects to an already running Streamable HTTP server and calls a tool:

#include <mcp/client/client.hpp>
#include <mcp/transport/http_client.hpp>
#include <boost/asio/co_spawn.hpp>
#include <boost/asio/detached.hpp>
#include <boost/asio/io_context.hpp>
#include <iostream>

int main() {
    using namespace mcp;

    boost::asio::io_context io;

    auto transport = std::make_shared<HttpClientTransport>(
        io.get_executor(), "http://127.0.0.1:3000/mcp");
    Client client(transport, io.get_executor());

    boost::asio::co_spawn(
        io,
        [&]() -> Task<void> {
            // Connect and initialize
            Implementation info;
            info.name = "math-client";
            info.version = "1.0.0";
            co_await client.connect(info, {});

            // Call the "add" tool
            nlohmann::json args = {{"a", 5}, {"b", 7}};
            auto result = co_await client.call_tool("add", args);
            std::cout << "Result: " << nlohmann::json(result).dump(2) << std::endl;

            client.close();
        }(),
        boost::asio::detached
    );

    io.run();
}

Important

Client requests time out after 30 seconds by default. The Client above takes no options, so every call_tool, read_resource and list_* it issues carries a 30-second deadline and throws mcp::McpError with code -32001 when it expires — even though the server may still be working on the call. Set ClientOptions::request_timeout before constructing the client if any of your tools legitimately run longer:

mcp::ClientOptions options;
options.request_timeout = std::chrono::minutes(5);
Client client(transport, io.get_executor(), options);

See Error Handling for per-request deadlines and what a timeout does and does not guarantee about the server.

Next Steps