Skip to content

Feature: server-intiated requests/notifications #398

Open

Description

@idanarye

Sometimes it's useful for the server to initiate requests to the client. The server may even expect a response from the client. I think OpenRPC should offer a way to define these, so that client implementers can know what requests they are going to receive and how should they response, and so that code generators can generate stubs for handling these.

Activity

  1. winstxnhdw commented on Jul 10, 2025

    @winstxnhdw

    +1

    The Language Server Protocol has the following method that requires such handling. Currently, clients have to hack around this.

  2. zcstarr commented on Jul 27, 2025

    @zcstarr
    Member

    I'm curious what your'e thinking about here, technically json-rpc doesn't have a server or client, it leans towards bidirectional communication. In the 1.3x spec we support notifications that defining methods without a result.

    We're going to be adding support for notifications through out the toolset, soon. Is there something that would be useful that goes beyond not specifying a result on a method? Curious what the spec 1.3x > doesn't support here :)

  3. idanarye commented on Jul 27, 2025

    @idanarye
    Author

    This is not about the distinction between requests and notifications. This is about the distinction between client-initiated and server-initiated.

    Request Notification
    Client-initiated Client sends message, server responds Client sends message, receives no response
    Server-initiated Server sends message, client responds Server sends message, receives no responds

    technically json-rpc doesn't have a server or client, it leans towards bidirectional communication.

    Maybe I'm misunderstanding something, but this doesn't seem correct? Unless it's a p2p protocol1 there is always a client and a server. The client is the one initiating the initial connection while the server is the one offering the endpoint and - formally or informally - defining the schema.

    Footnotes

    1. And even then, one could argue that each node is both client and server. ↩

  4. zcstarr commented on Jul 27, 2025

    @zcstarr
    Member

    Sorry, I was a bit confusing there. I should have said doesn't specifically have to be a server or client. I was just referring to the fact that an entity can be both, unlike say in REST where one entity is the client and one is specifically the server.

    The Client is defined as the origin of Request objects and the handler of Response objects.
    The Server is defined as the origin of Response objects and the handler of Request objects.
    
    One implementation of this specification could easily fill both of those roles, even at the same time, to other different clients or the same client. This specification does not address that layer of complexity.
    

    from the 2.0 specification https://www.jsonrpc.org/specification

    sequenceDiagram
        participant Server
        participant Client
    
        Note over Server: init() — acting as client
        Server->>Client: init():request
    
        Note over Client: init() response — acting as server
        Client->>Server: init():response
    
    Loading

    And I think you're saying the issue is because the specification doesn't allow for you to mark methods as having a definite direction.

    Offhand my suggestion would be to define an extension, we recently implemented the tooling to be able to add x-* and have those be validated across methods.

    Here's an example repo that direciton I think should help explain how it would work essentially I think you could

    "methods": [
        {
          "name": "init",
          "summary": "Initialization method",
          "x-server-initiated": True,
          "params": [],
          "result": {
            "name": "result",
            "description": "Semver of Starknet's JSON-RPC spec being used",
            "required": true,
            "schema": {
              "title": "JSON-RPC spec version",
              "type": "string"
            }
          }
        },
    

    It would be cool to see the extension go up , we're trying to get more people into writing extensions, and have a little helper guide on how to get this going.

    Does this make sense. If enough people use and find the extension useful we'd work on making it an official part of the upcoming spec.

    https://github.com/open-rpc/tools/tree/main/packages/extensions

  5. fgoujeon commented on Aug 8, 2025

    @fgoujeon

    Such an extension would be very useful for my use case as well.

    However, this proposed x-server-initiated worries me regarding backward compatibility. Tools implementing the current version of the spec may expect all methods from methods to be client-initiated.

    Wouldn't it be safer to add something like x-server-initiated-methods (with type [Method Object | Reference Object]) at the same level as methods?

    Please tell me if I'm missing something.

  6. zcstarr commented on Aug 8, 2025

    @zcstarr
    Member

    I don't think it's a big deal right now, because consumers of the spec all internalize the server or client aspect of the spec currently. I think x-server-initiated tag would be ignored by anyone that is building against a spec that suddenly used it. By default x-extensions are optional.

    I can see how x-server-initiated-methods would make things like the .discover easier on implementers of .discover, because you wouldn't need to filter methods out by extension support.

    That said I think, that it is better to maybe define the feature flag on the method. If you define it on the method, then we already know that the method will be validate, and all the validation tools will continue to work , and you won't have to repeat any definitions or add additional schema work to validate.

    The second thing is, as we go down the extensions path way and more people use them, we can buff out schema utils to make convenience methods for filtering out top level components so as a consumer you could do something like
    filter({'x-server-initiated: true}, 'method') => [Method Object | Reference Object]` super fuzy on the implementation here but it makes it possible to make nice convenience methods because we know the type etc... already

    We wouldn't need to cross validate or redefine MethodObject or reuse those types in those areas, there'd be a single location where methods are defined.

    I think maybe there's a general pattern here of being able, to if an extension belongs to a specific spec object type then apply it locally. If an extension applies to a document as a whole apply it globally. I think this will have the overall effect of making specifications and validations simpler and require fewer interdependent parts.

    Does this track with you're thinking or would this block you from achieving your aim?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions