Kirnot.RoslynMcpServer
0.4.0
dotnet tool install --global Kirnot.RoslynMcpServer --version 0.4.0
dotnet new tool-manifest
dotnet tool install --local Kirnot.RoslynMcpServer --version 0.4.0
#tool dotnet:?package=Kirnot.RoslynMcpServer&version=0.4.0
nuke :add-package Kirnot.RoslynMcpServer --version 0.4.0
roslyn-mcp-server
roslyn-mcp-server is an unofficial C# MCP server that lets AI agents use
Roslyn language features through roslyn-language-server.
The server is meant for Agent CLI-style tools working inside real C# repositories,
including large mono-repos. It runs as an MCP stdio server, starts
roslyn-language-server as a child LSP process after a solution or project is
selected, then translates MCP tool calls into LSP requests.
The main goal is not to replace an IDE. The goal is to give an agent enough compiler-backed context to read, review, and navigate C# code without forcing the agent to parse a large repository by itself.
Why This Exists
AI agents can inspect files with normal filesystem tools, but C# code often needs semantic context:
- where a symbol is defined
- which overload or type a reference points to
- where a symbol is referenced
- what diagnostics Roslyn currently knows about
- what symbols are present in a file or workspace
Roslyn already knows how to answer these questions. This project provides a thin MCP bridge so an agent can ask those questions while it works.
Large Repository Design
The project assumes large repositories from the beginning. A useful agent tool must stay predictable even when a repo has hundreds of projects, many solutions, slow restore state, or partial Roslyn indexing.
That leads to a few design choices:
- By default the server does not load a solution at startup;
--load-solutioncan opt into early solution loading. - Workspace discovery is bounded by scan depth, timeout, and candidate limits.
- If multiple
.sln,.slnx, or.csprojfiles exist, the agent must choose. - Roslyn LS is launched only after
load_solution,load_project, or an unambiguous first read-tool auto-load. - Read tools do not block indefinitely while the language server is warming.
- Large result sets are capped and report
totalKnown,returned, andtruncatedmetadata. - Warming or partially loaded workspaces return best-effort results with
workspaceState,completeness, and retry metadata. - Diagnostics are based on
textDocument/publishDiagnosticsnotifications already processed by the bounded background diagnostics queue; the server does not run an unbounded workspace-wide diagnostic computation. Queue capacity and pending/processed/dropped/stale counts are exposed throughget_workspace_status.
In practice, WorkspaceWarming is a normal state for large repositories. Agents
should use partial results when they are good enough and call
get_workspace_status when they need to understand load warnings or failures.
Implemented Tools
Workspace tools:
list_workspaces- Discover.sln,.slnx, and.csprojcandidates under the workspace root. OptionalmaxDepthskips git-based discovery and performs bounded filesystem BFS for near-root workspace files.load_solution- Load a selected.slnor.slnxinto Roslyn LS.load_project- Load a selected.csprojinto Roslyn LS.get_workspace_status- Report the selected target, load state, warnings, open documents, and diagnostics queue/cache status.
Read-only Roslyn tools:
document_symbols- Return file-level types, members, and symbol ranges, optionally filtering returned symbols by kind while preserving ancestor context for matching descendants.hover- Return Roslyn hover text for a source position.go_to_definition- Return definition locations for a source position.peek_definition- Return definition locations plus bounded source snippets.find_references- Return references for a source position.peek_references- Return reference locations plus bounded source snippets.find_implementations- Return implementation locations from an interface, abstract member, or base contract position. Calling it on a concrete implementation may legitimately return only that implementation. Results can be narrowed with root-relativeincludePathPrefixes.get_call_hierarchy- Return direct depth-1 incoming callers, outgoing callees, or both for a method, constructor, or property accessor position, optionally filtering returned edge counterparts by kind:method,constructor,property,event,operator, orfield, and by root-relativeincludePathPrefixes.get_type_hierarchy- Return base type, derived type, or interface implementation hierarchy edges for a type position, with bounded breadth-first traversal depth, result caps, and optional root-relativeincludePathPrefixes.find_symbols- Search workspace symbols by name, optionally filtering returned results by kind such asclass,interface,method,property, orfield, and by symbol-namematchMode:default,exact,prefix, orcontains. Default matching keeps Roslyn LS fuzzy candidates but ranks exact, prefix, and contains name matches before the result cap. It can also keep only symbols located under root-relativeincludePathPrefixes, which is useful in large repositories.diagnostics- Return currently known file or workspace diagnostics.
Resources:
roslyn://server/guide- Short usage guidance for agents.roslyn://server/capabilities- Short read-only capability summary.
This project is intentionally read-only. Rename, code actions, formatting, and apply/edit tools are outside the product direction; agents should make file changes with their normal workspace editing tools after using Roslyn context to understand the code.
Getting Started
Prerequisites:
- .NET 10 SDK for installing .NET tools
roslyn-language-server
Install roslyn-language-server separately:
dotnet tool install --global roslyn-language-server --prerelease
roslyn-mcp-server does not bundle Roslyn LS. Starting with v0.4.0, the .NET
tool package ID is Kirnot.RoslynMcpServer; the installed command remains
roslyn-mcp-server.
.NET Tool
Install the MCP server as a .NET global tool:
dotnet tool install --global Kirnot.RoslynMcpServer
Run the installed command:
roslyn-mcp-server --help
If your MCP client does not inherit the .NET global tools directory on PATH,
point it at the tool shim directly:
%USERPROFILE%\.dotnet\tools\roslyn-mcp-server.exe
On macOS or Linux:
$HOME/.dotnet/tools/roslyn-mcp-server
Release Artifacts
Alternatively, download the self-contained artifact for your OS from the v0.4.0 release or the latest release:
roslyn-mcp-server-v0.4.0-win-x64.ziproslyn-mcp-server-v0.4.0-linux-x64.tar.gzroslyn-mcp-server-v0.4.0-osx-x64.tar.gzroslyn-mcp-server-v0.4.0-osx-arm64.tar.gz
The release artifacts are self-contained and single-file. The server executable
does not require a separate .NET runtime installation, though roslyn-language-server
and the target C# repository still need a compatible .NET SDK/runtime environment.
Point your MCP client at the extracted executable:
C:\Tools\roslyn-mcp-server\roslyn-mcp-server.exe
On macOS or Linux, extract the .tar.gz and use the roslyn-mcp-server
executable from the extracted folder. If your archive tool does not preserve
the executable bit, run chmod +x roslyn-mcp-server.
Build From Source
Use source builds for local development, unsupported platforms, or if you want to run the server directly from this repository. Source builds require Git and the .NET 10 SDK.
git clone https://github.com/kirnot92/roslyn-mcp-server.git
cd roslyn-mcp-server
dotnet build .\src\RoslynMcpServer\RoslynMcpServer.csproj -c Release
The built server executable will be under:
src/RoslynMcpServer/bin/Release/net10.0/
On Windows, the executable is typically:
src/RoslynMcpServer/bin/Release/net10.0/roslyn-mcp-server.exe
On macOS or Linux, the executable is typically:
src/RoslynMcpServer/bin/Release/net10.0/roslyn-mcp-server
After installing, downloading, or building the server, configure your MCP client
to run roslyn-mcp-server or the server executable from the repository root you
want to inspect.
If you prefer a self-built release-style layout, publish instead of building.
Use the runtime identifier for your target platform, such as win-x64,
linux-x64, osx-x64, or osx-arm64:
git clone https://github.com/kirnot92/roslyn-mcp-server.git
cd roslyn-mcp-server
dotnet publish .\src\RoslynMcpServer\RoslynMcpServer.csproj -c Release -r win-x64 --self-contained true -p:PublishSingleFile=true -p:IncludeNativeLibrariesForSelfExtract=true -p:DebugType=None -p:DebugSymbols=false -o .\publish\roslyn-mcp-server
With the default configuration, the current working directory becomes the
workspace root. Use --root <path> only when your MCP client cannot set the
working directory. Use --roslyn-language-server <path> only when
roslyn-language-server is not on PATH.
--load-solution <path> is optional. When set, the server starts loading that
.sln or .slnx as soon as the MCP server starts, so Roslyn LS can warm while
the agent reads the repository. When it is omitted, the agent can still call
load_solution or load_project when it needs Roslyn context.
Recommended tool flow:
list_workspacesload_solutionorload_projectget_workspace_status- read-only Roslyn tools
For code review workflows, start workspace loading early. A good pattern is to inspect the changed file list, load the intended solution or project, then read the diff while Roslyn LS warms in the background.
MCP Client Setup
Install, download, or build the server first, then point your MCP client at
roslyn-mcp-server or the server executable. Use cwd or --root <repo-root>
so the server knows which repository to inspect.
Solution paths passed to --load-solution must be the exact root-relative path,
such as Sources/Server.sln, or an absolute path inside the root. The server
does not recursively search for a matching file name from this option.
1. Claude Code
Local setup with claude mcp add:
claude mcp add --transport stdio roslyn -- `
roslyn-mcp-server `
--root <repo-root> `
--load-solution Server.sln
Project-scoped .mcp.json:
{
"mcpServers": {
"roslyn": {
"command": "roslyn-mcp-server",
"args": ["--root", ".", "--load-solution", "Server.sln"]
}
}
}
2. Gemini CLI
Project .gemini/settings.json:
{
"mcpServers": {
"roslyn": {
"command": "roslyn-mcp-server",
"args": ["--load-solution", "Server.sln"],
"cwd": "<repo-root>",
"timeout": 30000
}
}
}
3. Codex
Global ~/.codex/config.toml, or project-scoped .codex/config.toml in a
trusted project:
[mcp_servers.roslyn]
command = "roslyn-mcp-server"
args = ["--root", "<repo-root>", "--load-solution", "Server.sln"]
If you keep a project-scoped .codex/config.toml in the repository root, --root
can usually be .:
[mcp_servers.roslyn]
command = "roslyn-mcp-server"
args = ["--root", ".", "--load-solution", "Server.sln"]
Multiple Solutions
For repositories with separate solutions, run separate MCP server entries. For example, a Unity project can expose both server and client solutions:
{
"mcpServers": {
"roslyn-server": {
"command": "roslyn-mcp-server",
"args": ["--load-solution", "Server.sln"],
"cwd": "<repo-root>"
},
"roslyn-unity": {
"command": "roslyn-mcp-server",
"args": ["--load-solution", "UnityClient.sln"],
"cwd": "<repo-root>"
}
}
}
More setup and client examples are in docs/usage.md.
Current Status
The project is pre-release but usable for read-only C# navigation and diagnostics in agent workflows. It has been smoke-tested with real repositories including PowerShell, Semantic Kernel, and ASP.NET Core. Those tests are intentionally about responsiveness and usable metadata, not perfect semantic completeness for every large solution.
Known constraints:
roslyn-language-serveris a prerelease dependency and may change behavior.- Large repositories may remain in
WorkspaceWarmingfor a long time. - Project load errors usually reflect local SDK, workload, restore, or
global.jsonenvironment problems and are surfaced through workspace warnings. - Diagnostics are current-known diagnostics from the last processed
textDocument/publishDiagnosticsnotifications, not a guaranteed full build result. - Write/refactoring tools are not implemented.
Implementation notes for maintainers are in AGENTS.md and docs/implementation-notes.md.
License
This project is licensed under the MIT License. See LICENSE for details.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
This package has no dependencies.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.4.0 | 186 | 5/23/2026 |