strike48-connector 0.2.2

Rust SDK for the Strike48 Connector Framework
Documentation

Matrix Connector SDK for Rust

A Rust SDK for building connectors that integrate with the Matrix Connector Framework.

Features

  • gRPC bidirectional streaming - Efficient communication with Matrix server
  • Type-safe protobuf integration - Auto-generated types from protobuf definitions
  • Async/await support - Built on Tokio for high-performance async operations
  • Multiple payload encodings - JSON, RAW_BYTES, JSON_LINES, and more
  • Automatic reconnection - Handles connection failures gracefully
  • Session token support - Fast reconnection using session tokens
  • Comprehensive error handling - Detailed error types and messages

Installation

From GitHub (Internal - Recommended)

Add to your Cargo.toml:

[dependencies]
matrix-connector-sdk = { 
    git = "https://github.com/Strike48/matrix-mcf-grpc-v1", 
    path = "src/apps/matrix_connectors/sdks/rust" 
}

For specific version/tag:

[dependencies]
matrix-connector-sdk = { 
    git = "https://github.com/Strike48/matrix-mcf-grpc-v1", 
    tag = "v0.1.0",
    path = "src/apps/matrix_connectors/sdks/rust" 
}

For specific branch:

[dependencies]
matrix-connector-sdk = { 
    git = "https://github.com/Strike48/matrix-mcf-grpc-v1", 
    branch = "develop",
    path = "src/apps/matrix_connectors/sdks/rust" 
}

For Private Repositories

Configure Git authentication for Cargo:

# Option 1: Use SSH (recommended)
# Cargo uses SSH by default if available

# Option 2: Use Personal Access Token via .netrc
cat >> ~/.netrc << EOF
machine github.com
login YOUR_GITHUB_USERNAME
password YOUR_GITHUB_TOKEN
EOF
chmod 600 ~/.netrc

# Option 3: Configure git credential helper
git config --global credential.helper store

Then add to Cargo.toml:

[dependencies]
matrix-connector-sdk = { 
    git = "ssh://git@github.com/Strike48/matrix-mcf-grpc-v1", 
    path = "src/apps/matrix_connectors/sdks/rust" 
}

From Crates.io (Coming Soon)

[dependencies]
matrix-connector-sdk = "0.1.0"

From Local Path (Development)

[dependencies]
matrix-connector-sdk = { path = "path/to/matrix-connector-sdk" }

From Source (Development)

cd src/apps/matrix_connectors/sdks/rust

# Build (proto stubs auto-generated via build.rs)
cargo build

Prerequisites:

# Install protoc (macOS)
brew install protobuf

# Install protoc (Linux)
apt install protobuf-compiler

The Rust SDK uses tonic-build in build.rs to auto-generate protobuf stubs during compilation. No manual proto generation is needed.

Quick Start

Basic Echo Connector

use strike48_connector_sdk::*;
use std::sync::Arc;

struct EchoConnector;

impl BaseConnector for EchoConnector {
    fn connector_type(&self) -> &str {
        "echo"
    }

    fn version(&self) -> &str {
        "1.0.0"
    }

    fn execute(
        &self,
        request: serde_json::Value,
        _capability_id: Option<&str>,
    ) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<serde_json::Value>> + Send>> {
        Box::pin(async move {
            Ok(serde_json::json!({
                "success": true,
                "echo": request,
                "timestamp": chrono::Utc::now().to_rfc3339()
            }))
        })
    }
}

#[tokio::main]
async fn main() -> Result<()> {
    init_logger();
    
    let config = ConnectorConfig {
        matrix_host: "localhost:50061".to_string(),
        tenant_id: "default".to_string(),
        connector_type: "echo".to_string(),
        instance_id: format!("echo-{}", chrono::Utc::now().timestamp_millis()),
        version: "1.0.0".to_string(),
        auth_token: String::new(),
        use_tls: false,
        ..ConnectorConfig::default()
    };

    let connector = Arc::new(EchoConnector);
    let runner = ConnectorRunner::new(config, connector);
    
    runner.run().await?;
    Ok(())
}

Configuration

The SDK supports configuration via environment variables or programmatically:

Environment Variables

Variable Description Default
MATRIX_HOST or MATRIX_URL Matrix server URL localhost:50061
TENANT_ID Tenant identifier required
INSTANCE_ID Connector instance ID Auto-generated (see below)
AUTH_TOKEN JWT token (optional) Empty (uses approval flow)
USE_TLS Enable TLS false
CONNECTOR_DISPLAY_NAME Human-readable name for UI instance_id
CONNECTOR_TAGS Comma-separated tags Empty

Instance ID

The INSTANCE_ID uniquely identifies your connector instance. This is critical for:

  • Credential persistence - Saved credentials are keyed by instance ID
  • Session management - Matrix server tracks sessions by instance
  • Reconnection - Same instance ID allows seamless reconnection

If not provided, the SDK generates a random instance ID:

{connector_type}-{timestamp_millis}

Best Practice: Always set INSTANCE_ID for production connectors to enable auto-reconnection after restarts.

# Recommended: Stable instance ID
export INSTANCE_ID=echo-prod

# Auto-generated: Random on each start (not recommended for production)
# (omit INSTANCE_ID)

Authentication & Private Key Storage

The SDK uses asymmetric authentication (private_key_jwt). On first connection:

  1. Admin approves the connector in Matrix Studio
  2. SDK generates an RSA key pair automatically
  3. Private key is saved for future reconnections

Default Storage Locations:

Item Location
Private Keys ~/.matrix/keys/{connector_type}_{instance_id}.pem
Credentials ~/.matrix/credentials/matrix_{tenant}_{type}_{instance}.json

Override Storage Paths:

# Override keys directory
export MATRIX_KEYS_DIR=/custom/path/to/keys

# Direct private key path (for cert-manager/K8s)
export MATRIX_PRIVATE_KEY_PATH=/var/run/secrets/matrix/tls.key
export MATRIX_CLIENT_ID=my-connector-client
export MATRIX_KEYCLOAK_URL=https://keycloak.example.com/realms/matrix

Reconnection Behavior

When the connector restarts with the same INSTANCE_ID:

  1. SDK loads saved credentials from ~/.matrix/credentials/
  2. Fetches a fresh JWT using the saved private key
  3. Reconnects to Matrix without requiring re-approval

This only works if:

  • INSTANCE_ID is the same as the previous run
  • Credentials file exists at the expected path
  • Private key file exists at the expected path

Programmatic Configuration

let config = ConnectorConfig {
    matrix_host: "matrix.example.com:50061".to_string(),
    tenant_id: "my-tenant".to_string(),
    connector_type: "my-connector".to_string(),
    instance_id: "my-instance".to_string(),
    version: "1.0.0".to_string(),
    auth_token: "jwt-token".to_string(),
    use_tls: true,
    ..ConnectorConfig::default()
};

Instance Metadata (Multi-Instance Routing)

Instance metadata enables multi-instance routing and better UI display:

let config = ConnectorConfig::from_env()
    .display_name("Production Server 1")     // Human-readable name for UI
    .tag("prod")                             // Tags for grouping
    .tag("us-east-1")
    .with_metadata("location", "AWS US-East-1")  // Key-value metadata
    .with_metadata("owner", "platform-team");

Available Builder Methods:

Method Description
.display_name("Name") Human-readable name for UI (defaults to instance_id)
.tag("prod") Add a single tag for grouping
.tags(["prod", "us-east-1"]) Add multiple tags at once
.with_metadata("key", "value") Add operator metadata
.metadata_from_env("PREFIX_") Load metadata from env vars with prefix

Example with Environment Metadata:

// Reads CONNECTOR_LOCATION, CONNECTOR_OWNER, etc.
let config = ConnectorConfig::from_env()
    .display_name("Analytics Node")
    .tags(["prod", "analytics"])
    .metadata_from_env("CONNECTOR_");

Agent Routing Behavior:

  • "run command" → round-robin across all instances
  • "run command on prod-1" → route to specific instance_id
  • "run command on Production Server 1" → route via display_name
  • "run command on all prod servers" → broadcast to instances tagged "prod"

Examples

See the examples/ directory for complete examples:

  • echo_connector.rs - Simple echo connector that returns the input

Running Examples

# Set environment variables
export MATRIX_HOST=localhost:50061
export TENANT_ID=default

# Run echo connector
cargo run --example echo_connector

Building

# Build the SDK
cargo build

# Build with examples
cargo build --examples

# Run tests
cargo test

# Run integration tests (requires running Matrix server)
cargo test -- --ignored

Architecture

The SDK consists of several key components:

  • BaseConnector - Trait that connectors must implement
  • ConnectorRunner - Manages connector lifecycle and message handling
  • ConnectorHandle - Safe handle for sending messages from callbacks (WebSocket frames, invoke)
  • types - Type definitions matching protobuf schemas
  • utils - Serialization, deserialization, and helper functions
  • process - Async process execution (non-blocking tokio::process::Command wrappers)
  • error - Comprehensive error types

Payload Encodings

The SDK supports multiple payload encodings:

  • JSON - Standard JSON encoding (default)
  • RAW_BYTES - Raw byte arrays
  • JSON_LINES - Newline-separated JSON
  • ARROW_IPC - Apache Arrow IPC format
  • PROTOBUF - Protocol Buffers
  • MSGPACK - MessagePack
  • PARQUET - Apache Parquet

Error Handling

All operations return Result<T, ConnectorError>:

match runner.run().await {
    Ok(_) => println!("Connector stopped gracefully"),
    Err(e) => eprintln!("Error: {} (code: {})", e, e.code()),
}

Logging

The SDK uses the tracing crate for logging. Initialize with:

init_logger();

Control log level via RUST_LOG environment variable:

RUST_LOG=debug cargo run --example echo_connector