Add conceptual docs on accessing HttpContext (#771)
* Add doc with sample on accessing HttpContext * Apply suggestions from PR review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
parent
ab6d3e1ac5
commit
39b0ed3c18
17 changed files with 288 additions and 2 deletions
|
|
@ -18,6 +18,10 @@
|
||||||
<Folder Name="/docs/concepts/elicitation/samples/server/">
|
<Folder Name="/docs/concepts/elicitation/samples/server/">
|
||||||
<Project Path="docs/concepts/elicitation/samples/server/Elicitation.csproj" />
|
<Project Path="docs/concepts/elicitation/samples/server/Elicitation.csproj" />
|
||||||
</Folder>
|
</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/" />
|
||||||
<Folder Name="/docs/concepts/logging/samples/" />
|
<Folder Name="/docs/concepts/logging/samples/" />
|
||||||
<Folder Name="/docs/concepts/logging/samples/client/">
|
<Folder Name="/docs/concepts/logging/samples/client/">
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@
|
||||||
<TargetFramework>net9.0</TargetFramework>
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||||
|
<GenerateTargetFrameworkAttribute>false</GenerateTargetFrameworkAttribute>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@
|
||||||
<TargetFramework>net9.0</TargetFramework>
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||||
|
<GenerateTargetFrameworkAttribute>false</GenerateTargetFrameworkAttribute>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
||||||
31
docs/concepts/httpcontext/httpcontext.md
Normal file
31
docs/concepts/httpcontext/httpcontext.md
Normal file
|
|
@ -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
docs/concepts/httpcontext/samples/HttpContext.csproj
Normal file
18
docs/concepts/httpcontext/samples/HttpContext.csproj
Normal file
|
|
@ -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
docs/concepts/httpcontext/samples/HttpContext.http
Normal file
15
docs/concepts/httpcontext/samples/HttpContext.http
Normal file
|
|
@ -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
docs/concepts/httpcontext/samples/Program.cs
Normal file
26
docs/concepts/httpcontext/samples/Program.cs
Normal file
|
|
@ -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();
|
||||||
|
|
@ -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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
28
docs/concepts/httpcontext/samples/Tools/ContextTools.cs
Normal file
28
docs/concepts/httpcontext/samples/Tools/ContextTools.cs
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
using ModelContextProtocol.Server;
|
||||||
|
using System.ComponentModel;
|
||||||
|
|
||||||
|
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";
|
||||||
|
}
|
||||||
|
|
||||||
|
var headers = new Dictionary<string, string>();
|
||||||
|
foreach (var header in context.Request.Headers)
|
||||||
|
{
|
||||||
|
headers[header.Key] = string.Join(", ", header.Value.ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
return headers;
|
||||||
|
}
|
||||||
|
// </snippet_AccessHttpContext>
|
||||||
|
}
|
||||||
112
docs/concepts/httpcontext/samples/TryItOut.ipynb
Normal file
112
docs/concepts/httpcontext/samples/TryItOut.ipynb
Normal file
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.AspNetCore": "Warning"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
9
docs/concepts/httpcontext/samples/appsettings.json
Normal file
9
docs/concepts/httpcontext/samples/appsettings.json
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.AspNetCore": "Warning"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowedHosts": "*"
|
||||||
|
}
|
||||||
|
|
@ -5,6 +5,8 @@
|
||||||
<TargetFramework>net9.0</TargetFramework>
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||||
|
<GenerateTargetFrameworkAttribute>false</GenerateTargetFrameworkAttribute>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@
|
||||||
<TargetFramework>net9.0</TargetFramework>
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||||
|
<GenerateTargetFrameworkAttribute>false</GenerateTargetFrameworkAttribute>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@
|
||||||
<TargetFramework>net9.0</TargetFramework>
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||||
|
<GenerateTargetFrameworkAttribute>false</GenerateTargetFrameworkAttribute>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@
|
||||||
<TargetFramework>net9.0</TargetFramework>
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||||
|
<GenerateTargetFrameworkAttribute>false</GenerateTargetFrameworkAttribute>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ items:
|
||||||
items:
|
items:
|
||||||
- name: Logging
|
- name: Logging
|
||||||
uid: logging
|
uid: logging
|
||||||
- name: Server Features
|
- name: HTTP Context
|
||||||
items:
|
uid: httpcontext
|
||||||
- name: Filters
|
- name: Filters
|
||||||
uid: filters
|
uid: filters
|
||||||
Loading…
Reference in a new issue