cpp-mcp

repository·main·Indexed 43 days ago

https://github.com/hkr04/cpp-mcp

A C++ implementation of the Model Context Protocol (MCP) that provides standardized interfaces for AI agents to interact with tools, resources, and prompts via JSON-RPC 2.0. It includes support for both HTTP/SSE and stdio transports, as well as optional TLS/SSL support for secure connections.

Tokens
1.9K
Snippets
5
Records
7
Agent score
6%

What's inside cpp-mcp

  1. How the MCP components work together

    main

    The framework is organized into several core components that implement the Model Context Protocol:

    • mcp_server.h/cpp: The main server implementation.
    • mcp_client.h: An abstract interface for all client implementations.
    • mcp_sse_client.h/cpp: A client implementation using HTTP and Server-Sent Events (SSE).
    • mcp_stdio_client.h/cpp: A client implementation using standard input/output (stdio), capable of launching and communicating with subprocesses.
    • mcp_tool.h/cpp: Manages and invokes MCP tools.
    • mcp_resource.h/cpp: Manages MCP resources.
    • mcp_message.h/cpp: Handles JSON-RPC 2.0 serialization/deserialization.
  2. Set up an MCP HTTP Server

    main

    To implement an MCP server over HTTP, configure a mcp::server::configuration object, instantiate a mcp::server, and register tools, resources, and prompts.

    Key Steps:

    1. Configure: Set host and port in mcp::server::configuration.
    2. Initialize: Call server.set_server_info(name, version).
    3. Register Tools: Use mcp::tool_builder to define parameters and register a handler function. Handlers receive mcp::json params and must return a JSON object containing a type: "text" array.
    4. Register Resources: Use server.register_resource(uri, resource_ptr).
    5. Register Prompts: Use mcp::prompt_builder and a handler that returns a JSON array of messages.
    6. Start: Call server.start(true) for blocking mode.
    mcp::server::configuration srv_conf;
    srv_conf.host = "localhost";
    srv_conf.port = 8888;
    
    mcp::server server(srv_conf);
    server.set_server_info("MCP Example Server", "0.1.0");
    
    // Register a tool
    mcp::json hello_handler(const mcp::json& params, const std::string /* session_id */) {
        std::string name = params.contains("name") ? params["name"].get<std::string>() : "World";
        return {{
            {"type", "text"},
            {"text", "Hello, " + name + "!"}
        }};
    }
    
    mcp::tool hello_tool = mcp::tool_builder("hello")
            .with_description("Say hello")
            .with_string_param("name", "Name to say hello to", "World")
            .build();
    
    server.register_tool(hello_tool, hello_handler);
    server.start(true);
  3. Build the MCP Protocol Framework

    main

    You can build the framework using CMake. Depending on your requirements, you can build a standard version, a version with tests, or a version with SSL support.

    Standard Build

    cmake -B build
    cmake --build build --config Release

    Build with Tests (requires GoogleTest via git submodules)

    git submodule update --init --recursive
    cmake -B build -DMCP_BUILD_TESTS=ON
    cmake --build build --config Release

    Build with SSL Support (required for HTTPS connections)

    git submodule update --init --recursive
    cmake -B build -DMCP_SSL=ON
    cmake --build build --config Release
  4. Configure TLS/SSL for HTTP Servers and Clients

    main

    When connecting to https endpoints, you must compile the project with -DMCP_SSL=ON.

    Server Configuration To enable TLS on an HTTP server, provide the paths to your certificate and private key in the mcp::server::configuration object:

    mcp::server::configuration srv_conf;
    srv_conf.host = "localhost";
    srv_conf.port = 8888;
    srv_conf.ssl.server_cert_path = "./server.cert.pem";
    srv_conf.ssl.server_private_key_path = "./server.key.pem";

    Client Configuration Simply use an https:// URL when instantiating an mcp::sse_client:

    mcp::sse_client client("https://localhost:8888");
  5. Use the SSE (HTTP) Client

    main

    The mcp::sse_client communicates with MCP servers using HTTP and Server-Sent Events (SSE). This is ideal for web-based or network-accessible servers.

    Usage Pattern:

    1. Instantiate mcp::sse_client with the server URL.
    2. (Optional) Set authentication tokens via set_auth_token() or custom headers via set_header().
    3. Initialize the connection with initialize(name, version).
    4. Call tools using call_tool(name, params).
    #include "mcp_sse_client.h"
    
    mcp::sse_client client("http://localhost:8080");
    client.set_auth_token("your_auth_token");
    client.set_header("X-Custom-Header", "value");
    
    if (client.initialize("My Client", "1.0.0")) {
        mcp::json result = client.call_tool("tool_name", {
            {"param1", "value1"},
            {"param2", 42}
        });
    }
  6. Use the Stdio Client

    main

    The mcp::stdio_client communicates with MCP servers via standard input/output. This is the default transport for clients like Claude Desktop and Cursor. It is used to launch and manage local server subprocesses.

    Usage Pattern:

    1. Instantiate mcp::stdio_client with the command used to run the server (e.g., npx -y @modelcontextprotocol/server-filesystem /path/to/dir).
    2. Initialize the connection with initialize(name, version).
    3. Interact with the server using list_resources(), read_resource(uri), or call_tool(name, params).
    #include "mcp_stdio_client.h"
    
    mcp::stdio_client client("npx -y @modelcontextprotocol/server-everything");
    
    if (client.initialize("My Client", "1.0.0")) {
        mcp::json resources = client.list_resources();
        mcp::json content = client.read_resource("resource://uri");
        mcp::json result = client.call_tool("tool_name", {
            {"param1", "value1"}
        });
    }
  7. Run the Agent Example CLI

    main

    The agent_example is a CLI tool that demonstrates an agent interacting with an LLM and MCP tools.

    Command Line Arguments:

    • --base-url: LLM base URL (e.g. https://openrouter.ai)
    • --endpoint: LLM endpoint (default to /v1/chat/completions/)
    • --api-key: LLM API key
    • --model: Model name (e.g. gpt-3.5-turbo)
    • --system-prompt: System prompt
    • --max-tokens: Maximum number of tokens to generate (default to 2048)
    • --temperature: Temperature (default to 0.0)
    • --max-steps: Maximum steps calling tools without user input (default to 3)

    Example Usage:

    ./build/examples/agent_example --base-url <base_url> --endpoint <endpoint> --api-key <api_key> --model <model_name>

    Note: Use -DMCP_SSL=ON during build if connecting to an https base URL.