modelcontextprotocol / modelcontextprotocol/csharp-sdk

Support for dynamic tools

Aperta
#237 12 commenti 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

enhancement needs confirmation
Lingua principale
C#
Stelle
4.5k
Fork
814
Merge medio
9g 19h
PR unite (30g)
4

Descrizione

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.

Guida per i contributori

Apri la guida per i contributori

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Direzione di ricerca

Inizia leggendo la registrazione degli strumenti esistente e la gestione delle chiamate alla base di AddMcpServer, WithTools e dell’alternativa personalizzata CallToolHandler. Confronta la registrazione statica degli strumenti con i punti di ingresso proposti DynamicTools e Invoke. L’implementazione dovrebbe includere la registrazione a runtime di più strumenti per un singolo handler, l’iniezione dei servizi e un percorso dei risultati definito, con test che coprano il comportamento.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
csharp
Ambito
api, backend
Tipo di issue
Funzionalità
Difficoltà
5/5
Tempo stimato
Più di una settimana
Stato di attività
Ferma
Chiarezza
Abbastanza chiara
Idoneità per principianti
25/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.