← MCP Servers
Claude Code MCP server Free

Notes Server in C# Free Claude Code MCP server, copy & paste

The notes server in C# with the official ModelContextProtocol package — attributes on static methods.

WHEN TO USE IT

When you live in .NET and want your tools as ordinary C# methods with dependency injection.

Lives in Registered with `claude mcp add`, or shared with the team in .mcp.json at the project root.
Checked

Formats change. If a field stops working, check it against Anthropic's documentation.

Read it before you install it. A MCP server runs with your user account's permissions, on its own, every time it is triggered. That is what makes it useful, and why a stranger's should never be installed unread — this one included.

Install

ModelContextProtocol brings hosting and DI. Microsoft.Extensions.Hosting is there because an MCP server is a host with a transport, not a bare console app.

dotnet new console -o NotesMcp
cd NotesMcp
dotnet add package ModelContextProtocol
dotnet add package Microsoft.Extensions.Hosting
Program.cs

[McpServerToolType] marks the class, [McpServerTool] each method, [Description] is what Claude reads. The logging line sends every log to stderr, because stdout is the protocol.

using System.ComponentModel;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using ModelContextProtocol.Server;

var builder = Host.CreateApplicationBuilder(args);

// stdout carries the protocol — send all logging to stderr.
builder.Logging.AddConsole(o => o.LogToStandardErrorThreshold = LogLevel.Trace);

builder.Services
    .AddMcpServer()
    .WithStdioServerTransport()
    .WithToolsFromAssembly();

await builder.Build().RunAsync();

[McpServerToolType]
public static class NotesTools
{
    private static readonly string Root =
        Environment.GetEnvironmentVariable("NOTES_DIR")
        ?? Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "notes");

    [McpServerTool, Description("Find notes containing the query (case-insensitive). Returns file:line: text.")]
    public static string SearchNotes(
        [Description("Text to look for")] string query,
        int limit = 10)
    {
        var hits = new List<string>();

        foreach (var file in Directory.EnumerateFiles(Root, "*.md", SearchOption.AllDirectories).Order())
        {
            var lines = File.ReadAllLines(file);
            for (var i = 0; i < lines.Length && hits.Count < limit; i++)
            {
                if (lines[i].Contains(query, StringComparison.OrdinalIgnoreCase))
                {
                    hits.Add($"{Path.GetRelativePath(Root, file)}:{i + 1}: {lines[i].Trim()}");
                }
            }
        }

        return hits.Count == 0 ? "No matches." : string.Join('\n', hits);
    }
}
Add it to Claude Code

Build once and point Claude Code at the output, rather than dotnet run — a server that compiles on every start is slow to connect.

dotnet build -c Release

claude mcp add --transport stdio --env NOTES_DIR=$HOME/notes notes \
  -- dotnet /absolute/path/to/NotesMcp/bin/Release/net10.0/NotesMcp.dll

claude mcp list

MORE MCP SERVERS

The authority

Anthropic's documentation for MCP Servers

This template is a starting point. Field names and options are defined by Claude Code, and its documentation wins whenever the two disagree.

Read the docs ↗

https://code.claude.com/docs/en/mcp

New drops, every week

Free tools & Claude templates, landing regularly.

We keep shipping new free tools, code recipes and Claude Code templates. Follow @freeyantra on Instagram or join the newsletter so you never miss one.

Follow @freeyantra

or get them by email

Double opt-in. Unsubscribe any time. Privacy