claude-pyls
A lightweight Python LSP MCP server + grep-intercept hook for Claude Code. Gives Claude token-efficient symbol navigation in any Python project.
Why
When Claude Code searches for a Python symbol using Grep, it reads large swaths of source into context. A targeted LSP lookup costs a fraction of that.
Measured savings (Haiku, claude -p, 400-file project):
| Metric | Without (Grep) | With (pyls) | Savings |
|---|---|---|---|
| Cost | $0.0586 | $0.0119 | 80% cheaper |
| Cache creation tokens | 39,124 | 2,953 | 92% less |
| Duration | 10.6s | 5.7s | 46% faster |
Modes
Small (single-repo, zero-startup)
Regex scan over class/def lines. Starts in 0.2s (raw JSON-RPC, no MCP SDK). Optionally enhances with jedi for precise goto/references. Ideal for per-project activation.
Big (environment-wide, daemon)
A persistent LSP daemon that starts on boot and serves an entire Python environment. Longer startup, higher accuracy, multi-repo awareness. Good for large monorepos or shared dev environments. (Planned — not yet implemented.)
Install
pip install claude-pyls # small mode (regex scan)
pip install claude-pyls[lsp] # + jedi for enhanced accuracy
Quick start
# Scaffold .mcp.json + hook into your project
claude-pyls setup
# Or manually add to .mcp.json:
# {"mcpServers": {"pyls": {"command": "claude-pyls", "args": ["serve"]}}}
Tools exposed
| Tool | Description |
|---|---|
find_definition |
File + line where a symbol is defined |
find_references |
All sites where a symbol is used |
find_symbols |
All definitions matching a name pattern |
Known limitations
- Textual scan only (small mode) — won't resolve dynamic attributes, decorated names, or re-exports
- jedi (when enabled) is lazy-loaded on first call (~3–4s first call, fast after)
- File cache is not invalidated mid-session — restart the server after large refactors
- Hook catches bare symbol names (PascalCase, camelCase, snake_case 2+ segments) — prefixed patterns pass through
Releasing
Publishing is manual for now (no CI/CD). The PyPI API token lives in a local .env file (gitignored) in the format pypi=pypi-....
# one-time: install hatch into the dev venv
pip install hatch
# build wheel + sdist
hatch build
# publish — reads the token out of .env WITHOUT exporting every line
# of .env into your shell (avoids leaking unrelated vars). Never commit .env.
HATCH_INDEX_USER=__token__ \
HATCH_INDEX_AUTH="$(grep '^pypi=' .env | cut -d= -f2-)" \
hatch publish
# tag the release (replace X.Y.Z with the version you just bumped
# in src/claude_pyls/__init__.py and pyproject.toml — see below)
git tag vX.Y.Z && git push origin vX.Y.Z
Version bump procedure
Before each release, bump the version in both locations (they must stay in sync):
src/claude_pyls/__init__.py—__version__ = "x.y.z"pyproject.toml—version = "x.y.z"
Then commit, build, publish, and tag as shown above.
License
MIT
Metadata
Release files for claude-pyls 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| claude_pyls-0.1.0.tar.gz | 13.8 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| claude_pyls-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 26.5 kB
Release files / claude_pyls-0.1.0.tar.gz
| Download URL | claude_pyls-0.1.0.tar.gz |
|---|---|
| Size | 13.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
12b83d1ea2e9af9aeb4edd61da1cd152b6f9b459f6b4f1f1a6de97dcd1af65f8
|
|
BLAKE2b-256 checksum How to use checksums |
56bc5cc06562b52339869a896284e670c947786acd4efe24b73add62cee09cf5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
Hatch/1.16.5 cpython/3.12.13 HTTPX/0.28.1
|
Release files / claude_pyls-0.1.0-py3-none-any.whl
| Download URL | claude_pyls-0.1.0-py3-none-any.whl |
|---|---|
| Size | 12.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e8138f4a368be68406c01f96d63b74b556595097f47608c71a61e5c4e2ec4b33
|
|
BLAKE2b-256 checksum How to use checksums |
6b761732e6ae299e45f67d1297607f1b312ca82482376e46e26906b6f23cdba3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
Hatch/1.16.5 cpython/3.12.13 HTTPX/0.28.1
|
Security for claude-pyls 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.