.. _library_json_rpc:

``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 <../../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-20-messages:

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-1:

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-1:

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-1:

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
