mtwRequest's core is written in Rust for maximum performance. Language bindings make it accessible from Node.js, Python, PHP, and the browser (WASM). This guide covers using mtwRequest from each language.
+-------------------+
| mtwRequest Core | (Rust)
| (crates/*) |
+---+---+---+---+---+
| | | |
v v v v
NAPI PyO3 FFI WASM
| | | |
Node Python PHP Browser
Source: bindings/node/, bindings/python/, bindings/php/, bindings/wasm/
The Node.js binding uses NAPI-RS for native performance without the overhead of a separate process.
npm install mtw-requestimport { MtwServer, MtwConfig } from 'mtw-request';
const server = new MtwServer({
host: '127.0.0.1',
port: 8080,
transport: {
websocket: { path: '/ws', pingInterval: 30 },
},
});
// Register event handlers
server.onConnect((connId, metadata) => {
console.log(`Connected: ${connId} from ${metadata.remoteAddr}`);
});
server.onDisconnect((connId, reason) => {
console.log(`Disconnected: ${connId} (${reason})`);
});
server.onMessage((connId, message) => {
console.log(`Message from ${connId}:`, message.type, message.payload);
// Echo back
if (message.type === 'request') {
server.send(connId, {
type: 'response',
refId: message.id,
payload: message.payload,
});
}
});
// Start
await server.start();
console.log('Server running on ws://127.0.0.1:8080/ws');// Create channels
server.createChannel('chat.general', { maxMembers: 100, history: 50 });
server.createChannel('notifications', { history: 10 });
// Subscribe/publish
server.subscribe('chat.general', connId);
server.publish('chat.general', { user: 'alice', text: 'Hello!' });const server = await MtwServer.fromConfig('./mtw.toml');
await server.start();The Python binding uses PyO3 to expose Rust functionality as a native Python module.
pip install mtw-requestimport mtw_request
import asyncio
async def main():
server = mtw_request.Server(
host="127.0.0.1",
port=8080,
)
@server.on_connect
async def handle_connect(conn_id, metadata):
print(f"Connected: {conn_id} from {metadata.remote_addr}")
@server.on_disconnect
async def handle_disconnect(conn_id, reason):
print(f"Disconnected: {conn_id} ({reason})")
@server.on_message
async def handle_message(conn_id, message):
print(f"Message from {conn_id}: {message.type}")
if message.type == "request":
await server.send(conn_id, {
"type": "response",
"ref_id": message.id,
"payload": message.payload,
})
# Create channels
server.create_channel("chat.general", max_members=100, history=50)
await server.start()
print("Server running on ws://127.0.0.1:8080/ws")
# Run until interrupted
await server.run_forever()
asyncio.run(main())import mtw_request
import asyncio
async def main():
conn = mtw_request.Connection("ws://localhost:8080/ws")
await conn.connect()
# Subscribe
await conn.subscribe("chat.general")
# Publish
await conn.publish("chat.general", {"text": "Hello from Python!"})
# Request/response
response = await conn.request({"action": "get_users"}, timeout=30)
print(f"Users: {response.payload}")
# Listen for messages
@conn.on_message
def handle(msg):
print(f"Received: {msg}")
# AI agent
async for chunk in conn.agent_stream("assistant", "What is mtwRequest?"):
print(chunk.text, end="", flush=True)
print()
await conn.close()
asyncio.run(main())server = mtw_request.Server.from_config("mtw.toml")The PHP binding uses FFI (Foreign Function Interface) to call Rust functions directly.
composer require mtw/request<?php
use Mtw\Request\Server;
use Mtw\Request\Channel;
$server = new Server([
'host' => '127.0.0.1',
'port' => 8080,
]);
$server->onConnect(function (string $connId, array $metadata) {
echo "Connected: {$connId}\n";
});
$server->onMessage(function (string $connId, array $message) use ($server) {
echo "Message from {$connId}: {$message['type']}\n";
if ($message['type'] === 'request') {
$server->send($connId, [
'type' => 'response',
'ref_id' => $message['id'],
'payload' => $message['payload'],
]);
}
});
// Create channels
$server->createChannel('chat.general', ['maxMembers' => 100, 'history' => 50]);
$server->start();
echo "Server running on ws://127.0.0.1:8080/ws\n";
$server->run();<?php
use Mtw\Request\Connection;
$conn = new Connection('ws://localhost:8080/ws');
$conn->connect();
$conn->subscribe('chat.general');
$conn->publish('chat.general', ['text' => 'Hello from PHP!']);
$response = $conn->request(['action' => 'get_users'], timeout: 30);
var_dump($response);
$conn->close();The WASM binding compiles the Rust core to WebAssembly, enabling high-performance message processing directly in the browser.
npm install @mtw/wasmimport init, { WasmMtwConnection } from '@mtw/wasm';
// Initialize the WASM module
await init();
// Create a connection (uses the browser's native WebSocket)
const conn = new WasmMtwConnection('ws://localhost:8080/ws');
conn.onConnected((meta) => {
console.log('Connected via WASM:', meta.connId);
});
conn.onMessage((msg) => {
// Message is already decoded in WASM (faster than JS JSON.parse for large payloads)
console.log('Message:', msg);
});
await conn.connect();
// Encode/decode with WASM performance
conn.subscribe('chat.general');
conn.publish('chat.general', { text: 'Hello from WASM!' });| Scenario | Recommendation |
|---|---|
| Simple chat/messaging | Use @mtw/client (pure JS) |
| High-frequency binary data (3D, audio) | Use @mtw/wasm |
| Large JSON payloads | Use @mtw/wasm (faster parsing) |
| Bundle size sensitive | Use @mtw/client (smaller) |
| Server-side Node.js | Use mtw-request (native binding) |
The Rust core provides significant performance advantages over pure JavaScript implementations, particularly for WebSocket-heavy workloads.
| Implementation | Messages/sec | Latency (p99) |
|---|---|---|
| Rust (native server) | ~500,000 | <1ms |
| Node.js (NAPI binding) | ~200,000 | <2ms |
| Python (PyO3 binding) | ~100,000 | <5ms |
| Pure Node.js (ws) | ~50,000 | <10ms |
| WASM (browser) | ~150,000 | <3ms |
| Implementation | Operations/sec |
|---|---|
| Rust (serde_json) | ~2,000,000 |
| WASM (serde_json) | ~800,000 |
| Node.js (native) | ~500,000 |
| Python (json) | ~200,000 |
| Implementation | Frames/sec |
|---|---|
| Rust (native) | ~5,000,000 |
| WASM | ~2,000,000 |
| Node.js (Buffer) | ~1,000,000 |
These numbers demonstrate why using the Rust bindings rather than reimplementing protocol logic in each language provides both performance and correctness benefits.
| Binding | Source | Status |
|---|---|---|
| Node.js (NAPI-RS) | bindings/node/ |
Planned (Phase 4) |
| Python (PyO3) | bindings/python/ |
Planned (Phase 4) |
| PHP (FFI) | bindings/php/ |
Planned (Phase 4) |
| WASM (wasm-bindgen) | bindings/wasm/ |
Planned (Phase 4) |
The binding directories contain scaffold files. Full implementations are coming in Phase 4 of the project roadmap. In the meantime, you can use the @mtw/client TypeScript package (pure JS) for browser and Node.js connectivity.
- Getting Started -- project setup
- Frontend Guide -- TypeScript/React client SDKs (available now)
- Server Guide -- Rust server configuration