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 app
  • src/McpServer/WeatherService: weather lookup service
  • scripts: 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 (pwsh or 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_PORT and defaults to 8081
  • 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:

  1. Add the method in a class marked with [McpServerResourceType]
  2. Annotate the method with [McpServerResource]
  3. Add [Description("...")] for client-friendly metadata
  4. Return serializable output (string or JSON payload)
  5. 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
  • scripts/list-mcp-server-resources.ps1
    • Calls resources/list
  • scripts/call-mcp-tool.ps1
    • Calls tools/call
  • scripts/call-mcp-resources.ps1
    • Calls resources/read

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.

Gora LEYE

I'm a microsoft most valuable professional (MVP) .NET Architect and Technical Expert skills located in Paris (FRANCE). The purpose of this blog is mainly to post general .NET tips and tricks, www.masterconduite.com Gora LEYE

Support us

BMC logoBuy me a coffee