Agents IA (MCP)
Les capacités exposées par l'API REST sont aussi publiées sous forme d'outils Model Context Protocol, afin qu'un agent IA puisse les utiliser directement.
Un outil n'est pas une implémentation parallèle : il dispatche le même handler que son équivalent REST, sous la même authentification, les mêmes scopes, le même quota et les mêmes règles d'idempotence. Ce qu'un agent ne peut pas faire en REST, il ne peut pas le faire en MCP.
tools/list va un pas plus loin que la découverte REST : il ne renvoie que les outils dont votre jeton
porte les scopes. Là où l'OpenAPI liste toutes les routes et ne refuse qu'à l'appel, un outil hors de vos
scopes n'apparaît simplement pas — appelé par son nom malgré tout, il répond en nommant le scope manquant.
Se connecter
| Endpoint | /mcp sur l'hôte de l'API Staff & Go |
| Transport | Streamable HTTP |
| Authentification | Serveur de ressources OAuth 2.1 — les mêmes identifiants partenaire qu'en REST |
La découverte suit la RFC 9728 : GET /.well-known/oauth-protected-resource renvoie l'identifiant de la ressource, son serveur d'autorisation et
les scopes qu'elle accepte. Un client MCP conforme lit cela et sait où s'authentifier.
Le jeton doit être émis pour l'audience de cette API. Nous n'acceptons jamais un identifiant transmis en passe-plat depuis ailleurs, et un jeton émis pour une autre audience est rejeté — c'est tout l'objet du rattachement d'audience.
Mise en place
L'accès partenaire est machine-to-machine, donc le flux prévu est client_credentials. Beaucoup de clients
MCP n'implémentent que le flux interactif par redirection et ne peuvent pas l'exécuter ; coller un en-tête
Authorization statique dans un fichier de configuration n'est pas une solution non plus, puisque le jeton
expire.
Nous publions un petit proxy stdio exactement pour ce cas : il détient vos identifiants client, émet et rafraîchit le jeton, et parle du MCP stdio simple à votre client. Node 20 ou supérieur est le seul prérequis — le proxy n'a aucune dépendance à installer.
| Téléchargement | |
|---|---|
mcp-stdio-proxy.mjs |
le proxy — le seul fichier strictement nécessaire |
install.mjs |
enregistre le proxy auprès de Claude Desktop, et écrit un modèle de fichier de réglages si aucun config.yml n'est présent |
install.ps1 · install.sh |
lanceurs pour le précédent |
Chaque fichier est servi en texte brut, pour que vous puissiez lire un script dans le navigateur avant de l'exécuter. Faites-le.
Réglages
L'installeur lit ses réglages dans un config.yml posé à côté de lui. Le plus simple est de le télécharger
depuis Staffngo : Applications (API), dans le dialogue du secret de votre application, bouton Télécharger la
configuration MCP (config.yml). Si aucun config.yml n'est présent, l'installeur écrit à sa place un modèle
commenté, à remplacer par le fichier téléchargé ou à remplir à la main. Quatre valeurs vous reviennent :
| Réglage | |
|---|---|
EXTERNAL_MCP_URL |
https://<votre-hote-api-external>/mcp |
KEYCLOAK_TOKEN_URL |
l'endpoint de jeton de votre serveur d'autorisation — publié, avec les scopes qu'il accepte, sur GET /.well-known/oauth-protected-resource du même hôte : inutile de le deviner |
PARTNER_CLIENT_ID · PARTNER_CLIENT_SECRET |
les identifiants partenaire qui vous ont été remis |
Il n'y a rien à déclarer sur les scopes : ceux accordés à votre application sont portés par vos identifiants et entrent dans le jeton sans être réclamés. C'est aussi ce qui fera survivre votre configuration le jour où un administrateur modifiera ce que votre intégration a le droit de lire.
Un réglage ne sert qu'en développement local : NODE_TLS_REJECT_UNAUTHORIZED: "0", présent dans le modèle
sous forme de ligne commentée (#) que vous ne décommentez que face à un certificat de développement
auto-signé. Node ne lit pas le magasin de certificats du système, donc faire confiance à un certificat de
développement au niveau du système ne suffit pas à le lui faire accepter. Face à un hôte avec un vrai
certificat, laissez-la commentée.
Le fichier est en clé: valeur plat — le lecteur refuse l'imbrication et les listes plutôt que de les
mal lire.
Claude Desktop
Quatre étapes :
Node 20 ou supérieur.
node --versionvous indique ce qui est installé.Téléchargez votre
config.ymldepuis Staffngo : Applications (API), dans le dialogue du secret de votre application, bouton Télécharger la configuration MCP (config.yml). Il contient déjà les quatre valeurs.Téléchargez les scripts (tableau ci-dessus) dans le même dossier que
config.yml, puis lancez l'installeur :./install.sh # macOS / Linux .\install.ps1 # Windows (PowerShell)Sous Windows, si PowerShell refuse d'exécuter
install.ps1(politique d'exécutionRestricted, ou invite « éditeur non approuvé »), lancez à la placenode install.mjs: Node n'est pas soumis à cette politique, et c'est exactement le même installeur.Quittez Claude Desktop complètement — depuis la zone de notification, pas seulement la fenêtre — puis relancez-le. La configuration n'est relue qu'au démarrage. Le connecteur apparaît sous le nom
staffngo.
L'installeur copie le proxy à côté de la configuration de Claude et fusionne une seule entrée dans
claude_desktop_config.json, en conservant toutes les autres clés et tous les autres serveurs. Il sauvegarde
le fichier au préalable (.bak-<horodatage>), et --dry-run montre exactement ce qui changerait sans rien
écrire.
Sans config.yml, l'installeur écrit un modèle à côté de lui, vous l'indique et s'arrête sans erreur :
remplacez-le par le fichier téléchargé (ou renseignez les quatre valeurs), puis relancez-le. C'est un repli,
pas une étape du parcours.
Vous aviez déjà installé le MCP ? L'ancienne entrée external n'est pas renommée par l'installeur.
Supprimez-la à la main de claude_desktop_config.json (une sauvegarde .bak-<horodatage> est faite à chaque
écriture), puis relancez l'installeur. Pour enregistrer plusieurs environnements côte à côte, donnez un nom
à chacun avec --name — par exemple --name staffngo-staging --config config.staging.yml.
Pour le faire à la main, le fichier se trouve ici :
| Plateforme | Chemin |
|---|---|
| Windows — version Store (MSIX) | %LOCALAPPDATA%\Packages\Claude_*\LocalCache\Roaming\Claude\ |
| Windows — installeur classique | %APPDATA%\Claude\ |
| macOS | ~/Library/Application Support/Claude/ |
| Linux | ~/.config/Claude/ |
La version Store est un paquet MSIX, et MSIX redirige %APPDATA% — sa configuration n'est donc jamais
sous %APPDATA%\Claude, ce qui explique qu'on ne trouve rien en cherchant là. Le dossier n'apparaît qu'après
un premier lancement de Claude Desktop.
Claude Code
Claude Code lit .mcp.json à la racine du projet, sous une clé mcpServers :
{
"mcpServers": {
"staffngo": {
"command": "node",
"args": ["/chemin/absolu/vers/mcp-stdio-proxy.mjs"],
"env": {
"EXTERNAL_MCP_URL": "https://<votre-hote-api-external>/mcp",
"KEYCLOAK_TOKEN_URL": "https://<votre-serveur-autorisation>/realms/<realm>/protocol/openid-connect/token",
"PARTNER_CLIENT_ID": "<votre client id>",
"PARTNER_CLIENT_SECRET": "<votre secret client>"
}
}
}
}
.mcp.json est committé par convention : mettez plutôt un fichier contenant un secret dans votre
configuration non suivie.
VS Code
VS Code lit .vscode/mcp.json, dont les serveurs vivent sous une clé servers et non mcpServers. Le
triplet command / args / env est identique au bloc ci-dessus. Vérifiez le schéma exact dans la
documentation de votre version de VS Code — il a changé plus d'une fois.
Tout autre client stdio
Tout ce qui précède, ce sont les trois mêmes valeurs dans des emballages différents. Quel que soit le nom que votre client donne à sa configuration, il lui faut :
- command — le chemin absolu de votre exécutable
node - args — le chemin absolu de
mcp-stdio-proxy.mjs - env — les quatre réglages de
config.yml
Utilisez des chemins absolus. Votre client démarre le process lui-même, hors de tout shell qui résoudrait un chemin relatif, un lien symbolique ou un alias.
Si le serveur n'apparaît pas, le proxy écrit ses diagnostics ([mcp-proxy] …) sur stderr, jamais sur
stdout qui porte le flux JSON-RPC. Cherchez-les dans les journaux de votre client.
La seule chose qui vous coûtera une après-midi
Ne déclarez aucun scope côté client. Les scopes accordés à votre application sont portés par vos
identifiants et entrent dans le jeton d'eux-mêmes : il n'y a rien à lister dans config.yml ni dans la
configuration de votre client. Un outil dont votre jeton n'a pas les scopes est absent de tools/list —
vous n'obtenez aucun refus qui l'expliquerait, vous ne voyez simplement jamais l'outil. Si un agent vous dit
qu'une capacité n'existe pas, vérifiez d'abord dans Staffngo, menu Applications (API), les scopes accordés à votre
application.
S'en servir dans un chat
Vous n'appelez pas les outils vous-même — vous demandez en langage naturel et l'agent choisit. Commencez par lui faire dire ce qu'il a, ce qui vaut aussi comme test que vos scopes sont bien passés :
Quels outils te donne le connecteur staffngo ? Liste-les avec ce que fait chacun.
Ensuite, demandez la chose, pas l'outil :
| Ce que vous tapez | Ce qu'il va chercher |
|---|---|
| À quoi mon accès partenaire a-t-il droit ? Quels modules sont actifs ? | le profil partenaire |
| Liste les types de congé disponibles. | une lecture de référentiel |
| Donne-moi les dix premiers salariés, avec leur fonction et leur manager. | la liste des salariés |
| Prends le premier et montre-moi ses contrats de travail. | les contrats de ce salarié |
| Quelles absences entre le 1er et le 30 septembre ? | les lignes de congé, avec une fenêtre de dates |
| Et ses soldes de congés ? | les soldes de ce salarié |
| Montre-moi la trace d'audit de ce que tu viens de faire. | la piste d'audit |
Le chaînage est là que c'est le plus utile. Les identifiants sont opaques : vous ne pouvez pas en taper un de mémoire. Le flux naturel est donc liste → « prends celui-là » → détail, et l'agent reporte l'identifiant tout seul. C'est la séquence qu'une intégration doit exécuter de toute façon ; le chat la rend simplement confortable.
Trois choses ressembleront à des pannes sans en être :
- Un champ à
nullnommé dans une envelopperestrictedest une réponse délibérée, pas un échec. Demandez ce qui a été caviardé et pourquoi — le motif est dans la charge utile. - Un outil absent plutôt qu'un refus. Si l'agent vous dit qu'une capacité n'existe pas, le scope manque très probablement à votre jeton, et l'outil ne lui a donc jamais été présenté. Vérifiez les scopes d'abord.
- Les écritures antérieures à l'API partenaire ne sont jamais exposées en outils, quel que soit votre jeton. Un agent ne peut pas les déclencher.
Une mise en garde à dire franchement : ces réponses portent des données personnelles, et dans un chat elles entrent dans la conversation et y restent. Pour montrer la forme d'une réponse à quelqu'un, préférez une ligne de test à un vrai dossier.
Nommage des outils et versions
Les noms d'outils sont stables et portent leur version dès qu'il en existe plusieurs —
get_partner_profile et get_partner_profile_v2 sont deux outils distincts, aux contrats distincts.
Épinglez celui que vous visez ; un nom ne change jamais de sens en silence.
Indications de sûreté
Chaque outil déclare ce qu'il fait, pour qu'un framework d'agent puisse décider s'il faut demander à un humain d'abord :
| Indication | Signification |
|---|---|
ReadOnly |
Ne modifie rien. |
Idempotent |
Répéter l'appel a le même effet que l'appeler une fois. |
Destructive |
Produit un effet qui ne se défait pas trivialement. |
OpenWorld |
Touche un état au-delà de cette API. |
Servez-vous-en. Un outil marqué Destructive est un outil où la boucle de réessai d'un agent a des
conséquences réelles : exigez une confirmation humaine, et envoyez un Idempotency-Key pour qu'un réessai ne
puisse pas doubler l'effet. Voir Idempotence.
Quota
Les appels MCP et les appels REST partagent un seul compteur par tenant. Un agent qui interroge en boucle
consomme le budget dont votre intégration a aussi besoin, et les en-têtes RateLimit s'appliquent de la même
manière — voir Limites de débit.