-
Notifications
You must be signed in to change notification settings - Fork 0
MCP_TRANSPORTS
ThemisDB's MCP (Model Context Protocol) server supports three transport mechanisms for LLM integration:
- stdio - Standard input/output for Claude Desktop (Linux/macOS)
- SSE (Server-Sent Events) - HTTP-based unidirectional streaming
- WebSocket - Bidirectional real-time communication
All transports implement the same JSON-RPC 2.0 protocol and provide identical MCP functionality.
| Feature | stdio | SSE | WebSocket |
|---|---|---|---|
| Direction | Bidirectional | Server→Client | Bidirectional |
| Connection | Process pipes | HTTP long-polling | TCP socket |
| Reconnect | Process restart | Automatic (SSE) | Manual |
| Multiplexing | Single client | Multiple clients | Multiple sessions |
| Latency | Very low | Low | Very low |
| Complexity | Simple | Moderate | Moderate |
| Use Case | Claude Desktop | Web dashboards | Real-time apps |
| Platform | POSIX only | Cross-platform | Cross-platform |
Uses standard input/output streams for communication with Claude Desktop on POSIX systems (Linux/macOS).
McpServer::Config config;
config.enable_stdio = true;
config.stdio_buffer_size = 4096;
McpServer server(io_context, config);
server.start();{
"mcpServers": {
"themisdb": {
"command": "/usr/local/bin/themis_server",
"args": ["--mcp-stdio", "--db-path", "/var/lib/themisdb"]
}
}
}- Protocol: JSON-RPC 2.0 over stdin/stdout
- Framing: Newline-delimited JSON
-
Async I/O: Uses
select()for non-blocking reads - Limitations: Single client, POSIX only, requires process lifecycle management
# Client (Claude) sends via stdin
{"jsonrpc":"2.0","method":"tools/call","params":{"name":"get_entity","arguments":{"key":"user:123"}},"id":1}
# Server responds via stdout
{"jsonrpc":"2.0","result":{"status":"success","key":"user:123","value":{"name":"Alice"}},"id":1}HTTP-based unidirectional streaming from server to client. Clients initiate requests via HTTP POST and receive responses + notifications via SSE stream.
Client ThemisDB MCP Server
| |
|---(1) HTTP POST /mcp/sse/call------>| (Tool/Resource request)
|<-----(2) HTTP 200 + SSE stream------|
| |
|<-----(3) data: {...response...}-----| (JSON-RPC response)
|<-----(4) : keepalive-----------------| (Every 30s)
|<-----(5) data: {...notification.}---| (Async events)
| |
|---(6) HTTP POST /mcp/sse/disconnect->| (Cleanup)
|<-----(7) HTTP 200 OK-----------------|
GET /mcp/sse/subscribe?client_id=<uuid> HTTP/1.1
Host: localhost:8080
Accept: text/event-stream
HTTP/1.1 200 OK
Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive
: connected
data: {"jsonrpc":"2.0","method":"initialized","params":{}}
: keepalive
data: {"jsonrpc":"2.0","result":{"..."},"id":1}POST /mcp/sse/request HTTP/1.1
Host: localhost:8080
Content-Type: application/json
{
"client_id": "550e8400-e29b-41d4-a716-446655440000",
"request": {
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "get_entity",
"arguments": {"key": "user:123"}
},
"id": 1
}
}POST /mcp/sse/disconnect HTTP/1.1
Host: localhost:8080
Content-Type: application/json
{
"client_id": "550e8400-e29b-41d4-a716-446655440000"
}McpServer::Config config;
config.enable_sse = true;
config.sse_keepalive_ms = 30000; // Send keepalive every 30s
McpServer server(io_context, config);
server.start();
// Attach to HTTP server for endpoint handling
server.attachHttpServer(http_server);const clientId = crypto.randomUUID();
// Subscribe to SSE stream
const eventSource = new EventSource(`/mcp/sse/subscribe?client_id=${clientId}`);
eventSource.onmessage = (event) => {
const response = JSON.parse(event.data);
console.log('Received:', response);
};
eventSource.onerror = (error) => {
console.error('SSE error:', error);
eventSource.close();
};
// Send request
async function callTool(name, args) {
const response = await fetch('/mcp/sse/request', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
client_id: clientId,
request: {
jsonrpc: '2.0',
method: 'tools/call',
params: { name, arguments: args },
id: Date.now()
}
})
});
return response.json();
}
// Usage
await callTool('get_entity', {key: 'user:123'});
// Cleanup
eventSource.close();
await fetch('/mcp/sse/disconnect', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({client_id: clientId})
});- Protocol: JSON-RPC 2.0 over SSE + HTTP POST
-
Framing: SSE event stream format (
data:prefix, double newline) -
Keepalive: Comment lines (
: keepalive\n\n) every 30 seconds - Multiplexing: Supports multiple clients via client_id
- Reconnect: Automatic via EventSource API
- Buffering: Server buffers events per client until consumed
Full-duplex bidirectional communication over persistent WebSocket connection.
Client ThemisDB MCP Server
| |
|--(1) HTTP Upgrade to WebSocket----->|
|<----(2) 101 Switching Protocols-----|
| |
|<===(3) WebSocket Connection Open====|
| |
|---(4) {"method":"tools/call",...}--->| (Request)
|<-----(5) {"result":{...},"id":1}-----| (Response)
| |
|<-----(6) {"method":"ping",...}-------| (Ping every 30s)
|---(7) {"method":"pong",...}--------->| (Pong response)
| |
|<-----(8) {"method":"notification".}--| (Async notification)
| |
|--(9) Close frame--------------------->|
|<---(10) Close frame ACK---------------|
GET /mcp/ws HTTP/1.1
Host: localhost:8080
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=// Client → Server (Request)
{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "put_entity",
"arguments": {
"key": "user:456",
"value": {"name": "Bob", "email": "bob@example.com"}
}
},
"id": 2
}
// Server → Client (Response)
{
"jsonrpc": "2.0",
"result": {
"status": "success",
"message": "Entity stored successfully",
"key": "user:456"
},
"id": 2
}
// Server → Client (Notification)
{
"jsonrpc": "2.0",
"method": "notification",
"params": {
"type": "cdc_event",
"key": "user:456",
"operation": "PUT"
}
}McpServer::Config config;
config.enable_websocket = true;
config.websocket_ping_interval_ms = 30000; // Ping every 30s
McpServer server(io_context, config);
server.start();
// Attach to HTTP server for WebSocket upgrade handling
server.attachHttpServer(http_server);const ws = new WebSocket('ws://localhost:8080/mcp/ws');
ws.onopen = () => {
console.log('MCP WebSocket connected');
// Call a tool
ws.send(JSON.stringify({
jsonrpc: '2.0',
method: 'tools/call',
params: {
name: 'get_schema',
arguments: {}
},
id: 1
}));
};
ws.onmessage = (event) => {
const message = JSON.parse(event.data);
if (message.method === 'ping') {
// Respond to ping
ws.send(JSON.stringify({
jsonrpc: '2.0',
method: 'pong',
params: {}
}));
} else if (message.result) {
// Handle response
console.log('Response:', message.result);
} else if (message.method) {
// Handle notification
console.log('Notification:', message.params);
}
};
ws.onerror = (error) => {
console.error('WebSocket error:', error);
};
ws.onclose = () => {
console.log('WebSocket closed');
};
// Cleanup
ws.close();const WebSocket = require('ws');
const ws = new WebSocket('ws://localhost:8080/mcp/ws');
ws.on('open', async () => {
console.log('Connected to MCP server');
// Helper function to call MCP tools
const callTool = (name, args) => {
return new Promise((resolve, reject) => {
const id = Date.now();
const handler = (data) => {
const msg = JSON.parse(data);
if (msg.id === id) {
ws.off('message', handler);
if (msg.error) reject(msg.error);
else resolve(msg.result);
}
};
ws.on('message', handler);
ws.send(JSON.stringify({
jsonrpc: '2.0',
method: 'tools/call',
params: { name, arguments: args },
id
}));
});
};
// Use the helper
try {
const result = await callTool('get_entity', {key: 'user:123'});
console.log('Entity:', result.value);
} catch (error) {
console.error('Error:', error);
}
});
ws.on('message', (data) => {
const msg = JSON.parse(data);
if (msg.method === 'ping') {
ws.send(JSON.stringify({
jsonrpc: '2.0',
method: 'pong',
params: {}
}));
} else if (msg.method === 'notification') {
console.log('Notification:', msg.params);
}
});- Protocol: JSON-RPC 2.0 over WebSocket
- Framing: WebSocket text frames (one JSON message per frame)
- Keepalive: Ping/pong frames every 30 seconds
- Multiplexing: One session per WebSocket connection
- Reconnect: Manual (client must reconnect)
- Message Queue: Server queues messages per session until delivered
- Integrating with Claude Desktop
- Running on Linux/macOS
- Single-user desktop environment
- Minimal latency requirements
- Process-based security model
- Building web dashboards or monitoring UIs
- Server-initiated notifications needed
- Clients are browsers without WebSocket support
- Firewall-friendly unidirectional streaming
- HTTP proxy compatibility required
- Building interactive web applications
- Real-time bidirectional communication needed
- Long-lived connections with frequent exchanges
- Lower protocol overhead desired
- Modern browser or Node.js client
All transports use JSON-RPC 2.0 error responses:
{
"jsonrpc": "2.0",
"error": {
"code": -32600,
"message": "Invalid request: missing 'key' parameter",
"data": {
"field": "key",
"provided": null
}
},
"id": 1
}-
-32700: Parse error -
-32600: Invalid request -
-32601: Method not found -
-32602: Invalid params -
-32603: Internal error -
-32000to-32099: Server-defined errors
- ✅ Process isolation (OS-level security)
- ✅ No network exposure
⚠️ Requires file system access control⚠️ Vulnerable to local privilege escalation
⚠️ No built-in authentication (add via HTTP auth)⚠️ CSRF protection needed for POST endpoints- ✅ TLS encryption supported (HTTPS)
- ✅ CORS configuration available
⚠️ Client_id must be cryptographically random (UUIDv4)
⚠️ No built-in authentication (add via handshake)- ✅ TLS encryption supported (WSS)
- ✅ Origin checking for CSRF protection
⚠️ Rate limiting recommended per session- ✅ Automatic connection limits
- Use TLS (HTTPS/WSS) for production SSE/WebSocket
- Implement authentication middleware for HTTP endpoints
- Add rate limiting per client_id (SSE) or session (WebSocket)
- Validate all JSON-RPC requests (parameter types, ranges)
- Use parameterized queries to prevent Cypher/SQL injection
- Sanitize user inputs in all MCP tool arguments
config.stdio_buffer_size = 8192; // Larger buffer for bulk operationsconfig.sse_keepalive_ms = 15000; // More frequent keepalive for aggressive proxies
// Consider buffering limits per client to prevent memory exhaustionconfig.websocket_ping_interval_ms = 60000; // Less frequent ping for stable connections
// Adjust message queue size if handling high-frequency updates// Enable MCP transport logging
spdlog::set_level(spdlog::level::debug);
// Log output examples:
// [info] MCP Server started successfully
// [debug] MCP SSE client added: 550e8400-e29b-41d4-a716-446655440000, total clients: 3
// [debug] MCP WebSocket message queued for session: ws_abc123
// [trace] MCP SSE keepalive sent to 3 clientsTrack transport health:
- Active client/session count
- Messages sent/received
- Average latency per transport
- Error rates
- Connection lifetime statistics
- Windows stdio support via named pipes
- Authentication and authorization framework
- Rate limiting per client/session
- Message compression (gzip)
- Binary protocol option for performance
- Multiplexing multiple MCP servers over single transport
- Connection pooling for HTTP/2 Server Push
ThemisDB v1.3.4 | GitHub | Documentation | Discussions | License
Last synced: January 02, 2026 | Commit: 6add659
Version: 1.3.0 | Stand: Dezember 2025
- Übersicht
- Home
- Dokumentations-Index
- Quick Reference
- Sachstandsbericht 2025
- Features
- Roadmap
- Ecosystem Overview
- Strategische Übersicht
- Geo/Relational Storage
- RocksDB Storage
- MVCC Design
- Transaktionen
- Time-Series
- Memory Tuning
- Chain of Thought Storage
- Query Engine & AQL
- AQL Syntax
- Explain & Profile
- Rekursive Pfadabfragen
- Temporale Graphen
- Zeitbereichs-Abfragen
- Semantischer Cache
- Hybrid Queries (Phase 1.5)
- AQL Hybrid Queries
- Hybrid Queries README
- Hybrid Query Benchmarks
- Subquery Quick Reference
- Subquery Implementation
- Content Pipeline
- Architektur-Details
- Ingestion
- JSON Ingestion Spec
- Enterprise Ingestion Interface
- Geo-Processor Design
- Image-Processor Design
- Hybrid Search Design
- Fulltext API
- Hybrid Fusion API
- Stemming
- Performance Tuning
- Migration Guide
- Future Work
- Pagination Benchmarks
- Enterprise README
- Scalability Features
- HTTP Client Pool
- Build Guide
- Implementation Status
- Final Report
- Integration Analysis
- Enterprise Strategy
- Verschlüsselungsstrategie
- Verschlüsselungsdeployment
- Spaltenverschlüsselung
- Encryption Next Steps
- Multi-Party Encryption
- Key Rotation Strategy
- Security Encryption Gap Analysis
- Audit Logging
- Audit & Retention
- Compliance Audit
- Compliance
- Extended Compliance Features
- Governance-Strategie
- Compliance-Integration
- Governance Usage
- Security/Compliance Review
- Threat Model
- Security Hardening Guide
- Security Audit Checklist
- Security Audit Report
- Security Implementation
- Development README
- Code Quality Pipeline
- Developers Guide
- Cost Models
- Todo Liste
- Tool Todo
- Core Feature Todo
- Priorities
- Implementation Status
- Roadmap
- Future Work
- Next Steps Analysis
- AQL LET Implementation
- Development Audit
- Sprint Summary (2025-11-17)
- WAL Archiving
- Search Gap Analysis
- Source Documentation Plan
- Changefeed README
- Changefeed CMake Patch
- Changefeed OpenAPI
- Changefeed OpenAPI Auth
- Changefeed SSE Examples
- Changefeed Test Harness
- Changefeed Tests
- Dokumentations-Inventar
- Documentation Summary
- Documentation TODO
- Documentation Gap Analysis
- Documentation Consolidation
- Documentation Final Status
- Documentation Phase 3
- Documentation Cleanup Validation
- API
- Authentication
- Cache
- CDC
- Content
- Geo
- Governance
- Index
- LLM
- Query
- Security
- Server
- Storage
- Time Series
- Transaction
- Utils
Vollständige Dokumentation: https://makr-code.github.io/ThemisDB/