Configuring a custom local language server

Hi Community,

I’m migrating the code analysis part of a VS Code extension into an LSP, and I’m trying to test it out with Jupyter Lab as well.

The LSP itself is not a separate npm package for now, but lives as a separate server module inside the VS Code extension’s repository. So, what I’m trying to do is point the Jupyter Lab LSP configuration to execute my compiled server.js at a dedicated location on my file system.

I’m on a Windows 10 system, I have jupyterlab-lsp installed, and I’ve tried the following configuration but the language server doesn’t seem to spin up.

Based on Configuring backend — Language Server Protocol integration for Jupyter[Lab] I added a new file in c:\Users\<username>\AppData\Local\Programs\Python\Python311\etc\jupyter\jupyter_server_config.d\ called codiga_language_server.json with the following content:

{
  "LanguageServerManager": {
    "language_servers": {
      "codiga_language_server": {
        "version": 2,
        "argv": ["node", "d:\\vscode-plugin\\server\\out\\server.js", "--node-ipc"],
        "languages": ["python"],
        "mime_types": ["text/python"],
        "display_name": "Codiga Language Server"
      }
    }
  }
}

My understanding of argv is that it should assemble a shell/cmd command that would invoke the server. Although, I’m confused about that because the few examples I’ve seen seem different from what I understand based on the documentation.

Then, I added the following in Settings > Advanced Settings Editor > Language Server > User Preferences based on https://github.com/jupyter-lsp/jupyterlab-lsp:

{
  "language_servers": {
      "codiga_language_server": {
          "serverSettings": {
          }
      }
  }
}

I don’t see any log message from Jupyter that it has picked up my LSP configuration (though I don’t know if there supposed to be any such message), and I have into-file logging in my LSP, that doesn’t even create the log file.

I’d appreciate some pointers on this, because I’m not sure if I’m missing any other configuration, or what have I possibly misconfigured. Thank you in advance.

PS: I’m new to Jupyter Lab, so any detail is useful.

I, meanwhile, was able to figure out the problem and launch the server (although still have some problems with it). It might be useful for others.

  1. Missing package dependency

Since the LSP’s source repo has three package.json files (in root, client, server), I had a missing dependency in the server module which I took for granted because running the server from VS Code, it was available from the root package.json and node_modules.

I was able to figure this out because I was trying the server in Sublime Text as well, and I bumped into its LSP: Toggle Log Panel command which displayed errors from the Node execution.

I’m sure this could have been troubleshot with Jupyter as well, but it was by chance that I found that command.

  1. –node-ipc instead of --stdio

I was trying to launch the server with the --stdio flag in argv, which actually did launch, but I got errors like the ones below, so I decided to give --node-ipc a try, which solved it for me:

d:\vscode-plugin\server\node_modules\vscode-jsonrpc\lib\common\connection.js:531
                        responsePromise.reject(new messages_1.ResponseError(error.code, error.message, error.data));
                                               ^

ResponseError: Unhandled method workspace/workspaceFolders
    at handleResponse (d:\vscode-plugin\server\node_modules\vscode-jsonrpc\lib\common\connection.js:531:48)
    at processMessageQueue (d:\vscode-plugin\server\node_modules\vscode-jsonrpc\lib\common\connection.js:327:17)
    at Immediate.<anonymous> (d:\vscode-plugin\server\node_modules\vscode-jsonrpc\lib\common\connection.js:311:13)
    at processImmediate (node:internal/timers:466:21) {
  code: -32601,
  data: undefined
}
[E 2023-02-15 15:06:47.168 ServerApp] <LspStdIoWriter(parent=<LanguageServerSession(language_server=codiga_language_server, argv=['node', 'd:\\vscode-plugin\\server\\out\\server.js', '--stdio'])>)> couldn't write message:
 Content-Length: 585

    {"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"file:///<absolute path to source file>","version":3},"contentChanges":[{"text":"<text of the source file>"}]}}
    Traceback (most recent call last):
      File "C:\Users\<username>\AppData\Local\Programs\Python\Python311\Lib\site-packages\jupyter_lsp\stdio.py", line 193, in write
        await convert_yielded(self._write_one(response.encode("utf-8")))
      File "C:\Users\<username>\AppData\Local\Programs\Python\Python311\Lib\concurrent\futures\thread.py", line 58, in run
        result = self.fn(*self.args, **self.kwargs)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      File "C:\Users\<username>\AppData\Local\Programs\Python\Python311\Lib\site-packages\jupyter_lsp\stdio.py", line 201, in _write_one
        self.stream.write(message)
    OSError: [Errno 22] Invalid argument

Little bit of correction:

--node-ipc doesn’t seem to be supported by Jupyter Lab, instead I had to use --stdio. Using --node-ipc, my server.js was called, but the server connection itself was not established.

Also, the Unhandled method workspace/workspaceFolders error refers to that fact that Jupyter Lab, apparently, doesn’t have support for multiple workspace folders, so I have to handle the single project root folder differently.