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/">
|
||||
<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/">
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@
|
|||
<TargetFramework>net9.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<GenerateTargetFrameworkAttribute>false</GenerateTargetFrameworkAttribute>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@
|
|||
<TargetFramework>net9.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<GenerateTargetFrameworkAttribute>false</GenerateTargetFrameworkAttribute>
|
||||
</PropertyGroup>
|
||||
|
||||
<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>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<GenerateTargetFrameworkAttribute>false</GenerateTargetFrameworkAttribute>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@
|
|||
<TargetFramework>net9.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<GenerateTargetFrameworkAttribute>false</GenerateTargetFrameworkAttribute>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@
|
|||
<TargetFramework>net9.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<GenerateTargetFrameworkAttribute>false</GenerateTargetFrameworkAttribute>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@
|
|||
<TargetFramework>net9.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<GenerateTargetFrameworkAttribute>false</GenerateTargetFrameworkAttribute>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ items:
|
|||
items:
|
||||
- name: Logging
|
||||
uid: logging
|
||||
- name: Server Features
|
||||
items:
|
||||
- name: HTTP Context
|
||||
uid: httpcontext
|
||||
- name: Filters
|
||||
uid: filters
|
||||
Loading…
Reference in a new issue