Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions ModelContextProtocol.slnx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
<Folder Name="/docs/concepts/elicitation/samples/server/">
<Project Path="docs/concepts/elicitation/samples/server/Elicitation.csproj" />
</Folder>
<Folder Name="/docs/concepts/httpcontext/" />
<Folder Name="/docs/concepts/httpcontext/samples/">
<Project Path="docs/concepts/httpcontext/samples/HttpContext.csproj" />
</Folder>
<Folder Name="/docs/concepts/logging/" />
<Folder Name="/docs/concepts/logging/samples/" />
<Folder Name="/docs/concepts/logging/samples/client/">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<GenerateTargetFrameworkAttribute>false</GenerateTargetFrameworkAttribute>
</PropertyGroup>

<ItemGroup>
Expand Down
2 changes: 2 additions & 0 deletions docs/concepts/elicitation/samples/server/Elicitation.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<GenerateTargetFrameworkAttribute>false</GenerateTargetFrameworkAttribute>
</PropertyGroup>

<ItemGroup>
Expand Down
31 changes: 31 additions & 0 deletions docs/concepts/httpcontext/httpcontext.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
---
title: HTTP Context
author: mikekistler
description: How to access the HttpContext in the MCP C# SDK.
uid: httpcontext
---

## HTTP Context

When using the Streamable HTTP transport, an MCP server may need to access the underlying [HttpContext] for a request.
The [HttpContext] contains request metadata such as the HTTP headers, authorization context, and the actual path and query string for the request.

To access the [HttpContext], the MCP server should add the [IHttpContextAccessor] service to the application service collection (typically in Program.cs).
Then any classes, e.g. a class containing MCP tools, should accept an [IHttpContextAccessor] in their constructor and store this for use by its methods.
Methods then use the [HttpContext property][IHttpContextAccessor.HttpContext] of the accessor to get the current context.

[HttpContext]: https://learn.microsoft.com/dotnet/api/microsoft.aspnetcore.http.httpcontext
[IHttpContextAccessor]: https://learn.microsoft.com/dotnet/api/microsoft.aspnetcore.http.ihttpcontextaccessor
[IHttpContextAccessor.HttpContext]: https://learn.microsoft.com/dotnet/api/microsoft.aspnetcore.http.ihttpcontextaccessor.httpcontext

The following code snippet illustrates how to add the [IHttpContextAccessor] service to the application service collection:

[!code-csharp[](samples/Program.cs?name=snippet_AddHttpContextAccessor)]

Any class that needs access to the [HttpContext] can accept an [IHttpContextAccessor] in its constructor and store it for later use.
Methods of the class can then access the current [HttpContext] using the stored accessor.

The following code snippet shows the `ContextTools` class accepting an [IHttpContextAccessor] in its primary constructor
and the `GetHttpHeaders` method accessing the current [HttpContext] to retrieve the HTTP headers from the current request.

[!code-csharp[](samples/Tools/ContextTools.cs?name=snippet_AccessHttpContext)]
18 changes: 18 additions & 0 deletions docs/concepts/httpcontext/samples/HttpContext.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

<PropertyGroup>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<GenerateTargetFrameworkAttribute>false</GenerateTargetFrameworkAttribute>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="../../../../src/ModelContextProtocol.AspNetCore/ModelContextProtocol.AspNetCore.csproj" />
</ItemGroup>

</Project>
15 changes: 15 additions & 0 deletions docs/concepts/httpcontext/samples/HttpContext.http
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
@HostAddress = http://localhost:3001

POST {{HostAddress}}/
Accept: application/json, text/event-stream
Content-Type: application/json
MCP-Protocol-Version: 2025-06-18

{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "get_http_headers"
}
}
26 changes: 26 additions & 0 deletions docs/concepts/httpcontext/samples/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using HttpContext.Tools;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddMcpServer()
.WithHttpTransport()
.WithTools<ContextTools>();

// <snippet_AddHttpContextAccessor>
builder.Services.AddHttpContextAccessor();
// </snippet_AddHttpContextAccessor>

builder.Logging.AddConsole(options =>
{
options.LogToStandardErrorThreshold = LogLevel.Information;
});

var app = builder.Build();

app.UseHttpsRedirection();

app.MapMcp();

app.Run();
23 changes: 23 additions & 0 deletions docs/concepts/httpcontext/samples/Properties/launchSettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"$schema": "https://json.schemastore.org/launchsettings.json",
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": false,
"applicationUrl": "http://localhost:3001",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": false,
"applicationUrl": "https://localhost:7191;http://localhost:3001",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
33 changes: 33 additions & 0 deletions docs/concepts/httpcontext/samples/Tools/ContextTools.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using Microsoft.AspNetCore.Http;
using ModelContextProtocol.Server;
using System.ComponentModel;
using System.Text.Json;

namespace HttpContext.Tools;


// <snippet_AccessHttpContext>
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";
}

// Remainder of GetHttpHeaders method follows
// </snippet_AccessHttpContext>

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

return headers;
}
}
112 changes: 112 additions & 0 deletions docs/concepts/httpcontext/samples/TryItOut.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "37868ee2",
"metadata": {
"language_info": {
"name": "polyglot-notebook"
},
"polyglot_notebook": {
"kernelName": "csharp"
}
},
"source": [
"## HTTP Context\n",
"\n",
"This project illustrates how to access the HttpContext from tool calls. See the [README](../README.md) for more details.\n"
]
},
{
"cell_type": "markdown",
"id": "093a7d4f",
"metadata": {},
"source": [
"### Examples\n",
"\n",
"The following request illustrates a tool call that retrieves the HTTP headers from the [HttpContext] using the [IHttpContextAccessor].\n",
"\n",
"The server implements two other tools, `get_request_info` and `get_user_claims`. You can modify the code below to call these tools as well,\n",
"which illustrate how to access other parts of the [HttpContext].\n",
"\n",
"\n",
"[HttpContext]: https://docs.microsoft.com/dotnet/api/microsoft.aspnetcore.http.httpcontext\n",
"[IHttpContextAccessor]: https://docs.microsoft.com/dotnet/api/microsoft.aspnetcore.http.ihttpcontextaccessor"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "3324ec56",
"metadata": {
"language_info": {
"name": "polyglot-notebook"
},
"polyglot_notebook": {
"kernelName": "pwsh"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{\n",
" \"result\": {\n",
" \"content\": [\n",
" {\n",
" \"type\": \"text\",\n",
" \"text\": \"[]\"\n",
" }\n",
" ],\n",
" \"structuredContent\": {\n",
" \"result\": []\n",
" }\n",
" },\n",
" \"id\": 1,\n",
" \"jsonrpc\": \"2.0\"\n",
"}\n"
]
}
],
"source": [
"curl -s -X POST http://localhost:3001 `\n",
"-H \"ProtocolVersion: 2025-06-18\" `\n",
"-H \"Accept: application/json, text/event-stream\" `\n",
"-H \"Content-Type: application/json\" `\n",
"-d '{\n",
" \"jsonrpc\": \"2.0\",\n",
" \"id\": 1,\n",
" \"method\": \"tools/call\",\n",
" \"params\": {\n",
" \"name\": \"get_user_claims\"\n",
" }\n",
"}' | Where-Object { $_ -like \"data:*\" } | ForEach-Object { $_.Substring(5) } | jq"
]
}
],
"metadata": {
"kernelspec": {
"display_name": ".NET (C#)",
"language": "C#",
"name": ".net-csharp"
},
"language_info": {
"name": "polyglot-notebook"
},
"polyglot_notebook": {
"kernelInfo": {
"defaultKernelName": "csharp",
"items": [
{
"aliases": [],
"languageName": "csharp",
"name": "csharp"
}
]
}
}
},
"nbformat": 4,
"nbformat_minor": 5
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}
9 changes: 9 additions & 0 deletions docs/concepts/httpcontext/samples/appsettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}
2 changes: 2 additions & 0 deletions docs/concepts/logging/samples/client/LoggingClient.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<GenerateTargetFrameworkAttribute>false</GenerateTargetFrameworkAttribute>
</PropertyGroup>

<ItemGroup>
Expand Down
2 changes: 2 additions & 0 deletions docs/concepts/logging/samples/server/Logging.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<GenerateTargetFrameworkAttribute>false</GenerateTargetFrameworkAttribute>
</PropertyGroup>

<ItemGroup>
Expand Down
2 changes: 2 additions & 0 deletions docs/concepts/progress/samples/client/ProgressClient.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<GenerateTargetFrameworkAttribute>false</GenerateTargetFrameworkAttribute>
</PropertyGroup>

<ItemGroup>
Expand Down
2 changes: 2 additions & 0 deletions docs/concepts/progress/samples/server/Progress.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<GenerateTargetFrameworkAttribute>false</GenerateTargetFrameworkAttribute>
</PropertyGroup>

<ItemGroup>
Expand Down
4 changes: 2 additions & 2 deletions docs/concepts/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ items:
items:
- name: Logging
uid: logging
- name: Server Features
items:
- name: HTTP Context
uid: httpcontext
- name: Filters
uid: filters
Loading