---
title: Language Server Protocol
description: Interact with language server protocol servers in your sandboxes.
---
Language Server Protocol (LSP) support is available through LSP server instances created from a sandbox. A language server runs inside the sandbox and analyzes the project's code, so your application gets IDE-grade code intelligence for code that never leaves the sandbox.
An LSP server covers code completions, file open and close notifications, document symbols, and sandbox-wide symbol search. Each server instance is scoped to one language and one project directory; Python and TypeScript language servers are available by default.
## Workflow
Follow this order when using LSP in a sandbox:
1. Create an LSP server instance with **`create_lsp_server`** or **`createLspServer`**
2. Call **`start()`** to initialize the language server; LSP methods fail until the server is started
3. Call **`didOpen()`** on a file before requesting completions or document symbols for that file
4. Use completions, document symbols, or sandbox symbols
5. Call **`didClose()`** when you finish with a file
6. Call **`stop()`** when the LSP server is no longer needed
## Create LSP servers
Create an LSP server instance by providing the language ID and the path to the project.
- **Python**: **`LspLanguageId.PYTHON`**
- **TypeScript and JavaScript**: **`LspLanguageId.TYPESCRIPT`**
- **Custom**: Install the language server for your target language
```python
from daytona import Daytona, LspLanguageId
# Create Sandbox
daytona = Daytona()
sandbox = daytona.create()
# Create LSP server for Python
lsp_server = sandbox.create_lsp_server(
language_id=LspLanguageId.PYTHON,
path_to_project="workspace/project"
)
```
```typescript
import { Daytona, LspLanguageId } from '@daytona/sdk'
// Create sandbox
const daytona = new Daytona()
const sandbox = await daytona.create()
// Create LSP server for TypeScript
const lspServer = await sandbox.createLspServer(
LspLanguageId.TYPESCRIPT,
'workspace/project'
)
```
```ruby
require 'daytona'
# Create Sandbox
daytona = Daytona::Daytona.new
sandbox = daytona.create
# Create LSP server for Python
lsp_server = sandbox.create_lsp_server(
language_id: Daytona::LspServer::Language::PYTHON,
path_to_project: 'workspace/project'
)
```
```go
// Create sandbox
client, err := daytona.NewClient()
if err != nil {
log.Fatal(err)
}
ctx := context.Background()
sandbox, err := client.Create(ctx, nil)
if err != nil {
log.Fatal(err)
}
// Create LSP server for Python
lsp := sandbox.CreateLspServer(types.LspLanguagePython, "workspace/project")
```
```java
import io.daytona.sdk.Daytona;
import io.daytona.sdk.LspServer;
import io.daytona.sdk.Sandbox;
public class App {
public static void main(String[] args) {
try (Daytona daytona = new Daytona()) {
Sandbox sandbox = daytona.create();
LspServer lspServer = sandbox.createLspServer(
"python",
"workspace/project");
}
}
}
```
## Start LSP servers
Start an LSP server by calling **`start()`** before any other LSP operation.
```python
lsp = sandbox.create_lsp_server(
language_id=LspLanguageId.PYTHON,
path_to_project="workspace/project"
)
lsp.start() # Initialize the server
# Now ready for LSP operations
```
```typescript
const lsp = await sandbox.createLspServer(
LspLanguageId.TYPESCRIPT,
'workspace/project'
)
await lsp.start() // Initialize the server
// Now ready for LSP operations
```
```ruby
lsp = sandbox.create_lsp_server(
language_id: Daytona::LspServer::Language::PYTHON,
path_to_project: 'workspace/project'
)
lsp.start # Initialize the server
# Now ready for LSP operations
```
```go
lsp := sandbox.CreateLspServer(types.LspLanguagePython, "workspace/project")
err := lsp.Start(ctx) // Initialize the server
if err != nil {
log.Fatal(err)
}
// Now ready for LSP operations
```
```java
LspServer lsp = sandbox.createLspServer("typescript", "workspace/project");
lsp.start("typescript", "workspace/project");
// Now ready for LSP operations
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/lsp/start' \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"languageId": "python",
"pathToProject": "workspace/project"
}'
```
## Stop LSP servers
Stop an LSP server by calling **`stop()`** when the LSP server is no longer needed.
```python
# When done with LSP features
lsp.stop() # Clean up resources
```
```typescript
// When done with LSP features
await lsp.stop() // Clean up resources
```
```ruby
# When done with LSP features
lsp.stop # Clean up resources
```
```go
// When done with LSP features
err := lsp.Stop(ctx) // Clean up resources
if err != nil {
log.Fatal(err)
}
```
```java
// When done with LSP features
lsp.stop("typescript", "workspace/project"); // Clean up resources
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/lsp/stop' \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"languageId": "python",
"pathToProject": "workspace/project"
}'
```
## Code completions
Get code completions for a specific position in a file by providing the file path and position.
- Position values are zero-based (`line: 0` is the first line)
- Call **`didOpen()`** on the file before requesting completions
```python
completions = lsp_server.completions(
path="workspace/project/main.py",
position={"line": 10, "character": 15}
)
print(f"Completions: {completions}")
```
```typescript
const completions = await lspServer.completions('workspace/project/main.ts', {
line: 10,
character: 15,
})
console.log('Completions:', completions)
```
```ruby
completions = lsp_server.completions(
path: 'workspace/project/main.py',
position: { line: 10, character: 15 }
)
puts "Completions: #{completions}"
```
```go
completions, err := lsp.Completions(ctx, "workspace/project/main.py",
types.Position{Line: 10, Character: 15},
)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Completions: %v\n", completions)
```
```java
var completions = lsp.completions(
"typescript",
"workspace/project",
"workspace/project/Main.java",
10,
15);
System.out.println("Completions: " + completions);
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/lsp/completions' \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"context": {
"triggerCharacter": "",
"triggerKind": 1
},
"languageId": "python",
"pathToProject": "workspace/project",
"position": {
"character": 15,
"line": 10
},
"uri": "workspace/project/main.py"
}'
```
## File notifications
Daytona provides methods to notify the LSP server when files are opened or closed. This enables completion and symbol tracking for the specified files.
### Open file
Notify the language server that a file has been opened for editing by providing the path to the file. The server reads the file contents from disk at open time.
```python
# Notify server that a file is open
lsp_server.did_open("workspace/project/main.py")
```
```typescript
// Notify server that a file is open
await lspServer.didOpen('workspace/project/main.ts')
```
```ruby
# Notify server that a file is open
lsp_server.did_open('workspace/project/main.py')
```
```go
// Notify server that a file is open
err := lsp.DidOpen(ctx, "workspace/project/main.py")
if err != nil {
log.Fatal(err)
}
```
```java
// Notify server that a file is open
lsp.didOpen("typescript", "workspace/project", "workspace/project/Main.java");
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/lsp/did-open' \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"languageId": "python",
"pathToProject": "workspace/project",
"uri": "workspace/project/main.py"
}'
```
### Close file
Notify the language server that a file has been closed by providing the path to the file. This allows the server to clean up resources associated with that file.
```python
# Notify server that a file is closed
lsp_server.did_close("workspace/project/main.py")
```
```typescript
// Notify server that a file is closed
await lspServer.didClose('workspace/project/main.ts')
```
```ruby
# Notify server that a file is closed
lsp_server.did_close('workspace/project/main.py')
```
```go
// Notify server that a file is closed
err := lsp.DidClose(ctx, "workspace/project/main.py")
if err != nil {
log.Fatal(err)
}
```
```java
// Notify server that a file is closed
lsp.didClose("typescript", "workspace/project", "workspace/project/Main.java");
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/lsp/did-close' \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"languageId": "python",
"pathToProject": "workspace/project",
"uri": "workspace/project/main.py"
}'
```
## Document symbols
Retrieve symbols (functions, classes, variables, etc.) from a document by providing the path to the file.
```python
symbols = lsp_server.document_symbols("workspace/project/main.py")
for symbol in symbols:
print(f"Symbol: {symbol.name}, Kind: {symbol.kind}")
```
```typescript
const symbols = await lspServer.documentSymbols('workspace/project/main.ts')
symbols.forEach((symbol) => {
console.log(`Symbol: ${symbol.name}, Kind: ${symbol.kind}`)
})
```
```ruby
symbols = lsp_server.document_symbols('workspace/project/main.py')
symbols.each do |symbol|
puts "Symbol: #{symbol.name}, Kind: #{symbol.kind}"
end
```
```go
symbols, err := lsp.DocumentSymbols(ctx, "workspace/project/main.py")
if err != nil {
log.Fatal(err)
}
for _, symbol := range symbols {
fmt.Printf("Symbol: %v\n", symbol)
}
```
```java
var symbols = lsp.documentSymbols(
"typescript",
"workspace/project",
"workspace/project/Main.java");
for (var symbol : symbols) {
System.out.println("Symbol: " + symbol.getName() + ", Kind: " + symbol.getKind());
}
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/lsp/document-symbols?languageId=python&pathToProject=workspace/project&uri=workspace/project/main.py'
```
## Sandbox symbols
Search for symbols across all files in the sandbox by providing the query and the language ID. The Java SDK uses **`workspaceSymbols()`** instead of **`sandboxSymbols()`**.
```python
symbols = lsp_server.sandbox_symbols("MyClass")
for symbol in symbols:
print(f"Found: {symbol.name} at {symbol.location}")
```
```typescript
const symbols = await lspServer.sandboxSymbols('MyClass')
symbols.forEach((symbol) => {
console.log(`Found: ${symbol.name} at ${symbol.location}`)
})
```
```ruby
symbols = lsp_server.sandbox_symbols('MyClass')
symbols.each do |symbol|
puts "Found: #{symbol.name} at #{symbol.location}"
end
```
```go
symbols, err := lsp.SandboxSymbols(ctx, "MyClass")
if err != nil {
log.Fatal(err)
}
for _, symbol := range symbols {
fmt.Printf("Found: %v\n", symbol)
}
```
```java
var symbols = lsp.workspaceSymbols("MyClass", "typescript", "workspace/project");
for (var symbol : symbols) {
System.out.println("Found: " + symbol.getName() + " at " + symbol.getLocation());
}
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/lsp/workspacesymbols?query=MyClass&languageId=python&pathToProject=workspace/project'
```