Le cœur open source

Le cœur de akko-mcp-trino, sous licence Apache 2.0, donne à un agent IA un accès MCP en lecture seule à Trino, par défaut sous l'identité de chaque utilisateur, sans jamais transmettre son token.

Le cœur de akko-mcp-trino est un serveur MCP pour Trino, sous licence Apache 2.0, en version 0.6.0. Il donne à un agent IA six tools pour explorer un Trino et y lire des données. La garde de lecture seule est décidée sur l’arbre SQL. Chaque appel est borné et laisse une ligne d’audit.

Par défaut, chaque requête s’exécute sous le nom de l’utilisateur pour qui l’agent travaille. Le serveur vérifie le token de l’utilisateur, émis pour ce serveur. Il l’échange auprès de l’identity provider (IdP) contre un token distinct, émis pour Trino, par OAuth 2.0 Token Exchange (RFC 8693). Le token de l’utilisateur ne quitte jamais le serveur. Trino et sa policy décident ensuite de ce que l’agent peut lire.

Vous venez de la 0.5 ? La 0.6.0 change les valeurs par défaut. Un appelant vérifié est exigé, et le mode jwt échange le token de l’appelant au lieu de le transmettre, comme l’exige la spécification MCP. Une configuration 0.5 ne démarre plus telle quelle : akko-mcp-trino --check dit ce qui manque, et le guide MIGRATING.md décrit chaque étape. Les versions 0.5.x ne sont plus maintenues.

Le cœur, et ce que livrent AKKO et ARCHE

Cœur open source Dans AKKO et ARCHE
Identité dans Trino par défaut celle de chaque utilisateur, par échange de tokens ou par impersonation ; une identité unique seulement si l’administrateur la nomme les mêmes, et d’autres façons de porter l’identité de l’utilisateur
Lecture seule sur l’arbre SQL oui oui
Bornes de lignes et de temps oui, actives par défaut oui
Traces une ligne d’audit par appel, avec l’appelant un audit relié au journal du moteur
Tools six tools d’exploration et de lecture les mêmes, et des tools supplémentaires
Contexte métier du catalogue non oui, sans jamais décrire ce que la personne ne voit pas
Gestion des agents et des accès non oui
Exploitation en entreprise à votre charge installée et suivie avec la plateforme

Le cœur convient à des agents qui lisent chacun sous les droits de la personne, sur un Trino qui fait confiance à votre IdP. Il convient aussi à un agent qui lit sous un compte unique, dont vos règles bornent les droits. La présentation décrit le serveur complet.

Installer

pip install akko-mcp-trino        # ou : pipx install akko-mcp-trino
uvx akko-mcp-trino --version      # sans installation, comme le font la plupart des MCP hosts

Vous pouvez aussi l’installer depuis la source.

git clone https://github.com/AKKO-p/akko-mcp-trino.git
cd akko-mcp-trino
python -m venv .venv && source .venv/bin/activate
pip install -e .

Il faut Python 3.12 ou plus récent. Le paquet installe un module Python (akko_mcp_trino) et une commande (akko-mcp-trino) ; python -m akko_mcp_trino lance le même serveur.

En conteneur

L’image est publiée sur Docker Hub, pour linux/amd64 et linux/arm64. Elle tourne sous un utilisateur non root et porte une sonde de santé. Elle se configure avec les mêmes variables d’environnement, sur les ports 3000 (MCP) et 3001 (santé).

docker run --rm akkoai/akko-mcp-trino:0.6 akko-mcp-trino --version

docker run -d --name akko-mcp-trino -p 3000:3000 -p 3001:3001 \
  -e TRINO_HOST=trino.example.internal -e TRINO_PORT=8443 -e TRINO_HTTP_SCHEME=https \
  -e TRINO_CATALOG=iceberg \
  -e MCP_JWKS_URL=https://idp.example.com/realms/data/protocol/openid-connect/certs \
  -e MCP_OIDC_ISSUER=https://idp.example.com/realms/data \
  -e MCP_OIDC_AUDIENCE=akko-mcp \
  -e TRINO_TOKEN_EXCHANGE_URL=https://idp.example.com/realms/data/protocol/openid-connect/token \
  -e TRINO_TOKEN_EXCHANGE_CLIENT_ID=akko-mcp \
  -e TRINO_TOKEN_EXCHANGE_CLIENT_SECRET=... \
  -e TRINO_TOKEN_EXCHANGE_AUDIENCE=trino \
  akkoai/akko-mcp-trino:0.6

L’étiquette 0.6 suit la dernière version de la branche 0.6 ; 0.6.0 désigne une version précise.

Le code, les tests et les exemples sont sur GitHub ; le journal des versions suit chaque changement, et une vulnérabilité se signale selon la politique de sécurité.

Démarrer

Le serveur lit toute sa configuration dans l’environnement. Pointez-le sur votre Trino et sur votre IdP, puis lancez-le. Les valeurs par défaut sont les plus sûres : chaque requête s’exécute sous le nom de l’appelant (mode jwt), et une requête sans token valide est refusée.

export TRINO_HOST=trino.example.internal
export TRINO_PORT=8443
export TRINO_HTTP_SCHEME=https         # obligatoire : un token ne circule jamais en http
export TRINO_CATALOG=iceberg

# La porte : des tokens émis pour ce serveur, vérifiés avec le JWKS de l'IdP
export MCP_JWKS_URL=https://idp.example.com/realms/data/protocol/openid-connect/certs
export MCP_OIDC_ISSUER=https://idp.example.com/realms/data
export MCP_OIDC_AUDIENCE=akko-mcp       # l'audience des tokens émis pour ce serveur, jamais celle de Trino

# Un token pour Trino, par échange (RFC 8693), jamais celui de l'appelant
export TRINO_TOKEN_EXCHANGE_URL=https://idp.example.com/realms/data/protocol/openid-connect/token
export TRINO_TOKEN_EXCHANGE_CLIENT_ID=akko-mcp
export TRINO_TOKEN_EXCHANGE_CLIENT_SECRET=...
export TRINO_TOKEN_EXCHANGE_AUDIENCE=trino

akko-mcp-trino --check                 # la configuration effective, sans aucun secret
akko-mcp-trino                         # sert en streamable-http sur le port 3000

--check affiche la configuration effective et les avertissements, sans jamais imprimer un secret. Il sort avec le code 2 si le serveur refuserait de démarrer. Au démarrage, le serveur écrit une ligne comme celle-ci.

INFO:__main__:serving transport=streamable-http port=3000 auth=True strict=True identity=jwt extensions=none

Trois endpoints permettent ensuite de suivre le serveur, sur le port de santé.

curl -s localhost:3001/health    # {"status":"ok"}     ne touche jamais Trino
curl -s localhost:3001/ready     # {"status":"ready"}  Trino répond
curl -s localhost:3001/metrics   # métriques Prometheus

/health ne touche jamais Trino, pour qu’une sonde de vie ne tue pas le serveur parce que Trino est lent. /ready interroge Trino selon le mode d’identité. En mode jwt, c’est le endpoint public /v1/info de Trino. En modes impersonation et service, c’est un SELECT 1 borné sous TRINO_USER, au nom de personne d’autre. /metrics expose mcp_trino_queries_total, mcp_trino_query_errors_total et mcp_trino_query_duration_seconds.

L’identité dans Trino

Le serveur vérifie d’abord le token de l’appelant : signature contre le JWKS de l’IdP, issuer, audience, expiration. L’audience doit nommer ce serveur (MCP_OIDC_AUDIENCE ou MCP_RESOURCE_URL). Un token émis pour Trino est refusé, même s’il nomme aussi ce serveur. Par défaut, une requête sans token valide reçoit un 401 avant toute requête vers Trino. La variable TRINO_IDENTITY_MODE dit ensuite sous quelle identité Trino exécute.

Mode Qui Trino voit Comment Trino le sait Quand le choisir
jwt (défaut) l’appelant un token pour Trino, obtenu par le serveur par échange (RFC 8693) ; Trino le vérifie avec son authentification JWT l’IdP sait échanger des tokens (RFC 8693) ; testé avec Keycloak 26
impersonation l’appelant le compte du serveur (mot de passe ou certificat client) demande à Trino d’exécuter au nom de l’appelant, sous une règle d’impersonation réservée à ce compte l’IdP ne sait pas échanger de tokens
service TRINO_USER, le même pour tous les appelants un mot de passe, un certificat client, ou rien pour un Trino local seulement si on le nomme : une identité pour tous, annoncée au démarrage et à chaque MCP host

Dans tous les modes, le token de l’appelant ne quitte jamais le serveur. Le nom de l’appelant vient toujours de son token vérifié, jamais d’un en-tête qu’il aurait écrit. Les modes jwt et impersonation refusent de démarrer si la porte n’exige pas un token valide, et un mode inconnu empêche le démarrage.

Chaque utilisateur sous ses propres droits (jwt, par défaut)

Le token de l’appelant est émis pour ce serveur. Le serveur l’échange auprès de l’IdP contre un token dont l’audience est TRINO_TOKEN_EXCHANGE_AUDIENCE, le garde en mémoire jusqu’à peu avant son expiration, et l’envoie à Trino. Le endpoint d’échange est en https seulement.

Côté IdP, donnez à ce serveur un client confidentiel autorisé à échanger des tokens, et rendez-lui accessible l’audience de Trino. Avec Keycloak 26, activez Standard token exchange sur ce client et ajoutez-lui un mapper d’audience vers le client Trino. Les clients de vos MCP hosts placent ce serveur dans l’audience de leurs tokens, par un mapper d’audience lui aussi. Le dossier integration/ du dépôt contient un tel realm, testé à chaque pull request.

Côté Trino, réglez http-server.authentication.type=JWT et http-server.authentication.jwt.key-file sur l’adresse du JWKS de l’IdP. Réglez http-server.authentication.jwt.principal-field sur le même claim que celui lu par le serveur (preferred_username ou sub). required-issuer et required-audience attachent le token à votre IdP et à l’audience de Trino.

Le serveur ne transmet jamais le token qu’il a reçu. Il l’échange contre un token émis pour Trino, avec son propre client. Trino vérifie ce second token et exécute la requête sous le nom de la personne : Ranger ou OPA décident pour elle. Le seul secret du serveur est ce client : réservez-lui, et à lui seul, le droit d’échange vers l’audience de Trino. Une configuration qui accepterait l’audience de Trino refuse de démarrer.

Sans échange de tokens (impersonation)

Quand l’IdP ne sait pas échanger de tokens, le serveur s’authentifie auprès de Trino avec son propre compte, et Trino exécute chaque requête sous le nom de l’appelant vérifié.

export TRINO_IDENTITY_MODE=impersonation
export TRINO_USER=mcp-service
export TRINO_CLIENT_CERT=/certs/mcp-service.crt   # mTLS ; ou TRINO_PASSWORD en https
export TRINO_CLIENT_KEY=/certs/mcp-service.key

Trino authentifie ce compte (par certificat ou par mot de passe, en plus de l’authentification de vos utilisateurs) et l’autorise, lui seul, à agir au nom des utilisateurs. Avec le contrôle d’accès fichier de Trino, cela donne la règle suivante.

{"impersonation": [{"original_user": "mcp-service", "new_user": ".*", "allow": true}]}

Restreignez new_user aux utilisateurs pour qui les agents travaillent. Avec cette règle, personne d’autre ne peut agir au nom d’un autre : un utilisateur qui envoie un en-tête nommant quelqu’un d’autre est refusé par Trino. Gardez le secret de ce compte comme celui de tout service account : qui le détient peut agir au nom de tout utilisateur que la règle permet.

Une identité unique (service, seulement si on la nomme)

export TRINO_IDENTITY_MODE=service
export TRINO_USER=mcp-reader
export TRINO_PASSWORD=...               # ou TRINO_CLIENT_CERT et TRINO_CLIENT_KEY ; https seulement

Chaque requête s’exécute sous TRINO_USER, quel que soit l’appelant. Donnez à cette identité les droits que tout appelant du serveur peut avoir, en lecture seule, pas plus. Le serveur l’annonce par un avertissement au démarrage, dans --check et à chaque MCP host, dans les instructions d’initialisation. La porte reste active par défaut. Pour servir sans porte, en local seulement, posez aussi MCP_AUTH_ENABLED=false et MCP_AUTH_REQUIRED=false ; l’avertissement le dit.

Ce qui le prouve

Le dépôt fait tourner à chaque pull request une intégration réelle, Keycloak et Trino dans Docker. Elle couvre l’échange de tokens, l’impersonation par certificat client, le mode service et chaque refus à la porte. Le sandbox le rejoue en cinq minutes sur la 0.6.0. Deux comptes posent la même question et obtiennent deux réponses. Une requête sans token, un token falsifié et un token émis pour Trino au lieu du serveur reçoivent tous trois un 401.

Les six tools

Tool Arguments Ce qu’il rend
list_catalogs aucun {"catalogs": [...], "truncated": bool}, les catalogs visibles
list_schemas catalog {"schemas": [...], "truncated": bool}, les schémas de ce catalog
list_tables catalog, schema {"tables": [...], "truncated": bool}, les tables et vues de ce schéma
describe_table catalog, schema, table, sample_rows (0 à 20) les colonnes, leurs types et commentaires, truncated, et un échantillon gouverné si on le demande
explain_query sql {"plan": "..."}, le plan d’une requête en lecture, sans l’exécuter
execute_query sql, max_rows (facultatif, inférieur au plafond) {"columns": [...], "rows": [...], "row_count": n, "truncated": bool}

Chaque tool passe par Trino sous le mode d’identité, les tools de liste compris : les métadonnées sont des données, et Trino ne liste que ce que cette identité peut voir. Chaque description de tool est écrite pour un modèle et dit ce que le tool rend. Celles de describe_table et execute_query précisent qu’une valeur masquée ou une ligne absente est la policy d’accès, pas une erreur à relancer. Les erreurs reviennent à l’agent sous la forme {"error": "..."}, avec le message entier de Trino ; un refus de droit est une erreur ordinaire, pas un plantage.

execute_query n’est annoté en lecture seule (readOnlyHint: true) que tant que TRINO_READ_ONLY vaut true. Avec TRINO_READ_ONLY=false, ses annotations et sa description disent qu’il peut écrire, pour que le MCP host demande la confirmation qu’il sauterait pour un tool en lecture seule.

La lecture seule

execute_query accepte tout le SQL que Trino accepte, à condition que ce soit une lecture. La requête est analysée en arbre syntaxique. Elle est refusée si elle contient plus d’une instruction, ou si une écriture (INSERT, UPDATE, DELETE, MERGE, CREATE, DROP, ALTER, GRANT, CALL, SET) apparaît n’importe où dans l’arbre, CTE, sous-requêtes et instruction expliquée par un EXPLAIN compris. EXPLAIN ANALYZE est refusé, puisqu’il exécute ce qu’il explique.

Les table functions (TABLE(...)) sont refusées. Un TABLE(pg.system.query(query => '...')) se lit comme un simple SELECT, mais envoie du SQL brut à la source sous le compte du connecteur, hors des row filters et des column masks. Le catalog system est refusé aussi. Chaque identifiant est validé ([A-Za-z_][A-Za-z0-9_-]*) avant d’entrer dans le SQL. Un nom sans catalog se lit dans le catalog de session (TRINO_CATALOG) : donnez-lui un catalog de données.

Ce que couvre la lecture seule

La garde refuse toute écriture qui passe par ce serveur. Elle ne garantit pas les droits de l’utilisateur dans Trino. En modes jwt et impersonation, Trino exécute la requête sous le nom de l’utilisateur, avec les droits que sa policy lui donne. Un utilisateur autorisé à écrire peut donc toujours écrire par un autre client Trino, avec un token pour Trino que l’IdP lui délivre directement. Le token obtenu par échange reste dans la mémoire du serveur et n’est jamais rendu à l’agent ni au MCP host.

Pour une lecture seule de bout en bout, le moteur doit tenir la ligne lui aussi. Donnez des règles en lecture seule aux identités par lesquelles les agents atteignent Trino. Réservez l’échange vers l’audience de Trino au client de ce serveur. Limitez la règle d’impersonation aux utilisateurs pour qui les agents travaillent. Refusez aussi les table functions et le catalog system dans la policy. La garde reste une seconde ligne. Le blog raconte comment elle a pris sa forme.

Les bornes

Borne Variable Défaut Effet
Plafond de lignes TRINO_MAX_ROWS 100 une ligne de plus est lue pour dire si la réponse est coupée (truncated), et le reste de la requête est annulé dans Trino
Budget d’une requête TRINO_QUERY_TIMEOUT_SECONDS 60 une requête plus longue est annulée dans Trino, et l’agent en est informé
Budget d’un appel MCP_CALL_TIMEOUT_SECONDS 120 passé ce délai, aucune requête ne démarre, celle en cours est annulée, et l’agent reçoit une erreur plutôt qu’une réponse partielle

Une question d’agent doit revenir en moins d’une minute. Une requête plus longue est souvent un scan complet que l’agent doit resserrer, et l’erreur qu’il reçoit le lui dit. Deux minutes par appel laissent la place à un tool qui enchaîne deux ou trois requêtes. 0 retire la limite d’un budget, et --check affiche les deux. Le budget est tenu par le serveur, pas posé en propriété de session, pour qu’un moteur qui interdit les propriétés de session ne refuse pas toutes les requêtes.

Le journal

Chaque réponse porte un en-tête X-Request-Id : celui de la passerelle quand il est simple, sinon un identifiant généré. Chaque appel de tool écrit une ligne JSON dans le journal mcp.audit, indexée par cet identifiant.

{"request_id":"edge-42","tool":"execute_query","subject":"alice","ok":false,"error":"USER_ERROR:PERMISSION_DENIED","duration_ms":84}

Avec la configuration de journal par défaut, la ligne sort précédée de INFO:mcp.audit: ; un collecteur qui attend du JSON pur retire ce préfixe. La ligne dit qui a appelé quel tool, avec quel résultat et en combien de temps. Elle n’a aucun champ qui pourrait contenir le token ou le texte SQL. Une erreur y figure sous forme de code, jamais de message, parce qu’un message de Trino peut citer une valeur lue dans une ligne (Cannot cast '<valeur>' to INT). L’agent, lui, lit le message entier.

Refus et avertissements

Chaque refus porte un en-tête X-Reason et l’identifiant de la requête, jamais le token. Une requête sans token valide (absent, falsifié, expiré, ou émis pour une autre audience, celle de Trino comprise) reçoit 401 unauthenticated, avec un corps qui dit quoi envoyer. Quand MCP_RESOURCE_URL est posé, le serveur publie ses métadonnées de ressource protégée (RFC 9728) sous /.well-known/oauth-protected-resource, et le 401 porte WWW-Authenticate: Bearer resource_metadata="…", comme le demande la spécification d’autorisation MCP.

Une configuration qui laisse quelque chose ouvert est dite trois fois : une ligne WARNING au démarrage, dans --check, et à chaque MCP host dans les instructions d’initialisation. Le cœur avertit du mode service et d’une porte qui n’exige pas de token valide.

Brancher un MCP host

À distance, le MCP host se connecte à l’adresse du serveur (/mcp en streamable-http, le transport par défaut ; /sse pour un MCP host plus ancien). Il envoie le token d’accès de l’utilisateur, émis pour ce serveur. Un MCP host qui implémente l’autorisation MCP trouve l’IdP lui-même, par les métadonnées que le serveur publie quand MCP_RESOURCE_URL est posé.

{
  "mcpServers": {
    "trino": {
      "url": "https://mcp.example.internal/mcp",
      "headers": {"Authorization": "Bearer <le token d'accès de l'utilisateur, émis pour ce serveur>"}
    }
  }
}

En local, Claude Desktop, Cursor ou Mistral Vibe lancent eux-mêmes le serveur en stdio. Il n’y a pas de requête HTTP : l’appelant vient de l’environnement, par le token d’accès de l’utilisateur dans MCP_USER_TOKEN, émis pour ce serveur et vérifié comme un en-tête. En mode strict, le défaut, le serveur refuse de démarrer sans lui. En mode jwt, ce token est échangé contre un token pour Trino, comme en http.

{
  "mcpServers": {
    "trino": {
      "command": "uvx",
      "args": ["akko-mcp-trino"],
      "env": {
        "MCP_TRANSPORT": "stdio",
        "TRINO_HOST": "trino.example.internal", "TRINO_PORT": "8443", "TRINO_HTTP_SCHEME": "https",
        "TRINO_CATALOG": "iceberg",
        "MCP_JWKS_URL": "https://idp.example.com/realms/data/protocol/openid-connect/certs",
        "MCP_OIDC_ISSUER": "https://idp.example.com/realms/data",
        "MCP_OIDC_AUDIENCE": "akko-mcp",
        "TRINO_TOKEN_EXCHANGE_URL": "https://idp.example.com/realms/data/protocol/openid-connect/token",
        "TRINO_TOKEN_EXCHANGE_CLIENT_ID": "akko-mcp",
        "TRINO_TOKEN_EXCHANGE_CLIENT_SECRET": "<le secret client de ce serveur>",
        "TRINO_TOKEN_EXCHANGE_AUDIENCE": "trino",
        "MCP_USER_TOKEN": "<le token d'accès de l'utilisateur, émis pour ce serveur>"
      }
    }
  }
}

En mode impersonation, remplacez les variables TRINO_TOKEN_EXCHANGE_* par TRINO_IDENTITY_MODE=impersonation, TRINO_USER et son certificat ou son mot de passe. Filtrez l’en-tête Host avec MCP_ALLOWED_HOSTS quand le serveur est joignable par un navigateur.

Étendre sans modifier

Un paquet Python peut ajouter des tools ou des comportements autour du cœur, sans le modifier. Il s’enregistre sous un groupe de points d’entrée, et l’exploitant le nomme au démarrage.

[project.entry-points."akko_mcp_trino.tools"]
mes-outils = "mon_paquet.outils:register"
export MCP_TOOL_PLUGINS=mes-outils

Rien n’est chargé qui ne soit nommé, et un nom inconnu empêche le démarrage. Un tool ajouté passe par le même client, donc sous le même mode d’identité, avec la même garde de lecture seule et la même ligne de journal.

Une extension plus large (MCP_EXTENSIONS, groupe akko_mcp_trino.extensions) peut ajouter des modes d’identité, des audiences acceptées (jamais celle de Trino), des gardes à l’entrée, des routes, des tools ou des champs de journal. Ses gardes s’exécutent autour de la vérification du token, jamais à sa place, et la garde de lecture seule s’applique à toute requête. Un mode d’identité qui envoie à Trino un token pour l’appelant doit en obtenir un pour Trino, jamais transmettre celui de l’appelant.

Configuration

Toute la configuration se lit dans l’environnement ; rien n’est codé en dur.

Trino

Variable Rôle Défaut
TRINO_HOST, TRINO_PORT le coordinateur localhost, 8080
TRINO_HTTP_SCHEME http ou https ; un mot de passe ou un token ne part jamais en http http
TRINO_VERIFY vérification TLS : true, false, ou le chemin de l’autorité de Trino true
TRINO_IDENTITY_MODE jwt (chaque requête sous l’appelant, par échange de tokens), impersonation (chaque requête sous l’appelant, au nom duquel agit TRINO_USER) ou service (chaque requête sous TRINO_USER, annoncé par un avertissement) ; les deux premiers exigent https et une porte qui exige un token valide ; un mode inconnu empêche le démarrage jwt
TRINO_TOKEN_EXCHANGE_URL jwt : le endpoint token de l’IdP, en https seulement aucun (obligatoire en jwt)
TRINO_TOKEN_EXCHANGE_CLIENT_ID, TRINO_TOKEN_EXCHANGE_CLIENT_SECRET jwt : le client confidentiel de ce serveur auprès de l’IdP ; --check n’imprime jamais le secret aucun (obligatoires en jwt)
TRINO_TOKEN_EXCHANGE_AUDIENCE jwt : l’audience du token demandé pour Trino, celle que nomme le required-audience de Trino ; jamais une audience que ce serveur accepte aucun (obligatoire en jwt)
TRINO_TOKEN_EXCHANGE_SCOPE jwt : les scopes demandés avec lui, séparés par des espaces aucun
TRINO_TOKEN_EXCHANGE_VERIFY vérification TLS du endpoint d’échange : true, false, ou le chemin d’une autorité true
TRINO_USER le compte du serveur : chaque requête s’exécute sous lui en mode service ; en mode impersonation, il s’authentifie et agit au nom de l’appelant trino
TRINO_PASSWORD son mot de passe, envoyé en authentification Basic, refusé en http aucun
TRINO_CLIENT_CERT, TRINO_CLIENT_KEY un certificat client et sa clé (chemins PEM), pour authentifier le compte en mTLS ; https seulement aucun
TRINO_CATALOG le catalog de session, où se lit un nom sans catalog ; donnez-lui un catalog de données system
TRINO_READ_ONLY refuser les écritures dans execute_query true
TRINO_SOURCE la source que Trino enregistre pour chaque requête le nom du serveur
TRINO_REQUEST_TIMEOUT_SECONDS le délai d’une requête HTTP vers Trino 30
TRINO_MAX_ROWS, TRINO_QUERY_TIMEOUT_SECONDS, MCP_CALL_TIMEOUT_SECONDS les bornes ci-dessus 100, 60, 120

Identité

Variable Rôle Défaut
MCP_AUTH_ENABLED vérifier les tokens des appelants (la porte) true
MCP_AUTH_REQUIRED refuser en 401 une requête sans token valide ; jwt et impersonation refusent de démarrer sans elle true
MCP_JWKS_URL le JWKS de l’IdP aucun (obligatoire quand la vérification est active)
MCP_OIDC_ISSUER l’issuer exigé aucun
MCP_OIDC_AUDIENCE l’audience exigée, celle des tokens émis pour ce serveur (RFC 8707) ; jamais celle de Trino aucun (elle ou MCP_RESOURCE_URL, obligatoire quand la vérification est active)
MCP_RESOURCE_URL l’adresse canonique de ce serveur, comme https://mcp.example.com/mcp : acceptée comme audience, nommée dans les métadonnées de ressource protégée (RFC 9728) et dans le 401 aucun
MCP_JWT_LEEWAY_SECONDS la tolérance sur exp, nbf et iat, pour l’écart d’horloge 30
MCP_ALLOWED_HOSTS le filtre de l’en-tête Host, entrées séparées par des virgules ; vide, tout est servi aucun

La vérification active sans JWKS ou sans audience propre empêche le démarrage. MCP_AUTH_REQUIRED=true avec MCP_AUTH_ENABLED=false l’empêche aussi, puisque le serveur refuserait toutes les requêtes.

Serveur

Variable Rôle Défaut
MCP_TRANSPORT streamable-http, sse ou stdio streamable-http
MCP_PORT, MCP_HEALTH_PORT les ports d’écoute 3000, 3001
MCP_SERVER_NAME le nom annoncé aux MCP hosts trino-mcp
MCP_USER_TOKEN en stdio seulement, le token d’accès de l’utilisateur, émis pour ce serveur aucun (obligatoire en mode strict)
MCP_TOOL_PLUGINS, MCP_EXTENSIONS les plugins et extensions à charger, par nom aucun

Compatibilité

Pris en charge
Python 3.12, 3.13
Trino 351 et suivants ; https avec l’authentification JWT en mode jwt, avec une authentification par mot de passe ou certificat et des règles d’impersonation en mode impersonation
Moteurs de policy OPA, Ranger, contrôle d’accès fichier de Trino
Identity providers tout IdP OIDC qui publie un JWKS, pour la porte ; pour le mode jwt, un IdP qui sait échanger des tokens (RFC 8693), comme Keycloak 26 ; sinon, le mode impersonation
MCP transports streamable-http, sse et stdio, par le SDK officiel
Modèles tous ; le serveur ne parle jamais à un modèle

Aller plus loin

Pour d’autres façons de porter l’identité de l’utilisateur, un audit relié au journal du moteur, le contexte métier du catalogue et la gestion des agents et des accès, voyez le serveur livré dans AKKO et ARCHE. Pour une question, écrivez-nous. Pour signaler un problème du cœur, ouvrez une issue.