json_rpc

JSON-RPC 2.0 protocol encoding and decoding library. Provides predicates for constructing, parsing, classifying, and inspecting JSON-RPC 2.0 messages (requests, notifications, responses, and error responses). Also provides stream-based message I/O for implementing JSON-RPC clients and servers, including Content-Length header framing as used by the Language Server Protocol (LSP) and the Model Context Protocol (MCP). Uses the json library for JSON parsing and generation.

API documentation

Open the ../../apis/library_index.html#json_rpc link in a web browser.

Loading

To load this library, load the loader.lgt file:

| ?- logtalk_load(json_rpc(loader)).

Testing

To test this library predicates, load the tester.lgt file:

| ?- logtalk_load(json_rpc(tester)).

Usage

Constructing JSON-RPC 2.0 messages

Construct requests, notifications, responses, and error responses:

| ?- json_rpc::request(subtract, [42,23], 1, Request).
Request = {jsonrpc-'2.0', method-subtract, params-[42,23], id-1}.

| ?- json_rpc::notification(update, [1,2,3], Notification).
Notification = {jsonrpc-'2.0', method-update, params-[1,2,3]}.

| ?- json_rpc::response(19, 1, Response).
Response = {jsonrpc-'2.0', result-19, id-1}.

| ?- json_rpc::error_response(-32601, 'Method not found', 1, ErrorResponse).

Standard error constructors

| ?- json_rpc::parse_error(Error).
Error = ...

| ?- json_rpc::invalid_request(Error).
Error = ...

| ?- json_rpc::method_not_found(1, Error).
Error = ...

| ?- json_rpc::invalid_params(1, Error).
Error = ...

| ?- json_rpc::internal_error(1, Error).
Error = ...

Encoding and decoding

| ?- json_rpc::request(subtract, [42,23], 1, Request),
   json_rpc::encode(Request, JSON).
JSON = '{"jsonrpc":"2.0","method":"subtract","params":[42,23],"id":1}'.

| ?- json_rpc::decode('{"jsonrpc":"2.0","result":19,"id":1}', Term).

Message classification

| ?- json_rpc::is_request(Message).
...

| ?- json_rpc::is_notification(Message).
...

| ?- json_rpc::is_response(Message).
...

| ?- json_rpc::is_error_response(Message).
...

| ?- json_rpc::is_batch(Messages).
...

Field extraction

| ?- json_rpc::id(Message, Id).
...

| ?- json_rpc::method(Message, Method).
...

| ?- json_rpc::params(Message, Params).
...

| ?- json_rpc::result(Message, Result).
...

| ?- json_rpc::error_code(Message, Code).
...

| ?- json_rpc::error_message(Message, ErrorMessage).
...

| ?- json_rpc::error_data(Message, Data).
...

Stream I/O (client and server API)

Write and read newline-delimited JSON-RPC messages over streams:

| ?- json_rpc::write_message(Output, Message).
...

| ?- json_rpc::read_message(Input, Message).
...

These predicates can be used with any stream, including socket streams from the sockets library, to implement JSON-RPC clients and servers.

Content-Length framed I/O (LSP/MCP protocols)

Write and read JSON-RPC messages using Content-Length header framing as defined by the Language Server Protocol (LSP) and the Model Context Protocol (MCP). Each message is preceded by a Content-Length: N\r\n\r\n header where N is the byte length of the JSON body:

| ?- json_rpc::write_framed_message(Output, Message).
...

| ?- json_rpc::read_framed_message(Input, Message).
...

read_framed_message/2 fails at end of stream or if the header is missing or malformed.

API summary

Message construction

Predicates for building JSON-RPC 2.0 message terms. Requests include an id for matching responses; notifications do not.

  • request(+Method, +Params, +Id, --Request) - Construct a request

  • request(+Method, +Id, --Request) - Construct a request with no parameters

  • notification(+Method, +Params, --Notification) - Construct a notification

  • notification(+Method, --Notification) - Construct a notification with no parameters

  • response(+Result, +Id, --Response) - Construct a successful response

  • error_response(+Code, +Message, +Id, --ErrorResponse) - Construct an error response

  • error_response(+Code, +Message, +Data, +Id, --ErrorResponse) - Construct an error response with data

Standard error responses

Convenience predicates for the five standard JSON-RPC 2.0 error codes.

  • parse_error(--ErrorResponse) - Parse error (-32700)

  • invalid_request(--ErrorResponse) - Invalid request (-32600)

  • method_not_found(+Id, --ErrorResponse) - Method not found (-32601)

  • invalid_params(+Id, --ErrorResponse) - Invalid params (-32602)

  • internal_error(+Id, --ErrorResponse) - Internal error (-32603)

Encoding and decoding

Convert between JSON-RPC message terms and JSON atoms (strings).

  • encode(+Term, --JSON) - Encode a JSON-RPC term to a JSON atom

  • decode(+JSON, --Term) - Decode a JSON atom to a JSON-RPC term

Message classification

Test what kind of JSON-RPC message a term represents.

  • is_request(+Term) - Test if a term is a request

  • is_notification(+Term) - Test if a term is a notification

  • is_response(+Term) - Test if a term is a successful response

  • is_error_response(+Term) - Test if a term is an error response

  • is_batch(+Term) - Test if a term is a batch (non-empty list)

Field extraction

Extract individual fields from JSON-RPC message terms.

  • id(+Message, --Id) - Extract the id field

  • method(+Message, --Method) - Extract the method field

  • params(+Message, --Params) - Extract the params field

  • result(+Message, --Result) - Extract the result field

  • error(+Message, --Error) - Extract the error object

  • error_code(+Message, --Code) - Extract the error code

  • error_message(+Message, --ErrorMessage) - Extract the error message

  • error_data(+Message, --Data) - Extract the error data

Stream I/O

Read and write JSON-RPC messages over streams. The newline-delimited variants are suitable for socket-based communication. The Content-Length framed variants implement the header-based framing used by the Language Server Protocol (LSP) and the Model Context Protocol (MCP).

  • write_message(+Output, +Message) - Write a newline-delimited message

  • read_message(+Input, --Message) - Read a newline-delimited message

  • write_framed_message(+Output, +Message) - Write a message with Content-Length framing

  • read_framed_message(+Input, --Message) - Read a message with Content-Length framing