Skip to content

feat: diagnostics tool implementation #34

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

krmcbride
Copy link

I've been tinkering around with fully implementing the getDiagnostics tool and have things basically working in a similar fashion to how they do in VSCode.

One little improvement I've made over the VSCode behavior is, when you ask about diagnostics in a file that doesn't have a buffer open, rather than lying to you and telling you the file is clean, it'll return a MCP error to indicate it can't return diagnostics for files without a buffer.

Summary

Add getDiagnostics tool for retrieving LSP diagnostics from Neovim

Details

  • Implements MCP-compatible getDiagnostics tool that retrieves LSP diagnostics (errors, warnings) from open
    buffers
  • Supports optional uri parameter to filter diagnostics for a specific file
  • Returns diagnostics in MCP content format with JSON-encoded diagnostic information
  • Converts 0-indexed Neovim diagnostic positions to 1-indexed for better user experience (matching editor line
    numbers)
  • Includes comprehensive error handling for unopened files and missing LSP/diagnostic APIs
  • Adds full test coverage for all functionality including URI filtering and edge cases

Copy link
Member

@ThomasK33 ThomasK33 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for opening this PR; it looks very nice.

Please make sure to fix the luacheck errors so that CI can pass.

Also left some review comments on the changes.

Comment on lines 66 to 64
error({
code = -32001,
message = "File not open in buffer",
data = "File must be open in Neovim to retrieve diagnostics: " .. filepath,
})
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note to myself: Refactor the error returning in this file, as in the rest of the codebase, we return errors as values.

Comment on lines 55 to 59
local uri = params.uri
local filepath = uri
if uri:sub(1, 7) == "file://" then
filepath = uri:sub(8) -- Remove "file://" prefix
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use vim.uri_to_fname here instead?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Since uri_to_fname throws if the input doesn't have a scheme I went back and forth on how defensive to be, but ended up going with the simplest/least defensive approach of just blindly passing whatever uri is into it assuming it will always be a proper file URI.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's fine, simple is good for now.
If we're trying to be defensive here, we might also wrap it in a pcall and check if it's ok.

Comment on lines 35 to 42
local log_module_ok, log = pcall(require, "claudecode.logger")
if not log_module_ok then
return {
code = -32603, -- Internal error
message = "Internal error",
data = "Failed to load logger module",
}
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that we have to pcall this.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I confess to copy/pasta on this from close_tab, fyi 🙈

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In that case, I'll have to take a look and do some refactoring. Thanks for the mention 👍

@krmcbride krmcbride force-pushed the diag-tool branch 2 times, most recently from 27989b6 to 069e061 Compare June 14, 2025 01:59
@krmcbride
Copy link
Author

Something interesting happened as I was testing this just now -- Claude started adding 1 to line and character numbers on its own, so everything it mentioned was off by one (since I'm already compensating for this). So I asked it what the hell it was doing (because I could see the MCP diag tool response body was accurate) and it said that since it was Neovim LSP diagnostics, and those are 0-indexed, it was adding 1 to everything for me...

So... I've removed any mention of neovim LSP from the things Claude can see in the diagnostic tool 😆

We're living in a weird new world

@ThomasK33
Copy link
Member

You'll need to update the tests, as they are still expecting the old string values containing Neovim references.
Apart from that, it looks good to me.

@krmcbride
Copy link
Author

You'll need to update the tests, as they are still expecting the old string values containing Neovim references. Apart from that, it looks good to me.

Oops! OK, should be g2g

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants