Skip to content

feat(lsp): non-blocking startup so slow-to-initialize LSP servers (large OmniSharp/Unity solutions) don't time out #172

Description

@xldeveloper

Problem

Driving OmniSharp (Windows .NET Framework build, via Visual Studio MSBuild) against a large Unity solution (~130 C# projects) makes mcpls unusable. Four distinct issues compound:

  1. Hardcoded 30 s initialize timeoutlsp/lifecycle.rs uses Duration::from_secs(30) for the initialize request regardless of the configured timeout_seconds. OmniSharp needs ~86 s to load the solution before answering initialize, so it is always killed mid-load.
  2. Bare null JSON-RPC messages at startup — OmniSharp emits non-object JSON-RPC messages during startup; the receive loop treats them as a protocol error and exits, dropping the connection.
  3. MCP startup blocked on LSP initserve_with awaits LSP initialization before starting the MCP server, so the MCP initialize response is blocked for the whole LSP load. Clients (e.g. Claude Code) time out the initialize request at ~60 s → MCP error -32001: Request timed out.
  4. Misleading error while loading — a request for a configured language whose server is still initializing returns "no LSP server configured", implying misconfiguration rather than "still loading".

Proposed fix

  • Honor the per-server timeout_seconds for the initialize handshake (not a hardcoded 30 s).
  • Skip non-object JSON-RPC messages and keep reading.
  • Start the MCP server immediately and initialize LSP servers in a background task; register them into the shared translator once ready.
  • Add a ServerInitializing error ("still initializing, wait and retry") for requests that arrive during the load window. This requires marking Error #[non_exhaustive] — a breaking change for downstream crates that match it exhaustively (they must add a wildcard arm), mirroring the existing InboundMessage precedent.

Validation

Verified end-to-end against OmniSharp on a 133-project Unity solution via Claude Code: MCP initialize returns immediately, OmniSharp finishes loading (~86 s) in the background, and get_references / rename_symbol work once loaded.

A PR implementing this is ready to follow.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions