IA

Language Server Protocol (LSP) no OpenCode — Guia Completo

O Language Server Protocol (LSP) é o standard universal que dá inteligência de código a qualquer editor. Descobre como o OpenCode usa LSP para autocomplete, diagnóstico, go-to-definition e navegação — e como se compara com o MCP.

O Language Server Protocol (LSP) é para a edição de código o que o USB é para periféricos: um standard universal que permite a qualquer editor ter suporte nativo para qualquer linguagem. E no OpenCode, é o que dá ao teu agente de IA uma perceção sobre-humana do código que está a ler.

Imagina que estás a programar e o teu editor mostra-te erros a vermelho antes de sequer compilares. Ou que, ao fazeres hover sobre uma função, vês a sua assinatura, documentação e tipos esperados. Ou que o autocomplete te sugere exatamente o método que precisas, com os parâmetros certos, sem teres de decorar nada.

Essa magia toda chama-se Language Server Protocol (LSP). Foi criado pela Microsoft em 2016 para o VS Code, e rapidamente se tornou o standard da indústria. Hoje, todos os editores modernos o suportam — Emacs, Vim, Neovim, Sublime Text, Zed, Helix, e claro, o OpenCode. O repositório da especificação tem mais de 13 mil estrelas no GitHub, e dezenas de servidores de linguagem já o suportam.

Com o LSP ativo, o agente de IA vê o código com uma precisão que não se consegue só com grep.

LSP no OpenCode — Thumbnail

O OpenCode integra Language Server Protocol para dar inteligência ao agente de IA sobre o código


O que é o Language Server Protocol?

O Language Server Protocol (LSP) é um protocolo de comunicação baseado em JSON-RPC 2.0 que standardiza a forma como os editores de código obtêm funcionalidades de inteligência de código — autocomplete, diagnóstico, navegação, refatoração, formatação — para qualquer linguagem de programação.

Antes do LSP, cada editor precisava de uma extensão específica para cada linguagem. O VS Code precisava de uma extensão para TypeScript, outra para Python, outra para Rust. Cada extensão era código diferente, com APIs diferentes, e um esforço de manutenção gigante.

A ideia do LSP é simples e genial: em vez de N linguagens × M editores (explosão combinatória), separa-se o cliente (editor) do servidor (análise da linguagem). O editor comunica com o servidor via JSON-RPC, e o servidor faz todo o trabalho pesado de análise sintática, semântica e type-checking.

Arquitetura LSP no OpenCode

Arquitetura LSP: OpenCode como cliente comunica com servidores de linguagem via JSON-RPC 2.0

Como funciona na prática:

  1. O editor (OpenCode, VS Code, Neovim) abre um ficheiro
  2. Deteta a extensão do ficheiro (ex: .ts) e inicia o servidor LSP correspondente (ex: typescript-language-server)
  3. O editor envia o conteúdo do ficheiro ao servidor via textDocument/didOpen
  4. O servidor analisa o código e responde com diagnósticos (erros, warnings), completions, etc.
  5. A comunicação é bidirecional e assíncrona — o servidor pode enviar atualizações sempre que o código muda

Nota: O LSP usa exclusivamente JSON-RPC 2.0 como protocolo de transporte, com mensagens request/response e notifications. Isto é exatamente o mesmo protocolo que o MCP usa — mas para um propósito completamente diferente. Ambas as equipas (Microsoft para LSP, Anthropic para MCP) escolheram JSON-RPC pela sua simplicidade e eficácia.


Como o OpenCode usa LSP

No OpenCode, o LSP não serve para mostrar um autocomplete numa UI (não há editor gráfico). Em vez disso, o LSP é usado para dar ao agente de IA uma compreensão profunda do código que está a analisar. O agente "vê" diagnósticos, tipos, referências e definições através do LSP, e usa essa informação para tomar decisões mais informadas.

O OpenCode atua como cliente LSP (não como servidor). Isto significa que ele inicia e comunica com servidores LSP externos (como o typescript-language-server, rust-analyzer, pyright, etc.), consumindo os dados que eles fornecem.

Capacidades LSP que o OpenCode usa:

Capacidade Request LSP O que o agente vê
Diagnóstico textDocument/publishDiagnostics Erros e warnings em tempo real, linha a linha
Autocomplete textDocument/completion Sugestões contextuais para completar código
Hover Info textDocument/hover Tipo, documentação e assinatura de símbolos
Go-to-Definition textDocument/definition Localização exata da definição de um símbolo
Find References textDocument/references Lista de todas as ocorrências de um símbolo
Code Actions textDocument/codeAction Sugestões de correção automática (ex: import em falta)
Formatação textDocument/formatting Código formatado segundo as regras do projeto
Signature Help textDocument/signatureHelp Parâmetros esperados por uma função

Quando o agente do OpenCode pede diagnósticos de um ficheiro, ele não está apenas a fazer cat ao ficheiro. Ele está a perguntar ao servidor LSP: "Há erros aqui? Que tipos estão a ser usados? O que posso melhorar?". O servidor responde com informação estruturada que o LLM pode processar e agir sobre ela.

Exemplo real: Quando pedes ao OpenCode "explica-me este ficheiro e encontra bugs", o agente primeiramente faz textDocument/publishDiagnostics para obter erros do LSP, depois pede textDocument/hover para inspecionar tipos, e só depois te responde com uma análise completa e contextualizada.


Instalação e Configuração de LSPs

O OpenCode tem LSP desativado por defeito. Para o ativar, precisas de configurar a secção lsp no teu opencode.json.

Ativar todos os servidores built-in:

{
  "$schema": "https://opencode.ai/config.json",
  "lsp": true
}
Copy

Com esta configuração, o OpenCode ativa todos os servidores LSP built-in para os quais encontra as dependências instaladas. Se tens o typescript no package.json, o servidor TypeScript é iniciado. Se tens o rust-analyzer no PATH, o servidor Rust é iniciado. E assim por diante.

Configuração granular (recomendada):

{
  "$schema": "https://opencode.ai/config.json",
  "lsp": {
    "typescript": {
      "command": ["typescript-language-server", "--stdio"],
      "extensions": [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".mts", ".cts"]
    },
    "rust": {
      "command": ["rust-analyzer"],
      "extensions": [".rs"]
    },
    "pyright": {
      "command": ["pyright-langserver", "--stdio"],
      "extensions": [".py", ".pyi"]
    },
    "gopls": {
      "command": ["gopls"],
      "extensions": [".go"]
    }
  }
}
Copy

Servidores LSP built-in do OpenCode:

O OpenCode vem com suporte para mais de 30 servidores LSP. Aqui estão os mais relevantes:

LSP Server Extensões Requisitos
typescript.ts, .tsx, .js, .jsx, .mjs, .cjsDependência typescript no projeto
rust (rust-analyzer).rsrust-analyzer no PATH
pyright.py, .pyipyright instalado (pip ou npm)
gopls.gogopls no PATH
bash (bash-language-server).sh, .bash, .zshAuto-instala via npm
lua-ls.luaAuto-instala para projetos Lua
zls (Zig).zig, .zonzig no PATH
clangd.c, .cpp, .h, .hppAuto-instala para projetos C/C++
elixir-ls.ex, .exselixir no PATH
jdtls (Java).javaJava SDK 21+
terraform.tf, .tfvarsAuto-instala do GitHub
svelte.svelteAuto-instala para projetos Svelte
vue.vueAuto-instala para projetos Vue
prisma.prismaprisma no PATH
php (intelephense).phpAuto-instala para projetos PHP
yaml-ls.yaml, .ymlAuto-instala o Red Hat yaml-language-server
deno.ts, .tsx, .js, .jsx, .mjsdeno no PATH + deno.json/deno.jsonc
oxlint.ts, .tsx, .js, .jsxDependência oxlint no projeto

Configurar variáveis de ambiente para LSP:

{
  "lsp": {
    "rust": {
      "command": ["rust-analyzer"],
      "env": {
        "RUST_LOG": "debug",
        "RUST_BACKTRACE": "1"
      }
    }
  }
}
Copy

Passar initialization options:

{
  "lsp": {
    "custom-lsp": {
      "command": ["custom-lsp-server", "--stdio"],
      "extensions": [".custom"],
      "initialization": {
        "preferences": {
          "importModuleSpecifierPreference": "relative"
        }
      }
    }
  }
}
Copy

Desativar servidores específicos:

{
  "lsp": {
    "typescript": {
      "disabled": true
    },
    "pyright": {
      "disabled": true
    }
  }
}
Copy

Adicionar servidores LSP personalizados:

{
  "lsp": {
    "texlab": {
      "command": ["texlab"],
      "extensions": [".tex", ".bib"]
    },
    "solargraph": {
      "command": ["solargraph", "stdio"],
      "extensions": [".rb"]
    }
  }
}
Copy

Exemplo Prático: LSP para TypeScript

Vamos montar um exemplo real. Imagina que tens um projeto TypeScript com o seguinte ficheiro src/app.ts:

interface User {
  name: string;
  email?: string;
}

function greet(user: User) {
  return `Olá, ${user.name}!`;
}

const user: User = { name: "Fuzza" };
console.log(greet(user));

const count;
console.log(count.toUpperCase());
Copy

Com o LSP ativo, quando o agente do OpenCode analisa este ficheiro, ele recebe automaticamente:

Diagnósticos (erros e warnings):

  • linha 12:7 — erro: 'count' is declared but its value is never read
  • linha 13:17 — erro: Property 'toUpperCase' does not exist on type 'undefined'
  • linha 6:3 — warning: Parameter 'user' implicitly has 'any' type (se strict mode)

Hover info sobre greet:

  • Assinatura: function greet(user: User): string
  • Documentação inline (se JSDoc estiver presente)

Autocomplete em user.:

  • name: string
  • email?: string | undefined

Code Actions disponíveis:

  • Adicionar tipo explícito ao count
  • Remover variável não utilizada

Isto significa que, mesmo antes de o agente responder, ele já sabe onde estão os erros, que tipos estão a ser usados, e o que pode ser melhorado. A resposta do agente é contextualizada e precisa — não é uma adivinhação.

Servidores LSP no OpenCode

OpenCode a mostrar diagnóstico LSP ativo e erros detetados no código

Dica: a documentação do OpenCode não lista um comando dedicado para veres o estado dos servidores LSP. Para confirmares que um arrancou, procura o processo com ps aux | grep -i lsp ou consulta a página de troubleshooting do OpenCode.


LSP vs MCP — Dois Protocolos que se Complementam

Se leste o nosso guia sobre MCP, deves estar a pensar: "Mas o LSP não é basicamente a mesma coisa que o MCP?"

A resposta curta: não. Mas são complementares. O LSP e o MCP partilham a mesma base (JSON-RPC 2.0) e a mesma filosofia de protocolo aberto, mas servem propósitos fundamentalmente diferentes.

LSP vs MCP

LSP vs MCP: dois protocolos, dois mundos, um ecossistema

Dimensão LSP MCP
Criado porMicrosoft (2016)Anthropic (2024)
PropósitoInteligência de códigoContexto e ações para LLMs
ClienteEditor/IDE (VS Code, Neovim, OpenCode)Aplicação de IA (Claude, OpenCode, Cline)
ServidorPor linguagem (typescript-language-server)Por domínio (filesystem, github, sentry)
Transportestdio / TCPstdio / SSE / Streamable HTTP
MensagenstextDocument/completion, hovertools/list, tools/call, resources/read
IniciativaDo editor (abrir ficheiro → pedir dados)Do LLM (decidir usar ferramenta)
OutputErros, tipos, sugestões de códigoDados de APIs, ficheiros, ações
TimingContínuo (sempre ativo enquanto editas)Sob demanda (quando o LLM decide)
MaturidadeMaduro (9+ anos, 13k+ estrelas no repositório da spec)Jovem (2 anos, a crescer depressa)

Como se complementam no OpenCode:

O LSP dá ao agente de IA uma compreensão profunda do código: "Aqui há um erro de tipo", "Esta função espera 3 parâmetros", "Este símbolo está definido neste ficheiro".

O MCP dá ao agente a capacidade de agir sobre o mundo exterior: "Lê este ficheiro", "Faz um commit", "Pesquisa na base de dados", "Cria um PR no GitHub".

No fundo, o LSP é o cérebro (compreensão) e o MCP é o músculo (ação). Um sem o outro é mais limitado; juntos, são uma combinação imbatível para assistência de código com IA.

Leitura recomendada: Vê o nosso guia completo sobre MCP para perceberes como configurar e criar os teus próprios servidores MCP. O LSP e o MCP são os dois pilares de qualquer setup sério de desenvolvimento assistido por IA.


Dicas e Boas Práticas

Depois de usar LSP com OpenCode no dia-a-dia, estas são as práticas que mais impacto tiveram na minha produtividade:

1. Ativa LSP por projeto, não globalmente

O LSP consome recursos — cada servidor é um processo separado. Num monorepo com TypeScript, Python e Rust, ter os três servidores ativos ao mesmo tempo pode consumir GB de RAM. Configura apenas os LSPs relevantes para cada projeto no opencode.json local.

// opencode.json (projeto TypeScript)
{
  "lsp": {
    "typescript": true
    // rust desativado, pyright desativado
  }
}
Copy

2. Confirma que o servidor arrancou

Quando um servidor LSP não está a funcionar como esperado, não há um comando dedicado para veres o estado — confirma que o processo arrancou (ps aux | grep -i lsp) e que o comando no opencode.json aponta para um binário que existe no PATH. A página de troubleshooting do OpenCode cobre os passos gerais de diagnóstico.

3. LSP vs CLI tools — escolhe a ferramenta certa

O LSP é excelente para feedback contínuo e em tempo real, mas para tarefas de verificação pontuais (como correr o type checker ou o linter), pode ser mais eficiente documentar comandos CLI no AGENTS.md. Por exemplo:

# Para verificar erros de tipo:
npm run typecheck

# Para lint:
npm run lint

# Para formatar:
npm run format
Copy

Isto permite ao agente executar verificações completas sob demanda, sem depender exclusivamente do LSP para tarefas que podem ser mais lentas ou inconsistentes.

4. Cuidado com servidores problemáticos

Alguns servidores LSP podem ter comportamentos inesperados — memory leaks, inicialização lenta, ou conflitos entre versões. Se notares que o OpenCode está lento ou a consumir demasiada RAM, verifica se há servidores LSP a acumular processos com ps aux | grep -i lsp.

O OpenCode pode lançar novos processos LSP sem limpar os anteriores em alguns cenários — se isso acontecer, desativa o servidor problemático com "disabled": true e usa apenas os que precisas.

5. Initialization options para servidores específicos

Alguns servidores LSP aceitam opções de inicialização que melhoram o comportamento no OpenCode. Por exemplo, o servidor TypeScript permite configurar preferências de importação:

{
  "lsp": {
    "typescript": {
      "command": ["typescript-language-server", "--stdio"],
      "initialization": {
        "preferences": {
          "importModuleSpecifierPreference": "relative",
          "includeCompletionsForModuleExports": true,
          "includeCompletionsWithInsertText": true
        }
      }
    }
  }
}
Copy

6. Combina LSP com instruções persistentes

Cria (ou junta a) um ficheiro AGENTS.md na raiz do projeto com instruções claras sobre como o agente deve usar o diagnóstico LSP — é esse ficheiro, não um .opencode/rules que não existe, que o OpenCode lê em todas as sessões:

# AGENTS.md (trecho)
## LSP
- Antes de responder a pedidos de revisão de código,
  verifica os diagnósticos LSP do ficheiro
- Se houver erros de tipo, prioriza a correção deles
- Usa code actions do LSP quando disponíveis
- Prefere usar `npm run typecheck` para validação final
Copy

7. Desativa LSP quando não precisas

Para projetos pequenos ou tarefas simples (como um script de bash), o LSP pode ser overkill. Desativa-o globalmente no teu ~/.config/opencode/opencode.json e ativa-o apenas nos projetos que realmente beneficiam dele:

// ~/.config/opencode/opencode.json (global — LSP desativado)
{
  "lsp": false
}

// /projeto-typescript/opencode.json (projeto — LSP ativo)
{
  "lsp": {
    "typescript": true
  }
}
Copy

Conclusão

O Language Server Protocol é uma peça fundamental no ecossistema de desenvolvimento moderno. O que começou como uma iniciativa da Microsoft para simplificar o VS Code tornou-se o standard universal para inteligência de código em todos os editores — e agora em agentes de IA como o OpenCode.

No OpenCode, o LSP é uma vantagem estratégica. Enquanto outros agentes de IA "adivinham" o que o código faz, o OpenCode sabe. Sabe onde estão os erros, que tipos cada variável tem, para onde cada função aponta, e o que precisa de ser corrigido.

O que fazer agora?

  • Se nunca usaste LSP no OpenCode, começa por ativar "lsp": true no teu opencode.json
  • Confirma que os servidores arrancaram com ps aux | grep -i lsp
  • Configura servidores específicos para os teus projetos (TypeScript, Python, Rust, Go, etc.)
  • Combina LSP com MCP — usa o nosso guia de MCP para configurares ferramentas externas
  • Junta-te à comunidade do OpenCode no Discord e partilha as tuas configurações

O desenvolvimento assistido por IA vai depender de modelos melhor informados mais do que de modelos maiores ou mais rápidos. E o LSP é a ponte que dá aos agentes de IA a compreensão que precisam para serem verdadeiramente úteis.


Recursos adicionais

Partilhar

Comentários 0

Ainda sem comentários — sê o primeiro.