Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/modelcontextprotocol/csharp-sdk/llms.txt

Use this file to discover all available pages before exploring further.

When using the Streamable HTTP transport, MCP servers often need access to the underlying HTTP request context. The HttpContext provides request metadata including headers, user identity, route data, and more.

Basic Setup

To access HttpContext in your MCP server tools or handlers:
1

Register IHttpContextAccessor

Add the IHttpContextAccessor service to your application (typically in Program.cs):
~/workspace/source/docs/concepts/httpcontext/samples/Program.cs
builder.Services.AddHttpContextAccessor();
2

Inject in your tool class

Accept IHttpContextAccessor in your tool class constructor:
[McpServerToolType]
public class MyTools(IHttpContextAccessor httpContextAccessor)
{
    private readonly IHttpContextAccessor _httpContextAccessor = httpContextAccessor;
}
3

Access the current context

Use the HttpContext property to get the current request context:
var context = _httpContextAccessor.HttpContext;
if (context != null)
{
    // Access request information
}

Complete Example

Here’s a complete example that retrieves HTTP headers from the current request:
~/workspace/source/docs/concepts/httpcontext/samples/Tools/ContextTools.cs
using ModelContextProtocol.Server;
using System.ComponentModel;

namespace HttpContext.Tools;

public class ContextTools(IHttpContextAccessor httpContextAccessor)
{
    [McpServerTool(UseStructuredContent = true)]
    [Description("Retrieves the HTTP headers from the current request and returns them as a JSON object.")]
    public object GetHttpHeaders()
    {
        var context = httpContextAccessor.HttpContext;
        if (context == null)
        {
            return "No HTTP context available";
        }

        var headers = new Dictionary<string, string>();
        foreach (var header in context.Request.Headers)
        {
            headers[header.Key] = string.Join(", ", header.Value.ToArray());
        }

        return headers;
    }
}

Common Use Cases

Accessing Request Headers

Retrieve specific headers from the current request:
[McpServerTool]
[Description("Gets the user agent from the request")]
public string GetUserAgent(IHttpContextAccessor httpContextAccessor)
{
    var context = httpContextAccessor.HttpContext;
    if (context == null) return "No context available";

    var userAgent = context.Request.Headers["User-Agent"].FirstOrDefault();
    return userAgent ?? "No User-Agent header found";
}

Accessing User Identity

Retrieve authenticated user information:
[McpServerToolType]
public class UserTools(IHttpContextAccessor httpContextAccessor)
{
    [McpServerTool]
    [Description("Gets the current authenticated user name")]
    public string GetCurrentUser()
    {
        var context = httpContextAccessor.HttpContext;
        if (context?.User?.Identity?.IsAuthenticated == true)
        {
            return context.User.Identity.Name ?? "Unknown user";
        }
        return "Not authenticated";
    }

    [McpServerTool]
    [Description("Gets all user claims")]
    public Dictionary<string, string> GetUserClaims()
    {
        var context = httpContextAccessor.HttpContext;
        if (context?.User == null) return new();

        var claims = new Dictionary<string, string>();
        foreach (var claim in context.User.Claims)
        {
            claims[claim.Type] = claim.Value;
        }
        return claims;
    }
}

Accessing Request Path and Query

Retrieve URL information:
[McpServerTool]
[Description("Gets request path and query string information")]
public object GetRequestInfo(IHttpContextAccessor httpContextAccessor)
{
    var context = httpContextAccessor.HttpContext;
    if (context == null) return "No context available";

    return new
    {
        Path = context.Request.Path.Value,
        QueryString = context.Request.QueryString.Value,
        Method = context.Request.Method,
        Scheme = context.Request.Scheme,
        Host = context.Request.Host.Value
    };
}

Accessing Remote IP Address

Get the client’s IP address:
[McpServerTool]
[Description("Gets the client IP address")]
public string GetClientIp(IHttpContextAccessor httpContextAccessor)
{
    var context = httpContextAccessor.HttpContext;
    if (context == null) return "No context available";

    var remoteIp = context.Connection.RemoteIpAddress;
    return remoteIp?.ToString() ?? "Unknown";
}

Custom Response Headers

Add custom headers to the response:
[McpServerTool]
[Description("Performs an operation and sets custom response headers")]
public string ProcessWithCustomHeaders(IHttpContextAccessor httpContextAccessor)
{
    var context = httpContextAccessor.HttpContext;
    if (context != null)
    {
        context.Response.Headers.Add("X-Custom-Header", "CustomValue");
        context.Response.Headers.Add("X-Processing-Time", DateTime.UtcNow.ToString("o"));
    }

    return "Processing complete with custom headers";
}

Advanced Scenarios

Per-Request Services

Access services scoped to the current HTTP request:
[McpServerToolType]
public class AdvancedTools(IHttpContextAccessor httpContextAccessor)
{
    [McpServerTool]
    [Description("Uses request-scoped services")]
    public string UseRequestScopedService()
    {
        var context = httpContextAccessor.HttpContext;
        if (context == null) return "No context available";

        // Access request-scoped services
        var scopedService = context.RequestServices.GetService<IMyScopedService>();
        return scopedService?.DoWork() ?? "Service not available";
    }
}

Session Data

Access HTTP session data:
[McpServerTool]
[Description("Gets a value from session")]
public string GetSessionValue(string key, IHttpContextAccessor httpContextAccessor)
{
    var context = httpContextAccessor.HttpContext;
    if (context?.Session == null) return "Session not available";

    var value = context.Session.GetString(key);
    return value ?? $"No value found for key: {key}";
}

[McpServerTool]
[Description("Sets a value in session")]
public string SetSessionValue(string key, string value, IHttpContextAccessor httpContextAccessor)
{
    var context = httpContextAccessor.HttpContext;
    if (context?.Session == null) return "Session not available";

    context.Session.SetString(key, value);
    return $"Session value set: {key} = {value}";
}

Request Body Access

Accessing the request body through HttpContext in MCP tools is not recommended because the MCP framework already reads the body to deserialize the JSON-RPC request. Use tool parameters instead.

Best Practices

The HttpContext may be null in certain scenarios (testing, background tasks):
var context = httpContextAccessor.HttpContext;
if (context == null)
{
    return "No HTTP context available";
}
Inject IHttpContextAccessor via constructor rather than using static access:
// ✅ Good: Constructor injection
public class MyTools(IHttpContextAccessor httpContextAccessor)

// ❌ Bad: Static or service locator patterns
Don’t store HttpContext in fields or properties - always get it from the accessor when needed:
// ✅ Good: Get context when needed
var context = _httpContextAccessor.HttpContext;

// ❌ Bad: Store in field
private readonly HttpContext _context;
Code that relies on HttpContext won’t work with non-HTTP transports (stdio, SSE). Consider making HTTP-specific features optional:
var context = httpContextAccessor.HttpContext;
if (context != null)
{
    // HTTP-specific logic
}
else
{
    // Fallback for non-HTTP transports
}
IHttpContextAccessor uses AsyncLocal<T> internally to provide the current context. This is thread-safe and works correctly with async/await.

API Reference

Build docs developers (and LLMs) love