# Lsp Setup

> LSP-enable a Python, TypeScript, or Rust repository for fast-agent development. Use when creating or refreshing agent cards with LSP function tools, configuring ty, typescript-language-server, or rust-analyzer integration, or scoping repo-local code navigation safely.

- Skill: `fast-agent-ai/lsp-setup` (Agent Skill, multi-file: 7 files)
- Install (CLI): `npx skillmds@latest add fast-agent-ai/lsp-setup`
- Raw SKILL.md: https://api.skillmd.com/api/skills/fast-agent-ai/lsp-setup/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: fast-agent-ai (https://skillmd.com/u/fast-agent-ai)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/fast-agent-ai/lsp-setup

---


# LSP Setup

Enable LSP-based code navigation in a repository by creating an agent card with LSP function tools.

One helper module, `lsp_tools.py`, serves every language. It routes requests to the right
language server by file suffix and is configured declaratively via an optional `lsp.toml` —
no code edits required. It uses only the Python standard library.

## Prerequisites

Install the language server(s) for the languages present in the repo:

- **Python**: `ty` language server (`uv tool install ty`)
- **TypeScript**: `typescript-language-server` (`npm install -g typescript-language-server typescript`)
- **Rust**: `rust-analyzer` (`rustup component add rust-analyzer`)

## Setup Steps

### 1. Examine the Repository

Before copying files, inspect the repo root:

```bash
ls -d */
ls pyproject.toml tsconfig.json package.json Cargo.toml 2>/dev/null
```

Identify:

- **Languages**: Python (`pyproject.toml`), TypeScript (`tsconfig.json`), Rust (`Cargo.toml`).
  Mixed-language repos are fine — one `lsp_tools.py` handles all of them.
- **Source directories**: Common patterns are `src/`, `lib/`, `app/`, `tests/`, `packages/`, `apps/`, `crates/`, `examples/`, `benches/`
- **Root-level files you may want to query**: `setup.py`, `manage.py`, `conftest.py`, `build.rs`, etc.
- **Any existing `.fast-agent/` setup**

### 2. Create Directory Structure

**IMPORTANT** -- Use the `fast-agent environment directory` if specified. The default is `.fast-agent/`.

```bash
mkdir -p .fast-agent/agent-cards
```

### 3. Copy the helper module and configure it

Copy the shared helper (same file for every language):

- `assets/lsp_tools.py` → `.fast-agent/agent-cards/lsp_tools.py`

`lsp_tools.py` works with zero configuration: it auto-detects the repo root (walking up
from its own location for `.git`, `pyproject.toml`, `Cargo.toml`, ...) and allows queries
across the whole repository using the built-in servers.

To scope or customize it, copy the config template and edit it:

- `assets/lsp.toml` → `.fast-agent/lsp.toml`

```toml
# .fast-agent/lsp.toml — all keys optional
allow = ["src", "tests"]        # directories the LSP tools may query
allow_files = ["conftest.py"]   # individual root-level files

# [servers.python]              # per-language overrides; e.g. swap ty for pyright
# command = ["pyright-langserver", "--stdio"]
```

Recommended `allow` patterns:

- Standard Python: `["src", "tests", "test", "examples"]`
- Standard TypeScript: `["src"]`
- Rust: `["src", "crates", "tests", "examples", "benches"]` + `allow_files = ["build.rs"]`
- Monorepo: `["packages", "apps", "libs"]`
- Django: `["app", "apps", "tests"]` + `allow_files = ["manage.py"]`

Prefer narrow allowlists. Omit `allow` (whole-repo access) only when that tradeoff is worth it.

Set `root` in `lsp.toml` only when auto-detection would pick the wrong directory —
for Rust, prefer the Cargo workspace root, especially for `crates/*` layouts.

### 4. Create or update the card files

Do **not** blindly overwrite an existing `.fast-agent/agent-cards/dev.md`.

#### If `dev.md` does not exist yet

Create it from this skill's language-specific template (they differ only in which
project files they embed in the prompt):

- Python: `assets/python/dev.md` → `.fast-agent/agent-cards/dev.md`
- TypeScript: `assets/typescript/dev.md` → `.fast-agent/agent-cards/dev.md`
- Rust: `assets/rust/dev.md` → `.fast-agent/agent-cards/dev.md`

These starter templates default to `model: $system.default`. Only pin a model if the repo already has a good reason to do that.

#### If `dev.md` already exists

Edit it in place and preserve the existing card configuration.

Keep existing frontmatter values unless you have a specific reason to change them, especially:

- `model`
- `default`
- `type`
- `shell`
- existing hooks, servers, tools, and other card settings

Model handling is especially important:

- If the existing card already pins a specific `model`, keep it.
- If the existing card already uses `model: $system.default`, keep that too.
- If you are creating a new card from scratch, prefer `model: $system.default` unless the repo explicitly needs a pinned model.

Only add the LSP function tools that are missing (the same block for every language):

```yaml
function_tools:
  - lsp_tools.py:lsp_hover
  - lsp_tools.py:lsp_definition
  - lsp_tools.py:lsp_references
  - lsp_tools.py:lsp_document_symbols
  - lsp_tools.py:lsp_workspace_symbols
  - lsp_tools.py:lsp_diagnostics
  - lsp_tools.py:lsp_self_test
```

Do not remove unrelated instructions from the existing prompt body just to add LSP support.

**DO** Add a navigation hint to the card if appropriate.

```markdown
Use LSP tools for structural queries: definitions, references, symbols, hover info, diagnostics.
For broad text discovery or file operations, use whatever search tool or card is already available in this environment.
```

### 5. Verify Setup

First compile the copied helper:

```bash
uv run python -m py_compile .fast-agent/agent-cards/lsp_tools.py
```

Then run the helper self-test from the repo root. Pass a known source file to test one
language; with no argument it detects the repo's languages and smoke-tests each server.

```bash
uv run python .fast-agent/agent-cards/lsp_tools.py
uv run python .fast-agent/agent-cards/lsp_tools.py path/to/source-file
```

Each detected language should print `OK: <server> returned document symbols ...`.
If a language fails, fix the server install, `lsp.toml` `root`, or allowlist before using the card.

For Rust, verify the executable itself, not just its PATH entry (`lsp_tools.py` also
does this automatically at server start):

```bash
command -v rust-analyzer
rust-analyzer --version
```

Finally validate the card and try it interactively:

```bash
fast-agent check
fast-agent go
```

Try:

- `run the LSP self-test`
- `show me the symbols in src/main.py`
- `find the definition of Foo in src/foo.py at line 12`
- `show me the symbols in crates/my_crate/src/lib.rs`

Adjust the path to a real file in the repo.

## Troubleshooting

Run `fast-agent check` to diagnose issues.

- **"ty is not available on PATH"**: Install ty (`uv tool install ty`)
- **"typescript-language-server is not available"**: Install via npm. Note: snap-packaged installs are sandboxed and cannot read repos under `/tmp`.
- **"rust-analyzer is not available on PATH"** / **"found on PATH but is not installed correctly"**: Install it with `rustup component add rust-analyzer`
- **"Path must live under..."**: Update `allow` or `allow_files` in `lsp.toml`
- **"Path is outside the repository root"**: Set `root` in `lsp.toml` (relative to that file)
- **"No LSP server is configured for '.xyz' files"**: Add a `[servers.<name>]` entry to `lsp.toml`
- **LSP starts but results are poor**: Confirm the detected root has the right `pyproject.toml`, `tsconfig.json`, or Cargo workspace layout and dependencies; override `root` in `lsp.toml` if not

