Connecteur d'assistant IA (MCP) Module
Ce que ça fait — et ce que ça ne fait pas
MCP (Model Context Protocol) est une façon standard pour un assistant IA d'appeler un outil externe. Vaks PM expose un serveur MCP pour qu'un assistant puisse interroger et mettre à jour l'espace de travail au nom d'un utilisateur connecté.
- L'assistant agit en tant que personne, pas en son nom propre. L'utilisateur se connecte via sa connexion habituelle — mot de passe local ou votre SSO. L'assistant opère ensuite strictement dans les limites des droits de cet utilisateur.
- Lecture par défaut, écriture uniquement si vous l'autorisez. D'emblée, l'assistant peut observer et suggérer. Les outils d'écriture n'apparaissent que lorsqu'un administrateur les active.
- La finance est gardée séparément. Les données financières restent invisibles aux assistants tant que vous ne les exposez pas délibérément, même pour un utilisateur qui les voit dans le navigateur.
- Chaque action est attribuée. Une action MCP est enregistrée comme action d'agent dans le journal d'audit, distincte de la même personne cliquant dans le navigateur, et porte la raison donnée par l'assistant.
- C'est un module premium. Il nécessite une licence incluant le connecteur IA, et la bascule par organisation en plus.
Le modèle de permissions
C'est la partie rassurante, et il vaut la peine de l'énoncer clairement à quiconque est inquiet à l'idée de connecter une IA à ses données de projet :
Concrètement, trois interrupteurs contrôlés par un administrateur décident du plafond :
| Bascule | Désactivée (défaut) | Activée |
|---|---|---|
| Activer le connecteur IA | Personne ne peut se connecter ; le consentement est refusé. | Les utilisateurs peuvent se connecter et s'authentifier. |
| Autoriser les actions d'écriture de l'IA | Lecture seule : l'assistant observe et suggère. | Les outils d'écriture apparaissent, bornés par les droits de chaque utilisateur. |
| Exposer la finance à l'IA | Budgets, marges et taux sont invisibles aux assistants. | La finance est lisible, toujours uniquement pour les utilisateurs qui ont déjà l'accès finance. |
Prérequis
| Côté | Ce qu'il vous faut |
|---|---|
| Licence | Une licence incluant le connecteur IA (MCP). Sans elle, la section affiche un avis de fonctionnalité premium et les bascules sont désactivées. |
| Vaks PM | org:manage pour l'activer et le configurer. Les utilisateurs individuels n'ont besoin que de leur compte habituel pour se connecter. |
| L'assistant | Un client compatible MCP. Claude et ChatGPT s'enregistrent seuls ; Copilot Studio et Power Platform nécessitent un client pré-enregistré — voir l'étape 3. |
| Joignabilité | L'assistant est un service cloud : il doit donc pouvoir joindre votre point de terminaison MCP. Pour une instance privée, cela demande une exposition délibérée — voir y accéder depuis l'extérieur. |
Étape 1 — Activer et cadrer
Ouvrez Admin → Intégrations → Connecteurs IA (MCP).
- Activez Activer le connecteur IA (MCP).
- Décidez de Autoriser les actions d'écriture de l'IA. Commencez en lecture seule. Vous pourrez activer les écritures plus tard, une fois que vous aurez vu comment les assistants sont utilisés.
- Décidez de Exposer la finance à l'IA. Laissez désactivé, sauf si vous voulez spécifiquement que les assistants lisent les chiffres financiers.
- Copiez l'URL du serveur MCP affichée dans la première carte — c'est ce que les utilisateurs collent dans leur assistant.
Étape 2 — Connecter un assistant
Un utilisateur ajoute Vaks PM comme connecteur personnalisé dans son assistant et colle l'URL du serveur MCP. L'assistant découvre seul comment s'authentifier et ouvre un flux de connexion :
- L'assistant envoie l'utilisateur vers Vaks PM pour s'authentifier (local ou SSO).
- L'utilisateur voit un écran de consentement indiquant exactement ce que l'assistant pourra faire.
- À l'approbation, l'assistant reçoit un jeton d'accès à courte durée de vie et peut commencer à travailler.
Claude et ChatGPT gèrent cela de bout en bout, sans configuration de votre côté au-delà de l'activation du connecteur. La connexion est un OAuth standard avec PKCE ; les jetons d'accès durent une heure et se rafraîchissent automatiquement.
Étape 3 — Clients pré-enregistrés (Copilot Studio, Power Platform)
Certaines plateformes ne s'enregistrent pas automatiquement. Pour celles-ci, créez un client à l'avance, sous Clients OAuth pré-enregistrés dans la même section :
- Donnez-lui un Nom.
- Collez l'URL de rappel du connecteur que vous construisez — pour Power Platform, elle ressemble à
https://global.consent.azure-apim.net/redirect/... - Pressez Créer le client. Le secret client est affiché une fois — copiez-le immédiatement, il n'est jamais réaffiché.
Claude et ChatGPT n'en ont pas besoin ; ils s'enregistrent seuls.
L'écran de consentement
Chaque connexion passe par un écran de consentement pour que l'utilisateur voie, et approuve, exactement ce qu'il accorde. Il affiche le nom de votre organisation, le compte sous lequel il est connecté, et une liste à puces de ce que l'assistant pourra faire — consulter les projets et tâches, consulter la charge et les rapports, éventuellement consulter la finance, et, quand les écritures sont activées, une ligne en évidence sur la création et la modification en son nom. Il se termine par l'assurance que l'assistant ne peut pas dépasser les propres droits de l'utilisateur.
Si le connecteur est désactivé au moment du consentement, l'écran le signale et n'offre aucun bouton d'approbation — la connexion ne peut pas aboutir.
Gérer les connexions
Deux vues vous permettent de voir et de couper les connexions :
- Administrateurs : Admin → Sécurité → Connexions actives → Connexions IA liste l'assistant connecté de chaque utilisateur — qui, quel client, dernière utilisation — avec un bouton Déconnecter. La déconnexion est immédiate : le jeton à courte durée de vie est révoqué, pas laissé à expirer.
- Chaque utilisateur : ses propres réglages Sécurité listent ses connexions IA avec la même déconnexion en libre-service.
Suspendre ou supprimer un utilisateur coupe aussi ses connexions automatiquement.
Y accéder depuis l'extérieur
Les assistants cloud doivent joindre votre point de terminaison MCP par Internet. La façon dont vous l'exposez est un choix de déploiement, et elle change l'URL — ce qui est le point de confusion le plus fréquent.
<tenant>.mcp.<domain> derrière une passerelle isolée — alors l'adresse à remettre aux utilisateurs est celle-là, pas celle qu'affiche le panneau d'administration. Confirmez auprès de qui a déployé l'instance quel nom d'hôte répond réellement, et partagez-le. Se tromper là-dessus est la raison habituelle de l'échec d'une première connexion.
Trois topologies, détaillées pas à pas plus bas :
- Assistants sur Internet, instance privée — un opérateur publie MCP à travers une passerelle isolée qui ne détient aucun secret et n'a aucun accès à la base de données. C'est la disposition durcie recommandée pour exposer une instance interne. Voir Option A.
- Assistants et instance sur le même réseau — aucune passerelle distincte nécessaire ; le point de terminaison est servi sur l'adresse du tenant et l'URL du panneau d'administration est correcte telle qu'affichée. Voir Option B.
- Aucun flux OAuth du tout — un utilisateur crée un jeton API personnel scopé à l'accès MCP dans ses réglages de compte et le colle dans le connecteur. Le plus simple pour un unique utilisateur avancé ; pas de connexion navigateur. Voir Option C.
docker compose ; il ne fait pas partie de la stack applicative Swarm ou Kubernetes. Les étapes ci-dessous montrent comment le construire, où le placer, et comment il se rattache à une instance Vaks PM déjà en service.
Comment le serveur MCP se relie à une instance existante
Le conteneur MCP est délibérément « pauvre » : il ne détient aucun secret, ne parle à aucune base de données, et n'applique aucune règle lui-même. Il reçoit le jeton du client IA et le relaie à l'API interne de votre instance, qui valide tout — PKCE, écran de consentement, gating de licence, RBAC, limitation de débit. Autrement dit, on ajoute une porte d'entrée ; on ne déplace ni ne duplique aucune donnée.
| Point | Détail |
|---|---|
| Conteneur séparé | Image vaks-pm/mcp:latest, déployée par son propre docker compose (infra/dmz/) — jamais mêlée à la stack api/web/worker. |
| Zéro secret sur la box | Elle ne stocke rien de sensible. Toute la sécurité (PKCE, consentement, licence, RBAC, rate-limit) est appliquée par l'API interne, jamais par le MCP. |
| Un seul flux sortant | De la box vers l'API interne en :443, sur un ensemble de chemins borné (allow-list Traefik : /mcp local, surface d'auth forwardée). Tout le reste de l'app reste injoignable via cette porte. |
| Nommage d'hôte | Un tenant est joint sur <slug>.mcp.<domaine>. Un seul certificat wildcard *.mcp.<domaine> couvre tous les tenants : le label mcp est retiré pour reconstituer le Host tenant (<slug>.<domaine>) passé à l'API. |
| Prérequis applicatif | Indépendant du déploiement : le tenant doit avoir activé le connecteur (mcp.enabled, étape 1) et la licence doit inclure la feature mcp. Sinon l'API n'émet aucun jeton (403), quelle que soit la topologie. |
| Mode serveur d'autorisation | VAKS_AUTH_SERVER_MODE=self en DMZ (l'AS annoncé aux clients IA = la box, qui forwarde l'auth vers l'interne) ; =tenant en interne (l'AS = l'adresse du tenant, jointe directement). |
Obtenir l'image MCP sur cet hôte
Le plus simple est de construire l'image sur place, depuis une copie du dépôt. Le Dockerfile MCP attend la racine du dépôt comme contexte de build. Aucun registry n'est requis.
# On the MCP host: get a copy of the repository, then build from its root
git clone <repo-url> vakspm && cd vakspm
sudo docker build -t vaks-pm/mcp:latest -f mcp/Dockerfile .
sudo docker image ls vaks-pm/mcp # check: the image is present
docker save -o mcp.tar vaks-pm/mcp:latest, copiez le fichier mcp.tar ainsi que le dossier infra/dmz/ sur cet hôte, puis importez l'image localement :
# On the MCP host, after copying mcp.tar here
sudo docker load -i mcp.tar
Option A — Passerelle DMZ isolée durci
La disposition recommandée pour exposer une instance privée à des assistants cloud. Une box de DMZ, qui ne rejoint pas l'overlay Swarm interne, publie /mcp à Internet et forwarde la surface d'auth (OAuth + connexion + consentement) vers l'API on-premise. L'API interne n'est jamais joignable directement depuis Internet.
Prérequis, à fournir par l'opérateur :
| Élément | Détail |
|---|---|
| Hôte DMZ | Docker + Docker Compose. Hors du Swarm interne. |
| DNS public | *.mcp.vaks-pm.com → IP publique de la box DMZ. |
| DNS interne (split-horizon) | internal.vaks-pm.com → Traefik on-prem, résolu depuis la DMZ. |
| Cert TLS public | Wildcard *.mcp.vaks-pm.com → certs/mcp-wildcard.{crt,key}. |
| CA interne | Si l'edge interne est en cert auto-signé : certs/internal-ca.crt (sinon retirer NODE_EXTRA_CA_CERTS + insecureSkipVerify). |
| Pare-feu | Internet → DMZ:443 et DMZ → internal.vaks-pm.com:443 UNIQUEMENT. Aucun accès base de données / Redis / overlay. |
Toujours connecté en SSH sur la box DMZ :
1 · Obtenir l'image — construire ou importer vaks-pm/mcp:latest sur cet hôte (voir obtenir l'image sur cet hôte ci-dessus).
2 · Configurer la box — dans le dossier infra/dmz/ du dépôt cloné sur cet hôte :
cd infra/dmz
cp .env.example .env # edit INTERNAL_EDGE_URL to your split-horizon internal edge
mkdir -p certs
# certs/mcp-wildcard.crt certs/mcp-wildcard.key public *.mcp.vaks-pm.com cert
# certs/internal-ca.crt internal edge CA (only if self-signed)
Le docker-compose.yml fixe les variables clés : VAKS_API_URL (= INTERNAL_EDGE_URL), VAKS_API_PREFIX=api/v1, VAKS_MCP_LABEL=mcp et VAKS_AUTH_SERVER_MODE=self. En principe, seul INTERNAL_EDGE_URL est à éditer.
3 · Démarrer :
docker compose up -d
docker compose logs -f mcp
4 · Vérifier — depuis Internet (remplacer demo par un slug de tenant réel) :
# Resource metadata (served locally by mcp) — resource + authorization_servers = self
curl -sk https://demo.mcp.vaks-pm.com/.well-known/oauth-protected-resource | jq
# AS discovery (forwarded to the internal API, URLs rewritten to the public host)
curl -sk https://demo.mcp.vaks-pm.com/.well-known/oauth-authorization-server | jq
# POST /mcp with no token → 401 + WWW-Authenticate pointing at resource_metadata
curl -ski -X POST https://demo.mcp.vaks-pm.com/mcp -d '{}' | grep -i www-authenticate
https://<slug>.mcp.vaks-pm.com/mcp : le client découvre l'AS, lance la connexion (forwardée vers l'app interne), obtient son jeton et appelle les tools. C'est ce nom d'hôte (pas l'URL du panneau d'administration) que vous remettez aux utilisateurs.
Option B — Interne / co-localisé même réseau
Si les clients IA joignent déjà l'instance sans passer par Internet, aucune box DMZ n'est nécessaire : on fait tourner la même image MCP à côté de l'API, sur le réseau overlay Swarm, et l'AS est annoncé directement sur l'adresse du tenant.
VAKS_API_URL), depuis là où il tourne. Ce n'est pas une valeur à retrouver ailleurs ; elle dépend de l'emplacement du MCP :
- Sur le même overlay Swarm que l'API (co-localisé) → le nom de service interne :
http://api:3000. C'est exactement la valeur que le serviceworkerutilise déjà (INTERNAL_API_URL: http://api:3000dansdocker-stack.yml). Pas de TLS ni de Traefik sur ce saut — on est dans l'overlay. En Kubernetes, l'équivalent est le Service de l'API dans le namespace :http://<release>-api:3000. - Sur un hôte séparé / en DMZ → le MCP ne peut pas joindre
api:3000(overlay uniquement), il passe donc par le Traefik interne via un nom résolu en split-horizon, ex.https://internal.vaks-pm.com— c'est leINTERNAL_EDGE_URLde l'Option A. Ce nom, c'est vous qui le choisissez : il doit résoudre vers le Traefik on-prem qui sert déjà l'app (IP du manager, ou VIP).
Host explicite (le host tenant, label mcp retiré), donc l'API résout le bon tenant en mode pooled indépendamment de l'URL de connexion.
Sur Docker Swarm — ajouter un service mcp à la stack, sur l'overlay de l'API, avec VAKS_AUTH_SERVER_MODE=tenant :
mcp:
image: vaks-pm/mcp:latest
networks: [vakspm] # the same overlay the `api` service is on
environment:
VAKS_API_URL: http://api:3000 # the API service on the overlay (same value the worker uses)
VAKS_API_PREFIX: api/v1
VAKS_AUTH_SERVER_MODE: tenant # the authorization server IS the tenant's own address
deploy:
labels:
- traefik.enable=true
- "traefik.http.routers.mcp.rule=PathPrefix(`/mcp`) || PathPrefix(`/.well-known/oauth-protected-resource`)"
- traefik.http.routers.mcp.priority=100 # beat the per-tenant catch-all on these two paths
- traefik.http.services.mcp.loadbalancer.server.port=8080
Ce routeur détourne /mcp (et les métadonnées RFC 9728) vers le conteneur MCP sur n'importe quel host tenant ; le Host entrant (ex. demo.vaks-pm.com) est préservé, et un seul service MCP sert tous les tenants. On réutilise le certificat existant de l'instance — aucun wildcard *.mcp ni cert séparé.
Sur Kubernetes — le chart Helm ne template pas (encore) le MCP : on applique les manifestes à côté, dans le même namespace que la release. Un Deployment + Service pour l'image, plus des chemins d'Ingress qui envoient /mcp vers ce Service sur le host tenant. Même logique qu'en Swarm : VAKS_API_URL pointe le Service de l'API du namespace, VAKS_AUTH_SERVER_MODE=tenant.
apiVersion: apps/v1
kind: Deployment
metadata: { name: mcp }
spec:
replicas: 2
selector: { matchLabels: { app: mcp } }
template:
metadata: { labels: { app: mcp } }
spec:
containers:
- name: mcp
image: vaks-pm/mcp:latest # your registry / tag
ports: [{ containerPort: 8080 }]
env:
- { name: VAKS_API_URL, value: "http://<release>-api:3000" } # the API Service in this namespace
- { name: VAKS_API_PREFIX, value: "api/v1" }
- { name: VAKS_AUTH_SERVER_MODE, value: "tenant" }
---
apiVersion: v1
kind: Service
metadata: { name: mcp }
spec:
selector: { app: mcp }
ports: [{ name: http, port: 8080, targetPort: 8080 }]
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata: { name: mcp }
spec:
ingressClassName: nginx # same class as the chart Ingress
tls:
- hosts: ["demo.vaks-pm.com"]
secretName: vaks-pm-tls # same TLS Secret as the chart Ingress
rules:
- host: demo.vaks-pm.com # the tenant host
http:
paths:
- path: /mcp
pathType: Prefix
backend: { service: { name: mcp, port: { number: 8080 } } }
- path: /.well-known/oauth-protected-resource
pathType: Prefix
backend: { service: { name: mcp, port: { number: 8080 } } }
Trouver le nom exact du Service de l'API : kubectl get svc -l app.kubernetes.io/component=api (typiquement <release>-api). Reprendre la même ingressClassName et le même secretName TLS que l'Ingress du chart ; le chemin /mcp l'emporte sur / (préfixe plus spécifique), donc il n'y a pas de conflit avec le routage existant. Un seul déploiement MCP sert tous les tenants : ajouter un host: par tenant à exposer.
Option C — Jeton statique, sans OAuth
Si le serveur d'autorisation doit rester strictement interne, ou pour un unique utilisateur avancé, on peut se passer complètement du flux OAuth : l'utilisateur crée un jeton API personnel scopé mcp:access dans ses réglages de compte et le colle dans le connecteur. Aucune connexion navigateur, aucune surface d'auth à forwarder. Le jeton reste soumis au même gating (licence + mcp.enabled) et aux mêmes droits que l'utilisateur.
Ce qui est journalisé
Chaque action MCP est attribuée comme action d'agent dans le journal d'audit — délibérément distinguée de la même personne agissant dans le navigateur, et d'un simple script utilisant le même jeton. Chaque écriture porte aussi la justification fournie par l'assistant, une raison d'une ligne pour l'action. La trace d'audit vous dit donc non seulement ce qui a changé, mais qu'un assistant l'a fait, au nom de qui, et pourquoi. Les connexions elles-mêmes sont visibles et révocables comme ci-dessus.
Dépannage
| Symptôme | Cause & correctif |
|---|---|
| L'assistant ne peut pas joindre le serveur du tout | Presque toujours l'URL : dans un déploiement à passerelle, l'URL du panneau d'administration n'est pas l'URL publique. Confirmez le vrai nom d'hôte avec votre opérateur. Vérifiez aussi que l'assistant, un service cloud, peut la joindre par Internet. |
| L'écran de consentement refuse, aucun bouton d'approbation | Le connecteur est désactivé. Activez-le dans la section d'administration. |
| L'assistant n'offre que des outils de lecture | Les écritures sont désactivées, ou la connexion précède leur activation. Activez Autoriser les actions d'écriture de l'IA ; les connexions existantes le prennent en compte à leur prochain rafraîchissement, une reconnexion est donc le correctif rapide. |
| Les écritures fonctionnaient, puis ont brièvement disparu | Une perte de contact passagère avec l'API fait retomber la session en lecture seule au lieu de produire une erreur. Elle se rétablit d'elle-même. Une perte persistante mérite une vérification avec votre opérateur. |
| La finance est invisible à l'assistant | Attendu, sauf si Exposer la finance à l'IA est activé — et même alors, uniquement pour les utilisateurs qui ont déjà l'accès finance. |
| L'utilisateur voit du texte d'erreur en français dans son assistant | Les descriptions d'outils destinées à l'assistant et certains messages d'exécution sont en français dans cette version, tandis que les écrans d'administration et de consentement sont en anglais. C'est cosmétique ; le comportement n'est pas affecté. |
| Copilot Studio ne peut pas se connecter | Il ne s'enregistre pas seul. Créez un client pré-enregistré et utilisez son URL de rappel, selon l'étape 3. |
À lire aussi : authentification unique OIDC, réutilisée pour la connexion MCP · produit & fonctionnalités pour le modèle de gouvernance des agents · toutes les intégrations.