Synap implements the Model Context Protocol (MCP) to enable AI assistants and language models to interact with the Synap server using structured tools.
MCP Library: Uses rmcp (Rust MCP implementation)
Synap exposes 8 MCP tools covering all core subsystems:
-
synap_kv_get- Retrieve a value- Input:
{ "key": "string" } - Output:
{ "value": "..." } - Read-only, Idempotent
- Input:
-
synap_kv_set- Store a value- Input:
{ "key": "string", "value": "string", "ttl": number? } - Output:
{ "success": true }
- Input:
-
synap_kv_delete- Delete a key- Input:
{ "key": "string" } - Output:
{ "deleted": boolean }
- Input:
-
synap_kv_scan- Scan keys by prefix- Input:
{ "prefix": "string"?, "limit": number? } - Output:
{ "keys": ["key1", "key2", ...] } - Read-only, Idempotent
- Input:
-
synap_queue_publish- Publish message to queue- Input:
{ "queue": "string", "message": "string", "priority": number? } - Output:
{ "message_id": "..." }
- Input:
-
synap_queue_consume- Consume message from queue- Input:
{ "queue": "string", "consumer_id": "string" } - Output:
{ "message_id": "...", "payload": [...], "priority": number }
- Input:
synap_stream_publish- Publish event to stream- Input:
{ "room": "string", "event": "string", "data": object } - Output:
{ "offset": number }
- Input:
synap_pubsub_publish- Publish to topic- Input:
{ "topic": "string", "message": object } - Output:
{ "message_id": "...", "subscribers_matched": number }
- Input:
Add to your Claude Desktop config (~/Library/Application Support/Claude/claude_desktop_config.json on macOS):
{
"mcpServers": {
"synap": {
"command": "synap-mcp-server",
"args": ["--url", "http://localhost:15500"],
"env": {
"SYNAP_API_KEY": "your-api-key-here"
}
}
}
}Create .cursorrules or .vscode/settings.json:
{
"mcp.servers": {
"synap": {
"command": "synap-mcp-server",
"args": ["--url", "http://localhost:15500"]
}
}
}use rmcp::model::CallToolRequestParam;
use serde_json::json;
use synap_server::{AppState, ScriptManager, handle_mcp_tool};
// Setup state
let state = Arc::new(AppState {
kv_store: Arc::new(KVStore::new(config.to_kv_config())),
queue_manager: Some(Arc::new(QueueManager::new(QueueConfig::default()))),
stream_manager: Some(Arc::new(StreamManager::new(StreamConfig::default()))),
partition_manager: None,
consumer_group_manager: None,
pubsub_router: Some(Arc::new(PubSubRouter::new())),
persistence: None,
script_manager: Arc::new(ScriptManager::default()),
// ... initialize monitoring and transaction managers as needed
});
// Call MCP tool
let request = CallToolRequestParam {
name: "synap_kv_set".into(),
arguments: json!({
"key": "user:123",
"value": "John Doe",
"ttl": 3600
}).as_object().cloned(),
};
let result = handle_mcp_tool(request, state).await?;User: "Store user:123 with value 'John Doe' in Synap"
Assistant (using MCP):
Tool: synap_kv_set
Arguments: {
"key": "user:123",
"value": "John Doe",
"ttl": 3600
}
Result: {"success": true}User: "Publish a message to the tasks queue with high priority"
Assistant (using MCP):
Tool: synap_queue_publish
Arguments: {
"queue": "tasks",
"message": "Process video #42",
"priority": 9
}
Result: {"message_id": "msg_abc123"}Run MCP tests:
# All MCP tests
cargo test --test mcp_tests
# Specific test
cargo test --test mcp_tests test_mcp_kv_get
# With output
cargo test --test mcp_tests -- --nocaptureTest Coverage: 5 tests covering all tool types
MCP requests support full authentication via HTTP headers, with permission checks for all operations.
# Via curl
curl -u username:password \
-X POST http://localhost:15500/mcp \
-H "Content-Type: application/json" \
-d '{
"method": "tools/call",
"params": {
"name": "synap_kv_get",
"arguments": {"key": "test"}
}
}'# Via curl
curl -X POST http://localhost:15500/mcp \
-H "Authorization: Bearer sk_XXXXX..." \
-H "Content-Type: application/json" \
-d '{
"method": "tools/call",
"params": {
"name": "synap_kv_get",
"arguments": {"key": "test"}
}
}'All MCP operations verify permissions before execution:
-
KV Operations: Requires
kv:*permissionssynap_kv_get- RequiresReadpermissionsynap_kv_set- RequiresWritepermissionsynap_kv_delete- RequiresDeletepermission
-
Queue Operations: Requires
queue:*permissionssynap_queue_publish- RequiresWritepermission
-
Hash Operations: Requires
hash:*permissionssynap_hash_get- RequiresReadpermissionsynap_hash_set- RequiresWritepermission
-
List Operations: Requires
list:*permissionssynap_list_push- RequiresWritepermissionsynap_list_pop- RequiresWritepermissionsynap_list_range- RequiresReadpermission
-
Set Operations: Requires
set:*permissionssynap_set_add- RequiresWritepermissionsynap_set_members- RequiresReadpermission
-
Admin Users: Bypass all permission checks (full access)
When authentication or authorization fails:
{
"error": {
"code": -32603,
"message": "Insufficient permissions for resource: kv:test_key, action: write"
}
}HTTP Status Codes:
401 Unauthorized- Missing or invalid credentials403 Forbidden- Valid credentials but insufficient permissions (handled in tool response)
Enable authentication in config.yml:
auth:
enabled: true
require_auth: true # Require auth for MCP requests
root:
username: "root"
password: "root"
enabled: trueEnvironment Variables:
SYNAP_AUTH_ENABLED=true- Enable authenticationSYNAP_AUTH_REQUIRE_AUTH=true- Require auth for all requestsSYNAP_AUTH_ROOT_USERNAME=root- Root usernameSYNAP_AUTH_ROOT_PASSWORD=root- Root password
# 1. Create API key (via REST API)
curl -u root:root \
-X POST http://localhost:15500/auth/keys \
-H "Content-Type: application/json" \
-d '{
"name": "mcp-readonly-key",
"permissions": [
{"resource": "kv:*", "actions": ["read"]}
]
}'
# Response: {"id": "...", "key": "sk_XXXXX..."}
# 2. Use API key for MCP request
curl -X POST http://localhost:15500/mcp \
-H "Authorization: Bearer sk_XXXXX..." \
-H "Content-Type: application/json" \
-d '{
"method": "tools/call",
"params": {
"name": "synap_kv_get",
"arguments": {"key": "test"}
}
}'
# 3. Write operation will fail (read-only key)
curl -X POST http://localhost:15500/mcp \
-H "Authorization: Bearer sk_XXXXX..." \
-H "Content-Type: application/json" \
-d '{
"method": "tools/call",
"params": {
"name": "synap_kv_set",
"arguments": {"key": "test", "value": "data"}
}
}'
# Response: Error - Insufficient permissionsWhen auth.require_auth=false, MCP requests can be made without authentication:
# No auth header required
curl -X POST http://localhost:15500/mcp \
-H "Content-Type: application/json" \
-d '{
"method": "tools/call",
"params": {
"name": "synap_kv_get",
"arguments": {"key": "test"}
}
}'Note: Anonymous access is only available when authentication is disabled or require_auth=false. In production, always enable require_auth=true.
All tools include MCP annotations:
- Read-only: Tools that don't modify state (
kv_get,kv_scan) - Idempotent: Safe to retry (
kv_get,kv_scan) - Non-idempotent: May have side effects if retried (all write operations)
MCP tools return standard MCP errors:
// Invalid params
Err(ErrorData::invalid_params("Missing key", None))
// Internal error
Err(ErrorData::internal_error("Set failed: ...", None))Error codes:
-32602: Invalid params-32603: Internal error
- Tools Definition:
synap-server/src/server/mcp_tools.rs - Handlers:
synap-server/src/server/mcp_handlers.rs - Tests:
synap-server/tests/mcp_tests.rs - Exports:
synap-server/src/lib.rs(public API)
Planned MCP features:
- Kafka-style tools: Partitioned topic operations
- Consumer group tools: Join, assign, commit offset
- Batch operations: Multi-get, multi-set via MCP
- Streaming results: For large scan operations
- MCP server binary: Standalone server for stdio transport
- Prompts: Pre-defined interaction patterns
- Resources: Expose Synap stats as MCP resources
- MCP Specification: https://spec.modelcontextprotocol.io/
- rmcp Crate: https://crates.io/crates/rmcp
- Synap API Docs: ../api/REST_API.md
Current State: ✅ PRODUCTION READY
- 8 tools implemented and tested
- 5 comprehensive tests passing
- Error handling complete
- Authentication integrated
- Tool annotations included
- Documentation complete
Version: 0.3.0-rc
Last Updated: October 22, 2025