Skip to content

Should we use the ActivatorUtilities.GetServiceOrCreateInstance to create the instance target when creating target? #1015

Description

@WeihanLi

Currently, we're using the ActivatorUtilities.CreateInstance method to create a target to invoke the related method for the tool call, it will create a new target each time, and some behavior may be incorrect from dependency injection.
Not sure if it's by design or a bug

/// <summary>Creates an instance of the target object.</summary>
private static object CreateTarget(
IServiceProvider? services,
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type type) =>
services is not null ? ActivatorUtilities.CreateInstance(services, type) :
Activator.CreateInstance(type)!;

I met an issue when using typed HttpClient, a minimal sample may look like below:

#!/usr/bin/env dotnet
#:sdk Microsoft.NET.Sdk.Web
#:package ModelContextProtocol.AspNetCore@0.4.0-preview.3
// #:project ../../src/ModelContextProtocol.AspNetCore/ModelContextProtocol.AspNetCore.csproj // same when reference the project

using ModelContextProtocol.Server;
using System.ComponentModel;

var builder = WebApplication.CreateSlimBuilder(args);

builder.Services.AddHttpClient<NoticeTool>(client =>
{
    client.BaseAddress = new Uri("https://reservation.weihanli.xyz/");
});
builder.Services.AddMcpServer()
    .WithHttpTransport()
    .WithTools<NoticeTool>();

var app = builder.Build();
app.MapMcp();
app.Run();


[McpServerToolType]
class NoticeTool(HttpClient httpClient)
{
    [McpServerTool, Description("Get recent notice from the reservation system.")]
    public async Task<string> GetNotice()
    {
        var responseText = await httpClient.GetStringAsync($"api/notice");
        return responseText;
    }
}

when the tool called, it would throw an exception like below:

Image

The HttpClient is not resolved as expected

It does work when I change it to use the ActivatorUtilities.GetServiceOrCreateInstance

Image

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions