Building a Remote MCP Server with .NET: Resources, and VS Code Integration
Building a Remote MCP Server with .NET: Resources Integration
The Model Context Protocol (MCP) is quickly becoming the standard way to expose structured capabilities to AI clients. Instead of hardcoding ad-hoc integrations, you define clear interfaces for tools and resources, then let MCP clients discover and use them.
In this post, I walk through a practical .NET implementation of a remote MCP server that exposes:
- MCP tools for actions such as ping and weather lookup
- MCP resources for read-only server metadata and runtime status
- HTTP MCP endpoint at
/mcp - Health endpoint at
/api/healthz
This project is implemented with ASP.NET Core and ModelContextProtocol.AspNetCore.
Source code for the project is available on GitHub:
Why this pattern matters
A remote MCP server gives you a reusable integration layer:
- AI clients can discover capabilities dynamically
- Your backend logic stays in strongly typed .NET code
- You can evolve tools and resources without changing client-side prompts
- You can test everything locally with simple PowerShell scripts
Project layout
The repository is organized like this:
src/McpServer/McpServer: MCP host appsrc/McpServer/WeatherService: weather lookup servicescripts: utility scripts to list and call MCP tools/resources.vscode/mcp.json: VS Code MCP server connection config
Prerequisites
Before running locally, make sure you have:
- Windows + PowerShell (
pwshor Windows PowerShell) - .NET SDK 10.0 (project targets
net10.0) - VS Code with MCP client support
- Internet access for weather calls (Open-Meteo)
Run the server locally
From the repository root:
dotnet restore .\src\McpServer\McpServer.slnx
dotnet run --project .\src\McpServer\McpServer\McpServer.csproj
By default, the server runs at:
http://0.0.0.0:8081/mcp
Additional notes:
- Port comes from
FUNCTIONS_CUSTOMHANDLER_PORTand defaults to8081 - Health check endpoint is
http://localhost:8081/api/healthz
Connect VS Code to the MCP server
Use this .vscode/mcp.json configuration:
{
"servers": {
"local-mcp-server": {
"url": "http://0.0.0.0:8081/mcp",
"type": "http"
}
}
}
After starting the server, use MCP commands in VS Code to connect and inspect discovered capabilities.
MCP tools exposed by this server
Tools are defined in McpServerTools.cs:
Ping(message: string)- Verifies server responsiveness and optionally echoes a message
GetWeather(city: string)- Retrieves current weather for a city
In many MCP clients, tool names may be normalized (for example lowercase with underscores). It is best to list tools first and then call by discovered name.
MCP resources exposed by this server
Resources are defined in McpServerResources.cs:
ServerInfo- Returns server metadata: name, version, environment, host details, runtime framework, and OS
Status- Returns runtime health-like information: timestamp, uptime, memory, and CPU usage snapshot
These are read-only capabilities meant for retrieval via resources/read.
How to create your own MCP resource
Creating a resource in this project follows a simple pattern:
- Add the method in a class marked with
[McpServerResourceType] - Annotate the method with
[McpServerResource] - Add
[Description("...")]for client-friendly metadata - Return serializable output (string or JSON payload)
- Ensure resources are registered in startup (
.WithResources<McpServerResources>())
Example:
[McpServerResource]
[Description("Returns current process metrics")]
public string ProcessMetrics()
{
var data = new
{
Timestamp = DateTimeOffset.UtcNow,
WorkingSet = Environment.WorkingSet,
Memory = GC.GetTotalMemory(false),
ProcessorCount = Environment.ProcessorCount
};
return JsonSerializer.Serialize(data, new JsonSerializerOptions { WriteIndented = true });
}
Local testing scripts
This repo includes practical PowerShell scripts:
scripts/list-mcp-server-tools.ps1- Calls
tools/list
- Calls
scripts/list-mcp-server-resources.ps1- Calls
resources/list
- Calls
scripts/call-mcp-tool.ps1- Calls
tools/call
- Calls
scripts/call-mcp-resources.ps1- Calls
resources/read
- Calls
Quick test commands
If your machine blocks unsigned scripts, use a process-scoped bypass first:
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass -Force
Then run:
.\scripts\list-mcp-server-tools.ps1
.\scripts\list-mcp-server-resources.ps1
.\scripts\call-mcp-tool.ps1 -toolName 'ping' -toolParams @{ message = 'hello from local test' }
.\scripts\call-mcp-tool.ps1 -toolName 'get_weather' -toolParams @{ city = 'Paris' }
.\scripts\call-mcp-resources.ps1 -ResourceUri 'resource://mcp/server_info'
.\scripts\call-mcp-resources.ps1 -ResourceUri 'resource://mcp/status'
Final thoughts
This setup gives you a clean, production-friendly starting point for MCP in .NET:
- clear tool contracts for actions
- clear resource contracts for read-only context
- local scripts for fast iteration
- straightforward VS Code integration
From here, you can add authentication, richer domain resources, and additional tools while keeping your MCP surface organized and discoverable.

