How to Access Custom HTTP Headers in Your C# MCP Server



This content originally appeared on DEV Community and was authored by Riccardo Gregori

If you ever tried to configure an HTTP/SSE based MCP Server in Claude Desktop or Visual Studio Code you’ve probably stumbled upon the possibility to provide custom HTTP headers to your requests.

VS Code

Custom HTTP Headers in MCP configuration - Visual Studio Code

Claude Desktop

Custom HTTP Headers in MCP configuration - Claude Desktop

This can be particularly useful to manage authentication or configuration scenarios, or to provide static context to your tool execution.

🤔 But… how can I read those headers in my MCP Server?

If you, like me, are trying to create an MCP Server via Model Context Protocol C# SDK the process of getting those headers in your commands may be a little tricky, because the SDK natively doesn’t binds custom headers to tool arguments (or, at least, I didn’t found any docs or samples or managed to make it work properly).

But… there’s a way, leveraging a native ASP.Net Core feature.

IHttpContextAccessor is an interface provided by Microsoft.AspNetCore.Http assembly, that is part of the core ASP.NET engine. It allows you to access the current HttpContext instance from anywhere in your application.

🏗 Step 1. Add HttpContextAccessor to your service bindings

You can simply declare in your service bindings (Program.cs) that you want to leverage this feature:

var builder = WebApplication.CreateBuilder(args);

// ...more init logic here...

// Register HttpContextAccessor to enable access to HttpContext in tools
builder.Services.AddHttpContextAccessor();

// ...more init logic here...

// Initialize the MCP Server configuration
builder.Services.AddMcpServer()
.WithHttpTransport()
.WithToolsFromAssembly();

🚀 Step 2. Use IHttpContextAccessor in your tools

Once declared, you can inject an IHttpContextAccessor instance in your tool implementation, and use it to get all the details of the incoming request, HTTP headers included.

[McpServerToolType]
public sealed class EchoTool(IHttpContextAccessor httpContextAccessor)
{
    [McpServerTool, Description("Echoes back the input string.")]
    public async Task<string> Echo(IMcpServer server, string input)
    {
        var context = httpContextAccessor.HttpContext;
        if (!context?.Request.Headers.TryGetValue("x-my-custom-header", out var headerValue)) {
             // ...throw an exception or handle the missing header
        }

        //...actual command implementation
    }
}

🎯 How will I use it?

At the moment, the MCP Server I’ve built — FormEngineer — runs over STDIO. While this works, I see several reasons why SSE (and ideally remote SSE) is a better approach:

  • 🪲 Debugging: It’s easier to run and debug a remote MCP server than a local one
  • 🔌 Persistent connection: No need to spin up a new process for each client interaction.
  • 🌐 Remote accessibility: Makes it easier to expose the server outside the local machine.
  • ⚡ Scalability: Multiple clients can connect and interact without tight coupling to the process lifecycle.
  • 🗂 Remote session management: Enables more advanced scenarios like maintaining state or preferences across multiple requests from the same client.

In a remote setup, I asked myself how to pass the Dataverse environment target from the client to the server.
With the STDIO approach, the client simply launches the MCP Server executable with the environment arguments attached — and that’s it.

But in a remote SSE context, the server is expected to be always running. This means the target environment (or any similar contextual information) must be passed with each request.
That’s exactly where the problem arose — and where the solution described above comes in.


This content originally appeared on DEV Community and was authored by Riccardo Gregori