modelcontextprotocol / modelcontextprotocol/python-sdk

Requests with "id": null silently misclassified as notifications

Ouverte
#2,057 10 commentaires 1 réaction 0 personnes assignées Voir sur GitHub

Personne n'a encore pris cette issue.

bug improves spec compliance P2
Langage dominant
Python
Étoiles
24.3k
Forks
4k
Merge moyen
1 j 1 h
PR mergées (30 j)
31

Description

Initial Checks
Description

When a JSON-RPC request arrives with "id": null, the SDK should reject it. Both JSON-RPC 2.0 and the MCP spec restrict request IDs to strings or integers. Instead, the request is silently reclassified as a JSONRPCNotification and the caller gets a 202 with no response.

This happens because of how JSONRPCMessage union resolution interacts with extra='allow':

  1. RequestId correctly excludes None (Annotated[int, Field(strict=True)] | str).
  2. JSONRPCRequest validation rejects id: null, working as intended.
  3. Pydantic falls through to JSONRPCNotification, which absorbs "id": None as an extra field via extra='allow'.
  4. The streamable HTTP transport sees "not a request" and returns 202.

The net effect is the caller gets no error and no response, which is hard to debug. Found via authprobe scanning.

I suspect the v2 migration to TypeAdapter and dropping extra='allow' on top-level types would resolve this, but wanted to flag it for the current release line too.

Example Code
from mcp.types import JSONRPCMessage, JSONRPCRequest

msg = {"jsonrpc": "2.0", "method": "initialize", "id": None}

# JSONRPCRequest correctly rejects null id
try:
    JSONRPCRequest.model_validate(msg)
except Exception:
    print("JSONRPCRequest rejects null id")  # Expected

# JSONRPCMessage falls through to JSONRPCNotification
parsed = JSONRPCMessage.model_validate(msg)
print(type(parsed.root).__name__)   # JSONRPCNotification (unexpected)
print(parsed.root.model_extra)      # {'id': None}
Python & MCP Python SDK
Python 3.13
mcp 1.14.1 (also reproduced on 1.26.0, latest at time of filing)

Guide de contribution

Ouvrir le guide de contribution

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Piste de recherche

Commencez par la validation de JSONRPCMessage et JSONRPCRequest, puis suivez la manière dont le transport HTTP streamable traite un message analysé. Reproduisez l’exemple null-id fourni et vérifiez qu’il est rejeté comme une requête invalide, plutôt que classé comme JSONRPCNotification ou traité par une réponse 202.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Évaluation

Stack technique
python
Domaine
api
Type d'issue
Bug
Difficulté
3/5
Temps estimé
1-2 jours
Activité
À l'abandon
Clarté
Plutôt claire
Accessibilité débutants
48/100

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.