Restore `[McpServerTool]` composability with MRTR input requests + tasks
I maintainer di solito rispondono entro 1 giorno
Valutazione
- Difficoltà
- 5/5
- Tempo stimato
- Più di una settimana
- Idoneità per principianti
- 35/100
- Tipo di issue
- Funzionalità
- Chiarezza
- Abbastanza chiara
- Stato di attività
- Tranquilla
- Stack tecnologico
- csharp
- Ambito
- backend-api-design
Direzione di ricerca
Inizia da src/ModelContextProtocol.Core/Server/McpTaskExecutionContext.cs, dal wrapper dell'attività intorno a McpServerImpl.cs:933 e dai test eliminati tests/ModelContextProtocol.Tests/Server/AutomaticInputRequiredStatusTests.cs per comprendere il comportamento esistente. Definisci e convalida la gestione degli input MRTR consapevole delle attività e la promozione sincrona delle attività, quindi documenta entrambi i pattern con esempi eseguibili in docs/concepts/tasks/tasks.md.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Context
SEP-2663 (Tasks extension) is being implemented in #1579 and SEP-2322 (MRTR) landed in #1458. Both extensions let a tool ask the user for input mid-execution, but via different protocol mechanisms:
- MRTR:
tools/callround-trips — the server returns aninput_requiredresult, the client re-sendstools/callwith input responses, the server replays the handler. - Tasks:
tasks/update— the server sets the task tostatus = input_requiredwith the pending input requests, the client sendstasks/updatewith input responses, the task body'sElicitAsync/SampleAsync/RequestRootsAsyncawait resumes.
End users writing [McpServerTool] methods don't know (and shouldn't need to know) which mechanism the client is using. Today, after #1579 lands, two composition cases break:
Case 1: [McpServerTool] + tasks _meta opt-in + input requests inside the method body
A [McpServerTool] method that calls ElicitAsync/SampleAsync/RequestRootsAsync works when invoked synchronously (MRTR translates the call into a tools/call round-trip). But when the client signals the tasks opt-in (SEP-2663 §51 _meta envelope), the SDK pre-creates a task and runs the method body in Task.Run. Inside the body, the MRTR backcompat resolver throws InputRequiredException. The task wrapper's generic catch (Exception ex) at McpServerImpl.cs:933 turns this into a Failed task with the literal exception message — no hint that "MRTR can't compose with tasks under this wrapper".
The SEP-1686-era SDK supported this case via the AutomaticInputRequiredStatusTests test class (now deleted in cec5d998), which asserted that ElicitAsync/SampleAsync inside a task body auto-transitioned the task to InputRequired status. SEP-2663 preserves this capability at the protocol level (InputRequiredTaskResult + UpdateTaskRequestParams.InputResponses) but the new task wrapper doesn't wire it through.
Case 2: Sync [McpServerTool] that needs to escalate to a task mid-execution
A [McpServerTool] method may run synchronously for "most" requests but occasionally need to do long-running work. Today, the only way to support this is to write a CallToolWithTaskHandler that drives the task lifecycle manually. The pre-#1458 SDK had a DeferTaskCreation opt-in on [McpServerTool] that I removed in #1458 to keep the MRTR PR minimal — so this capability is currently absent.
Restoring something like DeferTaskCreation would let the method run sync first, then call e.g. context.PromoteToTaskAsync() to create a task and detach.
Proposed approach
Design and implement a unified composition story that addresses both cases. Sketch (not prescriptive — the right design needs more thought):
-
Task-aware MRTR for Case 1. When MRTR sees that it's running inside a task scope (via
McpTaskExecutionContext, which already exists atsrc/ModelContextProtocol.Core/Server/McpTaskExecutionContext.cs), translateElicitAsync/SampleAsync/RequestRootsAsyncinto task-protocol input requests (taskStore.SetInputRequestsAsync(...)and awaittasks/updateresume) instead of MRTR round-trips. The deletedAutomaticInputRequiredStatusTestsis the behavioral contract to restore. -
DeferTaskCreationfor Case 2. Re-introduce the[McpServerTool(DeferTaskCreation = true)]opt-in (or an equivalentMcpServerToolCreateOptionsshape) plus a context API (context.PromoteToTaskAsync(McpTaskInfo?)or similar) that the method can call to escalate. -
Documentation in
docs/concepts/tasks/tasks.mdcovering both patterns with runnable examples.
Open design questions:
- Should
DeferTaskCreationbe the default for async[McpServerTool]methods, or stay opt-in? (Default-on is more ergonomic but changes existing behavior.) - How should
McpTaskExecutionContextbe discovered from within MRTR —AsyncLocal, parameter injection, or something else? - What does Case 1 look like when the client supports neither the tasks extension nor MRTR? (Probably: today's behavior, error returned.)
Out of scope
- Mid-flight transport switching (sticky session vs. resumable HTTP) — orthogonal, blocked on SEP-2575/2567 / #1610.
- Cross-process task store handoff for
DeferTaskCreation—IMcpTaskStorealready abstracts this.
Related
- #1458 — MRTR (removed the original
DeferTaskCreationto keep scope minimal) - #1579 — SEP-2663 Tasks extension
- #1610 — sessionless + handshake-less draft protocol (SEP-2575 + SEP-2567)
- SEP-2663 §51 (per-request
_metaopt-in envelope), §306 (durability), §186 (failed.error shape) - Deleted test (SEP-1686-era behavior contract for Case 1):
tests/ModelContextProtocol.Tests/Server/AutomaticInputRequiredStatusTests.csremoved in commitcec5d998
- Lingua principale
- C#
- Stelle
- 4.6k
- Fork
- 819
- Merge medio
- 8g 7h
- PR unite (30g)
- 3
Preparare l'ambiente
Avvia il container di sviluppo del progetto nel browser, con il tuo account GitHub.
- Nessun Dockerfile né file Docker Compose
- Nessun modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di modelcontextprotocol/csharp-sdk
-
ClaimsPrincipal parameter injection sample requestForse già presa Una pull request collegata a questa issue è aperta o già unita. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 74/100
modelcontextprotocol/csharp-sdk#1899 ·
I maintainer di solito rispondono entro 1 giorno
-
Document ClientOAuthOptions.ScopeSelector usageForse già presa @z0rimo l’ha presa 24 giorni fa. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
modelcontextprotocol/csharp-sdk#1867 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
HTTP+SSE client: POST responses are never disposed, leaking one connection per sent messageForse già presa @yalcinfu22 l’ha presa 39 giorni fa. Aperta
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 88/100
modelcontextprotocol/csharp-sdk#1840 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
stdio client never closes the server's stdin, so every client dispose burns the full ShutdownTimeout (5s by default)Forse già presa @luisangelrod l’ha presa 40 giorni fa. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 84/100
modelcontextprotocol/csharp-sdk#1836 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
enhancement needs confirmation
Difficoltà 2/5 1-3 ore Idoneità per principianti 64/100
modelcontextprotocol/csharp-sdk#678 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di modelcontextprotocol/csharp-sdk
Issue simili
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 66/100
shimat/opencvsharp#2154 ·
I maintainer di solito rispondono entro 1 giorno
-
subsystem: UI
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
Open-Systems-Pharmacology/PK-Sim#3812 ·
I maintainer di solito rispondono entro 1 giorno
-
ClientIdGenerator.Random() only yields 16 distinct client ids (MaxSafeInteger uses XOR, not exponentiation)Forse già presa @makcgr l’ha presa oggi. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 85/100
-
C: Syntax
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100