Skip to main content

Building our first MCP Resources enabled MCP Server with C#

In our first post, we explored what MCP resources are and why they matter. In a second post, we learned how to use resources in VS Code. A third post followed where I showed the same in Visual Studio. Now it's time to build—let's create our own MCP resource server from scratch using C# and the official .NET SDK.

By the end of this post, you'll have a working MCP server that exposes both static and dynamic resources,

Setting up our project

Let's start by creating a new console application and adding the necessary packages.

Step 1: Create the Project

Open your terminal and run:

dotnet new console -n ProjectDocsServer
cd ProjectDocsServer

Step 2: Add Required Packages

We need two NuGet packages:

# Add the MCP SDK (currently in preview)
dotnet add package ModelContextProtocol --prerelease

# Add hosting support for dependency injection
dotnet add package Microsoft.Extensions.Hosting

The ModelContextProtocol package provides the core MCP server functionality, while Microsoft.Extensions.Hosting enables dependency injection and hosting capabilities.

Step 3: Basic Server Setup

Update your Program.cs with the following code:

Services.AddMcpServer() registers the MCP server services with the application, WithStdioServerTransport() configures standard input/output transport for communication, and WithResourcesFromAssembly() automatically discovers and registers resources from the current assembly.

Understanding MCP Resources in C#

Before we write any extra code, let's understand how resources work in the C# SDK.

Resource Types

Resources in MCP allow servers to expose data that provides context to language models, such as files, database schemas, or application-specific information. In C#, you define resources using attributes:

  • [McpServerResourceType] - Marks a class that contains resource methods
  • [McpServerResource] - Marks a method as a resource provider
  • Description attribute - Provides human-readable descriptions

Direct vs Templated Resources

McpServerResource is used to represent both direct resources (like "resource://example") and templated resources (like "resource://example/{id}"):

  • Direct resources have fixed URIs and return the same content
  • Templated resources use URI templates with parameters for dynamic content

Creating our first MCP resource

Add a new file called ProjectResources.cs. In this file we configure 2 resources that can be fetched:

Key points:

  • The UriTemplate defines how clients reference this resource
  • Static methods work great for read-only data
  • Return types determine the content type (string = text content)

Now let's add dynamic resources that accept parameters. Add these methods to ProjectResources.cs:

URI templates with parameters allow resources to be dynamic and flexible, with the SDK automatically handling parameter extraction from the URI.

Testing our MCP Server

The easiest way to test our MCP server is through the MCP inspector. The MCP Inspector is a debugging tool that allows you to test your server's resources and tools interactively:

# Install the MCP Inspector
npm install -g @modelcontextprotocol/inspector

# Run your server with the inspector
npx @modelcontextprotocol/inspector dotnet run

This will open up your browser and load the MCP inspector.  Click on connect to start interacting with the server.

Let’s check if we can fetch a static resource.

  • Go to the resources tab and click on List resources:

  • Now you should get a list of available resources:

 

  • Click on a specific resource to get a response back:

And also try the resource templates we created:

  • On the resources tab and click on List templates.
  • Now you should get a list of available templates:

    • Click on a specific template and specify the required argument:

     

    • Now we can fetch the resource

     

    That is a good starting point…

    What’s next?

    In the next post, we look at some more advanced features and share some best practices.

    Keep you posted!

    Popular posts from this blog

    Azure DevOps/ GitHub emoji

    I’m really bad at remembering emoji’s. So here is cheat sheet with all emoji’s that can be used in tools that support the github emoji markdown markup: All credits go to rcaviers who created this list.

    .NET 8–Keyed/Named Services

    A feature that a lot of IoC container libraries support but that was missing in the default DI container provided by Microsoft is the support for Keyed or Named Services. This feature allows you to register the same type multiple times using different names, allowing you to resolve a specific instance based on the circumstances. Although there is some controversy if supporting this feature is a good idea or not, it certainly can be handy. To support this feature a new interface IKeyedServiceProvider got introduced in .NET 8 providing 2 new methods on our ServiceProvider instance: object? GetKeyedService(Type serviceType, object? serviceKey); object GetRequiredKeyedService(Type serviceType, object? serviceKey); To use it, we need to register our service using one of the new extension methods: Resolving the service can be done either through the FromKeyedServices attribute: or by injecting the IKeyedServiceProvider interface and calling the GetRequiredKeyedServic...

    Kubernetes–Limit your environmental impact

    Reducing the carbon footprint and CO2 emission of our (cloud) workloads, is a responsibility of all of us. If you are running a Kubernetes cluster, have a look at Kube-Green . kube-green is a simple Kubernetes operator that automatically shuts down (some of) your pods when you don't need them. A single pod produces about 11 Kg CO2eq per year( here the calculation). Reason enough to give it a try! Installing kube-green in your cluster The easiest way to install the operator in your cluster is through kubectl. We first need to install a cert-manager: kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.14.5/cert-manager.yaml Remark: Wait a minute before you continue as it can take some time before the cert-manager is up & running inside your cluster. Now we can install the kube-green operator: kubectl apply -f https://github.com/kube-green/kube-green/releases/latest/download/kube-green.yaml Now in the namespace where we want t...