pforge-bridge

Crates.iopforge-bridge
lib.rspforge-bridge
version0.1.4
created_at2025-10-03 12:01:13.675729+00
updated_at2025-12-06 12:09:51.335861+00
descriptionLanguage bridge FFI for pforge
homepagehttps://github.com/paiml/pforge
repositoryhttps://github.com/paiml/pforge
max_upload_size
id1866576
size88,728
Noah Gift (noahgift)

documentation

https://docs.rs/pforge-runtime

README

pforge-bridge

crates.io Documentation

Language bridges for polyglot MCP handlers - write handlers in Python, Go, Node.js, and other languages while using pforge's Rust runtime.

Features

  • Multi-Language Support: Python, Go, Node.js, and more
  • Zero-Copy FFI: Efficient data passing across language boundaries
  • Type Safety: Preserve type information across language bridges
  • Error Propagation: Native error semantics in each language
  • Stable ABI: C FFI for maximum compatibility
  • Async Support: Works with async handlers in all languages

Supported Languages

Language Status Features
Python ✅ Stable Async/await, type hints, error handling
Go 🚧 Beta Goroutines, error handling
Node.js 🚧 Beta Promises, TypeScript support
Ruby 📋 Planned -
Java 📋 Planned -

Installation

cargo add pforge-bridge

Quick Start

Python Handler

pforge.yaml:

tools:
  - type: native
    name: analyze_data
    description: "Analyze data with Python"
    handler:
      bridge: python
      path: handlers.analyze_data
    params:
      data: { type: array, required: true }

handlers.py:

async def analyze_data(params):
    """Analyze data using numpy and pandas"""
    import numpy as np
    data = np.array(params['data'])

    return {
        'mean': float(np.mean(data)),
        'std': float(np.std(data)),
        'min': float(np.min(data)),
        'max': float(np.max(data))
    }

Go Handler

pforge.yaml:

tools:
  - type: native
    name: process_image
    description: "Process image with Go"
    handler:
      bridge: go
      path: handlers.ProcessImage
    params:
      image_url: { type: string, required: true }

handlers.go:

package handlers

import (
    "encoding/json"
    "image"
    _ "image/jpeg"
    "net/http"
)

func ProcessImage(params map[string]interface{}) (interface{}, error) {
    imageURL := params["image_url"].(string)

    resp, err := http.Get(imageURL)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()

    img, _, err := image.Decode(resp.Body)
    if err != nil {
        return nil, err
    }

    bounds := img.Bounds()
    return map[string]interface{}{
        "width":  bounds.Dx(),
        "height": bounds.Dy(),
    }, nil
}

Node.js Handler

pforge.yaml:

tools:
  - type: native
    name: fetch_data
    description: "Fetch data with Node.js"
    handler:
      bridge: node
      path: handlers.fetchData
    params:
      url: { type: string, required: true }

handlers.js:

export async function fetchData(params) {
    const response = await fetch(params.url);
    const data = await response.json();

    return {
        status: response.status,
        data: data,
        headers: Object.fromEntries(response.headers)
    };
}

Architecture

C FFI Layer

The bridge uses a stable C ABI for maximum compatibility:

// Bridge function signature
typedef struct {
    const char* data;
    size_t len;
} BridgeData;

typedef BridgeData (*BridgeHandler)(BridgeData params);

Zero-Copy Parameter Passing

Parameters are passed as pointers, not serialized:

// Rust side
let params_ptr = params.as_ptr();
let params_len = params.len();

// Python side receives raw pointer
let result = python_handler(params_ptr, params_len);

Error Handling

Errors propagate with full context:

# Python raises exception
raise ValueError("Invalid data format")
// Rust receives typed error
Err(Error::Handler("Python error: Invalid data format".into()))

Bridge Configuration

Python Bridge

bridges:
  python:
    runtime: cpython  # or pypy
    version: "3.11"
    venv: .venv       # Optional virtualenv
    requirements: requirements.txt

Install dependencies:

pip install pforge-bridge-python

Go Bridge

bridges:
  go:
    version: "1.21"
    mod: handlers    # Go module name

Install bridge:

go get github.com/paiml/pforge-bridge-go

Node.js Bridge

bridges:
  node:
    runtime: node    # or bun, deno
    version: "20"
    package: package.json

Install bridge:

npm install @paiml/pforge-bridge

Advanced Usage

Type Mapping

Automatic type conversion between languages:

JSON Type Rust Python Go Node.js
string String str string string
number f64 float float64 number
integer i64 int int64 number
boolean bool bool bool boolean
array Vec list []interface{} Array
object HashMap dict map Object

Custom Serialization

Override default serialization:

from pforge_bridge import register_serializer

@register_serializer(MyClass)
def serialize_myclass(obj):
    return {
        'type': 'MyClass',
        'data': obj.to_dict()
    }

State Sharing

Share state between Rust and bridge languages:

// Rust side
let state = Arc::new(RwLock::new(SharedState::new()));
bridge.set_state("shared", state.clone());
# Python side
state = get_shared_state("shared")
async with state.write():
    state.counter += 1

Performance

Operation Overhead
Function call ~1-5Ξs
Parameter passing (1KB) ~100ns
Result marshaling (1KB) ~100ns
Error propagation ~500ns

The bridge is optimized for minimal overhead while maintaining safety.

Security

  • Sandboxing: Optional process isolation for handlers
  • Resource Limits: Memory and CPU limits per handler
  • Capability-Based: Handlers only access granted capabilities
  • Input Validation: Automatic validation of bridge parameters

Debugging

Enable debug logging:

PFORGE_BRIDGE_LOG=debug pforge serve

Trace bridge calls:

bridge.enable_tracing(true);

Limitations

  • No direct pointer sharing between languages
  • Serialization overhead for complex types
  • Each bridge adds ~5MB to binary size
  • Requires language runtime installed

Documentation

Contributing

We welcome bridge implementations for additional languages! Please open an issue or pull request on GitHub.

License

MIT

Commit count: 0

cargo fmt