python-language-server (pyls): the Palantir LSP implementation, and what it still pins you to
An implementation of the Language Server Protocol for Python
At a glance
- What is it?
- Palantir's python-language-server, usually called pyls, is the Jedi-backed Language Server Protocol implementation that editors like Neovim and VS Code can drive over JSON-RPC. It is MIT licensed, its last release was 0.36.2 in December 2020, and its dependency pins tell you more about its age than any changelog does.
- Who is it for?
- Adopt python-language-server if you need a small, MIT-licensed LSP server you can pip install and point an existing client at, and you accept that the latest release is 0.36.2 from 2020-12-11 with jedi pinned below 0.18.0. Do not adopt it if you need features that arrived in newer Jedi versions, since the setup.py pin blocks them, or if you want a server whose release cadence tracks current Python tooling.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 86 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 24, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What pyls solves, and which editors it is for
An editor that wants to offer completions, go-to-definition, hover text, references, signature help, document symbols and formatting for Python has to do the parsing itself, or delegate. pyls delegates. It implements the Language Server Protocol, so any client that speaks LSP can get Python intelligence without embedding a Python parser. The README lists exactly that feature set and shows it in GIFs for auto completion, linting with pycodestyle and pyflakes, signature help, go to definition, hover, find references, document symbols and document formatting.
The target user is not someone choosing an IDE. It is someone who already has an editor and needs a server behind it, or a maintainer wiring Python support into a client. The repository ships a vscode-client/ directory, which is the project's own example of that wiring, and the README points at vscode-client/package.json as the full set of supported configuration options. That file, not the README, is the real configuration reference. Treat the README as an orientation page and the client manifest as the contract.
Jedi does the analysis; pluggy and JSON-RPC do the rest
The base install depends on Jedi for completions, definitions, hover, references, signature help and symbols. That is the whole analysis engine. Everything else is optional and discovered at runtime: if Rope is present it can provide completions and renaming, Pyflakes and McCabe and pycodestyle and pydocstyle act as linters, and autopep8 or YAPF handle formatting, with YAPF preferred over autopep8 when both are installed. The mechanism is plugin discovery through pluggy, which is why third-party packages such as pyls-mypy, pyls-isort and pyls-black can add functionality without patching the server.
Transport is python-jsonrpc-server, a separate package in install_requires. The server does not open a socket by itself; the client launches it and speaks JSON-RPC over the pipe the client chooses. That is why there is no port or URL in this project's documentation. Configuration arrives in layers, and the README is explicit about the order: user configuration in the home directory first, overridden by configuration passed in by the language client, and then overridden by configuration discovered in the workspace. Workspace configuration is read from pycodestyle locations (~/.config/pycodestyle, setup.cfg, tox.ini, pycodestyle.cfg) or flake8 locations (~/.config/flake8, setup.cfg, tox.ini, flake8.cfg). The default source is pycodestyle; setting pyls.configurationSources to ['flake8'] switches it. That layering is the part most people get wrong, because a setup.cfg in the repository silently wins over what they set in the editor.
Installing python-language-server and running a first real use
The base install is one pip command, and it pulls Jedi plus the JSON-RPC server. The README notes that if pip complains with 'install_requires' must be a string or list of strings, setuptools is too old and should be upgraded first.
pip install python-language-server
pip install -U setuptoolsOptional providers are opt-in through extras. To get YAPF formatting, the README gives this exact form:
pip install 'python-language-server[yapf]'And to pull every optional provider at once:
pip install 'python-language-server[all]'After installation, the server is a command your editor launches, not a daemon you start and visit. The project's own development instructions show the intended loop against VS Code: install the client extension, then run VS Code configured to use pyls, with the wiring described at the bottom of vscode-client/src/extension.ts. Debug output appears under View -> Output, with pyls in the dropdown, and Cmd + r refreshes the window.
virtualenv env
. env/bin/activate
pip install .
cd vscode-client
yarn install
yarn run vscode -- $PWD/../Configuration is passed by the client. To turn on docstring linting, the README gives this setting:
"pyls.plugins.pydocstyle.enabled": truepydocstyle is disabled by default, so without that key you will see no docstring diagnostics regardless of what is installed.
The dependency pins are the real limitation
setup.py pins jedi>=0.17.2,<0.18.0. That upper bound is the single most consequential line in the repository. It means the server is built against the 0.17 series of Jedi and will not accept a 0.18 install, so anything that changed in Jedi's later API is unavailable here regardless of what you install alongside it. If your environment already resolves Jedi to a newer version for another tool, you have a conflict to manage rather than a configuration to change.
The release history reinforces the point. The most recent release listed is 0.36.2, published on 2020-12-11, preceded by 0.36.1 on 2020-11-08 and 0.36.0 on 2020-11-03. The repository is not archived and the last push was on 2026-07-06, so the codebase is not frozen, but there is a long gap between the release tags and that push. Do not read commit activity as a statement about the published artifact. If you install from PyPI you get the 2020 release; if you install from the develop branch you get something the project has not tagged.
The second limitation is coverage. Everything analytical routes through Jedi and the optional linters, so there is no type checker in the base install. Mypy support exists only as the separate pyls-mypy plugin, and the README points at that repository for how to write plugins rather than documenting the plugin's behaviour itself. If you need type checking out of the box, this is the wrong tool as shipped.
Alternatives: what changes when you leave pyls
The obvious comparison is python-lsp-server, the community fork that continues the same design. The difference is not conceptual, since both implement LSP for Python over a client-launched process, but in maintenance and dependency posture: a fork exists precisely because the upstream project's release cadence stalled at 0.36.2, and it is free to move its Jedi pin forward while pyls cannot without a new release. If your reason for looking at pyls is 'I want an MIT-licensed, pip-installable Python LSP server', the fork answers the same question with a different release history, and that history is the deciding factor.
The other direction is a bundled client. Editors that ship their own Python intelligence do not need pyls at all, and the trade-off is the opposite one: you get a tighter integration without managing a separate server process, and you give up the ability to swap the analysis engine or run the same server across several editors. That matters if you use more than one client, because a single pyls install configured once can serve them all, whereas bundled intelligence is configured per editor.
Within the pyls ecosystem itself, the alternative to installing extras is not installing them. Running the base package gives you Jedi-backed navigation and nothing else; adding [all] gives you linting and formatting from five separate tools. Those are genuinely different products in daily use, and the extras list is the switch.
Maintenance cost, upgrading, and the MIT licence
Upgrading pyls means upgrading a package whose newest release is 0.36.2 from 2020-12-11. The repository is not archived and the last push was on 2026-07-06, so changes exist in the tree, but the README documents no upgrade procedure, no deprecation policy and no migration notes between 0.36.x versions. RELEASE.md exists at the top level, so there is a release process, but the README does not describe what changes when you move between releases. Plan on reading commit history rather than release notes.
The practical cost is dependency management. The jedi<0.18.0 pin and the python-jsonrpc-server>=0.4.0 requirement both constrain what else can live in the same environment. If you install pyls into a project virtualenv rather than a dedicated one, those constraints apply to the project too. A dedicated environment for the server avoids that entirely, and the project's own development instructions already use a virtualenv, which is a reasonable default to copy.
The licence is MIT, stated in the README and present as a LICENSE file at the repository root. MIT is permissive: it allows use, modification and redistribution with the copyright notice and permission notice retained. That is a statement about the licence text, not legal advice, and it says nothing about the licences of Jedi, Rope, Pyflakes, McCabe, pycodestyle, pydocstyle, autopep8, YAPF or the third-party plugins, each of which carries its own terms. If you redistribute a bundle that includes optional providers, check those separately.
Editorial conclusion
Adopt python-language-server if you need a small, MIT-licensed LSP server you can pip install and point an existing client at, and you accept that the latest release is 0.36.2 from 2020-12-11 with jedi pinned below 0.18.0. Do not adopt it if you need features that arrived in newer Jedi versions, since the setup.py pin blocks them, or if you want a server whose release cadence tracks current Python tooling. Before committing, verify that your client can pass pyls.configurationSources and the pyls.plugins.* settings, then install with the extras you actually need and confirm the optional providers load.
Frequently asked questions
What is python-language-server (pyls)?
It is Palantir's implementation of the Language Server Protocol for Python, described in the README as a Python 2.7 and 3.5+ implementation. The base install uses Jedi to provide completions, definitions, hover, references, signature help and symbols.
How do I install python-language-server?
The README gives pip install python-language-server for the base install, which requires Jedi. Optional providers are added with the extras syntax, for example pip install 'python-language-server[yapf]' or pip install 'python-language-server[all]'.
How do I restart the python-language-server in my editor?
The README does not document restarting the server. Its development section covers refreshing Visual Studio Code with Cmd + r, which reloads the window rather than restarting pyls specifically.
What is the best language server for Python?
The README makes no such ranking. It shows that pyls is one option: an MIT-licensed LSP implementation whose base install relies on Jedi, with linters and formatters available as optional extras.
How do I install python-language-server for Neovim?
The README gives no Neovim instructions. It documents pip installation of the server and a VS Code development client under vscode-client/, and it states that configuration is passed in by the language client, so a Neovim setup would depend on that client's own configuration mechanism.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/palantir-python-language-server)