{
  "markdown": "# SharpLensMcp\n\n[![NuGet](https://img.shields.io/nuget/v/SharpLensMcp.svg)](https://www.nuget.org/packages/SharpLensMcp)\n[![npm](https://img.shields.io/npm/v/sharplens-mcp.svg)](https://www.npmjs.com/package/sharplens-mcp)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)\n\nA Model Context Protocol (MCP) server providing **92 AI-optimized tools** for .NET/C# semantic code analysis, navigation, refactoring, and code generation using Microsoft Roslyn.\n\nBuilt for AI coding agents - provides compiler-accurate code understanding that AI cannot infer from reading source files alone.\n\n## Installation\n\n### Via NuGet (Recommended)\n```bash\ndotnet tool install -g SharpLensMcp\n```\n\nThen run with:\n```bash\nsharplens\n```\n\n### Via npm\n```bash\nnpx -y sharplens-mcp\n```\n\n### Build from Source\n```bash\ndotnet build -c Release\ndotnet publish -c Release -o ./publish\n```\n\n## Claude Code Setup\n\n1. **Install the tool** (pick one):\n```bash\ndotnet tool install -g SharpLensMcp\n# or\nnpx -y sharplens-mcp\n```\n\n2. **Create `.mcp.json` in your project root**:\n```json\n{\n  \"mcpServers\": {\n    \"sharplens\": {\n      \"type\": \"stdio\",\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"sharplens-mcp\"],\n      \"env\": {\n        \"DOTNET_SOLUTION_PATH\": \"/path/to/your/Solution.sln (or .slnx)\"\n      }\n    }\n  }\n}\n```\n\n3. **Restart Claude Code** to load the MCP server\n\n4. **Verify** by asking Claude to run a health check on the Roslyn server\n\n### Why Use This with Claude Code?\n\nClaude Code has native LSP support for basic navigation (go-to-definition, find references). SharpLensMcp adds **deep semantic analysis**:\n\n| Capability | Native LSP | SharpLensMcp |\n|------------|------------|--------------|\n| Go to definition | ✅ | ✅ |\n| Find references | ✅ | ✅ |\n| Find async methods missing CancellationToken | ❌ | ✅ |\n| Impact analysis (what breaks?) | ❌ | ✅ |\n| Dead code detection | ❌ | ✅ |\n| Complexity metrics | ❌ | ✅ |\n| Safe refactoring with preview | ❌ | ✅ |\n| Batch operations | ❌ | ✅ |\n\n## Configuration\n\n| Environment Variable | Description | Default |\n|---------------------|-------------|---------|\n| `DOTNET_SOLUTION_PATH` | Path to `.sln` or `.slnx` file to auto-load on startup | None (must call `load_solution`) |\n| `SHARPLENS_ABSOLUTE_PATHS` | Use absolute paths instead of relative | `false` (relative paths save tokens) |\n| `SHARPLENS_LOG_LEVEL` | Logging verbosity: `Trace`, `Debug`, `Information`, `Warning`, `Error` | `Information` |\n| `SHARPLENS_TIMEOUT_SECONDS` | Timeout for long-running operations | `30` |\n| `SHARPLENS_MAX_DIAGNOSTICS` | Maximum diagnostics to return | `100` |\n| `SHARPLENS_ENABLE_SEMANTIC_CACHE` | Enable semantic model caching | `true` (set to `false` to disable) |\n\nThe pre-1.6.0 `ROSLYN_*` spellings of the last four variables are still read as a fallback for one release; the `SHARPLENS_*` spelling wins when both are set.\n\nIf `DOTNET_SOLUTION_PATH` is not set, you must call the `load_solution` tool before using other tools.\n\n## Migrating from 1.5.x tool names\n\nTool names no longer carry the `roslyn:` prefix — the colon violates the MCP tool-name pattern (`^[a-zA-Z0-9_-]{1,64}$`), which some clients enforce. Every tool keeps its name minus the prefix:\n\n| 1.5.x name | 1.6.0 name |\n|------------|------------|\n| `roslyn:load_solution` | `load_solution` |\n| `roslyn:get_diagnostics` | `get_diagnostics` |\n| `roslyn:rename_symbol` | `rename_symbol` |\n| ...same rule for all tools... | drop the `roslyn:` prefix |\n\n`tools/list` publishes only the new names. Calls using the old prefixed names are still accepted as aliases for one release and will be removed in the following one.\n\n## AI Agent Configuration Tips\n\nAI models may have trained bias toward using their native tools (Grep, Read, LSP) instead of MCP server tools, even when SharpLensMcp provides better capabilities.\n\n**To ensure optimal tool usage:**\n\n1. **Claude Code**: Add to your project's `CLAUDE.md`:\n   ```\n   For C# code analysis, prefer SharpLensMcp tools over native tools:\n   - Use `search_symbols` instead of Grep for finding symbols\n   - Use `get_method_source` instead of Read for viewing methods\n   - Use `find_references` for semantic (not text) references\n   ```\n\n2. **Other MCP clients**: Configure tool priority in your agent's system prompt\n\nThe semantic analysis from Roslyn is more accurate than text-based search, especially for overloaded methods, partial classes, and inheritance hierarchies.\n\n## Agent Responsibility: Document Synchronization\n\n**Important:** SharpLensMcp maintains an in-memory representation of your solution for fast queries. When files are modified externally (via Edit/Write tools), the agent is responsible for synchronizing changes.\n\n### When to call `sync_documents`:\n\n| Action | Call sync_documents? |\n|--------|---------------------|\n| Used Edit tool to modify .cs files | ✅ **Yes** |\n| Used Write tool to create new .cs files | ✅ **Yes** |\n| Deleted .cs files | ✅ **Yes** |\n| Used SharpLensMcp refactoring tools (rename, extract, etc.) | ❌ No (auto-updated) |\n| Modified .csproj files | ❌ No (use `load_solution` instead) |\n\n### Usage:\n\n```\n# After editing specific files\nsync_documents(filePaths: [\"src/MyClass.cs\", \"src/MyService.cs\"])\n\n# After bulk changes - sync all documents\nsync_documents()\n```\n\n### Why this design?\n\nThis mirrors how LSP (Language Server Protocol) works - the client (editor) notifies the server of changes. This approach:\n- Eliminates race conditions (agent controls timing)\n- Avoids file watcher complexity and platform quirks\n- Is faster than full solution reload\n- Gives agents explicit control over workspace state\n\n**If you don't sync:** Queries may return stale data (old method signatures, missing new files, etc.)\n\n## Features\n\n- **92 Semantic Analysis Tools** - Navigation, refactoring, code generation, diagnostics, discovery, audit/quality\n- **AI-Optimized Descriptions** - Clear USAGE/OUTPUT/WORKFLOW patterns\n- **Structured Responses** - Consistent `success/error/data` format with `suggestedNextTools`\n- **Zero-Based Coordinates** - Clear warnings to prevent off-by-one errors\n- **Preview Mode** - Safe refactoring with preview before apply\n- **Batch Operations** - Multiple lookups in one call to reduce context usage\n\n## Tool Categories\n\n### Navigation & Discovery (24 tools)\n| Tool | Description |\n|------|-------------|\n| `get_symbol_info` | Semantic info at position |\n| `go_to_definition` | Jump to symbol definition |\n| `find_references` | All references; each classified read/write/invocation/cast/typeof/nameof/attribute; optional `kind` filter |\n| `find_implementations` | Interface/abstract implementations |\n| `find_callers` | Impact analysis - who calls this? |\n| `get_call_graph` | Multi-hop callers/callees graph with depth bound + cycle detection |\n| `find_path_between` | Reachability + the connecting call path(s) between two methods; follows dispatch, with barriers and a checkpoint |\n| `get_type_hierarchy` | Inheritance chain |\n| `search_symbols` | Glob pattern search (`*Handler`, `Get*`) |\n| `semantic_query` | Multi-filter search (async, public, etc.) |\n| `get_type_members` | All members by type name |\n| `get_type_members_batch` | Multiple types in one call |\n| `get_method_signature` | Detailed signature by name |\n| `get_derived_types` | Find all subclasses |\n| `get_base_types` | Full inheritance chain |\n| `get_attributes` | List attributes on a symbol |\n| `get_containing_member` | Enclosing symbol at position |\n| `get_method_overloads` | All overloads of a method |\n| `find_attribute_usages` | Find types/members by attribute |\n| `get_external_type_info` | Inspect NuGet/BCL/external assembly types — members + XML docs |\n| `resolve_stack_trace` | Map a pasted stack trace to file/line/symbol, mangling undone |\n| `get_extension_methods` | Extensions applying to a type — classic and C# 14 blocks |\n| `get_documentation` | Full XML docs for a symbol with `<inheritdoc>` expanded |\n| `get_super_method` | Navigate to the base member / interface members a member implements |\n\n### Analysis (17 tools)\n| Tool | Description |\n|------|-------------|\n| `get_diagnostics` | Compiler errors/warnings + configured analyzer findings (StyleCop, Roslynator, NetAnalyzers); matches CI |\n| `diff_api_surface` | Public-API breaking-change report vs a git ref |\n| `get_exception_flow` | Which exceptions can escape a method, and where they're caught |\n| `find_similar_code` | Structural similarity search (token-shingle fingerprints) |\n| `remove_unused_code` | Compute dead-code removals + newly unused usings (generation-only) |\n| `find_dead_branches` | Unreachable basic blocks per method (real CFG, not heuristics) |\n| `add_missing_imports` | Compute the usings that fix CS0246/CS0103 (generation-only) |\n| `analyze_data_flow` | Variable assignments and usage |\n| `analyze_control_flow` | Branching/reachability |\n| `analyze_change_impact` | What breaks if changed? |\n| `check_type_compatibility` | Can A assign to B? |\n| `get_outgoing_calls` | What does this method call? |\n| `find_unused_code` | Dead code detection |\n| `validate_code` | Compile check without writing |\n| `get_complexity_metrics` | Cyclomatic, nesting, LOC, cognitive |\n| `find_circular_dependencies` | Project and namespace cycle detection |\n| `get_missing_members` | Unimplemented interface/abstract members |\n\n### Refactoring (16 tools)\n| Tool | Description |\n|------|-------------|\n| `rename_symbol` | Safe rename across solution |\n| `change_signature` | Add/remove/reorder parameters |\n| `extract_method` | Extract with data flow analysis |\n| `extract_interface` | Generate interface from class |\n| `generate_constructor` | From fields/properties |\n| `move_type_to_file` | Compute the contents to move a type into its own file (generation-only) |\n| `split_type` | Compute a partial-class split for selected members (generation-only) |\n| `organize_usings` | Sort and remove unused |\n| `organize_usings_batch` | Batch organize multiple files |\n| `format_document_batch` | Batch format files in project |\n| `get_code_actions_at_position` | All Roslyn refactorings at position |\n| `apply_code_action_by_title` | Apply any refactoring by title |\n| `implement_missing_members` | Generate interface stubs |\n| `encapsulate_field` | Field to property |\n| `inline_variable` | Inline temp variable |\n| `extract_variable` | Extract expression to variable |\n\n### Code Generation (3 tools)\n| Tool | Description |\n|------|-------------|\n| `add_null_checks` | Generate ArgumentNullException guards |\n| `generate_equality_members` | Equals/GetHashCode/operators |\n| `generate_test_stub` | Compilable test skeleton for a method (framework auto-detected) |\n\n### Compound Tools (7 tools)\n| Tool | Description |\n|------|-------------|\n| `get_type_overview` | Full type info in one call |\n| `analyze_method` | Signature + callers + outgoing calls + location |\n| `get_file_overview` | File summary with diagnostics |\n| `get_method_source` | Source code by name |\n| `get_method_source_batch` | Multiple method sources in one call |\n| `get_instantiation_options` | How to create a type |\n| `get_project_health` | Composite audit dashboard: diagnostics + unused + coupling + coverage per project |\n\n### Audit & Quality (10 tools)\n| Tool | Description |\n|------|-------------|\n| `find_god_objects` | Detect over-coupled types via efferent + afferent coupling + member-count thresholds |\n| `find_untested_code` | Find public surface not reached by any [Fact]/[Theory]/[Test]/[TestMethod] |\n| `find_tests` | Which tests cover a symbol — the inverse of find_untested_code |\n| `find_type_instantiations` | Where a type is constructed (`new T`) |\n| `find_pattern_usages` | Where a type appears in is/as/pattern matches |\n| `find_throw_sites` | Where an exception type is thrown (optionally derived) |\n| `find_catch_blocks` | Where an exception type is caught (optionally via a base clause) |\n| `find_async_issues` | async void / blocking-on-async / unforwarded CancellationToken |\n| `check_architecture` | Enforce namespace/project dependency rules over the type graph |\n| `find_naming_violations` | Naming audit honoring .editorconfig rules, with conventional defaults |\n\n### Discovery (3 tools)\n| Tool | Description |\n|------|-------------|\n| `get_di_registrations` | Scan DI service registrations |\n| `find_reflection_usage` | Detect reflection/dynamic usage |\n| `find_interceptors` | Surface [InterceptsLocation] call rerouting, generated code included |\n\n### Infrastructure (12 tools)\n| Tool | Description |\n|------|-------------|\n| `health_check` | Server status + load fidelity (`partial` flag, declared-vs-loaded projects, `loadFailures`) — check without reloading |\n| `find_unused_dependencies` | PackageReferences/ProjectReferences the compiler never needs |\n| `fix_all` | Compute the fix for every instance of a diagnostic id (generation-only) |\n| `load_solution` | Load .sln/.slnx; reports partial loads (`partial` + `loadFailures`) so dropped projects / unresolvable references aren't silent |\n| `sync_documents` | Sync file changes into loaded solution |\n| `get_project_structure` | Solution structure |\n| `dependency_graph` | Project dependencies |\n| `get_code_fixes` | Available fixes for a diagnostic |\n| `apply_code_fix` | Apply a specific code fix |\n| `get_nuget_dependencies` | NuGet package listing per project |\n| `get_source_generators` | List active source generators |\n| `get_generated_code` | View generated source code |\n\n## Other MCP Clients\n\nFor MCP clients other than Claude Code, add to your configuration:\n\n```json\n{\n  \"mcpServers\": {\n    \"sharplens\": {\n      \"command\": \"sharplens\",\n      \"args\": [],\n      \"env\": {\n        \"DOTNET_SOLUTION_PATH\": \"/path/to/your/Solution.sln (or .slnx)\"\n      }\n    }\n  }\n}\n```\n\n## Usage\n\n1. **Load a solution**: Call `load_solution` with path to `.sln` or `.slnx` file (or set `DOTNET_SOLUTION_PATH`)\n2. **Analyze code**: Use any of the 92 tools for navigation, analysis, refactoring, audit\n3. **Refactor safely**: Preview changes before applying with `preview: true`\n\n## Architecture\n\n```\nMCP Client (AI Agent)\n        | stdin/stdout (JSON-RPC 2.0)\n        v\n   SharpLensMcp\n   - Protocol handling\n   - 92 AI-optimized tools\n        |\n        v\nMicrosoft.CodeAnalysis (Roslyn)\n  - MSBuildWorkspace\n  - SemanticModel\n  - SymbolFinder\n```\n\n## Requirements\n\n- **.NET 8.0 SDK or later** — works with .NET 8, 9, 10, and future versions. Analyzes any .NET 8+ project/solution.\n- MCP-compatible AI agent\n\n## FAQ\n\n**Why does the tool target `net8.0` — can it analyze my .NET 9 / .NET 10 project?**\n\nYes. `net8.0` is the tool's own runtime floor — the Roslyn 5.x packages it builds on require it — not a ceiling on what it can analyze. `RollForward` lets the installed tool run on newer .NET runtimes, and `MSBuildWorkspace` loads each project's real target framework from its csproj, so one install analyzes solutions targeting .NET 8, 9, 10, and beyond.\n\n## Development\n\n### Adding New Tools\n\n1. **Add the method to the matching `src/RoslynService.*.cs` partial** (Navigation, Analysis, Refactoring, CallAnalysis, …) and return through the shared response envelope:\n```csharp\npublic async Task<object> YourToolAsync(string param1, int? param2 = null,\n    CancellationToken cancellationToken = default)\n{\n    EnsureSolutionLoaded();\n    // Your logic...\n    return CreateSuccessResponse(\n        data: new { /* results */ },\n        suggestedNextTools: new[] { \"next_tool_hint\" }\n    );\n}\n```\n\n2. **Register one `ToolDefinition` in `src/ToolRegistry.cs`** — its name, description, input schema, the `ReadOnly` flag (mutating tools pass `ReadOnly: false` and receive a `destructiveHint` annotation), and a handler that binds arguments through `JsonRpcParameters` and calls your method. The registry drives both `tools/list` and dispatch; there is no separate switch to edit. Two tests keep it honest: `ToolsListGoldenTests` locks the published schema byte-for-byte (re-capture the golden when a schema change is intentional), and `ToolSchemaParityTests` asserts every parameter the handler reads is declared in the schema.\n\n3. **Build and publish**:\n```bash\ndotnet build -c Release\ndotnet publish -c Release -o ./publish\n```\n\n4. **Add both test levels** — a unit test of the `RoslynService` method against a deterministic fixture, AND a wire test through the MCP dispatcher (in `tests/SharpLensMcp.Tests/Mcp/`) with exact value locks plus an error path. This is non-negotiable; see [Testing](#testing).\n\n### Testing\n\nEvery test must satisfy the **Testing Charter (C1–C9)** in [`tests/SharpLensMcp.Tests/TESTING.md`](tests/SharpLensMcp.Tests/TESTING.md) — the standing contract. The headline rules:\n\n- **Lock exact values** (C1): assert a concrete name / count / substring / error code / `(line, column)` — never `NotBeNull` / `> 0` / a type-only check as the *sole* assertion.\n- **Both levels per tool** (C4): a unit test against a `Fixtures/*.cs` fixture **and** a dispatcher (wire) test that unwraps `content[0].text`, plus an error path.\n- **Right casing** (C3): in-process Newtonsoft yields PascalCase `error.Code` / `meta.TotalCount`; the MCP wire yields camelCase. Read the casing your test's path actually produces.\n- **Deterministic** (C7): the suite is serialized via `xunit.runner.json`; fixture mutators always restore; the timeout test uses a forced-cancellation seam, not a timing race.\n- **Out-of-process spine** (C6): `StdioIntegrationTests` value-pins one tool per category over the real binary and runs the `tools/list` golden over the stdio pipe.\n- **Pre-commit gate** (C9): build-clean + green is necessary but **not** sufficient — re-read each changed test and confirm it fails on a wrong answer.\n\nRun the suite:\n```bash\ndotnet test -c Release\n```\n\n### Key Files\n\n| File | Purpose |\n|------|---------|\n| `src/RoslynService.cs` + the `src/RoslynService.*.cs` partials | Tool implementations split by concern across ~30 partials (Navigation, Analysis, Refactoring, Inspection, Validation, TypeDiscovery, Discovery, ExternalApi, Quality, Metrics, CodeActions, CodeGeneration, Compound, CallAnalysis, ExceptionFlow, StackTrace, ApiSurface, SimilarCode, …) — each file's name predicts its contents |\n| `src/McpServer.cs` | MCP protocol mechanics: JSON-RPC parse loop, `initialize` negotiation, per-call timeout, in-band vs protocol error mapping |\n| `src/ToolRegistry.cs` + `src/ToolDefinition.cs` | The tool surface: one `ToolDefinition` record per tool (name, schema, `ReadOnly` flag, handler). Drives `tools/list` order and dispatch lookup |\n| `src/JsonRpcParameters.cs` + `JsonRpcInvalidParamsException.cs` | Typed JSON-RPC argument accessors and the `-32602 Invalid params` exception they raise |\n| `src/*Data.cs` / `*Entry.cs` records, `ConstructorMember.cs`, `SignatureChange.cs` | Typed records used by the audit composite, constructor generator, and signature-change parser (one type per file) |\n\n## License\n\nMIT - See [LICENSE](LICENSE) for details.\n<!-- mcp-name: io.github.pzalutski-pixel/sharplens -->\n",
  "bytes": 18958,
  "sha": "e6164151640801821883c7a094096f9dee8caf39ef91d8788c246e9a4ee69401",
  "repo_slug": "pzalutski-pixel/sharplens-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_pzalutski_pixel_sharplens_b7c8255b/readme"
}