resharper-cli-mcp
Runs JetBrains ReSharper command-line tools to inspect code for issues and apply code cleanup to .NET solutions.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@resharper-cli-mcpinspect the solution for code issues"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
resharper-cli-mcp
resharper-cli-mcp is an MCP server that runs JetBrains' ReSharper command-line tools and exposes them to C# coding agents over stdio. It is unofficial — not affiliated with or endorsed by JetBrains.
It gives an agent two things a text search cannot: a real ReSharper inspection of your solution (resharper_inspect), and ReSharper's own code cleanup applied in place (resharper_cleanup). The server shells out to a jb you install yourself, and bundles no JetBrains software.
Quickstart
The server needs the .NET 10 SDK and JetBrains' ReSharper Command Line Tools. Both install as .NET global tools, and neither needs an IDE.
dotnet tool install -g JetBrains.ReSharper.GlobalTools
dotnet tool install -g Zphil.ReSharperCliRegister the server with your MCP client under the command resharper-cli-mcp. For Claude Code, add it to .mcp.json:
{
"mcpServers": {
"resharper": {
"command": "resharper-cli-mcp"
}
}
}The server finds a single .sln/.slnx in its working directory. When that directory holds zero or several, set JB_SOLUTION_PATH in the config's env block or pass solutionPath on the call.
VS Code and Cursor users can add the server in one click, once both tools are installed:
Related MCP server: lsp-tools-mcp
Install as a Claude Code plugin
Claude Code users can install everything in one step instead of editing .mcp.json by hand. This repository doubles as a single-plugin marketplace, so the tools, the derive_style_guide prompt, and both guide resources — resharper://guides/configuration for what ReSharper enforces and resharper://guides/setup for running the server — arrive together:
/plugin marketplace add andypgray/resharper-cli-mcp
/plugin install resharper-cli-mcp@resharper-cli-mcpThe plugin starts the server with dotnet dnx, which fetches Zphil.ReSharperCli from NuGet on first use — so you skip dotnet tool install for the wrapper itself. You still need the .NET 10 SDK and JetBrains' ReSharper Command Line Tools (dotnet tool install -g JetBrains.ReSharper.GlobalTools), which this project never bundles. ReSharper's caches live in the plugin's own data directory, outside your source tree.
Tools
Tool | Mutates files | What it does |
| no | Runs ReSharper InspectCode and returns the issues, grouped by file. |
| yes | Runs ReSharper CleanupCode to reformat and normalize the given files in place. |
| no (deletes caches) | Drops the solution's ReSharper cache so the next run rebuilds its analysis from cold. |
Scope resharper_inspect with the files glob and raise severity (Suggestion, Warning, Error; default Warning) to control how much comes back. Each issue carries a file, line, severity, rule ID, and message:
Found 2 issue(s) across 1 file(s):
### /repo/src/HomeController.cs
- **Line 8** [WARNING] `RedundantUsingDirective`: Using directive is not required by the code and can be safely removed.
- **Line 24** [SUGGESTION] `FieldCanBeMadeReadOnly.Local`: Field can be made readonly.A solution-wide run comes back more compactly: once it would overflow the output budget, issues repeating a rule within a file collapse to a single line — - **`NotAccessedPositionalProperty.Global`** [WARNING] x30, lines 13-42 — so the count stays exact and every line number is still there. See Configuration for the rest of that ladder.
Call resharper_cleanup once, at the end of a task, with every file you changed batched into the one call.
The first run on a solution is slow while ReSharper builds its caches under --caches-home; later runs reuse them and finish in seconds. The server caps each run at 10 minutes, and RESHARPER_MCP_TIMEOUT_SECS moves that cap. The cap is the server's own — no MCP client requires one this short — so a solution whose cold analysis needs longer should be given longer rather than retried, and narrowing the call with files will not make it finish: jb analyses the whole solution whatever the report is scoped to.
To spend that cold run on idle time rather than yours, the server starts one speculative inspection of the discovered solution as soon as a client connects — one pass at a time, skipped when any run against that cache succeeded in the last hour, and silently skipped entirely when there is no solution to find. A real call arriving mid-pre-warm cancels it and takes the cache, so it never queues behind one in the same server process; one running in another process cannot be cancelled and is the one case where a first call can be slower than before. A call that hits the run cap arms another pass against the solution that timed out — the cache is part-built and you are reading the error, which is when speculative work is worth most — and that is the only thing that re-arms it, so it never runs on a timer or per message. It is a full solution analysis, which is not free — set RESHARPER_MCP_PREWARM=off to turn it off.
A second checkout of one repository — a git worktree, a clone, a copy — is always cold, because jb keys a cache generation by the solution's absolute path. So when a call finds no cache for its solution and a same-named solution's last successful run recorded one, the server copies that generation under the name jb will look for, holding the queue lock on both. It is silent and best-effort: it gives up at the first doubt, never replaces a cache that already exists, never runs after a resharper_reset_cache, and leaves jb to validate what it was given. It is a trade rather than a free win — jb re-keys a copied cache, which costs about a minute, in exchange for the difference between a cold analysis and a warm one — so it is aimed at the solutions where that difference is minutes and a cold run risks the cap, not at ones that already finish quickly.
Calls against one solution are serialized, across every client on the machine: only one jb at a time can use a solution's cache, and a second one that tries silently forks a cold copy instead of waiting — so two sessions inspecting one solution would otherwise make each other slow and leave a stale cache behind. A call therefore waits up to the same cap for a run already in flight before starting its own run, and says so if that wait runs out. If your MCP client's own tool-call timeout is shorter than a cold run needs, the client gives up first. In Claude Code, raise it with a per-server "timeout" in milliseconds in .mcp.json, or the MCP_TOOL_TIMEOUT environment variable.
When ReSharper reports errors your compiler does not
ReSharper's solution-wide analysis keeps its own index in that cache, and it can miss invalidating the consumers of a declaration you reshaped. The result is .CSharpErrors issues — Cannot resolve symbol 'Foo' — in files you never edited, while the build and the tests stay green. It does not self-heal: re-running returns the identical set until the cache generation is dropped.
An inspection that reports any compilation error therefore leads with a note saying so, and resharper_reset_cache is the cure. It deletes the solution's cache generation directories, taking the same queue lock the analysis tools take so it never deletes a cache out from under a running jb, and the next call rebuilds from cold. It drops only what provably belongs to the solution it was pointed at: jb names those directories with a hash of the solution's full path, which the server reproduces, so a cache home shared with another checkout of the same repository is ordinary — the generations that are not this solution's are named in the report and left where they are.
The ReSharper CLI exposes no cache-invalidation option of its own — --caches-home only chooses where caches live — which is why this operation lives in the wrapper.
Configuration
Set these in the MCP client config's env block. All are optional. Each JB_ variable becomes something jb itself is told; the RESHARPER_MCP_ ones govern this server's own behaviour and never reach jb.
Variable | Purpose |
| Solution to use when the working directory has zero or several. |
| Explicit |
| ReSharper cache directory (default |
| Semicolon-separated ReSharper plugin IDs to load. |
| Custom NuGet source for those plugins. |
| Cap in seconds on one |
|
|
| Level for the rolling file log (default |
| Client output budget; caps large inspection results. |
The solutionPath tool argument overrides JB_SOLUTION_PATH for a single call. When a result would exceed MAX_MCP_OUTPUT_TOKENS (2.5 characters per token, or 25,000 characters when unset), the two analysis tools re-render it at progressively lower detail until it fits, then append a DETAIL REDUCED note naming the level and what that level gave up. Inspection steps down five: every issue listed, then repeated rules collapsed per file, then only the eight most-affected files listed, then a rules-and-files rollup, then a one-line summary. Every issue is still counted and every file still named at each step — a reduced result is complete but less detailed, unlike a truncated one. Truncation at a line boundary remains only as a last-resort backstop for when even the one-line summary overflows.
Solution discovery tries, in order: the solutionPath argument, then JB_SOLUTION_PATH, then a single .sln/.slnx in the working directory (top level only, no parent walk). Zero or several without an override is an error that names the variable to set.
Settings discovery tries, in order: JB_SETTINGS_PATH (a missing file logs a warning and falls through), then a .DotSettings file beside the solution, then GlobalSettingsStorage.DotSettings in the JetBrains shared directory, then none. On top of whichever it finds, jb also reads .editorconfig from the source tree automatically — no flag needed — so editorconfig style rules apply even with no .DotSettings at all.
Logs roll daily under %LOCALAPPDATA%\Zphil.ReSharperCli\logs on Windows, and the platform-equivalent path elsewhere. Nothing leaves the machine; PRIVACY.md states that as policy.
Deriving a style guide for a legacy codebase
Adding this server to a large existing solution unlocks a second workflow: deriving an intentional ReSharper style guide from the code you already have, so an inspection flags real house-style deviations rather than un-configured defaults. The server advertises an MCP prompt, derive_style_guide (surfaced as a slash command or prompt-picker entry in clients that render prompts), that walks an agent through it.
Be clear on the division of labour: ReSharper's command-line tools have no "infer settings from code" verb, and this server does not infer settings. The agent derives the rules from evidence — the code plus whatever is already in the repo (StyleCop, analyzers, an existing .editorconfig) — and resharper_inspect validates them: scope an inspection to a representative folder, then keep or silence each noisy rule until the remaining output is all intentional. The recipe is .editorconfig-first (portable across ReSharper, StyleCop.Analyzers, Roslyn, dotnet format, and Rider), spilling only ReSharper-only knobs and cleanup-profile definitions into .sln.DotSettings. When the codebase genuinely mixes conventions, the prompt pauses and asks rather than guessing.
If a teammate has ReSharper or Rider, prefer JetBrains' first-party Detect Code Style Settings for the baseline; it is IDE-only, so this recipe is the path for headless, CI, or no-licence use, and it adds StyleCop reconciliation and severity tuning on top. See also ReSharper's Use EditorConfig and the InspectCode / CleanupCode references. The embedded prompt is the full recipe; this section is only a digest of it.
Cleanup is cosmetic
resharper_cleanup never changes behavior. Its fallback Built-in: Full Cleanup profile fixes formatting and style only, so an agent should write correct logic and let the cleanup pass handle the polish. There is no need to re-inspect or rebuild after it. That profile handles all of these:
unused usings, sorted and shortened qualified references
indentation, spacing, line breaks, and wrapping
varversus explicit type, per the solution's settingsmodifier order, and explicit or implicit modifiers as configured
redundant parentheses,
this.qualifiers, casts, and default valuesbraces around single statements, per style
auto-properties, readonly fields, object-creation style, trailing commas, namespace style
Keep the agent's editing effort on logic, types, naming, and architecture. For a legacy codebase where Full Cleanup would churn regions you did not touch — or for a deliberate style it would normalize away — define a narrower profile (for example Custom: No Reordering) in the solution's .sln.DotSettings. Name it under SilentCleanupProfile there and every call uses it without a profile argument, including calls from an agent that does not know it exists; the profile argument overrides it per call.
resharper_cleanup reports which of the files it changed on disk, so an agent can see when a cleanup rewrote something it meant to leave alone rather than trusting a bare "completed". A small batch lists every file; a solution-wide run collapses the per-file detail toward counts to stay within the output budget.
Configuring what ReSharper enforces
The two tools read two independent configuration axes: resharper_inspect obeys inspection severities (what gets reported), and resharper_cleanup enforces code style through its cleanup profile (what gets rewritten). They do not share a switch — setting a rule to DO_NOT_SHOW hides its inspection issue but does not stop cleanup from normalizing that style. Some styles are binary with no "leave alone" value (argument style is positional or named), so protecting one means narrowing the profile, excluding the file, or an in-source // ReSharper disable comment.
Rather than carry that model in every session's context, the server advertises it as an on-demand MCP resource, resharper://guides/configuration — the two axes, how to protect a deliberate style, where settings and .editorconfig are read from, and the .DotSettings key shapes. A client that surfaces resources lets an agent load it exactly when it is about to change what ReSharper enforces.
A second resource, resharper://guides/setup, covers running the server rather than configuring ReSharper: how jb and the solution are discovered, why the first call is slow and what the background pre-warm does about it, what the run cap means and why calls against one solution queue, how a large result is shortened to fit the output budget, the environment variables above, and where logs go. An agent loads it when a call cannot find jb or the solution, times out, or comes back shortened. Splitting the two keeps each pull small, and keeps the always-loaded server instructions down to the cross-tool rules that no schema can express.
Cleanup reminder hook
The single end-of-task cleanup above is easy for an agent to forget. A Claude Code PostToolUse hook can nudge it toward the habit without running anything itself. Add this to .claude/settings.json:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "grep -qiE '\"file_path\"[[:space:]]*:[[:space:]]*\"[^\"]*\\.(cs|razor)\"' && printf '%s' '{\"hookSpecificOutput\":{\"hookEventName\":\"PostToolUse\",\"additionalContext\":\"When this task is done, batch every edited .cs/.razor file into one resharper_cleanup call.\"}}' || true"
}
]
}
]
}
}After each .cs/.razor edit the hook adds a one-line reminder to the agent's context; on any other file it prints nothing and does nothing. It never edits code or calls the tool, so the agent decides when to clean up. The command uses grep and printf, so it needs a POSIX shell (on Windows, Git Bash).
Contributing
Contributions are welcome. Bug reports reproduced on a public solution, MCP client-compatibility fixes, and improvements to discovery or output formatting land best. See CONTRIBUTING.md for the development setup (.NET 10 SDK) and the two-seam test architecture. To report a security issue privately, see SECURITY.md.
License
MIT; see LICENSE.
JetBrains and ReSharper are trademarks of JetBrains s.r.o. This project is an independent wrapper of their ReSharper Command Line Tools, which ship under JetBrains' own license.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseAqualityCmaintenanceMCP Server providing AI agents with tooling for Gerrit code review workflows via stdio transport.18141MIT
- Alicense-qualityBmaintenanceExposes Language Server Protocol (LSP) tools such as diagnostics, goto definition, find references, symbols, and rename as a stdio MCP server.6MIT
- FlicenseAqualityCmaintenanceMinimal MCP server bridging a Roslyn C# language server to AI agents, exposing tools for diagnostics, call hierarchy, and type hierarchy.1
- AlicenseAqualityCmaintenanceMCP server for .NET assembly analysis. Vendor-neutral wrapper around AsmResolver and ILSpy for parsing and decompiling .NET assemblies.111MIT
Related MCP Connectors
The MCP server for Azure DevOps, bringing the power of Azure DevOps directly to your agents.
MCP Server for Slima - AI Writing IDE for Novel Authors with AI Beta Reader.
A MCP server built for developers enabling Git based project management with project and personal…
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/andypgray/resharper-cli-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server