Skip to content

Charudatta999/cpp-mcp

Repository files navigation

cpp-mcp

A lightweight, dependency-conscious C++20 framework for the Model Context Protocol (MCP).
One binary. Any REST API. Just JSON.

CI C++20 Dependencies Static Platform License

C++ MCP Server | MCP C++ SDK | Config-driven MCP API Gateway | Static MCP binary for AI agents

Build MCP servers in C++ with zero runtime dependencies. A secure, supply-chain-safe alternative to Python and TypeScript MCP implementations. Fully static binary with AES-256-GCM transport authentication for enterprise deployment. Works with Claude Desktop, VS Code Copilot, Cursor, and any MCP-compatible AI client.


Why cpp-mcp?

MCP servers are typically written in Python or JavaScript. cpp-mcp gives you the same capability with:

  • Small native binary — no Python or Node.js runtime
  • Config-driven API gateway — add GitHub, Jira, GitLab, Slack, or any REST API by writing a JSON file. Zero recompilation.
  • Fully static linking — only depends on KERNEL32.dll on Windows; zero shared deps for vendored Linux builds
  • Native HTTP — WinHTTP on Windows, vendored static libcurl on Linux/macOS
  • AES-256-GCM transport auth — platform-native crypto (BCrypt/CNG on Windows, OpenSSL on Unix)

Quick Start

Build (Windows)

git clone https://github.com/Charudatta999/cpp-mcp.git
cd cpp-mcp
cmake -B build -G Ninja -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_BUILD_TYPE=Release
cmake --build build

Build (Linux — vendored static)

# Build vendored OpenSSL 3.3 + curl 8.11 from source (one-time)
chmod +x third_party/build_deps.sh
third_party/build_deps.sh all

# Build cpp-mcp against vendored static libs
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j$(nproc)

# Clean source artifacts (keeps compiled static libs)
third_party/build_deps.sh clean

Build (Linux — Container, e.g. Oracle Linux 8)

podman build -t cpp-mcp-oel8 -f Containerfile.oel8 .
# Builds vendored deps, compiles, runs tests, verifies static linkage

Connect any REST API — no code needed

# GitHub — 11 tools, zero code
api_gateway configs/github.json

# Jira — 30 tools, zero code
api_gateway configs/jira.json

# GitLab — 5 tools, zero code
api_gateway configs/gitlab.json

# Your own API — write a JSON config, zero code
api_gateway configs/your_api.json

Use with Claude Desktop

{
  "mcpServers": {
    "github": {
      "command": "D:/path/to/api_gateway.exe",
      "args": ["D:/path/to/configs/github.json"],
      "env": { "GITHUB_TOKEN": "ghp_xxxxx" }
    }
  }
}

That's it. Claude can now list repos, search code, create issues, and more.


Features

Feature Details
MCP Primitives Tools, Resources, Prompts — full spec
JSON-RPC 2.0 Request, response, notification, error lifecycle
Stdio Transport For Claude Desktop, Cursor, VS Code Copilot, Windsurf
HTTP Client Transport WinHTTP (Windows), libcurl (Linux/macOS)
HTTP Server Transport Built-in TCP server for hosting MCP over HTTP POST
API Gateway Config-driven, supports any REST API
REST Auth Bearer token, Basic auth, API key header
Transport Auth AES-256-GCM encrypted token header (BCrypt on Windows, OpenSSL on Unix)
Path Templates {{variable}} substitution in URL paths
Param Routing Parameters auto-routed to path / query / body / header
Signal Handling Graceful SIGINT/SIGTERM shutdown with cleanup callbacks
Structured Logging Leveled logging (Trace→Fatal) with pluggable sinks
Static Linking Single binary, zero runtime dependencies
CI/CD GitHub Actions: Windows MSVC, Linux OEL8 glibc 2.28 (GCC 13), ASan/UBSan
Container Build Containerfile for Oracle Linux 8 (enterprise Linux)
C++20 No Boost, no heavy frameworks

The API Gateway

The killer feature. One compiled binary (api_gateway) turns any REST API into an MCP server at runtime via a JSON config:

Config Schema

{
  "server": {
    "name": "my-api",
    "version": "1.0.0"
  },
  "defaults": {
    "base_url": "https://api.example.com",
    "headers": {
      "Accept": "application/json"
    },
    "auth": {
      "type": "bearer",
      "token_env": "MY_API_TOKEN"
    }
  },
  "tools": [
    {
      "name": "list_items",
      "description": "List all items",
      "method": "GET",
      "path": "/v1/items",
      "parameters": [
        {
          "name": "limit",
          "type": "string",
          "description": "Max results",
          "required": false,
          "location": "query",
          "default": "10"
        }
      ]
    },
    {
      "name": "get_item",
      "description": "Get an item by ID",
      "method": "GET",
      "path": "/v1/items/{{item_id}}",
      "parameters": [
        {
          "name": "item_id",
          "type": "string",
          "description": "Item ID",
          "required": true,
          "location": "path"
        }
      ]
    },
    {
      "name": "create_item",
      "description": "Create a new item",
      "method": "POST",
      "path": "/v1/items",
      "parameters": [
        {
          "name": "title",
          "type": "string",
          "description": "Item title",
          "required": true,
          "location": "body"
        }
      ]
    }
  ]
}

Parameter Locations

Location Behavior
path Substituted into URL via {{name}} template
query Appended as ?key=value
body Assembled into JSON request body
header Sent as HTTP header

REST Auth Types

Type Config Env Vars
bearer "token_env": "VAR_NAME" VAR_NAME=ghp_xxx
basic "username_env" + "password_env" USER=x, PASS=y
api_key "header_name" + "key_env" KEY=xxx

Transport Authentication (AES-256-GCM)

For securing MCP transport channels (e.g. HTTP server mode), cpp-mcp provides symmetric-key authentication using AES-256-GCM:

  • 256-bit key, 96-bit random IV per encryption, 128-bit GCM auth tag
  • Encrypted token sent as Mcp-Auth-Token HTTP header
  • Server decrypts and validates at the transport layer, before any JSON-RPC dispatch

Key provisioning — pick whichever suits your deployment:

Source How
Environment variable MCP_AUTH_KEY=<64-hex-chars>
File Raw 32 bytes or 64 hex chars on disk
Programmatic Pass raw bytes via KeyConfig

Crypto backends — zero external deps on Windows:

Platform Backend Notes
Windows BCrypt (CNG) FIPS 140-2 certified, ships with OS
Linux/macOS OpenSSL libcrypto Hardware-accelerated, vendored or system

Pre-built API Configs

Ready-to-use configs in configs/:

GitHub — 11 tools

Search repos, list issues/PRs/commits, get file contents, create issues, and more.

export GITHUB_TOKEN=ghp_xxxxx
./api_gateway configs/github.json
Tool Description
get_user Get user profile
get_authenticated_user Get current user
list_repos List repos for user/org
get_repo Get repo details
list_issues List issues (state filter)
create_issue Create a new issue
list_pull_requests List PRs
get_file_contents Read file from repo
search_repos Search repositories
search_code Search code
list_commits List commits

Jira — 30 tools

Full Jira coverage including issues, sprints, boards, worklogs, and more.

export JIRA_EMAIL=you@company.com
export JIRA_API_TOKEN=your_token
./api_gateway configs/jira.json
Category Tools
Search jira_search
Issues jira_get_issue, jira_create_issue, jira_update_issue, jira_delete_issue, jira_assign_issue
Workflow jira_get_transitions, jira_transition_issue
Comments jira_add_comment, jira_get_comments
Worklogs jira_add_worklog, jira_get_worklogs
History jira_get_issue_history
Links jira_link_issues, jira_get_issue_watchers, jira_add_watcher
Projects jira_list_projects, jira_get_project, jira_list_issue_types, jira_list_statuses
Boards jira_list_boards, jira_get_board_backlog
Sprints jira_list_sprints, jira_get_sprint, jira_get_sprint_issues
Versions jira_list_versions, jira_get_version
Users jira_user_search, jira_get_myself
Server jira_get_server_info

GitLab — 5 tools

export GITLAB_TOKEN=glpat-xxxxx
./api_gateway configs/gitlab.json
Tool Description
list_projects List your projects
get_project Get project details
list_merge_requests List MRs
list_issues List issues
create_issue Create new issue

Writing Custom MCP Servers in C++

For cases where you need custom logic beyond REST API mapping:

Stdio Server

#include "mcp/mcp.hpp"

int main() {
    auto transport = std::make_unique<mcp::StdioTransport>();
    mcp::McpServer server({"my-server", "1.0.0"}, std::move(transport));

    mcp::ToolDefinition tool;
    tool.name        = "hello";
    tool.description = "Say hello";
    tool.input_schema.properties_json = R"({
        "name": {"type": "string", "description": "Who to greet"}
    })";
    tool.input_schema.required = {"name"};

    server.add_tool(tool, [](const mcp::ParamMap& args) {
        mcp::ToolResult r;
        r.content.push_back(mcp::TextContent{"Hello, " + args.at("name") + "!"});
        return r;
    });

    server.run();
}

HTTP Server

#include "mcp/mcp.hpp"

int main() {
    mcp::HttpServerConfig config;
    config.bind_address = "127.0.0.1";
    config.port = 8080;

    auto transport = std::make_unique<mcp::HttpServerTransport>(config);
    mcp::McpServer server({"my-server", "1.0.0"}, std::move(transport));

    // Register tools, resources, prompts...
    mcp::install_signal_handlers([&]() { server.stop(); });
    server.run();
}

HTTP Client

#include "mcp/mcp.hpp"

int main() {
    auto transport = std::make_unique<mcp::HttpClientTransport>(
        "http://localhost:8080");
    mcp::McpClient client(std::move(transport));

    client.initialize();

    auto tools = client.list_tools();
    for (const auto& t : tools)
        printf("Tool: %s\n", t.name.c_str());

    auto result = client.call_tool("hello", {{"name", "World"}});
    // result.content[0] -> TextContent{"Hello, World!"}
}

Project Structure

cpp-mcp/
├── CMakeLists.txt
├── Containerfile.oel8              # OEL8 container build (vendored static)
├── .github/workflows/ci.yml       # CI: Windows MSVC, Linux GCC/Clang, ASan
├── include/mcp/
│   ├── mcp.hpp                     # Umbrella include
│   ├── core/
│   │   ├── types.hpp               # MCP type definitions
│   │   ├── errors.hpp              # Error codes & exceptions
│   │   ├── json_utils.hpp          # JSON-RPC builders & parsers
│   │   └── log.hpp                 # Structured leveled logging
│   ├── transport/
│   │   ├── transport.hpp           # Abstract transport interface
│   │   ├── stdio_transport.hpp     # Stdin/stdout transport
│   │   ├── http_transport.hpp      # HTTP client transport (WinHTTP/curl)
│   │   └── http_server_transport.hpp # HTTP server transport (TCP)
│   ├── server/
│   │   ├── server.hpp              # MCP server
│   │   └── signal_handler.hpp      # Graceful shutdown signal handling
│   ├── client/
│   │   └── client.hpp              # MCP client
│   ├── auth/
│   │   └── auth.hpp                # AES-256-GCM transport auth
│   └── gateway/
│       └── api_gateway.hpp         # Config-driven API gateway
├── src/                            # Implementation files
├── examples/
│   ├── example_server.cpp          # Tool + Resource + Prompt demo
│   ├── example_calculator.cpp      # Calculator tool server
│   └── github_server.cpp           # Hardcoded GitHub server (legacy)
├── tests/
│   ├── cpp_mcp_tests.cpp           # Core protocol tests
│   └── auth_tests.cpp              # Auth module tests
├── benchmarks/
│   └── benchmark_smoke.cpp         # Benchmark smoke tests
├── configs/                        # Ready-to-use API configs
│   ├── github.json                 # GitHub API — 11 tools
│   ├── jira.json                   # Jira API — 30 tools
│   └── gitlab.json                 # GitLab API — 5 tools
└── third_party/
    ├── rapidjson/                  # Header-only JSON (bundled)
    └── build_deps.sh              # Vendored OpenSSL + curl builder

Building

Windows (Clang + Ninja — recommended)

cmake -B build -G Ninja -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_BUILD_TYPE=Release
cmake --build build

Windows (MSVC)

cmake -B build -G "Visual Studio 17 2022"
cmake --build build --config Release

Linux (vendored static — recommended for deployment)

# One-time: build vendored OpenSSL 3.3 + curl 8.11 from source
third_party/build_deps.sh all

# Build (auto-detects vendored libs, enables curl)
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j$(nproc)

# Verify: no shared openssl/curl/crypto dependencies
ldd build/api_gateway | grep -E 'libssl|libcurl|libcrypto'  # should be empty

Linux (system libraries)

# Install deps (Ubuntu/Debian)
sudo apt install libcurl4-openssl-dev libssl-dev

cmake -B build -DMCP_USE_CURL=ON -DCMAKE_BUILD_TYPE=Release
cmake --build build -j$(nproc)

Container (Oracle Linux 8)

podman build -t cpp-mcp-oel8 -f Containerfile.oel8 .

Builds vendored OpenSSL + curl from source, compiles with GCC 13 + -Werror, runs tests, and verifies fully static linkage.

CMake Options

Option Default Description
MCP_BUILD_EXAMPLES ON Build example programs
MCP_BUILD_GATEWAY ON Build the API gateway executable
MCP_BUILD_TESTS ON Build the test suite
MCP_BUILD_BENCHMARKS ON Build benchmark executables
MCP_USE_CURL OFF Enable libcurl HTTP backend (Linux/macOS)
MCP_WARNINGS_AS_ERRORS OFF Treat compiler warnings as errors
MCP_ENABLE_SANITIZERS OFF Enable ASan + UBSan (Clang/GCC)

Tests

ctest --test-dir build --output-on-failure

HTTP Backend

Platform Backend Dependencies
Windows WinHTTP None (system DLL)
Linux libcurl Vendored static or system (-DMCP_USE_CURL=ON)
macOS libcurl Vendored static or system (-DMCP_USE_CURL=ON)

Client Configuration

Claude Desktop

Add to %APPDATA%\Claude\claude_desktop_config.json (Windows) or ~/Library/Application Support/Claude/claude_desktop_config.json (macOS):

{
  "mcpServers": {
    "github": {
      "command": "D:/path/to/api_gateway.exe",
      "args": ["D:/path/to/configs/github.json"],
      "env": { "GITHUB_TOKEN": "ghp_xxxxx" }
    },
    "jira": {
      "command": "D:/path/to/api_gateway.exe",
      "args": ["D:/path/to/configs/jira.json"],
      "env": {
        "JIRA_EMAIL": "you@company.com",
        "JIRA_API_TOKEN": "your_token"
      }
    }
  }
}

VS Code (GitHub Copilot)

Add .vscode/mcp.json to your workspace:

{
  "servers": {
    "github": {
      "type": "stdio",
      "command": "D:/path/to/api_gateway.exe",
      "args": ["D:/path/to/configs/github.json"],
      "env": { "GITHUB_TOKEN": "ghp_xxxxx" }
    }
  }
}

Cursor

Add to .cursor/mcp.json:

{
  "mcpServers": {
    "github": {
      "command": "D:/path/to/api_gateway.exe",
      "args": ["D:/path/to/configs/github.json"],
      "env": { "GITHUB_TOKEN": "ghp_xxxxx" }
    }
  }
}

Windsurf

Add to ~/.codeium/windsurf/mcp_config.json (same format as Cursor).


Adding a New API

  1. Create a JSON file (e.g. configs/slack.json)
  2. Define server, defaults (base URL, auth), and tools (endpoints + params)
  3. Run: ./api_gateway configs/slack.json

No C++ code. No recompilation. Same binary.

Example — Slack in 15 lines:

{
  "server": { "name": "slack", "version": "1.0.0" },
  "defaults": {
    "base_url": "https://slack.com/api",
    "auth": { "type": "bearer", "token_env": "SLACK_TOKEN" }
  },
  "tools": [
    {
      "name": "post_message",
      "description": "Post a message to a Slack channel",
      "method": "POST",
      "path": "/chat.postMessage",
      "parameters": [
        { "name": "channel", "type": "string", "description": "Channel ID", "required": true, "location": "body" },
        { "name": "text", "type": "string", "description": "Message text", "required": true, "location": "body" }
      ]
    }
  ]
}

CI

GitHub Actions runs on every push and PR to main:

Job Platform Compiler glibc What
Windows windows-latest MSVC N/A Debug + Release, tests
Linux (OEL8) Oracle Linux 8 container GCC 13 2.28 Release, vendored static, -Werror, tests, linkage verification, binary artifacts
Sanitizers ubuntu-latest Clang 17 ~2.39 Debug, ASan + UBSan

Linux binaries are built against glibc 2.28 (the lowest supported enterprise glibc) and uploaded as CI artifacts — portable to RHEL 8+, OEL 8+, Amazon Linux 2, and any distro with glibc >= 2.28.


License

LGPL-3.0 — you can link cpp-mcp into commercial/proprietary products without open-sourcing your application. If you modify cpp-mcp itself, those modifications must be released under LGPL-3.0.


Comparison with Other MCP Implementations

cpp-mcp Python/TS MCP servers Other C++ MCP libs
Runtime deps None (static binary) Python/Node.js + 200+ packages Dynamic libs (httplib, nlohmann-json)
Supply chain surface RapidJSON only (header-only, bundled) PyPI/npm ecosystem Git submodules
API gateway Config-driven, zero code Requires code per integration Not available
Transport auth AES-256-GCM (platform-native) Token headers Token headers
Enterprise Linux OEL8/glibc 2.28, CI-verified static Depends on system Python Not addressed
Binary size Single static executable Entire runtime + venv Dynamic, multiple shared libs

Keywords: C++ MCP server, Model Context Protocol C++, MCP SDK C++, MCP API gateway, cpp mcp framework, C++ AI agent, MCP static binary, secure MCP server, MCP Claude Desktop, MCP VS Code, MCP Cursor, JSON-RPC C++, REST to MCP, supply chain secure MCP, enterprise MCP server, C++20 MCP, static linked MCP, AES-256-GCM MCP auth, MCP server no dependencies, MCP alternative to Python, mcp-server-cpp

About

C++20 MCP framework — config-driven API gateway, AES-256-GCM auth, fully static binary. Turn any REST API into an MCP server with zero code. No Python. No npm. No supply chain risk.

Topics

Resources

License

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors