Skip to main content

wire_rpc

Typed asyncio JSON-RPC 2.0 with JSON/Pydantic/MessagePack codecs and TCP, HTTP, WebSocket, stdio, and in-process thread transports.

Quick start

The user guide covers handlers, routers, middleware, the client, transports, authentication, monitoring and testing.

A server registers handlers on an App. The type hint on params sets how incoming params are validated, and the return hint sets how the result is encoded.

# server.py
import msgspec
from wire_rpc import App
from wire_rpc.transports.tcp import TcpServerTransport


class AddParams(msgspec.Struct):
    a: int
    b: int


app = App(TcpServerTransport(host="127.0.0.1", port=9000))


@app.method("add")
async def add(params: AddParams, ctx) -> int:
    return params.a + params.b


if __name__ == "__main__":
    app.run()

A client calls a method by name and names the type it expects back:

# client.py
import asyncio
from wire_rpc import Client
from wire_rpc.transports.tcp import TcpClientTransport


async def main():
    async with Client(TcpClientTransport(host="127.0.0.1", port=9000)) as client:
        print(await client.call("add", int, {"a": 2, "b": 3}))  # 5


asyncio.run(main())

A server error reaches the client as WireRpcError, which carries the JSON-RPC code and message. Handler exception details are never sent to the client.

Batches (a JSON array of requests, as in section 6 of the JSON-RPC 2.0 spec) work on every transport. A batch shares one handler_timeout, holds at most max_batch_size calls (100 by default), and its reply always fits max_response_size.

Handlers take (ctx) or (params, ctx). ctx is whatever the @app.on_startup hook returned, such as a database pool. Trusted request metadata, including the authenticated principal, comes from current_request(). Group related methods with Router("prefix"), and wrap them with @app.middleware or @router.middleware.

Transports

App serves one peer, and requests run one at a time. MulticastApp serves many peers, each identified by a client_id, and can broadcast notifications to all of them.

Transport Use with Notes
TcpServerTransport / TcpClientTransport App / Client Length-prefixed frames, optional TLS. The server serves one connection; the app stops when it closes.
TcpMulticastServerTransport MulticastApp Many TCP clients, bounded per-client queues.
HttpServerTransport / HttpClientTransport App / Client One POST /rpc per call. Text codecs only.
WsServerTransport / WsClientTransport App / Client One WebSocket connection on /ws. Text codecs only.
MulticastWsServerTransport MulticastApp Many WebSocket clients, for browsers.
StdIoTransport / StdIoServerTransport Client / App Talk to a child process over its stdin/stdout.
ThreadTransport App + Client Two threads in one process, each with its own event loop.

Every transport enforces a maximum message size. Authentication is set per transport with auth=; see the authentication suite.

Between threads

ThreadTransport.pair() returns two connected ends. Give one to each thread; each end binds to the event loop of the thread that connects it. Sending copies the message, and an end that is full (max_queue_size unread messages) rejects new sends instead of growing without limit. Either thread can start first: a send waits up to connect_timeout (5 seconds by default) for the other end to connect.

import asyncio
import threading

from wire_rpc import App, Client
from wire_rpc.transports import ThreadTransport

client_end, server_end = ThreadTransport.pair()
app = App(server_end)


@app.method("add")
async def add(params: dict, ctx) -> int:
    return params["a"] + params["b"]


threading.Thread(target=app.run, daemon=True).start()


async def main():
    async with Client(client_end) as client:
        print(await client.call("add", int, {"a": 2, "b": 3}))  # 5


asyncio.run(main())

Development and release checks

Requires Python 3.12 or newer, uv, and a running Docker daemon for the full suite. Testcontainers starts isolated PostgreSQL 17 and Redis 7 services automatically. Missing Docker or a failed container startup fails the tests; no backend is silently skipped. To explicitly run only tests without Docker: uv run --locked pytest -q -W error -m "not integration".

uv sync --locked
uv run --locked pyrefly check
uv run --locked ruff check
uv run --locked pytest -q -W error
uv build --no-sources
uv run --locked python scripts/check_wheel.py

Pyrefly checks the package, tests, and release scripts against a Python 3.12 baseline, configured in [tool.pyrefly], and runs in CI. Ruff enforces pyflakes rules and import order, configured in [tool.ruff]; uv run ruff check --fix sorts imports.

Tests are organized by attack surface. Concurrency tests use events and controlled ordering; socket tests use ephemeral ports. Test timeouts are deadlock guards. The CI matrix covers Python 3.12–3.14 on Linux, macOS, and Windows.

Releases follow semantic versioning; see the changelog for the policy and for breaking changes. Report vulnerabilities privately as described in SECURITY.md.

Read production contracts before deploying, including codec compatibility, identity propagation, overload behavior, cancellation semantics, resource budgets, and platform limitations.

Benchmarks give rough per-transport latency and throughput, and how to reproduce them.

The execution plan records the follow-up hardening work. The initial review records the first transport/codec regression pass.

The authentication suite documents authenticators, credential validators, session backends, client credentials, TLS policy, and adversarial backend tests. Optional extras are password, jwt, redis, and postgres; core imports do not require them.

Metadata

Release files for wire-rpc 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for wire-rpc 0.2.0
File Size Uploaded Provenance Actions
wire_rpc-0.2.0.tar.gz 257.4 kB Without provenance Details for wire_rpc-0.2.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for wire-rpc 0.2.0
File Interpreter ABI Platform Actions
wire_rpc-0.2.0-py3-none-any.whl Python 3 none any Details for wire_rpc-0.2.0-py3-none-any.whl

Total release size: 348.7 kB

Release files / wire_rpc-0.2.0.tar.gz

Download URL wire_rpc-0.2.0.tar.gz
Size 257.4 kB
Tags Source
SHA-256 checksum
How to use checksums
413538c2996024d22d94855a5d436a3cb369cf71bc94f47c20c6133fe1478a8b
BLAKE2b-256 checksum
How to use checksums
cdb2bb0e98ff94a2bc5453fedf9621d09a2fac770a1e4993e41678b771144f77
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.6.3

Release files / wire_rpc-0.2.0-py3-none-any.whl

Download URL wire_rpc-0.2.0-py3-none-any.whl
Size 91.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
738c8ef4fce267d12ed54a665dfab25dbbf906e59b7882eb61a55950b4d73127
BLAKE2b-256 checksum
How to use checksums
859f55b0b7c8886856489962bf0bb86bf29f222ae6a83f16831998b493e22f09
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.6.3

Security for wire-rpc 0.2.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page