Install
$ agentstack add mcp-laplaceliu-mcpp ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ● Network access Used
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
MCPP - Modern C++ MCP Framework
A Modern C++ implementation of the Model Context Protocol (MCP), designed to be a balanced framework between simplicity and completeness.
Features
- 100% Header-Only - No compilation of core library needed, just include and use
- Full MCP Protocol Support (version 2025-06-18)
- Multiple Transport Layers:
- Stdio: Local process communication via stdin/stdout
- HTTP/SSE: Remote communication with Server-Sent Events
- WebSocket: Bidirectional real-time communication (client & server modes)
- Server Capabilities: Tools, Resources, Prompts, Sampling, Elicitation, Logging
- Client Capabilities: Full client-side MCP support
- Enterprise Features:
- Middleware/Filter Chain framework
- Token Bucket Rate Limiting
- Circuit Breaker pattern
- Prometheus Metrics export
- Bearer Token Authentication with RBAC
Requirements
- C++14 compatible compiler (GCC 7+, Clang 5+, MSVC 2019+)
- CMake 3.10+
- OpenSSL (libssl-dev on Ubuntu/Debian)
- Dependencies (managed via CMake FetchContent):
- nlohmann/json 3.10.5
- cpp-httplib 0.15.3
- libwebsockets 4.3.4
- GoogleTest 1.14.0
Installation
Quick Start
# Clone the repository
git clone https://github.com/laplaceliu/mcpp.git
cd mcpp
# Create build directory
mkdir build && cd build
# Configure with CMake
cmake ..
# Build (header-only - only examples and tests need compilation)
make -j$(nproc)
# Run tests
ctest --output-on-failure
Dependencies
The project uses CMake FetchContent to download dependencies. The dependency management is in _deps/CMakeLists.txt.
Required system packages:
- Ubuntu/Debian:
sudo apt-get install libssl-dev - macOS: OpenSSL is included (or
brew install opensslif needed) - Fedora/RHEL:
sudo dnf install openssl-devel
Build Options
| Option | Default | Description | |--------|---------|-------------| | MCPP_BUILD_TESTS | ON | Build unit tests | | MCPP_BUILD_EXAMPLES | ON | Build example applications |
Project Structure
mcpp/
├── include/mcpp/
│ ├── core/ # Core types and utilities
│ │ ├── json.hpp # JSON type aliases
│ │ ├── types.hpp # MCP protocol types
│ │ └── error.hpp # Error handling
│ ├── protocol/ # JSON-RPC protocol
│ │ ├── message.hpp # Message parsing/serialization
│ │ ├── request.hpp # Request routing
│ │ └── response.hpp
│ ├── transport/ # Transport layers
│ │ ├── itransport.hpp # ITransport interface
│ │ ├── factory.hpp # TransportFactory
│ │ ├── transport.hpp # Backwards compatibility (includes factory.hpp)
│ │ ├── stdio.hpp # stdio transport
│ │ ├── http.hpp # HTTP/SSE transport
│ │ └── websocket.hpp # WebSocket transport (libwebsockets)
│ ├── server/ # Server implementation
│ │ ├── server.hpp
│ │ ├── tool.hpp
│ │ ├── resource.hpp
│ │ └── prompt.hpp
│ ├── client/ # Client implementation
│ │ └── client.hpp
│ └── enterprise/ # Enterprise features
│ ├── middleware.hpp
│ ├── ratelimit.hpp
│ ├── circuit.hpp
│ ├── metrics.hpp
│ └── auth.hpp
├── src/ # (Empty - header-only library)
├── tests/ # Unit tests
└── examples/ # Example applications
Note: This is a 100% Header-Only library. No source files need to be compiled for the core library. Simply include the headers and link to OpenSSL and libwebsockets.
Usage
Creating a Server
#include "mcpp/server/server.hpp"
#include
using namespace mcpp;
// Define a tool handler
CallToolResult echo_tool(const std::string& name, const JsonValue& args) {
CallToolResult result;
result.is_error = false;
std::string input = args.value("message", std::string());
result.content.push_back(JsonValue::object({
{"type", "text"},
{"text", "Echo: " + input}
}));
return result;
}
int main() {
// Create server options
ServerOptions options;
options.name = "my-server";
options.version = "1.0.0";
options.capabilities.supports_tools = true;
options.capabilities.supports_resources = true;
// Create and start server
Server server(options);
// Register tools
server.register_tool(
"echo",
"Echo back the input message",
JsonValue::object({
{"type", "object"},
{"properties", JsonValue::object({
{"message", JsonValue::object({
{"type", "string"},
{"description", "Message to echo"}
})}
})},
{"required", JsonValue::array({"message"})}
}),
echo_tool
);
// Start server with stdio transport (default)
server.start();
server.wait();
return 0;
}
Using Different Transports
#include "mcpp/transport/transport.hpp"
using namespace mcpp;
// Create transport using factory
auto transport = TransportFactory::create(TransportFactory::Type::Stdio);
// Or by name
auto http_transport = TransportFactory::create("http");
auto ws_transport = TransportFactory::create("websocket");
// Configure WebSocket transport
WebSocketConfig ws_config;
ws_config.host = "localhost";
ws_config.port = 8080;
ws_config.path = "/mcp";
ws_config.is_server = false; // Client mode
ws_config.use_ssl = false;
WebSocketTransport ws(ws_config);
ws.on_message([](const std::string& msg) {
// Handle incoming message
});
ws.start();
Creating a Client
#include "mcpp/client/client.hpp"
#include
using namespace mcpp;
int main() {
ClientOptions options;
options.name = "my-client";
options.version = "1.0.0";
options.transport_type = TransportFactory::Type::Stdio;
auto client = std::make_shared(options);
// Handle sampling requests from server
client->on_sampling_request([](const SamplingParams& params) {
SamplingResult result;
result.is_error = false;
result.content = /* ... */;
return result;
});
// Handle elicitation requests
client->on_elicitation_request([](const ElicitationParams& params) {
ElicitationResult result;
result.is_error = false;
result.content = /* ... */;
return result;
});
client->start();
client->wait();
return 0;
}
Using Enterprise Features
Rate Limiting
#include "mcpp/enterprise/ratelimit.hpp"
using namespace mcpp::enterprise;
// Create rate limiter with custom config
RateLimiter::Config config;
config.tokens_per_second = 100;
config.max_tokens = 100;
config.tokens_per_request = 1;
RateLimiter limiter(config);
// Check if request is allowed
auto result = limiter.check("user_id");
if (result.allowed) {
// Process request
} else {
// Rate limited - retry_after_ms until more tokens
}
Circuit Breaker
#include "mcpp/enterprise/circuit.hpp"
using namespace mcpp::enterprise;
CircuitBreaker breaker("my-service", CircuitBreaker::Config());
// Execute with circuit breaker protection
auto result = execute_with_circuit(
breaker,
[]() { return call_service(); }, // Primary function
[]() { return fallback_value(); } // Fallback when circuit open
);
Prometheus Metrics
#include "mcpp/enterprise/metrics.hpp"
using namespace mcpp::enterprise;
// Register metrics
auto& registry = MetricsRegistry::instance();
registry.counter("requests_total", "Total requests")->increment();
registry.gauge("active_connections", "Active connections")->set(42);
registry.histogram("request_duration", "Request duration")->observe(0.123);
// Export metrics in Prometheus format
std::string output = registry.export_prometheus();
Authentication & RBAC
#include "mcpp/enterprise/auth.hpp"
using namespace mcpp::enterprise;
// Create authorizer with RBAC
Authorizer authorizer;
// Add roles and permissions
authorizer.add_permission("admin", "tools:*");
authorizer.add_permission("user", "tools:read");
authorizer.add_role("user1", "admin");
// Check permissions
if (authorizer.has_permission("user1", "tools:read")) {
// Access granted
}
// Generate and validate tokens
Token token = authorizer.generate_token("user1", std::chrono::hours(24));
if (authorizer.validate_token(token)) {
// Token valid
}
Testing
# Run all tests
ctest --output-on-failure
# Or run tests directly
./build/bin/tests
# Run specific test suite
./build/bin/tests --gtest_filter="RateLimiterTest.*"
# Run transport tests only
./build/bin/tests --gtest_filter="*Transport*"
Test Coverage: 109 tests across 14 test suites covering:
- JSON parsing and serialization
- JSON-RPC message protocol
- Server primitives (Tools, Resources, Prompts)
- Transport layers (Stdio, HTTP/SSE, WebSocket)
- Enterprise features (Rate limiting, Circuit breaker, Metrics)
API Reference
Server
Server::Server(ServerOptions)- Create server with optionsServer::start()- Start the serverServer::stop()- Stop the serverServer::wait()- Wait for shutdownServer::register_tool(...)- Register a toolServer::register_resource(...)- Register a resourceServer::register_prompt(...)- Register a prompt
Client
Client::Client(ClientOptions)- Create client with optionsClient::start()- Start the clientClient::stop()- Stop the clientClient::on_sampling_request(...)- Set sampling handlerClient::on_elicitation_request(...)- Set elicitation handlerClient::on_progress_notification(...)- Set progress handlerClient::logging_message(...)- Send logging message
Transport
TransportFactory::create(Type)- Create transport by type (Stdio/Http/WebSocket)TransportFactory::create(string)- Create transport by name ("stdio"/"http"/"websocket")ITransport::start()- Start transportITransport::stop()- Stop transportITransport::send(message)- Send messageITransport::on_message(handler)- Set message handlerITransport::on_error(handler)- Set error handlerWebSocketTransport::WebSocketTransport(Config)- Create with configWebSocketTransport::set_url(url)- Set WebSocket URLWebSocketFramer::frame(message)- Frame WebSocket message (RFC 6455)StdioFramer::frame/decode- Frame/decode stdio messagesHttpFramer::frame/frame_sse- Frame HTTP messages/SSE events
Enterprise
RateLimiter::check(key)- Check rate limit for keyCircuitBreaker::allow_request()- Check if request allowedCircuitBreaker::record_success()- Record successful callCircuitBreaker::record_failure()- Record failed callMetricsRegistry::counter(name, help)- Get/create counterMetricsRegistry::gauge(name, help)- Get/create gaugeMetricsRegistry::histogram(name, help)- Get/create histogramAuthorizer::has_permission(role, permission)- Check permissionAuthorizer::generate_token(user_id, duration)- Generate token
Documentation
Building API Documentation
This project uses Doxygen for API documentation. To generate the documentation:
# Install Doxygen (if not already installed)
# Ubuntu/Debian:
sudo apt-get install doxygen
# macOS:
brew install doxygen
# Fedora/RHEL:
sudo dnf install doxygen
# Generate documentation (run from project root)
doxygen docs/Doxyfile.in
# View the documentation
# Open docs/doxygen/html/index.html in a browser
open docs/doxygen/html/index.html # macOS
xdg-open docs/doxygen/html/index.html # Linux
The generated documentation will be in docs/doxygen/html/ directory:
index.html- Main documentation pageclasses.html- Class hierarchyfiles.html- File list
License
MIT License - see LICENSE file for details
Source & license
This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: laplaceliu
- Source: laplaceliu/mcpp
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.