Transport-level routing for MCP/ACP protocols

We appreciate your patience. The service is temporarily operating in an external runtime environment.

Echo Worker

Simple reference implementation demonstrating the NDJSON worker protocol for stdio Bus kernel.

Getting Started

Echo Worker

Overview

The Echo Worker is a minimal worker implementation that echoes back any JSON-RPC messages it receives. It serves as both a testing tool for stdio Bus kernel functionality and a reference implementation for developers creating custom workers.

Key Features:

  • Simple NDJSON protocol implementation
  • JSON-RPC 2.0 compliant
  • Session affinity support
  • Graceful shutdown handling
  • Reference code for custom workers

Purpose

The Echo Worker serves multiple purposes:

  1. Testing: Verify stdio Bus kernel functionality and message routing
  2. Reference Implementation: Demonstrate the NDJSON worker protocol through clean, documented code
  3. Development: Quick testing during development without complex protocol implementations
  4. Learning: Understand how workers communicate with stdio Bus kernel

Usage

Standalone Testing

Run the Echo Worker directly to test the NDJSON protocol:

echo '{"jsonrpc":"2.0","id":"1","method":"test","params":{"foo":"bar"}}' | \
node node_modules/@stdiobus/workers-registry/workers/echo-worker/echo-worker.js
Code block in Bash, 2 lines

Expected output:

{"jsonrpc":"2.0","id":"1","result":{"method":"test","params":{"foo":"bar"}}}
Code block in JSON, 1 line

Using with stdio Bus

Configuration file (echo-worker-config.json):

{
"pools": [
{
"id": "echo-worker",
"command": "npx",
"args": [
"@stdiobus/workers-registry",
"echo-worker"
],
"instances": 1
}
]
}
Code block in JSON, 13 lines

Run with Docker:

docker run \
--name stdiobus-echo \
-p 9000:9000 \
-v $(pwd):/stdiobus:ro \
-v $(pwd)/echo-worker-config.json:/config.json:ro \
stdiobus/stdiobus:latest \
--config /config.json --tcp 0.0.0.0:9000
Code block in Bash, 7 lines

Run with binary:

./stdio_bus --config echo-worker-config.json --tcp 0.0.0.0:9000
Code block in Bash, 1 line

Testing the Connection

Send a test message to the Echo Worker:

echo '{"jsonrpc":"2.0","id":"1","method":"echo","params":{"test":true}}' | nc localhost 9000
Code block in Bash, 1 line

Response:

{"jsonrpc":"2.0","id":"1","result":{"method":"echo","params":{"test":true}}}
Code block in JSON, 1 line

Configuration

Basic Configuration

Minimal configuration for running a single Echo Worker instance:

{
"pools": [
{
"id": "echo-worker",
"command": "npx",
"args": [
"@stdiobus/workers-registry",
"echo-worker"
],
"instances": 1
}
]
}
Code block in JSON, 13 lines

Multiple Instances

Run multiple Echo Worker instances for load testing:

{
"pools": [
{
"id": "echo-worker",
"command": "npx",
"args": [
"@stdiobus/workers-registry",
"echo-worker"
],
"instances": 4
}
]
}
Code block in JSON, 13 lines

With Custom Limits

Configure resource limits for testing backpressure and error handling:

{
"pools": [
{
"id": "echo-worker",
"command": "npx",
"args": [
"@stdiobus/workers-registry",
"echo-worker"
],
"instances": 1
}
],
"limits": {
"max_input_buffer": 1048576,
"max_output_queue": 4194304,
"max_restarts": 5,
"restart_window_sec": 60,
"drain_timeout_sec": 30,
"backpressure_timeout_sec": 60
}
}
Code block in JSON, 21 lines

Protocol Implementation

The Echo Worker demonstrates the core NDJSON protocol requirements:

Reading from stdin

import readline from 'readline';
 
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
terminal: false
});
 
rl.on('line', (line) => {
try {
const msg = JSON.parse(line);
handleMessage(msg);
} catch (err) {
console.error('Parse error:', err.message);
}
});
Code block in JavaScript, 16 lines

Writing to stdout

function sendResponse(id, result, sessionId) {
const response = {
jsonrpc: '2.0',
id: id,
result: result
};
if (sessionId) {
response.sessionId = sessionId;
}
console.log(JSON.stringify(response));
}
Code block in JavaScript, 13 lines

Handling SIGTERM

process.on('SIGTERM', () => {
console.error('Shutting down...');
rl.close();
});
 
rl.on('close', () => process.exit(0));
Code block in JavaScript, 6 lines

Testing Use Cases

Protocol Verification

Test that stdio Bus correctly routes messages to workers:

# Send request
echo '{"jsonrpc":"2.0","id":"1","method":"test","params":{}}' | nc localhost 9000
 
# Verify response format
# Should receive: {"jsonrpc":"2.0","id":"1","result":{"method":"test","params":{}}}
Code block in Bash, 5 lines

Session Affinity Testing

Test that messages with the same sessionId are routed to the same worker instance:

# Send multiple messages with same sessionId
echo '{"jsonrpc":"2.0","id":"1","method":"test","sessionId":"sess-123","params":{}}' | nc localhost 9000
echo '{"jsonrpc":"2.0","id":"2","method":"test","sessionId":"sess-123","params":{}}' | nc localhost 9000
echo '{"jsonrpc":"2.0","id":"3","method":"test","sessionId":"sess-123","params":{}}' | nc localhost 9000
 
# All responses should come from the same worker instance
Code block in Bash, 6 lines

Load Testing

Test stdio Bus performance with multiple concurrent connections:

# Run multiple clients in parallel
for i in {1..100}; do
echo '{"jsonrpc":"2.0","id":"'$i'","method":"test","params":{}}' | nc localhost 9000 &
done
wait
Code block in Bash, 5 lines

Error Handling

Test how stdio Bus handles malformed messages:

# Send invalid JSON
echo 'not-json' | nc localhost 9000
 
# Send JSON-RPC without required fields
echo '{"method":"test"}' | nc localhost 9000
Code block in Bash, 5 lines

Development Reference

The Echo Worker source code serves as a reference for creating custom workers. Key implementation patterns:

Message Handling

function handleMessage(msg) {
// Requests have an 'id' field and require a response
if (msg.id !== undefined) {
const result = {
method: msg.method,
params: msg.params
};
sendResponse(msg.id, result, msg.sessionId);
}
// Notifications don't have an 'id' and don't require a response
else {
console.error('Received notification:', msg.method);
}
}
Code block in JavaScript, 14 lines

Error Responses

function sendError(id, code, message, sessionId) {
const response = {
jsonrpc: '2.0',
id: id,
error: {
code: code,
message: message
}
};
if (sessionId) {
response.sessionId = sessionId;
}
console.log(JSON.stringify(response));
}
Code block in JavaScript, 16 lines

Logging

// Always log to stderr, never to stdout
console.error('Worker started');
console.error('Processing message:', msg.method);
console.error('Error occurred:', err.message);
Code block in JavaScript, 4 lines

Best Practices

When using the Echo Worker as a reference for custom workers:

  1. Never write non-JSON to stdout - All output to stdout must be valid NDJSON
  2. Log to stderr only - Use console.error() for all logging and debugging
  3. Preserve sessionId - Always include sessionId in responses when present in requests
  4. Handle SIGTERM - Implement graceful shutdown to avoid data loss
  5. Parse errors carefully - Catch JSON parse errors and log them to stderr
  6. Validate JSON-RPC - Check for required fields (jsonrpc, id, method)
  7. Use readline interface - Process stdin line-by-line for NDJSON protocol

Next Steps

Resources

  • Echo Worker Source Code
  • NDJSON Specification
stdioBus
© 2026 stdio Bus. All rights reserved.