Connecteur d'assistant IA (MCP) Module

Vaks PM · Guide d'intégration · MCP · Juillet 2026

Ce que vous obtiendrez. Des utilisateurs connectant un assistant IA — Claude, ChatGPT, Copilot Studio — à Vaks PM, pour qu'il puisse lire leurs projets et, si vous l'autorisez, agir en leur nom. L'assistant se connecte en tant que l'utilisateur et ne peut jamais faire plus que ce que l'utilisateur pourrait faire. Il est opt-in par organisation et désactivé tant que vous ne l'activez pas.

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é.

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 :

Les droits d'un assistant sont vos droits, intersectés avec ce que l'admin a autorisé — jamais plus. L'ensemble des permissions effectives est le rôle propre de l'utilisateur, restreint par les scopes du connecteur, restreint encore par les bascules lecture/écriture et finance. Un membre de base connectant un assistant ne peut atteindre rien qu'un membre de base ne puisse déjà atteindre. Il n'existe aucun moyen pour la connexion d'élever ses privilèges.

Concrètement, trois interrupteurs contrôlés par un administrateur décident du plafond :

BasculeDésactivée (défaut)Activée
Activer le connecteur IAPersonne ne peut se connecter ; le consentement est refusé.Les utilisateurs peuvent se connecter et s'authentifier.
Autoriser les actions d'écriture de l'IALecture seule : l'assistant observe et suggère.Les outils d'écriture apparaissent, bornés par les droits de chaque utilisateur.
Exposer la finance à l'IABudgets, 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
LicenceUne licence incluant le connecteur IA (MCP). Sans elle, la section affiche un avis de fonctionnalité premium et les bascules sont désactivées.
Vaks PMorg:manage pour l'activer et le configurer. Les utilisateurs individuels n'ont besoin que de leur compte habituel pour se connecter.
L'assistantUn 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).

  1. Activez Activer le connecteur IA (MCP).
  2. 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.
  3. Décidez de Exposer la finance à l'IA. Laissez désactivé, sauf si vous voulez spécifiquement que les assistants lisent les chiffres financiers.
  4. Copiez l'URL du serveur MCP affichée dans la première carte — c'est ce que les utilisateurs collent dans leur assistant.
Il n'y a rien de plus à configurer pour la connexion. MCP réutilise votre authentification existante — comptes locaux et tout SSO que vous avez mis en place. Les utilisateurs se connectent exactement comme pour l'application web. Si vous utilisez le SSO, la connexion MCP passe aussi par lui.
La temporisation des bascules a une subtilité. Les accès en écriture et à la finance sont décidés au moment où un utilisateur se connecte. Activer les écritures ne les accorde pas rétroactivement aux assistants déjà connectés tant qu'ils ne se rafraîchissent pas ; désactiver les écritures met jusqu'à une heure à disparaître d'une connexion existante. La finance, en revanche, est vérifiée en direct à chaque requête. Si vous devez couper les écritures immédiatement, déconnectez les connexions (voir gérer les connexions) plutôt que de seulement basculer l'interrupteur.

É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 :

  1. L'assistant envoie l'utilisateur vers Vaks PM pour s'authentifier (local ou SSO).
  2. L'utilisateur voit un écran de consentement indiquant exactement ce que l'assistant pourra faire.
  3. À 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 :

  1. Donnez-lui un Nom.
  2. Collez l'URL de rappel du connecteur que vous construisez — pour Power Platform, elle ressemble à https://global.consent.azure-apim.net/redirect/...
  3. 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.

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 :

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.

L'URL affichée dans l'écran d'administration suppose que le point de terminaison est servi sur l'adresse propre du tenant. Si votre opérateur a exposé MCP sur un nom d'hôte distinct — une configuration durcie le place souvent sur <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 :

La suite s'adresse à l'opérateur qui exploite les serveurs — pas à l'administrateur du tenant. Le serveur MCP se déploie comme un conteneur à part, avec son propre fichier 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.

PointDé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 boxElle 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 sortantDe 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ôteUn 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 applicatifIndé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'autorisationVAKS_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

Toutes les commandes de cette section — et des options A à C ci-dessous — se lancent directement sur le serveur qui hébergera le MCP (la box DMZ, ou un hôte interne), connecté en SSH. Il n'y a pas de poste de pilotage : cet hôte a Docker, puisqu'il fait tourner le conteneur.

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
Cet hôte ne peut pas construire ? (dépôt indisponible, ou chaîne de build à garder hors DMZ) — construisez l'image ailleurs, exportez-la avec 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.

Internet ──443──► [DMZ · Traefik]──┬─ /mcp, /.well-known/oauth-protected-resource → mcp (local) └─ /oauth, /login, /oauth-consent, /assets, ─443─► API interne /.well-known/oauth-authorization-server (seul flux sortant)

Prérequis, à fournir par l'opérateur :

ÉlémentDétail
Hôte DMZDocker + 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 publicWildcard *.mcp.vaks-pm.comcerts/mcp-wildcard.{crt,key}.
CA interneSi l'edge interne est en cert auto-signé : certs/internal-ca.crt (sinon retirer NODE_EXTRA_CA_CERTS + insecureSkipVerify).
Pare-feuInternet → 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
Une fois ces trois vérifications vertes, brancher le connecteur côté client IA (Claude / ChatGPT / Copilot Studio) sur 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.

« Edge interne » = simplement l'URL où le conteneur MCP joint l'API (la variable 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 service worker utilise déjà (INTERNAL_API_URL: http://api:3000 dans docker-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 le INTERNAL_EDGE_URL de 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).
Quel que soit ce réglage, le MCP transmet l'identité du tenant dans un en-tête 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.

Dans ce mode, l'URL du panneau d'administration est correcte telle qu'affichée — le point de terminaison est servi sur l'adresse propre du tenant. C'est le seul cas où l'on peut remettre aux utilisateurs l'URL du panneau sans la corriger.

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.

Les justifications sont encouragées, pas imposées. Le connecteur demande aux assistants d'expliquer chaque écriture, et les mieux élevés le font. Mais le champ est facultatif : une écriture peut donc réussir sans. Traitez sa présence comme un contexte utile, pas comme une garantie.

Dépannage

SymptômeCause & correctif
L'assistant ne peut pas joindre le serveur du toutPresque 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'approbationLe connecteur est désactivé. Activez-le dans la section d'administration.
L'assistant n'offre que des outils de lectureLes é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 disparuUne 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'assistantAttendu, 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 assistantLes 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 connecterIl 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.