Command Palette

Search for a command to run...

Home / Servers

rpc

Updated 12d ago

by source-repo

Source RPC

TypeScript RPC for a network of peers — a browser tab, a Node service, and a plant full of devices — over WebSocket and MQTT 5, with one programming model across all of them.

A class is the contract. There is no code generation, no schema language and no .proto file: the server hands one live instance to exposeClassInstance, the client compiles against the same class with import type, and calling a method on the typed proxy runs it on that instance.

npm install @source-repo/rpc

If all you need is a browser and a Node server

Use tRPC. It is very good at exactly that, it is far more widely used, and you will find more answers to your questions.

Come here when the shape is different — when there are more than two parties and they are not all on the same kind of link:

  • devices on an MQTT broker and operator screens on a WebSocket, calling each other without either end knowing which transport the other is on
  • peers that cannot listen — a browser tab hosting a service, a box behind NAT — that still need to be addressable by name
  • commands that change something physical, where sending one twice is not free

The problem it is built around

Most RPC libraries make it easy to call a function. Rather fewer distinguish the call failed from I lost the answer to a command that may well have run — and when the call opens a valve, that is the distinction that decides whether an operator sends a second start.

Retrying a read costs a round trip. Retrying a start costs a second start.

A class is the contract

// pump.ts — shared by both sides. No base class, and the decorators are optional.
export class Pump {
    private bar = 0

    @rpc({ semantics: 'query' })                    async pressure()             { return this.bar }
    @rpc({ semantics: 'idempotent-command' })       async setSetpoint(bar: number) { this.bar = bar }
    @rpc({ semantics: 'non-repeatable-command' })   async dispense()             { /* … */ }
}

The server holds one long-lived instance. State lives in fields, where you would have put it anyway; nothing is constructed or discarded per call.

const server = new RpcServer({ name: 'plantServer', transports: [{ brokerurl: 'mqtt://plant:1883' }] })
server.exposeClassInstance(new Pump(), 'pump')
await server.ready()

The caller imports the type and none of the code, so the implementation never reaches a browser bundle.

import type { Pump } from './pump.js'

const pump = await client.proxy<Pump>('pump', 'plantServer')
await pump.setSetpoint(4)

The network

A peer is anything with a name, and a frame is addressed to a name, not to a socket. Once that is true, a server can call as well as answer, and a server that exposes nothing and forwards everything is a bus — so there is no separate broker implementation, and there should not be.

   browser tab              browser tab
   hosting a service        running the console
            │                       │
            └───────────┬───────────┘
                        │  WebSocket (socket.io)
                  ┌─────┴──────┐
                  │    bus     │  :7843   relays; exposes nothing
                  └─────┬──────┘
                        │  MQTT 5
        ┌───────────────┼───────────────┐
        │               │               │
   plantServer       cellSrv         ovenSrv

The console calls ovenSrv without knowing it is on MQTT. ovenSrv calls the browser tab without knowing it cannot listen. Peers announce themselves, so discovery is free — no scanning, no configured host list — and a peer is never advertised back down the link it came from, so brokers joined in a ring settle rather than storm.

What you get that is hard to find elsewhere

Related servers

n8n

Updated today

by n8n-io

Fair-code workflow automation platform with native AI capabilities. Combine visual building with custom code, self-host or cloud, 400+ integrations.

204,501

mcp-server-fetch

OfficialUpdated 14d ago

by modelcontextprotocol

A Model Context Protocol server providing tools to fetch and convert web content for usage by LLMs

90,371

@modelcontextprotocol/server-everything

OfficialUpdated 14d ago

by modelcontextprotocol

MCP server that exercises all the features of the MCP protocol

90,371

mcp-server-git

OfficialUpdated 14d ago

by modelcontextprotocol

A Model Context Protocol server providing tools to read, search, and manipulate Git repositories programmatically via LLMs

90,371