Atypical-Consulting/RoselineMCP

GitHub: Atypical-Consulting/RoselineMCP

RoselineMCP 将 Roslyn 编译平台封装为 MCP 服务器,让 AI 编程 Agent 以结构化方式导航和编辑 C# 代码,大幅降低 token 消耗。

Stars: 1 | Forks: 0

# RoselineMCP [![Atypical-Consulting - RoselineMCP](https://img.shields.io/static/v1?label=Atypical-Consulting&message=RoselineMCP&color=blue&logo=github)](https://github.com/Atypical-Consulting/RoselineMCP) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![.NET 10](https://img.shields.io/badge/.NET-10.0-purple?logo=dotnet)](https://dotnet.microsoft.com/) [![stars - RoselineMCP](https://img.shields.io/github/stars/Atypical-Consulting/RoselineMCP?style=social)](https://github.com/Atypical-Consulting/RoselineMCP) [![forks - RoselineMCP](https://img.shields.io/github/forks/Atypical-Consulting/RoselineMCP?style=social)](https://github.com/Atypical-Consulting/RoselineMCP) [![GitHub tag](https://img.shields.io/github/tag/Atypical-Consulting/RoselineMCP?include_prereleases=&sort=semver&color=blue)](https://github.com/Atypical-Consulting/RoselineMCP/releases/) [![issues - RoselineMCP](https://img.shields.io/github/issues/Atypical-Consulting/RoselineMCP)](https://github.com/Atypical-Consulting/RoselineMCP/issues) [![GitHub pull requests](https://img.shields.io/github/issues-pr/Atypical-Consulting/RoselineMCP)](https://github.com/Atypical-Consulting/RoselineMCP/pulls) [![GitHub last commit](https://img.shields.io/github/last-commit/Atypical-Consulting/RoselineMCP)](https://github.com/Atypical-Consulting/RoselineMCP/commits/main) [![CI](https://static.pigsec.cn/wp-content/uploads/repos/cas/ad/ad5834178f7599af9fdda11629d49cae07f2997beec49821b2920eff5bfd50e7.svg)](https://github.com/Atypical-Consulting/RoselineMCP/actions/workflows/ci.yml) [![NuGet](https://img.shields.io/nuget/v/RoselineMCP.svg)](https://www.nuget.org/packages/RoselineMCP/) [![Docker](https://img.shields.io/docker/v/phmatray/roseline-mcp?label=docker)](https://hub.docker.com/r/phmatray/roseline-mcp) [![Docs & Benchmark](https://img.shields.io/badge/docs-site-e01e5a)](https://atypical-consulting.github.io/RoselineMCP/) [![Tokens saved](https://img.shields.io/badge/tokens-89%25_fewer_(median)-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。
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` 结构。
## 可用工具 ### 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://contrib.rocks/image?repo=Atypical-Consulting/RoselineMCP)](https://github.com/Atypical-Consulting/RoselineMCP/graphs/contributors)
标签:AI编程助手, macOS, MCP协议, Roslyn, SOC Prime, 代码分析, 凭证管理, 开发工具, 请求拦截