dotnet-sherlock-mcp
ILSpy for LLM coding agents. Reflection-based MCP server with 31+ tools to explore .NET assemblies, NuGet packages, types, members, attributes, and XML docs.
Documentation
Sherlock MCP for .NET
Sherlock MCP for .NET is a comprehensive Model Context Protocol (MCP) server that provides deep introspection capabilities for .NET assemblies. It enables Language Learning Models (LLMs) to analyze and understand your .NET code with precision, delivering accurate and context-aware responses for complex development scenarios.
This tool is essential for developers who want to harness LLM capabilities for:
- Deep codebase analysis - Understanding complex .NET architectures and dependencies
- Precise type information - Getting detailed metadata about types, members, and their signatures
- Automated documentation - Extracting and utilizing XML documentation and attributes
- Custom tooling - Building sophisticated tools that interact with .NET assemblies
- Code generation - Creating accurate code based on existing type structures
Key Features
- Comprehensive MCP Server: Provides 36 specialized tools for .NET assembly analysis
- Advanced Assembly Introspection: Deep reflection-based analysis of types, members, and metadata
- Rich Member Analysis: Detailed inspection of methods, properties, fields, events, and constructors
- Smart Filtering & Pagination: Advanced filtering by name/attributes with efficient pagination for large datasets
- XML Documentation Integration: Automatic extraction of summary, parameters, returns, and remarks
- Performance Optimized: Caching, streaming, and memory-efficient processing
- Stable JSON API: Consistent envelopes with versioning and structured error codes
- .NET 9.0 Native: Built on the latest .NET platform with modern C# features
- Project Integration: Solution and project file analysis with dependency resolution
- Current MCP SDK: Built on
ModelContextProtocol2.1.0 (GA) - Current MCP Specification: Speaks protocol revision
2026-07-28, and negotiates down automatically for clients on earlier revisions
What's New in 2.13.0
- MCP 2026-07-28: upgraded to
ModelContextProtocol2.1.0, so clients negotiate the current specification revision instead of falling back. The handshake-less request flow is supported, and clients on earlier revisions keep working unchanged. - Tool annotations: all 36 tools now advertise a title plus accurate behavioural hints (
readOnlyHint,destructiveHint,openWorldHint,idempotentHint), so clients can tell at a glance that 35 of them only read metadata. - Cacheable tool list:
tools/listadvertisesttlMsandcacheScopeand returns tools in a deterministic order, letting clients skip redundant re-fetches. SeeCHANGELOG.mdfor full details.
Installation
Run with dnx (.NET 10 SDK)
With the .NET 10 SDK, dnx downloads the package from NuGet and runs it directly — no install step:
dnx Sherlock.MCP.Server@2.13.0 --yes
--yes skips the interactive confirmation prompt, which an MCP client launching the server over stdio can't answer. Pinning the version keeps launches reproducible; bump it when you want to upgrade. The package is published with the McpServer package type, so it is also listed as an MCP server on NuGet.org.
Install as a global tool
On any supported SDK (.NET 8 or later), install the global tool from NuGet (adds sherlock-mcp to your PATH):
dotnet tool install -g Sherlock.MCP.Server
Alternatively, during development you can run the server locally:
dotnet run --project src/server/Sherlock.MCP.Server.csproj
Configure Your MCP Client
Sherlock runs as a standard MCP server that communicates over stdio.
Using dnx
- Claude Code:
claude mcp add sherlock -- dnx Sherlock.MCP.Server@2.13.0 --yes
- VS Code (
.vscode/mcp.json):
{
"servers": {
"sherlock": {
"type": "stdio",
"command": "dnx",
"args": ["Sherlock.MCP.Server@2.13.0", "--yes"]
}
}
}
Using the global tool
- Cursor: Settings → MCP / Custom tools → Add tool → Command:
sherlock-mcp - Claude Desktop / other MCP clients: Add a server entry pointing to the
sherlock-mcpcommand. Example JSON entry (refer to your client’s docs for exact file location/format):
{
"servers": {
"sherlock": {
"command": "sherlock-mcp"
}
}
}
No arguments are required. The server self-registers all tools when launched.
Auto-Configure for .NET Projects
You usually don't need to paste anything. Sherlock ships its usage guidance in the MCP instructions field returned at initialize, and most MCP clients (including Claude Code) surface that to the agent automatically — so the guidance stays correct and versioned with the package, with no copy-paste to maintain.
The snippets below are optional reinforcement. Keep them short and principle-based rather than enumerating tool names and workflows: a static list pasted into your repo will drift as Sherlock's tools evolve, whereas the tools' own descriptions (and the server instructions) always match the version you're running.
Tool names are exposed in
snake_case(get_type_methods,search_members, …); argument names stay camelCase (projection,nameContains).
Claude Code (CLAUDE.md)
Optional — a short pointer in your project's CLAUDE.md:
## .NET Assembly Analysis
Use the Sherlock MCP tools (`get_type_methods`, `search_members`, …) for .NET type/assembly
questions instead of guessing. Locate DLLs with the `find_assembly_by_*` / `get_project_output_paths`
tools rather than hardcoding bin paths. Start lean — `search_members` or `get_types_from_assembly`,
then drill in — and pass `projection='full'` only when you need parameters/attributes/modifiers.
The tools' own descriptions cover the specifics.
Cursor (.cursor/rules)
The single-file .cursorrules format is deprecated (and silently ignored in Cursor's Agent mode).
Add a Project Rule at .cursor/rules/sherlock.mdc instead:
---
description: Use Sherlock MCP for .NET assembly/type analysis
alwaysApply: true
---
- Prefer the Sherlock MCP tools (snake_case, e.g. `get_type_methods`, `search_members`) over guessing about .NET APIs.
- Find DLLs with `find_assembly_by_*` / `get_project_output_paths`; don't hardcode `bin/Debug/<tfm>/*.dll`.
- Start lean (`search_members` / `get_types_from_assembly`); request `projection='full'` only when you need parameters/attributes/modifiers.
Other agents (AGENTS.md)
For tools that follow the cross-editor AGENTS.md convention, the same short pointer works — drop the Claude Code snippet above into your AGENTS.md.
Global configuration
For system-wide usage, add to your global agent settings:
For .NET work, use the Sherlock MCP tools (snake_case) to analyze assemblies, types, and members instead of guessing. Start lean and opt into projection='full' only when you need detail.
How To Prompt It
Below are compact prompt snippets you can paste into your chat to get productive fast. Adjust paths to your local DLLs.
General setup
You have access to an MCP server named "sherlock" that can analyze .NET assemblies. Prefer these tools for .NET questions and include short reasoning for which tool you chose. Ask me for the assembly path if missing.
Enumerate members for a type
Analyze: /absolute/path/to/MyLib/bin/Debug/net9.0/MyLib.dll
Type: MyNamespace.MyType
List methods, including non-public, filter name contains "Async", include attributes, return JSON.
Get XML docs for a member
Use GetXmlDocsForMember on /abs/path/MyLib.dll, type MyNamespace.MyType, member TryParse. Summarize the summary + params.
Find types and drill in
List types from /abs/path/MyLib.dll; then get type info for the first result and list its nested types.
Tune paging and filters
Use GetTypeMethods on /abs/path/MyLib.dll, type MyNamespace.MyType, sortBy name, sortOrder asc, skip 0, take 25, hasAttributeContains Obsolete.
Browse lean, then get detail (projection)
On /abs/path/MyLib.dll, run GetTypeMethods for MyNamespace.MyType with the default summary projection to see signatures. Then re-call GetTypeMethods with projection='full' only for the methods I name to get their parameters and attributes.
Trace relationships and call sites
On /abs/path/MyLib.dll: FindImplementationsOf MyNamespace.IMyService. Then FindReferencesTo that interface with analysisDepth='il' to find callers, and GetMethodCalls on the most relevant method to see what it invokes.
Tools Overview
Tool names: MCP clients call these tools in
snake_case—GetTypeMethods→get_type_methods,SearchMembers→search_members, and so on. The PascalCase names used throughout this README match the underlying C# methods and the tool descriptions your client displays.
Assembly Discovery & Analysis
AnalyzeAssembly: Complete assembly overview with public types and metadataGetAssemblyInfo: Assembly-level metadata — identity/version, target framework, and referenced assemblies (projection=fulladds all assembly attributes)FindAssemblyByClassName: Locate assemblies declaring a public type by simple, full or nested name; skipsobj/,ref/,refint/,node_modules/,packages/,TestResults/and dot-directories, and ranksbin/matches firstFindAssemblyByFileName: Find assemblies by file name under a root directory, with the same exclusions and rankingFindAssemblyByNugetPackage: Resolve a DLL from the local NuGet cache by package id (optionalversion/tfm)
Type Introspection
GetTypesFromAssembly: List all public types with metadata (paginated)AnalyzeType: Comprehensive type analysis with all membersGetTypeInfo: Detailed type metadata (accessibility, generics, nested types)GetTypeHierarchy: Inheritance chain and interface implementationsGetGenericTypeInfo: Generic parameters, arguments, and variance informationGetTypeAttributes: Custom attributes declared on typesGetNestedTypes: Nested type declarations
Member Analysis (Filterable & Paginated)
GetAllTypeMembers: All members across all categoriesGetTypeMethods: Method signatures, overloads, and metadataGetTypeProperties: Property details including getters/setters and indexersGetTypeFields: Field information including constants and readonly fieldsGetTypeEvents: Event declarations with handler typesGetTypeConstructors: Constructor signatures and parametersAnalyzeMethod: Deep method analysis with overloads and attributes
Member Search
SearchMembers: Search a whole assembly for members whose name contains a fragment — the entry point when you know a member name but not its declaring type. Filter bymemberKinds(method|property|field|event|type).
Reverse Lookup
FindImplementationsOf: Types implementing an interface or deriving from a base class (open-generic match supported)FindMethodsReturning: Methods whose return type matches a given type (open-generic match supported)FindExtensionMethodsFor: Extension methods that extend a given type (scans static classes bythis-parameter)FindReferencesTo: Broader sweep across parameters, fields, properties, events, and generic arguments; passanalysisDepth='il'to also resolve inbound callers from method bodies
IL Analysis
GetMethodCalls: Read a method's IL body to list what it calls and which fields it touches — the "what does this method do?" question signature-level tools can't answer (aggregates across overloads; use.ctor/.cctorfor constructors)
Attributes & Metadata
GetMemberAttributes: Attributes for specific membersGetParameterAttributes: Parameter-level attribute information
XML Documentation
GetXmlDocsForType: Extract type-level XML documentationGetXmlDocsForMember: Member-specific documentation (summary/params/returns/remarks)
Project & Solution Analysis
AnalyzeSolution: Parse .sln files and enumerate projectsAnalyzeProject: Project metadata, references, and build configurationGetProjectOutputPaths: Resolve output directories for different configurationsResolvePackageReferences: Map NuGet packages to cached assembliesFindDepsJsonDependencies: Parse deps.json for runtime dependencies
Configuration & Runtime
GetRuntimeOptions: Current server configuration and defaultsUpdateRuntimeOptions: Modify pagination, caching, and search behavior
Resources
Three resource templates let clients fetch a single type, doc entry or cached package without another tool call. Every variable is percent-encoded.
sherlock://assembly/{path}/type/{fullName}: Type metadata, the same payload asget_type_infosherlock://assembly/{path}/docs/{memberId}: XML documentation for a documentation id such asT:Ns.TypeorM:Ns.Type.Method(System.String)sherlock://nuget/{packageId}/{version}: The assembly a cached NuGet package version resolves to, the same payload asfind_assembly_by_nuget_package
search_members, get_types_from_assembly and the find_* reverse-lookup tools return a resource_link to the type resource for each distinct type on the page, after the JSON text block. resources/read carries private caching hints; a URI whose assembly, type, doc id or package doesn't exist fails with -32602.
Template variables support completion/complete, returning at most 100 values:
path: recently loaded assemblies, then.dll/.exefiles and subfolders of the folder being typedfullName: type names (metadata form, e.g.List`1) from the assembly in thepathcontext argumentmemberId: documentation ids from the XML file next to thepathassemblypackageId/version: package folders and their versions (newest first) in the local NuGet cache
Advanced Filtering & Pagination
All member analysis tools support comprehensive filtering and pagination:
Filtering Options:
caseSensitive(bool): Case-sensitive type/member matchingnameContains(string): Filter by member name substringhasAttributeContains(string): Filter by attribute type substringincludePublic/includeNonPublic(bool): Visibility filteringincludeStatic/includeInstance(bool): Member type filtering
Pagination:
skip/take(int): Standard offset paginationmaxItems(int): Maximum results per request (default 50;FindReferencesTodefaults to 25)continuationToken(string): Token-based pagination for large datasetssortBy/sortOrder(string): Sort by name/access in asc/desc order
Response Shape (token efficiency)
Most enumerating tools default to a lean summary projection and let you opt into the heavier full payload only when you need it. Reach for full deliberately — summary is usually enough to decide your next call.
projection(summary|full): supported byGetTypesFromAssembly,GetTypeMethods,GetAssemblyInfo,GetMethodCalls,FindImplementationsOf,FindMethodsReturning,FindExtensionMethodsFor, andFindReferencesTo.summaryreturns just enough to browse (e.g.{ name, signature }for methods);fulladds structured fields (parameters, attributes, return type, modifiers, etc.). Note:GetTypeProperties/Fields/Events/Constructorshave a single fixed shape and take noprojection.analysisDepth(signatures|il):FindReferencesToonly.signatures(default) scans member declarations;iladditionally scans method bodies for inbound callers (slower).additionalAssemblies(string[]): widen the search scope forGetTypeHierarchyand the reverse-lookup tools.GetTypeHierarchy.derivedTypesstaysnulluntil you pass this.noCache(bool): bypass the response cache for a single call when you suspect stale results.
Type Resolution:
- Supports full names (
Namespace.Type), simple names (Type), and nested types (Outer+Inner) - Case sensitivity controlled by
caseSensitiveparameter - Automatic fallback resolution for ambiguous type names
Response Schema
All tools return a stable JSON envelope:
{ "kind": "type.list|member.methods|...", "version": "1.0.0", "data": { /* result */ } }
Error results are flagged with MCP's isError: true, so clients can tell a failure from a result without parsing the text. Errors use a consistent shape. Every error carries kind, version, code, and message; some add details, and guided errors add a suggestion, alternativeTools, or recommendedParams to point the agent at a next step:
{
"kind": "error",
"version": "1.0.0",
"code": "MethodNotFound",
"message": "No method named 'Parse' was found on type 'MyApp.Config' in MyApp.dll.",
"suggestion": "Verify the type and method names. Use get_type_methods to list available methods, or set includeNonPublic=true for private methods.",
"alternativeTools": ["get_type_methods", "analyze_type"]
}
Error codes:
- Not found:
AssemblyNotFound(recommendedParams.similarFileslists near-miss assemblies in the same folder),TypeNotFound/MemberNotFound(recommendedParams.candidateslists the closest names),MethodNotFound,PackageNotFound,VersionNotFound,XmlNotFound,ProjectNotFound,FileNotFound - Bad input:
AmbiguousTypeName(only for clients that can't elicit;recommendedParams.candidateslists the matching full names),InvalidArgument,InvalidProjection,InvalidAnalysisDepth,InvalidContinuationToken - Loading:
InvalidAssembly(not a managed assembly),DependencyNotFound(a referenced assembly couldn't be loaded),DependencyResolutionFailed,AccessDenied - Limits & internal:
ResponseTooLarge,InternalError
Roadmap
Shipped features and planned work are summarized in src/docs/roadmap.md; the live checklist is tracked in #87.
Contributing
Contributions are welcome. This repo includes an .editorconfig with modern C# preferences (file-scoped namespaces, expression-bodied members, 4-space indentation).
Commit Message Format
This project uses Conventional Commits for automated changelog generation. All commits must follow this format:
type(scope): description
Valid types:
feat- A new featurefix- A bug fixdocs- Documentation only changesstyle- Code style changes (formatting, semicolons, etc)refactor- Code change that neither fixes a bug nor adds a featureperf- Performance improvementtest- Adding or correcting testsbuild- Changes to build system or dependenciesci- Changes to CI configurationchore- Other changes that don't modify src or test filesrevert- Reverts a previous commit
Examples:
git commit -m "feat(tools): add new assembly analysis tool"
git commit -m "fix: resolve null reference in type loader"
git commit -m "docs(readme): update installation instructions"
Development Setup
# Restore .NET tools (versionize, husky)
dotnet tool restore
# Install git hooks for commit validation
dotnet husky install
Guidelines
- Keep changes small and focused; add unit tests for new behavior.
- Follow the response envelope and error code conventions when adding tools.
- Run
dotnet buildanddotnet testlocally before opening a PR.
Creating a Release
Maintainers can create releases using:
# Restore tools if not already done
dotnet tool restore
# Preview what will change
dotnet versionize --dry-run
# Create release (bumps version, updates changelog, creates git tag)
dotnet versionize
# Push changes and tag to trigger release workflow
git push --follow-tags
versionize only bumps the project version. Before pushing, bump both version fields in server.json (and the pinned dnx version in this README) in the same release commit, then re-point the tag at it. server.json is packed into the NuGet package as .mcp/server.json.
The release workflow will automatically:
- Verify that the tag,
server.jsonand the project version all match - Build and test the project
- Create a GitHub Release with changelog notes
- Publish the NuGet package and the MCP Registry entry
MCP Registry
mcp-name: io.github.jcucci/dotnet-sherlock-mcp
License
Sherlock MCP for .NET is licensed under the MIT License.