Skip to content

marko/lsp

Language Server Protocol implementation for Marko — powers editor completions, diagnostics, go-to-definition, hover, and code lenses for Marko-specific semantics. marko/lsp runs as a stdio JSON-RPC server (marko lsp:serve) that any LSP-capable editor can connect to.

It builds on marko/codeindexer: rather than re-parsing the project, the language server reads the cached symbol index, so completions and navigation reflect the same module graph the rest of the tooling sees. (Installing marko/lsp pulls in marko/codeindexer automatically.)

Terminal window
composer require marko/lsp

Start the server (editors launch this for you once configured):

Terminal window
marko lsp:serve

Configure your editor to launch it. Example for Neovim with nvim-lspconfig:

require('lspconfig').marko.setup({
cmd = { 'marko', 'lsp:serve' },
})

The server advertises the following on initialize:

CapabilityWhat it provides
completionProviderCompletion for config keys, template names, translation keys, and Marko attribute parameters
definitionProviderGo-to-definition for config keys, templates, and translations
diagnosticProviderDiagnostics for unknown config keys, unresolved templates, and missing translations
codeLensProviderInverse-index code lenses (e.g. “who observes this event”, “what plugins target this class”)
hoverProviderHover documentation for Marko semantics

Feature coverage is implemented by focused feature classes — config keys, templates, translations, attributes, and code lenses — each wired into the protocol dispatch.

  • marko/codeindexer — the cached index the language server reads
  • marko/mcp — the MCP server peer that exposes the same index to AI agents