NPM Version PyPI Version License
Bidirectional JSON-RPC 2.0 over WebSocket β TypeScript & Python.
# TypeScript npm install echorpc # Python pip install echorpc
- Bidirectional RPC β server and client can call each other's methods
- Pub/Sub β fire-and-forget notifications via
publish/subscribe - Batch requests β multiple calls per frame, results returned in order
- Auth β token validated during HTTP upgrade
- Heartbeat β ping/pong with auto-disconnect on timeout
- Auto-reconnect β exponential backoff, handlers and subscriptions preserved
- Broadcast β send to all connections, filter by role, or exclude specific peers
from echorpc import EchoServer server = EchoServer(port=9100, auth_handler=lambda p: p["token"] == "secret") # Define a command that clients can call @server.command("add") def add(params): return {"sum": params["a"] + params["b"]} # Listen for events from clients @server.event("chat") async def on_chat(data): print("on_chat", data) await server.start()
from echorpc import EchoClient client = EchoClient("ws://localhost:9100", token="secret") # Let the server call you back client.register("double", lambda p: p["x"] * 2) # Subscribe to events client.subscribe("chat", lambda data: print(data)) await client.connect() # Call a server command result = await client.request("add", {"a": 1, "b": 2}) # Publish event to the server await client.publish("chat", {"text": "hello"}) # Send multiple calls at once results = await client.batch_request([ ("add", {"a": 1, "b": 2}), ("add", {"a": 3, "b": 4}), ])
import { EchoServer } from "echorpc"; const server = new EchoServer({ port: 9100, authHandler: (p) => p.token === "secret", }); // Define a command that clients can call server.register("add", (p: { a: number; b: number }) => ({ sum: p.a + p.b, })); // Listen for events from clients server.subscribe("chat", async (data) => { console.log("chat", data); }); await server.start();
import WebSocket from "ws"; import { EchoClient } from "echorpc"; const client = new EchoClient("ws://localhost:9100", { token: "secret", WebSocket, }); // Let the server call you back client.register("double", (p) => p.x * 2); // Subscribe to events client.subscribe("chat", (data) => console.log(data)); await client.connect(); // Call a server command const result = await client.request("add", { a: 1, b: 2 }); // Publish event to the server client.publish("chat", { text: "hello" }); // Send multiple calls at once const results = await client.batchRequest([ ["add", { a: 1, b: 2 }], ["add", { a: 3, b: 4 }], ]);
No WebSocket import needed β uses the native one.
import { EchoClient } from "echorpc"; const client = new EchoClient("ws://localhost:9100", { token: "secret" }); await client.connect();
| Code | Name | Meaning |
|---|---|---|
| -32700 | Parse error | Invalid JSON |
| -32601 | Method not found | No such method |
| -32603 | Internal error | Handler threw |
| -32001 | Not connected | No active connection |
| -32002 | Timeout | Request timed out |
| -32003 | Auth failed | Authentication rejected |
MIT License Β© 2026-PRESENT Del Wang