C# 解决方案智能 MCP 服务器

DotSight 是一个为 AI 编程代理提供 C# 解决方案只读智能分析能力的 MCP 服务器,支持符号导航、源码搜索、依赖图、影响分析和测试目标发现等场景。

  • by adirh3
  • C#
  • 本地部署
  • 更新于
在 GitHub 查看 adirh3/DotSight

使用说明

DotSight

An MCP (Model Context Protocol) server that provides C# solution intelligence to AI coding agents. Built with .NET 10, Roslyn, and the official ModelContextProtocol SDK.

Tools

Tool Description
get_project_graph Bounded project/dependency overview with compact summaries, project filters, and project/file paging; optional TFMs, packages and code outlines
find_symbols Bounded, paged name/regex discovery across source and optional metadata, with exact signatures and source locations
get_symbol_detail Resolve a name or source position to exact symbol/overload and expression type/nullability facts, with declaration/API details
get_source_text Read one symbol/file region or batch up to 20 selections, with line numbers, shared output budgets and checksum-guarded continuations
search_source Compact C# body-text/regex search with scoped files/projects, bounded snippets, exact coordinates and enclosing-symbol selectors; detailed context is opt-in
get_member_context One semantic context packet: target implementation plus bound helper/accessor/operator/field/constant dependencies and relevant source
get_test_targets Recognized statically related test methods, fixture/project/framework evidence and actionable test-runner/filter arguments
get_document_symbols File outline — all symbols defined in a source file with kind, signature, and line numbers
find_references All usages of a symbol across the solution with location info
find_implementations Concrete implementations of interfaces, abstract classes, virtual members
analyze_symbol Byte-bounded impact/call-flow analysis with focused section selection, references, callers, outgoing calls, implementations, overrides and test evidence
preview_rename Roslyn-backed rename preview with exact text edits, base checksums, optional file rename metadata, and opt-in post-rename compiler checks; never writes files
get_diagnostics Compiler errors, warnings, and analyzer diagnostics by scope
inspect_package Inspect resolved or cached package metadata, exact assembly/version provenance, and opt-in non-public API signatures; no runtime assembly loading

All tools are read-only — no modifications to source code or projects.

DotSight tracks saved C# files and relevant MSBuild inputs. When they change, the next tool call reloads a coherent Roslyn solution snapshot. Unsaved editor buffers are intentionally outside the MCP server's view.

Semantic tools accept an exact fully qualified name and optional signature. When overloads or multi-project symbols are ambiguous, use the returned candidates or select the symbol by file, line, and column. DotSight does not silently choose the first overload.

Roslyn workflow shortcuts

These queries replace facts an agent would otherwise reconstruct across searches, source reads, reflection probes and test-runner inspection. They do not edit code or execute tests.

Understand a member and its bound dependencies

{
  "fullyQualifiedName": "Example.Identity.GetIdentity",
  "project": "Example",
  "dependencyDepth": 3,
  "includeTests": true
}

Use this with get_member_context. It collects the implementation and Roslyn-bound helper calls, relevant property reads/writes, fields/constants, constructors and operators (including compound assignments and increments), retaining project ownership and source excerpts. Invoked local functions are followed, but merely declared lambdas/local functions are not assumed to execute. Runtime delegate/dynamic targets remain unresolved rather than guessed.

Ordinary property reads follow the getter; writes, including deconstruction targets, follow the setter. Writes through a ref-returning property follow its getter to obtain the storage. accessorScope identifies the accessors followed. Non-finite float/double constants are represented as the JSON strings "NaN", "Infinity" and "-Infinity"; ordinary constant values retain their JSON types.

The defaults allow 16 dependencies, depth 3 and 120 source lines per member. Check graph limits, source omissions and source.next before assuming the context is complete. Compiler-generated property storage is identified separately from package metadata. Recognized related tests and project/filter arguments are included when they fit; testTargetsOmitted explicitly indicates when to call get_test_targets separately.

Identify the actual test targets and command

{
  "fullyQualifiedName": "Example.Worker.Transform(int)",
  "project": "Example",
  "helperDepth": 0
}

Use this with get_test_targets. Production members are mapped through Roslyn references to recognized attributed test methods, not guessed from names. Direct test methods and fixture types are also accepted. To validate a known set across fixtures/projects in one request, use fullyQualifiedNames with 1-16 exact names instead of a single selection.

The result includes framework/attribute evidence, a bound reference location/snippet, bounded test-method source, relation/depth, fixture lifecycle identities and project-grouped argv (including dotnet, owning csproj and filter). helperDepth=1 permits one intermediate source member; use 0 for strictly direct relationships. Framework recognition supports xUnit, NUnit and MSTest attributes. Unknown configuration or unsupported Microsoft.Testing.Platform commands are explicit and have no invented argv. Generic/parameterized forms may need a reported conservative fixture filter.

These are static targets, not runtime discovery or exhaustive coverage. Run the returned base command with appropriate existing build options and verify a nonzero test count. No --no-build, target framework, or execution success is assumed.

Ask what code at a position actually binds to

{
  "file": "Services\\Worker.cs",
  "line": 42,
  "column": 20,
  "project": "Example"
}

Use this with get_symbol_detail. A method identifier selects its invocation and reports the exact compile-time overload, generic/reduced-extension facts, assembly/declaration identity, actual/converted types, nullable annotations/flow and Roslyn candidate reason. Direct argument details include parameter bindings and conversions, including expanded params arrays/collections; referenced locals/parameters carry their declaration/type evidence. A lambda with no inherent type is reported as null, not as a failed lookup.

Names/signatures remain supported. Positions are one-based UTF-16. Ambiguous project contexts and failed overload binding stay explicit. Named type/member information is now under symbol; source answers add binding, semantics, arguments and bounded diagnostics. Check omissions rather than assuming every type member or argument was emitted.

Inspect the exact API metadata already available

{
  "packageName": "Example.SDK",
  "version": "1.2.3",
  "targetFramework": "net10.0",
  "typeFilter": "Example.Session",
  "includeNonPublic": true,
  "memberFilter": "Dispatch"
}

Use this with inspect_package. The resolver first uses actual compilation/restore context. Explicit cached versions can be inspected without a temporary build and without substituting a different active version. project selects an exact consuming project name, ID or absolute project path; ambiguous project/version/asset contexts return candidates. targetFramework selects a verified restore target or cached asset group, not a framework guessed from C# language version.

includeNonPublic=true reimports metadata using Roslyn's all-member import mode. accessibilityFilter can narrow internal/private/etc. declarations; containing types are retained when their members match. Explicit static/instance, return and parameter fields accompany signatures. Assembly identity/path/hash, package manifest/version evidence, asset framework and source/reference-assembly limitations are returned together. Where the local package archive exists, the named asset's bytes are compared to the cached assembly; this is not a package-signature/authenticity attestation. Source-project references and cached NuGet assets are distinguished. Reference assemblies may lack private metadata; verified restored implementation assets are used when available.

This is declaration metadata, not IL decompilation or runtime assembly execution. The existing temporary restore/build fallback remains only for genuinely unavailable package inspection; it never modifies the current project.

Efficient source investigation

Choose the narrowest tool instead of loading a full graph or large class first:

  • Known file or simple literal check: native file/glob/text tools can be cheaper, especially before the semantic workspace is loaded. DotSight adds exact semantic navigation; it is not a requirement to replace every file read or grep.
  • Known symbol: use find_symbols when necessary, then pass its exact name/signature to get_source_text or analyze_symbol.
  • Known message or body text: use search_source. It returns matching context, exact coordinates and an enclosing-symbol selector in one request. Text matches are not proof of semantic references.
  • Several related declarations: use get_source_text with requests to share one workspace snapshot, project default and response budget. An item's project overrides the shared default:
{
  "project": "Example",
  "requests": [
    { "fullyQualifiedName": "Example.Worker.Start" },
    { "fullyQualifiedName": "Example.Worker.Stop" },
    { "file": "Services\\Worker.cs", "startLine": 40, "endLine": 65 }
  ],
  "maxOutputBytes": 16384
}

get_source_text, find_symbols, search_source, analyze_symbol, and get_project_graph default to 16 KiB of UTF-8 JSON, including result metadata. maxOutputBytes accepts 4096-65536 bytes, but inline safety caps the effective budget at 16384 unless allowLargeOutput=true. outputBudget reports any reduction. This prevents clients from replacing large answers with temporary-file notices even when an agent requests an oversized budget. Opt into larger results only when your client can consume them.

The budget applies to the tool's returned JSON, before the MCP transport envelope; it is not a token or elapsed-time guarantee. Prefer scoped search/outline queries before whole-file reads, and batch independent known selections rather than requesting several large files upfront. No dependencies are installed, builds run, or application code executed by these queries.

Source bounds and continuations

Single-source calls retain the file, startLine, endLine, totalLines and line-numbered source fields. Both file and symbol requests now obey maxLines (default 200, configurable from 1 to 2000) and the shared byte budget; previously whole-symbol responses were unbounded. Check status, truncated, and next rather than assuming the requested source was returned in full.

  • Pass a returned next object as the next single request, or put it inside a new requests batch. It contains the exact remaining range and expectedChecksum; changed source yields content_changed, not a silently stitched result.
  • Batches preserve request order and report each processed item's status. nextRequestIndex identifies requests not processed within the shared budget; retry those as well as any individual next continuations. complete is false if any selection failed, was truncated, or was not processed.
  • Source columns are one-based UTF-16 positions. startColumn and an exclusive endColumn support long-line/mid-declaration paging without losing characters or splitting surrogate pairs. With no endColumn, endLine is inclusive.
  • Symbol requests select one declaration. Partial symbols report declarationIndex and declarationCount; request each part explicitly when needed.
  • Checksums are SHA-256 over the decoded source re-encoded as UTF-8, not checksums of original on-disk encoding bytes. Saved solution documents share the acquired Roslyn snapshot. Other files retain the disk-read fallback, are labeled origin: "disk", and use content checksums rather than claiming workspace snapshot consistency. A shared project also scopes resources such as XAML beneath that project's directory; it does not select compiled documents belonging to another project.
  • Linked/multi-target files require an unambiguous project for source retrieval. Invalid selections return structured errors; a bad item does not hide other successful batch items.

Content search

{
  "pattern": "case (AssistantTurnEndEvent|SessionIdleEvent)",
  "useRegex": true,
  "project": "Example",
  "fileFilter": "Services\\SessionService.cs",
  "contextLines": 2,
  "maxResults": 20
}

Search is case-insensitive and compact by default. Compact matches keep readable file/project/coordinate fields, short context (up to 64 surrounding characters per side) and exact enclosing-symbol selectors. Repeated project/document IDs are stored once in documents, referenced by each match's documentIndex; linked contexts remain distinguishable. Set compact=false for the original detailed per-match metadata and wider requested context. The complete match is never clipped.

fileFilter is a solution-relative path substring, not a glob; both separator styles work. Regex searches have a 100 ms timeout per match operation. Returned matches include clipping/range metadata. Unfit hits and regex timeouts produce explicit errors, not misleading empty success.

Follow nextOffset with the same query/scope and expectedSnapshotVersion from workspace.version; positive offsets require it. matchedAtLeast is a lower bound, not an invented total, and scanComplete distinguishes an exhausted scan from a result-limited scan. Enclosing-symbol information is computed only for returned matches.

Search covers normal C# documents loaded in the snapshot, preserving linked project/document identities. Conventional obj/bin and generated suffix paths are excluded unless includeGenerated=true. Source-generator output, additional documents such as XAML, and arbitrary files outside the snapshot are not searched.

Symbol discovery

find_symbols returns compact count/symbols pages rather than spilling large lists of names and documentation. Use a project and kind filter when known, and follow nextOffset with the same query and expectedSnapshotVersion. Exact signatures and locations remain available for overload selection. XML summaries require includeDocumentation=true; metadata references remain opt-in. A bounded page is not proof that all matches were returned.

Compact project maps

Use summaryOnly=true with a case-insensitive projectFilter for project identity/count questions. Summary mode explicitly omits packages, references, edges, files and outlines. Exact project selection remains available.

Detailed maps support projectOffset/maxProjects and project-relative fileFilter, fileOffset/maxFiles. Follow nextProjectOffset and per-project filePage.nextFileOffset with expectedSnapshotVersion from snapshot.version; nonzero offsets require it, and changed versions are rejected. Nonzero file offsets also require one matching project and projectOffset=0. Edges describe outgoing dependencies of returned projects, including targets outside the selected scope.

Always inspect truncated, budgetLimited and omittedDetails. Oversized dependency/package sections are explicitly omitted with retry guidance. File offsets do not split a single oversized outline: use a scoped source/symbol query instead of assuming a missing outline is empty.

Focused impact analysis

analyze_symbol accepts sections containing references, incomingCalls/callers, outgoingCalls/callees, implementations, or overrides. Omit it for all sections. A byte-limited combined response preserves original totals and test-reference counts while marking shortened section lists as truncated. byteLimited and the response hint identify this case; request individual sections for more focused evidence. Section selection currently projects one computed analysis rather than skipping semantic computation, so it is an output-size control, not a latency promise.

Installation

dotnet tool install -g DotSight --prerelease

Setup

Add DotSight to your VS Code user MCP config (one-time setup, works for all C# workspaces):

Ctrl+Shift+P → "MCP: Open User Configuration":

{
  "servers": {
    "dotsight": {
      "type": "stdio",
      "command": "dotsight"
    }
  }
}
}

DotSight auto-detects the .sln file from the workspace directory. If you have multiple solutions or need to specify one explicitly, use --solution:

{
  "mcp": {
    "servers": {
      "dotsight": {
        "type": "stdio",
        "command": "dotsight",
        "args": ["--solution", "${workspaceFolder}/MyApp.sln"]
      }
    }
  }
}

You can also use a per-workspace .vscode/mcp.json if you prefer.

Running from source

dotnet run -- --solution /path/to/YourSolution.sln

Building

dotnet build
dotnet pack   # produces a .nupkg for tool installation