Skip to content

Commit 39b0ed3

Browse files
mikekistlerCopilot
andauthored
Add conceptual docs on accessing HttpContext (#771)
* Add doc with sample on accessing HttpContext * Apply suggestions from PR review Co-authored-by: Copilot <[email protected]>
1 parent ab6d3e1 commit 39b0ed3

File tree

17 files changed

+288
-2
lines changed

17 files changed

+288
-2
lines changed

ModelContextProtocol.slnx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@
1818
<Folder Name="/docs/concepts/elicitation/samples/server/">
1919
<Project Path="docs/concepts/elicitation/samples/server/Elicitation.csproj" />
2020
</Folder>
21+
<Folder Name="/docs/concepts/httpcontext/" />
22+
<Folder Name="/docs/concepts/httpcontext/samples/">
23+
<Project Path="docs/concepts/httpcontext/samples/HttpContext.csproj" />
24+
</Folder>
2125
<Folder Name="/docs/concepts/logging/" />
2226
<Folder Name="/docs/concepts/logging/samples/" />
2327
<Folder Name="/docs/concepts/logging/samples/client/">

docs/concepts/elicitation/samples/client/ElicitationClient.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
<TargetFramework>net9.0</TargetFramework>
66
<ImplicitUsings>enable</ImplicitUsings>
77
<Nullable>enable</Nullable>
8+
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
9+
<GenerateTargetFrameworkAttribute>false</GenerateTargetFrameworkAttribute>
810
</PropertyGroup>
911

1012
<ItemGroup>

docs/concepts/elicitation/samples/server/Elicitation.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
<TargetFramework>net9.0</TargetFramework>
55
<Nullable>enable</Nullable>
66
<ImplicitUsings>enable</ImplicitUsings>
7+
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
8+
<GenerateTargetFrameworkAttribute>false</GenerateTargetFrameworkAttribute>
79
</PropertyGroup>
810

911
<ItemGroup>
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
---
2+
title: HTTP Context
3+
author: mikekistler
4+
description: How to access the HttpContext in the MCP C# SDK.
5+
uid: httpcontext
6+
---
7+
8+
## HTTP Context
9+
10+
When using the Streamable HTTP transport, an MCP server may need to access the underlying [HttpContext] for a request.
11+
The [HttpContext] contains request metadata such as the HTTP headers, authorization context, and the actual path and query string for the request.
12+
13+
To access the [HttpContext], the MCP server should add the [IHttpContextAccessor] service to the application service collection (typically in Program.cs).
14+
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.
15+
Methods then use the [HttpContext property][IHttpContextAccessor.HttpContext] of the accessor to get the current context.
16+
17+
[HttpContext]: https://learn.microsoft.com/dotnet/api/microsoft.aspnetcore.http.httpcontext
18+
[IHttpContextAccessor]: https://learn.microsoft.com/dotnet/api/microsoft.aspnetcore.http.ihttpcontextaccessor
19+
[IHttpContextAccessor.HttpContext]: https://learn.microsoft.com/dotnet/api/microsoft.aspnetcore.http.ihttpcontextaccessor.httpcontext
20+
21+
The following code snippet illustrates how to add the [IHttpContextAccessor] service to the application service collection:
22+
23+
[!code-csharp[](samples/Program.cs?name=snippet_AddHttpContextAccessor)]
24+
25+
Any class that needs access to the [HttpContext] can accept an [IHttpContextAccessor] in its constructor and store it for later use.
26+
Methods of the class can then access the current [HttpContext] using the stored accessor.
27+
28+
The following code snippet shows the `ContextTools` class accepting an [IHttpContextAccessor] in its primary constructor
29+
and the `GetHttpHeaders` method accessing the current [HttpContext] to retrieve the HTTP headers from the current request.
30+
31+
[!code-csharp[](samples/Tools/ContextTools.cs?name=snippet_AccessHttpContext)]
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<Project Sdk="Microsoft.NET.Sdk.Web">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net9.0</TargetFramework>
5+
<Nullable>enable</Nullable>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
</PropertyGroup>
8+
9+
<PropertyGroup>
10+
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
11+
<GenerateTargetFrameworkAttribute>false</GenerateTargetFrameworkAttribute>
12+
</PropertyGroup>
13+
14+
<ItemGroup>
15+
<ProjectReference Include="../../../../src/ModelContextProtocol.AspNetCore/ModelContextProtocol.AspNetCore.csproj" />
16+
</ItemGroup>
17+
18+
</Project>
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
@HostAddress = http://localhost:3001
2+
3+
POST {{HostAddress}}/
4+
Accept: application/json, text/event-stream
5+
Content-Type: application/json
6+
MCP-Protocol-Version: 2025-06-18
7+
8+
{
9+
"jsonrpc": "2.0",
10+
"id": 2,
11+
"method": "tools/call",
12+
"params": {
13+
"name": "get_http_headers"
14+
}
15+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using HttpContext.Tools;
2+
3+
var builder = WebApplication.CreateBuilder(args);
4+
5+
// Add services to the container.
6+
7+
builder.Services.AddMcpServer()
8+
.WithHttpTransport()
9+
.WithTools<ContextTools>();
10+
11+
// <snippet_AddHttpContextAccessor>
12+
builder.Services.AddHttpContextAccessor();
13+
// </snippet_AddHttpContextAccessor>
14+
15+
builder.Logging.AddConsole(options =>
16+
{
17+
options.LogToStandardErrorThreshold = LogLevel.Information;
18+
});
19+
20+
var app = builder.Build();
21+
22+
app.UseHttpsRedirection();
23+
24+
app.MapMcp();
25+
26+
app.Run();
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"$schema": "https://json.schemastore.org/launchsettings.json",
3+
"profiles": {
4+
"http": {
5+
"commandName": "Project",
6+
"dotnetRunMessages": true,
7+
"launchBrowser": false,
8+
"applicationUrl": "http://localhost:3001",
9+
"environmentVariables": {
10+
"ASPNETCORE_ENVIRONMENT": "Development"
11+
}
12+
},
13+
"https": {
14+
"commandName": "Project",
15+
"dotnetRunMessages": true,
16+
"launchBrowser": false,
17+
"applicationUrl": "https://localhost:7191;http://localhost:3001",
18+
"environmentVariables": {
19+
"ASPNETCORE_ENVIRONMENT": "Development"
20+
}
21+
}
22+
}
23+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using ModelContextProtocol.Server;
2+
using System.ComponentModel;
3+
4+
namespace HttpContext.Tools;
5+
6+
// <snippet_AccessHttpContext>
7+
public class ContextTools(IHttpContextAccessor httpContextAccessor)
8+
{
9+
[McpServerTool(UseStructuredContent = true)]
10+
[Description("Retrieves the HTTP headers from the current request and returns them as a JSON object.")]
11+
public object GetHttpHeaders()
12+
{
13+
var context = httpContextAccessor.HttpContext;
14+
if (context == null)
15+
{
16+
return "No HTTP context available";
17+
}
18+
19+
var headers = new Dictionary<string, string>();
20+
foreach (var header in context.Request.Headers)
21+
{
22+
headers[header.Key] = string.Join(", ", header.Value.ToArray());
23+
}
24+
25+
return headers;
26+
}
27+
// </snippet_AccessHttpContext>
28+
}
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"id": "37868ee2",
6+
"metadata": {
7+
"language_info": {
8+
"name": "polyglot-notebook"
9+
},
10+
"polyglot_notebook": {
11+
"kernelName": "csharp"
12+
}
13+
},
14+
"source": [
15+
"## HTTP Context\n",
16+
"\n",
17+
"This project illustrates how to access the HttpContext from tool calls. See the [README](../README.md) for more details.\n"
18+
]
19+
},
20+
{
21+
"cell_type": "markdown",
22+
"id": "093a7d4f",
23+
"metadata": {},
24+
"source": [
25+
"### Examples\n",
26+
"\n",
27+
"The following request illustrates a tool call that retrieves the HTTP headers from the [HttpContext] using the [IHttpContextAccessor].\n",
28+
"\n",
29+
"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",
30+
"which illustrate how to access other parts of the [HttpContext].\n",
31+
"\n",
32+
"\n",
33+
"[HttpContext]: https://docs.microsoft.com/dotnet/api/microsoft.aspnetcore.http.httpcontext\n",
34+
"[IHttpContextAccessor]: https://docs.microsoft.com/dotnet/api/microsoft.aspnetcore.http.ihttpcontextaccessor"
35+
]
36+
},
37+
{
38+
"cell_type": "code",
39+
"execution_count": 4,
40+
"id": "3324ec56",
41+
"metadata": {
42+
"language_info": {
43+
"name": "polyglot-notebook"
44+
},
45+
"polyglot_notebook": {
46+
"kernelName": "pwsh"
47+
}
48+
},
49+
"outputs": [
50+
{
51+
"name": "stdout",
52+
"output_type": "stream",
53+
"text": [
54+
"{\n",
55+
" \"result\": {\n",
56+
" \"content\": [\n",
57+
" {\n",
58+
" \"type\": \"text\",\n",
59+
" \"text\": \"[]\"\n",
60+
" }\n",
61+
" ],\n",
62+
" \"structuredContent\": {\n",
63+
" \"result\": []\n",
64+
" }\n",
65+
" },\n",
66+
" \"id\": 1,\n",
67+
" \"jsonrpc\": \"2.0\"\n",
68+
"}\n"
69+
]
70+
}
71+
],
72+
"source": [
73+
"curl -s -X POST http://localhost:3001 `\n",
74+
"-H \"ProtocolVersion: 2025-06-18\" `\n",
75+
"-H \"Accept: application/json, text/event-stream\" `\n",
76+
"-H \"Content-Type: application/json\" `\n",
77+
"-d '{\n",
78+
" \"jsonrpc\": \"2.0\",\n",
79+
" \"id\": 1,\n",
80+
" \"method\": \"tools/call\",\n",
81+
" \"params\": {\n",
82+
" \"name\": \"get_user_claims\"\n",
83+
" }\n",
84+
"}' | Where-Object { $_ -like \"data:*\" } | ForEach-Object { $_.Substring(5) } | jq"
85+
]
86+
}
87+
],
88+
"metadata": {
89+
"kernelspec": {
90+
"display_name": ".NET (C#)",
91+
"language": "C#",
92+
"name": ".net-csharp"
93+
},
94+
"language_info": {
95+
"name": "polyglot-notebook"
96+
},
97+
"polyglot_notebook": {
98+
"kernelInfo": {
99+
"defaultKernelName": "csharp",
100+
"items": [
101+
{
102+
"aliases": [],
103+
"languageName": "csharp",
104+
"name": "csharp"
105+
}
106+
]
107+
}
108+
}
109+
},
110+
"nbformat": 4,
111+
"nbformat_minor": 5
112+
}

0 commit comments

Comments
 (0)