ASP.NET Core implementation of a Model Context Protocol (MCP) server that exposes tools for working with C# code, including a semantic search_local_repo tool backed by an external search service with a local fallback.
- HTTP-based MCP server (
MapMcp) suitable for use from MCP-enabled clients. search_local_repotool for semantic search over a C# repository.- Calls a configurable remote semantic search endpoint.
- Falls back to a local scan of the repo when the remote call fails.
- Strongly typed request/response models (
AskRequest,AskResponse,CodeChunk). - Source-generated JSON serialization via
AppJsonSerializerContext. - Resilient HTTP client with retry and timeout policies.
- Centralized error handling via
GlobalExceptionHandlerandProblemDetails.
src/McpServer/Program.cs– minimal hosting setup, wiring of services and MCP endpoint.src/McpServer/Configuration/ServiceExtensions.cs– DI and configuration extension methods:AddHttp– configures theCSharpCodeServiceHTTP client and resilience.AddSettings– bindsCSharpCodeSettingsfrom configuration.AddServices– registers MCP server and tools.
src/McpServer/McpTools/CSharpCodeTools.cs– MCP tool definitions, includingsearch_local_repo.src/McpServer/Services/CSharpCodeService.cs– calls the external semantic search API and implements local fallback.src/McpServer/Models/*.cs– DTOs used by the tool and service:AskRequest– question text andTopKvalue.AskResponse/SearchResonse– answer and ranked code chunks.CodeChunk– information about each code snippet.
src/McpServer/Settings/CSharpCodeSettings.cs– configuration for the external search service.src/McpServer/appsettings.json– default configuration (logging andCSharpCodeSettings).src/McpServer/McpServer.http– example HTTP requests for manual testing..mcp.json– example MCP client configuration pointing at this server.
- .NET SDK compatible with the target framework configured in the project (see
.csproj). - An external semantic search API that accepts the
AskRequestpayload and returns anAskResponse-compatible JSON body, or willingness to rely on the built-in local fallback.
Primary configuration lives in src/McpServer/appsettings.json and environment-specific overrides (for example appsettings.Development.json). Relevant section:
"CSharpCodeSettings": {
"SearchEndpoint": "http://localhost:9020/api/ask",
"TopK": 10
}SearchEndpoint– URL of the remote semantic search endpoint the server will POST to.TopK– default maximum number of results for searches.
Configuration is loaded and attached to the builder in AddConfiguration, and bound to CSharpCodeSettings via AddSettings.
From the repository root:
cd src/McpServer
dotnet runBy default, Program.cs configures Kestrel to listen on:
http://*:5000
You can adjust the URLs in Program.cs or via standard ASP.NET Core hosting configuration (for example the ASPNETCORE_URLS environment variable).
The server uses AddMcpServer() and MapMcp() to expose tools over HTTP. A minimal MCP HTTP client request flow is illustrated in src/McpServer/McpServer.http:
initializecall to start a session.tools/callwithname: "search_local_repo"to execute the tool.
Example tools/call body:
{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "search_local_repo",
"arguments": {
"prompt": "Find code that chunks c# files",
"topK": 10
}
}
}Adjust your client-side .mcp.json (or equivalent) to point at the URL where this server is running. The sample .mcp.json included in the repo shows a basic HTTP configuration.
- The MCP runtime invokes
CSharpCodeTools.SearchLocalRepowith:prompt– the query text.topK– an optional maximum number of results.
- The tool creates an
AskRequestinstance and callsCSharpCodeService.SearchLocalRepo. CSharpCodeService:- Serializes the request with
AppJsonSerializerContext. - POSTs it to the configured
SearchEndpoint. - Deserializes the response to
AskResponseon success. - If the HTTP call fails or throws, logs a warning and falls back to a local search.
- Serializes the request with
- The local fallback:
- Locates the repo root by walking up from the current directory.
- Enumerates
*.csfiles undersrc/McpServer, skippingbin/obj. - Scores files by how many query terms they contain.
- Builds
CodeChunkresults with a short snippet and content hash. - Returns an
AskResponsesummarizing matches.
CSharpCodeTools.SearchLocalReposerializes theAskResponseto JSON usingAppJsonSerializerContextand returns it to the MCP client.
The project uses source-generated serialization via AppJsonSerializerContext in CSharpCodeTools.cs, annotated with JsonSerializable for all relevant types (AskRequest, AskResponse, SearchResonse, CodeChunk, and some primitives). This context is passed explicitly to JsonSerializer to ensure consistent, efficient serialization for both HTTP calls and MCP responses.
To add a new MCP tool:
- Create a new public class in
src/McpServer/McpToolsmarked with[McpServerToolType]. - Add static methods annotated with
[McpServerTool](and optional[Description]). - Register the tool type in
AddServicesvia.WithTools<YourToolClass>(). - If the tool needs new request/response models, add them under
src/McpServer/Modelsand register them withAppJsonSerializerContextvia additionalJsonSerializableattributes.
After adding tools or models, rebuild and restart the server so the MCP client can discover the new capabilities.