buchmiet/RoslynMcpServer
If you are the rightful owner of RoslynMcpServer and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to dayong@mcphub.com.
The Roslyn MCP Server is a Model Context Protocol server that provides Roslyn-based code analysis tools for .NET solutions and projects.
Roslyn MCP Server
A Model Context Protocol (MCP) server that provides Roslyn-based code analysis tools for .NET solutions and projects.
Features
- Load .NET solutions and projects - Support for
.slnand.csprojfiles - Type information retrieval - Get detailed information about types including members, accessibility, and documentation
- Find references - Search for all references to a symbol across the entire solution
- Symbol formatting - Format symbols with source location information
- Describe symbols - Get detailed information about any symbol by name or position
- Go to definition - Find the source definition of symbols
Prerequisites
- .NET 9.0 SDK or later
- MSBuild (included with .NET SDK)
Building
dotnet build src/RoslynMcpServer/RoslynMcpServer.csproj
Running
The server communicates via JSON-RPC 2.0 over stdin/stdout:
dotnet run --project src/RoslynMcpServer/RoslynMcpServer.csproj
Run as DLL
For production use, build the Release configuration and run the compiled DLL directly:
# Build Release configuration
dotnet build -c Release src/RoslynMcpServer/RoslynMcpServer.csproj
# Run the DLL directly (replace <YOUR_PATH> with your actual installation path)
dotnet <YOUR_PATH>/RoslynMcpServer/src/RoslynMcpServer/bin/Release/net9.0/RoslynMcpServer.dll
The server uses newline-delimited JSON (NDJSON) for JSON-RPC messages as per the MCP STDIO transport specification. Messages are delimited by newlines (LF), and must not contain embedded newlines. All logging and diagnostic output is sent to STDERR, keeping STDOUT clean for JSON-RPC communication.
Self-Test STDIO
To verify the server is working correctly with clean STDIO:
# Test the JSON-RPC communication (NDJSON format)
# Replace <YOUR_PATH> with your actual installation path
printf '{"jsonrpc":"2.0","method":"tools/list","params":{},"id":1}\n' | \
dotnet <YOUR_PATH>/RoslynMcpServer/src/RoslynMcpServer/bin/Release/net9.0/RoslynMcpServer.dll
# Expected: JSON-RPC response as a single line terminated with newline, no extra text on STDOUT
Available Tools
The Roslyn MCP Server provides 9 powerful tools for .NET code analysis. Each tool has a specific description that AI models see, along with a detailed input schema defining available parameters.
Tools Overview
| Tool Name | Purpose | Key Features |
|---|---|---|
| load_project | Load .NET solution/project | Initialize workspace for analysis |
| get_type_info | Type information retrieval | Members, methods, properties with pagination |
| find_references | Find symbol usages | All references across solution |
| describe_symbol | Symbol details | By name or file position |
| goto_definition | Navigate to source | Find where symbol is defined |
| get_method_dependencies | Analyze method calls | Call graph, reads/writes, callers |
| get_inheritance_tree | Type hierarchy | Base classes, interfaces, derived types |
| get_all_implementations | Interface implementations | Find all concrete implementations |
| test_symbol_formatting | Diagnostic tool | Verify server functionality |
1. load_project (formerly load_solution)
Model Description: "Load a .NET project file (.csproj) or solution (.sln) for analysis. Prefer .csproj files. Use ABSOLUTE paths only!"
Purpose: Loads a .NET solution or project file into memory for analysis by other tools.
Parameters:
path(string, required): ABSOLUTE path to the .csproj (preferred) or .sln file
Example Request:
{
"jsonrpc": "2.0",
"method": "tools/call",
"params": [{
"name": "load_project",
"arguments": {
"path": "/absolute/path/to/MyProject.csproj" // Replace with your actual project path
}
}],
"id": 1
}
Example Response:
{
"success": true,
"solutionPath": "/absolute/path/to/MyProject.csproj", // Your actual path will be here
"projectCount": 3,
"projects": [
{"name": "MyProject", "tfm": "net9.0"},
{"name": "MyProject.Tests", "tfm": "net9.0"}
]
}
Usage Notes:
- Always use absolute paths
- Prefer .csproj files over .sln for faster loading
- Must be called before using any other analysis tools
- The tool maintains backward compatibility with "load_solution" name
2. get_type_info
Model Description: "Get detailed information about a type including members, inheritance, and documentation"
Purpose: Retrieves comprehensive information about a type, including all its members (fields, properties, methods, events), with pagination support for large types.
Parameters:
fullyQualifiedName(string, required): Fully qualified name of the type (e.g., System.String, MyNamespace.MyClass)page(integer, optional): Page number (1-based), default: 1, minimum: 1pageSize(integer, optional): Number of results per page, default: 200, range: 1-500
Example Request:
{
"jsonrpc": "2.0",
"method": "tools/call",
"params": [{
"name": "get_type_info",
"arguments": {
"fullyQualifiedName": "System.Collections.Generic.List`1",
"pageSize": 20
}
}],
"id": 2
}
Example Response:
{
"success": true,
"symbol": {
"display": "class List<T>",
"file": null,
"line": -1,
"column": -1
},
"totalMembers": 85,
"page": 1,
"pageSize": 20,
"members": [
{
"Name": "Count",
"Kind": "Property",
"Accessibility": "Public",
"IsStatic": false,
"Type": "int",
"Parameters": null
},
{
"Name": "Add",
"Kind": "Method",
"Accessibility": "Public",
"IsStatic": false,
"Type": "void",
"Parameters": "T item"
}
],
"nextCursor": "page=2"
}
Usage Notes:
- Use pagination for types with many members (e.g., System.String has 200+ members)
- Members include fields, properties, methods, constructors, events, and nested types
- Generic types should include backtick notation (e.g.,
List1forList`)
3. find_references
Model Description: "Find all references to a symbol in the loaded solution"
Purpose: Searches the entire loaded solution to find all usages and references to a specified symbol (type, method, property, field, etc.).
Parameters:
fullyQualifiedName(string, required): Fully qualified name of the symbolpage(integer, optional): Page number (1-based), default: 1, minimum: 1pageSize(integer, optional): Number of results per page, default: 200, range: 1-500timeoutMs(integer, optional): Timeout in milliseconds, default: 60000, range: 1000-300000
Example Request:
{
"jsonrpc": "2.0",
"method": "tools/call",
"params": [{
"name": "find_references",
"arguments": {
"fullyQualifiedName": "MyApp.Services.IUserService.GetUserAsync",
"pageSize": 25,
"timeoutMs": 120000
}
}],
"id": 3
}
Example Response:
{
"success": true,
"total": 47,
"page": 1,
"pageSize": 25,
"references": [
{
"file": "/src/MyApp/Controllers/UserController.cs",
"line": 42,
"column": 15,
"text": "var user = await _userService.GetUserAsync(userId);"
},
{
"file": "/src/MyApp/Services/OrderService.cs",
"line": 108,
"column": 20,
"text": "var customer = await userService.GetUserAsync(order.CustomerId);"
}
],
"nextCursor": "eyJvZmZzZXQiOjI1fQ=="
}
Usage Notes:
- The search includes all direct references, method calls, type instantiations, and inheritance
- Use
nextCursorfor pagination (opaque token for the next page) - Increase
timeoutMsfor large solutions or complex symbols - Results include the exact line of code containing the reference
4. describe_symbol
Model Description: "Get detailed information about a symbol by fully qualified name or file position"
Purpose: Retrieves detailed information about any symbol, either by its fully qualified name or by specifying a position in a file. Useful for understanding what's at a specific code location.
Parameters (Option 1 - by name):
fullyQualifiedName(string): Fully qualified name of the symbol (provide this OR file/line/column)
Parameters (Option 2 - by position):
file(string): File path (use with line and column)line(integer): Line number (1-based, use with file and column)column(integer): Column number (1-based, use with file and line)
Example Request (by name):
{
"jsonrpc": "2.0",
"method": "tools/call",
"params": [{
"name": "describe_symbol",
"arguments": {
"fullyQualifiedName": "System.Linq.Enumerable.Where"
}
}],
"id": 4
}
Example Request (by position):
{
"jsonrpc": "2.0",
"method": "tools/call",
"params": [{
"name": "describe_symbol",
"arguments": {
"file": "/src/MyApp/Services/UserService.cs",
"line": 42,
"column": 20
}
}],
"id": 5
}
Example Response:
{
"success": true,
"display": "Task<User?> UserService.GetUserAsync(int userId)",
"file": "/src/MyApp/Services/UserService.cs",
"line": 42,
"column": 17,
"kind": "Method",
"containingType": "MyApp.Services.UserService",
"containingNamespace": "MyApp.Services",
"isAsync": true,
"returnType": "Task<User?>",
"accessibility": "Public"
}
Usage Notes:
- Position-based lookup is useful for IDE-like "go to definition" scenarios
- Returns comprehensive metadata about the symbol including its kind, containing type, and namespace
- Works with any symbol: types, methods, properties, fields, parameters, local variables
5. goto_definition
Model Description: "Find the source definition of a symbol"
Purpose: Locates the exact source code location where a symbol is defined. If source code is not available (e.g., for framework types), returns the metadata definition location.
Parameters:
fullyQualifiedName(string, required): Fully qualified name of the symbol
Example Request:
{
"jsonrpc": "2.0",
"method": "tools/call",
"params": [{
"name": "goto_definition",
"arguments": {
"fullyQualifiedName": "MyApp.Core.Domain.User.Validate"
}
}],
"id": 6
}
Example Response:
{
"success": true,
"display": "bool User.Validate()",
"file": "/src/MyApp.Core/Domain/User.cs",
"line": 156,
"column": 17,
"isSourceDefinition": true,
"isFromMetadata": false,
"kind": "Method",
"containingType": "MyApp.Core.Domain.User",
"containingNamespace": "MyApp.Core.Domain"
}
Usage Notes:
- Essential for navigation and code exploration
isSourceDefinitionindicates if actual source code was foundisFromMetadataindicates if the definition comes from compiled assemblies- Returns exact file path, line, and column for precise navigation
6. get_method_dependencies
Model Description: "Analyze method dependencies: calls, reads/writes of fields/properties; optional callers"
Purpose: Provides deep analysis of a method's dependencies, including what it calls, what fields/properties it reads or writes, and optionally who calls it. Supports transitive analysis with configurable depth.
Parameters:
fullyQualifiedName(string): Fully qualified name (or use file/line/column)file(string): File path (alternative to fullyQualifiedName)line(integer): Line number (1-based, use with file)column(integer): Column number (1-based, use with file)depth(integer, optional): Traversal depth for transitive calls, default: 1, minimum: 1includeCallers(boolean, optional): Include list of callers of the root method, default: falsetreatPropertiesAsMethods(boolean, optional): Report property accessors as method calls, default: truepage(integer, optional): Page number for calls list, default: 1, minimum: 1pageSize(integer, optional): Number of results per page, default: 200, range: 1-500timeoutMs(integer, optional): Timeout in milliseconds, default: 60000, range: 1000-300000
Example Request:
{
"jsonrpc": "2.0",
"method": "tools/call",
"params": [{
"name": "get_method_dependencies",
"arguments": {
"fullyQualifiedName": "MyApp.Services.OrderService.ProcessOrderAsync",
"depth": 3,
"includeCallers": true,
"treatPropertiesAsMethods": true,
"pageSize": 100
}
}],
"id": 7
}
Example Response:
{
"success": true,
"symbol": {
"display": "async Task<OrderResult> OrderService.ProcessOrderAsync(Order order)",
"file": "/src/MyApp/Services/OrderService.cs",
"line": 45,
"column": 17
},
"totalCalls": 12,
"calls": [
{
"display": "Task<bool> IPaymentService.ProcessPaymentAsync(decimal amount)",
"file": "/src/MyApp/Services/PaymentService.cs",
"line": 23,
"column": 17
},
{
"display": "void ILogger.LogInformation(string message)",
"file": null,
"line": -1,
"column": -1
}
],
"reads": [
{
"display": "OrderSettings OrderService._settings",
"file": "/src/MyApp/Services/OrderService.cs",
"line": 12,
"column": 19
}
],
"writes": [
{
"display": "DateTime Order.ProcessedAt",
"file": "/src/MyApp/Models/Order.cs",
"line": 34,
"column": 19
}
],
"callers": [
{
"display": "Task<IActionResult> OrderController.CreateOrder(OrderDto dto)",
"file": "/src/MyApp/Controllers/OrderController.cs",
"line": 67,
"column": 15
}
],
"page": 1,
"pageSize": 100,
"nextCursor": null
}
Usage Notes:
depthcontrols how deep to traverse the call graph (1 = direct calls only, 2+ = transitive)- Use
includeCallersto understand what code depends on this method readsandwriteshelp identify data dependencies and potential side effects- Excellent for understanding method complexity and refactoring impact
9. test_symbol_formatting
Model Description: "Test tool to demonstrate symbol formatting with location info"
Purpose: A diagnostic tool that tests and demonstrates the server's symbol formatting capabilities. Useful for verifying the server is working correctly.
Parameters:
- None required
Example Request:
{
"jsonrpc": "2.0",
"method": "tools/call",
"params": [{
"name": "test_symbol_formatting",
"arguments": {}
}],
"id": 11
}
Example Response:
{
"success": true,
"message": "Symbol formatting test completed",
"examples": [
{
"symbol": "System.String",
"formatted": "class String",
"location": "metadata"
},
{
"symbol": "MyApp.Core.User",
"formatted": "class User",
"location": "/src/MyApp.Core/User.cs:10:5"
}
]
}
Tool Usage Patterns
Common Workflows
1. Code Navigation Flow:
load_project → describe_symbol → goto_definition → find_references
2. Type Analysis Flow:
load_project → get_type_info → get_inheritance_tree → get_all_implementations
3. Dependency Analysis Flow:
load_project → get_method_dependencies (depth:3, includeCallers:true)
4. Refactoring Preparation:
load_project → find_references → get_method_dependencies → get_inheritance_tree
Best Practices
- Always Load First: Call
load_projectbefore any other tool - Use Absolute Paths: All file paths must be absolute, not relative
- Pagination: Use pagination for large result sets to avoid timeouts
- Timeouts: Increase
timeoutMsfor complex operations on large codebases - Position vs Name: Use file/line/column for precise location, FQN for known symbols
Performance Considerations
- Project Loading: Prefer
.csprojover.slnfor faster loading - Depth Limits: Use reasonable depth values (1-3) for dependency analysis
- Solution Scope: Set
solutionOnly: trueto limit results to your code - Caching: The server caches loaded solutions for subsequent operations
STDIO Examples (CLI)
All tools communicate via MCP over STDIO using NDJSON. Below are quick CLI snippets using printf piped into the running server.
Note: Load a solution or project first.
# Load solution or project (replace <YOUR_SOLUTION_PATH> with actual path)
printf '{"jsonrpc":"2.0","method":"tools/call","params":[{"name":"load_solution","arguments":{"path":"<YOUR_SOLUTION_PATH>/your.sln"}}],"id":1}\n' \
| dotnet run --project src/RoslynMcpServer/RoslynMcpServer.csproj
get_method_dependencies:
printf '{"jsonrpc":"2.0","method":"tools/call","params":[{"name":"get_method_dependencies","arguments":{"fullyQualifiedName":"MyApp.Core.Utils.DoWork","depth":2,"includeCallers":true}}],"id":2}\n' \
| dotnet run --project src/RoslynMcpServer/RoslynMcpServer.csproj
get_inheritance_tree:
printf '{"jsonrpc":"2.0","method":"tools/call","params":[{"name":"get_inheritance_tree","arguments":{"fullyQualifiedName":"MyApp.Core.BaseType","direction":"descendants","includeInterfaces":true}}],"id":3}\n' \
| dotnet run --project src/RoslynMcpServer/RoslynMcpServer.csproj
get_all_implementations:
printf '{"jsonrpc":"2.0","method":"tools/call","params":[{"name":"get_all_implementations","arguments":{"fullyQualifiedName":"MyApp.Core.IMyInterface","includeDerivedInterfaces":true}}],"id":4}\n' \
| dotnet run --project src/RoslynMcpServer/RoslynMcpServer.csproj
get_type_info:
printf '{"jsonrpc":"2.0","method":"tools/call","params":[{"name":"get_type_info","arguments":{"fullyQualifiedName":"System.String","pageSize":10}}],"id":5}\n' \
| dotnet run --project src/RoslynMcpServer/RoslynMcpServer.csproj
find_references:
printf '{"jsonrpc":"2.0","method":"tools/call","params":[{"name":"find_references","arguments":{"fullyQualifiedName":"MyApp.Core.SomeType","pageSize":50}}],"id":6}\n' \
| dotnet run --project src/RoslynMcpServer/RoslynMcpServer.csproj
describe_symbol (by name):
printf '{"jsonrpc":"2.0","method":"tools/call","params":[{"name":"describe_symbol","arguments":{"fullyQualifiedName":"System.Console.WriteLine"}}],"id":7}\n' \
| dotnet run --project src/RoslynMcpServer/RoslynMcpServer.csproj
describe_symbol (by position):
printf '{"jsonrpc":"2.0","method":"tools/call","params":[{"name":"describe_symbol","arguments":{"file":"/absolute/path/to/File.cs","line":42,"column":15}}],"id":8}\n' \
| dotnet run --project src/RoslynMcpServer/RoslynMcpServer.csproj
goto_definition:
printf '{"jsonrpc":"2.0","method":"tools/call","params":[{"name":"goto_definition","arguments":{"fullyQualifiedName":"MyApp.Core.SomeType.SomeMethod"}}],"id":9}\n' \
| dotnet run --project src/RoslynMcpServer/RoslynMcpServer.csproj
test_symbol_formatting:
printf '{"jsonrpc":"2.0","method":"tools/call","params":[{"name":"test_symbol_formatting","arguments":{}}],"id":10}\n' \
| dotnet run --project src/RoslynMcpServer/RoslynMcpServer.csproj
7. get_inheritance_tree
Model Description: "Return full inheritance tree (ancestors, interfaces, descendants; optional overrides)"
Purpose: Analyzes the complete inheritance hierarchy of a type, showing base classes, implemented interfaces, and derived types. Can optionally include override information for virtual members.
Parameters:
fullyQualifiedName(string): Target type name (or use file/line/column)file(string): File path (alternative to fullyQualifiedName)line(integer): Line number (1-based, use with file)column(integer): Column number (1-based, use with file)direction(string, optional): Tree direction - "both", "ancestors", or "descendants", default: "both"includeInterfaces(boolean, optional): Include implemented interfaces, default: trueincludeOverrides(boolean, optional): Include override information per member, default: falsemaxDepth(integer, optional): Maximum depth for descendants tree, default: 10, range: 1-100solutionOnly(boolean, optional): Only include types with source in loaded solution, default: truepage(integer, optional): Page number for flat descendants list, default: 1pageSize(integer, optional): Number of results per page, default: 200, range: 1-500timeoutMs(integer, optional): Timeout in milliseconds, default: 60000, range: 1000-300000
Example Request:
{
"jsonrpc": "2.0",
"method": "tools/call",
"params": [{
"name": "get_inheritance_tree",
"arguments": {
"fullyQualifiedName": "MyApp.Core.Domain.BaseEntity",
"direction": "descendants",
"includeInterfaces": true,
"includeOverrides": true,
"maxDepth": 5
}
}],
"id": 8
}
Example Response:
{
"success": true,
"root": {
"display": "abstract class BaseEntity",
"file": "/src/MyApp.Core/Domain/BaseEntity.cs",
"line": 5,
"column": 14
},
"ancestors": [
{"display": "class System.Object"}
],
"interfaces": [
{"display": "interface IEntity"},
{"display": "interface IValidatable"}
],
"descendantsTree": {
"display": "class User : BaseEntity",
"file": "/src/MyApp.Core/Domain/User.cs",
"children": [
{
"display": "class AdminUser : User",
"file": "/src/MyApp.Core/Domain/AdminUser.cs",
"children": []
}
]
},
"descendantsFlat": [
{"display": "class User : BaseEntity"},
{"display": "class AdminUser : User"},
{"display": "class Product : BaseEntity"}
],
"overrides": {
"Validate": [
{"type": "User", "hasOverride": true},
{"type": "Product", "hasOverride": true}
]
},
"page": 1,
"pageSize": 200,
"total": 3
}
Usage Notes:
descendantsTreeprovides hierarchical view,descendantsFlatprovides linear list- Use
solutionOnly: falseto include framework types in the hierarchy includeOverridesshows which derived types override virtual/abstract members- Essential for understanding type hierarchies and polymorphic behavior
8. get_all_implementations
Model Description: "List all implementations of an interface, or implementations of a specific interface member"
Purpose: Finds all concrete implementations of an interface or a specific interface member. Useful for understanding how contracts are implemented across the codebase.
Parameters:
fullyQualifiedName(string): Target interface or interface member (or use file/line/column)file(string): File path (alternative to fullyQualifiedName)line(integer): Line number (1-based, use with file)column(integer): Column number (1-based, use with file)member(string, optional): Specific member name when FQN points to interface typesolutionOnly(boolean, optional): Only include implementations in loaded solution, default: trueincludeDerivedInterfaces(boolean, optional): Include derived interfaces, default: truepage(integer, optional): Page number, default: 1pageSize(integer, optional): Number of results per page, default: 200, range: 1-500timeoutMs(integer, optional): Timeout in milliseconds, default: 60000, range: 1000-300000
Example Request (interface):
{
"jsonrpc": "2.0",
"method": "tools/call",
"params": [{
"name": "get_all_implementations",
"arguments": {
"fullyQualifiedName": "MyApp.Services.IUserService",
"includeDerivedInterfaces": true,
"solutionOnly": true
}
}],
"id": 9
}
Example Request (specific member):
{
"jsonrpc": "2.0",
"method": "tools/call",
"params": [{
"name": "get_all_implementations",
"arguments": {
"fullyQualifiedName": "MyApp.Services.IUserService",
"member": "GetUserAsync",
"includeDerivedInterfaces": false
}
}],
"id": 10
}
Example Response:
{
"success": true,
"interface": {
"display": "interface IUserService",
"file": "/src/MyApp/Services/IUserService.cs",
"line": 5
},
"derivedInterfaces": [
{
"display": "interface IExtendedUserService : IUserService",
"file": "/src/MyApp/Services/IExtendedUserService.cs"
}
],
"implementations": [
{
"display": "class UserService : IUserService",
"file": "/src/MyApp/Services/UserService.cs",
"line": 12
},
{
"display": "class CachedUserService : IUserService",
"file": "/src/MyApp/Services/CachedUserService.cs",
"line": 8
},
{
"display": "class MockUserService : IUserService",
"file": "/tests/MyApp.Tests/Mocks/MockUserService.cs",
"line": 6
}
],
"memberImplementations": {
"GetUserAsync": [
{"type": "UserService", "hasImplementation": true},
{"type": "CachedUserService", "hasImplementation": true},
{"type": "MockUserService", "hasImplementation": true}
]
},
"total": 3,
"page": 1,
"pageSize": 200
}
Usage Notes:
- Essential for dependency injection analysis and understanding interface usage
- Use
memberparameter to find implementations of a specific method/property includeDerivedInterfaceshelps track interface inheritance chains- Combine with
solutionOnly: falseto include framework implementations
AI-Friendly Usage (0.2.0)
The Roslyn MCP Server now includes AI-friendly wrappers that provide deterministic, non-interactive access to the server's functionality. These tools output clean NDJSON and route all logging to STDERR, making them ideal for automated systems and AI agents.
All tools require a prior load_project call before using analysis commands.
Single-Shot Commands
Execute one-off commands using the bash wrapper:
# Load a project (always do this first)
# Replace <YOUR_PROJECT_PATH> with your actual project path
./tools/ai/roslyn-ai.sh --load "<YOUR_PROJECT_PATH>/YourProject.csproj"
# Get type information
./tools/ai/roslyn-ai.sh --type "System.String" 20
# Find references
./tools/ai/roslyn-ai.sh --refs "MyNamespace.MyClass"
# Get method dependencies
./tools/ai/roslyn-ai.sh --deps "MyClass.MyMethod" 2 true
# Get inheritance tree
./tools/ai/roslyn-ai.sh --tree "MyClass" descendants
Session Mode
Load a project and execute a command in one call:
# Example using the session helper
# Replace <YOUR_PROJECT_PATH> with your actual project path
./examples/ai/session.sh "<YOUR_PROJECT_PATH>/YourProject.csproj"
# Manual session mode
./tools/ai/roslyn-ai.sh --session "<YOUR_PROJECT_PATH>/YourProject.csproj" type System.String 10
Batch Mode
Execute multiple commands from a file or stdin:
# Using the batch example
# Replace <YOUR_PROJECT_PATH> with your actual project path
./examples/ai/run_batch.sh "<YOUR_PROJECT_PATH>/YourProject.csproj"
# Manual batch mode with file
./tools/ai/roslyn-ai.sh --batch commands.txt
# Batch mode from stdin (replace <PROJECT_PATH> with actual path)
echo -e "load <PROJECT_PATH>/project.csproj\ntype System.String\nrefs MyClass" | ./tools/ai/roslyn-ai.sh --batch
Python Interface
Use the Python wrapper for programmatic access:
from tools.ai.roslyn_mcp_ai import RoslynMCP
# Context manager approach (recommended)
with RoslynMCP() as mcp:
# Load project first (replace with your actual project path)
result = mcp.load_project("/your/actual/path/to/project.csproj")
if not result.success:
print(f"Error: {result.error}")
return
# Get type information
result = mcp.get_type_info("System.String")
print(result.data)
# CLI usage (replace <YOUR_PROJECT_PATH> with actual path)
python3 ./tools/ai/roslyn_mcp_ai.py \
--project "<YOUR_PROJECT_PATH>/project.csproj" \
--command type \
--target "System.String" \
--page-size 20 \
--json
Features
- Deterministic Output: All responses are consistent NDJSON
- Clean STDOUT: Only data output, all logs go to STDERR
- Error Handling: Non-zero exit codes on errors
- Timeouts: Configurable timeouts for operations
- Multiple Formats: Bash scripts, Python class, and CLI tools
Available Commands
| Command | Description | Arguments |
|---|---|---|
load | Load project/solution | <path> |
type | Get type information | <type-name> [page-size] |
refs | Find references | <symbol-name> |
symbol | Describe symbol | <symbol-name> |
def | Go to definition | <symbol-name> |
deps | Get dependencies | <method> [depth] [include-callers] |
tree | Get inheritance tree | <type> [direction] |
impl | Get implementations | <interface> |
test | Test formatting | (no args) |
Note: All file paths must be absolute paths. The wrappers require the main server to be built first.
Protocol
The server implements the Model Context Protocol (MCP) using JSON-RPC 2.0. Messages are transmitted using the NDJSON (newline-delimited JSON) format.
Message Format
Request:
{"jsonrpc":"2.0","method":"<method>","params":<params>,"id":<id>}\n
Response:
{"jsonrpc":"2.0","id":<id>,"result":<result>}\n
Transport (STDIO)
The server uses the MCP STDIO transport with NDJSON format:
- Format: One JSON object per line, terminated by
\n(LF) - Encoding: UTF-8
- No embedded newlines: JSON messages must not contain literal newlines
- Output streams:
- STDOUT: Only valid MCP messages
- STDERR: All logs and diagnostic output
For more details, see the MCP Transport specification.
Error Handling
- Missing or invalid arguments return an error with
isError: true - Timeouts are handled gracefully with appropriate error messages
- WorkspaceFailed events are logged to stderr for debugging
Known Issues
OpenSolutionAsyncmay hang in some environments. The server includes a 90-second timeout as a workaround.- Target framework detection may not work for all project types.
Development
The project is structured as follows:
src/RoslynMcpServer/
Infrastructure/ # MCP protocol implementation
McpServer.cs # Main MCP server with tool registration
JsonRpcLoop.cs # JSON-RPC message handling
Roslyn/ # Roslyn integration
WorkspaceHost.cs # MSBuild workspace management
SymbolFormatting.cs # Symbol display formatting
Tools/ # MCP tool implementations
LoadSolutionTool.cs # Solution/project loading
GetTypeInfoTool.cs # Type information retrieval
FindReferencesTool.cs # Reference finding
DescribeSymbolTool.cs # Symbol description by name or position
GotoDefinitionTool.cs # Find symbol source definition
License
MIT