Skip to content

Conversation

PederHP
Copy link
Collaborator

@PederHP PederHP commented Aug 21, 2025

Had Copilot help create a sample of how to use ConfigureSessionOptions to make tools dynamic and client/user specific. See #714.

Copilot AI and others added 5 commits August 22, 2025 11:12
…a-1d92ba914d7b

Rename AspNetCoreMcpServerPerUserTools to AspNetCoreMcpPerSessionTools with route-based filtering
@PederHP
Copy link
Collaborator Author

PederHP commented Aug 22, 2025

I've updated the sample as per @halter73 's suggestion to use route as the criteria instead of a header - to avoid any confusion with the mechanisms provided by the upcoming authorization convenience. The sample should show how to use arbitrary criteria to modify the Tools collection in the ConfigureSessionOptions delegate.

Copy link
Contributor

@halter73 halter73 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great!

Copy link
Contributor

@halter73 halter73 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alternatively, we could filter out the tools, but starting from an empty list does seem simpler. If we wanted to improve this further, we could have a ConcurrentDictionary<string, McpServerTool[]> to look up the tool types more efficiently so we don't have to do a bunch of reflection at the start of each session.

@PederHP
Copy link
Collaborator Author

PederHP commented Aug 26, 2025

@halter73

Applied your suggested changes to start from an empty list without clearing, but hadn't noticed that this means the capability isn't initialized when configuring the session options. To make the sample reasonably simply, I added this back rather than manually configure the capability.

I could change it to add a basic tool that's always there, but that might add more confusion than benefit.

@halter73
Copy link
Contributor

I could change it to add a basic tool that's always there, but that might add more confusion than benefit.

I think the better bet is to manually initialize the capabilities. That way, the ConfigureSessionOptions callback doesn't need to null-check it either making it slightly shorter while also getting rid of all the WithTools calls. I'd also just index into RouteValues directly and call ToLower() inline. I it's easier to see what's going on at a glance that way.

        // Configure per-session options to filter tools based on route category
        options.ConfigureSessionOptions = async (httpContext, mcpOptions, cancellationToken) =>
        {
            var toolCategory = httpContext.Request.RouteValues["toolCategory"]?.ToString()?.ToLower() ?? "all";

            // Get pre-populated tools for the requested category
            if (toolDictionary.TryGetValue(toolCategory, out var tools))
            {
                mcpOptions.Capabilities = new();
                mcpOptions.Capabilities.Tools = new();
                var toolCollection = mcpOptions.Capabilities.Tools.ToolCollection = new();

                foreach (var tool in tools)
                {
                    toolCollection.Add(tool);
                }
            }
        };

@jozkee Is looking at moving where we put the [JsonIgnore]'d properties on the capabilities types like the collections and handlers so they aren't so deeply nested which could make this look even nicer.

Another thing that might help tighten this up is just removing the OpenTelemetry dependencies from this sample. I think it's enough to leave that in the AspNetCoreMcpServer sample and keep this one a little more focused on the per-session options.

@halter73 halter73 changed the title Per User (Client) Tools Sample Per Route Tools Sample Aug 27, 2025
@halter73 halter73 mentioned this pull request Aug 27, 2025
9 tasks
@halter73 halter73 changed the title Per Route Tools Sample Per RouteValue Tools Sample Aug 27, 2025
@PederHP PederHP requested a review from halter73 September 1, 2025 15:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants