The Problem Nobody Talks About
Every AI coding tool operates at the filesystem level. They read files. They run grep. They parse text.
When you ask "find all usages of ProcessDocument", they run something like:
grep -rn "ProcessDocument" . --include="*.cs"
And you get back:
- The actual method definition
-
ProcessDocumentAsync(different method!) - String literals in log messages
- Comments mentioning the method
- Variable names like
processDocumentResult - XML documentation references
Now imagine doing a rename based on that. π
Meanwhile, Visual Studio knows β through Roslyn, the C# compiler β exactly:
- Where
ProcessDocumentis defined - Every place it's called (and nothing else)
- What interface declares it
- What classes override it
- What it's not (ProcessDocumentAsync is a different symbol)
The Solution: Expose Roslyn via MCP
VS-MCP is a Visual Studio extension that exposes Roslyn's semantic analysis as MCP (Model Context Protocol) tools.
Any MCP-compatible client β Claude Code, Claude Desktop, Codex CLI, Gemini CLI, OpenCode, Aider, Cline, Windsurf β can now use 20 tools powered by the actual C# compiler.
The Tools
π Navigation (find things semantically)
FindSymbols β Search symbols by name. Not text. Symbols.
You: "Find WhisperFactory in my solution"
AI: Found WhisperFactory
β Class | Whisper.net | WhisperFactory.cs | Line 16
One result. Exact. Knows it's a class, knows the namespace.
FindSymbolDefinition β The semantic equivalent of F12.
You: "Go to the definition of IDocumentService"
AI: β Interface | DocFlow.Core | IDocumentService.cs | Line 8
FindSymbolUsages β Every reference, compiler-verified.
You: "Find all usages of ProcessDocument"
AI: Found 4 usages:
β IDocumentService.cs:12 (declaration)
β DocumentService.cs:45 (implementation)
β DocumentController.cs:23 (call)
β BackgroundWorker.cs:67 (call)
Note: ProcessDocumentAsync NOT included β different symbol
GetSymbolAtLocation β What's at line X, column Y?
You: "What's the symbol at line 15 in Program.cs?"
AI: β Method: ConfigureServices | Class: Program | Returns: void
π³ Understanding (comprehend architecture)
GetInheritance β Full type hierarchy.
You: "What inherits from BaseDocument?"
AI: BaseDocument hierarchy:
β Base: EntityBase
β Interfaces: IDocument, ITrackable, IAuditable
β Derived: Invoice, PurchaseOrder, CreditNote, DeliveryNote
Try getting this from grep. I'll wait.
GetMethodCallers β Who calls this method?
You: "What calls ValidateToken?"
AI: ValidateToken is called by:
β ApiKeyMiddleware.Invoke()
β LoginController.Authenticate()
β RefreshTokenHandler.Handle()
GetMethodCalls β What does this method call?
You: "What does ValidateToken call internally?"
AI: ValidateToken calls:
β TokenRepository.FindByHash()
β ClaimsParser.Extract()
β AuditLogger.LogAccess()
Combine callers + callees and you have a call graph. From the compiler. Not from guessing.
GetDocumentOutline β Semantic structure of any file.
You: "Show me the structure of DocumentService.cs"
AI: DocumentService.cs outline:
β Namespace: DocFlow.Services
β Class: DocumentService : IDocumentService
β Method: ProcessDocument(Document doc) β Result
β Method: ValidateDocument(Document doc) β bool
β Property: Logger (ILogger)
β Field: _repository (IDocumentRepository)
βοΈ Refactoring (change things safely)
RenameSymbol β The killer tool. Roslyn-powered rename across the entire solution.
You: "Rename ProcessDocument to HandleDocument"
AI: β Renamed in 8 files, 23 locations
β Interface updated
β Implementations updated
β Call sites updated
β ProcessDocumentAsync: untouched (different symbol)
β String literals: untouched
β Build verification: 0 errors
FormatDocument β Visual Studio's own formatter, not dotnet format.
ποΈ Infrastructure
ExecuteCommand β Build/clean with structured diagnostics.
You: "Build MyProject"
AI: Build succeeded | 0 errors | 2 warnings
β Warning CS0168: Variable 'ex' declared but never used (File.cs:42)
ExecuteAsyncTest β Run tests with real-time status.
You: "Run the integration tests"
AI: Running tests... 12/45 passed
...
Complete: 44 passed, 1 failed
β Failed: TestPaymentProcessing β Assert.Equal failed
GetSolutionTree β Full solution structure.
GetProjectReferences β Dependency graph between projects.
TranslatePath β WSL β Windows path conversion (crucial for Claude Code users).
GetSelection / CheckSelection β Read active editor selection.
GetActiveFile β Current file and cursor position.
GetLoggingStatus / SetLogLevel β Diagnostics.
Multi-Solution: See Inside Your Dependencies
Enterprise devs don't just work on their own code. You depend on libraries β and sometimes you need the AI to understand those libraries too.
VS-MCP supports multiple Visual Studio instances simultaneously β each on its own configurable port.
Your project β VS-MCP on port 3010
Whisper.net source (cloned from GH) β VS-MCP on port 3011
EF Core source (cloned from GH) β VS-MCP on port 3012
Your AI connects to all three. Now it can:
- Find how library authors intended their API to be used
- Discover implementation patterns inside library source code
- Trace calls across your code and library code
- Understand inheritance that spans project boundaries
In your MCP client configuration, you simply set up named connections. Three options depending on your client:
Option 1: Clients with native HTTP support (Claude Desktop, Claude Code)
{
"mcpServers": {
"vs-mcp": {
"type": "http",
"url": "http://localhost:3010/sdk/"
},
"vs-mcp-whisper": {
"type": "http",
"url": "http://localhost:3011/sdk/"
}
}
}
Option 2: Clients without HTTP support (via mcp-remote proxy)
{
"mcpServers": {
"vs-mcp": {
"command": "npx",
"args": ["-y", "mcp-remote", "http://localhost:3010/sdk/"]
},
"vs-mcp-whisper": {
"command": "npx",
"args": ["-y", "mcp-remote", "http://localhost:3011/sdk/"]
}
}
}
Option 3: Codex CLI (TOML)
[mcp_servers.vs-mcp]
type = "stdio"
command = "npx"
args = ["mcp-remote", "http://localhost:3010/sdk/"]
[mcp_servers.vs-mcp-whisper]
type = "stdio"
command = "npx"
args = ["mcp-remote", "http://localhost:3011/sdk/"]
Each name tells the AI what it's connecting to. vs-mcp is your project, vs-mcp-whisper is the library source. The AI knows where to look.
No more guessing how a library works. Open the source, connect VS-MCP, and your AI reads it with compiler-level understanding.
Plus: toggle individual tools on/off and switch WSL/Windows path formats from a settings panel inside VS.
When You Need This
You don't need this for a weekend project with 3 files.
You need this when:
- Your solution has 20+ projects
- You have complex inheritance hierarchies
- Dependency injection makes grep useless for finding implementations
- You need safe refactoring across hundreds of files
- Your AI assistant keeps saying "I found 47 matches for that method name"
- You want your AI to understand architecture, not just read text
Installation
- Install from Visual Studio Marketplace
- Set your port in MCP Server Settings (default: 3010)
- Add to your MCP client config:
"vs-mcp": {
"type": "http",
"url": "http://localhost:3010/sdk/"
}
Or via mcp-remote for clients without native HTTP:
"vs-mcp": {
"command": "npx",
"args": ["-y", "mcp-remote", "http://localhost:3010/sdk/"]
}
- Your AI now has compiler-level intelligence
Works with Claude Code, Claude Desktop, Codex CLI, Gemini CLI, OpenCode, Aider, Cline, Windsurf, and any MCP-compatible client.
VS-MCP: 20 tools. 12 Roslyn-powered. Free.
π Website β
π₯ Install from Marketplace β
π¬ Watch the demo β
0ics srl β Italian software company specializing in AI-powered development tools.
Top comments (0)