Atypical-Consulting/RoselineMCP
GitHub: Atypical-Consulting/RoselineMCP
RoselineMCP 将 Roslyn 编译平台封装为 MCP 服务器,让 AI 编程 Agent 以结构化方式导航和编辑 C# 代码,大幅降低 token 消耗。
Stars: 1 | Forks: 0
# RoselineMCP
[](https://github.com/Atypical-Consulting/RoselineMCP)
[](https://opensource.org/licenses/MIT)
[](https://dotnet.microsoft.com/)
[](https://github.com/Atypical-Consulting/RoselineMCP)
[](https://github.com/Atypical-Consulting/RoselineMCP)
[](https://github.com/Atypical-Consulting/RoselineMCP/releases/)
[](https://github.com/Atypical-Consulting/RoselineMCP/issues)
[](https://github.com/Atypical-Consulting/RoselineMCP/pulls)
[](https://github.com/Atypical-Consulting/RoselineMCP/commits/main)
[](https://github.com/Atypical-Consulting/RoselineMCP/actions/workflows/ci.yml)
[](https://www.nuget.org/packages/RoselineMCP/)
[](https://hub.docker.com/r/phmatray/roseline-mcp)
[](https://atypical-consulting.github.io/RoselineMCP/)
[-1baf7a)](https://atypical-consulting.github.io/RoselineMCP/benchmark)
**📖 [文档、工具参考及真实基准测试 →](https://atypical-consulting.github.io/RoselineMCP/)**
## 目录
- [为什么选择 RoselineMCP](#why-roselinemcp)
- [快速开始](#quick-start)
- [功能](#features)
- [技术栈](#tech-stack)
- [入门指南](#getting-started)
- [MCP 客户端兼容性](#mcp-client-compatibility)
- [可用工具](#available-tools)
- [工具注解](#tool-annotations)
- [工具兼容性策略](#tool-compatibility-policy)
- [架构](#architecture)
- [项目结构](#project-structure)
- [安全性](#security)
- [文档](#documentation)
- [路线图](#roadmap)
- [贡献](#contributing)
- [许可证](#license)
- [鸣谢](#acknowledgments)
## 为什么选择 RoselineMCP
你的编程 Agent 不应该为了修改一个方法而去读取一个 700 行的文件。源代码占据了 Agent 的 token 预算的大头,因此最划算的优化就是停止向它提供整个文件。
RoselineMCP 将 [Roslyn](https://github.com/dotnet/roslyn) 编译平台封装为一个 MCP 服务器。
它不再将源代码直接喂给模型,而是精准地回答*结构性*问题——这个符号在哪使用、谁实现了这个接口、谁调用了这个方法、这个文件的结构是什么——并且它进行**精准的**编辑:成员级别的 diff,而不是整个文件的重写。
在 RoselineMCP 自己的源代码上,与读取相应文件相比,只读导航工具在每个任务中返回的 **token 中位数减少了 89%**(合并且按大小加权后:93%)——[诚实测量,包含表现不佳的用例](https://atypical-consulting.github.io/RoselineMCP/benchmark)。
## 快速开始
任何支持 `dnx`(.NET 中的 `npx` 等价物)的 MCP 客户端都可以按需运行它——无需安装步骤。
需要 .NET 10 SDK。
```
// claude_desktop_config.json · .vscode/mcp.json · ~/.cursor/mcp.json
{
"mcpServers": {
"roseline": { "command": "dnx", "args": ["RoselineMCP", "--yes"] }
}
}
```
然后要求你的 Agent *“找到 `OrderService.Checkout` 的每一个调用方”* 或 *“在整个解决方案中将 `Foo` 重命名为 `Bar`。”* 想要使用固定版本的 NuGet 安装或 Docker?请参阅 [入门指南](#getting-started)。
## 功能
- [x] **高效利用 token 的代码导航** —— 通过 Roslyn 提供符号、引用、调用图、类型层次结构和文件大纲,而不是读取整个文件。每个任务实测 **token 减少中位数达 89%**(合并且按大小加权后:93%)——[查看基准测试](https://atypical-consulting.github.io/RoselineMCP/benchmark)。
- [x] **精准代码编辑** —— 替换/添加/删除成员或在整个解决方案中重命名符号,输出统一的 diff 而非重写整个文件。默认提供预览。
- [x] **全面分析与自动修复** —— 针对整个解决方案的诊断(Roslyn + Roslynator),支持自动修复和可审查的补丁。
- [x] **默认只读** —— 七个导航工具和诊断/补丁工具从不触碰磁盘;三个写入工具需要显式设置 `previewOnly: false`。
- [x] **兼容你的客户端** —— Claude Desktop, VS Code (Copilot / MCP), Cursor。支持通过 `dnx`、NuGet 全局工具或 Docker 安装。
- [x] **诚实、可复现的基准测试** —— 在你自己的解决方案上运行:`dotnet run --project RoselineMCP.TokenBenchmark -c Release`。
## 技术栈
| 层级 | 技术 |
|-------|-----------|
| 运行时 | .NET 10.0 |
| 编译平台 | Roslyn (Microsoft.CodeAnalysis) 5.6.0 |
| 分析器 | Roslynator 4.15.0 |
| MCP SDK | ModelContextProtocol 1.4.0 |
| Diff 引擎 | DiffPlex 1.9.0 |
| 构建系统 | MSBuild 18.7.1 |
| 宿主环境 | Microsoft.Extensions.Hosting 10.0.9 |
## 入门指南
### 前置条件
- **NuGet 全局工具**: .NET 10.0 SDK 或更高版本
- **Docker**: Docker Desktop 或 Docker Engine
- **从源码构建**: .NET 10.0 SDK + MSBuild(包含在 Visual Studio 或 .NET SDK 中)
- **MCP 客户端**: Claude Desktop 或任何兼容 MCP 的客户端
### 安装
**选项 1 -- `dnx`(无需安装步骤)** *(推荐)*
RoselineMCP 提供了一个 [MCP 服务器注册清单](.mcp/server.json),因此任何理解 `dnx` 启动器(.NET 中的 `npx` 等价物——按需解析并运行打包为 NuGet 的工具,无需单独的 `dotnet tool install` 步骤)的 MCP 客户端都可以直接启动它。需要 .NET 10.0 SDK。
```
{
"mcpServers": {
"roseline": {
"command": "dnx",
"args": ["RoselineMCP", "--yes"]
}
}
}
```
将此内容添加到你的 Claude Desktop 或 VS Code MCP 配置中(有关每个客户端的确切文件位置,请参阅下文的 [MCP 客户端兼容性](#mcp-client-compatibility))。
`dnx` 会在首次使用时下载并缓存该工具,因此无需全局预装任何内容。
**选项 2 -- NuGet 全局工具** *(离线 / 固定版本安装)*
需要 .NET 10.0 SDK 或更高版本。
```
dotnet tool install -g RoselineMCP
```
安装完成后,`roseline-mcp` 命令将全局可用。
#### Claude Desktop 配置(NuGet 全局工具)
添加到你的 Claude Desktop 配置文件(`claude_desktop_config.json`)中:
```
{
"mcpServers": {
"roseline": {
"command": "roseline-mcp"
}
}
}
```
**选项 3 -- Docker**
无需 SDK。适用于任何安装了 Docker 的平台。
```
docker run -i --rm phmatray/roseline-mcp:latest
```
#### Claude Desktop 配置
```
{
"mcpServers": {
"roseline": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"phmatray/roseline-mcp:latest"
]
}
}
}
```
**选项 4 -- 从源码构建**
```
git clone https://github.com/Atypical-Consulting/RoselineMCP.git
cd RoselineMCP
dotnet build
dotnet test
```
#### Claude Desktop 配置(从源码构建)
```
{
"mcpServers": {
"roseline": {
"command": "dotnet",
"args": ["run", "--project", "/path/to/RoselineMCP/RoselineMCP.csproj"]
}
}
}
```
## MCP 客户端兼容性
RoselineMCP 使用普通的 stdio MCP 通信,因此它应该能兼容任何支持 MCP 的客户端。下面的代码片段是**文档说明,并未在每种情况下都进行独立验证**——我们已经确认了协议级别的行为(stdio 传输、工具发现、JSON 响应)可以正常工作,但我们并没有亲自对每个客户端自己的配置 UI/文件进行端到端的测试。如果其中某个配置在你的客户端版本中无法按文运行,请提交一个 issue。
## 可用工具
### 1. AnalyzeSolution
分析整个 C# 解决方案以获取诊断信息。只读——从不修改磁盘上的文件。
`pathOrGit` 也接受 `http(s)://` Git URL,该 URL 将被浅克隆到临时目录,分析完毕后将被删除。
```
analyzeSolution({
pathOrGit: "/path/to/solution.sln",
include: "Core", // Optional: only project names containing this substring
exclude: "Test", // Optional: skip project names containing this substring
severity: "warning", // Optional: minimum severity (Error|Warning|Info|Hidden)
maxDiagnostics: 100 // Optional: Maximum diagnostics to return (default: 100)
})
```
**返回:** 解决方案文件名、项目数量、`diagnosticSummary`(按严重程度统计)以及 `topDiagnostics` 数组(包含每个诊断的项目/文件/行/列/ID/严重程度/信息)。
### 2. ListDiagnostics
获取特定项目的详细诊断信息。只读——从不修改磁盘上的文件。
`project` 是**可选的**,并接受与导航工具相同的引用(名称、目录、`.csproj` 或 `.sln` 路径);如果省略,则从工作目录自动发现解决方案/项目。
```
listDiagnostics({
project: "MyProject.csproj", // Optional: name, directory, .csproj, or .sln; auto-discovered if omitted
ids: ["CS0168", "CS0219"], // Optional: Filter by diagnostic IDs
files: ["Controller.cs"], // Optional: substring match against each diagnostic's file path (case-insensitive; NOT a glob pattern)
max: 50 // Optional: Maximum results
})
```
**返回:** 项目名称、`totalDiagnostics` 计数、过滤后的 `diagnostics` 列表、`stats`(按 ID 和严重程度分组的计数),以及 `suggestedFixableIds`——实际上注册了代码修复提供程序的诊断 ID。
### 3. ApplyFixes
为指定的诊断应用自动代码修复。**默认为预览模式**:
`previewOnly` 默认为 `true`,因此在不设置此项的情况下调用此工具绝不会写入磁盘——你必须显式传入 `previewOnly: false` 才能应用更改。`project` 是**可选的**,接受与导航工具相同的引用(名称、目录、`.csproj` 或 `.sln` 路径);如果省略,则从工作目录自动发现解决方案/项目。
```
applyFixes({
ids: ["CS0168", "RCS1001"], // Diagnostic IDs to fix
project: "MyProject.csproj", // Optional: name, directory, .csproj, or .sln; auto-discovered if omitted
previewOnly: false // Optional (default: true). Set false to write changes to disk.
})
```
**返回:** 项目名称、`fixedCount`、`fixersApplied`(实际修复的诊断 ID)、`changedFiles`(相对于解决方案根目录,使用正斜杠——与导航工具的基础路径相同)、统一的 diff `patch`、`notes`(跳过/失败的 ID 和状态消息),以及回显是否写入了任何内容的 `previewOnly`。
### 4. CreatePatch
在两个文本版本之间生成统一的 diff。只读——纯粹对提供的字符串进行操作,从不触碰文件系统。
```
createPatch({
before: "original code",
after: "modified code",
fileName: "Example.cs", // Optional: For display in diff
ignoreWhitespace: false, // Optional: ignore whitespace-only differences
ignoreCase: false // Optional: ignore case differences
})
```
**返回:** 统一的 diff `patch`、`hasChanges`、`linesAdded`、`linesRemoved`,以及用于 diff 头部的 `fileName`/`summary`。
### 代码导航工具(只读)
这些工具返回**精确的结构而不是整个文件**,因此 AI Agent 可以在代码库中定位自身,同时消耗的 token 比直接读取源代码要少得多。所有工具都是只读的,并且接受一个**可选的** `project`(名称、目录、`.csproj` 路径或 `.sln` 路径)——如果省略,RoselineMCP 将从其工作目录自动发现解决方案/项目。当项目属于某个解决方案时,将加载整个解决方案,并且符号搜索/解析将跨越其中的每个项目(包括请求的项目未引用的同级项目),因此引用/重命名是跨项目的。请求/响应结构在 [docs/API.md](docs/API.md) 中。
#### 5. SearchSymbols
通过通配符/子字符串名称模式查找符号,或勾勒单个文件的大纲。
```
searchSymbols({
project: "MyApp.Core",
query: "*Service", // Substring, or wildcard with * and ? — omit to outline a file
file: "UserService.cs", // Optional: restrict to one file, or outline it when query omitted
kinds: ["class", "method"], // Optional: filter by kind (also accepts "type" / "member")
max: 50 // Optional (default: 50)
})
```
**返回:** `symbols`(名称、fullName、种类、签名、文件、行——文件路径相对于解决方案根目录;而单文件大纲则返回名称、种类、签名、行、containingType),`totalFound`,`truncated`(未受限限制时省略)。
#### 6. GetSymbolInfo
紧凑的“转到定义”:符号的声明元数据以及(可选)其源代码。
```
getSymbolInfo({
project: "MyApp.Core",
symbol: "Acme.Users.UserService.GetUser", // Simple or fully-qualified name
includeSource: true // Optional (default: true)
})
```
**返回:** 名称、fullName、种类、签名,以及(为空/不存在时省略)修饰符、baseTypes、接口、文档、definitionFile/Line 和源代码。可访问性已经是 `signature` 的一部分;`definitionFile` 相对于解决方案根目录。
#### 7. FindReferences
在整个解决方案中符号的每个使用位置,以位置+单行代码片段的形式呈现。
```
findReferences({ project: "MyApp.Core", symbol: "GetUser", includeDefinition: false, max: 100 })
```
**返回:** `references`(文件——相对于解决方案根目录,行,代码片段),`totalReferences`,`truncated`(未受限限制时省略)。
#### 8. FindImplementations
接口/成员的实现、虚函数/抽象成员的重写,或类的派生类型。
```
findImplementations({ project: "MyApp.Core", symbol: "IRepository", max: 100 })
```
**返回:** `implementations`(符号摘要),`totalFound`,`truncated`。
#### 9. GetCallGraph
方法的具有深度限制的调用方和/或被调用方图,并带有循环检测。
```
getCallGraph({
project: "MyApp.Core",
method: "Handle",
direction: "callers", // "callers" (default) | "callees" | "both"
depth: 1, // 1-3 (default: 1)
max: 50 // Optional: nodes expanded per direction
})
```
**返回:** 由节点组成的 `callers`/`callees` 树(带有简单参数类型名称的 fullName、文件——相对于解决方案根目录、行、truncated、children)。调用 GetSymbolInfo 以获取节点的完整签名。
#### 10. GetTypeHierarchy
类型的基类链、已实现的接口和/或派生类型。
```
getTypeHierarchy({
project: "MyApp.Core",
type: "SqlRepository",
direction: "both", // "base" | "derived" | "both" (default)
max: 100 // Optional: maximum derived types returned (default: 100)
})
```
**返回:** `baseTypes`、`interfaces`、`derivedTypes`(作为符号摘要)。
#### 13. GetSymbolAtPosition
位于 `file:line(:column)` 位置的符号——将诊断、堆栈跟踪或 grep 命中结果转换为符号名称,而无需读取文件。
```
getSymbolAtPosition({
project: "MyApp.Core",
file: "UserService.cs", // File name or path suffix (same matching as SearchSymbols)
line: 42, // 1-based
column: 17 // Optional (1-based) — omit to resolve the most relevant symbol on the line
})
```
**返回:** 名称、fullName、种类、签名、`isDeclaration`(该位置是否位于符号自身的声明上),以及(为空/不存在时省略)containingType、文档、definitionFile/Line(相对于解决方案根目录)。仅限行的查询优先匹配该行上的声明,而不是被引用的符号。
### 代码编辑工具(默认提供预览)
输出成员级别的更改而非整个文件重写的精准编辑。与 `ApplyFixes` 一样,两者**均默认为预览模式**(`previewOnly: true`)——除非你显式传入 `previewOnly: false`,否则不会向磁盘写入任何内容。
#### 11. EditMember
替换、添加或删除单个类型成员;返回统一的 diff。
```
editMember({
project: "MyApp.Core",
symbol: "Acme.UserService.GetUser", // The member (replace/delete), or the container type (add)
operation: "replace", // "replace" | "add" | "delete"
newSource: "public User GetUser(int id) => _repo.Find(id);", // Required for replace/add
previewOnly: false // Optional (default: true). Set false to write to disk.
})
```
**返回:** 操作、目标、`changedFiles`、`patch`、`previewOnly`、`applied`、`notes`。
#### 12. RenameSymbol
重命名符号并更新整个解决方案中的所有引用(Roslyn 重命名);返回统一的 diff。
```
renameSymbol({ project: "MyApp.Core", symbol: "GetUser", newName: "GetUserById", previewOnly: false })
```
**返回:** 符号、newName、`changedFiles`、`patch`、`previewOnly`、`applied`、`notes`。
## 工具注解
RoselineMCP 的 SDK(`ModelContextProtocol` 1.4.0)支持标准的 MCP 工具
[注解提示](https://modelcontextprotocol.io/)(`readOnlyHint`、`destructiveHint`、
`idempotentHint`),并且每个工具都通过 `[McpServerTool(ReadOnly = ..., Destructive = ..., Idempotent = ...)]` 声明了它们:
| 工具 | readOnlyHint | destructiveHint | idempotentHint | 备注 |
|------|:---:|:---:|:---:|-------|
| `AnalyzeSolution` | ✅ true | ❌ false | ✅ true | 从不写入磁盘。 |
| `ListDiagnostics` | ✅ true | ❌ false | ✅ true | 从不写入磁盘。 |
| `ApplyFixes` | ❌ false | ⚠️ true | ❌ false | `destructiveHint` 是一个静态的、最坏情况下的注解:它是 `true`,因为当传入 `previewOnly: false` 时,该工具*可以*写入文件,尽管默认调用(未设置 `previewOnly`,即 `true`)不会写入任何内容。SDK 的注解模型无法表达“仅对特定参数值具有破坏性”——请参阅源代码中 `ApplyFixesTool.ApplyFixes` 上的文档注释。 |
| `CreatePatch` | ✅ true | ❌ false | ✅ true | 纯粹对提供的两个字符串进行操作;从不触碰文件系统。 |
| `SearchSymbols` | ✅ true | ❌ false | ✅ true | 从不写入磁盘。 |
| `GetSymbolInfo` | ✅ true | ❌ false | ✅ true | 从不写入磁盘。 |
| `FindReferences` | ✅ true | ❌ false | ✅ true | 从不写入磁盘。 |
| `FindImplementations` | ✅ true | ❌ false | ✅ true | 从不写入磁盘。 |
| `GetCallGraph` | ✅ true | ❌ false | ✅ true | 从不写入磁盘。 |
| `GetTypeHierarchy` | ✅ true | ❌ false | ✅ true | 从不写入磁盘。 |
| `GetSymbolAtPosition` | ✅ true | ❌ false | ✅ true | 从不写入磁盘。 |
| `EditMember` | ❌ false | ⚠️ true | ❌ false | 与 `ApplyFixes` 具有相同的最坏情况 `destructiveHint` 原理:仅在传入 `previewOnly: false` 时写入文件;默认调用不会写入任何内容。 |
| `RenameSymbol` | ❌ false | ⚠️ true | ❌ false | 与 `ApplyFixes` 具有相同的最坏情况 `destructiveHint` 原理:仅在传入 `previewOnly: false` 时写入文件;默认调用不会写入任何内容。 |
这些提示是针对会展示它们的 MCP 客户端(例如,在 Agent 调用破坏性工具之前警告用户)的每个工具的静态元数据——它们描述了工具在最坏情况下的行为,而不是任何特定调用的结果。请参阅下文的 [工具兼容性策略](#tool-compatibility-policy),了解这些注解所支持的围绕工具名称和参数的稳定性保证。
## 工具兼容性策略
- **工具名称和必选参数在同一主版本内是稳定的。** 针对针对 `1.x` 版本的 `AnalyzeSolution(pathOrGit, ...)` 编写的 MCP 客户端集成将在所有 `1.x` 发行版中继续有效。
- **可选参数可能会在次要版本中添加**(例如,`CreatePatch` 增加了 `ignoreWhitespace`/`ignoreCase` 作为可选的默认参数,而不会破坏现有的调用方)。
- **重命名或移除参数、更改参数的必选/可选状态,或者更改工具的名称都属于破坏性变更。** 破坏性变更会在 [`CHANGELOG.md`](CHANGELOG.md) 中的专门“破坏性变更”标题下标出,且仅随主版本号升级发布。
- 响应*结构*(JSON 字段名称/类型)记录在 [`docs/API.md`](docs/API.md) 中,并遵循相同的策略:新增字段属于非破坏性变更,重命名/移除字段属于破坏性变更。
## 支持的分析器
诊断工具(`analyze_solution`、`list_diagnostics`、`apply_fixes`)通过 Roslyn 的 `CompilationWithAnalyzers` 报告编译器诊断以及分析器诊断:
- **Roslyn 分析器** -- 内置的 C# 编译器诊断
- **Roslynator** -- 500 多个针对 C# 的分析器和修复程序,**与 RoselineMCP 捆绑在一起**(以 `analyzers/` 文件夹的形式发布在 `RoselineMCP.dll` 旁边)并且默认执行,因此 RCS* 诊断可以直接显示并支持开箱即用的修复
- **自定义分析器** -- 你的被分析解决方案所引用的任何基于 Roslyn 的分析器,都会从项目的分析器引用中加载,并与捆绑的分析器一起运行(没有内置的 StyleCop.Analyzers 引用——如果你需要 SA* 诊断,请将其添加到你的被分析解决方案中;只有当能够加载匹配的修复程序时,分析器报告的规则才是可自动修复的)
将 `RoselineMCP:RunAnalyzers` 设置为 `false` 可仅获取编译器诊断(对于大型解决方案速度更快;请参阅 [配置](#configuration) 和 [`SECURITY.md`](SECURITY.md) 中的分析器执行说明)。
## 示例
### 分析解决方案
```
# 与 MCP client 一起使用
mcp call analyzeSolution '{
"pathOrGit": "/Users/dev/MyProject/MyProject.sln",
"severity": "warning",
"maxDiagnostics": 50
}'
```
响应:
```
{
"solution": "MyProject.sln",
"projects": 5,
"diagnosticSummary": {
"error": 2,
"warning": 15,
"info": 28
},
"topDiagnostics": [
{
"id": "CS0168",
"severity": "warning",
"message": "The variable 'ex' is declared but never used",
"file": "Program.cs",
"line": 42
}
]
}
```
### 应用修复
```
mcp call applyFixes '{
"project": "MyProject.Core.csproj",
"ids": ["CS0168", "RCS1001"],
"previewOnly": true
}'
```
响应包含一个统一的 diff 补丁,显示了所有将被应用的更改。
## 配置
RoselineMCP 会从安装服务器二进制文件的目录(`AppContext.BaseDirectory`)中读取 `appsettings.json` 和 `appsettings.{Environment}.json`——**而不是**从进程工作目录读取。从目标代码仓库内部启动服务器绝不会加载该代码仓库自己的 `appsettings.json`,并且随 `dotnet tool` 安装打包的设置始终能被找到。
配置仅在启动时读取一次;没有基于文件更改的重新加载监听。
### 环境变量
以 `ROSELINE_` 为前缀的环境变量会覆盖 JSON 文件中的设置,并使用 `__` 作为节分隔符。因此,`RoselineMCP` 节下的设置需要加上双重前缀:
```
# RoselineMCP:EnableDiagnosticLogging
ROSELINE_RoselineMCP__EnableDiagnosticLogging=true
# RoselineMCP:DefaultTimeout (毫秒)
ROSELINE_RoselineMCP__DefaultTimeout=300000
# RoselineMCP:RunAnalyzers (为 false 时仅包含 compiler-only diagnostics)
ROSELINE_RoselineMCP__RunAnalyzers=false
# Logging:LogLevel:RoselineMCP
ROSELINE_Logging__LogLevel__RoselineMCP=Debug
```
- `DOTNET_ENVIRONMENT`:设置环境(Development, Production)
### appsettings.json
配置日志记录和其他设置:
```
{
"Logging": {
"LogLevel": {
"Default": "Information",
"RoselineMCP": "Debug"
}
},
"RoselineMCP": {
"DefaultTimeout": 120000,
"EnableDiagnosticLogging": false,
"WorkspaceCache": true,
"RunAnalyzers": true
}
}
```
- `RoselineMCP:DefaultTimeout`:应用于每个工具调用的实际耗时超时限制(毫秒),这是在调用方自身的取消机制之外附加的。`0` 表示禁用。
- `RoselineMCP:EnableDiagnosticLogging`:可选的、仅限本地的工具调用追踪——请参阅 [调试日志](#debug-logging)。默认禁用;在 `appsettings.Development.json` 中启用。
- `RoselineMCP:WorkspaceCache`:在导航/编辑工具调用之间重用已加载的 MSBuild workspace(默认启用)——请参阅 [性能](#performance)。设置为 `false` 则每次调用都加载全新的 workspace。
- `RoselineMCP:RunAnalyzers`:在诊断工具中运行 Roslyn 分析器(捆绑的 Roslynator + 目标项目自身的分析器引用)(默认启用)——请参阅 [支持的分析器](#supported-analyzers)。设置为 `false` 可仅获取编译器诊断。
## 架构
RoselineMCP 使用 **stdio 传输** —— 这是一个有意为之的设计决策。服务器作为由 MCP 客户端(Claude Desktop,AI Agent)启动的本地进程运行,通过 stdin/stdout 进行通信,并在客户端断开连接时退出。这使其非常适合作为 NuGet 全局工具(`dotnet tool install -g RoselineMCP`)或 Docker 镜像进行分发——无需绑定端口、无需 HTTP 服务器、无需管理基础设施。
```
┌─────────────────────┐
│ MCP Client │
│ (Claude Desktop, │
│ AI Assistants) │
└────────┬────────────┘
│ MCP Protocol (stdio)
▼
┌─────────────────────┐
│ RoselineMCP │
│ MCP Server │
│ │
│ ┌───────────────┐ │
│ │ Tool Layer │ │
│ │ (Analyze, │ │
│ │ Fix, Patch) │ │
│ └───────┬───────┘ │
│ ▼ │
│ ┌───────────────┐ │
│ │ Service Layer │ │
│ │ (Workspace, │ │
│ │ Diagnostics) │ │
│ └───────┬───────┘ │
│ ▼ │
│ ┌───────────────┐ │
│ │ Roslyn + │ │
│ │ Roslynator │ │
│ │ Analyzers │ │
│ └───────────────┘ │
└─────────────────────┘
│
▼
┌─────────────────────┐
│ C# Source Code │
│ (.sln / .csproj) │
└─────────────────────┘
```
## 项目结构
```
RoselineMCP/
├── RoselineMCP/
│ ├── Interfaces/ # Service interfaces
│ ├── Services/ # Core business logic
│ ├── Tools/ # MCP tool implementations
│ ├── Models/ # Data transfer objects
│ └── Program.cs # Application entry point
├── RoselineMCP.Tests/ # Unit tests
├── .github/workflows/ # CI/CD pipelines
├── Dockerfile # Container build
└── RoselineMCP.sln # Solution file
```
## 性能
- **Workspace 缓存** -- 导航、编辑和诊断/修复工具(`ListDiagnostics`、`ApplyFixes` 以及所有由 `IProjectLoader` 支持的工具)在调用之间重用已加载的 `MSBuildWorkspace`,从而在第一次调用之后,每次调用都省去了数百毫秒的重新加载时间。缓存条目经过指纹识别(`.sln` 的最后写入时间 + 大小,每个 `.csproj` 和每个源文件及其目录),并在每次调用时重新检查,因此磁盘上的任何更改——包括 RoselineMCP 自己的编辑——都会触发全新的重新加载。使用 `RoselineMCP:WorkspaceCache = false` 禁用
- **Workspace 隔离** -- `AnalyzeSolution` 每次操作仍会创建一个全新的 `MSBuildWorkspace`(请参阅 [架构](#architecture))
- **顺序项目分析** -- 解决方案中的项目是一次分析一个,而不是并发分析,以保持 MSBuild workspace 状态的一致性
- **结果上限** -- 无论找到了多少结果,`maxDiagnostics`/`max` 都会限制每次调用返回的诊断数量
## 安全性
- **默认只读** -- `AnalyzeSolution`、`ListDiagnostics`、`CreatePatch` 以及所有六个代码导航工具(`SearchSymbols`、`GetSymbolInfo`、`FindReferences`、`FindImplementations`、`GetCallGraph、`GetTypeHierarchy`)从不写入磁盘。三个具备写入能力的工具——`ApplyFixes`、`EditMember` 和 `RenameSymbol`——各自默认设为 `previewOnly: true`;写入需要调用方显式传入 `previewOnly: false`。
- **真正的、只读的 Git 克隆** -- `pathOrGit` 接受 `http(s)://` Git URL,并将其浅克隆(`git clone --depth 1`)到一个临时目录中,该目录在操作完成后会被删除。没有其他 URL 方案会被视为 Git 远程仓库。
- **MSBuild 不是沙箱** -- 通过 `MSBuildWorkspace` 加载 `.sln`/`.csproj` 属于设计时的 MSBuild 评估,可能会执行嵌入在项目中的构建逻辑(`` 任务、自定义 `UsingTask` 程序集、导入的 `.targets`/`.props`)。分析完全不受信任的代码仓库或 URL 会在宿主机上带来真实的代码执行风险。**在将 RoselineMCP 指向不受信任的输入之前,请参阅 [`SECURITY.md`](SECURITY.md)** 获取完整的说明和操作建议。
- **分析器执行即代码执行** -- 诊断工具也会在进程内运行目标项目自身引用的 Roslyn 分析器(请参阅 [支持的分析器](#supported-analyzers));来自不受信任代码仓库的分析器等同于任意代码。`RoselineMCP:RunAnalyzers = false` 会禁用所有分析器执行(包括捆绑的 Roslynator)。请参阅 [`SECURITY.md`](SECURITY.md)。
- **没有专门的路径遍历沙箱** -- 路径通过简单的存在性检查进行解析,而不是根据允许的根目录进行规范化;请将 `pathOrGit`/`project`/`branch` 视为受信任的操作员输入。
## 故障排除
### 常见问题
1. **找不到 MSBuild**:确保已安装 .NET SDK 并将其添加到了 PATH 中
2. **解决方案无法加载**:检查是否缺少 NuGet 包,并运行 `dotnet restore`
3. **未找到分析器 (RCS*/SA*) 诊断**:验证 `RoselineMCP:RunAnalyzers` 是否未被设置为 `false`;对于非捆绑的规则集(例如 StyleCop),请验证是否已在目标项目中安装了分析器
4. **权限被拒绝**:确保对解决方案文件具有读取权限
### 调试日志
启用详细日志记录:
```
ROSELINE_Logging__LogLevel__RoselineMCP=Debug dotnet run --project RoselineMCP/RoselineMCP.csproj
```
### 追踪单个工具调用
每个工具调用都会获得一个每次调用的相关 ID(一个 GUID)。它的生成成本极低,因此总是会创建,但仅在你需要时才会显示:它包含在每个 JSON 错误响应(`correlationId`)中,并通过 `ILogger.BeginScope` 附加到该调用的日志行中,这样报告失败的用户就可以交给你一个 ID,通过它能追溯到完整的服务器端日志条目——而无需搜索时间戳。
对于将每次工具调用(开始/停止、持续时间、成功/失败)作为 `System.Diagnostics.Activity` span 进行更深度的、可选的追踪,请将 `RoselineMCP:EnableDiagnosticLogging` 设置为 `true`(在 `appsettings.Development.json` 中已经是 `true`):
```
ROSELINE_RoselineMCP__EnableDiagnosticLogging=true dotnet run --project RoselineMCP/RoselineMCP.csproj
```
这使用内置的 `ActivitySource`/`Activity` API 而不是 OpenTelemetry SDK,因此它不会增加额外的依赖。Span 完全通过现有的 `ILogger` 管道进行记录,该管道已经路由到了 stderr——绝不会路由到 stdout(MCP JSON-RPC 通道)——并且永远不会通过网络发送任何内容;当该标志关闭(默认)时,不会注册任何监听器,Span 几乎不产生任何成本。
## 路线图
- [ ] 额外的分析器规则集(SonarAnalyzer, FxCop)
- [ ] 带有置信度评分的自动修复建议
- [ ] 用于自动化分析管道的 CI/CD 集成
- [ ] 单次会话中的多解决方案支持
- [ ] 增量分析(仅针对已更改的文件)
- [ ] 通过 MCP 进行自定义分析器规则配置
## 文档
- **[文档网站](https://atypical-consulting.github.io/RoselineMCP/)** -- 概述、工具参考以及 [token 节省基准测试](https://atypical-consulting.github.io/RoselineMCP/benchmark)
(由 `website/` 构建,部署在 GitHub Pages 上)
- [docs/API.md](docs/API.md) -- 每个 MCP 工具的完整请求/响应参考、服务接口、模型以及错误响应契约
- [docs/AGENT-BENCHMARK.md](docs/AGENT-BENCHMARK.md) -- 端到端 A/B 测试:AI Agent 使用 RoselineMCP 真的能节省 token 吗?(诚实的答案——在大型代码库上优势显著,小型代码库上则基本持平)
- [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) -- 分层架构、数据流和设计模式
- [PROMPTS.md](PROMPTS.md) -- 每个工具的示例提示词和端到端工作流
- [CHANGELOG.md](CHANGELOG.md) -- 发布历史和破坏性变更
- [SECURITY.md](SECURITY.md) -- 漏洞报告和 MSBuild 代码执行注意事项
- [CONTRIBUTING.md](CONTRIBUTING.md) -- 开发设置和 PR 流程
## 贡献
欢迎贡献!请先阅读 [CONTRIBUTING.md](CONTRIBUTING.md)。
1. Fork 该仓库
2. 创建你的功能分支 (`git checkout -b feature/amazing-feature`)
3. 使用 [约定式提交](https://www.conventionalcommits.org/) 进行提交 (`git commit -m 'feat: add amazing feature'`)
4. 推送到该分支 (`git push origin feature/amazing-feature`)
5. 提交一个 Pull Request
## 许可证
[MIT](LICENSE) © 2026 [Atypical Consulting SRL](https://atypical.garry-ai.cloud)
## 鸣谢
- 基于 [Roslyn](https://github.com/dotnet/roslyn) 构建 —— .NET 编译平台
- 由 [Roslynator](https://github.com/JosefPihrt/Roslynator) 提供支持 —— C# 分析器和重构
- 使用 [DiffPlex](https://github.com/mmanela/diffplex) —— Diff 生成库
- 实现了 [Model Context Protocol](https://modelcontextprotocol.io) —— AI 助手集成协议
由 [Atypical Consulting](https://atypical.garry-ai.cloud) 精心打造 —— 固执己见的、生产级别的开源项目。
[](https://github.com/Atypical-Consulting/RoselineMCP/graphs/contributors)
Claude Desktop
编辑 `claude_desktop_config.json`(文件位置见上文的 [安装](#getting-started)),并在 `mcpServers` 下添加一个 `roseline` 条目,可以使用上述展示的四种安装选项(`dnx`、全局工具、Docker 或从源码构建)中的任何一种。VS Code (GitHub Copilot / MCP 扩展)
在你的工作区或用户 `mcp.json` 中添加一个条目(命令面板 → “MCP: Open User Configuration”,或工作区中的 `.vscode/mcp.json`): ``` { "servers": { "roseline": { "command": "dnx", "args": ["RoselineMCP", "--yes"] } } } ``` 如果你是通过 NuGet 全局工具安装的,则替换为 `"command": "roseline-mcp"`(无需 `args`)。Cursor
在 `~/.cursor/mcp.json`(全局)或 `.cursor/mcp.json`(项目本地)中添加一个 `roseline` 条目,使用与上面的 VS Code 代码片段相同的 `command`/`args` 结构。标签:AI编程助手, macOS, MCP协议, Roslyn, SOC Prime, 代码分析, 凭证管理, 开发工具, 请求拦截