Aller au contenu principal
Page traduite

Cette page a été traduite de l'anglais avec l'aide de l'IA. En cas de divergence, la version anglaise fait référence.

mcp

Commande utilisée pour lancer StackQL en tant que serveur Model Context Protocol (MCP), ce qui permet aux agents et assistants IA d'interagir avec l'infrastructure cloud à l'aide des capacités de requête de StackQL.

Qu'est-ce que MCP ?

Le Model Context Protocol (MCP) est un protocole ouvert qui standardise la manière dont les applications d'IA interagissent avec les sources de données et les outils externes. En exécutant StackQL en tant que serveur MCP, vous permettez aux agents IA (Claude, Cursor, Continue, agents personnalisés, etc.) d'interroger et de gérer l'infrastructure cloud de plusieurs providers en langage naturel.


Syntaxe​

stackql mcp [flags] pour un serveur MCP autonome.

stackql srv [flags] pour exécuter le serveur MCP aux côtés du serveur de protocole filaire PostgreSQL dans le même processus.


Modes de déploiement​

Le serveur MCP de StackQL peut être déployé dans trois configurations différentes pour répondre à diverses exigences d'architecture. Les exemples ci-dessous activent explicitement le service sans authentification avec "allow_unauthenticated": true, ce qui convient au développement local ; pour tout ce qu'un autre processus ou un autre hôte peut atteindre, configurez plutôt un jeton bearer (voir Authentification des clients HTTP).

1. Serveur MCP autonome​

Exécutez StackQL en tant que serveur MCP dédié sur un port donné.

stackql mcp \
--mcp.server.type=http \
--mcp.config '{"server": {"transport": "http", "address": "127.0.0.1:9912", "allow_unauthenticated": true}}'

Cas d'utilisation : lorsque vous avez uniquement besoin d'un accès par le protocole MCP et que la compatibilité avec le protocole filaire PostgreSQL n'est pas nécessaire.

2. Serveur MCP + PostgreSQL (en mémoire)​

Exécutez simultanément les serveurs MCP et PostgreSQL, avec une communication en mémoire entre eux.

stackql srv \
--mcp.server.type=http \
--mcp.config '{"server": {"transport": "http", "address": "127.0.0.1:9912", "allow_unauthenticated": true}}' \
--pgsrv.port 5665

Cas d'utilisation : lorsque vous avez besoin à la fois d'un accès par le protocole MCP pour les agents IA et du protocole filaire PostgreSQL pour les clients de base de données traditionnels, avec des performances maximales grâce à la communication en mémoire.

3. Serveur MCP + PostgreSQL (proxy inverse)​

Exécutez les deux serveurs avec une communication TCP, ce qui prend en charge les déploiements distribués et le chiffrement TLS.

stackql srv \
--mcp.server.type=reverse_proxy \
--mcp.config '{"server": {"transport": "http", "address": "127.0.0.1:9004", "allow_unauthenticated": true}, "backend": {"dsn": "postgres://stackql:stackql@127.0.0.1:5446?default_query_exec_mode=simple_protocol"}}' \
--pgsrv.port 5446

Avec chiffrement TLS :

stackql srv \
--mcp.server.type=reverse_proxy \
--mcp.config '{"server": {"tls_cert_file": "/path/to/server_cert.pem", "tls_key_file": "/path/to/server_key.pem", "transport": "http", "address": "127.0.0.1:9004", "auth_token_env_var": "STACKQL_MCP_TOKEN"}, "backend": {"dsn": "postgres://stackql:stackql@127.0.0.1:5446?default_query_exec_mode=simple_protocol"}}' \
--pgsrv.port 5446

TLS chiffre le transport mais n'authentifie pas le client ; cet exemple exige donc aussi le jeton bearer contenu dans STACKQL_MCP_TOKEN.

Cas d'utilisation : lorsque vous devez séparer les charges de travail MCP et PostgreSQL entre différents processus ou hôtes, ou lorsque vous avez besoin du chiffrement TLS pour le point de terminaison MCP.


Options de configuration​

Type de serveur MCP​

TypeDescription
httpMode serveur HTTP direct - les requêtes MCP sont traitées dans le processus par le moteur StackQL.
reverse_proxyMode proxy inverse - les requêtes MCP sont transmises à un serveur PostgreSQL sous-jacent via le DSN configuré. Utilisé avec stackql srv.
stdioTransport par entrée/sortie standard - le serveur lit les requêtes sur stdin et écrit les réponses sur stdout. Utilisé par les clients MCP embarqués dans un éditeur (Claude Desktop, Cursor, etc.).

Format de journal MCP​

L'option --mcp.log.format sélectionne l'encodage du journal d'audit : jsonl (valeur par défaut) ou otel (enregistrements de journal OpenTelemetry OTLP/JSON). Elle prévaut sur server.audit.format dans l'objet de configuration. Consultez Format de journal.

Version du protocole MCP​

L'option --mcp.protocol.version définit la révision du protocole la plus récente que le serveur annonce : auto (valeur par défaut, toutes les révisions prises en charge), 2026-07-28 (sans session uniquement) ou une révision plus ancienne telle que 2025-11-25 (cette révision et les précédentes). Elle prévaut sur server.protocol_version dans l'objet de configuration. Consultez Fixer la révision.

Objet de configuration MCP​

L'option --mcp.config accepte un objet JSON de la structure suivante.

Configuration du serveur​
ChampDescriptionObligatoire
server.transportProtocole de transport - http ou stdio.Oui
server.addressAdresse et port d'écoute du serveur MCP (par exemple 127.0.0.1:9912). Transport HTTP uniquement.Pour http
server.tls_cert_fileChemin du fichier de certificat TLS pour HTTPS.Non
server.tls_key_fileChemin du fichier de clé privée TLS pour HTTPS.Non
server.auth_token_env_varNom d'une variable d'environnement contenant un jeton bearer prépartagé. Lorsqu'il est défini, chaque requête HTTP doit porter Authorization: Bearer <token> ; le serveur refuse de démarrer si la variable est absente ou vide. Consultez Authentification des clients HTTP.Ce champ ou allow_unauthenticated, pour http
server.allow_unauthenticatedActivation explicite du service du transport HTTP sans authentification des clients. Valeur par défaut : false.Ce champ ou auth_token_env_var, pour http
server.modeContrat de sécurité qui contrôle les mutations et les opérations de cycle de vie. L'une des valeurs read_only, safe (valeur par défaut), delete_safe, full_access. Consultez Modes du serveur.Non
server.read_onlyAlias booléen hérité de mode: read_only. Lorsque les deux champs sont définis, mode l'emporte.Non
server.statelessSert Streamable HTTP sans sessions (pas de Mcp-Session-Id), ce qui est la manière dont la révision du protocole 2026-07-28 est servie en HTTP. Valeur par défaut : false. Ignoré pour stdio. Consultez Prise en charge des révisions du protocole.Non
server.protocol_versionRévision du protocole la plus récente annoncée : auto (valeur par défaut), 2026-07-28 ou une révision plus ancienne telle que 2025-11-25. 2026-07-28 implique stateless pour Streamable HTTP. Consultez Fixer la révision.Non
server.auditConfiguration du sous-système d'audit, dont audit.format (jsonl ou otel). Consultez Journal d'audit.Non
Configuration du backend (mode proxy inverse uniquement)​
ChampDescriptionObligatoire
backend.dsnChaîne de connexion PostgreSQL du serveur StackQL backend.Oui (pour reverse_proxy)

info

Le DSN du backend doit inclure le paramètre default_query_exec_mode=simple_protocol pour une compatibilité optimale.

Listes d'autorisation​
ChampDescription
enabled_toolsTableau des noms d'outils que le serveur est autorisé à publier. S'il est omis ou vide, tous les outils intégrés sont enregistrés. Sert à exposer un sous-ensemble restreint (par exemple un serveur d'inventaire en lecture seule).
enabled_promptsTableau de noms de prompts. Même sémantique que enabled_tools, mais pour la surface des prompts.

Exemple - un serveur qui publie uniquement server_info et list_providers :

{
"server": {"transport": "http", "address": "127.0.0.1:9912", "allow_unauthenticated": true},
"enabled_tools": ["server_info", "list_providers"]
}

Prise en charge des révisions du protocole​

La révision du protocole 2026-07-28, server.stateless et le format de journal d'audit otel sont disponibles dans les versions de StackQL à partir de v0.11.660. server.protocol_version et l'option --mcp.protocol.version sont disponibles dans les versions de StackQL à partir de v0.12.732.

Le serveur parle toutes les révisions du Model Context Protocol prises en charge par le SDK MCP Go et négocie client par client, de sorte qu'un parc de clients hétérogènes fonctionne avec un seul serveur.

RévisionCycle de vieDemande d'approbation (safe / delete_safe)
2026-07-28 (annoncée)Pas de handshake : server/discover, puis chaque requête porte io.modelcontextprotocol/protocolVersion et io.modelcontextprotocol/clientCapabilities dans _meta (plus les en-têtes Mcp-Protocol-Version, Mcp-Method et Mcp-Name en HTTP).Résultat input_required, que le client relance avec inputResponses (SEP-2322).
2025-11-25, 2025-06-18Handshake initialize / notifications/initialized.Requête elicitation/create à l'initiative du serveur.
2025-03-26, 2024-11-05Comme ci-dessus.Comme ci-dessus.

stdio sert toutes les révisions dans un seul processus : la première requête d'un client 2026-07-28 est servie sans handshake et le initialize d'un client plus ancien fonctionne toujours. Rien n'est à configurer pour Claude Desktop, les lanceurs npm / PyPI ou l'image Docker.

Streamable HTTP utilise par défaut le modèle avec état, à une session par client (Mcp-Session-Id), que le SDK sert pour les révisions jusqu'à 2025-11-25. Une requête 2026-07-28 reçoit l'erreur JSON-RPC -32022 (version de protocole non prise en charge ; un simple HTTP 400 dans les versions jusqu'à v0.12.718) dont data.supported liste les révisions à handshake, et server/discover annonce la même chose ; le client négocie donc une révision inférieure et les intégrations HTTP existantes conservent leurs sessions et leurs demandes d'approbation inchangées. Définissez server.stateless (ou fixez la révision à 2026-07-28, ci-dessous) pour servir 2026-07-28 nativement en HTTP :

stackql mcp \
--mcp.server.type=http \
--mcp.config '{"server": {"transport": "http", "address": "127.0.0.1:9912", "allow_unauthenticated": true, "stateless": true}}'

Un serveur sans session n'émet aucun Mcp-Session-Id, répond à GET et DELETE par 405 (il n'y a pas de session à fermer), garde tools/list, prompts/list et resources/list invariants d'une connexion à l'autre, et fait passer l'aller-retour d'approbation par input_required. Il accepte toujours le initialize d'un client plus ancien et lui sert les lectures, mais il ne peut pas conserver la capacité d'élicitation que ce client a déclarée à l'initialisation (chaque requête obtient une session éphémère) ; les clients plus anciens ne peuvent donc pas approuver les écritures soumises à approbation sur un serveur sans session. Choisissez stateless pour les hôtes à la révision actuelle et la valeur par défaut pour un parc qui comprend encore des clients plus anciens.

Le serveur ne conserve aucun état entre les appels : le mode, l'audit et les identifiants des providers relèvent de la configuration au niveau du processus, de sorte que rien n'a besoin d'être déplacé derrière des handles explicites.

Fixer la révision​

Par défaut, le serveur annonce toutes les révisions prises en charge et négocie client par client. L'option --mcp.protocol.version, ou server.protocol_version dans l'objet de configuration (l'option l'emporte), définit la révision la plus récente annoncée :

# sessionless only; stateless Streamable HTTP is implied
stackql mcp \
--mcp.server.type=http \
--mcp.protocol.version=2026-07-28 \
--mcp.config '{"server": {"transport": "http", "address": "127.0.0.1:9912", "allow_unauthenticated": true}}'

# handshake lifecycle only
stackql mcp --mcp.server.type=stdio --mcp.protocol.version=2025-11-25
ValeurAnnoncéEffet
auto (valeur par défaut) ou absenteToutes les révisions prises en charge.Négociation comme ci-dessus : la révision la plus élevée que les deux parties parlent.
2026-07-282026-07-28 uniquement.Sans session uniquement, et stateless est implicite pour Streamable HTTP. Le initialize d'un client plus ancien reçoit la réponse 2025-11-25, signal pour ce client de se déconnecter plutôt que de lire la réponse comme le nouveau cycle de vie.
2025-11-25 (ou toute révision plus ancienne)Cette révision et toutes les précédentes.Cycle de vie à handshake uniquement : une requête 2026-07-28 reçoit l'erreur JSON-RPC -32022 avec data.supported listant les révisions annoncées, afin que le client puisse renégocier. Les clients à handshake plus anciens conservent leur propre révision.

Toute autre valeur fait échouer la validation de la configuration au démarrage, et l'erreur indique les valeurs autorisées.

Limites de transport​

Les corps des requêtes Streamable HTTP sont plafonnés à 4 MiB (HTTP 413 au-delà), un JSON imbriqué sur plus de 1000 niveaux est rejeté avant l'analyse, et une trame stdio est plafonnée à 8 MiB. Aucune de ces limites n'est configurable ; toutes se situent bien au-dessus de toute instruction SQL que le serveur accepte.


(Re)chargement des identifiants (--env.file + reload_credentials)​

remarque

--env.file et l'outil reload_credentials sont disponibles dans les versions de StackQL postérieures à v0.10.542.

Le bloc d'environnement d'un processus est figé à son lancement. Cela pose deux problèmes pour les serveurs MCP :

  • Un serveur MCP stdio lancé par un client de bureau (Claude Desktop, Cursor, etc.) sans les variables d'environnement d'identifiants ne peut jamais les voir - le client transmet son propre environnement au sous-processus.
  • Les identifiants de courte durée renouvelés n'atteignent jamais une session de serveur de longue durée.

L'option --env.file comble ces deux lacunes en désignant un fichier de type dotenv qui sert de magasin d'identifiants modifiable :

stackql mcp --mcp.server.type=stdio --env.file /path/to/stackql-credentials.env

Sémantique du chargement​

Le fichier est chargé dans l'environnement du processus au démarrage, pour chaque point d'entrée (exec, shell, srv, registry, mcp) :

  • Lorsque l'option est vide ou absente, rien ne se passe - les identifiants sont résolus à la demande depuis l'environnement du processus au moment de la requête, exactement comme dans le comportement historique.
  • Un fichier absent au chemin indiqué est une opération sans effet tolérée (le fichier peut être créé plus tard).
  • Un fichier mal formé ou illisible est une erreur fatale au démarrage.
  • Seules les clés dont la valeur n'est pas vide sont définies ; les variables d'environnement existantes du processus sont écrasées (le fichier est la source de vérité) ; rien n'est jamais supprimé.
  • L'option est disponible en ligne de commande uniquement - elle n'est pas lue depuis .stackqlrc.

Le format du fichier est un KEY=VALUE par ligne. Les commentaires #, les lignes vides, un préfixe export facultatif, des guillemets simples ou doubles facultatifs autour de la valeur et les fins de ligne CRLF sont tous tolérés :

# stackql-credentials.env
export OKTA_SECRET_KEY="00abc...xyz"
STACKQL_GITHUB_USERNAME=myuser
STACKQL_GITHUB_PASSWORD='ghp_mytoken'

reload_credentials​

L'outil reload_credentials recharge le fichier --env.file dans l'environnement du processus en cours de session, puis indique l'état de résolution des identifiants par provider. Les valeurs des secrets ne sont jamais renvoyées, journalisées ni auditées - uniquement les noms et les états. Sans --env.file configuré, l'outil se réduit à une simple sonde d'état.

Lorsqu'une requête échoue à la résolution des identifiants, l'erreur MCP porte une indication invitant l'agent à appeler reload_credentials puis à réessayer ; les clients agentiques se rétablissent ainsi d'eux-mêmes : écrivez l'identifiant dans le fichier, demandez à l'agent de recharger, et la requête en échec réussit à la nouvelle tentative - aucun redémarrage du serveur n'est nécessaire.

reload_credentials n'est pas pris en charge en mode backend reverse_proxy - les requêtes s'exécutent dans le processus du serveur stackql distant ; l'outil renvoie donc une erreur invitant l'utilisateur à recharger sur le serveur sous-jacent.

Windows et Claude Desktop​

setx écrit dans le registre, pas dans les processus en cours d'exécution, et Claude Desktop transmet son propre environnement (périmé) aux sous-processus MCP - les changements d'identifiants nécessitent donc normalement un redémarrage complet de Claude Desktop. Avec --env.file, le fichier d'identifiants peut être créé ou renouvelé à tout moment et reload_credentials le prend en compte sans aucun redémarrage. Consultez Utiliser StackQL avec Claude Desktop pour un exemple de configuration complet.


Authentification des clients HTTP​

remarque

server.auth_token_env_var et server.allow_unauthenticated sont disponibles dans les versions de StackQL à partir de v0.12.742.

Le transport HTTP exige l'authentification des clients. server.auth_token_env_var nomme une variable d'environnement contenant un jeton bearer prépartagé ; chaque requête doit porter Authorization: Bearer <token>, faute de quoi elle reçoit la réponse 401. Le jeton est lu depuis l'environnement ; il n'apparaît donc jamais dans --mcp.config ni dans les arguments du processus.

export STACKQL_MCP_TOKEN="$(openssl rand -hex 32)"

stackql mcp \
--mcp.server.type=http \
--mcp.config '{"server": {"transport": "http", "address": "127.0.0.1:9912", "auth_token_env_var": "STACKQL_MCP_TOKEN"}}'
Authentification du serveur requise

Servir sans jeton relève d'une activation explicite : définissez "allow_unauthenticated": true dans server. Sans aucune des deux clés, le serveur s'arrête au démarrage avec un message qui nomme les deux ; il s'arrête aussi si la variable du jeton est absente ou vide. À partir de la version v0.12.742, vous devez ajouter soit auth_token_env_var, soit "allow_unauthenticated": true à server lorsque vous utilisez le transport http.

TLS (tls_cert_file / tls_key_file) chiffre le transport mais n'authentifie pas le client ; associez-le à un jeton pour tout écouteur au-delà de l'interface de bouclage. Les requêtes de navigateur cross-origin (un Origin non concordant, ou un Sec-Fetch-Site cross-site) sont refusées avec 403, quelle que soit l'authentification. Le stackql_mcp_client fourni n'envoie aucun en-tête Authorization ; un serveur qu'il pilote doit donc activer explicitement le service sans authentification.

À partir de v1.0, démarrer le serveur avec --access.config remplace le contrôle par jeton partagé par une authentification par appelant : chaque requête HTTPS est vérifiée avec le schéma configuré (JWT, bearer statique ou TLS mutuel) et autorisée au regard des règles de politique. Le TLS du serveur est alors obligatoire, l'authentification local_os est refusée en HTTP, et une requête sans identifiants ne se rabat jamais sur le jeton d'environnement du serveur. La gestion des accès n'est pas disponible avec le type de serveur reverse_proxy.


Modes du serveur​

server.mode choisit l'un des quatre contrats de sécurité. Tous les quatre autorisent SELECT et les lectures de métadonnées ; ils diffèrent dans leur traitement des mutations et des opérations de cycle de vie.

ModeSELECT / métadonnéesINSERT / UPDATE / REPLACEDELETEEXEC (cycle de vie)
read_onlyautorisérefusérefusérefusé
safe (valeur par défaut)autoriséapprobation requiseapprobation requiseapprobation requise
delete_safeautoriséautoriséapprobation requiseapprobation requise
full_accessautoriséautoriséautoriséautorisé

Refusé renvoie immédiatement une erreur au client.

Approbation requise utilise le flux d'élicitation MCP, dont la forme dépend de la révision du protocole négociée :

  • Si le client a annoncé la capacité d'élicitation (à l'initialisation, ou dans les capacités client de _meta par requête en 2026-07-28), le serveur demande à l'utilisateur d'approuver l'action au moyen d'un court message (nom de l'outil, classe de requête, SQL). En 2026-07-28, la demande est renvoyée sous la forme d'un résultat input_required portant une requête d'entrée elicitation/create sous l'identifiant stackql_approval, et le client relance l'appel avec la réponse dans inputResponses ; sur les révisions antérieures, le serveur envoie lui-même la requête elicitation/create en cours d'appel. L'utilisateur accepte, refuse ou annule.
  • Si le client n'a pas annoncé l'élicitation, l'outil est refusé avec un message qui explique ce manque et oriente l'exploitant vers le mode full_access.

L'approbation est donnée par le client ; elle protège donc contre un agent qui agit sans son utilisateur, pas contre un appelant non fiable. Associez le transport HTTP à l'authentification des clients lorsque les appelants ne sont pas de confiance.

Le mode est global pour chaque serveur. Il n'existe pas de dérogation par outil.

À partir de v1.0, run_select_query refuse INSERT, UPDATE, REPLACE, DELETE et EXEC dans tous les modes, y compris full_access ; l'erreur nomme run_mutation_query ou run_lifecycle_operation. Chaque outil porte aussi un title et les quatre indications de comportement MCP sous forme de booléens explicites (readOnlyHint, destructiveHint, idempotentHint, openWorldHint), dérivées de la même classification que celle appliquée par le contrôle de politique. openWorldHint vaut true pour list_registry, pull_provider, run_select_query, run_mutation_query et run_lifecycle_operation, qui atteignent les points de terminaison du registre ou des providers, et false pour les outils qui ne lisent que l'état local. Les indications sont consultatives, pour l'expérience utilisateur du client ; l'application reste du ressort du contrôle de politique.

Contrôle des charges utiles

À partir de la version v0.12.742, une charge utile contenant plusieurs instructions est contrôlée par son instruction la plus privilégiée dans tous les modes ; SELECT 1; DELETE ... est donc traité comme un DELETE et l'enregistrement d'audit porte le query_class mutation_delete. validate_select_query accepte exactement une instruction.

Changement de comportement du mode par défaut​

Les versions précédentes n'appliquaient la sécurité qu'au moyen d'une seule option read_only: true/false dont la valeur par défaut était "aucune application". La valeur par défaut actuelle (mode: safe) soumet d'emblée les mutations à l'approbation de l'utilisateur. Les exploitants qui utilisent un client compatible avec l'élicitation (Claude Desktop, Cursor, Continue, etc.) verront une demande d'approbation par mutation. Les exploitants qui exécutent des automatisations, ou le stackql_mcp_client fourni (qui n'annonce pas l'élicitation), doivent activer explicitement mode: full_access pour exécuter des mutations et des opérations de cycle de vie.

La clé JSON / YAML héritée read_only: true est toujours acceptée par compatibilité ascendante et est traitée comme équivalente à mode: read_only.

Exemples​

# Read-only: SELECTs proceed; mutations and lifecycle refused immediately.
stackql mcp \
--mcp.server.type=http \
--mcp.config '{"server": {"transport": "http", "address": "127.0.0.1:9912", "allow_unauthenticated": true, "mode": "read_only"}}'

# Delete-safe: INSERT/UPDATE proceed; DELETE and EXEC need approval.
stackql mcp \
--mcp.server.type=http \
--mcp.config '{"server": {"transport": "http", "address": "127.0.0.1:9912", "allow_unauthenticated": true, "mode": "delete_safe"}}'

# Full access: everything proceeds without prompting. Use only with trusted
# clients and operators.
stackql mcp \
--mcp.server.type=http \
--mcp.config '{"server": {"transport": "http", "address": "127.0.0.1:9912", "allow_unauthenticated": true, "mode": "full_access"}}'

Journal d'audit​

Chaque appel d'outil écrit un enregistrement dans la destination d'audit configurée, en JSONL par défaut ou sous forme d'enregistrements de journal OpenTelemetry (voir Format de journal). L'audit est activé par défaut. L'audit répond à la question "qu'a fait l'agent", pas à "qu'a vu l'agent" - les lignes de résultat des instructions SELECT ne sont volontairement pas enregistrées, quel que soit le format.

Ce qui est enregistré​

ChampDescription
timestampHeure réelle au début de l'appel (RFC3339).
toolNom de l'outil (par exemple run_select_query).
modeMode du serveur en vigueur au moment de l'appel.
decisionallow / refuse_immediate / needs_approval_accepted / needs_approval_declined / needs_approval_cancelled / needs_approval_unavailable.
query_classselect / mutation_create / mutation_delete / lifecycle / unknown. Pour une charge utile contenant plusieurs instructions, la classe de la plus privilégiée.
sqlChaîne SQL pour les outils de requête (run_select_query, run_mutation_query, run_lifecycle_operation, validate_select_query).
argsChamps de hiérarchie pour les outils de métadonnées (list_*, describe_method) ; SQL + row_limit pour les outils de requête.
duration_msDurée réelle du contrôle + du gestionnaire.
errorMessage d'erreur si l'outil a échoué ou a été refusé.

Les lignes de résultat des instructions SELECT sont délibérément exclues - elles peuvent être très volumineuses et contenir des données sensibles.

Destination fichier​

La seule destination fournie aujourd'hui est file. Un objet JSON par ligne, fsync après chaque enregistrement, rotation de type lumberjack par taille / âge / nombre de sauvegardes.

stackql mcp \
--mcp.server.type=http \
--mcp.config '{
"server": {
"transport": "http",
"address": "127.0.0.1:9912",
"allow_unauthenticated": true,
"audit": {
"file": {
"path": "/var/log/stackql-mcp.log",
"max_size_mb": 100,
"max_backups": 5,
"max_age_days": 30
}
}
}
}'

Deux façons d'indiquer l'emplacement :

  • audit.file.path - un chemin de fichier complet (absolu, ou relatif au répertoire de travail courant, cwd).
  • audit.file.dir - un répertoire ; la destination y choisit le nom de base stackql_mcp_server_<RFC3339-utc-second>.log.

Lorsqu'aucun des deux n'est défini dans mcp.config, le serveur MCP donne à dir le répertoire de travail courant comme valeur par défaut, afin que les exploitants existants observent le même comportement qu'auparavant. Le paquet générique de destination sous-jacent refuse lui-même de choisir silencieusement un répertoire - la décision "où atterrissent les journaux" est toujours prise par l'appelant.

Le chemin absolu résolu est écrit sur stderr au démarrage sous la forme sink file: /path/to/file.log.

Format de journal​

Le flux d'audit a deux encodages, écrits dans la même destination fichier :

stackql mcp --mcp.server.type=stdio --mcp.log.format=jsonl # default, unchanged
stackql mcp --mcp.server.type=stdio --mcp.log.format=otel # OTLP/JSON log records

L'option prévaut sur server.audit.format dans mcp.config ("audit": {"format": "otel"}). jsonl est compatible à l'octet près avec les enregistrements décrits ci-dessus. otel écrit un objet OTLP/JSON LogsData par ligne, la forme que le récepteur otlp_json_file de l'OpenTelemetry Collector ingère telle quelle (vérifié avec otelcol-contrib 0.160.0) ; le flux atteint donc n'importe quel pipeline OTLP sans processeur de transformation :

receivers:
otlp_json_file:
include: [/var/log/stackql-mcp.log]
exporters:
debug: {}
service:
pipelines:
logs:
receivers: [otlp_json_file]
exporters: [debug]

Chaque appel d'outil produit un enregistrement de journal ; un appel passé par le contrôle d'approbation produit un second enregistrement pour la décision d'élicitation. Les enregistrements d'un même appel partagent gen_ai.tool.call.id et un identifiant de trace. Un traceparent W3C fourni par l'appelant dans params._meta est respecté ; sinon, un identifiant de trace est généré par session MCP afin que les enregistrements d'une session d'agent puissent être corrélés.

L'ensemble d'attributs émis est une interface versionnée : le scope d'instrumentation est github.com/stackql/stackql/pkg/mcp_server/audit en version 1.0.0, et schemaUrl fixe les conventions stables à https://opentelemetry.io/schemas/1.44.0. Les attributs gen_ai.* et mcp.* suivent les conventions sémantiques GenAI et MCP, qui sont au statut Development ; la version du scope est incrémentée lorsque l'ensemble change.

AttributEnregistrementValeur
service.name, service.versionressourcestackql, la version de StackQL
gen_ai.operation.nameappel d'outilexecute_tool
mcp.method.nameles deuxtools/call sur l'enregistrement d'appel d'outil, elicitation/create sur l'enregistrement de décision
gen_ai.tool.nameles deuxNom de l'outil
gen_ai.tool.call.idles deuxGénéré par appel, partagé par les deux enregistrements
mcp.protocol.versionles deuxRévision négociée
mcp.session.idles deuxIdentifiant de session (absent pour les requêtes HTTP sans session)
stackql.modeles deuxMode du serveur
stackql.decisionles deuxLa valeur decision du tableau ci-dessus
stackql.queryappel d'outilSQL tel quel, pour les outils de requête
stackql.query_classappel d'outilLa valeur query_class
stackql.providerappel d'outilProvider, pour les outils de métadonnées
stackql.query.sourceappel d'outilIdentifiant d'entrée de la Query Library, lorsqu'il est fourni
stackql.duration_msappel d'outilDurée réelle
stackql.rows_returnedappel d'outilNombre de lignes, pour les outils qui renvoient des lignes
error.type, error.messageappel d'outilEn cas d'échec : la décision de refus, ou tool_error après le contrôle

Le corps est execute_tool <tool> / elicitation <tool> ; la gravité est INFO, ou ERROR lorsque l'appel a échoué ou a été refusé. Le contrat de masquage est identique dans les deux formats : les valeurs de résultat ne sont jamais sérialisées, seule l'instruction qui les a produites l'est.

Modes de défaillance​

Lorsque la destination renvoie une erreur, le comportement de la réponse dépend de audit.failure_mode.

failure_modeEffet
strict (valeur par défaut)L'appel d'outil renvoie l'erreur d'audit au client même si l'outil sous-jacent a réussi. C'est voulu : mieux vaut une réponse ambiguë pour le client qu'un DELETE non détecté.
strict_mutationsLes SELECT / lectures de métadonnées se poursuivent avec une note sur stderr ; les mutations et les opérations de cycle de vie font remonter l'erreur d'audit.
best_effortToujours journaliser sur stderr et poursuivre.

Séquencement​

L'écriture d'audit a lieu après l'exécution de l'outil (ou son blocage par le contrôle) mais avant le retour de la réponse au client. En mode strict, un échec d'écriture d'audit sur un DELETE réussi signifie que la ligne a disparu mais que le client reçoit une erreur - c'est voulu, afin qu'aucune mutation ne passe sans être auditée.

Désactiver l'audit​

Pour désactiver entièrement l'audit (le comportement antérieur à PR2) :

stackql mcp \
--mcp.server.type=http \
--mcp.config '{"server": {"transport": "http", "address": "127.0.0.1:9912", "allow_unauthenticated": true, "audit": {"disabled": true}}}'

Outils MCP disponibles​

Lorsqu'il s'exécute en tant que serveur MCP, StackQL expose les outils suivants, sous réserve de la liste d'autorisation enabled_tools configurée. Chacun renvoie à la fois une vue texte rendue (pour le LLM) et une charge utile structurée et typée (pour les clients programmatiques). Le rendu texte par défaut est un tableau markdown pour les résultats uniformes de plusieurs lignes, ou un bloc KV markdown pour les résultats clairsemés / à un seul enregistrement. Les outils qui ont des arguments acceptent un argument facultatif format (markdown ou json) qui remplace ce rendu ; sinon, le paramètre de rendu du serveur est utilisé. Les entrées ci-dessous listent les arguments propres à chaque tâche ; ? marque les entrées facultatives.

Cliquez sur le nom d'un outil pour accéder à sa page de référence complète, avec les entrées, le comportement de contrôle et un exemple de prompt.

OutilRenduDescriptionEntrées
server_infoKVIdentité et runtime du serveur : version de stackql, moteur SQL sous-jacent, emplacement du registre de providers, mode, option de lecture seule. Appelez-le une fois en début de session.aucune
list_providersTableauProviders déjà téléchargés dans le cache local - sommet de la hiérarchie.aucune
list_servicesTableauServices d'un provider.provider
list_resourcesTableauRessources d'un provider.service.provider, service
list_methodsTableauMéthodes d'accès (opérations HTTP) d'une ressource, avec le verbe SQL auquel chacune correspond et ses paramètres obligatoires. Appelez-le avant d'écrire toute requête - c'est ici que les paramètres WHERE obligatoires sont déduits.provider, service, resource
describe_methodKVContrat d'E/S complet d'une méthode (toujours EXTENDED) : entrées obligatoires et facultatives, et champs de sortie qu'un SELECT peut référencer.provider, service, resource, method
query_library_searchTableauTrouve des modèles de requête sélectionnés à partir d'une intention en langage naturel. En lecture seule ; les entrées de mutation nécessitent une activation explicite et sont exclues en mode read_only.intent, provider?, service?, tags?, include_mutations?, limit?
query_library_getKVRécupère un modèle et ses déclarations de paramètres. Avec un params non vide, valide les valeurs et renvoie le SQL rendu ainsi que next_tool, sans l'exécuter.id, params?
validate_select_queryKVAnalyse et planifie un seul SELECT sans l'exécuter. Renvoie {valid, errors}. SELECT uniquement ; exactement une instruction.sql
run_select_queryTableauExécute un SELECT. Renvoie {rows}. Lectures uniquement.sql, row_limit?
run_mutation_queryKVExécute INSERT/UPDATE/REPLACE/DELETE sur le provider. Effets de bord réels. Renvoie {messages, timestamp}. Contrôlé par le mode du serveur.sql
run_lifecycle_operationKVExécute une opération de cycle de vie EXEC de stackql. Renvoie {messages, timestamp}. Contrôlé par le mode du serveur.sql
list_registryTableauProviders (et leurs versions) disponibles dans le registre configuré. À distinguer de list_providers, qui ne liste que les providers déjà téléchargés.provider?
pull_providerKVInstalle un seul provider depuis le registre dans le cache local. État du cache local uniquement - aucun effet sur le plan de contrôle ou le plan de données du cloud.provider, version?
reload_credentialsTableauRecharge les identifiants depuis le fichier dotenv --env.file dans l'environnement du processus et indique l'état de résolution par provider (ok, unresolved, not_checked). Ne renvoie jamais les valeurs des secrets. Autorisé dans tous les modes.provider?

Consultez query_library_search avant d'écrire du SQL à partir de zéro, puis utilisez query_library_get pour inspecter et rendre un modèle correspondant. Les outils de requête acceptent aussi un argument facultatif source contenant l'identifiant de l'entrée de la Query Library, à des fins d'attribution uniquement ; l'exécution reste soumise au mode du serveur et à la politique d'approbation habituels.

remarque

describe_resource a été retiré dans StackQL v0.12.732 ; les clients MCP, les prompts ou les instructions d'agent qui l'appelaient doivent appeler à la place list_methods puis describe_method. Une ressource n'a pas de liste de champs unique, car chaque méthode d'accès renvoie sa propre forme ; les noms de colonnes proviennent donc de describe_method pour la méthode vers laquelle une requête est routée. L'instruction SQL DESCRIBE est inchangée.

Prompts MCP disponibles​

Un seul prompt statique est publié.

PromptDescription
write_safe_selectConseils pour écrire des requêtes SELECT sûres sur les ressources stackql. Explique comment utiliser SHOW METHODS IN <provider>.<service>.<resource> pour découvrir la bonne méthode de lecture et les paramètres WHERE obligatoires.

Options​

OptionDescription
--mcp.server.typeType de serveur MCP : http, stdio ou reverse_proxy (ce dernier s'utilise avec stackql srv).
--mcp.configObjet de configuration JSON du serveur MCP. YAML est également accepté.
--mcp.protocol.versionRévision du protocole la plus récente annoncée : auto (valeur par défaut), 2026-07-28 ou une révision plus ancienne telle que 2025-11-25. Consultez Fixer la révision.
--env.fileFichier d'identifiants de type dotenv chargé au démarrage et rechargé à la demande par l'outil reload_credentials. Consultez (Re)chargement des identifiants.
--pgsrv.portPort TCP du serveur de protocole filaire PostgreSQL (utilisé avec stackql srv).
-H, --helpAffiche les informations d'aide.
-v, --verboseExécute en mode verbeux avec une sortie supplémentaire.

   

consultez Options globales pour des options supplémentaires

info

Vous devez définir les variables d'environnement requises pour l'authentification des providers avant de démarrer le serveur MCP, ou désigner un fichier d'identifiants de type dotenv avec --env.file. Pour plus d'informations, consultez Utiliser un provider.


Exemples​

Serveur MCP autonome de base​

Lancez un serveur MCP autonome avec l'authentification du provider et un jeton bearer pour ses clients :

export GOOGLE_CREDENTIALS=$(cat /path/to/google-credentials.json)
export STACKQL_MCP_TOKEN="$(openssl rand -hex 32)"

stackql mcp \
--mcp.server.type=http \
--mcp.config '{"server": {"transport": "http", "address": "127.0.0.1:9912", "auth_token_env_var": "STACKQL_MCP_TOKEN"}}' \
--registry='{"url": "https://registry.stackql.io/providers"}' \
--auth='{"google": {"type": "service_account", "credentialsfilepath": "/path/to/google-credentials.json"}}'

Serveur MCP avec serveur PostgreSQL (en mémoire)​

Exécutez les serveurs MCP et PostgreSQL pour un accès par les deux protocoles :

export GOOGLE_CREDENTIALS=$(cat /path/to/google-credentials.json)

stackql srv \
--mcp.server.type=http \
--mcp.config '{"server": {"transport": "http", "address": "127.0.0.1:9912", "allow_unauthenticated": true}}' \
--pgsrv.port 5665 \
--registry='{"url": "https://registry.stackql.io/providers"}' \
--auth='{"google": {"type": "service_account", "credentialsfilepath": "/path/to/google-credentials.json"}}'

Serveur d'inventaire en lecture seule avec audit vers un chemin connu​

Utile pour un agent d'analyse d'inventaire qui ne doit jamais effectuer de mutation :

stackql mcp \
--mcp.server.type=http \
--mcp.config '{
"server": {
"transport": "http",
"address": "127.0.0.1:9912",
"allow_unauthenticated": true,
"mode": "read_only",
"audit": {"file": {"path": "/var/log/stackql-mcp-audit.log"}}
}
}' \
--registry='{"url": "https://registry.stackql.io/providers"}' \
--auth='{"google": {"type": "service_account", "credentialsfilepath": "/path/to/google-credentials.json"}}'

Serveur d'automatisation en accès complet​

Pour les pipelines d'automatisation de confiance qui ont besoin de mutations et ne peuvent pas répondre aux demandes d'élicitation. Le pipeline présente le jeton bearer contenu dans STACKQL_MCP_TOKEN :

stackql mcp \
--mcp.server.type=http \
--mcp.config '{
"server": {
"transport": "http",
"address": "127.0.0.1:9912",
"auth_token_env_var": "STACKQL_MCP_TOKEN",
"mode": "full_access"
}
}' \
--registry='{"url": "https://registry.stackql.io/providers"}' \
--auth='{"google": {"type": "service_account", "credentialsfilepath": "/path/to/google-credentials.json"}}'

Serveur MCP sécurisé avec TLS​

Lancez un serveur MCP avec chiffrement TLS en mode proxy inverse :

Générez d'abord les certificats TLS (auto-signés pour le développement) :

openssl req -x509 -newkey rsa:4096 -keyout server_key.pem -out server_cert.pem -days 365 -nodes

Démarrez ensuite le serveur :

stackql srv \
--mcp.server.type=reverse_proxy \
--mcp.config '{
"server": {
"tls_cert_file": "server_cert.pem",
"tls_key_file": "server_key.pem",
"transport": "http",
"address": "127.0.0.1:9004",
"auth_token_env_var": "STACKQL_MCP_TOKEN"
},
"backend": {
"dsn": "postgres://stackql:stackql@127.0.0.1:5446?default_query_exec_mode=simple_protocol"
}
}' \
--pgsrv.port 5446 \
--registry='{"url": "https://registry.stackql.io/providers"}' \
--auth='{"google": {"type": "service_account", "credentialsfilepath": "/path/to/google-credentials.json"}}'

Tester votre serveur MCP​

Le dépôt fournit un client MCP de développement (stackql_mcp_client) pour les scripts et les tests de régression. Compilez-le avec :

python cicd/python/build.py --build-mcp-client

Cela produit ./build/stackql_mcp_client.

Notez que stackql_mcp_client n'envoie aucun en-tête Authorization, de sorte que le serveur qu'il cible doit définir "allow_unauthenticated": true (comme le font les exemples ci-dessus) ; un serveur protégé par jeton lui répond par 401. Il n'annonce pas non plus la capacité d'élicitation MCP - il est destiné aux scripts non interactifs. Face à un serveur safe ou delete_safe, il reçoit le refus "client does not support elicitation" sur les appels de mutation et de cycle de vie. Pour des tests interactifs avec des demandes d'élicitation, utilisez un client MCP embarqué dans un éditeur (Claude Desktop, Cursor, Continue).

# List all available tools
./build/stackql_mcp_client exec \
--client-type=http \
--url=http://127.0.0.1:9912

# Server identity, mode, audit / registry context
./build/stackql_mcp_client exec \
--client-type=http \
--url=http://127.0.0.1:9912 \
--exec.action server_info

# Re-source the --env.file credentials file and report per-provider
# credential status - a good first diagnostic when queries fail on auth
./build/stackql_mcp_client exec \
--client-type=http \
--url=http://127.0.0.1:9912 \
--exec.action reload_credentials

# List providers already pulled into the local cache
./build/stackql_mcp_client exec \
--client-type=http \
--url=http://127.0.0.1:9912 \
--exec.action list_providers

# List providers (and versions) available in the registry
./build/stackql_mcp_client exec \
--client-type=http \
--url=http://127.0.0.1:9912 \
--exec.action list_registry

# Install a provider from the registry into the local cache
./build/stackql_mcp_client exec \
--client-type=http \
--url=http://127.0.0.1:9912 \
--exec.action pull_provider \
--exec.args '{"provider": "kafka"}'

# List services for a provider
./build/stackql_mcp_client exec \
--client-type=http \
--url=http://127.0.0.1:9912 \
--exec.action list_services \
--exec.args '{"provider": "google"}'

# List access methods for a resource (this is how an agent finds required
# WHERE parameters before writing a query)
./build/stackql_mcp_client exec \
--client-type=http \
--url=http://127.0.0.1:9912 \
--exec.action list_methods \
--exec.args '{"provider": "google", "service": "compute", "resource": "networks"}'

# Validate a SELECT without executing
./build/stackql_mcp_client exec \
--client-type=http \
--url=http://127.0.0.1:9912 \
--exec.action validate_select_query \
--exec.args '{"sql": "select name from google.compute.networks where project = '"'"'my-project'"'"';"}'

# Execute a SELECT
./build/stackql_mcp_client exec \
--client-type=http \
--url=http://127.0.0.1:9912 \
--exec.action run_select_query \
--exec.args '{"sql": "select name from google.compute.networks where project = '"'"'my-project'"'"';"}'

# Mutation - succeeds only against a full_access server, or against
# delete_safe (for INSERT/UPDATE) or safe with an elicitation-capable client.
./build/stackql_mcp_client exec \
--client-type=http \
--url=http://127.0.0.1:9912 \
--exec.action run_mutation_query \
--exec.args '{"sql": "delete from google.compute.firewalls where project = '"'"'my-project'"'"' and firewall = '"'"'old-rule'"'"';"}'

Exemples de réponses​

server_info (sur un serveur en mode par défaut) :

{
"version": "0.10.444",
"commit": "abc1234",
"build_date": "2026-05-16T10:47:33Z",
"platform": "linux/amd64",
"transport": "http",
"sql_backend": "sqlite3",
"provider_registry": "https://registry.stackql.io/providers",
"mode": "safe",
"is_read_only": false
}

run_select_query :

{
"rows": [
{"name": "default"},
{"name": "pathfinders-test-01"},
{"name": "returning-test-03"}
]
}

run_mutation_query (sur un serveur full_access) :

{
"messages": ["The operation was despatched successfully"],
"timestamp": "2026-05-16T10:47:33+10:00 AEST"
}

Exemple de ligne du journal d'audit pour la même mutation :

{"timestamp":"2026-05-16T00:47:33Z","tool":"run_mutation_query","mode":"full_access","decision":"allow","query_class":"mutation_delete","sql":"delete from google.compute.firewalls where project = 'my-project' and firewall = 'old-rule';","args":{"sql":"delete from google.compute.firewalls where project = 'my-project' and firewall = 'old-rule';","row_limit":0},"duration_ms":42}

Intégration avec les assistants IA​

Pour intégrer le serveur MCP de StackQL à un assistant IA, enregistrez stackql comme serveur MCP dans la configuration de l'assistant. La plupart des clients MCP embarqués dans un éditeur exécutent le serveur sur stdio ; pour ceux-ci, utilisez --mcp.server.type=stdio et l'assistant lance directement le processus. Les agents autonomes qui parlent HTTP peuvent se connecter à un processus stackql mcp --mcp.server.type=http de longue durée.

Pour Claude Desktop - y compris la fiche de l'Anthropic Connector Directory (la méthode d'installation recommandée), le MCP Bundle téléchargeable (.mcpb) et la configuration manuelle - consultez Utiliser StackQL avec Claude Desktop.

remarque

L'emplacement des fichiers de configuration varie selon le système d'exploitation et l'assistant IA. Consultez la documentation de votre assistant IA pour connaître le chemin et le format corrects.


Considérations d'architecture​

Pour choisir un mode de déploiement, tenez compte des points suivants :

  1. Autonome (stackql mcp) : configuration la plus simple, idéale pour le développement et pour les clients embarqués dans un éditeur sur stdio.
  2. Double serveur en mémoire (stackql srv avec mcp.server.type=http) : un seul processus sert à la fois le protocole MCP et le protocole filaire PostgreSQL. Meilleures performances, convient à la plupart des déploiements en production.
  3. Proxy inverse (stackql srv avec mcp.server.type=reverse_proxy) :
    • permet de séparer les charges de travail entre processus ou hôtes
    • prend en charge le chiffrement TLS pour des points de terminaison MCP sécurisés
    • permet la mise à l'échelle indépendante des interfaces MCP et PostgreSQL
    • offre de la souplesse pour l'intégration de CA d'entreprise (remarque : la prise en charge des CA d'entreprise est expérimentale)

Et séparément, en matière de sécurité :

  • Commencez avec la valeur par défaut mode: safe. Les clients compatibles avec l'élicitation (Claude Desktop, Cursor, Continue) demandent confirmation à l'utilisateur avant toute mutation.
  • Fixez mode: read_only pour les agents d'inventaire ou d'analyse qui ne doivent jamais écrire.
  • Fixez mode: delete_safe lorsque vous voulez une liberté de création et de mise à jour, tout en gardant un humain dans la boucle pour les opérations destructrices.
  • Réservez mode: full_access aux pipelines d'automatisation de confiance, et uniquement en association avec un journal d'audit que quelqu'un examine.
  • Définissez server.auth_token_env_var sur tout écouteur HTTP que d'autres processus ou hôtes peuvent atteindre ; allow_unauthenticated est destiné au développement local. TLS seul n'authentifie pas les clients.
attention

Lorsque vous utilisez TLS avec des autorités de certification (CA) d'entreprise, une configuration supplémentaire peut être nécessaire. Cette fonctionnalité est expérimentale et peut nécessiter des ajustements selon votre implémentation de CA.


Pour aller plus loin​

  • La référence pour les développeurs du paquet est le README de pkg/mcp_server dans le dépôt stackql.
  • La documentation technique destinée aux contributeurs se trouve dans docs/mcp.md dans le dépôt stackql et comprend des exemples de réponses détaillés pour chaque outil.