Razor, metacode and decompilation
Three ways of reading code that is not plain C# in a Roslyn project: Razor pages, canonical pseudocode shared by every language, and compiled assemblies — managed or native.
Razor and Blazor pages
.cshtml and .razor files are not Roslyn
documents: the Razor SDK compiles them with a different toolchain.
VisualMCP reads them from disk, with a dedicated
scanner that maps each file to a page model — which also means the
analysis works without a loaded solution, useful for auditing a
repository you have not opened.
| Tool | Answers |
|---|---|
razor_pages | What exists and how it is wired: kind, @page route, @model, layout, sections, @inject, handlers, code-behind, markup counts. |
analyze_razor_pages | What is wrong with the markup: broken HTML, accessibility, Razor misuse, maintainability. |
find_razor_vulnerabilities | What is exploitable: XSS, CSRF, secrets, unsafe URLs, CSP — each finding with a CWE id. |
razor_edit | The write side: six verified text splices. |
The security rules know Razor: @Html.Raw with an
unencoded value, model data inside a <script> block
or an inline handler, javascript: URLs, POST forms with
no anti-forgery token, passwords submitted with GET, hardcoded
credentials, target="_blank" without
noopener. Values already passed to an encoder do not
fire. It is a heuristic analysis — no data flow — so a clean result is
not a security proof.
razor_edit performs one verified splice per call: set or
remove an attribute on the n-th element with a tag, add a
directive, insert, replace or delete lines. The expect
argument takes the text the target lines must currently hold — if the
file no longer matches, the edit is refused. The page is re-scanned
before writing, and the result reports the findings the edit resolved
and introduced.
Metacode
Metacode is one canonical pseudocode model for syntax trees from different languages. The same algorithm prints the same body, line for line, whichever frontend produced it: uppercase keywords, one statement per line, operator precedence preserved.
metacode_translate path=Services/OrderService.cs
metacode_translate path=Pages/Checkout.cshtml
metacode_compare leftPath=OrderService.cs rightPath=OrderService.kt.mc
- C#, Visual Basic, Razor, JavaScript, Java, Python, C++ and Rust are all inputs — the last three through their own toolchains, lowered into the same model.
- A construct the model has no node for stays visible as
RAW[lang]with a diagnostic: incomplete translation is visible, never silent. metacode_compareis the equivalence check: two spellings of an algorithm compared line by line, which is how you review a port or verify that a refactor kept the shape of a body.
Decompiling managed assemblies
| Tool | What it does |
|---|---|
decompile_type | One type from a .dll back to C#, with ILSpy. |
decompile_assembly | A whole module, or a filtered, paged set of types; can export one file per type. |
inspect_assembly | The public API — types, base types, interfaces, members — without running anything. |
decompile_to_metacode | ILSpy → C# → the metacode model, printed as pseudocode instead of C#. |
inspect_package, decompile_package_type | The same, starting from a NuGet package id and version. |
Recovering native binaries
analyze_native_binary runs Ghidra headless
on a PE/ELF/Mach-O file, exports every function's decompiled C and
lowers it into the same model:
analyze_native_binary binaryPath=C:\Windows\System32\notepad.exe maxFunctions=5
It is a real external run — tens of seconds, bounded by a timeout that kills the whole process tree. Narrow it with a function name or entry address, or a maximum function count. Ghidra is installed on demand into the per-user tools folder when no installation is found, and the binary never leaves the machine.
Decompiled code lives in the same AST
What gets decompiled is stored in the same tables as
the solution's own code, under assembly:// and
native:// keys, with provenance columns that say which
file it came from and that it was decompiled. The complexity ranking,
the metacode queries and a raw SQL query never confuse recovered code
with source you own — so “what does this library actually do?” is
answered with the same tools that answer it about your own code.