-
-
Notifications
You must be signed in to change notification settings - Fork 4.8k
feat: Add MCP server #19592
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
feat: Add MCP server #19592
Conversation
✅ Deploy Preview for docs-eslint canceled.
|
Hi everyone, it looks like we lost track of this pull request. Please review and see what the next steps are. This pull request will auto-close in 7 days without an update. |
Still iterating on this. |
I've got this working and it's kind of fun. 😄 Also added setup docs. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After looking into this pull request I'm excited to see the new MCP server feature come to life. I left some comments.
Co-authored-by: Francesco Trotta <github@fasttime.org>
Okay, I removed the "lint and fix" tool. I also removed the prompts as it's unclear how this is intended to be used and I'd rather start small and add things later as we find their helpful. |
const eslint = new ESLint({ | ||
// enable lookup from file rather than from cwd | ||
flags: ["unstable_config_lookup_from_file"], | ||
}); | ||
|
||
const results = await eslint.lintFiles(filePaths); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In VS Code (I haven't checked other IDEs yet) the MCP server runs with cwd set to my user's home folder. This is reflected in the cwd
constructor option and it could affect how plugins work when files are linted. Are we comfortable with this? Alternatively we could set the current directory explicitly with process.chdir
to avoid surprises.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure there's anything we can do about this. I don't think we have a logical directory to pass to process.chdr()
.
As a note, this is why we need the unstable_config_lookup_from_file
flag passed to correctly find a config file for any files being linted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought that maybe we could set the current directory explicitly to os.homedir()
or to /
in case the server is started from a different location.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I this calling process.chdir()
is a bit dangerous. It's possible that they're still trying to figure out what the cwd
for MCP servers and I don't think we want to override that default.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like Cursor sets the cwd to the location of the Cursor executable. I'd say let's hold off on trying to change the directory. Maybe there's a way we can get the editor to give us a relevant directory.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Windsurf also passes its own cwd to the MCP server process. We can start with the editor default then.
### 1. Access Windsurf Settings | ||
|
||
Navigate to Windsurf - Settings > Advanced Settings, or open the Command Palette and select "Open Windsurf Settings Page". | ||
|
||
### 2. Add ESLint MCP Server | ||
|
||
Scroll down to the Cascade section and click the "Add Server" button. Then select "Add custom server +". |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably the UI is different for different operating systems or releases. For me in Windows the menu selection was File > Preferences > Windsurf Settings, then I clicked on the "Cascade" tab and the page scrolled down to that section directly.
lib/mcp/mcp-server.js
Outdated
const filePathsSchema = { | ||
filePaths: z | ||
.array( | ||
z | ||
.string() | ||
.min(1) | ||
.describe("Full filesystem path of a file to be analyzed"), | ||
) | ||
.nonempty(), | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After removing describe()
I'm still seeing the error "Invalid type for parameter 'filePaths' in tool lint-files" in Cursor, but now it's showing a button where I can start lint-files
anyway, and it seems to be working. So probably it's okay to keep it like this.
const eslint = new ESLint({ | ||
// enable lookup from file rather than from cwd | ||
flags: ["unstable_config_lookup_from_file"], | ||
}); | ||
|
||
const results = await eslint.lintFiles(filePaths); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Windsurf also passes its own cwd to the MCP server process. We can start with the editor default then.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This pull request adds an MCP server to ESLint that is triggered using the new CLI option "--mcp". The changes include new tests for the MCP server, updates to the CLI option parsing, and comprehensive documentation on configuring and using the MCP server.
- Added tests in tests/lib/mcp/mcp-server.js to validate MCP server behavior.
- Introduced a new CLI flag in lib/options.js and integrated the MCP server implementation in lib/mcp/mcp-server.js.
- Updated documentation in docs/src/use/mcp.md and docs/src/use/command-line-interface.md to guide users in configuring and using the MCP server.
Reviewed Changes
Copilot reviewed 8 out of 10 changed files in this pull request and generated no comments.
Show a summary per file
File | Description |
---|---|
tests/lib/mcp/mcp-server.js | New tests to verify the behavior of the MCP server and ESLint tool integration. |
tests/lib/cli.js | Removed extraneous commented separator lines. |
lib/options.js | Added conditional inclusion of the "--mcp" CLI flag when using flat config. |
lib/mcp/mcp-server.js | Implemented MCP server logic and tool registration for linting files. |
docs/src/use/mcp.md | Documentation for setting up and using the MCP server across various editors. |
docs/src/use/command-line-interface.md | Updated CLI documentation to include the new "--mcp" option. |
Files not reviewed (2)
- .temp-eslintsuppressions: Language not supported
- package.json: Language not supported
Comments suppressed due to low confidence (2)
tests/lib/mcp/mcp-server.js:60
- [nitpick] Consider adding tests to verify that the MCP server handles invalid or empty 'filePaths' inputs properly, ensuring robust validation of the provided schema.
describe("Tools", () => {
lib/options.js:216
- [nitpick] The '--mcp' flag is conditionally added only when using flat config. Confirm whether this behavior is intentional or if the flag should be available regardless of the config type to avoid potential inconsistencies in CLI usage.
let mcpFlag;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks! This is good enough for a start. I left some comments but I don't have any further suggestions at this time. I would like another review from a team member, if possible.
Oh, and we should probably add |
I opted to fix the test so that |
Ping @mdjermanovic. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This pull request introduces a new CLI option (--mcp) to start an MCP server for ESLint and adds the necessary integration for both internal tests and external documentation.
- Adds a new MCP server implementation and related tests
- Updates CLI options and documentation for MCP server usage across multiple editors
- Removes extraneous comment lines in the CLI tests to improve readability
Reviewed Changes
Copilot reviewed 9 out of 10 changed files in this pull request and generated no comments.
Show a summary per file
File | Description |
---|---|
tests/lib/mcp/mcp-server.js | New tests for validating MCP server behavior |
tests/lib/cli.js | Removed redundant separator comment |
lib/options.js | Added conditional definition of the mcpFlag option |
lib/mcp/mcp-server.js | New MCP server implementation exposing the "lint-files" tool |
docs/src/use/mcp.md | Added documentation for setting up the ESLint MCP server |
docs/src/use/command-line-interface.md | Updated CLI documentation for the new --mcp option |
Files not reviewed (1)
- package.json: Language not supported
Comments suppressed due to low confidence (2)
tests/lib/mcp/mcp-server.js:83
- [nitpick] Consider adding an inline comment to explain the rationale behind slicing the rawResults array to omit the header and footer, to enhance future maintainability.
const results = rawResults.slice(1, rawResults.length - 1)
lib/options.js:218
- [nitpick] Consider reviewing the conditional inclusion of the mcpFlag; verify if the MCP server option should also be available in non-flat config environments for consistency.
if (usingFlatConfig) {
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks!
While I think this change is awesome to have, it just introduced a ton of new dependencies for Please consider reverting this PR and invest into #19682 . |
If one doesn't use AI to read ESLint messages, why do they have to install all that? |
Watch the dependencies changed by this PR more intuitively, and almost doubles in both the number and size: |
There is a PR open for extracting it: #19699 |
Prerequisites checklist
What is the purpose of this pull request? (put an "X" next to an item)
[ ] Documentation update
[ ] Bug fix (template)
[ ] New rule (template)
[ ] Changes an existing rule (template)
[ ] Add autofix to a rule
[x] Add a CLI option
[ ] Add something to the core
[ ] Other, please explain:
What changes did you make? (Give an overview)
This change adds an MCP server that is triggered by
--mcp
. Because no other options are valid with this, I implemented it similar to--init
.The TypeScript SDK is a bit rough, so I had to work around a couple of things. Overall, everything works. You can test it out locally using the MCP inspector:
https://github.com/modelcontextprotocol/inspector
fixes #19588
Is there anything you'd like reviewers to focus on?