Présentation du protocole

Le Type Server Protocol (TSP) est un protocole JSON‑RPC dédié à la récupération de données d’analyse de type Python. Il s’appuie sur les formes de données du Language Server Protocol (LSP) – notamment Position et Range – et représente les URI sous forme de chaînes, exactement comme le LSP. Les méthodes sont préfixées typeServer/ et couvrent la version du protocole, les instantanés (snapshots), les chemins de recherche Python, la résolution d’imports et les requêtes de type (calculé, déclaré, attendu).

Les artefacts officiels du protocole résident dans le répertoire du dépôt : typeServerProtocol.ts décrit les interfaces TypeScript, tsp.json fournit le modèle lisible par machine, et tsp.schema.json en définit le schéma JSON. Cette centralisation garantit que chaque implémentation se base sur la même spécification.

Mécanisme de connexion et versionnage

Un client démarre un serveur de type et communique via la même connexion JSON‑RPC que le LSP, en utilisant un transport supporté – typiquement stdio ou Node IPC. En mode stdio, la sortie standard doit être réservée aux messages JSON‑RPC, ce qui impose une discipline stricte sur l’écriture de logs. Le protocole utilise des chaînes de version sémantique ; bien que la série actuelle soit 0.x, les changements de version mineure peuvent introduire des ruptures, alors que les correctifs restent rétro‑compatibles dans la même branche mineure.

Le flux d’initialisation suit le modèle LSP : le client envoie initialize, puis interroge typeServer/getSupportedProtocolVersion pour valider la compatibilité, avant de récupérer le premier instantané avec typeServer/getSnapshot. Les requêtes de type ou de résolution d’imports incluent cet identifiant d’instantané, et le serveur notifie les invalidations via typeServer/snapshotChanged.

Mode multi‑connexion et performances

{
  "capabilities": {
    "experimental": {
      "typeServerMultiConnection": {
        "supportedTransports": ["ipc"]
      }
    }
  }
}

Le protocole autorise des canaux supplémentaires en lecture seule, négociés lors de l’étape d’initialisation LSP via la capacité expérimentale typeServerMultiConnection. Si client et serveur déclarent un transport commun (actuellement ipc), le client peut ouvrir un canal dédié :

{
  "type": "open",
  "kind": "ipc",
  "args": [""]
}

Ces canaux parallèles permettent d’exécuter un grand volume de requêtes de type sans bloquer le flux principal, ce qui est utile pour des workers en arrière‑plan ou des analyses batch. La négociation reste optionnelle : en absence de capacité partagée, la session se poursuit en mode mono‑connexion, garantissant la compatibilité avec les implémentations qui ne supportent pas le mode multi‑connexion.

Contraintes de sécurité et limites

Les canaux additionnels sont strictement en lecture seule ; ils ne peuvent pas transmettre de notifications de synchronisation de documents, de changements de configuration ou de snapshots, qui restent réservés à la connexion principale. Cette séparation limite l’exposition du serveur à des mutations non intentionnelles. Le serveur doit valider chaque requête typeServer/connection, accepter ou refuser l’ouverture du point d’accès IPC, et renvoyer un champ success explicite. En cas d’échec, un message court doit être fourni pour le journal.

Enfin, le protocole ne définit aucun mécanisme d’authentification intrinsèque ; la sécurité repose sur le contrôle d’accès du transport sous‑jacent (par exemple, les permissions du socket IPC). Les implémentations doivent donc veiller à isoler les points d’accès IPC et à appliquer des politiques de sandboxing afin d’éviter des attaques de type injection de messages JSON‑RPC.