Transport-level routing for MCP/ACP protocols

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

API Reference

Complete API reference for @stdiobus/workers-registry, including module imports, TypeScript types, and environment variables.

Getting Started

API Reference

Overview

The @stdiobus/workers-registry package provides worker implementations for stdio Bus kernel. This reference covers the programmatic API for importing and using workers in your applications.

Package Information

Package name: @stdiobus/workers-registry

Version: 1.3.19 (pre-release)

License: Apache-2.0

Repository: github.com/stdiobus/workers-registry

npm: npmjs.com/package/@stdiobus/workers-registry

Installation

npm install @stdiobus/workers-registry
Code block in Bash, 1 line

Requirements:

  • Node.js ≥20.0.0
  • TypeScript 5.x (for TypeScript projects)

Module Imports

Default Export

The default export provides the ACP Worker:

// CommonJS
const worker = require('@stdiobus/workers-registry');
 
// ES Modules
import worker from '@stdiobus/workers-registry';
Code block in JavaScript, 5 lines

Named Exports

Import specific workers using named exports:

// Import specific workers
import {
acpWorker,
echoWorker,
mcpEchoServer,
mcpToAcpProxy,
registryLauncher
} from '@stdiobus/workers-registry/workers';
 
// Import workers metadata
import { workers } from '@stdiobus/workers-registry/workers';
Code block in JavaScript, 11 lines

Worker Paths

Import workers by path:

// ACP Worker
import acpWorker from '@stdiobus/workers-registry/workers/acp-worker';
 
// Echo Worker
import echoWorker from '@stdiobus/workers-registry/workers/echo-worker';
 
// MCP Echo Server
import mcpEchoServer from '@stdiobus/workers-registry/workers/mcp-echo-server';
 
// MCP-to-ACP Proxy
import mcpToAcpProxy from '@stdiobus/workers-registry/workers/mcp-to-acp-proxy';
 
// Registry Launcher
import registryLauncher from '@stdiobus/workers-registry/workers/registry-launcher';
Code block in JavaScript, 14 lines

Workers Metadata

The package exports a metadata object containing information about all available workers:

import { workers } from '@stdiobus/workers-registry/workers';
 
console.log(workers);
// {
// 'acp-worker': {
// name: 'ACP Worker',
// description: 'Full ACP protocol implementation',
// entrypoint: './workers/acp-worker/dist/index.js',
// protocol: 'ACP'
// },
// 'echo-worker': {
// name: 'Echo Worker',
// description: 'Simple echo worker for testing',
// entrypoint: './workers/echo-worker/echo-worker.js',
// protocol: 'NDJSON'
// },
// // ... other workers
// }
Code block in JavaScript, 18 lines

Workers Metadata Structure

interface WorkersMetadata {
[workerId: string]: {
name: string; // Display name
description: string; // Brief description
entrypoint: string; // Path to worker entry point
protocol: string; // Protocol(s) supported
};
}
Code block in TypeScript, 8 lines

TypeScript Types

Worker Types

// ACP Worker types
import type { ACPAgent } from '@stdiobus/workers-registry/workers/acp-worker';
import type { ACPSession } from '@stdiobus/workers-registry/workers/acp-worker';
import type { ACPMessage } from '@stdiobus/workers-registry/workers/acp-worker';
 
// MCP Echo Server types
import type { MCPServer } from '@stdiobus/workers-registry/workers/mcp-echo-server';
import type { MCPTool } from '@stdiobus/workers-registry/workers/mcp-echo-server';
 
// Registry Launcher types
import type { RegistryAgent } from '@stdiobus/workers-registry/workers/registry-launcher';
import type { AgentMetadata } from '@stdiobus/workers-registry/workers/registry-launcher';
Code block in TypeScript, 12 lines

Configuration Types

/**
* stdio Bus pool configuration
*/
interface PoolConfig {
/** Unique identifier for this worker pool */
id: string;
/** Path to the executable */
command: string;
/** Command-line arguments */
args?: string[];
/** Number of worker instances */
instances: number;
/** Environment variables */
env?: Record<string, string>;
}
 
/**
* stdio Bus limits configuration
*/
interface LimitsConfig {
/** Maximum input buffer size per connection (bytes) */
max_input_buffer?: number;
/** Maximum output queue size per connection (bytes) */
max_output_queue?: number;
/** Maximum worker restarts within restart window */
max_restarts?: number;
/** Time window for counting restarts (seconds) */
restart_window_sec?: number;
/** Timeout for graceful shutdown (seconds) */
drain_timeout_sec?: number;
/** Timeout before closing connection when queue is full (seconds) */
backpressure_timeout_sec?: number;
}
 
/**
* Complete stdio Bus configuration
*/
interface StdioBusConfig {
/** Worker pool configurations */
pools: PoolConfig[];
/** Resource limits */
limits?: LimitsConfig;
}
Code block in TypeScript, 43 lines

JSON-RPC Types

/**
* JSON-RPC 2.0 request
*/
interface JSONRPCRequest {
/** JSON-RPC version (always "2.0") */
jsonrpc: '2.0';
/** Request ID (string or number) */
id: string | number;
/** Method name */
method: string;
/** Method parameters */
params?: Record<string, any>;
/** Optional session ID for session affinity */
sessionId?: string;
}
 
/**
* JSON-RPC 2.0 response
*/
interface JSONRPCResponse {
/** JSON-RPC version (always "2.0") */
jsonrpc: '2.0';
/** Request ID */
id: string | number;
/** Result (if successful) */
result?: any;
/** Error (if failed) */
error?: JSONRPCError;
/** Optional session ID */
sessionId?: string;
}
 
/**
* JSON-RPC 2.0 error
*/
interface JSONRPCError {
/** Error code */
code: number;
/** Error message */
message: string;
/** Additional error data */
data?: any;
}
 
/**
* JSON-RPC 2.0 notification (no response expected)
*/
interface JSONRPCNotification {
/** JSON-RPC version (always "2.0") */
jsonrpc: '2.0';
/** Method name */
method: string;
/** Method parameters */
params?: Record<string, any>;
}
Code block in TypeScript, 55 lines

Environment Variables

Global Variables

These environment variables apply to all workers:

VariableTypeDefaultDescription
NODE_ENVstringdevelopmentNode.js environment (development, production)
LOG_LEVELstringinfoLogging level (debug, info, warn, error)
DEBUGstring-Enable debug output (set to * for all)

ACP Worker Variables

VariableTypeDefaultDescription
MCP_SERVERSstring-Comma-separated list of MCP server names
MCP_CONFIG_PATHstring./mcp-servers.jsonPath to MCP servers configuration file

Registry Launcher Variables

VariableTypeDefaultDescription
REGISTRY_URLstringACP Registry URLURL to ACP Registry JSON
CACHE_TTLnumber3600Registry cache TTL in seconds
API_KEYS_PATHstring-Path to API keys configuration file

MCP-to-ACP Proxy Variables

VariableTypeDefaultDescription
ACP_HOSTstringlocalhoststdio Bus host address
ACP_PORTstring9000stdio Bus port number
AGENT_IDstring-Target agent ID for routing
TIMEOUTnumber30000Request timeout in milliseconds

MCP Echo Server Variables

VariableTypeDefaultDescription
LOG_LEVELstringinfoLogging level
NODE_ENVstringdevelopmentNode.js environment

Programmatic Usage

Running Workers Programmatically

import { spawn } from 'child_process';
import { workers } from '@stdiobus/workers-registry/workers';
 
/**
* Spawn a worker process
*/
function spawnWorker(workerId, args = []) {
const workerMeta = workers[workerId];
if (!workerMeta) {
throw new Error(`Unknown worker: ${workerId}`);
}
 
const worker = spawn('node', [
workerMeta.entrypoint,
...args
], {
stdio: ['pipe', 'pipe', 'pipe']
});
 
return worker;
}
 
// Usage
const echoWorker = spawnWorker('echo-worker');
 
// Send message to worker
echoWorker.stdin.write(JSON.stringify({
jsonrpc: '2.0',
id: '1',
method: 'test',
params: {}
}) + '\n');
 
// Read response from worker
echoWorker.stdout.on('data', (data) => {
const response = JSON.parse(data.toString());
console.log('Response:', response);
});
 
// Handle errors
echoWorker.stderr.on('data', (data) => {
console.error('Worker error:', data.toString());
});
 
// Handle exit
echoWorker.on('exit', (code) => {
console.log('Worker exited with code:', code);
});
Code block in JavaScript, 48 lines

Creating Custom Workers

import readline from 'readline';
 
/**
* Base class for custom workers
*/
class BaseWorker {
constructor() {
this.rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
terminal: false
});
 
this.setupHandlers();
}
 
setupHandlers() {
this.rl.on('line', (line) => {
try {
const message = JSON.parse(line);
this.handleMessage(message);
} catch (err) {
console.error('Parse error:', err.message);
}
});
 
process.on('SIGTERM', () => {
this.shutdown();
});
 
this.rl.on('close', () => {
process.exit(0);
});
}
 
handleMessage(message) {
// Override in subclass
if (message.id !== undefined) {
this.sendResponse(message.id, {
status: 'ok'
}, message.sessionId);
}
}
 
sendResponse(id, result, sessionId = null) {
const response = {
jsonrpc: '2.0',
id,
result
};
 
if (sessionId) {
response.sessionId = sessionId;
}
 
console.log(JSON.stringify(response));
}
 
sendError(id, code, message, sessionId = null) {
const response = {
jsonrpc: '2.0',
id,
error: {
code,
message
}
};
 
if (sessionId) {
response.sessionId = sessionId;
}
 
console.log(JSON.stringify(response));
}
 
shutdown() {
console.error('Shutting down...');
this.rl.close();
}
}
 
// Usage
class MyWorker extends BaseWorker {
handleMessage(message) {
if (message.method === 'myMethod') {
this.sendResponse(message.id, {
result: 'success'
}, message.sessionId);
} else {
this.sendError(message.id, -32601, 'Method not found', message.sessionId);
}
}
}
 
const worker = new MyWorker();
Code block in JavaScript, 95 lines

Worker Communication

import { EventEmitter } from 'events';
import readline from 'readline';
 
/**
* Worker communication helper
*/
class WorkerClient extends EventEmitter {
constructor(worker) {
super();
this.worker = worker;
this.requestId = 0;
this.pendingRequests = new Map();
this.setupReadline();
}
 
setupReadline() {
const rl = readline.createInterface({
input: this.worker.stdout,
crlfDelay: Infinity
});
 
rl.on('line', (line) => {
try {
const response = JSON.parse(line);
this.handleResponse(response);
} catch (err) {
this.emit('error', err);
}
});
 
this.worker.stderr.on('data', (data) => {
this.emit('stderr', data.toString());
});
 
this.worker.on('exit', (code) => {
this.emit('exit', code);
});
}
 
handleResponse(response) {
if (response.id && this.pendingRequests.has(response.id)) {
const { resolve, reject } = this.pendingRequests.get(response.id);
this.pendingRequests.delete(response.id);
 
if (response.error) {
reject(new Error(response.error.message));
} else {
resolve(response.result);
}
}
}
 
sendRequest(method, params = {}, sessionId = null) {
return new Promise((resolve, reject) => {
const id = String(++this.requestId);
const request = {
jsonrpc: '2.0',
id,
method,
params
};
 
if (sessionId) {
request.sessionId = sessionId;
}
 
this.pendingRequests.set(id, { resolve, reject });
this.worker.stdin.write(JSON.stringify(request) + '\n');
});
}
 
close() {
this.worker.kill('SIGTERM');
}
}
 
// Usage
import { spawn } from 'child_process';
 
const worker = spawn('node', [
'@stdiobus/workers-registry',
'echo-worker'
]);
 
const client = new WorkerClient(worker);
 
client.on('stderr', (data) => {
console.error('Worker stderr:', data);
});
 
client.on('exit', (code) => {
console.log('Worker exited:', code);
});
 
// Send request
const result = await client.sendRequest('test', { foo: 'bar' });
console.log('Result:', result);
 
// Close worker
client.close();
Code block in JavaScript, 100 lines

Command-Line Interface

Universal Launcher

Run any worker using the universal launcher:

npx @stdiobus/workers-registry <worker-name> [args...]
Code block in Bash, 1 line

Available workers:

  • acp-worker - ACP Worker
  • registry-launcher - Registry Launcher
  • echo-worker - Echo Worker
  • mcp-echo-server - MCP Echo Server
  • mcp-to-acp-proxy - MCP-to-ACP Proxy

Examples:

# Run echo worker
npx @stdiobus/workers-registry echo-worker
 
# Run ACP worker
npx @stdiobus/workers-registry acp-worker
 
# Run registry launcher with API keys
npx @stdiobus/workers-registry registry-launcher /path/to/api-keys.json
Code block in Bash, 8 lines

Direct Worker Execution

Run workers directly using their entry points:

# Echo Worker
node ./node_modules/@stdiobus/workers-registry/workers/echo-worker/echo-worker.js
 
# ACP Worker
node ./node_modules/@stdiobus/workers-registry/workers/acp-worker/dist/index.js
 
# MCP Echo Server
node ./node_modules/@stdiobus/workers-registry/workers/mcp-echo-server/dist/index.js
Code block in Bash, 8 lines

Error Handling

Error Codes

Standard JSON-RPC 2.0 error codes:

CodeMessageDescription
-32700Parse errorInvalid JSON
-32600Invalid RequestMissing required fields
-32601Method not foundUnknown method
-32602Invalid paramsInvalid parameters
-32603Internal errorWorker internal error

Worker-specific error codes:

CodeMessageDescription
-32000Server errorGeneric worker error
-32001Session not foundInvalid session ID
-32002Agent not foundInvalid agent ID
-32003Tool not foundInvalid tool name
-32004Tool execution errorTool execution failed

Error Handling Example

try {
const result = await client.sendRequest('test', {});
console.log('Success:', result);
} catch (err) {
if (err.code === -32601) {
console.error('Method not found');
} else if (err.code === -32602) {
console.error('Invalid parameters');
} else {
console.error('Error:', err.message);
}
}
Code block in JavaScript, 12 lines

Best Practices

Module Imports

  1. Use named imports - More explicit and tree-shakeable
  2. Import types separately - Keep types separate from runtime code
  3. Use path imports - Import specific workers by path for better code splitting

Worker Management

  1. Handle SIGTERM - Always implement graceful shutdown
  2. Log to stderr - Never write non-JSON to stdout
  3. Validate input - Check JSON-RPC format and required fields
  4. Preserve sessionId - Include sessionId in responses when present

Error Handling

  1. Use standard error codes - Follow JSON-RPC 2.0 specification
  2. Provide error details - Include helpful error messages
  3. Handle timeouts - Set appropriate timeouts for requests
  4. Retry logic - Implement exponential backoff for retries

Performance

  1. Reuse connections - Keep worker processes alive
  2. Connection pooling - Use multiple worker instances
  3. Buffer management - Monitor buffer sizes and backpressure
  4. Resource cleanup - Clean up resources promptly

Next Steps

stdioBus
© 2026 stdio Bus. All rights reserved.