<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Prashant Patil</title>
    <description>The latest articles on Forem by Prashant Patil (@prashant_patil_9e62d3fa8a).</description>
    <link>https://forem.com/prashant_patil_9e62d3fa8a</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3679473%2Fd1373e51-83e2-4971-a679-d2ee57a15999.png</url>
      <title>Forem: Prashant Patil</title>
      <link>https://forem.com/prashant_patil_9e62d3fa8a</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/prashant_patil_9e62d3fa8a"/>
    <language>en</language>
    <item>
      <title>MCP server for C# development with real NuGet reflection</title>
      <dc:creator>Prashant Patil</dc:creator>
      <pubDate>Mon, 13 Apr 2026 15:08:51 +0000</pubDate>
      <link>https://forem.com/prashant_patil_9e62d3fa8a/i-just-wanted-claude-to-stop-hallucinating-my-nuget-apis-somehow-i-ended-up-building-a-full-c-dev-12om</link>
      <guid>https://forem.com/prashant_patil_9e62d3fa8a/i-just-wanted-claude-to-stop-hallucinating-my-nuget-apis-somehow-i-ended-up-building-a-full-c-dev-12om</guid>
      <description>&lt;h1&gt;
  
  
  sharp-mcp:
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Roslyn-Powered C# Analysis, Real NuGet DLL Reflection, and Safe Live File Editing for Claude, On Your Machine via MCP
&lt;/h2&gt;

&lt;p&gt;If you've ever watched an AI confidently call a NuGet method removed two versions ago — and only found out when your build broke — this is for you.&lt;/p&gt;

&lt;p&gt;Or if you've pasted five service classes into a chat, watched the context fill up, and still got a half-baked answer.&lt;/p&gt;

&lt;p&gt;Or if you work in finance or healthcare and the phrase "your code is sent to our servers" is a non-starter.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/patilprashant6792-official/sharp-mcp" rel="noopener noreferrer"&gt;https://github.com/patilprashant6792-official/sharp-mcp&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The problem nobody talks about
&lt;/h2&gt;

&lt;p&gt;Every AI coding tool in 2025 has the same three silent killers for .NET developers specifically.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hallucinated APIs.&lt;/strong&gt; LLMs are frozen at their training cutoff. NuGet ships breaking changes constantly. &lt;code&gt;System.Text.Json&lt;/code&gt; changed nullable handling between 6.0 and 8.0. EF Core changed &lt;code&gt;DbContext&lt;/code&gt; configuration between 7.0 and 8.0. &lt;code&gt;IgnoreNullValues&lt;/code&gt; was deprecated mid-lifecycle. The model doesn't know. It generates code that looks right and doesn't compile.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Context bloat.&lt;/strong&gt; A 500-line service class costs ~2,000 tokens raw. Load ten files and you've burned your entire context budget before writing a single line. Copilot's &lt;code&gt;#codebase&lt;/code&gt; search is widely documented as unreliable — developers end up manually attaching files and hitting the limit anyway.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Your code leaves your machine.&lt;/strong&gt; Copilot, Cursor, Windsurf — every cloud AI tool sends your source to an external server with every request. For finance, healthcare, or any regulated industry, that's not a theoretical concern. It's a compliance issue.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sharp-mcp&lt;/code&gt; fixes all three. It runs entirely on your machine, exposes your codebase as structured MCP tools, and — the part no other tool does — reflects your actual installed NuGet DLLs via &lt;code&gt;MetadataLoadContext&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  The novel piece: real NuGet DLL reflection
&lt;/h2&gt;

&lt;p&gt;When you ask &lt;code&gt;sharp-mcp&lt;/code&gt; how to use a method from a NuGet package, it doesn't consult training data. Here's what actually happens:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Resolves the exact version pinned in your &lt;code&gt;.csproj&lt;/code&gt; via &lt;code&gt;NuGet.Protocol&lt;/code&gt; — no guessing&lt;/li&gt;
&lt;li&gt;Downloads the &lt;code&gt;.nupkg&lt;/code&gt; and picks the right &lt;code&gt;net*/&lt;/code&gt; target framework folder with automatic fallback chain&lt;/li&gt;
&lt;li&gt;Downloads transitive dependencies — &lt;code&gt;MetadataLoadContext&lt;/code&gt; needs them to resolve cross-assembly types correctly; without this, reflection on generics and inherited types silently fails&lt;/li&gt;
&lt;li&gt;Loads the DLL into an isolated &lt;code&gt;MetadataLoadContext&lt;/code&gt; — binary inspection only, never executed, zero risk of static constructors or process pollution&lt;/li&gt;
&lt;li&gt;Returns valid, copy-paste-ready C# signatures from your exact binary&lt;/li&gt;
&lt;li&gt;Disposes the context immediately — no assembly leaks, no AppDomain side effects&lt;/li&gt;
&lt;li&gt;Caches the result in Redis for 7 days, keyed on &lt;code&gt;packageId:version:targetFramework&lt;/code&gt; — second call is a Redis read, not a download&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;No training cutoff. No hallucinated overloads. No deprecated methods that "still work" in the model's memory. Your DLL. Your truth.&lt;/p&gt;

&lt;p&gt;Token cost comparison for NuGet exploration:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;What you're doing&lt;/th&gt;
&lt;th&gt;Raw dump&lt;/th&gt;
&lt;th&gt;sharp-mcp&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Explore a namespace&lt;/td&gt;
&lt;td&gt;~6,000 tokens&lt;/td&gt;
&lt;td&gt;~250 tokens&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Explore a class&lt;/td&gt;
&lt;td&gt;~2,000 tokens&lt;/td&gt;
&lt;td&gt;~400 tokens&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fetch one method&lt;/td&gt;
&lt;td&gt;~2,000 tokens&lt;/td&gt;
&lt;td&gt;~120 tokens&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  But NuGet reflection alone isn't a dev assistant
&lt;/h2&gt;

&lt;p&gt;Here's the honest part: NuGet reflection solves one problem. What makes &lt;code&gt;sharp-mcp&lt;/code&gt; actually useful for day-to-day .NET development is that all 22 tools form a closed loop. Each one makes the others more powerful.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌──────────────────────────────────────────────────────────┐
│                     sharp-mcp loop                       │
│                                                          │
│  understand        explore         edit         verify   │
│  codebase  ──►  NuGet APIs  ──►  files   ──►   build    │
│     ▲                                              │     │
│     └──────────────────────────────────────────────┘     │
└──────────────────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You explore a NuGet API with real signatures → write code against those signatures → edit the right file using Roslyn-derived line numbers → build immediately to catch errors. Break any link in that chain and the whole thing degrades. This is the ecosystem.&lt;/p&gt;




&lt;h2&gt;
  
  
  Understand: Roslyn analysis, not grep
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;analyze_c_sharp_file&lt;/code&gt; uses a full Roslyn syntax tree walker — not text search — to extract structured metadata from every &lt;code&gt;.cs&lt;/code&gt; file: DI constructor graphs, method signatures with exact start/end line numbers, attributes, XML doc comments, public/private toggle. Batch mode lets you pass &lt;code&gt;Services/A.cs,Services/B.cs,Controllers/C.cs&lt;/code&gt; in one call.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;fetch_method_implementation&lt;/code&gt; returns a complete method body with every line numbered. Those line numbers are what Claude uses directly in &lt;code&gt;edit_lines&lt;/code&gt; patch operations — no guessing, no off-by-one errors.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;analyze_method_call_graph&lt;/code&gt; walks every &lt;code&gt;.cs&lt;/code&gt; file in your project before you touch a signature and returns every caller — file, class, exact line number. The difference between a safe refactor and a CI failure at 11pm.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;get_project_skeleton&lt;/code&gt; gives you an ASCII folder tree with file sizes and NuGet package list. Pass &lt;code&gt;"*"&lt;/code&gt; and it shows every registered project at once. &lt;code&gt;search_code_globally&lt;/code&gt; finds classes, interfaces, methods, and properties by name across all projects simultaneously.&lt;/p&gt;

&lt;p&gt;All of this is Redis-backed. Roslyn parses each file once on startup, serializes the AST metadata to Redis, and serves every subsequent call in milliseconds. A &lt;code&gt;FileSystemWatcher&lt;/code&gt; with a 300ms debounce evicts and rewrites only the changed file on every save. Claude always sees your code as it exists on disk right now — never stale. This is what makes long feature implementation sessions practical — you never burn tokens re-reading files Claude already knows.&lt;/p&gt;




&lt;h2&gt;
  
  
  Explore: NuGet IntelliSense from your actual binary
&lt;/h2&gt;

&lt;p&gt;The NuGet tools follow exactly the sequence a developer uses in an IDE — not a bulk dump of everything at once:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;get_package_namespaces      ← "I installed OpenAI — what namespaces does it expose?"
get_namespace_types         ← "What types exist in OpenAI.Chat?" (~10 tokens/type)
get_type_surface(type)      ← "What can I call on ChatClient?"
get_type_shape(type)        ← "What does ChatCompletion look like?"
get_method_overloads(...)   ← expand specific overload groups on demand
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each step returns only what the next decision requires. Nothing is dumped until asked for. The entire exploration of an unfamiliar package costs ~800 tokens total vs ~6,000 for a full namespace dump. Over a multi-hour implementation session this compounds significantly.&lt;/p&gt;




&lt;h2&gt;
  
  
  Edit: surgical file operations with real safety guarantees
&lt;/h2&gt;

&lt;p&gt;Claude can create, edit, move, rename, and delete files — all guarded by per-file semaphore locking (concurrent writes serialized, never dropped), atomic batch-move validation (all destinations validated before any file moves; one failure aborts the entire batch), path sandboxing (traversal structurally impossible — resolved against project root), permanent blocked patterns (&lt;code&gt;bin/&lt;/code&gt;, &lt;code&gt;obj/&lt;/code&gt;, &lt;code&gt;.git/&lt;/code&gt;, secrets, tokens — enforced at the service layer, not a config flag), and automatic Redis cache eviction on every write so the next analysis call sees the updated file immediately.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;edit_lines&lt;/code&gt; applies multiple patch/insert/delete/append operations to a single file atomically. Patches are validated for overlaps then applied bottom-up — original line numbers stay correct for every patch in the batch. This is what lets Claude make multi-location changes in one shot without line drift.&lt;/p&gt;




&lt;h2&gt;
  
  
  Verify: build with structured Roslyn diagnostics
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;execute_dotnet_command&lt;/code&gt; runs &lt;code&gt;dotnet clean + build&lt;/code&gt; and returns structured diagnostics — not raw stderr:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"severity"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"CS0246"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"file"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Services/OrderService.cs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"line"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Claude reads the file path and line number, jumps straight to the problem using the analysis tools, and fixes it. The loop — explore → edit → build → fix — runs entirely inside the conversation without copy-pasting error output.&lt;/p&gt;




&lt;h2&gt;
  
  
  Multi-project from day one
&lt;/h2&gt;

&lt;p&gt;Register as many projects as you have. Every tool accepts &lt;code&gt;projectName&lt;/code&gt;. Claude can read the skeleton of one microservice, fetch a method from another, edit a third, build a fourth — in one conversation, without context switching. Pass &lt;code&gt;"*"&lt;/code&gt; to any tool to scope it across all registered projects simultaneously.&lt;/p&gt;




&lt;h2&gt;
  
  
  The privacy angle
&lt;/h2&gt;

&lt;p&gt;Claude receives structured metadata — class names, method signatures, line ranges. Not your business logic. Not your proprietary algorithms. Not your customer data. Nothing leaves your machine.&lt;/p&gt;

&lt;p&gt;For .NET developers in finance or healthcare this isn't a nice-to-have. With the EU AI Act in phased enforcement and data residency requirements tightening globally, a tool that processes source code locally is increasingly the only compliant option.&lt;/p&gt;




&lt;h2&gt;
  
  
  Stack
&lt;/h2&gt;

&lt;p&gt;.NET 10 · Roslyn (Microsoft.CodeAnalysis.CSharp 5.0) · Redis (StackExchange.Redis + NRedisStack) · ModelContextProtocol 0.5 · NuGet.Protocol · System.Reflection.MetadataLoadContext · ngrok SSE transport&lt;/p&gt;

&lt;p&gt;22 MCP tools across 8 tool classes: code analysis, project exploration, NuGet reflection, file operations, dotnet CLI, utility.&lt;/p&gt;




&lt;h2&gt;
  
  
  Get started
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/patilprashant6792-official/sharp-mcp
&lt;span class="nb"&gt;cd &lt;/span&gt;sharp-mcp/LocalMcpServer
dotnet run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Start Redis:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 6379:6379 redis:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expose with ngrok:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ngrok http 5000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Register your projects via the web UI — no config files to hand-edit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;http://localhost:5000/config.html
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the ngrok &lt;code&gt;/sse&lt;/code&gt; URL to Claude.ai → Settings → Connectors. Claude discovers all 22 tools automatically. Full setup walkthrough in the README.&lt;/p&gt;




&lt;h2&gt;
  
  
  What this doesn't replace
&lt;/h2&gt;

&lt;p&gt;This is not inline autocomplete. It doesn't suggest the next line as you type and doesn't integrate into your IDE as an extension.&lt;/p&gt;

&lt;p&gt;What it replaces is the reasoning session — when you open a chat to understand a codebase, plan a refactor, check what breaks if you change a signature, look up how a dependency actually works, or implement a feature that spans multiple files. That's the scope it's built for. And that's where the closed loop — Roslyn analysis, real NuGet reflection, surgical editing, live build feedback — earns its keep.&lt;/p&gt;




&lt;p&gt;Drop a comment if you've hit any of these walls. Genuinely curious what .NET packages and patterns people are trying to get Claude to reason about.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>csharp</category>
      <category>dotnet</category>
      <category>mcp</category>
    </item>
  </channel>
</rss>
