title: Creating LSP (Language Server Protocol) for multiple clients using RPC
body: <p>I am trying to create a custom LSP.
  My goal is to create one language server for both monaco editor (on web) and vscode extension.</p>
  <p>Currently I use Node/IPC to connect the vscode-extension with the server.
  and ws-jsonrpc to connect monaco editor with the server.</p>
  <p>quoting from this article <a href="https://blog.logrocket.com/how-to-use-the-language-server-protocol-to-extending-a-client-764da0e7863c/" rel="nofollow noreferrer">Extending a client with the language server protocol</a>
  :</p>
  <blockquote>
  <p>There are multiple ways to use JSON-RPC, but you see these two ways in
  most implementations:</p>
  <ul>
  <li>Communication is done via the standard input / output, i.e., the command line interface</li>
  <li>Communication is performed via TCP/IP, i.e., network messages similar to HTTP</li>
  </ul>
  </blockquote>
  <p>I should be able to use JSON-RPC for both communication (internal communication between processes which is the vscode-extesion in my case , and external communication which is monaco-editor in my case)</p>
  <p>Here is how I am launching the server for the moment:</p>
  <p>For IPC communication:</p>
  <pre><code>const languageServer = new LanguageServer(createConnection(ProposedFeatures.all));
  languageServer.start();
  </code></pre>
  <p>For WebSocket RPC:</p>
  <pre><code>import * as express from &quot;express&quot;;
  import * as ws from &quot;ws&quot;;
  
  import * as rpc from &quot;vscode-ws-jsonrpc&quot;;
  import * as url from &quot;url&quot;;
  import * as http from &quot;http&quot;;
  import * as net from &quot;net&quot;;
  
  const app = express();
  const server = app.listen(3000);
  const wss = new ws.Server({
      noServer: true,
      perMessageDeflate: false
  });
  
  function launch(socket : rpc.IWebSocket ){
      const reader = new rpc.WebSocketMessageReader(socket);
      const writer = new rpc.WebSocketMessageWriter(socket);
      const languageServer = new LanguageServer(createConnection(reader, writer));
      languageServer.start();
      
  }
  server.on('upgrade', (request: http.IncomingMessage, socket: net.Socket, head: Buffer) =&gt; {
      const pathname = request.url ? url.parse(request.url).pathname : undefined;
      console.log(&quot;server on upgrade &quot;, pathname);
  
      if (pathname === '/sampleServer') {
          wss.handleUpgrade(request, socket, head, (webSocket: any) =&gt; {
  
              const socket: rpc.IWebSocket = {
                  send: (content: any) =&gt; webSocket.send(content, (error: any) =&gt; {
                      if (error) {
                          throw error;
                      }
                  }),
                  onMessage: (cb: any) =&gt; webSocket.on('message', cb),
                  onError: (cb: any) =&gt; webSocket.on('error', cb),
                  onClose: (cb: any) =&gt; webSocket.on('close', cb),
                  dispose: () =&gt; webSocket.close()
              };
              // launch the server when the web socket is opened
              if (webSocket.readyState === webSocket.OPEN) {
                  launch(socket); 
              } else {
                  webSocket.on('open', () =&gt; {
                      launch(socket); 
                  });
              }
          });
      }
  })
  </code></pre>