Skip to content

Language server protocol (LSP)

rumdl includes a built-in LSP server for real-time Markdown linting in your editor.

Starting the server

# Default: use stdio (for editor integration)
rumdl server

# With custom config
rumdl server --config .rumdl.toml

# Verbose logging (for debugging)
rumdl server --verbose

# TCP mode (for debugging)
rumdl server --port 9257

Capabilities

The rumdl LSP server provides:

  • Diagnostics: Real-time linting as you type
  • Code actions: Quick fixes for auto-fixable issues
  • Document formatting: Format entire document (rumdl fmt)
  • Range formatting: Format selected text
  • Completion: Language suggestions for fenced code blocks

Code block language completion

When typing a fenced code block, rumdl provides intelligent completions for language labels. Type ```py and completions will appear for languages starting with "py" (Python, etc.).

The completion uses GitHub Linguist data (799+ languages) and respects your MD040 configuration:

[MD040]
# Only suggest these languages
allowed-languages = ["Python", "JavaScript", "Rust"]

# Or exclude specific languages
disallowed-languages = ["HTML"]

# Prefer specific aliases
preferred-aliases = { Python = "py", JavaScript = "js" }

Features:

  • Triggers after ``` or ~~~ fence markers
  • Supports extended fences (4+ backticks for nested blocks)
  • Filters by allowed-languages and disallowed-languages
  • Prioritizes preferred-aliases in results
  • Shows canonical language name in completion details

Editor configuration

Neovim (nvim-lspconfig)

Add to your Neovim configuration:

-- if you do not use nvim-lspconfig, add this rumdl config
vim.lsp.config("rumdl", {
  cmd = { "rumdl", "server" },
  filetypes = { "markdown" },
  root_markers = { ".git" },
})

vim.lsp.enable("rumdl")

Helix

Add to languages.toml:

[language-server.rumdl]
command = "rumdl"
args = ["server"]

[[language]]
name = "markdown"
language-servers = ["rumdl"]
formatter = { command = "rumdl", args = ["check", "--fix", "--stdin"] }

Note: The [[language]] block replaces the Helix defaults. Add any other language servers you use (e.g., marksman) to the language-servers list. rumdl was merged into Helix's built-in config after the 25.07.1 release, so manual configuration will not be needed once the next Helix version ships.

VS Code

Install the rumdl VS Code extension from the marketplace.

The extension automatically manages the LSP server.

Zed

Add to your Zed settings:

{
  "lsp": {
    "rumdl": {
      "binary": {
        "path": "rumdl",
        "arguments": ["server"]
      }
    }
  },
  "languages": {
    "Markdown": {
      "language_servers": ["rumdl"]
    }
  }
}

Sublime Text (LSP package)

Add to LSP settings (Preferences > Package Settings > LSP > Settings):

{
  "clients": {
    "rumdl": {
      "enabled": true,
      "command": ["rumdl", "server"],
      "selector": "text.html.markdown"
    }
  }
}

Emacs (lsp-mode)

Add to your Emacs configuration:

(with-eval-after-load 'lsp-mode
  (add-to-list 'lsp-language-id-configuration '(markdown-mode . "markdown"))
  (lsp-register-client
   (make-lsp-client
    :new-connection (lsp-stdio-connection '("rumdl" "server"))
    :major-modes '(markdown-mode)
    :server-id 'rumdl)))

Emacs (eglot)

Add to your Emacs configuration:

(with-eval-after-load 'eglot
  (add-to-list 'eglot-server-programs
               '(markdown-mode . ("rumdl" "server"))))

Configuration

The LSP server uses the same configuration as the CLI. It automatically discovers .rumdl.toml or pyproject.toml in your project.

You can override the config path:

rumdl server --config /path/to/.rumdl.toml

Or use built-in defaults only:

rumdl server --no-config

Troubleshooting

Enable verbose logging

rumdl server --verbose

This outputs detailed logs to stderr, which most editors capture in their LSP logs.

Check server is working

Test the server manually:

echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"capabilities":{}}}' | rumdl server

You should see a JSON response with server capabilities.

Common issues

Diagnostics not appearing:

  • Ensure the file is recognized as Markdown (check file extension)
  • Check that rumdl is in your PATH
  • Look at your editor's LSP logs for errors

Wrong config being used:

  • Use --verbose to see which config file is loaded
  • Use --config to specify an explicit path
  • Use --no-config to ignore all config files

See also