3
3
using OpenTelemetry . Trace ;
4
4
using AspNetCoreMcpPerSessionTools . Tools ;
5
5
using ModelContextProtocol . Server ;
6
+ using System . Collections . Concurrent ;
7
+ using System . Reflection ;
6
8
7
9
var builder = WebApplication . CreateBuilder ( args ) ;
8
10
11
+ // Create and populate the tool dictionary at startup
12
+ var toolDictionary = new ConcurrentDictionary < string , McpServerTool [ ] > ( ) ;
13
+ PopulateToolDictionary ( toolDictionary ) ;
14
+
9
15
// Register all MCP server tools - they will be filtered per session based on route
10
16
builder . Services . AddMcpServer ( )
11
17
. WithHttpTransport ( options =>
18
24
19
25
// Get the tool collection that we can modify per session
20
26
var toolCollection = mcpOptions . Capabilities ? . Tools ? . ToolCollection ;
21
- if ( toolCollection ! = null )
27
+ if ( toolCollection = = null )
22
28
{
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 )
25
36
{
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 ) ;
48
38
}
49
39
}
50
40
} ;
68
58
69
59
app . Run ( ) ;
70
60
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 )
73
63
{
74
64
// Try to get tool category from route values
75
65
if ( context . Request . RouteValues . TryGetValue ( "toolCategory" , out var categoryObj ) && categoryObj is string category )
81
71
return "all" ;
82
72
}
83
73
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 > ( )
87
95
{
96
+ var tools = new List < McpServerTool > ( ) ;
88
97
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 )
90
99
. Where ( m => m . GetCustomAttributes ( typeof ( McpServerToolAttribute ) , false ) . Any ( ) ) ;
91
-
100
+
92
101
foreach ( var method in methods )
93
102
{
94
103
try
95
104
{
96
105
var tool = McpServerTool . Create ( method , target : null , new McpServerToolCreateOptions ( ) ) ;
97
- toolCollection . Add ( tool ) ;
106
+ tools . Add ( tool ) ;
98
107
}
99
108
catch ( Exception ex )
100
109
{
101
110
// Log error but continue with other tools
102
111
Console . WriteLine ( $ "Failed to add tool { toolType . Name } .{ method . Name } : { ex . Message } ") ;
103
112
}
104
113
}
114
+
115
+ return [ .. tools ] ;
105
116
}
0 commit comments