What ESLint MCP Server Actually Is
ESLint MCP Server is a Model Context Protocol server that wraps ESLint's Node.js API and exposes it as MCP tools. When an AI assistant — Claude, Cursor, GitHub Copilot — connects to it, the assistant can lint files, retrieve violation details, inspect resolved ESLint configuration, and apply auto-fixes. All without leaving the conversation.
This matters because the typical AI coding workflow has a gap: the model writes code, you save the file, you run ESLint manually, you paste results back into chat, and the model tries again. ESLint MCP closes that loop. The agent lints the file itself, sees the exact violations, and iterates without you copying anything.
In one sentence: ESLint MCP Server turns ESLint into a tool an AI agent can call directly.
Why This Exists: The Problem It Solves
Linters are feedback loops. The faster you close the loop, the better the code quality. ESLint MCP compresses that loop from minutes to seconds inside an AI-assisted workflow.
Without it:
- AI generates code
- You save and run
npx eslint src/file.ts - You copy output into chat
- AI suggests a fix
- Repeat
With ESLint MCP:
- AI generates code
- AI calls
lint_filetool - AI sees violations inline
- AI fixes and re-lints in the same turn
For developers using Cursor agents, Claude Code, or Copilot's agent mode to write non-trivial features, this is the difference between an agent that ships clean code and one that ships code you have to clean up afterward.
Architecture: How the Pieces Connect
┌─────────────────────────────────────────────────────────────┐
│ Your Development Machine │
│ │
│ ┌──────────────────┐ MCP (JSON-RPC over stdio) │
│ │ AI Client │◄────────────────────────────────┐ │
│ │ (Claude / Cursor │ │ │
│ │ / Copilot) │────────────────────────────────►│ │
│ └──────────────────┘ │ │
│ │ │
│ ┌─────────┴──┐ │
│ │ ESLint │ │
│ │ MCP │ │
│ │ Server │ │
│ └─────┬──────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────┐│
│ │ ESLint Node API││
│ │ (local or ││
│ │ bundled) ││
│ └────────┬────────┘│
│ │ │
│ ▼ │
│ ┌─────────────────┐│
│ │ Your Project ││
│ │ Files + ││
│ │ eslint.config.js││
│ │ (or .eslintrc) ││
│ └─────────────────┘│
└─────────────────────────────────────────────────────────────┘
The transport layer is stdio — the MCP client spawns the server as a child process and communicates over stdin/stdout using JSON-RPC messages. There is no HTTP server, no port, no network exposure. This is the correct architecture for local developer tooling.
The server resolves ESLint from your project's node_modules. This means it respects your installed version, your eslint.config.js or .eslintrc.*, and your plugins. It behaves identically to running npx eslint yourself.
Available MCP Tools
The ESLint MCP Server exposes three primary tools:
| Tool | Description | Key Parameters |
|---|---|---|
lint_file | Lint a single file and return violations | filePath, fix (boolean) |
lint_text | Lint raw text content with a specified file extension | text, fileExt, fix |
get_eslint_config | Retrieve the resolved ESLint config for a file | filePath |
lint_file is the workhorse. lint_text is useful when you want to lint code snippets that don't exist on disk yet. get_eslint_config helps agents understand which rules apply before suggesting changes — a technique that produces significantly better code generation.
Prerequisites
Before you install the server:
- Node.js 18+ — the server uses modern Node.js APIs
- ESLint installed locally in your project (
npm install --save-dev eslint) - An ESLint config file:
eslint.config.js,eslint.config.mjs,.eslintrc.json, or.eslintrc.js - An MCP-compatible client (Claude Desktop, Claude Code, Cursor, VS Code + Copilot)
You do not need ESLint installed globally. Local installation is preferred and produces more predictable results.
Installation
Option 1: Run with npx (Zero Installation)
The fastest way to try it:
npx @eslint/mcp@latest
This downloads and runs the server without adding it to your project. Useful for evaluating before committing, but npx re-downloads on each invocation if the cache is cold. For day-to-day use, install it explicitly.
Option 2: Local Project Installation
npm install --save-dev @eslint/mcp
Then reference it in your MCP client config as:
{
"command": "node",
"args": ["./node_modules/@eslint/mcp/bin/eslint-mcp.js"]
}
Option 3: Global Installation
npm install -g @eslint/mcp
Useful if you work across many projects and want a single installation. The tradeoff: you need to keep it updated manually, and it still resolves ESLint from each project's local node_modules.
Configuring Your MCP Client
Claude Desktop
Open your Claude Desktop config file:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
Add the ESLint server under mcpServers:
{
"mcpServers": {
"eslint": {
"command": "npx",
"args": ["-y", "@eslint/mcp@latest"],
"cwd": "/path/to/your/project"
}
}
}
The cwd field is critical. It sets the working directory for the server process, which determines where ESLint looks for config files and resolves local node_modules. Always point it at your project root.
Restart Claude Desktop after saving. You should see the ESLint tools appear in the tool panel.
Claude Code
Claude Code supports MCP natively via its CLI. Add the server to your project:
claude mcp add eslint -- npx -y @eslint/mcp@latest
To scope it to the current project only:
claude mcp add --scope project eslint -- npx -y @eslint/mcp@latest
This writes the config to .claude/mcp.json in your project root, which you can commit to version control so every team member gets the server automatically when using Claude Code.
Verify it registered:
claude mcp list
You should see eslint listed with status connected.
Cursor
Open Cursor Settings → MCP → Add new global MCP server and paste:
{
"mcpServers": {
"eslint": {
"command": "npx",
"args": ["-y", "@eslint/mcp@latest"]
}
}
}
Cursor automatically uses the workspace root as the working directory, so you typically don't need to specify cwd. However, if you're working in a monorepo and want ESLint to resolve from a specific package, set cwd explicitly to that package path.
Alternatively, create a .cursor/mcp.json file in your project root for project-scoped configuration:
{
"mcpServers": {
"eslint": {
"command": "node",
"args": ["./node_modules/@eslint/mcp/bin/eslint-mcp.js"]
}
}
}
Using ./node_modules/ here means the server runs the exact version you've installed and audited, not whatever npx resolves at runtime.
VS Code + GitHub Copilot
VS Code added MCP support in version 1.99. To configure ESLint MCP:
- Open VS Code Settings (⌘, on macOS)
- Search for
mcp - Click Edit in settings.json
Add to your workspace or user settings.json:
{
"mcp": {
"servers": {
"eslint": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@eslint/mcp@latest"],
"cwd": "${workspaceFolder}"
}
}
}
}
The ${workspaceFolder} variable resolves to your open workspace root — correct behavior for most single-project setups.
For Copilot to use the tool, invoke it from Copilot Chat in Agent mode (@workspace or agent panel). Copilot's standard inline completions do not invoke MCP tools — only the agent/chat interface does.
You can also add this to .vscode/settings.json and commit it to your repo, giving the whole team the MCP server automatically:
{
"mcp": {
"servers": {
"eslint": {
"type": "stdio",
"command": "node",
"args": ["./node_modules/@eslint/mcp/bin/eslint-mcp.js"]
}
}
}
}
Verifying the Server Is Working
Before trusting any MCP server in your workflow, verify it is registered and responding correctly.
From Claude Desktop or Claude Code, ask in chat:
"What MCP tools do you have available?"
You should see lint_file, lint_text, and get_eslint_config listed.
Quick smoke test — ask the AI:
"Use lint_file to lint src/index.ts and show me any violations."
If it returns results (or confirms zero violations), the server is connected and ESLint is resolving correctly.
From the terminal, you can also test the JSON-RPC interface directly:
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' | npx @eslint/mcp@latest
You should receive a JSON response listing the available tools with their input schemas.
Trust but verify: Before adding any MCP server to your toolchain, check it against the MCPForge Verify tool. It scans packages for known security issues, suspicious dependencies, and community trust signals. The ESLint MCP Server is published by the ESLint team — it's trustworthy — but building this habit protects you when evaluating third-party servers.
Real Linting Workflows
Workflow 1: AI-Driven Code Review with Lint Feedback
This is the killer use case. You ask an AI agent to implement a feature, and it lints its own output before presenting it to you.
Prompt:
"Implement a React hook that fetches user data. After writing it, lint the file and fix any ESLint violations before showing me the result."
The agent:
- Writes
useUserData.ts - Calls
lint_filewithfix: falseto see violations - Applies fixes
- Calls
lint_fileagain to confirm zero violations - Shows you the clean file
This works best when you also ask the agent to call get_eslint_config first, so it understands which rules are active for that file type.
Workflow 2: Migrating to Strict Rules
When adopting a stricter ESLint config, your codebase probably has hundreds of violations. Use an agent to work through them systematically:
For each file in src/:
1. Call lint_file
2. Analyze violations that can't be auto-fixed
3. Suggest refactors
4. Apply fixes
5. Verify with lint_file again
This is tedious to do manually, but an agent with ESLint MCP access can process files in batch while you review the diffs.
Workflow 3: Config Validation During Setup
When setting up a new ESLint config, use get_eslint_config to verify rules are resolving as expected:
"Call get_eslint_config for src/components/Button.tsx and confirm that the @typescript-eslint/no-explicit-any rule is set to error."
This is faster than reading the merged flat config output from eslint --print-config.
Workflow 4: Pre-Commit Lint in Agent Workflows
In automated agentic pipelines (not just interactive chat), include a lint step:
{
"steps": [
{ "action": "write_file", "path": "src/service.ts" },
{ "action": "call_tool", "tool": "lint_file", "params": { "filePath": "src/service.ts", "fix": true } },
{ "action": "verify_no_violations" }
]
}
If lint violations remain after auto-fix, the pipeline fails and the agent knows to revise before proceeding.
Flat Config vs Legacy Config
ESLint v9 made flat config (eslint.config.js) the default. ESLint MCP Server handles both, but there are behavioral differences worth understanding.
| Aspect | Legacy (.eslintrc) | Flat Config (eslint.config.js) |
|---|---|---|
| Auto-detection | Based on file presence | Preferred in ESLint v9+ |
| File resolution | Cascades up directory tree | Single root config |
| Plugin loading | Via plugins array with strings | Via ESLint v9 plugin API |
| MCP compatibility | Full | Full |
get_eslint_config output | Per-rule with severity | Flat rule object |
If you're on ESLint v9 and still using .eslintrc, you're running in compatibility mode via @eslint/eslintrc. This works, but you'll see deprecation warnings. ESLint MCP works in both modes.
For new projects, use flat config:
// eslint.config.js
import js from '@eslint/js';
import tseslint from 'typescript-eslint';
export default [
js.configs.recommended,
...tseslint.configs.recommended,
{
files: ['**/*.ts', '**/*.tsx'],
rules: {
'@typescript-eslint/no-explicit-any': 'error',
'@typescript-eslint/prefer-nullish-coalescing': 'warn',
},
},
{
ignores: ['dist/**', 'node_modules/**'],
},
];
Common Mistakes and How to Avoid Them
Mistake 1: Wrong Working Directory
Symptom: ESLint returns no results or throws "No ESLint configuration found."
Why it happens: The MCP server started from a directory that doesn't contain your ESLint config. This happens when cwd isn't set or is set to the wrong path.
Fix:
{
"command": "npx",
"args": ["-y", "@eslint/mcp@latest"],
"cwd": "/absolute/path/to/your/project"
}
Always use absolute paths in cwd. Relative paths behave differently across MCP clients.
Mistake 2: File Path Not Relative to Project Root
Symptom: lint_file returns an error like "File not found" or produces wrong results.
Why it happens: The agent passes an absolute path or a path relative to its own working context, not the server's cwd.
Fix: Instruct the agent explicitly:
"When calling lint_file, use paths relative to the project root (e.g., src/components/Button.tsx, not /Users/you/project/src/components/Button.tsx)."
You can enforce this in a system prompt if you're building an automated agent.
Mistake 3: ESLint Version Mismatch
Symptom: The server starts but rules don't match what you see in your editor or CI.
Why it happens: There are multiple ESLint installations — global, local, and potentially one bundled with the MCP server — and the wrong one is being used.
Fix: Ensure ESLint is installed locally and the server is started from the project root. Confirm with:
node -e "const {ESLint} = require('eslint'); console.log(new ESLint().version)"
Run this from your project root to see which version resolves.
Mistake 4: Flat Config Not Detected
Symptom: On ESLint v9, rules from eslint.config.js are ignored.
Why it happens: The MCP server is using ESLint in legacy mode, bypassing your flat config.
Fix: Ensure you're on @eslint/mcp version 0.1.0 or later, which has proper flat config detection. Also confirm your config file is named exactly eslint.config.js or eslint.config.mjs — ESLint v9 is picky about filenames.
Mistake 5: fix: true Writing Unexpected Changes
Symptom: Files are modified in unexpected ways after lint_file with auto-fix.
Why it happens: Auto-fix applies all fixable rules, which might reformat code, reorder imports, or change quotes — all correct per your config but surprising if you didn't expect it.
Fix: Run lint_file with fix: false first to review violations. Only enable fix: true after confirming the changes are acceptable. In agentic workflows, always diff the result before committing.
Mistake 6: Ignoring Plugin Resolution Errors
Symptom: Server starts but certain rules produce errors like "Definition for rule 'react/prop-types' was not found."
Why it happens: ESLint plugins need to be installed in the project's node_modules. If eslint-plugin-react isn't installed, those rules can't run.
Fix:
npm install --save-dev eslint-plugin-react
Check your package.json to ensure all plugins referenced in your ESLint config are listed as devDependencies.
Troubleshooting
Server Doesn't Appear in Tool List
- Check the MCP client logs. In Claude Desktop: Help → MCP Logs. In Cursor: View → Output → MCP.
- Confirm the command resolves: run
npx @eslint/mcp@latestmanually in your terminal from the same directory. - Check for JSON syntax errors in your config file — a single misplaced comma breaks everything.
- Restart the MCP client after config changes. Most clients don't hot-reload server configs.
Server Starts But Tools Return Errors
Enable debug logging by setting the DEBUG environment variable:
{
"mcpServers": {
"eslint": {
"command": "npx",
"args": ["-y", "@eslint/mcp@latest"],
"env": {
"DEBUG": "eslint:*"
}
}
}
}
This surfaces ESLint's internal resolution process, showing exactly which config file it found and which rules it loaded.
npx Is Slow to Start
npx checks for updates on every invocation. For faster startup:
- Install
@eslint/mcplocally and reference./node_modules/@eslint/mcp/bin/eslint-mcp.jsdirectly. - Or use
npx --no-install @eslint/mcp(only works if already cached).
Local installation is faster, more reproducible, and lets you pin a specific version.
Flat Config Parse Errors
If your eslint.config.js uses top-level await or modern syntax, ensure the server runs on Node.js 18+. Check:
node --version
Also verify your config file doesn't have syntax errors by running:
node eslint.config.js
If this throws, the MCP server won't be able to load it either.
Monorepo: Wrong Config Being Resolved
In a monorepo with package-level ESLint configs, the server resolves config based on its cwd. If you start it from the repo root but want package-level rules, you have two options:
Option A: Run per-package servers with cwd set to each package:
{
"mcpServers": {
"eslint-frontend": {
"command": "npx",
"args": ["-y", "@eslint/mcp@latest"],
"cwd": "/path/to/repo/packages/frontend"
},
"eslint-backend": {
"command": "npx",
"args": ["-y", "@eslint/mcp@latest"],
"cwd": "/path/to/repo/packages/backend"
}
}
}
Option B: Use a root-level flat config with per-package overrides and run a single server from the root.
Security Considerations
ESLint MCP Server is a local stdio server, which limits its attack surface. But there are real security considerations:
File System Access
The server reads files from your project directory via ESLint's API. It cannot write files unless fix: true is passed explicitly. However, it can read any file ESLint can read, which includes potentially sensitive .env or config files if they match lint patterns.
Mitigation: Ensure your .eslintignore or flat config ignores array excludes sensitive files.
Supply Chain Risk
MCP servers run as local processes with your user's permissions. A malicious MCP server package could exfiltrate files or execute arbitrary code.
Always verify MCP packages before installing. The MCPForge verified directory lists MCP servers that have passed trust and security checks. For the official ESLint MCP Server, published by the ESLint organization on npm, you're in safe hands — but make this verification a habit for any MCP server you add.
AI-Controlled Fix Operations
When an AI agent calls lint_file with fix: true, it directly modifies files on disk. In interactive workflows this is fine — you're reviewing changes. In fully automated pipelines, implement guardrails:
- Always run in a git worktree or checkout
- Diff results before committing
- Require human approval for fixes on production branches
No Network Exposure
The stdio transport means there's no port, no HTTP server, and no network exposure. This is the correct architecture for local tooling. If someone proposes an ESLint MCP server that runs over HTTP/SSE for local use, treat that as a red flag.
Production Recommendations
If you're rolling this out across a team or embedding it in an agentic pipeline:
Pin the Version
Don't use @eslint/mcp@latest in team configs. Pin to a specific version:
{
"args": ["-y", "@eslint/mcp@0.1.0"]
}
Or install locally and commit your package-lock.json. This prevents unexpected behavior when the package updates.
Commit MCP Config to Version Control
For Claude Code, commit .claude/mcp.json. For VS Code + Copilot, commit .vscode/settings.json with the MCP block. This gives every developer on your team the server automatically without individual setup.
# .claude/mcp.json
{
"mcpServers": {
"eslint": {
"command": "node",
"args": ["./node_modules/@eslint/mcp/bin/eslint-mcp.js"]
}
}
}
Using the local node_modules path here ensures everyone uses the version installed by npm install, controlled by your package.json.
Add to onboarding docs
Document which MCP servers your team uses in your engineering onboarding guide. Developers joining the team shouldn't have to discover this through word of mouth.
Keep ESLint Aligned Across Environments
The version of ESLint used by the MCP server, your editor extension, and your CI pipeline should be identical. Divergence causes confusing "works on my machine" lint failures.
// package.json
{
"devDependencies": {
"eslint": "^9.17.0",
"@eslint/mcp": "^0.1.0"
}
}
Lock these in package.json and commit package-lock.json.
Monitor Agent Behavior
In agentic workflows, log which files the agent lints and whether it applies auto-fixes. Unexpected fix patterns (touching files outside the feature scope) indicate a prompt or agent design issue, not an ESLint issue.
ESLint MCP vs Running ESLint Directly
Knowing when to use the MCP server versus a direct CLI call matters:
| Scenario | ESLint MCP Server | Direct CLI (npx eslint) |
|---|---|---|
| AI agent needs lint results | ✅ Ideal | ❌ Agent can't run CLI |
| Interactive AI coding session | ✅ Best fit | ❌ Breaks conversation flow |
| CI/CD pipeline | ⚠️ Overkill | ✅ Simpler and faster |
| Pre-commit hook | ⚠️ Overhead | ✅ Use lint-staged |
| Batch-fixing hundreds of files | ⚠️ Possible but slow | ✅ eslint --fix '**/*.ts' |
| Understanding resolved config | ✅ Via get_eslint_config | ✅ eslint --print-config |
| Team onboarding / consistent setup | ✅ Commit MCP config | ✅ Commit .eslintrc |
The MCP server shines in interactive AI contexts. Direct CLI is still the right tool for CI, pre-commit hooks, and bulk operations.
Example: Complete Project Setup
Here's a complete, production-ready setup for a TypeScript project with flat config:
1. Install dependencies:
npm install --save-dev eslint @eslint/js typescript-eslint @eslint/mcp
2. Create eslint.config.js:
// eslint.config.js
import js from '@eslint/js';
import tseslint from 'typescript-eslint';
export default [
js.configs.recommended,
...tseslint.configs.strictTypeChecked,
{
languageOptions: {
parserOptions: {
project: true,
tsconfigRootDir: import.meta.dirname,
},
},
},
{
files: ['**/*.ts', '**/*.tsx'],
rules: {
'@typescript-eslint/no-explicit-any': 'error',
'@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
'no-console': ['warn', { allow: ['error', 'warn'] }],
},
},
{
ignores: ['dist/**', 'node_modules/**', '**/*.d.ts'],
},
];
3. Create .claude/mcp.json (Claude Code):
{
"mcpServers": {
"eslint": {
"command": "node",
"args": ["./node_modules/@eslint/mcp/bin/eslint-mcp.js"]
}
}
}
4. Create .vscode/settings.json (VS Code + Copilot):
{
"mcp": {
"servers": {
"eslint": {
"type": "stdio",
"command": "node",
"args": ["./node_modules/@eslint/mcp/bin/eslint-mcp.js"]
}
}
}
}
5. Commit everything:
git add eslint.config.js .claude/mcp.json .vscode/settings.json package.json package-lock.json
git commit -m "feat: add ESLint flat config and MCP server setup"
Every team member who clones the repo and runs npm install gets a fully working ESLint MCP setup.
Recent Changes in the ESLint MCP Ecosystem
The @eslint/mcp package is actively maintained by the ESLint core team. Key developments:
- Flat config support is stable as of v0.1.0, coinciding with ESLint v9's promotion of flat config as the default.
- VS Code MCP support landed in VS Code 1.99 (April 2025), making the Copilot integration possible without third-party extensions.
- Claude Code added first-class MCP project scoping (
--scope project) in early 2025, making team-committed configs practical. - Cursor MCP support has been stable since late 2024 and supports both global and project-scoped server definitions.
Check the official @eslint/mcp GitHub repository for the latest changelog before pinning a version in production.
Want to analyze your API security?
Import your OpenAPI spec and generate a Security Report automatically.
Key Takeaways
- ESLint MCP Server is the official MCP integration from the ESLint team, exposing
lint_file,lint_text, andget_eslint_configas AI-callable tools - Always set
cwdto your project root in the MCP client config — this is the single biggest source of misconfiguration - Use local installation (
./node_modules/@eslint/mcp/) over npx in team environments for speed, reproducibility, and version control - Commit MCP config files (
.claude/mcp.json,.vscode/settings.json) to version control so the whole team benefits without manual setup - The MCP server is a local stdio process with no network exposure — secure by default, but still verify packages before installing via MCPForge Verify
- Use the server in interactive AI workflows; use
npx eslintdirectly in CI and pre-commit hooks - ESLint v9 flat config works fully with the MCP server — prefer it for new projects