Au 07/11/2026, Claude Code 2.1.319 (06/11/2026) prend en charge les tasks MCP dans le terminal : quand le serveur marque tools/call comme task, l'hôte déplace l'appel en arrière-plan et réinjecte le résultat après tasks/result. Protocole : SEP-1686 expérimental dans MCP 2025-11-25 (documentation Tasks). Pour un agent maison, l'enjeu n'est pas « savoir interroger », mais séparer JSON d'état de task, validation des arguments et CallToolResult final. Retours d'outils : outputSchema ; contrat Skills : Skills over MCP.
Les outils MCP longs (batch, API de jobs externes, crawling lourd) bloquaient toute la tour de dialogue. La task scinde « accepter la requête » et « livrer le résultat » en deux phases JSON-RPC : la première donne au modèle des métadonnées de task, pas le payload métier. Claude Code en fait le comportement hôte par défaut ; pour votre propre hôte, réutilisez la même machine à états — ne simulez pas un tool result à status: working.
Ce que Claude Code change le 6 nov.
- Arrière-plan : si le serveur MCP exécute
tools/callen task, Claude Code rend la main au modèle tout de suite et attend en arrière-plan — comme le prévoit SEP-1686 pour laisser le modèle continuer. CLAUDE_CODE_DISABLE_MCP_TASK_BACKGROUND: si activé, attente synchrone bloquante dans l'appel d'outil — pratique pour comparer sync et async.CLAUDE_CODE_DISABLE_MCP_TASKS=1: désactive entièrement le support des tasks MCP./tasks: l'UI terminal liste les sous-tâches en cours et terminées pour alignertaskIdet journaux JSON.
En une phrase. La task change la chronologie, pas le contrat Schema. inputSchema reste dans tools/list ; valider avant l'appel.
Forme JSON dans SEP-1686
Ajoutez task (optionnellement ttl en ms) dans les params de tools/call ; si le serveur accepte, le result est un CreateTaskResult, pas un CallToolResult ordinaire :
{
"tools_call_with_task": {
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "batch_index",
"arguments": {
"dataset": "logs-2026-11",
"shard": 3
},
"task": { "ttl": 120000 }
}
},
"create_task_result": {
"task": {
"taskId": "786512e2-9e0d-44bd-8f29-789f320fe840",
"status": "working",
"statusMessage": "The operation is now in progress.",
"createdAt": "2026-11-07T02:10:00Z",
"lastUpdatedAt": "2026-11-07T02:10:05Z",
"ttl": 120000,
"pollInterval": 5000
}
}
}
États terminaux : completed, failed, cancelled, plus input_required (entrée utilisateur ou hôte). Interrogation via tasks/get, résultat métier via tasks/result — même structure que tools/call synchrone (content, isError, structuredContent optionnel).
{
"tasks_get_response": {
"taskId": "786512e2-9e0d-44bd-8f29-789f320fe840",
"status": "completed",
"pollInterval": 5000,
"lastUpdatedAt": "2026-11-07T02:12:00Z"
},
"tasks_result_response": {
"content": [{ "type": "text", "text": "Indexed 1.2M rows in shard 3." }],
"isError": false,
"structuredContent": {
"rows": 1200000,
"shard": 3
}
}
}
Le serveur peut mettre io.modelcontextprotocol/model-immediate-response dans _meta de CreateTaskResult ; sinon message placeholder côté hôte. notifications/tasks/status est optionnel — la spec exige de ne pas se fier qu'au push : continuer tasks/get selon pollInterval.
capabilities et taskSupport
Au handshake, les deux parties déclarent capabilities.tasks. Un tools/call augmenté par task n'est permis que si le client annonce tasks.requests.tools.call et le serveur la supporte.
{
"server_capabilities_tasks": {
"capabilities": {
"tasks": {
"list": {},
"cancel": {},
"requests": {
"tools": { "call": {} }
}
}
}
},
"tool_list_entry": {
"name": "batch_index",
"description": "Index one shard of a dataset",
"inputSchema": {
"type": "object",
"properties": {
"dataset": { "type": "string" },
"shard": { "type": "integer", "minimum": 0 }
},
"required": ["dataset", "shard"],
"additionalProperties": false
},
"execution": {
"taskSupport": "optional"
}
}
}
Sans tasks.requests.tools.call côté serveur, le client ne doit pas envoyer d'appel avec task, même si taskSupport vaut optional. Avec taskSupport: required, un call sans params.task doit être refusé (la spec suggère -32601).
Interrogation côté hôte et fusion du résultat
- Valider les entrées : vérifier
argumentscontreinputSchemaen cache depuistools/list(JSON Schema 2020-12, SEP-1613). - Envoyer le call : joindre
params.taskselontaskSupport. - Réponse immédiate au modèle :
CreateTaskResultoumodel-immediate-response; enregistrertaskIddans l'état de session (objet JSON, pas seulement une chaîne). - Interroger :
tasks/getà intervalle ≥pollInterval, jusqu'à état terminal ouinput_required. - Récupérer le résultat :
tasks/result; sioutputSchema, validerstructuredContent(article outputSchema). - Réécrire dans le dialogue : le
CallToolResultfinal comme message de résultat d'outil ; pas de faux succès en phaseworking.
{
"host_session_tasks": {
"786512e2-9e0d-44bd-8f29-789f320fe840": {
"toolName": "batch_index",
"arguments": { "dataset": "logs-2026-11", "shard": 3 },
"lastStatus": "working",
"nextPollAt": "2026-11-07T02:10:10Z"
}
}
}
arguments et outputSchema
Erreur fréquente : sauter la validation d'entrée dès status: completed, ou traiter CreateTaskResult comme sortie d'outil dans un pipeline. Chemins sync et task : mêmes fonctions Schema.
{
"arguments_string": "{\"dataset\":\"logs-2026-11\",\"shard\":3}",
"inputSchema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"dataset": { "type": "string", "pattern": "^[a-z0-9-]+$" },
"shard": { "type": "integer", "minimum": 0 }
},
"required": ["dataset", "shard"],
"additionalProperties": false
}
}
Distinguer : échec Schema (client refuse, pas de call), Tool Execution Error (SEP-1303 : erreurs métier/validation via tool result pour auto-correction du modèle), task failed/cancelled (JSON d'état dans les logs, pas de demi-résultat comme succès).
Variables d'environnement du terminal
CLAUDE_CODE_DISABLE_MCP_TASK_BACKGROUND=1— attente synchrone de la task, pour tests d'intégration.CLAUDE_CODE_DISABLE_MCP_TASKS=1— tasks désactivées,tools/callbloquant classique.
Un hôte maison n'a pas ces variables ; la couche applicative peut imiter : « arrière-plan par défaut + option pour forcer le blocage » — proche de Claude Code en staging.
Essayer sur JSON Toolbox
- Coller
inputSchemaetarguments_stringci-dessus dans la validation Schema. - Avec l'outil MCP, comparer les noms de champs
taskSupportetinputSchema. - Formater
create_task_resultettasks_result_response— ne pas les fusionner en un faux tool result. - Pour la sortie structurée finale du modèle : schema sortie structurée séparé de l'objet d'état de task.
Questions fréquentes
En quoi la réponse d'une task MCP diffère-t-elle d'un tools/call classique ?
D'abord les métadonnées de task ; la vraie sortie est dans tasks/result.
Faut-il encore valider arguments quand la task tourne en arrière-plan ?
Oui — contre inputSchema avant le call.
Quelles valeurs pour execution.taskSupport ?
forbidden / optional / required, sous contrainte des capabilities.
À quoi sert CLAUDE_CODE_DISABLE_MCP_TASK_BACKGROUND ?
Force l'attente synchrone de la fin de la task MCP.
Comment tasks/result et outputSchema s'articulent ?
Comme pour un call synchrone — valider structuredContent une fois reçu.
Synthèse
Au 07/11/2026, Claude Code 2.1.319 fait des Tasks MCP le mode hôte par défaut du terminal : les longs tools/call deviennent d'abord CreateTaskResult, puis se terminent via tasks/get / tasks/result. En intégration agent, traiter le JSON d'état de task comme machine à états de session ; garder arguments / structuredContent sous JSON Schema 2020-12. Prochaine étape : un serveur MCP avec taskSupport: optional, comparer avec et sans CLAUDE_CODE_DISABLE_MCP_TASK_BACKGROUND sur les tours du modèle et les messages d'outil.