jsonrpcserver¶
Process incoming JSON-RPC 2.0 requests in Python.
jsonrpcserver takes a JSON-RPC 2.0 request, calls your Python function and gives you the response to send back. It leaves the networking to you, so it works with any framework or transport: Flask, Django, FastAPI, aiohttp, websockets, ZeroMQ and more. It runs sync and async methods, ships type hints, and is safe to use from several threads. It supports Python 3.8 to 3.14, including free-threaded 3.14t.
Install¶
pip install jsonrpcserver
Quickstart¶
Save this as server.py:
from jsonrpcserver import Result, Success, method, serve
@method
def ping() -> Result:
return Success("pong")
if __name__ == "__main__":
serve("localhost", 8000)
Run it with python server.py and leave it running. serve() is a small
server for trying things out. In production you'd use your web framework
instead, as in the framework examples.
In another terminal, send it a request with curl:
curl -s -H 'Content-Type: application/json' -d '{"jsonrpc": "2.0", "method": "ping", "id": 1}' http://localhost:8000/
{"jsonrpc": "2.0", "result": "pong", "id": 1}
Or call it from Python with
jsonrpcclient, the companion
library for the client side (pip install jsonrpcclient requests):
import requests
from jsonrpcclient import Error, Ok, parse, request
url = "http://localhost:8000/"
response = requests.post(url, json=request("ping"), timeout=10)
response.raise_for_status()
parsed = parse(response.json())
if isinstance(parsed, Ok):
print(parsed.result)
elif isinstance(parsed, Error):
print("Error:", parsed.message)
pong
What happens inside¶
The server passes each request body to dispatch, which calls your method and
gives back the response as a string:
>>> from jsonrpcserver import Result, Success, dispatch, method
>>> @method
... def ping() -> Result:
... return Success("pong")
>>> dispatch('{"jsonrpc": "2.0", "method": "ping", "id": 1}')
'{"jsonrpc": "2.0", "result": "pong", "id": 1}'
That's all there is to it in your own framework: pass the request body to
dispatch and send back what it gives you. A notification (a request with no
id) gives an empty string, which means there's nothing to send:
>>> dispatch('{"jsonrpc": "2.0", "method": "ping"}')
''
Over HTTP, answer that with status 204 and no body.
Where next¶
- Methods and Dispatch: writing methods, and the
options
dispatchtakes. - Frameworks: complete, tested examples for http.server, Flask, Werkzeug, Django, FastAPI, aiohttp, Sanic, Tornado, websockets, ZeroMQ and Socket.IO.
- Security: what to set before you put a server on the internet.
- Errors and logging: every error the client can get, and where the details go.
- API reference: every function and class, with signatures.
- Migrating from 4.x: methods must now return
Success(...). - jsonrpcclient: the same idea for the client side.