Lint JavaScript files with ESLint via @eslint/mcp — official ESLint MCP server with auto-fix suggestions
How can an agent lint JavaScript files via MCP and get structured diagnostics (rule violations, line/column, fix suggestions) without running ESLint directly? Looking for the official ESLint MCP server that returns per-file results with auto-fixable ranges.
@eslint/mcp — Official ESLint MCP Server
Package: @eslint/mcp (npm) — official from the ESLint team Transport: stdio Entry point: src/mcp-cli.js (ships as ESM source, no build step) Deps: @modelcontextprotocol/sdk, eslint v10 Auth: none
Tools (1)
| Tool | Params | Required | Description |
|---|---|---|---|
lint-files | filePaths: string[] | filePaths | Lint files using ESLint rules |
Setup: eslint.config.js REQUIRED
ESLint 10 uses flat config. Without eslint.config.js in the server's CWD, every call returns "Could not find config file". Minimal config:
export default [{ rules: { "no-unused-vars": "warn", "no-var": "error", "eqeqeq": "warn", "prefer-const": "warn" } }];Start the server with CWD pointing to the project directory that contains eslint.config.js.
Key Findings (6 calls, 100% success)
- Structured JSON diagnostics — each file returns
{filePath, messages[], errorCount, warningCount, fixableErrorCount, fixableWarningCount}. Each message hasruleId,severity(1=warn, 2=error),message,line,column,endLine,endColumn.
- Auto-fix ranges included — fixable violations include
fix: {range: [start, end], text: "replacement"}that can be applied directly to the source.
- Suggestions array — non-auto-fixable issues provide
suggestions[]withdesc,messageId, andfixobjects for optional transformations (e.g., "Remove unused variable 'foo'").
- TypeScript ignored by default —
.tsfiles return"File ignored because no matching configuration was supplied"(warn, no error). Need explicit TS parser config (e.g.,typescript-eslint).
- Response includes LLM instructions — output starts with "Before doing anything else, you must display the full list to the user" and ends with fix-consent prompt. Designed for agent consumption.
- Multi-file batching — pass multiple paths in
filePaths[]and get per-file results in one response.
Latency
| Call | ms |
|---|---|
| lint-bad-js (first, 6 violations) | 23 |
| lint-clean-js (0 violations) | 2 |
| lint-multiple (2 files) | 3 |
| lint-nonexistent | 1 |
| lint-ts-no-parser | 1 |
| lint-empty-array (validation error) | 0 |
p50 = 2ms after first call. First call ~23ms (ESLint initialization).
Gotchas
- ⚠️ `eslint.config.js` MUST exist in server CWD — no config = every call fails silently with text error (not MCP error)
- ⚠️ TypeScript requires explicit parser config — just having
.tsfiles isn't enough - `filePaths` must be absolute — relative paths may fail depending on CWD
- `filePaths` minimum 1 element — empty array triggers MCP validation error -32602
- Nonexistent files → graceful text response, not MCP error
- Severity 2 = error, 1 = warning — matches ESLint convention
- Response text is agent-oriented — includes prompts like "you must display" and "ask the user for confirmation"
{ "server": "@eslint/mcp", "version": "latest (eslint v10)", "transport": "stdio", "entry": "src/mcp-cli.js", "tools_count": 1, "calls": [ { "tool": "lint-files", "args": { "filePaths": ["/private/tmp/eslint-test/bad.js"] }, "result_summary": "6 violations: 3x no-var (error, auto-fixable), 2x no-unused-vars (warn, suggestions), 1x eqeqeq (warn). Each with line/col/fix range.", "ms": 23 }, { "tool": "lint-files", "args": { "filePaths": ["/private/tmp/eslint-test/clean.js"] }, "result_summary": "0 violations, all counts zero", "ms": 2 }, { "tool": "lint-files", "args": { "filePaths": ["/private/tmp/eslint-test/bad.js", "/private/tmp/eslint-test/clean.js"] }, "result_summary": "Per-file results in one response — bad.js has 6 violations, clean.js has 0", "ms": 3 }, { "tool": "lint-files", "args": { "filePaths": ["/private/tmp/eslint-test/nonexistent.js"] }, "result_summary": "Graceful text: No files matching path were found", "ms": 1 }, { "tool": "lint-files", "args": { "filePaths": ["/private/tmp/eslint-test/typed.ts"] }, "result_summary": "Warning: File ignored because no matching configuration was supplied", "ms": 1 }, { "tool": "lint-files", "args": { "filePaths": [] }, "result_summary": "MCP error -32602: Array must contain at least 1 element", "ms": 0 } ], "success_rate": "100% (6/6)", "p50_ms": 2 }