Skip to main content

tw2_jsonrpc

tw2_jsonrpc is the Python sibling of the Rust tw2-jsonrpc experiment: one bidirectional JSON-RPC Peer, async-first transport code, named params only, and a small decorator API for registering local methods.

This package is peer-first: connect over TCP, attach to stdio, connect over WebSocket, launch a child process that speaks over stdio, or accept TCP and WebSocket peers with a server registry.

Client Call

import tw2_jsonrpc

async with await tw2_jsonrpc.connect_tcp("127.0.0.1", 8080) as peer:
    result = await peer.call("math.add", a=2, b=3)

Params are named only. Pass a dict or omit params:

await peer.call("math.add", {"a": 2, "b": 3})
await peer.call("math.add", a=2, b=3)
await peer.call("health")

Array params are rejected with InvalidParams.

Transports

All transports return a Peer. After that, calls and notifications feel the same.

peer = await tw2_jsonrpc.connect_tcp("127.0.0.1", 8080)
peer = await tw2_jsonrpc.connect_stdio()
peer = await tw2_jsonrpc.connect_ws("ws://127.0.0.1:8080/rpc")

Subprocesses

Use start_subprocess when the library should launch and own a child process that speaks newline-delimited JSON-RPC over stdio. This is stdio JSON-RPC with child-process lifecycle management, not a separate transport protocol:

peer = await tw2_jsonrpc.start_subprocess(["worker", "--stdio"])

start_process remains available as an alias.

Server

A Server owns methods that should be installed on every peer it creates. peer_cls is chosen at the transport boundary:

server = tw2_jsonrpc.Server()

@server.method("math.add")
async def add(a: int, b: int) -> int:
    return a + b

handle = await server.serve_tcp("127.0.0.1", 8080, peer_cls=tw2_jsonrpc.TcpPeer)
await handle.serve_forever()

Peer subclasses can still carry per-peer state and methods:

class AppPeer(tw2_jsonrpc.TcpPeer):
    @tw2_jsonrpc.method("session.ping")
    async def ping(self) -> str:
        return "pong"

handle = await server.serve_tcp("127.0.0.1", 8080, peer_cls=AppPeer)

Use a handler for per-connection setup:

async def on_peer(peer: AppPeer) -> None:
    @peer.method("session.echo")
    async def echo(text: str) -> str:
        return text

handle = await server.serve_tcp(
    "127.0.0.1",
    8080,
    peer_cls=AppPeer,
    handler=on_peer,
)

WebSocket serving and subprocess peers use the same server registry:

handle = await server.serve_ws("127.0.0.1", 8080, peer_cls=tw2_jsonrpc.WebSocketPeer)
peer = await server.connect_subprocess(["worker", "--stdio"], peer_cls=tw2_jsonrpc.SubprocessPeer)

The free serve_tcp and serve_ws helpers remain available when you do not need server-wide methods.

Peer Handlers

Runtime registration is available directly on a peer:

peer = await tw2_jsonrpc.connect_stdio()

@peer.method("math.add")
async def add(a: int, b: int) -> int:
    return a + b

The method name can default to the function name:

@peer.method
async def health() -> dict:
    return {"ok": True}

Peer subclasses can expose decorated methods:

class App(tw2_jsonrpc.StdioPeer):
    @tw2_jsonrpc.method("tools.echo")
    async def echo(self, text: str) -> str:
        return text

Subclass handlers receive self as the current peer, so callbacks and notifications can use the same object:

class App(tw2_jsonrpc.StdioPeer):
    @tw2_jsonrpc.method("callback.demo")
    async def callback_demo(self, name: str) -> dict:
        await self.notify("callback.ready", {"name": name})
        return {"ok": True}

You can also register or remove handlers explicitly:

peer.add_method(echo, "tools.echo")
peer.remove_method("tools.echo")

Notifications

Notifications are fire-and-forget. No result is returned.

await peer.notify("log.info", message="started")

Handlers live in the same method table. If the incoming JSON-RPC message omits id, no response is sent, even if the handler returns a value.

For readability, notification is available as an alias for method registration:

@peer.notification("log.info")
async def log_info(message: str) -> None:
    print(message)

Errors

Remote JSON-RPC error responses become JsonRpcError subclasses:

try:
    result = await peer.call("math.add", {"a": 1, "b": 2})
except tw2_jsonrpc.InvalidParams:
    ...
except tw2_jsonrpc.JsonRpcError:
    ...

Handlers can raise structured JSON-RPC errors:

raise tw2_jsonrpc.InvalidParams("field 'name' is required")

Local timeout and cancellation stay local:

result = await peer.call("slow.method", {"x": 1}, timeout=5.0)

If a call is cancelled or times out, the pending local waiter is removed. JSON-RPC 2.0 has no standard remote cancellation, so a later response for that id is ignored.

Mental Model

  • Peer is a bidirectional JSON-RPC connection.
  • await peer.call(...) sends a request and returns the decoded result.
  • await peer.notify(...) sends a fire-and-forget message.
  • @peer.method registers a request handler.
  • Server registers methods shared by every peer it accepts or starts.
  • @peer.notification is a readability alias for notification handlers.
  • Only named params are supported.
  • The shape is intentionally close to tw2-jsonrpc, but Python does not need a builder or proc macro.

Metadata

Release files for tw2-jsonrpc 1.0.1

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

Source distribution (sdist)

Source distribution for tw2-jsonrpc 1.0.1
File Size Uploaded Provenance Actions
tw2_jsonrpc-1.0.1.tar.gz 8.1 kB Without provenance Details for tw2_jsonrpc-1.0.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for tw2-jsonrpc 1.0.1
File Interpreter ABI Platform Actions
tw2_jsonrpc-1.0.1-py3-none-any.whl Python 3 none any Details for tw2_jsonrpc-1.0.1-py3-none-any.whl

Total release size: 20.2 kB

Release files / tw2_jsonrpc-1.0.1.tar.gz

Download URL tw2_jsonrpc-1.0.1.tar.gz
Size 8.1 kB
Tags Source
SHA-256 checksum
How to use checksums
f57ed9c105bc8653b16b54cb75f8c677cbcacc009fe0544958b0e170045daa29
BLAKE2b-256 checksum
How to use checksums
f482587146dc9b1805cbd562b4463ee4088761c95b29d0f56a7d604e01ae18e2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.14 {"installer":{"name":"uv","version":"0.11.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / tw2_jsonrpc-1.0.1-py3-none-any.whl

Download URL tw2_jsonrpc-1.0.1-py3-none-any.whl
Size 12.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
be36ddb9c294db5ca5c04d674c8f169b33f08f8d2ff8eca45e2c29b3121eb895
BLAKE2b-256 checksum
How to use checksums
7058f0092ba04e7c561941f482f3b62b2bb7c27efbdae47cc058aea4f970e4c8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.14 {"installer":{"name":"uv","version":"0.11.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Security for tw2-jsonrpc 1.0.1

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

1.0.1 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