Skip to content

Commit 33fbfab

Browse files
committed
Refactor reflection to happen once only
1 parent e2ba19d commit 33fbfab

File tree

1 file changed

+44
-33
lines changed

1 file changed

+44
-33
lines changed

samples/AspNetCoreMcpPerSessionTools/Program.cs

Lines changed: 44 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,15 @@
33
using OpenTelemetry.Trace;
44
using AspNetCoreMcpPerSessionTools.Tools;
55
using ModelContextProtocol.Server;
6+
using System.Collections.Concurrent;
7+
using System.Reflection;
68

79
var builder = WebApplication.CreateBuilder(args);
810

11+
// Create and populate the tool dictionary at startup
12+
var toolDictionary = new ConcurrentDictionary<string, McpServerTool[]>();
13+
PopulateToolDictionary(toolDictionary);
14+
915
// Register all MCP server tools - they will be filtered per session based on route
1016
builder.Services.AddMcpServer()
1117
.WithHttpTransport(options =>
@@ -18,33 +24,17 @@
1824

1925
// Get the tool collection that we can modify per session
2026
var toolCollection = mcpOptions.Capabilities?.Tools?.ToolCollection;
21-
if (toolCollection != null)
27+
if (toolCollection == null)
2228
{
23-
// Add tools based on the requested category
24-
switch (toolCategory?.ToLower())
29+
return;
30+
}
31+
32+
// Get pre-populated tools for the requested category
33+
if (toolDictionary.TryGetValue(toolCategory.ToLower(), out var tools))
34+
{
35+
foreach (var tool in tools)
2536
{
26-
case "clock":
27-
// Clock category gets time/date tools
28-
AddToolsForType<ClockTool>(toolCollection);
29-
break;
30-
31-
case "calculator":
32-
// Calculator category gets mathematical tools
33-
AddToolsForType<CalculatorTool>(toolCollection);
34-
break;
35-
36-
case "userinfo":
37-
// UserInfo category gets session and system information tools
38-
AddToolsForType<UserInfoTool>(toolCollection);
39-
break;
40-
41-
case "all":
42-
default:
43-
// Default or "all" category gets all tools
44-
AddToolsForType<ClockTool>(toolCollection);
45-
AddToolsForType<CalculatorTool>(toolCollection);
46-
AddToolsForType<UserInfoTool>(toolCollection);
47-
break;
37+
toolCollection.Add(tool);
4838
}
4939
}
5040
};
@@ -68,8 +58,8 @@
6858

6959
app.Run();
7060

71-
// Helper methods for route-based tool category detection
72-
static string? GetToolCategoryFromRoute(HttpContext context)
61+
// Helper method for route-based tool category detection
62+
static string GetToolCategoryFromRoute(HttpContext context)
7363
{
7464
// Try to get tool category from route values
7565
if (context.Request.RouteValues.TryGetValue("toolCategory", out var categoryObj) && categoryObj is string category)
@@ -81,25 +71,46 @@
8171
return "all";
8272
}
8373

84-
static void AddToolsForType<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(
85-
System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicMethods)]T>(
86-
McpServerPrimitiveCollection<McpServerTool> toolCollection)
74+
// Helper method to populate the tool dictionary at startup
75+
static void PopulateToolDictionary(ConcurrentDictionary<string, McpServerTool[]> toolDictionary)
76+
{
77+
// Get tools for each category
78+
var clockTools = GetToolsForType<ClockTool>();
79+
var calculatorTools = GetToolsForType<CalculatorTool>();
80+
var userInfoTools = GetToolsForType<UserInfoTool>();
81+
McpServerTool[] allTools = [.. clockTools,
82+
.. calculatorTools,
83+
.. userInfoTools];
84+
85+
// Populate the dictionary with tools for each category
86+
toolDictionary.TryAdd("clock", clockTools);
87+
toolDictionary.TryAdd("calculator", calculatorTools);
88+
toolDictionary.TryAdd("userinfo", userInfoTools);
89+
toolDictionary.TryAdd("all", allTools);
90+
}
91+
92+
// Helper method to get tools for a specific type using reflection
93+
static McpServerTool[] GetToolsForType<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(
94+
System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicMethods)] T>()
8795
{
96+
var tools = new List<McpServerTool>();
8897
var toolType = typeof(T);
89-
var methods = toolType.GetMethods(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static)
98+
var methods = toolType.GetMethods(BindingFlags.Public | BindingFlags.Static)
9099
.Where(m => m.GetCustomAttributes(typeof(McpServerToolAttribute), false).Any());
91-
100+
92101
foreach (var method in methods)
93102
{
94103
try
95104
{
96105
var tool = McpServerTool.Create(method, target: null, new McpServerToolCreateOptions());
97-
toolCollection.Add(tool);
106+
tools.Add(tool);
98107
}
99108
catch (Exception ex)
100109
{
101110
// Log error but continue with other tools
102111
Console.WriteLine($"Failed to add tool {toolType.Name}.{method.Name}: {ex.Message}");
103112
}
104113
}
114+
115+
return [.. tools];
105116
}

0 commit comments

Comments
 (0)