modelcontextprotocol-cpp-sdk MCP server
Commit Nov 4, 2026A C++17 implementation of the Model Context Protocol providing client and server libraries for building AI tooling integrations.
Also known as jesspig/modelcontextprotocol-cpp-sdk
- Stars
- 3
- Tools
- —
- Downloads, 30 days
- —
- Latest version
- —
- Last commit
- Nov 4, 2026
- License
- MIT
What is modelcontextprotocol-cpp-sdk MCP?
modelcontextprotocol-cpp-sdk is a C++17 implementation of the Model Context Protocol providing client and server libraries for building AI tooling integrations.
Summary generated from the project's README
About modelcontextprotocol-cpp-sdk MCP server
This C++17 SDK provides a complete implementation of the Model Context Protocol for developers building AI tooling integrations. It includes both client and server libraries, allowing users to create servers that expose tools, resources, and prompts to LLM applications or build clients that connect to existing MCP servers. The library is designed for high performance and can be integrated into CMake projects using FetchContent.
Developers can choose from several transport methods including stdio, SSE, WebSocket, and Streamable HTTP. The SDK supports advanced features like OAuth with PKCE, token refresh, and DPoP for secure authentication. It is compatible with Windows, Linux, and macOS, requiring CMake 3.28 and a C++17 compliant compiler such as MSVC, Clang, or GCC. For users requiring TLS or specific OAuth features, OpenSSL can be integrated as an optional dependency.
What you can do with it
- 1Expose custom tools to LLMsA developer can create an MCP server that registers specific functions, like an echo tool, for an AI to call.
- 2Connect to remote AI servicesYou can build a client that discovers and interacts with various MCP servers using different communication protocols.
- 3Implement secure authenticationIntegrate OAuth flows with PKCE to manage secure user authorization and token management within your C++ application.
Written from the project's README. Every use case is checked against a quote from it.
README
View on GitHubMCP C++ SDK
中文版文档:README_zh.md
C++17 implementation of the Model Context Protocol (MCP), providing both client and server libraries for building MCP-based AI tooling integrations.
- What is MCP?
- Requirements
- Installation
- Quick Start
- Architecture
- Transports
- Usage
- OAuth Support
- Protocol Versions
- Migration
- Conformance Tests
- Examples
- Related Projects
- Non-standard Extensions
- Unsupported Declarations
- License
What is MCP?
The Model Context Protocol lets you build servers that expose data and functionality to LLM applications in a secure, standardized way. With this SDK you can:
- Build MCP servers that expose tools, resources, and prompts to any MCP host
- Build MCP clients that connect to any MCP server
- Support every standard transport: stdio, Streamable HTTP, SSE, WebSocket
Requirements
| Dependency | Minimum Version | Notes |
|---|---|---|
| CMake | 3.28 | Generator: Ninja recommended |
| C++ Compiler | C++17 | MSVC, Clang, GCC |
| OpenSSL | (optional) | Controlled by the MCP_WITH_OPENSSL switch (AUTO/ON/OFF, default AUTO). Required for TLS (WebSocket, SSE HTTPS); OAuth PKCE works without it (built-in SHA-256 fallback). Supports 3.x/4.x. Install: vcpkg install openssl / apt install libssl-dev / brew install openssl |
Supported platforms: Windows (MSVC, clang-cl), Linux (GCC, Clang), macOS (Clang).
Installation
Consume the SDK in your own CMake project via FetchContent:
include(FetchContent)
FetchContent_Declare(
mcp-cpp-sdk
GIT_REPOSITORY https://github.com/jesspig/modelcontextprotocol-cpp-sdk.git
GIT_TAG master
)
FetchContent_MakeAvailable(mcp-cpp-sdk)
target_link_libraries(your_target PRIVATE mcp-client mcp-server)
Available library targets: mcp-core, mcp-transport, mcp-protocol, mcp-server, mcp-client, mcp-http, mcp-ext. All libraries are static.
Quick Start
cmake --preset debug
cmake --build --preset debug
ctest --preset debug --output-on-failure
Configure presets: debug, release. Ninja generator required.
Architecture
┌─────────────────────────────────────┐
│ mcp-server mcp-client │ Server & Client API
├─────────────────────────────────────┤
│ mcp-protocol │ WireCodec, McpSessionHandler
├─────────────────────────────────────┤
│ mcp-transport mcp-http │ Transports, Streamable HTTP, SSE
├─────────────────────────────────────┤
│ mcp-core │ Types, JSON-RPC, interfaces
└─────────────────────────────────────┘
Library dependency chain: mcp-core (STATIC) → mcp-transport → mcp-protocol → mcp-server | mcp-client, and both of those also link mcp-ext (apps, DPoP, server card, triggers). mcp-http depends on mcp-transport and mcp-ext. All libraries are static.
- mcp-core — Core types, JSON-RPC message structures, error codes, capabilities, content types, transport interfaces.
- mcp-transport — Transport implementations: StdioServerTransport, StdioClientTransport, SseClientTransport, InMemoryTransport, WebSocketClientTransport, StreamableHttpServerTransport, StreamableHttpClientTransport. Platform-specific I/O in
detail/(posix, win32). - mcp-protocol —
McpSessionHandler(JSON-RPC engine), dual-eraWireCodec(2025-11-25 / 2026-07-28), request/response correlation with timeout,MessageFilterpipeline. - mcp-server —
McpServerwith tool/resource/prompt registration,IMcpTaskStore(incl.FileTaskStore), MRTR (InputRequiredResult), server → client elicitation, subscription management. - mcp-client —
McpClientwith server discovery (server/discover→ initialize fallback), version negotiation, OAuth (PKCE/CIMD with DCR fallback), MRTR (InputRequired loop), tool cache,FileTokenCache. - mcp-http — HTTP server for Streamable HTTP mode:
HttpServer,EventStore(SSE event persistence),StreamableHttpServerTransport,StreamableHttpClientTransport.
All transports
| Transport | Client | Server | Description |
|---|---|---|---|
| Stdio | Yes | Yes | stdin/stdout pipes, subprocess communication |
| Streamable HTTP | Yes | Yes | HTTP POST with JSON/session-mode responses |
| SSE | Yes | Yes¹ | Server-Sent Events for push notifications |
| WebSocket | Yes | No | TCP-based bidirectional (self-hosted WebSocketClient) |
| InMemory | Yes | Yes | In-process transport for testing |
¹ SSE server-side is provided through
StreamableHttpServerTransportwhenenable_legacy_sseistrue, which serves an SSE stream via HTTP GET.
Usage
Server
#include <mcp/server/McpServer.hpp>
#include <mcp/transport/StdioServerTransport.hpp>
using namespace mcp;
int main() {
auto transport = std::make_shared<StdioServerTransport>();
ServerOptions opts;
opts.server_info = Implementation{"MyServer", "1.0.0"};
auto server = McpServer::Create(transport, opts);
server->RegisterTool("echo",
ToolOptions{}.Description("Echo input text back"),
[](const RequestContext<CallToolRequestParams>& ctx) -> CallToolResult {
std::string text;
if (ctx.Params().arguments) {
auto* v = ctx.Params().arguments->Find("text");
if (v) text = v->GetString();
}
CallToolResult result;
result.content.push_back(TextContent{"text", text});
return result;
});
server->Run();
return 0;
}
Client
#include <mcp/client/McpClient.hpp>
#include <mcp/transport/StdioClientTransport.hpp>
using namespace mcp;
StdioClientTransportOptions transport_opts;
transport_opts.command = "path/to/server";
auto factory = std::make_shared<StdioClientTransport>(transport_opts);
auto transport = factory->Connect();
ClientOptions opts;
opts.client_info = Implementation{"MyClient", "1.0.0"};
auto client = McpClient::Create(transport, opts);
auto tools = client->ListTools();
for (const auto& tool : tools.tools) {
std::cout << tool.name << "\n";
}
auto result = client->CallTool("echo",
JsonValue::Object{{"text", "Hello, MCP!"}});
Handlers can be supplied before negotiation through ClientOptions: elicitation_handler, url_elicitation_handler, sampling_handler (legacy), and roots_handler (legacy). DeriveClientCapabilities advertises the matching capabilities automatically and only fills in what an explicit capabilities value leaves out. MRTR is driven automatically by default (input_required_config, auto_fulfill=true, 10 rounds); assign std::nullopt to input_required_config to receive input_required results unfulfilled. url_elicitation_handler returns an ElicitResult whose action must be accept, decline, or cancel (no handler means decline); the deprecated void callback remains available as SetLegacyUrlElicitationHandler and fixes the action to accept. ClientOptions::cache_auth_context returns an authorization context so private cached responses are partitioned per context and cleared when it changes. For custom methods, SendRequest / SendNotification / CancelRequest provide raw control, and SetLoggingLevel sends logging/setLevel on legacy sessions only (modern sessions reject it; pass logLevel per request instead).
OAuth Support
The client supports the MCP OAuth authorization flow:
- Authorization Code + PKCE flow with S256 code challenge
- CIMD client identity with DCR fallback (an
http(s)://client_idis fetched as a client metadata document; dynamic registration only when noclient_idis configured) - Token refresh and revocation
- Pluggable token cache (
ITokenCache), persistentFileTokenCacheincluded - DPoP (RFC 9449): server-side proof verification on the Streamable HTTP resource server — off by default, turned on per deployment with the experimental
enable_dpopswitch (StreamableHttpServerOptions::bearer_auth->enable_dpop), and requires OpenSSL; the client side can bind the authorization scheme and mint proofs (OAuthClientOptions::enable_dpop), but transports attach per-requestDPoPproof whenapply_per_request_headers/observe_response_challengeare bound viaApplyDPoPProofHeader/ObserveDPoPNonce
OAuthClientOptions oauth_opts;
oauth_opts.server_url = "https://auth.server.com/.well-known/oauth-authorization-server";
oauth_opts.client_id = "client-id";
oauth_opts.redirect_uri = "http://localhost:3000/callback";
OAuthClientProvider auth(oauth_opts);
auth.Authenticate();
Protocol Versions
| Version | Status | Key Features |
|---|---|---|
| 2025-11-25 | Legacy | initialize handshake, standalone sampling/roots/list |
| 2026-07-28 | Current | server/discover, per-request _meta, MRTR (InputRequiredResult), subscriptions/listen |
The WireCodec factory auto-selects the correct codec for the negotiated version via a simple string comparison (version >= "2026-07-28").
Documentation
The online manual is published at https://jesspig.github.io/modelcontextprotocol-cpp-sdk/ and lives in docs/en (Chinese mirror in docs/zh). It is organised in three layers — concepts, task-shaped how-tos, and an API reference:
- Quick start — five minutes to a working server and client, with expected output.
- Installation — dependencies, build options, CMake integration, optional OpenSSL.
- Protocol versions — the authoritative matrix of both eras.
- Register a tool — descriptions, input schema, annotations, structured output.
- Connect to a server — transports, connect modes, close timing.
- Handle errors — the three failure channels and error-code remapping.
- API reference — tables only: signatures, defaults, throws, source files.
All C++ samples come from docs/snippets, which is compiled by the mcp-docs-snippets target in CI, so a renamed or changed API fails the docs build instead of silently rotting the manual.
Migration
- 0.3.9 migration guide — 0.3.8 → 0.3.9 breaking changes with old/new forms and impact.
- 0.3.10 release notes — new APIs, behavior fixes, limits; the 0.3.9 breaks remain and are not restored.
- 0.3.11 release notes — contract attributes, stricter behavior, and deprecations;
ResourceNotFoundis deprecated since 0.3.11 and removed in 0.4.0.
The mcp-compat-smoke target compiles the previous public API and allowlists known breaks in tests/compat/expected_breaks.txt. Run cmake --build --preset debug --target mcp-compat-smoke. Deprecated items are registered in the deprecation registry.
Conformance Tests
124 conformance tests covering protocol type serialization across both eras:
- JSON-RPC message round-trips (request, notification, response, error)
- WireCodec era-gating (2025 vs 2026 method/notification sets)
- Tool, Resource, Prompt serialization with annotations and icons
- Content variant dispatch (text, image, audio, embedded resource)
- Elicitation and ElicitResultTyped
- MRTR (InputRequiredResult, InputRequests, factory helpers)
- Structured meta (RequestMetaObject, NotificationMetaObject)
- Extensions capability, ResultType enum, SubscriptionFilter
- Tasks (get/update/cancel), Logging (8 levels)
- Pagination, caching, protocol version helpers
Examples
Runnable examples in examples/:
| Example | Description |
|---|---|
| EchoServer | Minimal server with tool, resource, and prompt |
| WeatherServer | Server with external API integration |
| SimpleClient | Client that connects to a server in-process |
Build and run:
cmake --preset debug -DMCP_BUILD_EXAMPLES=ON
cmake --build --preset debug
# Run the echo server:
build/debug/examples/EchoServer/EchoServer
References
This SDK was developed against the official MCP protocol specification and reference implementations:
| Language | Repository | Tier |
|---|---|---|
| Python | modelcontextprotocol/python-sdk | Tier 1 |
| TypeScript | modelcontextprotocol/typescript-sdk | Tier 1 |
| Go | modelcontextprotocol/go-sdk | Tier 1 |
| C# | modelcontextprotocol/csharp-sdk | Tier 1 |
| Rust | modelcontextprotocol/rust-sdk | Tier 1 |
| Ruby | modelcontextprotocol/ruby-sdk | Tier 1 |
| Java | modelcontextprotocol/java-sdk | Tier 2 |
| Swift | modelcontextprotocol/swift-sdk | Tier 3 |
| PHP | modelcontextprotocol/php-sdk | Tier 3 |
| Kotlin | modelcontextprotocol/kotlin-sdk | Tier 3 |
Tiers follow the official SDK list (2026-07-28 revision): 6 Tier 1 (TypeScript, Python, C#, Go, Rust, Ruby — Rust promoted to Tier 1 via PR #3287 on 2026-08-21), Java is Tier 2, Swift/PHP/Kotlin are Tier 3. Tier rules: SDK Tiering System — experimental features and protocol extensions (such as Tasks and MCP Apps) are not required for any tier.
Ruby SDK cross-check
Implementation notes on the official Ruby SDK (mcp gem, main branch as of 2026-10-11; latest release 1.7.0 dated 2026-10-05, see CHANGELOG.md and version.rb), compared with this SDK per dimension:
| Dimension | Ruby (mcp gem) |
This SDK |
|---|---|---|
| Spec revisions | 2025-06-18, 2025-11-25, 2026-07-28 (ROADMAP.md, Current Status) | 2024-11-05…2026-07-28, dual-era codec (see Protocol Versions above) |
server/discover |
Modern era never negotiated via initialize (CHANGELOG §1.2.0); server/discover finalized with modern client support; per-transport era lock on stdio, sessionless modern path on Streamable HTTP (methods.rb) |
Auto mode with transport-classified fallback (version-negotiation) |
| MRTR | SEP-2322 input_required results with inputRequests/inputResponses + requestState, fulfilled on the legacy wire too (CHANGELOG §0.24.0/§1.2.0); resultType is only complete/input_required (result_type.rb) |
InputRequiredResult + elicitation loop (mrtr); additional task resultType for task handles |
| Headers | Sends SEP-2243 Mcp-Method/Mcp-Name, mirrors x-mcp-header params into Mcp-Param-* (CHANGELOG §0.22.0/§1.2.0; mcp_param_headers.rb); Mcp-Method required on the modern path |
Mcp-Name validation incl. tasks taskId check (mcp-param-headers, tasks-extension) |
| Cache | Server stamps SEP-2549 ttlMs/cacheScope (CHANGELOG §0.24.0/§1.2.0); no client-side response cache: lib/mcp/client/ holds only elicitation, http, mcp_param_headers, modern_envelope, oauth(+oauth/), paginated_result, stdio, tool, and client/http.rb matches no ttlMs/cacheScope/cache-hit logic (verified 2026-10-13 against main) |
Client response cache consuming both the 2026 top-level ttlMs/cacheScope and the 2025 nested cacheHint, with TTL + public/private partitions (response-cache) |
| Auth | Full OAuth 2.1 client (DCR, PKCE, CIMD, client_credentials, private_key_jwt, jwt-bearer, RFC 9207 iss, PRM-first discovery; CHANGELOG §0.17.0–§1.6.0) + server resource-server protection (README Features) |
PKCE/CIMD (DCR fallback) + FileTokenCache, server Bearer auth, opt-in server-side DPoP proof verification (dpop; see OAuth Support above) |
| Tasks (SEP-2663) | Not implemented — "remains planned" (ROADMAP.md, #391) | tasks/get|update|cancel dual-era + FileTaskStore (tasks-extension) |
| Skills (SEP-2640) | Not implemented【假设:methods.rb 方法全集、lib/mcp/、lib/mcp/client/、test/mcp/ 均无 skills 条目,CHANGELOG 全版本无 skills 记载】 |
skills/list|get + resources/directory/read, 2026-only (skills-extension) |
Non-standard Extensions
These capabilities are SDK extensions, not part of the 2026 core specification; each is opt-in and degrades to the baseline path when a peer does not implement it.
- ETag conditional requests — an SDK extension independent of the 2026
ttlMs/cacheScoperesponse cache. The client stores response bodies and sends_meta.ifNoneMatchwhenClientOptions::enable_etag_cache(default true) and the globalSetEtagCacheEnabledgate are both on; the server enables the gate throughServerOptions::enable_etag_cache(default false). Peers that do not implement the extension ignore it and return full responses, while TTL caching continues to work independently. - Progressive discovery /
SearchTools— an experimental SDK extension disabled by default on both sides (ServerOptions::enable_progressive_discovery/ClientOptions::enable_progressive_discovery). When enabled, the server acceptsquery/pageSizeontools/listand the client exposesSearchTools(query, page_size); it is not part of the 2026 core specification, and with the flags offSearchToolsdegrades to plain paginatedtools/list. - Server Cards — the server can generate a card (
McpServer::GetServerCard()) and expose it over Streamable HTTP atGET /server-cardwhenenable_server_cardis configured onServerOptions/StreamableHttpServerOptions; the client does not consume server cards, andserverInfofrom the handshake remains its identity source.
Unsupported Declarations
The following items are explicitly declared unsupported in this round; when a peer sends them, this SDK degrades gracefully (ignores the unknown field or falls back to the baseline path) instead of failing the session.
- Apps UI rendering — server-pushed UI components are not rendered and pass through as opaque data only.
- Full sampling — sampling is legacy partial only: the deprecated
sampling_handlercovers basic form and single-content sampling, and the modern 2026 era is not treated as a complete sampling capability; full sampling is out of scope for this round and is not counted as a Tier 1 parity closure item. - EMA — EMA negotiation is not implemented and peers fall back to baseline capability negotiation.
- DPoP client-side per-request proofs — server-side proof verification is implemented (off by default, experimental
enable_dpop, requires OpenSSL; see OAuth Support above); without the two callbacks above no proof is attached, while configured callbacks drive a DPoP session with a singleuse_dpop_nonceretry; with the switch off the plain Bearer path is unchanged (dpop). - jwt-bearer —
private_key_jwtclient authentication is supported (an ES256 client assertion is sent on the token requests whenprivate_key_pemis configured and the authorization server advertisesprivate_key_jwtintoken_endpoint_auth_methods_supported; requires OpenSSL), while the authorization-ownerjwt-bearergrant is not, and the public-client PKCE/CIMD flow remains the supported path. - File Uploads — resumable file-upload primitives are not implemented, and file content moves through existing tool/resource payloads only.
modelcontextprotocol-cpp-sdk MCP questions
What platforms are supported by the SDK?
The SDK supports Windows (MSVC, clang-cl), Linux (GCC, Clang), and macOS (Clang).
What transport methods are available?
It supports Stdio, Streamable HTTP, SSE, WebSocket, and InMemory transports.
Does the SDK support OAuth?
Yes, the client supports OAuth authorization flows including Authorization Code + PKCE, token refresh, and revocation.
How do I install the SDK in a CMake project?
You can consume the SDK using FetchContent in your CMake configuration.