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 providerDescriptionattribute - 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
UriTemplatedefines 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!
.png)





