Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
<!-- Testing dependencies -->
<ItemGroup>
<PackageVersion Include="Anthropic" Version="12.39.0" />
<PackageVersion Include="Azure.Monitor.OpenTelemetry.AspNetCore" Version="1.6.0" />
<PackageVersion Include="coverlet.collector" Version="10.0.1">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
Expand Down
1 change: 1 addition & 0 deletions samples/AspNetCoreMcpServer/AspNetCoreMcpServer.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Azure.Monitor.OpenTelemetry.AspNetCore" />
<PackageReference Include="OpenTelemetry" />
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" />
<PackageReference Include="OpenTelemetry.Extensions.Hosting" />
Expand Down
19 changes: 16 additions & 3 deletions samples/AspNetCoreMcpServer/Program.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using Azure.Monitor.OpenTelemetry.AspNetCore;
using OpenTelemetry;
using OpenTelemetry.Metrics;
using OpenTelemetry.Trace;
Expand Down Expand Up @@ -34,15 +35,27 @@
.WithTools<WeatherTools>()
.WithResources<SimpleResourceType>();

builder.Services.AddOpenTelemetry()
var telemetry = builder.Services.AddOpenTelemetry()
.WithTracing(b => b.AddSource("*")
.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation())
.WithMetrics(b => b.AddMeter("*")
.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation())
.WithLogging()
.UseOtlpExporter();
.WithLogging();

string? applicationInsightsConnectionString =
builder.Configuration["APPLICATIONINSIGHTS_CONNECTION_STRING"];

if (string.IsNullOrWhiteSpace(applicationInsightsConnectionString))
{
telemetry.UseOtlpExporter();
}
else
{
telemetry.UseAzureMonitor(options =>
options.ConnectionString = applicationInsightsConnectionString);
}

// Configure HttpClientFactory for weather.gov API
builder.Services.AddHttpClient("WeatherApi", client =>
Expand Down
48 changes: 48 additions & 0 deletions samples/AspNetCoreMcpServer/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# ASP.NET Core MCP server sample

This sample hosts an MCP server with Streamable HTTP and configures OpenTelemetry for MCP operations, ASP.NET Core requests, outgoing HTTP requests, metrics, and structured logs.

## Export to Application Insights

Set the Application Insights connection string and run the sample:

```bash
export APPLICATIONINSIGHTS_CONNECTION_STRING='InstrumentationKey=<your-instrumentation-key>;IngestionEndpoint=https://<region>.in.applicationinsights.azure.com/'
dotnet run --project samples/AspNetCoreMcpServer
```

PowerShell:

```powershell
$env:APPLICATIONINSIGHTS_CONNECTION_STRING = 'InstrumentationKey=<your-instrumentation-key>;IngestionEndpoint=https://<region>.in.applicationinsights.azure.com/'
dotnet run --project samples/AspNetCoreMcpServer
```

The connection string is read through ASP.NET Core configuration. Keep it outside source control and use your deployment platform's secret configuration in production.

When `APPLICATIONINSIGHTS_CONNECTION_STRING` is absent or empty, the sample retains its default OTLP exporter. Configure that path with standard `OTEL_EXPORTER_OTLP_*` environment variables.

## Signals and MCP attributes

Application Insights receives the signals already emitted by the SDK and the configured ASP.NET Core/OpenTelemetry instrumentation:

- server activities appear as requests and client activities appear as dependencies;
- structured logs appear as traces;
- MCP histograms appear as custom metrics;
- HTTP server and client instrumentation provides the surrounding transport spans.

MCP activities can include attributes such as `mcp.method.name`, `mcp.protocol.version`, `mcp.session.id`, `jsonrpc.request.id`, and `gen_ai.tool.name`. The exact attributes depend on the operation and whether sensitive-data telemetry is enabled.

For example, query MCP request and dependency telemetry in Logs:

```kusto
union withsource=TelemetryType requests, dependencies
| extend McpMethod = tostring(customDimensions["mcp.method.name"]),
ToolName = tostring(customDimensions["gen_ai.tool.name"]),
McpSession = tostring(customDimensions["mcp.session.id"])
| where isnotempty(McpMethod)
| project timestamp, TelemetryType, name, success, resultCode, McpMethod, ToolName, McpSession
| order by timestamp desc
```

Invalid tool calls, malformed JSON-RPC messages, and other failures appear only when the current SDK or ASP.NET Core instrumentation emits a log or activity for that path. This sample exports existing telemetry; it does not add custom protocol events or per-tool instrumentation.