Skip to content

Commit f74727d

Browse files
author
Liudmila Molkova
committed
update conventions and address feedback
1 parent aa786b8 commit f74727d

File tree

9 files changed

+247
-172
lines changed

9 files changed

+247
-172
lines changed

Directory.Packages.props

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@
5858
<PackageVersion Include="Moq" Version="4.20.72" />
5959
<PackageVersion Include="OpenTelemetry" Version="1.11.2" />
6060
<PackageVersion Include="OpenTelemetry.Exporter.InMemory" Version="1.11.2" />
61+
<PackageVersion Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.11.2" />
62+
<PackageVersion Include="OpenTelemetry.Instrumentation.Http " Version="1.11.0" />
63+
<PackageVersion Include="OpenTelemetry.Extensions.Hosting" Version="1.11.2" />
64+
<PackageVersion Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.11.1" />
6165
<PackageVersion Include="Serilog.Extensions.Hosting" Version="9.0.0" />
6266
<PackageVersion Include="Serilog.Extensions.Logging" Version="9.0.0" />
6367
<PackageVersion Include="Serilog.Sinks.Console" Version="6.0.0" />
@@ -66,10 +70,5 @@
6670
<PackageVersion Include="System.Linq.AsyncEnumerable" Version="$(System10Version)" />
6771
<PackageVersion Include="xunit.v3" Version="1.1.0" />
6872
<PackageVersion Include="xunit.runner.visualstudio" Version="3.0.2" />
69-
<PackageVersion Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.11.2" />
70-
<PackageVersion Include="OpenTelemetry.Instrumentation.Http " Version="1.11.0" />
71-
<PackageVersion Include="OpenTelemetry.Extensions.Hosting" Version="1.11.2" />
72-
<PackageVersion Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.11.1" />
73-
7473
</ItemGroup>
7574
</Project>

samples/AspNetCoreSseServer/Program.cs

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,22 @@
11
using TestServerWithHosting.Tools;
2-
using OpenTelemetry.Logs;
32
using OpenTelemetry.Metrics;
4-
using OpenTelemetry.Resources;
53
using OpenTelemetry.Trace;
6-
using AspNetCoreSseServer.Tools;
4+
using OpenTelemetry;
75

86
var builder = WebApplication.CreateBuilder(args);
97
builder.Services.AddMcpServer()
108
.WithTools<EchoTool>()
11-
.WithTools<SampleLlmTool>()
12-
.WithTools<LongRunningTool>();
9+
.WithTools<SampleLlmTool>();
1310

14-
var resource = ResourceBuilder.CreateEmpty().AddService("mcp.server");
1511
builder.Services.AddOpenTelemetry()
16-
.WithTracing(b => b.SetResourceBuilder(resource)
17-
.AddOtlpExporter()
18-
.AddSource("*")
12+
.WithTracing(b => b.AddSource("*")
1913
.AddAspNetCoreInstrumentation()
2014
.AddHttpClientInstrumentation())
21-
.WithMetrics(b => b.SetResourceBuilder(resource)
22-
.AddMeter("*")
23-
.AddOtlpExporter()
15+
.WithMetrics(b => b.AddMeter("*")
2416
.AddAspNetCoreInstrumentation()
2517
.AddHttpClientInstrumentation())
26-
.WithLogging(b => b.SetResourceBuilder(resource)
27-
.AddOtlpExporter());
18+
.WithLogging()
19+
.UseOtlpExporter();
2820

2921
var app = builder.Build();
3022

samples/AspNetCoreSseServer/Properties/launchSettings.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
"launchBrowser": true,
88
"applicationUrl": "http://localhost:3001",
99
"environmentVariables": {
10-
"ASPNETCORE_ENVIRONMENT": "Development"
10+
"ASPNETCORE_ENVIRONMENT": "Development",
11+
"OTEL_SERVICE_NAME": "sse-server",
1112
}
1213
},
1314
"https": {
@@ -16,7 +17,8 @@
1617
"launchBrowser": true,
1718
"applicationUrl": "https://localhost:7133;http://localhost:3001",
1819
"environmentVariables": {
19-
"ASPNETCORE_ENVIRONMENT": "Development"
20+
"ASPNETCORE_ENVIRONMENT": "Development",
21+
"OTEL_SERVICE_NAME": "sse-server",
2022
}
2123
}
2224
}

samples/ChatWithTools/Program.cs

Lines changed: 17 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,9 @@
55

66
using OpenTelemetry;
77
using OpenTelemetry.Trace;
8-
using System.Diagnostics;
98
using Microsoft.Extensions.Logging;
109
using OpenTelemetry.Logs;
1110
using OpenTelemetry.Metrics;
12-
using ModelContextProtocol.Protocol.Messages;
1311
using ModelContextProtocol.Protocol.Types;
1412

1513
using var tracerProvider = Sdk.CreateTracerProviderBuilder()
@@ -22,55 +20,38 @@
2220
.AddMeter("*")
2321
.AddOtlpExporter()
2422
.Build();
25-
26-
using var loggerFactory = LoggerFactory.Create(builder =>
27-
{
28-
builder.AddOpenTelemetry(opt =>
29-
{
30-
opt.IncludeFormattedMessage = true;
31-
opt.IncludeScopes = true;
32-
opt.AddOtlpExporter();
33-
});
34-
});
23+
using var loggerFactory = LoggerFactory.Create(builder => builder.AddOpenTelemetry(opt => opt.AddOtlpExporter()));
3524

3625
// Connect to an MCP server
37-
Console.WriteLine("Connecting client to MCP 'aspnetcore' server");
38-
26+
Console.WriteLine("Connecting client to MCP 'everything' server");
3927

40-
// Create an IChatClient. (This shows using OpenAIClient, but it could be any other IChatClient implementation.)
28+
// Create OpenAI client (or any other compatible with IChatClient)
4129
// Provide your own OPENAI_API_KEY via an environment variable.
42-
using IChatClient chatClient =
43-
new OpenAIClient(Environment.GetEnvironmentVariable("OPENAI_API_KEY")).AsChatClient("gpt-4o-mini")
30+
var openAIClient = new OpenAIClient(Environment.GetEnvironmentVariable("OPENAI_API_KEY"));
31+
32+
// Create a sampling client.
33+
using IChatClient samplingClient = openAIClient.AsChatClient("gpt-4o-mini")
4434
.AsBuilder()
45-
.UseFunctionInvocation()
4635
.UseOpenTelemetry(loggerFactory: loggerFactory, configure: o => o.EnableSensitiveData = true)
4736
.Build();
4837

49-
var samplingHandler = chatClient.CreateSamplingHandler();
50-
5138
var mcpClient = await McpClientFactory.CreateAsync(
5239
new()
5340
{
5441
Id = "everything",
55-
Name = "everything",
42+
Name = "Everything",
5643
TransportType = TransportTypes.StdIo,
57-
//TransportType = TransportTypes.Sse,
58-
//Location = "http://localhost:3001/sse",
5944
TransportOptions = new()
6045
{
61-
//["command"] = "npx", ["arguments"] = "-y @modelcontextprotocol/server-everything",
62-
["command"] = @"D:\repo\csharp-sdk\artifacts\bin\EverythingServer\net9.0\EverythingServer.exe"
46+
["command"] = "npx", ["arguments"] = "-y @modelcontextprotocol/server-everything",
6347
}
6448

6549
},
6650
clientOptions: new McpClientOptions()
6751
{
6852
Capabilities = new ClientCapabilities()
6953
{
70-
Sampling = new SamplingCapability() { SamplingHandler = (param, progress, ct) => {
71-
Console.WriteLine(param?.Meta?.ProgressToken);
72-
return samplingHandler(param, progress, ct);
73-
} }
54+
Sampling = new SamplingCapability() { SamplingHandler = samplingClient.CreateSamplingHandler() }
7455
},
7556
},
7657
loggerFactory: loggerFactory);
@@ -86,6 +67,13 @@
8667

8768
Console.WriteLine();
8869

70+
// Create an IChatClient that can use the tools.
71+
using IChatClient chatClient =
72+
openAIClient.AsChatClient("gpt-4o-mini")
73+
.AsBuilder()
74+
.UseFunctionInvocation()
75+
.UseOpenTelemetry(loggerFactory: loggerFactory, configure: o => o.EnableSensitiveData = true)
76+
.Build();
8977

9078
// Have a conversation, making all tools available to the LLM.
9179
List<ChatMessage> messages = [];

samples/EverythingServer/EverythingServer.csproj

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
<PackageReference Include="Microsoft.Extensions.Hosting" />
1212
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" />
1313
<PackageReference Include="OpenTelemetry.Extensions.Hosting" />
14-
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" />
1514
<PackageReference Include="OpenTelemetry.Instrumentation.Http" />
1615
</ItemGroup>
1716

samples/EverythingServer/Program.cs

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using ModelContextProtocol;
99
using ModelContextProtocol.Protocol.Types;
1010
using ModelContextProtocol.Server;
11+
using OpenTelemetry;
1112
using OpenTelemetry.Logs;
1213
using OpenTelemetry.Metrics;
1314
using OpenTelemetry.Resources;
@@ -189,21 +190,12 @@ await ctx.Server.RequestSamplingAsync([
189190
})
190191
;
191192

192-
193-
var resource = ResourceBuilder.CreateEmpty().AddService("mcp.server");
193+
ResourceBuilder resource = ResourceBuilder.CreateDefault().AddService("everything-server");
194194
builder.Services.AddOpenTelemetry()
195-
.WithTracing(b => b.SetResourceBuilder(resource)
196-
.AddOtlpExporter()
197-
.AddSource("*")
198-
.AddAspNetCoreInstrumentation()
199-
.AddHttpClientInstrumentation())
200-
.WithMetrics(b => b.SetResourceBuilder(resource)
201-
.AddMeter("*")
202-
.AddOtlpExporter()
203-
.AddAspNetCoreInstrumentation()
204-
.AddHttpClientInstrumentation())
205-
.WithLogging(b => b.SetResourceBuilder(resource)
206-
.AddOtlpExporter());
195+
.WithTracing(b => b.AddSource("*").AddHttpClientInstrumentation().SetResourceBuilder(resource))
196+
.WithMetrics(b => b.AddMeter("*").AddHttpClientInstrumentation().SetResourceBuilder(resource))
197+
.WithLogging(b => b.SetResourceBuilder(resource))
198+
.UseOtlpExporter();
207199

208200
builder.Services.AddSingleton(subscriptions);
209201
builder.Services.AddHostedService<SubscriptionMessageSender>();

src/ModelContextProtocol/Diagnostics.cs

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
using System.Diagnostics;
22
using System.Diagnostics.Metrics;
3+
using System.Text.Json;
4+
using System.Text.Json.Nodes;
5+
using ModelContextProtocol.Protocol.Messages;
36

47
namespace ModelContextProtocol;
58

@@ -34,4 +37,79 @@ internal static Histogram<double> CreateDurationHistogram(string name, string de
3437
HistogramBucketBoundaries = [0.01, 0.02, 0.05, 0.1, 0.2, 0.5, 1, 2, 5, 10, 30, 60, 120, 300],
3538
};
3639
#endif
40+
41+
internal static ActivityContext ExtractActivityContext(this DistributedContextPropagator propagator, IJsonRpcMessage message)
42+
{
43+
string? traceparent = null;
44+
string? tracestate = null;
45+
propagator?.ExtractTraceIdAndState(message, ExtractContext, out traceparent, out tracestate);
46+
ActivityContext.TryParse(traceparent, tracestate, true, out var activityContext);
47+
return activityContext;
48+
}
49+
50+
private static void ExtractContext(object? message, string fieldName, out string? fieldValue, out IEnumerable<string>? fieldValues)
51+
{
52+
fieldValues = null;
53+
fieldValue = null;
54+
55+
JsonNode? parameters = null;
56+
switch (message)
57+
{
58+
case JsonRpcRequest request:
59+
parameters = request.Params;
60+
break;
61+
62+
case JsonRpcNotification notification:
63+
parameters = notification.Params;
64+
break;
65+
66+
default:
67+
break;
68+
}
69+
70+
if (parameters?[fieldName] is JsonValue value && value.GetValueKind() == JsonValueKind.String)
71+
{
72+
fieldValue = value.GetValue<string>();
73+
}
74+
}
75+
76+
internal static void InjectActivityContext(this DistributedContextPropagator propagator, Activity? activity, IJsonRpcMessage message)
77+
{
78+
// noop if activity is null
79+
propagator?.Inject(activity, message, InjectContext);
80+
}
81+
82+
private static void InjectContext(object? message, string key, string value)
83+
{
84+
JsonNode? parameters = null;
85+
switch (message)
86+
{
87+
case JsonRpcRequest request:
88+
parameters = request.Params;
89+
break;
90+
91+
case JsonRpcNotification notification:
92+
parameters = notification.Params;
93+
break;
94+
95+
default:
96+
break;
97+
}
98+
99+
if (parameters is JsonObject jsonObject && jsonObject[key] == null)
100+
{
101+
jsonObject[key] = value;
102+
}
103+
}
104+
105+
internal static bool ShouldInstrumentMessage(IJsonRpcMessage message) =>
106+
ActivitySource.HasListeners() &&
107+
message switch
108+
{
109+
JsonRpcRequest => true,
110+
JsonRpcNotification notification => notification.Method != NotificationMethods.LoggingMessageNotification,
111+
_ => false
112+
};
113+
114+
internal static ActivityLink[] ActivityLinkFromCurrent() => Activity.Current is null ? [] : [new ActivityLink(Activity.Current.Context)];
37115
}

0 commit comments

Comments
 (0)