Skip to main content
Glama
README.md
# agy-lsp — Language Server Protocol MCP Bridge for Antigravity CLI

[![Version](https://img.shields.io/badge/version-1.2.0-purple.svg)](#13-development-testing--qa)
[![Tests](https://img.shields.io/badge/tests-47%20passed-brightgreen.svg)](#13-development-testing--qa)
[![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
[![Platform](https://img.shields.io/badge/platform-Windows%20%7C%20Linux%20%7C%20macOS-blue.svg)](#13-development-testing--qa)
[![MCP](https://img.shields.io/badge/MCP-2.0%20%2F%201.0-orange.svg)](https://modelcontextprotocol.io)
[![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)

*Read this in other languages: [English](README.md) | [Deutsch](README.de.md)*

**agy-lsp** is a production-ready, professional plugin for the **Google Antigravity CLI (`agy`)**. It connects AI coding agents to native **Language Servers (LSP)** for C#, C/C++, TypeScript/JavaScript, Python, Rust, and Go via the standardized **Model Context Protocol (MCP)**.

> **Companion Plugin:** Pair `agy-lsp` (static semantic navigation & diagnostics) with [**agy-dap**](https://github.com/k0pfnicker/agy-dap) (hypothesis-driven runtime debugging via DAP).

---

## Table of Contents

1. [Purpose & Benefits](#1-purpose--benefits)
   - [Empirical Benchmarks & Evaluation Results](#empirical-benchmarks--evaluation-results)
2. [Architecture](#2-architecture)
3. [MCP Tools Overview](#3-mcp-tools-overview)
4. [Supported Languages & Language Servers](#4-supported-languages--language-servers)
5. [Prerequisites](#5-prerequisites)
6. [Installation & Quickstart](#6-installation--quickstart)
   - [Windows](#windows-powershell)
   - [Linux / macOS](#linux--macos)
7. [Integration into Antigravity CLI](#7-integration-into-antigravity-cli)
8. [Language Server Installation](#8-language-server-installation)
9. [Configuration (`agy-lsp.json`)](#9-configuration-agy-lspjson)
10. [Token Efficiency & Context Optimization](#10-token-efficiency--context-optimization)
11. [Security Model](#11-security-model)
12. [Troubleshooting & Diagnostics](#12-troubleshooting--diagnostics)
13. [Development, Testing & QA](#13-development-testing--qa)
14. [Adding New Languages](#14-adding-new-languages)
15. [Known Limitations](#15-known-limitations)
16. [License](#16-license)

---

## 1. Purpose & Benefits

Large Language Models (LLMs) often face two major challenges when working in real-world software codebases:
1. **Inaccurate Search & Context Waste:** Plaintext keyword search and reading entire files consumes thousands of context tokens while frequently missing semantic relationships (such as method overloads, polymorphism, interface implementations, and namespaces).
2. **Missing Feedback Loops:** After modifying code, agents often fail to notice syntax, type-checking, or import errors until much later or not at all.

**agy-lsp** bridges this gap by giving the Antigravity agent direct compiler and type intelligence via standardized MCP tools:
- **Precise Symbol Navigation:** Jump to definitions and query all workspace references without guessing.
- **Automated Quality Control:** Fetch compiler diagnostics (errors, warnings, hints) immediately after edits.
- **Safe Refactoring:** Symbol renaming generates a unified preview diff before any changes are written to disk.
- **Minimized Token Usage:** Compact snippets, structural document outlines, and strict result limits prevent context bloat.

### Empirical Benchmarks & Evaluation Results

All claims below are continuously verified by our automated benchmark and E2E test suite ([`tests/test_benchmarks_and_value.py`](tests/test_benchmarks_and_value.py) and [`tests/test_e2e_real_lsp.py`](tests/test_e2e_real_lsp.py)) against real `clangd` (C/C++) and `pylsp` (Python) language server processes:

| Evaluation Scenario | Without `agy-lsp` (Grep / File Read / Raw LSP) | With `agy-lsp` (Smart MCP Bridge) | Measured Improvement |
| :--- | :--- | :--- | :--- |
| **1. Structural File Outline (`document_symbols`)**<br>*C header with 3 structs/enums (65 fields) & 4 functions* | **18,979 bytes** (`~4,745 tokens`) raw LSP JSON<br>**8,155 bytes** (`~2,039 tokens`) with uncollapsed fields | **1,647 bytes** (`~412 tokens`)<br>Collapses leaf struct/enum fields into `fields_count` | **-91.3% tokens** vs. Raw LSP<br>**-79.8% tokens** vs. Expanded |
| **2. Inaccurate LLM Column Estimates (`go_to_definition`)**<br>*10 imprecise calls: col 1 indentation, keywords (`int`, `const`), EOL, ±1 line* | **0 / 10 resolved (0% hit rate)**<br>Raw LSP fails when column lands on whitespace or keywords | **10 / 10 resolved (100% hit rate)**<br>Auto-snaps to identifier & supports `symbol_name` ±2 lines | **0% → 100% resolution rate** without LLM retry loops |
| **3. Semantic Navigation vs. Text Grep (`find_references` & `go_to_definition`)**<br>*Searching `execute_step` across C codebase with comments & string traps* | **8 grep matches (5 false positives = 62.5% noise)**<br>Requires reading full files (**3,975 bytes / ~994 tokens**) | **3 AST-verified references (0% false positives)**<br>Definition + 3-line snippet in **449 bytes (~112 tokens)** | **100% precision** (0 false positives)<br>**-88.7% context tokens** |
| **4. Real-Time Compiler Feedback & Cascade Filtering (`get_diagnostics`)**<br>*Detecting C type/identifier errors & filtering a 120-error template cascade* | No immediate feedback without full build;<br>Raw cascade: **145,680 bytes (~36,420 tokens)** | **2 errors detected in ~198 ms** via event-driven `didOpen`;<br>Deduplicated & capped: **27,912 bytes (~6,978 tokens)** | **< 200 ms** instant feedback<br>**-80.8% diagnostic noise** |
| **5. Safe Cross-File Refactoring (`rename_symbol`)**<br>*Renaming `execute_step` → `dispatch_op` across `engine.h` & `engine.c`* | Regex search/replace corrupts string literals (`"execute_step"`) and comments directly on disk | **2 files diffed (`applied: false` preview mode)**<br>Updates prototype, definition & call sites; strings/comments untouched | **Zero disk corruption**<br>100% AST-safe unified diff |
| **6. Zero-Read Call Graph Analysis (`call_hierarchy`)**<br>*Tracing callers & callees of `execute_step`* | Requires multiple `grep` passes and reading every candidate caller file | Single tool call returns incoming (`run_program`) & outgoing (`clamp_register`) calls directly from AST | **1 tool call** instead of multi-file inspection |

#### Why These Results Matter for AI Agents

1. **Massive Context Window Preservation (-80% to -91% Tokens):** In C/C++ and C# projects, headers and classes often contain dozens of struct fields or enum constants. Raw LSP dumps flood the LLM context window with thousands of lines of JSON coordinates. `agy-lsp` collapses leaf fields into `"fields_count": 34` by default while keeping every struct, class, enum, and function signature intact.
2. **Elimination of "Off-by-A-Few-Columns" Tool Failures (0% → 100% Hit Rate):** LLMs do not count 1-indexed character columns reliably—they frequently pass `character=1` (leading indentation) or land on return-type keywords (`static`, `int`, `const`, `def`). Standard LSP bridges return `null` on these positions, forcing the agent into expensive retry loops. `agy-lsp` automatically snaps to the nearest non-keyword identifier on the line (or matches `symbol_name` within ±2 lines) and retries alternative identifiers on the line if needed.
3. **Zero False Positives in Navigation & Refactoring:** Unlike `grep`/`ripgrep`, which matched **62.5% false positives** in comments and string literals in our benchmark, `agy-lsp` queries the compiler's AST (`clangd` / `pylsp` / `pyright` / `csharp-ls` / `tsserver`). When renaming symbols, string literals and comments are never accidentally modified, and changes are returned as a safe unified diff preview first.
4. **Sub-200ms Compiler Verification Without Running Full Builds:** Using event-driven `textDocument/publishDiagnostics` synchronization (`asyncio.Event`), the agent receives exact compiler errors (e.g., `"Use of undeclared identifier"`, `"Too many arguments to function call"`) within ~200 ms of opening or editing a file.

---

## 2. Architecture

```text
┌─────────────────────────────────────────────────────────────┐
│                    Antigravity CLI (agy)                    │
│                                                             │
│   Agent Turn / Reasoning ◄──► Skills / AGENTS.md Rules      │
└─────────────────────────────┬───────────────────────────────┘
                              │
                              │ Stdio Transport (JSON-RPC)
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                  agy-lsp (MCP-Server)                       │
│                                                             │
│  ├── Tool Schemas (get_diagnostics, go_to_definition, ...)  │
│  ├── Document Sync (didOpen, didChange, didClose, Cache)    │
│  ├── Token Reducer (Snippet extraction, Dedup, Limits)      │
│  └── Workspace Confinement Security Check                   │
└─────────────────────────────┬───────────────────────────────┘
                              │
                              │ Async Process I/O (Content-Length Framing)
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                   Language Server (LSP)                     │
│                                                             │
│   [Python]       [C#]             [C / C++]      [TS / JS]  │
│   pyright /      csharp-ls /      clangd         typescript-│
│   pylsp          Roslyn Server                   language-  │
│                                                  server     │
└─────────────────────────────────────────────────────────────┘
```

The bridge launches Language Server processes **on demand (lazy loading)** only when a tool targets a file belonging to that language. Running processes are reused throughout the session and automatically recovered with bounded retries if a crash occurs.

---

## 3. MCP Tools Overview

The plugin registers 11 high-performance MCP tools:

| Tool | Purpose | Key Parameters | Return Value |
| :--- | :--- | :--- | :--- |
| `get_diagnostics` | Retrieve compiler errors, warnings, and hints for a file or workspace | `file_path`, `line_start`, `line_end`, `severity`, `limit` | List of deduplicated diagnostics with file, line, column, code, and message. |
| `go_to_definition` | Jump from a symbol position to its definition/declaration | `file_path`, `line`, `character`, `symbol_name`, `include_snippet` | Target file, line range, and optional compact code excerpt. |
| `find_references` | Locate all usages of a symbol across the workspace | `file_path`, `line`, `character`, `symbol_name`, `include_declaration`, `limit` | List of reference locations across files. |
| `rename_symbol` | Perform workspace-wide LSP rename refactoring | `file_path`, `line`, `character`, `new_name`, `apply`, `symbol_name` | **Unified preview diff** across all affected files. Disk writes require `apply=True` and `writeChanges=True`. |
| `document_symbols` | Structural outline of classes, methods, and properties | `file_path`, `query`, `include_fields`, `max_depth` | Symbol tree with kind, line ranges, and identifiers (struct fields/enum members collapsed into `fields_count` by default). |
| `workspace_symbols` | Search symbols across the entire project | `query`, `limit` | Matches with symbol name, kind, file, and position. |
| `hover` | Inspect signatures, types, and docstrings | `file_path`, `line`, `character`, `symbol_name` | Markdown-formatted hover information. |
| `prepare_call_hierarchy` | Verify support and return call hierarchy root item | `file_path`, `line`, `character`, `symbol_name` | Prepared symbol item for call graphs. |
| `call_hierarchy` | Find callers (`incoming`) or called functions (`outgoing`) | `file_path`, `line`, `character`, `direction`, `symbol_name` | List of callers or callee functions. |
| `get_type_hierarchy` | Inspect base types (`supertypes`) or derived classes (`subtypes`) | `file_path`, `line`, `character`, `direction`, `symbol_name` | Type inheritance hierarchy. |
| `lsp_status` | Health status of all servers, workspace root, and errors | *none* | JSON overview of server states (`RUNNING`, `AVAILABLE`, `NOT_INSTALLED`, `CRASHED`), PID, and root. |

*Note:* All line and column arguments and outputs are **1-indexed** for agent ergonomics. Position-based tools also automatically snap inaccurate column estimates (`character`) or optional `symbol_name` arguments to the identifier on that line.

---

## 4. Supported Languages & Language Servers

| Language | Primary Server | File Extensions | Project Discovery Markers |
| :--- | :--- | :--- | :--- |
| **Python** | `pyright-langserver` *(Fallbacks: `basedpyright-langserver`, `pylsp`, `pyright`)* | `.py`, `.pyi` | `pyproject.toml`, `setup.py`, `requirements.txt` |
| **C#** | `csharp-ls` *(Fallback: `roslyn-language-server`)* | `.cs` | `*.sln`, `*.slnx`, `*.csproj` |
| **C / C++** | `clangd` *(Fallback: `ccls`)* | `.c`, `.cpp`, `.cc`, `.cxx`, `.h`, `.hpp`, `.hxx` | `CMakeLists.txt`, `compile_commands.json`, `*.vcxproj` |
| **TypeScript / JS**| `typescript-language-server` *(Fallback: `vtsls`)* | `.ts`, `.tsx`, `.js`, `.jsx`, `.mjs`, `.cjs` | `package.json`, `tsconfig.json` |
| **Rust** | `rust-analyzer` | `.rs` | `Cargo.toml` |
| **Go** | `gopls` | `.go` | `go.mod` |

---

## 5. Prerequisites

- **Operating System:** Windows 10/11, macOS, or Linux.
- **Python:** Python 3.9 or higher (Python 3.14+ fully supported).
- **Antigravity CLI:** `agy` installed.
- The corresponding language server for the language you wish to inspect (e.g. `pylsp` or `pyright` for Python, `clangd` for C++, etc.).

---

## 6. Installation & Quickstart

### Windows (PowerShell)

```powershell
# 1. Clone and enter the repository
git clone https://github.com/k0pfnicker/agy-lsp.git
cd agy-lsp

# 2. Create virtual environment and install dependencies (note the quotes around ".[dev]" in PowerShell)
python -m venv .venv
.\.venv\Scripts\pip.exe install -e ".[dev]"

# 3. Optional: Install Python & C/C++ language servers directly into .venv (no admin rights required)
.\.venv\Scripts\pip.exe install python-lsp-server clangd

# 4. Run one-step workspace & MCP setup
.\.venv\Scripts\python.exe setup_agy.py --workspace D:\YourProject
```

### Linux / macOS

```bash
# 1. Clone and enter the repository
git clone https://github.com/k0pfnicker/agy-lsp.git
cd agy-lsp

# 2. Create virtual environment and install dependencies
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"

# 3. Optional: Install Python & C/C++ language servers
pip install python-lsp-server clangd

# 4. Run one-step workspace & MCP setup
python setup_agy.py --workspace /path/to/your/project
```

---

## 7. Integration into Antigravity CLI

### Option A: Automated Setup via `setup_agy.py` (Recommended)

Running `python setup_agy.py --workspace <path>` automatically:
1. Detects the exact absolute path to `.venv/Scripts/agy-lsp` and `.venv/Scripts` (so language servers installed inside `.venv` are found automatically without modifying your global system `PATH`).
2. Registers `agy-lsp` in `~/.gemini/config/mcp_config.json`.
3. Installs the `SKILL.md` into `<workspace>/.agents/skills/agy-lsp/SKILL.md` without creating duplicate plugin MCP server entries.

### Option B: As a Discovered Plugin

The plugin also adheres to the official Antigravity plugin manifest specifications (`plugin.json` and `mcp_config.json`).
*(Note: Do not register both `~/.gemini/config/mcp_config.json` and `.agents/plugins/agy-lsp/mcp_config.json` simultaneously, or Antigravity will list two MCP server instances `agy-lsp` and `agy-lsp_agy-lsp`.)*

Validate the plugin with the official CLI command:
```bash
agy plugin validate .
```
Expected output:
```text
  [ok]    .
          ✔ skills      : 1 processed
          ✔ mcpServers  : 1 processed
```

---

## 8. Language Server Installation

If a language server is not installed, the plugin provides a clear, user-friendly error message with actionable installation commands. Executables installed inside the same `.venv` are discovered automatically:

### Python
```bash
# Option 1: python-lsp-server (pure Python, no Node.js required)
pip install python-lsp-server

# Option 2: Pyright
npm install -g pyright
```

### C# (.NET)
```bash
dotnet tool install -g csharp-ls
```

### C / C++
- **Python Wheel (Windows / Linux / macOS, no admin rights required):** `pip install clangd`
- **Windows:** `scoop install llvm` or `winget install LLVM.LLVM`
- **macOS:** `brew install llvm`
- **Linux (Debian/Ubuntu):** `sudo apt-get install clangd`

### TypeScript / JavaScript
```bash
npm install -g typescript-language-server typescript
```

---

## 9. Configuration (`agy-lsp.json`)

`agy-lsp` works out of the box with safe defaults. To customize behavior, place an `agy-lsp.json` file at your workspace root or under `~/.gemini/config/agy-lsp.json`:

```json
{
  "defaultLanguage": "auto",
  "workspaceRoot": null,
  "maxResults": 50,
  "includeCodeSnippets": false,
  "snippetContextLines": 3,
  "allowOutsideWorkspace": false,
  "writeChanges": false,
  "serverStartupTimeoutMs": 15000,
  "requestTimeoutMs": 10000,
  "maxRestartAttempts": 2,
  "servers": {
    "csharp": {
      "command": "csharp-ls",
      "args": []
    },
    "cpp": {
      "command": "clangd",
      "args": ["--background-index"]
    },
    "typescript": {
      "command": "typescript-language-server",
      "args": ["--stdio"]
    },
    "python": {
      "command": "pyright-langserver",
      "args": ["--stdio"],
      "fallbacks": [
        { "command": "pylsp", "args": [] }
      ]
    }
  }
}
```

### Configuration Options Reference

| Key | Type | Default | Description |
| :--- | :--- | :--- | :--- |
| `defaultLanguage` | `string` | `"auto"` | Fallback language for files with unrecognized extensions. |
| `workspaceRoot` | `string \| null` | `null` | Explicit workspace root. If `null`, discovered automatically via `.git`, `.sln`, etc. |
| `maxResults` | `integer` | `50` | Maximum number of diagnostics, references, or symbols returned. |
| `includeCodeSnippets` | `boolean` | `false` | Whether to include code snippets with definition and reference locations. |
| `snippetContextLines` | `integer` | `3` | Number of context lines before and after target line in snippets. |
| `allowOutsideWorkspace` | `boolean` | `false` | **Security boundary:** Forbids accessing paths outside the workspace root. |
| `writeChanges` | `boolean` | `false` | **Write protection:** Enables writing rename refactorings directly to disk. |
| `serverStartupTimeoutMs`| `integer` | `15000` | Timeout in milliseconds for LSP process initialization handshake. |
| `requestTimeoutMs` | `integer` | `10000` | Timeout in milliseconds for individual LSP JSON-RPC requests. |
| `maxRestartAttempts` | `integer` | `2` | Maximum retry attempts when a server process crashes unexpectedly. |

---

## 10. Token Efficiency & Context Optimization

To prevent context bloat and optimize LLM token consumption, `agy-lsp` incorporates several efficiency mechanisms:

1. **No Full File Dumps:** Returns precise coordinates or compact snippets (default: 3 lines context) instead of entire files.
2. **Diagnostic Deduplication:** Merges redundant diagnostic reports at identical file locations.
3. **Message Truncation:** Overly verbose compiler error messages are truncated at 400 characters (`... [truncated]`).
4. **Result Limiting & Pagination:** Result lists are capped at `maxResults` and annotated with a `truncated: true` flag and total count.
5. **Compact Structure:** Omits empty optional keys and null values.

---

## 11. Security Model

- **Workspace Confinement:** All file paths are canonicalized (`resolve()`). Accessing files outside the workspace root is rejected unless `allowOutsideWorkspace: true` is set. Path traversal attacks (`../../`) are blocked.
- **No Shell Execution:** Subprocesses are launched directly using `asyncio.create_subprocess_exec` without a shell (`shell=False`).
- **Static Command Allowlist:** Server commands are loaded strictly from static configuration or defaults, never from dynamic agent tool arguments.
- **Secret Redaction:** Stderr logs automatically redact bearer tokens, API keys, and passwords.
- **Stderr Isolation:** All diagnostic logs are routed strictly to `sys.stderr`, preserving clean JSON-RPC communication on `sys.stdout`.

---

## 12. Troubleshooting & Diagnostics

### Checking Server Health
Invoke the `lsp_status` tool through the agent or MCP:
```json
{
  "name": "lsp_status",
  "arguments": {}
}
```
Output details:
- Status per language (`RUNNING`, `AVAILABLE`, `NOT_INSTALLED`, `CRASHED`),
- Process ID (PID) and workspace root,
- Detailed error messages and installation advice if a binary is missing.

### Error: "Language server command '...' was not found"
Ensure the language server is installed and available in `PATH`, or specify its absolute executable path in `agy-lsp.json`:
```json
{
  "servers": {
    "csharp": {
      "command": "C:/Users/<User>/.dotnet/tools/csharp-ls.exe"
    }
  }
}
```

---

## 13. Development, Testing & QA

### Running the Test Suite & Empirical Benchmarks

The test suite contains **45 automated tests** across unit, integration, empirical benchmark, and real Language Server end-to-end categories (`pylsp` & `clangd`):

```powershell
# Run all 45 tests
.\.venv\Scripts\pytest.exe -v

# Run empirical benchmarks with detailed metrics output
.\.venv\Scripts\pytest.exe tests/test_benchmarks_and_value.py -v -s

# Run the real LSP process E2E tests (Python pylsp & C/C++ clangd)
.\.venv\Scripts\pytest.exe tests/test_e2e_real_lsp.py -v
```

### Linting & Formatting Check
```powershell
.\.venv\Scripts\ruff.exe check .
.\.venv\Scripts\ruff.exe format --check .
```

### Plugin Manifest Validation
```powershell
agy plugin validate .
```

---

## 14. Adding New Languages

To add a new language server (e.g. Rust via `rust-analyzer` or Go via `gopls`):

1. **Map file extensions:** In [`paths.py`](src/agy_lsp/utils/paths.py) in `EXTENSION_LANGUAGE_MAP`:
   ```python
   ".rs": "rust",
   ".go": "go",
   ```
2. **Register default server:** In [`config.py`](src/agy_lsp/config.py) in `DEFAULT_SERVERS`:
   ```python
   "rust": ServerConfig(command="rust-analyzer", args=[]),
   "go": ServerConfig(command="gopls", args=["serve"]),
   ```
3. **Add installation hint:** In [`adapters.py`](src/agy_lsp/lsp/adapters.py) in `INSTALL_HINTS`.

Alternatively, configure new languages purely declaratively in `agy-lsp.json` without modifying source code!

---

## 15. Known Limitations

- **C# on Modern .NET Previews:** On .NET 10 Preview environments, `dotnet tool install -g csharp-ls` may encounter packaging manifest issues. Configure an alternative Roslyn server path in `agy-lsp.json` if needed.
- **Multiple Workspace Roots:** The bridge currently targets one primary workspace root per session. Submodules and subfolders within the root are fully supported.
- **C/C++ Semantic Macro Expansion:** `clangd` yields optimal results when a `compile_commands.json` database is present in the workspace root.

---

## 16. License

This project is licensed under the [MIT License](LICENSE).

TDQS

A3.5/5.0

Scored across 11 tools

Disambiguation4/5

Most tools target clearly distinct LSP operations: diagnostics, status, definitions, references, rename, symbols, hover, and hierarchies. The only mild overlap is between prepare_call_hierarchy and call_hierarchy, where the preparatory step could be confused with the actual hierarchy query.

Naming Consistency4/5

Names are consistently snake_case and mostly follow verb_noun or clear noun_phrase patterns, e.g. go_to_definition, find_references, rename_symbol, get_type_hierarchy. Minor deviations include single-word hover and noun-style lsp_status/call_hierarchy, but the set remains predictable.

Tool Count5/5

Eleven tools is well-scoped for an LSP server, covering navigation, diagnostics, refactoring, symbols, and hierarchy queries without obvious bloat. Each tool appears to earn its place in the surface.

Completeness4/5

The server covers core LSP workflows: diagnostics, definition lookup, references, rename, document/workspace symbols, hover, and call/type hierarchies. Some secondary LSP capabilities such as code actions, formatting, or signature help are absent, but the main agent-facing operations are present.

Maintenance

ActivityMaintained
ResponsivenessNo issues