mcpField
C
C# Class Analyzer MCP

C# Class Analyzer MCP

本地服务
github.com开发工具11 周前更新

关于 C# Class Analyzer MCP

CSharpAnalyserMcp 是供 AI 助手和开发者浏览 C# 解决方案的只读 MCP 服务。它使用 Roslyn 提供针对声明、文档、继承关系和方法源码的查询,避免将整个文件读入上下文。

主要功能

  1. 01按文件夹或命名空间列出类型
  2. 02获取类型文档和成员签名
  3. 03查看方法签名、文档和方法体
  4. 04追踪继承关系与方法重写
  5. 05使用正则表达式搜索源码
  6. 06刷新缓存的解决方案快照

适用场景

  1. 01在大型 C# 解决方案中查找类型
  2. 02无需加载整个文件即可检查方法
  3. 03追踪实现和继承关系
  4. 04搜索符合模式的 C# 源码

MCP 相关

服务通过 stdio 通信,并将只读 Roslyn 查询作为 MCP 工具提供。它在 MCP 握手前将指定解决方案载入缓存快照。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

暂未收录安装方式

我们还没有获取到这个服务的安装包或远程地址,请按项目 README 中的说明安装。

代码仓库
安装包
nugetCSharpAnalyserMcp1.0.4

工具

还没有获取到工具列表

本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。

详细介绍

English | 简体中文

CSharpAnalyserMcp

一个只读的 Model Context Protocol(MCP)服务,可让 AI 助手通过 Roslyn 浏览任意 C# 解决方案。

该服务使用 MSBuildWorkspace 将解决方案加载到缓存的 Roslyn 快照中,然后回答关于解决方案的结构化查询:每种类型的声明位置、XML 文档,以及方法的签名、文档、源代码位置和主体。因此,Agent 可以提取所需的确切源代码片段,而不必将整个文件读入上下文窗口。

  • 传输方式:stdio(StdioServerTransport),协议流量仅通过 stdout 输出;所有日志均写入 stderr。
  • 解决方案路径通过命令行传入(--workspace <path to .sln>);解决方案在 MCP 握手之前加载,因此路径无效时会立即失败,在 stderr 输出消息并以非零退出代码退出。
  • 每个工具都返回 MCP 文本内容,从不返回 structuredContent:列表/层级/搜索工具每个条目返回一个文本块(从客户端角度看是字符串列表);详情工具则输出 path / desc / namespace / signature / body 块,各块之间以包含 --- 的行分隔。
  • 分发方式:以 .NET 工具 CSharpAnalyserMcp(命令 csharp-analyser-mcp)发布到 NuGet,并以 io.github.undy-mosq/CSharpAnalyserMcp 列入官方 MCP Registry。

安装

NuGet .NET 工具(推荐)
dotnet tool install --global CSharpAnalyserMcp
csharp-analyser-mcp --workspace D:\MyProject\MySolution.sln

# upgrade / remove
dotnet tool update --global CSharpAnalyserMcp
dotnet tool uninstall --global CSharpAnalyserMcp

请全局安装:--local 安装只会写入清单条目,因此 csharp-analyser-mcp 不会出现在 PATH 中,MCP 客户端也无法启动它。

使用 dnx 按需运行(无需安装,.NET SDK 10+)
# "--" separates dnx options from the arguments forwarded to the server
dnx CSharpAnalyserMcp --yes -- --workspace D:\MyProject\MySolution.sln
从源代码构建
git clone https://github.com/undy-mosq/CSharpAnalyserMcp
dotnet build CSharpAnalyserMcp\CSharpAnalyserMcp.csproj
dotnet run --project CSharpAnalyserMcp -- --workspace D:\MyProject\MySolution.sln

要求

用途要求
运行已发布的工具(dotnet tool install --global)PATH 中需有 .NET SDK 8.0 或更高版本(该包面向 net8.0)
使用 dnx 按需运行.NET SDK 10.0 或更高版本 — dnx 随 SDK 一同提供
从源代码构建/运行.NET SDK 8.0 或更高版本(项目面向 net8.0)
加载要分析的解决方案能够打开该解决方案的 MSBuild 工具链 — Visual Studio 2022 或 VS Build Tools(Microsoft.Build.Locator 会注册最新安装的实例),或用于 SDK 风格项目的 .NET SDK 本身

客户端配置

该服务使用单个参数启动:--workspace,指向解决方案文件。

已安装的 .NET 工具

全局工具启动器位于 %USERPROFILE%\.dotnet\tools。MCP 客户端会自行启动进程,且只能看到继承的 PATH,因此请使用绝对路径指向启动器(展开 %USERPROFILE%,例如 C:\Users\you\.dotnet\tools\csharp-analyser-mcp.exe):

Claude Desktop(claude_desktop_config.json):

{
  "mcpServers": {
    "csharp-analyser": {
      "command": "C:\\Users\\you\\.dotnet\\tools\\csharp-analyser-mcp.exe",
      "args": ["--workspace", "D:\\MyProject\\MySolution.sln"]
    }
  }
}

VS Code(.vscode/mcp.json):

{
  "servers": {
    "csharp-analyser": {
      "type": "stdio",
      "command": "C:\\Users\\you\\.dotnet\\tools\\csharp-analyser-mcp.exe",
      "args": ["--workspace", "D:\\MyProject\\MySolution.sln"]
    }
  }
}

仅当该目录已在客户端的 PATH 中时,裸命令名("command": "csharp-analyser-mcp")才有效;在安装工具之前启动的客户端会保留旧环境,因此更改 PATH 后请重启客户端。

使用 dnx 按需运行(无需安装)
{
  "servers": {
    "csharp-analyser": {
      "type": "stdio",
      "command": "dnx",
      "args": ["CSharpAnalyserMcp", "--yes", "--", "--workspace", "D:\\MyProject\\MySolution.sln"]
    }
  }
}

在包 ID 后追加 @<version> 可固定版本。NuGet 包页面的 MCP Server 选项卡提供了相同的 JSON,可供复制。dnx 是一个 .cmd 启动器;如果客户端无法启动它,请改用等效的 dotnet 形式:"command": "dotnet",并设置 "args": ["tool", "exec", "CSharpAnalyserMcp", "--yes", "--", "--workspace", "D:\\MyProject\\MySolution.sln"]。

已发布的可执行文件

VS Code(.vscode/mcp.json):

{
  "servers": {
    "csharp-analyser": {
      "type": "stdio",
      "command": "C:\\Tools\\csharp-analyser\\CSharpAnalyserMcp.exe",
      "args": ["--workspace", "D:\\MyProject\\MySolution.sln"]
    }
  }
}
从源代码运行项目
{
  "servers": {
    "csharp-analyser": {
      "type": "stdio",
      "command": "dotnet",
      "args": [
        "run",
        "--project",
        "D:\\MyProject\\CSharpAnalyserMcp\\CSharpAnalyserMcp\\CSharpAnalyserMcp.csproj",
        "--",
        "--workspace",
        "D:\\MyProject\\MySolution.sln"
      ]
    }
  }
}

在 VS Code 中按 F5 可调试服务本身;.vscode/launch.json 已传入 --workspace 参数 — 请将其指向你自己的解决方案。

工具

工具MCP 注解用途
list_classes_in_folder只读列出文件夹及其子文件夹中的类型声明(每种类型对应一段文本)
list_classes_in_namespace只读列出命名空间中的类型声明(可选包含子命名空间;每种类型对应一段文本)
get_class_documentation只读返回根据类型声明行定位的类型的 XML 文档和成员签名
get_method只读根据方法声明行及其所属类型的声明行定位方法,并返回其签名、XML 文档、位置和方法体
find_inheritance只读列出类型的派生类型树(第一项为类型本身)
find_method_overrides只读列出方法的重写项/实现项(第一项为方法本身)
search_regex只读使用正则表达式逐行搜索目录/文件(默认仅搜索 *.cs);每个匹配项对应一段文本
reload_solution幂等源文件更改后重新构建 Roslyn 快照
set_resolve_base_path幂等更改用于解析相对路径的目录
list_classes_in_folder
{ "folderPath": "src/Services", "kinds": ["class", "interface"] }
参数类型默认值描述
folderPathstring,必填—绝对路径,或相对于解析基目录的路径(默认为解决方案目录)。
kindsstring[]["class"]要包含的类型种类(参见类型种类与 kinds)。

会跳过 bin/obj 下的文件。返回字符串列表,每种类型对应一段文本,格式为 {relativePath} L{start}-{end} {namespace}: {signature};对于全局命名空间,会省略命名空间部分;对于 partial 类型,会报告其首个声明的位置,并在末尾附加 ...(partial xN)。

list_classes_in_namespace
{ "namespaceName": "MyApp.Services", "includeSubNamespaces": true, "kinds": ["all"] }
参数类型默认值描述
namespaceNamestring全局命名空间命名空间名称,例如 MyApp.Services。空值、global、global namespace 或 <global namespace> 均表示全局命名空间。
includeSubNamespacesbooltrue同时包含在子命名空间中声明的类型。
kindsstring[]["class"]要包含的类型种类。
get_class_documentation
{ "typeDeclaration": "public static class ItemConfig", "maxXmlChars": 2000 }
参数类型默认值描述
typeDeclarationstring,必填—类型的声明行(列表工具输出的 signature 部分),例如 public static class ItemConfig。去除空白字符后,必须与规范签名或声明的第一行源码完全匹配。
namespaceNamestring任意命名空间类型所属的命名空间;空值或 global 表示全局命名空间。
maxXmlCharsint2000每种类型原始 XML 文档的最大字符数(desc 字段);0 = 无限制。

匹配成功时,结果为一个文本块:path/desc/namespace(全局命名空间显示为 global)/signature/body(成员签名,每行一个);多个匹配项之间用仅包含 --- 的行分隔。未匹配时,会输出 (no match),随后是 candidates : 和候选声明行。

get_method
{ "methodDeclaration": "public static void SetEffect(RoleAttributes owner, int stack)", "typeDeclaration": "public class RoleAttributes", "namespaceName": "DuelModel" }
参数类型默认值描述
methodDeclarationstring,必填—方法的声明行,例如 public static string TextName(this ItemInfo.ItemType itemType)。方法名称及其参数类型会从此文本中解析。
typeDeclarationstring,必填—声明该方法的类/接口/结构体的声明行,例如 public static class ItemConfig。
namespaceNamestring任意命名空间声明类型所在的命名空间;为空或为 global 表示全局命名空间。
maxBodyCharsint8000方法体的最大字符数;0 = 不限。

匹配规则:

  • 两条声明行都必须在去除空白后,与规范签名或声明的首个源代码行完全匹配(不进行子字符串匹配)。
  • 只搜索该类型自身声明的成员(普通方法;不包括继承成员、构造函数或属性)。也会匹配显式接口实现(IFoo.Bar)。
  • 从声明行解析出的参数类型会以忽略大小写和空白的方式进行比较,且不包含命名空间前缀;C# 别名会映射为其元数据名称(int → Int32、string → String,……)。比较会逐步放宽:完全匹配 → 忽略泛型参数 → 允许参数列表前缀匹配。
  • 未匹配时,会打印 (no match),随后是 candidates : 和候选声明行(先列出该类型中同名的方法,否则列出该类型的所有方法)。

每个重载对应一个文本块,包含:path / desc(原始 XML 文档,最多 2000 个字符)/ namespace / class / signature / body(移除最外层花括号和公共缩进后的源代码);重载之间以单独一行 --- 分隔。

find_inheritance
{ "typeDeclaration": "public abstract class BuffEntity", "namespaceName": "Duel" }
参数类型默认值描述
typeDeclarationstring,必填—类/接口/结构体/记录的声明行。
namespaceNamestring任意命名空间类型所在的命名空间;为空或为 global 表示全局命名空间。

第一项是所查询的类型本身(无缩进、无前缀);每个派生类型随后作为独立文本内容列出,缩进一个制表符,并按层级在前面加上 -。类根类型会列出派生自它的类/记录;接口根类型会列出子接口,以及直接实现它的类/结构体/记录。泛型基类型通过 OriginalDefinition 匹配(Base<T> 和 Base<int> 视为同一基类型)。每个类型只出现一次,取其最浅层级;未匹配时,会打印 (no match),随后是 candidates : 和候选声明行。

find_method_overrides
{ "methodDeclaration": "public abstract void Apply(BuffEntity buff)", "typeDeclaration": "public abstract class BuffEntity", "namespaceName": "Duel" }
参数类型默认值描述
methodDeclarationstring,必填—方法的声明行。
typeDeclarationstring,必填—声明该方法的类/接口/结构体的声明行。
namespaceNamestring任意命名空间声明类型所在的命名空间;为空或为 global 表示全局命名空间。

第一项是方法本身;实现/重写随后作为独立文本内容列出,缩进一个制表符,并按层级在前面加上 -。接口成员根方法会列出所有实现类型中的实现方法(包括显式 IFoo.Bar 实现);类方法根方法会列出派生类中的 override。只报告向下方向,不会向上追溯基类声明。未匹配时,会打印 (no match),随后是 candidates : 和候选声明行。

search_regex
{ "path": "src/Services", "pattern": "public\\s+\\w+\\s+Get", "fileFilters": ["*.cs"] }
参数类型默认值描述
pathstring,必需—目录或文件:绝对路径,或相对于解析基目录的路径。
patternstring,必需—.NET 正则表达式,逐行匹配(默认区分大小写;使用 (?i) 可忽略大小写)。
fileFiltersstring[]["*.cs"]文件名 glob(* / ?,不区分大小写;多个模式之间为 OR 关系);当 path 是文件时忽略。
  • 递归搜索目录;跳过 bin / obj / .git 和符号链接目录。文件路径则直接搜索。
  • 每个匹配项对应一条文本内容:{relativePath} L{line}: {line text}(行文本会去除首尾空白)。
  • 最多返回 1000 个匹配项;结果被截断时,会追加一条 ... [truncated: showing 1000 of N matches]。
  • 直接读取磁盘上的文件,因此不受 Roslyn 快照 / reload_solution 影响。
  • 路径不存在或正则表达式无效时,会在文本中返回原因并设置 isError;没有匹配项时返回 (no match)。
reload_solution

无参数。丢弃缓存的快照并重新打开解决方案,因此后续查询会读取磁盘上的当前文件。输出 solution / resolveBaseDirectory / projects / reloaded : true ({ms} ms)。

set_resolve_base_path
{ "basePath": "src" }
参数类型默认值描述
basePathstring解决方案目录绝对路径,或相对于当前基目录的路径。留空 / 省略时恢复默认值(解决方案文件所在目录)。

类型种类和 kinds

kind 使用小写,且各值互斥:class、static class、record、struct、record struct、interface、enum、delegate。只有类可以是 static,因此 class 和 static class 是不同的类型;结构体、枚举、接口和委托没有静态形式。

kinds 筛选器不区分大小写,并接受多个值(省略 kinds 时,行为等同于 ["class"]):

kinds 值匹配项
(省略) / class所有类,包括静态类和记录
static / static class仅静态类
record记录和记录结构体
struct结构体和记录结构体
record struct仅记录结构体
enum / interface / delegate对应种类
all所有类型

同一张表、声明行协议(严格匹配 typeDeclaration / methodDeclaration 并通过 candidates 进行恢复)以及文本输出格式都会在 initialize 握手期间作为服务端级别的指令发送给客户端(参见 Tools/ServerInstructions.cs),因此模型无需猜测可接受的值或输出格式。

输出格式

每个工具都会返回 MCP 文本内容,不会返回 structuredContent。列表 / 层级 / 搜索工具会为每个条目返回一条文本内容,因此客户端收到的是字符串列表,而非以换行符连接的单个文本块。路径显示为相对于解析基目录的路径(默认为解决方案所在目录),并使用 / 作为分隔符。

列表(list_classes_in_folder / list_classes_in_namespace)

每种类型对应一条文本内容(工具返回字符串列表):

{relativePath} L{start}-{end} {namespace}: {signature}

全局命名空间会省略命名空间段(仅保留 :);partial 类型会显示其首个声明的位置,后接 ...(partial xN);未找到匹配项时返回单条 (no match)。

script/config/ItemConfig.cs L14-163: public static class ItemConfig
src/Services/UserService.cs L12-88 MyApp.Services: public class UserService : BaseService
类型详情(get_class_documentation)

每个同名类型对应一个文本块,各块之间以包含 --- 的行分隔:

path : {relativePath} L{start}-{end}
desc :
{raw XML documentation, truncated to maxXmlChars; the whole section is omitted when there is none}
namespace : {namespace; the global namespace prints as global}
signature : {modifiers + kind + name + type/primary-constructor parameters + constraints + base list}
body :
{member signatures, one per line: enum members / fields / properties / methods / events / nested types; omitted when there are none}
方法详情(get_method)

每个重载对应一个文本块,各块之间以包含 --- 的行分隔:

path : {relativePath} L{start}-{end}
desc :
{raw XML documentation, 2000-char cap}
namespace : {namespace}
class : {type name}
signature : {modifiers + return type + name + parameters (including this / ref / out / in / params)}
body :
{method source: block bodies lose their outermost braces and common indentation, expression bodies lose "=>"}

未找到匹配项时,会打印 (no match),随后是 candidates : 和候选声明行(简要行格式,可直接复制到声明参数中):

(no match)
candidates :
script/config/ItemConfig.cs L16-39: public static string TextName(this ItemInfo.ItemType itemType)
script/config/ItemConfig.cs L40-120: public static void RegisterItem(ItemModel model)
层级(find_inheritance / find_method_overrides)

第一项是查询的类型 / 方法本身(不缩进,也没有 -);派生类型 / 实现作为各自的文本内容列出,每个层级缩进一个制表符,并以 - 为前缀:

script/config/BuffEntity.cs L12-40 Duel: public abstract class BuffEntity
	-script/config/DamageBuff.cs L8-25 Duel: public class DamageBuff : BuffEntity
		-script/config/BurnBuff.cs L6-18 Duel: public class BurnBuff : DamageBuff
	-script/config/HealBuff.cs L9-20 Duel: public class HealBuff : BuffEntity

没有匹配项时,会返回单个 (no match) 项;如果有候选项,后面会列出 candidates : 和候选声明行。

正则搜索(search_regex)

每个匹配项都是一个文本内容:

src/Services/UserService.cs L42: public User GetById(int id)

没有匹配项时,会返回单个 (no match) 项;匹配项超过 1000 个时,会在末尾追加一条截断提示。

工作区(reload_solution / set_resolve_base_path)
solution : {absolute path of the solution file}
resolveBaseDirectory : {resolve base directory}
projects : {project count}
reloaded : true ({ms} ms)

输出限制

较长的内容会被截断,以缩小工具结果;追加的标记格式为 ... [truncated: showing {n} of {m} chars]。所有阈值均在 Services/TextTruncator.cs 中设置。

内容默认限制如何提高限制
desc(XML 文档)2000 个字符在 get_class_documentation 中使用 maxXmlChars(get_method 固定为 2000)
方法 body8000 个字符在 get_method 中使用 maxBodyChars

将 0 传给 maxXmlChars / maxBodyChars,即可在本次调用中禁用截断。

典型工作流

  1. 使用指向解决方案的 --workspace 启动一次服务(MCP 客户端会自动完成此操作)。
  2. 查找类型:list_classes_in_namespace { "namespaceName": "MyApp.Services" } 或 list_classes_in_folder { "folderPath": "src/Services", "kinds": ["all"] };若要查找特定字符串,请使用 search_regex { "path": "src", "pattern": "..." }。
  3. 通过从列表中复制类型的声明行,读取其契约:get_class_documentation { "typeDeclaration": "public class UserService : BaseService" }。
  4. 读取确切的实现:get_method { "methodDeclaration": "public User GetById(int id)", "typeDeclaration": "public class UserService : BaseService" }。
  5. 遍历层级:find_inheritance { "typeDeclaration": "public abstract class UserServiceBase" } 或 find_method_overrides { "methodDeclaration": "public abstract User GetById(int id)", "typeDeclaration": "public abstract class UserServiceBase" }。
  6. 源文件发生更改后,在下一次查询前调用 reload_solution,否则查询仍会基于过期快照返回结果。

故障排除

  • 服务立即退出,并在标准错误中显示 Solution file not found(或其他 MSBuild 错误)→ --workspace 路径错误;必须指向解决方案文件,而不是文件夹。
  • 客户端的 MCP 日志中显示 The command "dnx" was not found → dnx 随 .NET SDK 10 及更高版本提供。请安装 .NET SDK 10,或改用已安装的工具或已发布的可执行文件。
  • dotnet tool install 报告该软件包不是 .NET 工具 → 你指定的版本在启用 PackAsTool 之前就已打包;请改为安装当前版本(dotnet tool list --global 可显示已安装的工具)。
  • 客户端日志中显示 spawn csharp-analyser-mcp ENOENT 或 MCP error -32000: Connection closed → 客户端无法解析被告知要运行的命令。请使用 %USERPROFILE%\.dotnet\tools\csharp-analyser-mcp.exe 的绝对路径(--local 安装完全不会在此处提供 shim),然后重启客户端。
  • 发布后立即出现 Cannot find package CSharpAnalyserMcp with version x.y.z → NuGet 索引可能晚于发布更新。请稍后重试,或从已下载的 .nupkg 安装:dotnet tool install -g --add-source <folder> CSharpAnalyserMcp --version x.y.z。

行为说明与限制

  • 快照语义。 解决方案只会从磁盘读取一次;只有调用 reload_solution 后,文件编辑才会生效。未保存的编辑器缓冲区始终不可见。
  • 正则表达式搜索读取磁盘。 search_regex 直接读取文件,绕过 Roslyn 快照;默认搜索 *.cs,递归时跳过 bin/obj/.git,最多返回 1000 个匹配项。
  • 仅查看源代码。 会跳过 bin/obj 下的语法树,因此不会报告没有源代码声明的类型。
  • 仅限已声明成员。 get_method 不会遍历基类型、接口或 partial 类型的其他部分。
  • 名称必须完全匹配。 类型和方法名称必须完全匹配;命名空间按完整显示字符串进行比较。使用 namespaceName(或带限定名的 className)来区分。
  • 开销。 每次查询都会请求每个项目生成其编译,因此响应时间会随着解决方案规模增大而变长。
  • 诊断信息。 工作区加载问题会以 [WorkspaceFailed] {Kind}: {Message} 的格式写入 stderr;stdout 中只会输出 JSON-RPC 内容。
  • 每个进程仅支持一个解决方案。 工作区路径在启动时固定;要分析其他解决方案,请启动另一个实例。

许可证

MIT — 参见 LICENSE。


构建、发布和版本发布流程:docs/DEVELOPMENT.zh-CN.md(中文)。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。