RoslynMcpServer

buchmiet/RoslynMcpServer

3.1

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.

Tools
5
Resources
0
Prompts
0

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 .sln and .csproj files
  • 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 NamePurposeKey Features
load_projectLoad .NET solution/projectInitialize workspace for analysis
get_type_infoType information retrievalMembers, methods, properties with pagination
find_referencesFind symbol usagesAll references across solution
describe_symbolSymbol detailsBy name or file position
goto_definitionNavigate to sourceFind where symbol is defined
get_method_dependenciesAnalyze method callsCall graph, reads/writes, callers
get_inheritance_treeType hierarchyBase classes, interfaces, derived types
get_all_implementationsInterface implementationsFind all concrete implementations
test_symbol_formattingDiagnostic toolVerify 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: 1
  • pageSize (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 symbol
  • page (integer, optional): Page number (1-based), default: 1, minimum: 1
  • pageSize (integer, optional): Number of results per page, default: 200, range: 1-500
  • timeoutMs (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 nextCursor for pagination (opaque token for the next page)
  • Increase timeoutMs for 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
  • isSourceDefinition indicates if actual source code was found
  • isFromMetadata indicates 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: 1
  • includeCallers (boolean, optional): Include list of callers of the root method, default: false
  • treatPropertiesAsMethods (boolean, optional): Report property accessors as method calls, default: true
  • page (integer, optional): Page number for calls list, default: 1, minimum: 1
  • pageSize (integer, optional): Number of results per page, default: 200, range: 1-500
  • timeoutMs (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:

  • depth controls how deep to traverse the call graph (1 = direct calls only, 2+ = transitive)
  • Use includeCallers to understand what code depends on this method
  • reads and writes help 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

  1. Always Load First: Call load_project before any other tool
  2. Use Absolute Paths: All file paths must be absolute, not relative
  3. Pagination: Use pagination for large result sets to avoid timeouts
  4. Timeouts: Increase timeoutMs for complex operations on large codebases
  5. Position vs Name: Use file/line/column for precise location, FQN for known symbols

Performance Considerations

  • Project Loading: Prefer .csproj over .sln for faster loading
  • Depth Limits: Use reasonable depth values (1-3) for dependency analysis
  • Solution Scope: Set solutionOnly: true to 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: true
  • includeOverrides (boolean, optional): Include override information per member, default: false
  • maxDepth (integer, optional): Maximum depth for descendants tree, default: 10, range: 1-100
  • solutionOnly (boolean, optional): Only include types with source in loaded solution, default: true
  • page (integer, optional): Page number for flat descendants list, default: 1
  • pageSize (integer, optional): Number of results per page, default: 200, range: 1-500
  • timeoutMs (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:

  • descendantsTree provides hierarchical view, descendantsFlat provides linear list
  • Use solutionOnly: false to include framework types in the hierarchy
  • includeOverrides shows 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 type
  • solutionOnly (boolean, optional): Only include implementations in loaded solution, default: true
  • includeDerivedInterfaces (boolean, optional): Include derived interfaces, default: true
  • page (integer, optional): Page number, default: 1
  • pageSize (integer, optional): Number of results per page, default: 200, range: 1-500
  • timeoutMs (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 member parameter to find implementations of a specific method/property
  • includeDerivedInterfaces helps track interface inheritance chains
  • Combine with solutionOnly: false to 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

CommandDescriptionArguments
loadLoad project/solution<path>
typeGet type information<type-name> [page-size]
refsFind references<symbol-name>
symbolDescribe symbol<symbol-name>
defGo to definition<symbol-name>
depsGet dependencies<method> [depth] [include-callers]
treeGet inheritance tree<type> [direction]
implGet implementations<interface>
testTest 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

  • OpenSolutionAsync may 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