RoslynGate is a stdio MCP server that answers .NET symbol questions with Roslyn instead of text search. It returns compact, deterministic results so an agent can find a definition, reference, or hierarchy without dumping code into the context window.
It is built for medium and large .NET solutions. On a couple of projects, the MCP schema and the extra turns can cost more than the file reads they replace. Measure before expecting a win.
| Tool | Purpose |
|---|---|
get_symbol_definition |
Resolve one symbol by qualified name or file + line. |
find_symbol_references |
Find semantic references, paginated; includeDefinition=true also returns the resolved symbol. |
get_type_hierarchy |
Base types, interfaces, derived types, implementations. |
search_symbols |
Find symbols by name fragment before resolving. |
reload_workspace |
Reload after project or structural changes. |
Every response is JSON. detail=compact (default) keeps the wire small;
detail=verbose adds namespace, container, column, and longer documentation.
When a page is truncated, find_symbol_references and search_symbols also
return nextOffset and a hint:
{
"total": 120,
"offset": 0,
"truncated": true,
"nextOffset": 50,
"hint": "Call find_symbol_references again with offset=50 and the same arguments."
}Use parameterTypes to disambiguate overloads:
{
"name": "SampleSdk.Widget.Open",
"parameterTypes": ["string"]
}With the default watcher, .cs edits are applied incrementally. Structural
changes set stale: true; the agent should call reload_workspace before
trusting an empty result. Disable the watcher with --no-watch.
Against rg on this repository, compact tool output used 76-92% fewer
characters for definition, references, hierarchy, and search tasks. That is
tool output, not session tokens. Warm
queries took 4-11 ms; the first query includes MSBuild loading (~11 s on this
repository). The MCP handshake takes ~0.33 s after the first run; the first run
also extracts the single-file binary (~1.4 s). See
docs/BENCHMARKS.md for methodology and caveats.
The OpenCode A/B on a two-project fixture was a token loss (232k against 81k), because the fixed MCP and skill overhead was larger than the saved reads. Use medium and large repositories for a meaningful token A/B; on small projects, judge RoslynGate by correctness and warm-query latency instead. Measure with the OpenCode or Claude A/B harness before promising a percentage.
A separate roslyngate-ts product lives under products/typescript. It uses
the TypeScript compiler API (Program, TypeChecker, LanguageService) for
.ts, .tsx, .js, and .jsx.
cd products/typescript
npm install
npm run build
node dist/cli.js --check --solution ../../fixtures/TsSampleThe five MCP tools are the same contract as the .NET product. See
docs/TODO-TS.md for the remaining release work.
- .NET SDK. RoslynGate does not install or bundle the SDK; it uses the one
selected by the solution's
global.json, or the latest installed SDK. - Linux x64, Windows x64, or macOS arm64 (Apple Silicon). Intel Macs are not supported.
The binary is self-contained, so the .NET runtime is included. The SDK is still
required because MSBuildWorkspace uses MSBuild to evaluate projects, targets,
references, and generated code.
--check shows the selected SDK:
roslyngate --solution . --checkIf a global.json pins an SDK that is not installed, RoslynGate fails with the
requested version and the list of installed SDKs instead of silently using
another one.
Install and configure Claude Code in one step:
npm install -g roslyngate
cd /path/to/repository
roslyngate setup claudeOr run it without installing:
npx -y roslyngate@0.2.2 setup claude
bunx roslyngate@0.2.2 setup claudesetup claude writes .mcp.json with the native binary path, solution path,
and no npx or cmd /c indirection. Open Claude Code and approve
roslyngate in /mcp.
For teams, add the opt-in project skill:
roslyngate setup claude --skillThat writes .claude/skills/roslyn-symbols/SKILL.md, which can be committed.
An existing skill is left unchanged.
For OpenCode, use:
roslyngate setup opencode --solution . --skillThat writes or merges opencode.jsonc under mcp.servers.roslyngate, with
codemode: false, the native binary path, and a strict OpenCode skill under
.opencode/skills/roslyn-symbols/SKILL.md. The skill is also added to
instructions so it is always active. Then open OpenCode and run /mcps.
To use it as a plain CLI:
roslyngate --solution /path/to/repositoryThe first run downloads the self-contained binary for the current platform, verifies its SHA-256 checksum, and caches it. Supported platforms are Linux x64, Windows x64, and macOS arm64. Release binaries are available on the Releases page.
You can also download the binary for your platform from
Releases and verify its
.sha256 file.
roslyngate upgradeThis updates the global npm package, downloads the matching binary, and
updates the roslyngate.command path in .mcp.json in the current directory
when that command is a RoslynGate-managed cache path. It does not touch its
args, timeout, or other MCP servers. Restart Claude Code or run /mcp
afterwards.
If the command is portable (for example roslyngate or npx), the config is
left unchanged. The upgrade detects whether the active command came from npm
or Bun; use --manager npm|bun to override that detection. To update only npm
and the binary:
roslyngate upgrade --no-configUse --check to compare the installed and latest versions, or --dry-run to
see the actions without installing or writing:
roslyngate upgrade --check
roslyngate upgrade --dry-rundotnet build RoslynGate.sln -warnaserror
dotnet test RoslynGate.slndotnet run --project src/RoslynGate.Cli -- --solution fixtures/SampleSolutionThe process speaks MCP over stdin/stdout. Diagnostics go to stderr. Close stdin to stop it.
{
"mcpServers": {
"roslyngate": {
"command": "npx",
"args": ["-y", "roslyngate", "--solution", "/path/to/repository"]
}
}
}The repository ships opencode.jsonc, a local stdio server entry.
- Run
dotnet build. - Start OpenCode in this repository and run
/mcps. - Confirm
roslyngate connected. - Ask the agent to use
roslyngateto find a definition.
The command runs the built DLL, not dotnet run, so build output cannot
corrupt the MCP stdout stream. For a published binary, replace command with
the binary path and add --solution /path/to/repository.
See docs/CLIENTS.md for Claude Code, Cursor, VS Code, and
the generic mcpServers shape.
--check validates the configuration, locates the solution, and loads it with
MSBuild without starting the protocol. It reports the project count and load
time, and exits 0 when the workspace is usable and 1 otherwise.
roslyngate --solution . --checkFlags override environment variables, which override defaults.
| Flag | Environment | Default |
|---|---|---|
-s, --solution |
ROSLYGATE_SOLUTION |
auto-detect |
-l, --log-level |
ROSLYGATE_LOG_LEVEL |
error |
--detail |
ROSLYGATE_DETAIL |
compact |
--ref-limit |
ROSLYGATE_REF_LIMIT |
50 (max 200) |
--search-limit |
ROSLYGATE_SEARCH_LIMIT |
20 (max 50) |
--prewarm / --no-prewarm |
ROSLYGATE_PREWARM |
on |
--watch / --no-watch |
ROSLYGATE_WATCH |
on |
--check |
- | - |
-h, --help |
- | - |
-V, -v, --version |
- | - |
Exit codes: 0 normal end of input or successful check, 1 invalid
configuration or solution, 2 fatal startup failure.
Failures are self-correcting. When a call returns isError: true, read
error.hint and, if present, run error.try.
{
"error": {
"code": "symbol_not_found",
"message": "No symbol matches 'Widget.Opn'.",
"hint": "Names are case-sensitive. Search by fragment instead.",
"try": {
"tool": "search_symbols",
"arguments": { "query": "Opn", "limit": 10 }
}
}
}dotnet restore --locked-mode
dotnet restore fixtures/SampleSolution/SampleSolution.sln
dotnet build RoslynGate.sln -warnaserror
dotnet test RoslynGate.sln
dotnet format RoslynGate.sln --verify-no-changes
npm test --prefix packaging/npmSee CONTRIBUTING.md for the trunk-based workflow, CHANGELOG.md for release history, and docs/BENCHMARKS.md for token and latency measurements.
MIT. See LICENSE.