moonbitstack/moonjrpc/peer does not have a README file

    Frames

    pub(open) trait Frames {
    async fn read(Self) -> String?
    async fn write(Self, String) -> Unit
    }

    How one message's text travels: a line, a WebSocket frame, an HTTP body. Implement this to carry JSON-RPC over anything.

    Peer

    type Peer

    One end of a conversation in which either side may call the other. Messages are taken in the order they arrive: a notice finishes before the next message is looked at, a call starts in its turn and runs on in a task of its own, and a reply wakes its caller in its turn. So the updates a side sends before answering are handled before its caller sees the answer.

    A notice handler that waits on Peer::call waits for a reply that cannot be looked at until the handler returns. Start a task for that instead.

    Peer::call

    async fn Peer::call(self : Peer, name : String, params? :
    Json
    , timeout_ms? : Int?) ->
    Json

    Send a call and wait for its answer. The other side's error object raises Failed; no answer in time raises TimedOut, and the side going away raises Closed. Telling the other side the call was given up on is for the protocol to do: MCP, ACP and LSP each have their own notice for it.

    Peer::new

    fn Peer::new(frames : &Frames, methods? :
    Methods
    , timeout_ms? : Int?, batch? : Bool) -> Peer

    timeout_ms=None waits as long as it takes. batch=false answers an array with -32600, for protocols that forbid batches.

    Peer::notify

    async fn Peer::notify(self : Peer, name : String, params? :
    Json
    ) -> Unit

    Send a notice. It raises Closed once the other side has gone away.

    Peer::run

    async fn Peer::run(self : Peer) -> Unit

    Read until the other side closes. Calls still running are waited for, so a client that writes its requests and closes its end still gets its answers; cancel this task to stop sooner.

    content_length

    fn content_length(reader : &
    Reader
    , writer : &
    Writer
    , limit? : Int) -> &Frames

    A Content-Length header, a blank line, the body: the base protocol of LSP. A message over limit bytes raises TooLong.

    limit

    let limit : Int

    The longest message lines and content_length take: 64 MiB. vscode-jsonrpc and the MCP SDKs set no bound, gRPC's default is 4 MiB; no common value exists, so this takes the safe side without refusing what a large tool result needs.

    lines

    fn lines(reader : &
    Reader
    , writer : &
    Writer
    , limit? : Int) -> &Frames

    One message to a line: the stdio transport of MCP and ACP. Blank lines are skipped, a last line with no newline still counts, and a line over limit bytes raises TooLong.

    timeout_ms

    let timeout_ms : Int

    How long Peer::call waits: 60 seconds, the MCP TypeScript SDK's DEFAULT_REQUEST_TIMEOUT_MSEC.

    Source Files