Source of Truth: docs/ARCHITECTURE.md
Status: Canonical repo cleanup aligned to the current architecture as of 2026-05-16. This post summarizes how stdio and named pipes fit together; the focused stdio and named-pipe posts cover each transport in more detail.
Understanding a Local MCP Server Over Stdio and Local-Only Communication Over a Named Pipe
VS MCP Bridge uses two local communication boundaries together:
- An AI client talks to the local MCP server over stdio.
- The local MCP server talks to the Visual Studio extension over a named pipe.
Those two transports are easy to blur together, but they solve different problems. Stdio is the AI-facing MCP protocol boundary. The named pipe is the Visual Studio host boundary.
The Current Runtime Shape
The current VS-backed path is:
AI client
-> MCP over stdio
VsMcpBridge.McpServer
-> JSON request/response over local named pipe "VsMcpBridge"
VsMcpBridge.Vsix
-> Visual Studio SDK / DTE / editor state
The MCP server does not load inside Visual Studio. The VSIX does not speak MCP over stdout. Each side owns the work that belongs in its process.
Why stdio Exists
stdio gives the AI client a simple local way to launch and communicate with the MCP server. The client writes MCP messages to standard input and reads MCP responses from standard output. Microsoft documents the underlying .NET stream support through Process.StandardInput.
For MCP, the important rule is stricter than ordinary process communication: stdout is protocol output. It must stay clean. Random log lines, status messages, or troubleshooting text on stdout can corrupt the MCP conversation.
That is why diagnostics belong in transport-safe places: stderr where appropriate, local app-data logs, Visual Studio logs, UI logging, and durable trace artifacts. The MCP response stream should remain parseable protocol traffic.
Why the Named Pipe Exists
The named pipe exists because Visual Studio work belongs behind the VSIX boundary. The VSIX runs inside Visual Studio and can access DTE, editor state, solution state, the Error List, proposal review surfaces, and approved apply behavior.
The MCP server stays outside Visual Studio. For VS-backed tools, it uses a local named pipe to send a structured request to the VSIX. Microsoft documents the .NET named-pipe server primitive through NamedPipeServerStream.
This keeps Visual Studio concerns behind a local-only host boundary. The MCP server does not need DTE access, and the VSIX does not need to become an MCP stdio host.
The Two Boundaries Together
A normal VS-backed MCP call crosses the boundaries in order:
- The AI client sends an MCP tool request over stdio.
VsMcpBridge.McpServer resolves the registered MCP tool.
- The VS-backed tool method sends a request through
PipeClient.
PipeClient connects to the local VsMcpBridge named pipe.
PipeServer in the VSIX accepts and parses the request envelope.
- The pipe server dispatches only a known command to the host service layer.
VsService performs the Visual Studio operation.
- The response returns through the pipe.
- The MCP server returns the tool result over stdout.
The result is a local bridge, not a remote service and not one process doing everything.
Request Envelopes and Correlation
The named-pipe hop sends structured request/response envelopes, not free-form chat text. The envelope includes command and correlation metadata such as request IDs. Those IDs are how logs and trace artifacts reconnect a tool request to the pipe command and the host operation.
This matters because the useful troubleshooting question is rarely “did the bridge fail?” The useful question is more specific:
- Did the MCP request arrive over stdio?
- Did the MCP server resolve the expected tool?
- Did
PipeClient attempt the expected command?
- Did the named pipe connect?
- Did
PipeServer dispatch a known command?
- Did the Visual Studio-side operation complete?
- Did the response return through the same correlation chain?
That is the anti-black-box point of correlation metadata: the first missing boundary should be visible.
Startup and Activation Diagnostics
The VSIX side has to be active before VS-backed tools can succeed. In current live validation, the operator path is:
- Launch the Visual Studio Experimental Instance.
- Open View -> Other Windows -> VS MCP Bridge.
- Let the tool-window path initialize the VSIX/named-pipe side.
- Retry the VS-backed MCP tool.
If the MCP server cannot connect to the pipe, the current diagnostic path returns a structured activation message instead of an opaque timeout. That failure is still a tool result. It does not change the MCP transport, add retry loops, or write troubleshooting text outside the MCP response stream.
That distinction is useful: an inactive named pipe is not a stdio failure. It means the local MCP server could not reach the VSIX side.
Approval and Tool Execution Boundaries
The transports move requests. They do not authorize arbitrary behavior by themselves.
For Visual Studio edit operations, the named-pipe path reaches the VSIX proposal workflow. MCP can create proposals, but apply still requires explicit approval in the host UI.
For shared compiled bridge tools, execution flows through BridgeToolExecutor. That executor is the policy, approval, execution, audit, redaction, and correlation boundary for compiled tools. It owns the approval-aware tool execution seam, capability metadata evaluation hooks, secret-reference awareness, redacted audit envelopes, and classification metadata.
That means the full architecture has three different concerns, each with a different job:
- stdio moves MCP protocol messages between the AI client and local MCP server.
- named pipes move structured VS-backed requests between the MCP server and VSIX.
- BridgeToolExecutor governs shared compiled tool execution behind policy, approval, audit, and redaction seams.
Trace-Only Failure Evidence
Because stdout must stay clean, failure evidence lives in trace-safe places. The current repo keeps durable logs, metadata, and Mermaid sources for important paths, including inactive VSIX pipe diagnostics and shared tool execution.
A good inactive-pipe trace can be reconstructed as:
MCP tool request received
PipeClient attempted named-pipe connection
named pipe was unavailable
activation diagnostic returned
request/correlation metadata preserved
no raw payload or secret-like values disclosed
That is more useful than a raw timeout because it tells the operator what boundary failed and what to do next.
Related Mermaid Trace Sources
The repo already has Mermaid sources that support this article:
Those .mmd files are the diagram source of truth. This post references them directly instead of embedding generated images.
Why This Design Is Deliberate
The two transports keep the bridge small and local while preserving clear responsibilities:
- The AI client gets a standard MCP stdio process.
- The MCP server stays outside Visual Studio.
- Visual Studio APIs stay inside the VSIX.
- VS-backed operations cross a local named-pipe request boundary.
- Shared compiled tools have a separate execution/security boundary.
- Diagnostics stay reconstructable without polluting MCP stdout.
That separation is what lets the project add approval-aware execution, capability metadata, secret references, audit classification, and trace artifacts without turning transport code into a security policy engine.
Takeaway
The shortest accurate model is:
stdio gets into the MCP server
named pipes get into Visual Studio
BridgeToolExecutor governs shared compiled tool execution
Once that model is clear, the bridge becomes easier to reason about. Each boundary has a narrow job, and each important failure mode has somewhere observable to land.
— AI Systems Author