scriptling.runtime.jsonrpc
Overview
The scriptling.runtime.jsonrpc library registers handlers for a JSON-RPC 2.0 server that runs over stdin/stdout or HTTP: it does not make outbound JSON-RPC calls. Handlers are referenced by string ("library.function"), the same model used by runtime.http, so each request runs on a fresh, isolated evaluator in its own goroutine and a slow handler never blocks the next request.
Start the stdio server with the --json-rpc flag:
scriptling --json-rpc setup.pyLogging is automatically redirected to stderr so it never corrupts the JSON-RPC stream on stdout.
Start the HTTP server with --server and --json-rpc:
scriptling --server :8000 --json-rpc setup.pyHTTP JSON-RPC is served at POST /json-rpc and can run alongside normal runtime.http routes and MCP tools.
Available Functions
| Function | Description |
|---|---|
method(name, handler) |
Register a JSON-RPC method handler |
notification(name, handler) |
Register a notification handler (no response) |
error(code, message, data=None) |
Build a structured JSON-RPC error response |
Functions
method(name, handler)
Registers a JSON-RPC method handler. The handler receives the decoded JSON-RPC params as its single argument and returns a JSON-compatible result. Raise an exception, or return jsonrpc.error(...), to produce an error response.
Parameters:
name(str): JSON-RPC method name.handler(str): Handler function as"library.function".
Returns: None
# setup.py
import scriptling.runtime as runtime
runtime.jsonrpc.method("echo", "handlers.echo")
runtime.jsonrpc.method("divide", "handlers.divide")# handlers.py
import scriptling.runtime as runtime
def echo(params):
return params
def divide(params):
if params["b"] == 0:
return runtime.jsonrpc.error(-32602, "division by zero", {"field": "b"})
return params["a"] / params["b"]notification(name, handler)
Registers a JSON-RPC notification handler. Notifications are JSON-RPC requests without an id field. The handler receives the decoded params but no response is written, and return values are ignored.
Parameters:
name(str): JSON-RPC notification name.handler(str): Handler function as"library.function".
Returns: None
import scriptling.runtime as runtime
def on_progress(params):
# Side effects only; no response is written.
pass
runtime.jsonrpc.notification("progress", "handlers.on_progress")error(code, message, data=None)
Builds a structured JSON-RPC error response. Return this from a method handler to emit a JSON-RPC error response with a custom code.
Parameters:
code(int): JSON-RPC error code (e.g.-32602for invalid params).message(str): Human-readable error message.data(any, optional): Optional structured data attached to the error. Default:None.
Returns: JSONRPCError: instance recognized by the server and converted into a JSON-RPC error response.
import scriptling.runtime as runtime
def divide(params):
if params["b"] == 0:
return runtime.jsonrpc.error(-32602, "division by zero", {"field": "b"})
return params["a"] / params["b"]Concurrency Model
Each request is dispatched on its own goroutine with a fresh Scriptling evaluator, mirroring runtime.http, MCP, and WebSocket serving. Handlers cannot share in-memory state across requests; coordinate through runtime.kv or runtime.sync instead.
Stdio Wire Format
- Requests are newline-delimited JSON objects (NDJSON), one per line.
- Batches (JSON arrays) are supported: each element is dispatched concurrently and a single JSON array of responses is returned.
- Notifications (requests with no
id) produce no response. - Integer precision is preserved (numbers are not coerced to floats).
HTTP Wire Format
- Send a single JSON-RPC object or batch array with
POST /json-rpc. - Requests return
200 application/json. - Notifications and all-notification batches return
204 No Content. - Notifications inside a mixed batch are handled but omitted from the response array.
- Integer precision is preserved.
Error Codes
| Code | Meaning | Source |
|---|---|---|
-32700 |
Parse error | Malformed JSON on stdin or in the HTTP request body |
-32600 |
Invalid request | Not a valid JSON-RPC 2.0 request |
-32601 |
Method not found | No handler registered for method |
-32602 |
Invalid params | Params failed to decode (or via error()) |
-32603 |
Internal error | Request cancelled |
-32000 |
Server error | Handler raised an exception or returned an error |
Examples
Sample stdio session
$ echo '{"jsonrpc":"2.0","method":"echo","params":{"hello":"world"},"id":1}' \
| scriptling --json-rpc setup.py
{"jsonrpc":"2.0","result":{"hello":"world"},"id":1}
$ echo '[{"jsonrpc":"2.0","method":"divide","params":{"a":1,"b":0},"id":1},
{"jsonrpc":"2.0","method":"echo","params":42,"id":2}]' \
| scriptling --json-rpc setup.py
[{"jsonrpc":"2.0","error":{"code":-32602,"message":"division by zero","data":{"field":"b"}},"id":1},
{"jsonrpc":"2.0","result":42,"id":2}]Sample HTTP session
$ curl -X POST http://127.0.0.1:8000/json-rpc \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"echo","params":{"hello":"world"},"id":1}'
{"jsonrpc":"2.0","result":{"hello":"world"},"id":1}
$ curl -i -X POST http://127.0.0.1:8000/json-rpc \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"progress","params":{"done":1}}'
HTTP/1.1 204 No ContentNotes
- Methods/notifications are registered during setup script execution, then frozen.
- The
JSONRPCErrorclass is exposed asruntime.jsonrpc.JSONRPCErrorfor type checks. - Use
--json-rpctogether with--kv-storageor--libpathexactly as you would for the HTTP--servermode.
Security Considerations
This is an extended library, requiring registration in Go, see Library Registration.
scriptling.runtime.jsonrpc is server-only: it registers method/notification handlers for an incoming JSON-RPC stream and never issues outbound JSON-RPC calls itself. The risk shape matches runtime.http: registering a method exposes that handler to any peer that can reach the stdio stream or POST /json-rpc endpoint, so treat every registered method as a network-reachable entry point and validate params defensively. For a full risk breakdown across all libraries, see the Security Guide.
See Also
- scriptling.runtime.http: HTTP route registration sharing the same per-request evaluator model
- scriptling.runtime.plugin: full plugin protocol server (functions, constants, and classes)
- scriptling.runtime.kv: share state across JSON-RPC handlers
- Security Guide