modelcontextprotocol / modelcontextprotocol/csharp-sdk

Support for dynamic tools

Offen
#237 12 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Dieses Issue hat noch niemand übernommen.

enhancement needs confirmation
Vorherrschende Sprache
C#
Sterne
4.5k
Forks
814
Ø Merge
9 T. 19 Std.
Gemergte PRs (30 T.)
4

Beschreibung

Is your feature request related to a problem? Please describe.
I would like to map a collection of dynamic tools to a single class handler (see example below).

Describe the solution you'd like
I would like a single handler to be mapped to multiple tools. These tools will be dynamically mapped and available at runtime and may be on other servers. The core of this would be a base class DynamicTools

builder.Services.AddMcpServer()
    .WithStdioServerTransport()
    .WithTools<EchoTools>()  // support with static tools side by side
    .WithTools<MyDynamicTools>(
    [
        new Tool { Name = "echo_a", Description = "Echoes the input back to the user.", InputSchema = "..." },
        new Tool { Name = "echo_b", Description = "Echoes the input back to the user.", InputSchema = "..." },
    ]);

public class MyDynamicTools : DynamicTools
{
    private readonly HttpClient _client;

    public MyDynamicTools(HttpClient client) // also other scoped services should be able to be injected here
    {
        _client = client;
    }

    public override async Task<IMcpActionResult> Invoke(CallToolRequestParams requestParams)
    {
        // just an example other routing logic may apply here
        var result = await _client.PostAsJsonAsync($"/service/{requestParams.Name}", requestParams.Arguments);
        // could also return error
        return Ok(result);
    }
}

The rest would be optional, only the Invoke(CallToolRequestParams params) is important.
Maybe make it similar to MVC.

public interface IMcpActionResult
{
    Task Invoke(ITransport transport, CancellationToken cancellationToken);
}

public class OkObjectResult : IMcpActionResult
{
    private readonly object _value;
    public OkObjectResult(object value)
    {
        _value = value;
    }
    public Task Invoke(ITransport transport, CancellationToken cancellationToken)
    {
        return transport.SendMessageAsync(new JsonRpcResponse { Result = _value}, cancellationToken);
    }
}

public abstract class DynamicTools
{
    public abstract async Task<IMcpActionResult> Invoke(CallToolRequestParams requestParams);

    protected IMcpActionResult Ok(object value)
    {
        return new OkObjectResult(value);
    }
}

Describe alternatives you've considered
Create a custom a CallToolHandler

Additional context
Add any other context or screenshots about the feature request here.

Beitragsleitfaden

Beitragsleitfaden öffnen

Erste Schritte

  1. Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
  3. Forke das Repository und arbeite in einem Branch.
  4. Öffne einen Pull Request, der die Issue-Nummer nennt.

Rechercherichtung

Beginne damit, die bestehende Tool-Registrierung und Aufrufbehandlung hinter AddMcpServer, WithTools und der benutzerdefinierten Alternative CallToolHandler zu lesen. Vergleiche die statische Tool-Registrierung mit den vorgeschlagenen Einstiegspunkten DynamicTools und Invoke. Die Umsetzung sollte die Laufzeitregistrierung mehrerer Tools für einen Handler, die Injektion von Services und einen definierten Ergebnispfad umfassen, mit Tests, die das Verhalten abdecken.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Bewertung

Tech-Stack
csharp
Bereich
api, backend
Issue-Typ
Feature
Schwierigkeit
5/5
Geschätzter Aufwand
Über eine Woche
Aktivitätsstatus
Veraltet
Klarheit
Größtenteils klar
Anfängerfreundlichkeit
25/100

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.