让 Claude 按真实 NuGet 版本编写代码
Waymark v0.1 是面向 Windows 和 .NET 项目的本地 MCP 服务,可读取项目实际使用的 NuGet 包,并按结构定位 C# 代码。项目采用 MIT 许可证,提供敏感信息隐藏、请求日志和高风险操作的本机审批。
完整中文译文
Waymark v0.1 发布了。它让 Claude 在处理你的 .NET 项目时不再靠猜:读取项目实际使用版本的 NuGet 包,按代码结构定位 C# 代码,而不是逐个读取所有文件。所有有风险的操作,都必须经过你掌控的关口:由你批准,隐藏你的敏感信息,并记录每一次操作。
它运行在你的 Windows PC 上,支持网页版 Claude、Claude 应用和 Claude Code,并以 MIT 许可证开源。仓库地址:https://github.com/patilprashant6792-official/waymark-local
如果你读过我之前介绍 sharp-mcp 的文章,Waymark 就是它一路发展后的成果。

用大白话说,它是怎么回事
想象一个有保安值守的前台。Claude 不会直接走进你的电脑,而是来到前台,提出具体请求:“让我看看这个项目的结构”“这个包提供了什么”“修改这几行”“运行构建”。
前台只响应你已开启的功能,控制每次回复的长度,隐藏能够识别出的敏感信息,并把每个请求记进日志。遇到有风险的操作,它会停下来,等你点头。只有你能批准,而且只能在你自己的电脑上批准。
Claude 在编写库调用之前,会先核对真实的包。
Claude 无须读取每一个文件,就能理解大型 C# 代码库。
Claude 可以编辑、构建和修复代码,所有有风险的操作都由你批准。
它做过什么都有清晰记录,敏感信息会在进入聊天之前被隐藏。

我最自豪的部分:直接读取真实的 NuGet 包
所有助手在使用库时都有同一个习惯:凭记忆写调用。如果一个包在不同版本间发生过变化,或者它是个新包,助手写出的调用可能根本不存在于你使用的版本中,而你往往要等到构建报错才发现。
Waymark 用包本身取代记忆。这件事由两个工具完成。nuget_find 根据你对需求的描述查找类型和方法,并按匹配程度排序。nuget_expand 最多展开其中五个结果,展示它们的准确结构:构造函数和重载、属性、枚举值、包自带的 XML 文档,以及可以继续追查的相关类型。
下面是一次针对 Polly 的真实运行,使用面向 net10.0 的最新稳定版;真实项目会传入自己锁定的版本:
nuget_find(Polly, "retry policy")
Polly 8.8.0 (net10.0): 24 matches, best first
class Polly.Retry.RetryPolicy a retry policy for synchronous delegates
class Polly.Retry.AsyncRetryPolicy a retry policy for asynchronous delegates
nuget_find(Polly.Core, "retry strategy options")
Polly.Core 8.8.0 (net10.0)
class Polly.Retry.RetryStrategyOptions 1 ctor, 10 props
nuget_expand(Polly.Core, RetryStrategyOptions)
int MaxRetryAttempts { get; set; }
TimeSpan Delay { get; set; }
DelayBackoffType BackoffType { get; set; }
bool UseJitter { get; set; }
同一个库,两代 API,助手看到的都是你实际使用版本中的内容。
之所以能做到准确,是因为 Waymark 会根据项目中的版本和目标框架,检查已编译的包,而不加载或运行它。项目骨架会列出这些信息,包括在集中管理的 props 文件中设置的版本。包通过 HTTPS 从 nuget.org 获取,也可以使用 NuGet 文件夹中已有的副本。结果会在你自己的 PC 上建立索引,因此第二次查询几乎瞬间完成。
Waymark 教给 Claude 的规则是:没有在项目锁定版本中确认过的成员,就视为不存在。签名决定了什么确实存在。至于如何使用,Claude 会读取 README 或示例,文字说明永远不能推翻已经确认的签名。
我不是第一个让助手查询 NuGet 的人。我想要的是把整个流程放在同一个地方:按描述查找,按项目锁定的版本展开准确签名,与自己的代码索引放在一起,并受同一套关卡控制。
为 C# 而造,不只是处理文本
大多数助手把代码当作文本:为了找到一行代码,先读取一个文件。Waymark 则按 C# 的结构来理解 C#。
查找。 添加工作区时,Roslyn 会读取每个 C# 文件一次,无须编译,再将结构存入你自己 PC 上的 SQLite 文件:每个类型、每个成员的签名和准确行号范围,以及成员内部的调用。它只保存结构,从不保存源代码文本。无论你在 IDE 中编辑,还是 Claude 修改文件,文件监听器都会保持索引更新。接下来,Claude 会从整体逐步缩小范围:
- code_skeleton:展示带文件大小的目录树,以及每个项目使用的 NuGet 包和版本。
- code_search:按名称查找类型和成员,支持宽松匹配并对结果排序。也支持驼峰命名的首字母缩写:“PSS”可以找到 ProjectSkeletonService。
- code_outline:展示文件中的类型和成员,不包含实现体。
- code_method:完整展示一个方法,包含所有重载和真实行号。
code_callers 展示谁调用了某个方法,code_types 展示所有继承某个类型或实现某个接口的类型,code_grep 则查找不属于名称的普通文本,例如配置键、路由、SQL 和 Razor。所有回复都会排序、分页并限制数量,因此第一次调用返回的是一张地图,而不是整片疆域。
写入。 编辑按行号进行,使用的就是 code_method 刚刚返回的行号,因此 Claude 修改的正是自己读过的那些行。file_edit_lines 在一次调用中应用对同一文件的所有修改,按从下到上的顺序执行,避免行号偏移,并拒绝相互重叠的修改。文件会保留原有编码和换行符,每次写入都先写到临时文件,再替换原文件,因此即使失败,也不会留下只写了一半的文件。随后,cmd_dotnet build 返回带文件路径的编译器错误,形成完整循环:编辑、构建、读取错误、修复。有一个限制需要坦白说明:移动文件不会自动改写 C# 命名空间,因此 Claude 需要搜索旧名称,再逐个文件修正。
有两件事让我厌烦了:我的 AI 助手总在猜测那些根本不存在的代码,而且为了回答一个小问题,就要读取整个项目。于是,我做了一个辅助工具,让它能够好好查资料。那就是 sharp-mcp。我为它写过两篇文章:一篇介绍它如何阻止 Claude 编造库方法,另一篇介绍背后的设计取舍。
它对我来说很好用。但它能运行,只是因为我知道该怎么配置,而且它会信任任何拿到链接的人。个人工具这样做可以,却不适合交给其他人使用。
所以我从头开始,只问了一个问题:要让任何人都能安装它、信任它,需要做到什么?Waymark 就是答案。它安装简单,未经允许,任何内容都不会离开你的电脑;有风险的操作由你批准,每一次操作都会记录下来,供你查看。
你需要 Windows 10 或 11、git,以及一个免费的 ngrok 账号——如果你要使用网页版 Claude 的话。如果没有安装 .NET 10 SDK,安装程序会通过 winget 补上。
git clone https://github.com/patilprashant6792-official/waymark-local.git
执行 cd waymark-local,然后运行 install.cmd。
打开 http://localhost:47100,在 Setup 中粘贴你的 ngrok 地址,再到 Workspaces 中添加项目文件夹。
在 Claude 中添加一个自定义 connector,地址使用 Setup 页面显示的地址。Claude 和你的 Approvals 页面上都会出现配对码;核对一致后批准。如果没有出现配对提示,断开后重新连接。
这还是早期软件(v0.1)。在让它处理任何重要内容之前,请先阅读下文中的限制。
上面介绍的是思路。下面介绍安全机制的具体实现,供想核查这些说法的人参考。
它有两个入口。一个供 Claude 使用,通过 ngrok 隧道提供登录和工具访问。另一个是供你使用的管理应用,只监听本机。互联网只能访问第一个入口。
关卡、审批与敏感信息
编辑和命令都有开关控制。 文件工具默认关闭,直到你手动开启。共有 36 项命令操作,每项都可以设为 Off、Ask 或 Auto,也可以按工作区分别设置。默认情况下,10 项自动运行,包括构建、restore 和 git 读取操作;23 项先征求批准,包括测试、run、EF、commit、push 和 shell;3 项关闭,分别是 git reset hard、clean 和 branch delete。shell 最多只能设为 Ask。如果自上次批准后,能够执行代码的项目文件发生了变化,变更检查会要求重新批准。而且,批准只能在同一台电脑上的管理应用中完成,Claude 永远不能代为批准。

隐藏敏感信息,记录所有操作。 每个结果都会经过同一条处理流水线:私钥、云服务 token、JWT、连接字符串,以及名为 password 或 api key 等的值,都会被替换成类似 [redacted:kind] 的标记。如果检查本身失败,结果就不会被返回。每次调用都会写入一条审计记录和一条实时日志,并记录其 token 数量。此外,还有一个 Pause all 按钮。
更新使用 update.cmd;卸载使用 uninstall.cmd,除非你另行要求,否则会保留你的数据。
以下这些情况,我宁愿由自己先告诉你:
- 没有 sandbox。 你批准运行的测试、应用或脚本,都会以你的权限执行。它们可以读取你的密钥,也可以访问网络。这里的保护措施是:这些操作会先征求批准。请把仓库和包中的文本视为不可信内容,它们可能试图诱导 AI。
- 敏感信息按形式特征识别。 形式不常见的敏感信息可能漏过检查。删除聊天无法收回已经泄露的敏感信息;请轮换相关凭据。
- C# 索引按名称查找调用方。 code_callers 按方法名匹配,因此重载和同名方法可能产生误报。其他文件通过 code_grep 查找,每次调用都会扫描磁盘。
- NuGet 查询存在限制。 第一次查询某个包版本时,需要下载并建立索引,耗时几秒。每个包都有大小和数量上限:250 MB、20,000 个文件、64 个依赖。如果某个包需要间接依赖中的程序集,就需要明确指定该依赖,再重试一次。
- 一种隧道,一台机器。 目前只支持 ngrok,只能运行在 Windows 上,面向单个用户使用。
- 尚未实现 connectors,例如数据库访问。 对应页面目前已隐藏。
我在 Claude 的帮助下构建了 Waymark,但每项内容都会由我阅读,并决定是否纳入。
我希望听到你的反馈
- 告诉我,有哪个包的 API 总让助手用错。我会用 nuget_find 和 nuget_expand 跑一遍,并分享返回结果。
- 如果你读过 sharp-mcp 系列文章:你希望它具备、但我遗漏了什么?
- 哪些关卡的默认设置让你觉得不合适?如果由你发布,会怎样设置?
- 你是否希望支持其他隧道,例如 Tailscale 或 Cloudflare?
- 试着突破敏感信息隐藏机制;如果找到了办法,请通过仓库的 Security 标签页私下报告。
代码、指南和安全说明都在仓库里。欢迎提交 Issue 和 pull request。
如需进一步处理,你可以考虑屏蔽此人和/或举报滥用行为。