---
title: Language Server Protocol
description: Interact with language server protocol servers in your sandboxes.
---

import { TabItem, Tabs } from '@astrojs/starlight/components'

Daytona provides Language Server Protocol (LSP) support through sandbox instances. This enables advanced language features like code completion, diagnostics, and more.

## Create LSP servers

Daytona provides methods to create LSP servers. The `path_to_project` argument is relative to the current sandbox working directory when no leading `/` is used. The working directory is specified by WORKDIR when it is present in the Dockerfile, and otherwise falls back to the user's home directory.

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```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"
)
```

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
import { Daytona, LspLanguageId } from '@daytona/sdk'

// Create sandbox
const daytona = new Daytona()
const sandbox = await daytona.create({
  language: 'typescript',
})

// Create LSP server for TypeScript
const lspServer = await sandbox.createLspServer(
  LspLanguageId.TYPESCRIPT,
  'workspace/project'
)
```

</TabItem>
<TabItem label="Ruby" icon="seti:ruby">

```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'
)
```

</TabItem>
<TabItem label="Go" icon="seti:go">

```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)
}

// Get LSP service for Python
lsp := sandbox.Lsp(types.LspLanguagePython, "workspace/project")
```

</TabItem>
<TabItem label="Java" icon="seti:java">

```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(
                    LspServer.LspLanguageId.PYTHON.getValue(),
                    "workspace/project");
        }
    }
}
```

</TabItem>
</Tabs>

### Supported languages

The supported languages for creating LSP servers with Daytona are defined by the `LspLanguageId` enum:

| Enum Value                     | Description                            |
| ------------------------------ | -------------------------------------- |
| **`LspLanguageId.PYTHON`**     | Python language server                 |
| **`LspLanguageId.TYPESCRIPT`** | TypeScript/JavaScript language server  |

## Start LSP servers

Daytona provides methods to start LSP servers.

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
lsp = sandbox.create_lsp_server("typescript", "workspace/project")
lsp.start()  # Initialize the server
# Now ready for LSP operations
```

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
const lsp = await sandbox.createLspServer('typescript', 'workspace/project')
await lsp.start() // Initialize the server
// Now ready for LSP operations
```

</TabItem>
<TabItem label="Ruby" icon="seti:ruby">

```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
```

</TabItem>
<TabItem label="Go" icon="seti:go">

```go
lsp := sandbox.Lsp(types.LspLanguagePython, "workspace/project")
err := lsp.Start(ctx)  // Initialize the server
if err != nil {
	log.Fatal(err)
}
// Now ready for LSP operations
```

</TabItem>
<TabItem label="Java" icon="seti:java">

```java
LspServer lsp = sandbox.createLspServer("typescript", "workspace/project");
lsp.start("typescript", "workspace/project");
// Now ready for LSP operations
```

</TabItem>
<TabItem label="API" icon="seti:json">

```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/lsp/start' \
  --request POST \
  --header 'Content-Type: application/json' \
  --data '{
  "languageId": "",
  "pathToProject": ""
}'
```

</TabItem>
</Tabs>

## Stop LSP servers

Daytona provides methods to stop LSP servers.

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
# When done with LSP features
lsp.stop()  # Clean up resources
```

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
// When done with LSP features
await lsp.stop() // Clean up resources
```

</TabItem>
<TabItem label="Ruby" icon="seti:ruby">

```ruby
# When done with LSP features
lsp.stop  # Clean up resources
```

</TabItem>
<TabItem label="Go" icon="seti:go">

```go
// When done with LSP features
err := lsp.Stop(ctx)  // Clean up resources
if err != nil {
	log.Fatal(err)
}
```

</TabItem>
<TabItem label="Java" icon="seti:java">

```java
// When done with LSP features
lsp.stop("typescript", "workspace/project"); // Clean up resources
```

</TabItem>
<TabItem label="API" icon="seti:json">

```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/lsp/stop' \
  --request POST \
  --header 'Content-Type: application/json' \
  --data '{
  "languageId": "",
  "pathToProject": ""
}'
```

</TabItem>
</Tabs>

## Code completions

Daytona provides methods to get code completions for a specific position in a file.

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
completions = lsp_server.completions(
    path="workspace/project/main.py",
    position={"line": 10, "character": 15}
)
print(f"Completions: {completions}")
```

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
const completions = await lspServer.completions('workspace/project/main.ts', {
  line: 10,
  character: 15,
})
console.log('Completions:', completions)
```
</TabItem>

<TabItem label="Ruby" icon="seti:ruby">

```ruby
completions = lsp_server.completions(
  path: 'workspace/project/main.py',
  position: { line: 10, character: 15 }
)
puts "Completions: #{completions}"
```

</TabItem>
<TabItem label="Go" icon="seti:go">

```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)
```

</TabItem>
<TabItem label="Java" icon="seti:java">

```java
var completions = lsp.completions(
    "typescript",
    "workspace/project",
    "workspace/project/Main.java",
    10,
    15);
System.out.println("Completions: " + completions);
```

</TabItem>
<TabItem label="API" icon="seti:json">

```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/lsp/completions' \
  --request POST \
  --header 'Content-Type: application/json' \
  --data '{
  "context": {
    "triggerCharacter": "",
    "triggerKind": 1
  },
  "languageId": "",
  "pathToProject": "",
  "position": {
    "character": 1,
    "line": 1
  },
  "uri": ""
}'
```

</TabItem>
</Tabs>

## File notifications

Daytona provides methods to notify the LSP server when files are opened or closed. This enables features like diagnostics and completion tracking for the specified files.

### Open file

Notifies the language server that a file has been opened for editing.

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
# Notify server that a file is open
lsp_server.did_open("workspace/project/main.py")
```

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
// Notify server that a file is open
await lspServer.didOpen('workspace/project/main.ts')
```

</TabItem>
<TabItem label="Ruby" icon="seti:ruby">

```ruby
# Notify server that a file is open
lsp_server.did_open('workspace/project/main.py')
```

</TabItem>
<TabItem label="Go" icon="seti:go">

```go
// Notify server that a file is open
err := lsp.DidOpen(ctx, "workspace/project/main.py")
if err != nil {
	log.Fatal(err)
}
```

</TabItem>
<TabItem label="Java" icon="seti:java">

```java
// Notify server that a file is open
lsp.didOpen("typescript", "workspace/project", "workspace/project/Main.java");
```

</TabItem>
<TabItem label="API" icon="seti:json">

```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/lsp/did-open' \
  --request POST \
  --header 'Content-Type: application/json' \
  --data '{
  "languageId": "",
  "pathToProject": "",
  "uri": ""
}'
```

</TabItem>
</Tabs>

### Close file

Notifies the language server that a file has been closed. This allows the server to clean up resources associated with that file.

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
# Notify server that a file is closed
lsp_server.did_close("workspace/project/main.py")
```

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
// Notify server that a file is closed
await lspServer.didClose('workspace/project/main.ts')
```

</TabItem>
<TabItem label="Ruby" icon="seti:ruby">

```ruby
# Notify server that a file is closed
lsp_server.did_close('workspace/project/main.py')
```

</TabItem>
<TabItem label="Go" icon="seti:go">

```go
// Notify server that a file is closed
err := lsp.DidClose(ctx, "workspace/project/main.py")
if err != nil {
	log.Fatal(err)
}
```

</TabItem>
<TabItem label="Java" icon="seti:java">

```java
// Notify server that a file is closed
lsp.didClose("typescript", "workspace/project", "workspace/project/Main.java");
```

</TabItem>
<TabItem label="API" icon="seti:json">

```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/lsp/did-close' \
  --request POST \
  --header 'Content-Type: application/json' \
  --data '{
  "languageId": "",
  "pathToProject": "",
  "uri": ""
}'
```

</TabItem>
</Tabs>

## Document symbols

Daytona provides methods to retrieve symbols (functions, classes, variables, etc.) from a document.

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
symbols = lsp_server.document_symbols("workspace/project/main.py")
for symbol in symbols:
    print(f"Symbol: {symbol.name}, Kind: {symbol.kind}")
```

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
const symbols = await lspServer.documentSymbols('workspace/project/main.ts')
symbols.forEach((symbol) => {
  console.log(`Symbol: ${symbol.name}, Kind: ${symbol.kind}`)
})
```

</TabItem>
<TabItem label="Ruby" icon="seti:ruby">

```ruby
symbols = lsp_server.document_symbols('workspace/project/main.py')
symbols.each do |symbol|
  puts "Symbol: #{symbol.name}, Kind: #{symbol.kind}"
end
```

</TabItem>
<TabItem label="Go" icon="seti:go">

```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)
}
```

</TabItem>
<TabItem label="Java" icon="seti:java">

```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());
}
```

</TabItem>
<TabItem label="API" icon="seti:json">

```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/lsp/document-symbols?languageId=&pathToProject=&uri='
```

</TabItem>
</Tabs>

## Sandbox symbols

Daytona provides methods to search for symbols across all files in the sandbox.

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
symbols = lsp_server.sandbox_symbols("MyClass")
for symbol in symbols:
    print(f"Found: {symbol.name} at {symbol.location}")
```

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
const symbols = await lspServer.sandboxSymbols('MyClass')
symbols.forEach((symbol) => {
  console.log(`Found: ${symbol.name} at ${symbol.location}`)
})
```

</TabItem>
<TabItem label="Ruby" icon="seti:ruby">

```ruby
symbols = lsp_server.sandbox_symbols('MyClass')
symbols.each do |symbol|
  puts "Found: #{symbol.name} at #{symbol.location}"
end
```

</TabItem>
<TabItem label="Go" icon="seti:go">

```go
symbols, err := lsp.SandboxSymbols(ctx, "MyClass")
if err != nil {
	log.Fatal(err)
}
for _, symbol := range symbols {
	fmt.Printf("Found: %v\n", symbol)
}
```

</TabItem>
<TabItem label="Java" icon="seti:java">

```java
var symbols = lsp.workspaceSymbols("MyClass", "typescript", "workspace/project");
for (var symbol : symbols) {
    System.out.println("Found: " + symbol.getName() + " at " + symbol.getLocation());
}
```

</TabItem>
<TabItem label="API" icon="seti:json">

```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/lsp/workspacesymbols?query=&languageId=&pathToProject='
```

</TabItem>
</Tabs>

