ClickHouse

officiel

Interrogez votre serveur de base de données ClickHouse.

Que pouvez-vous faire avec ClickHouse MCP ?

  • Exécuter des requêtes SQL — Demandez d'exécuter toute requête SQL sur votre cluster ClickHouse via run_query, avec des paramètres nommés facultatifs.
  • Lister les bases de données — Demandez de voir toutes les bases de données disponibles sur votre cluster ClickHouse en utilisant list_databases.
  • Parcourir les tables avec des filtres — Demandez de lister les tables d'une base de données avec des motifs LIKE/NOT LIKE et une pagination via list_tables.
  • Inspecter le schéma d'une requête — Demandez de vérifier les colonnes et types de sortie d'une requête avant de l'exécuter en utilisant DESCRIBE.
  • Estimer le coût d'une requête — Demandez d'apercevoir les lectures estimées (parties, lignes, marques) pour un SELECT en utilisant EXPLAIN ESTIMATE.

Documentation

Serveur MCP ClickHouse

PyPI - Version

Un serveur MCP pour ClickHouse.

mcp-clickhouse MCP server

Le serveur implémente MCP 2026-07-28 et prend en charge les poignées de main initialize héritées de 2024-11-05 à 2025-11-25. Les clients modernes utilisent des requêtes sans session et server/discover. Les clients existants peuvent continuer à négocier le protocole hérité.

[!NOTE] Les requêtes HTTP sans MCP-Protocol-Version sont routées via le traitement hérité afin que les clients antérieurs à 2025-06-18 puissent continuer à se connecter. MCP 2026-07-28 permet ce comportement sur les serveurs qui prennent en charge ces clients. Les clients modernes doivent envoyer l'en-tête sur chaque requête POST.

Fonctionnalités

Outils ClickHouse

Les réponses des outils ClickHouse sont des chaînes encodées en JSON. Les entiers en dehors de [-9007199254740991, 9007199254740991] sont renvoyés sous forme de chaînes décimales pour préserver les valeurs exactes dans les clients JavaScript. Cela s'applique aux lignes de requête et aux métadonnées de table entières. Les entiers dans la plage sûre et les booléens conservent leurs types JSON.

  • run_query

    • Exécutez des requêtes SQL sur votre cluster ClickHouse.
    • Entrée : query (chaîne) : la requête SQL à exécuter.
    • Entrée facultative : params (objet) : valeurs nommées pour les espaces réservés ClickHouse {name:Type}. Voir Paramètres de requête.
    • Les requêtes s'exécutent en mode lecture seule par défaut (CLICKHOUSE_ALLOW_WRITE_ACCESS=false), mais les écritures peuvent être activées explicitement si nécessaire.
    • DESCRIBE (<query>) et EXPLAIN ESTIMATE <query> s'exécutent également ici et sont des moyens facultatifs d'inspecter le schéma de résultat d'une requête ou ses lectures estimées. Voir Vérifier une requête avant de l'exécuter.
  • list_databases

    • Liste toutes les bases de données sur votre cluster ClickHouse.
  • list_tables

    • Liste les tables d'une base de données avec pagination.
    • Entrée requise : database (chaîne).
    • Entrées facultatives :
      • like / not_like (chaîne) : applique des filtres LIKE ou NOT LIKE aux noms de tables.
      • page_token (chaîne) : jeton à usage unique renvoyé par un appel précédent. Il est conservé jusqu'à une heure.
      • page_size (entier, défaut 50) : nombre de tables renvoyées par page ; doit être supérieur à 0.
      • include_detailed_columns (booléen, défaut true) : lorsque false, omet les métadonnées de colonnes pour des réponses plus légères tout en conservant le create_table_query complet.
    • Forme de la réponse :
      • tables : tableau d'objets de table pour la page courante.
      • next_page_token : renvoyez cette valeur à usage unique avant son expiration pour récupérer la page suivante, ou null lorsqu'il n'y a plus de tables.
      • total_tables : nombre total de tables correspondant aux filtres fournis.

Paramètres de requête

Passez les valeurs séparément du SQL via l'objet facultatif params :

{
  "query": "SELECT {id:UInt32} AS id, {name:String} AS name",
  "params": {"id": 13, "name": "O'Reilly"}
}

Utilisez les espaces réservés {name:Type} de ClickHouse sans les mettre entre guillemets. Gardez l'accolade ouvrante, le nom et les deux-points adjacents, comme dans {id:UInt32}. Les espaces après les deux-points et dans le type sont pris en charge, comme dans {id: UInt32} et {amount:Decimal(18, 4)}. Pour la compatibilité entre les versions de pilotes prises en charge, commencez les noms par une lettre ou un trait de soulignement et utilisez uniquement des lettres, des chiffres et des traits de soulignement. Le formatage de style Python %s ou %(name)s et les paramètres binaires bruts $name$ du pilote ne sont pas pris en charge. Les appels avec uniquement query fonctionnent toujours. Omettre params, passer null ou passer un objet vide laisse la requête non liée.

Les valeurs de paramètres peuvent être des chaînes JSON, des nombres, des booléens, null ou des tableaux, à condition qu'elles correspondent au type ClickHouse déclaré :

  • Utilisez null avec un type Nullable(...).
  • Passez les entiers exacts en dehors de la plage sûre de JavaScript sous forme de chaînes décimales, par exemple "18446744073709551615" avec {id:UInt64}. Les dates, horodatages et décimales exactes peuvent également être passés sous forme de chaînes avec le type ClickHouse correspondant.
  • Liez les vecteurs comme un seul tableau, par exemple {vector:Array(Float32)} avec "params": {"vector": [0.25, 0.5, 0.75]}.
  • Les valeurs nulles dans les tableaux dépendent du pilote installé. Elles fonctionnent avec clickhouse-connect 1.8.0 mais échouent avec le minimum pris en charge 1.0.0.
  • Les listes et objets JSON ne peuvent pas être liés aux types ClickHouse Tuple et Map.

Les valeurs manquantes et les types incompatibles renvoient des erreurs de requête. Avec un params non vide, une requête contenant de nombreux débuts d'espaces réservés {name: non terminés est rejetée, y compris le texte ressemblant à des espaces réservés dans les commentaires ou les littéraux de chaîne. Les requêtes paramétrées utilisent la même protection en écriture, les mêmes délais d'attente, la même annulation et le même encodage de résultat JSON que les autres requêtes.

Les valeurs de paramètres restent hors des messages de journal SQL normaux du serveur MCP, mais restent dans les arguments d'outils MCP et peuvent apparaître dans les erreurs backend. ClickHouse 26.3.20.7 substitue les valeurs dans le texte de la requête dans system.query_log, system.processes, et system.text_log. La liaison de paramètres n'est pas une fonctionnalité de confidentialité et ne réduit pas le nombre de valeurs vectorielles envoyées dans un appel d'outil.

Vérifier une requête avant de l'exécuter

run_query exécute également DESCRIBE et EXPLAIN ESTIMATE. Les deux sont des vérifications facultatives : utilisez DESCRIBE lorsque vous avez besoin des colonnes et types de sortie d'une requête, et EXPLAIN ESTIMATE avant un SELECT qui pourrait être coûteux.

DESCRIBE (<query>) inspecte le schéma de résultat et renvoie les mêmes métadonnées de colonnes de sortie que DESCRIBE TABLE :

DESCRIBE (SELECT user, sum(amt) FROM events WHERE ts > now() - INTERVAL 30 DAY GROUP BY user)
user      String
sum(amt)  Decimal(38, 2)

ClickHouse doit analyser la requête pour répondre, donc les erreurs d'analyse apparaissent ici, avec le message propre de ClickHouse, au lieu de se produire en cours d'exécution :

DESCRIBE (SELECT usr FROM events)  -> Code: 47. Unknown expression identifier `usr` ... Maybe you meant: ['user']
DESCRIBE (SELECT * FROM nosuch)    -> Code: 60. Unknown table expression identifier 'nosuch'

Une requête qui se décrit proprement peut encore échouer lors de son exécution, sur une limite de mémoire ou une erreur de serveur distant, et elle ne dit rien sur le coût.

EXPLAIN ESTIMATE <query> renvoie les parties, lignes et marques que la requête lirait, une ligne par table, ce qui distingue une recherche par clé primaire d'un balayage complet :

EXPLAIN ESTIMATE SELECT count() FROM events WHERE id = 42
database  table   parts  rows   marks
default   events  1      8192   1

Ce sont des lectures estimées des tables de la famille MergeTree, après élagage de la clé primaire et des partitions. Ce ne sont ni des temps d'exécution ni des tailles de résultat, et les autres moteurs de table ne sont pas couverts.

Aucune des deux instructions n'exécute le corps de la requête, mais l'analyse n'est pas toujours gratuite : DESCRIBE (SELECT (SELECT sleep(1))) exécute la sous-requête scalaire lors de l'analyse. Les deux sont en lecture seule et fonctionnent sous le CLICKHOUSE_ALLOW_WRITE_ACCESS=false par défaut. Voir la documentation ClickHouse pour EXPLAIN ESTIMATE et DESCRIBE.

Outils chDB

  • run_chdb_select_query
    • Exécutez des requêtes SQL en utilisant le moteur ClickHouse embarqué de chDB.
    • Entrée : query (chaîne) : la requête SQL à exécuter.
    • Les entiers en dehors de [-9007199254740991, 9007199254740991] sont renvoyés sous forme de chaînes décimales.
    • Interrogez directement les données de diverses sources (fichiers, URL, bases de données) sans processus ETL.
    • Nécessite l'extra facultatif chdb : pip install 'mcp-clickhouse[chdb]'

Point de terminaison de vérification de santé

Lors de l'exécution avec un transport HTTP ou SSE, un point de terminaison de vérification de santé est disponible à /health. Ce point de terminaison :

  • Renvoie 200 OK (corps : OK) si le serveur est sain et peut se connecter à ClickHouse
  • Renvoie 503 Service Unavailable avec un message d'erreur générique si le serveur ne peut pas se connecter à ClickHouse
  • Renvoie 503 si une sonde ClickHouse ne se termine pas dans les deux secondes. Les requêtes concurrentes partagent une seule sonde en vol
  • Réutilise un résultat de sonde terminé pendant une seconde, donc les sondes qui arrivent en succession rapide ne se connectent pas chacune à ClickHouse. Un échec ou une récupération peut donc être signalé jusqu'à une seconde en retard

Les requêtes GET et HEAD vers le point de terminaison sont intentionnellement non authentifiées et exemptées de la validation Host et Origin afin que les sondes d'orchestration (par exemple, liveness/readiness Kubernetes, équilibreurs de charge) puissent utiliser des IP de pod ou cibles assignées à l'exécution sans configuration supplémentaire. /health est réservé et ne peut pas être utilisé comme chemin de transport MCP. Le corps de la réponse est délibérément minimal pour éviter de fuir les chaînes de version backend ou les détails d'erreur ; déboguez les échecs via les journaux du serveur.

Exemple :

curl http://localhost:8000/health
# Response: OK

Sécurité

Authentification pour les transports HTTP/SSE

Lors de l'utilisation d'un transport HTTP ou SSE, l'authentification est requise par défaut. Le transport stdio (par défaut) ne nécessite pas d'authentification car il ne communique que via l'entrée/sortie standard.

Trois modes d'authentification sont pris en charge. Choisissez-en un :

ModeQuand l'utiliserVariable d'environnement
Jeton porteur statiqueDéploiements simples, services internesCLICKHOUSE_MCP_AUTH_TOKEN
OAuth / OIDC (via FastMCP)Azure Entra, Google, GitHub, WorkOS, etc.FASTMCP_SERVER_AUTH=<provider-class-path> (+ variables FASTMCP_SERVER_AUTH_* spécifiques au fournisseur)
DésactivéDéveloppement local uniquementCLICKHOUSE_MCP_AUTH_DISABLED=true

Le démarrage échoue si aucun de ces éléments n'est configuré pour les transports HTTP/SSE.

Configuration de l'authentification

  1. Générez un jeton sécurisé (peut être n'importe quelle chaîne aléatoire) :

    # Using uuidgen (macOS/Linux)
    uuidgen
    
    # Using openssl
    openssl rand -hex 32
    
  2. Configurez le serveur avec le jeton :

    export CLICKHOUSE_MCP_AUTH_TOKEN="your-generated-token"
    
  3. Configurez votre client MCP pour inclure le jeton dans les requêtes :

    Pour Claude Desktop avec transport HTTP/SSE :

    {
      "mcpServers": {
        "mcp-clickhouse": {
          "url": "http://127.0.0.1:8000",
          "headers": {
            "Authorization": "Bearer your-generated-token"
          }
        }
      }
    }
    

    Remarque : le point de terminaison /health est intentionnellement non authentifié (voir Point de terminaison de vérification de santé ci-dessus). Pour vérifier que l'authentification par jeton porteur rejette réellement les requêtes non authentifiées, frappez le point de terminaison MCP lui-même, par exemple avec l'inspecteur MCP, ou en POSTant une requête JSON-RPC à /mcp avec et sans l'en-tête Authorization et en confirmant que l'appel non authentifié renvoie 401.

OAuth / OIDC via FastMCP

Pour les déploiements de production avec des fournisseurs d'identité (Azure Entra, Google, GitHub, WorkOS, etc.), déléguez l'authentification aux fournisseurs d'authentification intégrés de FastMCP au lieu d'utiliser un jeton statique. Définissez FASTMCP_SERVER_AUTH sur le chemin de classe complet d'un fournisseur d'authentification FastMCP, avec les variables FASTMCP_SERVER_AUTH_* spécifiques au fournisseur, et laissez CLICKHOUSE_MCP_AUTH_TOKEN non défini.

Exemple (Azure Entra) :

export FASTMCP_SERVER_AUTH=fastmcp.server.auth.providers.azure.AzureProvider
export FASTMCP_SERVER_AUTH_AZURE_TENANT_ID="<tenant-id>"
export FASTMCP_SERVER_AUTH_AZURE_CLIENT_ID="<client-id>"
export FASTMCP_SERVER_AUTH_AZURE_CLIENT_SECRET="<client-secret>"
export FASTMCP_SERVER_AUTH_AZURE_BASE_URL="https://mcp.example.com"
export FASTMCP_SERVER_AUTH_AZURE_REQUIRED_SCOPES="read access_as_user"

mcp-clickhouse conserve ces préfixes d'environnement FastMCP 2.14.7 pour les fournisseurs intégrés FastMCP 4.0.0 :

Chemin de classe du fournisseurPréfixe de variable du fournisseur
fastmcp.server.auth.providers.auth0.Auth0ProviderFASTMCP_SERVER_AUTH_AUTH0_
fastmcp.server.auth.providers.aws.AWSCognitoProviderFASTMCP_SERVER_AUTH_AWS_COGNITO_
fastmcp.server.auth.providers.azure.AzureProviderFASTMCP_SERVER_AUTH_AZURE_
fastmcp.server.auth.providers.descope.DescopeProviderFASTMCP_SERVER_AUTH_DESCOPEPROVIDER_
fastmcp.server.auth.providers.discord.DiscordProviderFASTMCP_SERVER_AUTH_DISCORD_
fastmcp.server.auth.providers.github.GitHubProviderFASTMCP_SERVER_AUTH_GITHUB_
fastmcp.server.auth.providers.google.GoogleProviderFASTMCP_SERVER_AUTH_GOOGLE_
fastmcp.server.auth.providers.introspection.IntrospectionTokenVerifierFASTMCP_SERVER_AUTH_INTROSPECTION_
fastmcp.server.auth.providers.jwt.JWTVerifierFASTMCP_SERVER_AUTH_JWT_
fastmcp.server.auth.providers.oci.OCIProviderFASTMCP_SERVER_AUTH_OCI_
fastmcp.server.auth.providers.scalekit.ScalekitProviderFASTMCP_SERVER_AUTH_SCALEKITPROVIDER_
fastmcp.server.auth.providers.supabase.SupabaseProviderFASTMCP_SERVER_AUTH_SUPABASE_
fastmcp.server.auth.providers.workos.WorkOSProviderFASTMCP_SERVER_AUTH_WORKOS_
fastmcp.server.auth.providers.workos.AuthKitProviderFASTMCP_SERVER_AUTH_AUTHKITPROVIDER_

Ajoutez le nom de champ du fournisseur en majuscules au préfixe. Voir la documentation FastMCP pour les exigences de configuration de chaque fournisseur.

Les valeurs d'authentification définies directement dans l'environnement du processus ont priorité, sans tenir compte de la casse. Le chargement par défaut de .env commence dans le répertoire du paquet mcp_clickhouse installé, résout d'abord les liens symboliques, puis remonte jusqu'à la racine du système de fichiers. Il charge le premier .env qu'il trouve et ne charge rien s'il n'y en a pas. Il ne lit jamais le répertoire de travail, quelle que soit la manière dont le serveur est lancé. Une copie du code source trouve normalement le .env à la racine du dépôt. Ce fichier peut également fournir FASTMCP_SERVER_AUTH et ses champs de fournisseur. Ses valeurs ont priorité sur le fichier d'authentification explicite ou de compatibilité. Pour la compatibilité FastMCP 2, mcp-clickhouse lit les champs de fournisseur manquants depuis .env dans le répertoire de travail, mais ce repli de compatibilité ne peut pas sélectionner FASTMCP_SERVER_AUTH. Un FASTMCP_ENV_FILE défini dans le processus remplace ce repli de compatibilité et peut fournir à la fois le sélecteur et les champs de fournisseur. Définissez-le avant le démarrage. Le chargeur de compatibilité mcp-clickhouse ne lit que FASTMCP_SERVER_AUTH et FASTMCP_SERVER_AUTH_* de ce fichier, il ne peut donc pas injecter de paramètres CLICKHOUSE_*. FastMCP 4 peut utiliser le même fichier pour ses propres paramètres plus larges. Un fournisseur personnalisé ne reçoit aucun argument de constructeur dérivé de l'environnement et doit prendre en charge la construction sans argument.

Traitez à la fois les fichiers .env découverts et ceux du répertoire de travail comme une configuration d'authentification de confiance. Toute personne pouvant créer ou écrire un .env dans n'importe quel répertoire du paquet jusqu'à la racine du système de fichiers peut contrôler quel fichier est découvert, sélectionner le fournisseur et définir ses champs. Toute personne pouvant écrire le fichier du répertoire de travail contrôle chaque champ de fournisseur absent du processus et de la configuration découverte, y compris les clés de signature, les émetteurs et les points de terminaison, ainsi que les secrets clients. Un FASTMCP_ENV_FILE défini dans le processus qui pointe vers un fichier appartenant à l'opérateur désactive le repli du répertoire de travail.

FastMCP 4 a modifié le stockage par défaut du proxy client OAuth. Les déploiements qui dépendaient du stockage par défaut du proxy OAuth de FastMCP 2 doivent faire réenregistrer et réautoriser les clients. Le stockage personnalisé compatible, les jetons porteurs statiques et la vérification JWT ne sont pas affectés.

Mode Développement (Désactivation de l'Authentification)

Pour le développement local et les tests uniquement, vous pouvez désactiver l'authentification en définissant :

export CLICKHOUSE_MCP_AUTH_DISABLED=true
export CLICKHOUSE_MCP_ALLOWED_HOSTS=127.0.0.1:8000,localhost:8000

AVERTISSEMENT : Utilisez ceci uniquement pour le développement local. Ne désactivez pas l'authentification lorsque le serveur est exposé à un réseau.

Configuration

Ce serveur MCP prend en charge à la fois ClickHouse et chDB. Vous pouvez activer l'un ou l'autre, ou les deux, selon vos besoins. Python 3.10 à 3.14 sont pris en charge. Python 3.12 est recommandé pour les lancements locaux.

  1. Ouvrez le fichier de configuration de Claude Desktop situé à :

    • Sur macOS : ~/Library/Application Support/Claude/claude_desktop_config.json
    • Sur Windows : %APPDATA%/Claude/claude_desktop_config.json
  2. Ajoutez ce qui suit :

{
  "mcpServers": {
    "mcp-clickhouse": {
      "command": "uv",
      "args": [
        "run",
        "--with",
        "mcp-clickhouse",
        "--python",
        "3.12",
        "mcp-clickhouse"
      ],
      "env": {
        "CLICKHOUSE_HOST": "<clickhouse-host>",
        "CLICKHOUSE_PORT": "<clickhouse-port>",
        "CLICKHOUSE_USER": "<clickhouse-user>",
        "CLICKHOUSE_PASSWORD": "<clickhouse-password>",
        "CLICKHOUSE_ROLE": "<clickhouse-role>",
        "CLICKHOUSE_SECURE": "true",
        "CLICKHOUSE_VERIFY": "true",
        "CLICKHOUSE_CONNECT_TIMEOUT": "30"
      }
    }
  }
}

Mettez à jour les variables d'environnement pour pointer vers votre propre service ClickHouse.

Ou, si vous souhaitez l'essayer avec le SQL Playground ClickHouse, vous pouvez utiliser la configuration suivante :

{
  "mcpServers": {
    "mcp-clickhouse": {
      "command": "uv",
      "args": [
        "run",
        "--with",
        "mcp-clickhouse",
        "--python",
        "3.12",
        "mcp-clickhouse"
      ],
      "env": {
        "CLICKHOUSE_HOST": "sql-clickhouse.clickhouse.com",
        "CLICKHOUSE_PORT": "8443",
        "CLICKHOUSE_USER": "demo",
        "CLICKHOUSE_PASSWORD": "",
        "CLICKHOUSE_SECURE": "true",
        "CLICKHOUSE_VERIFY": "true",
        "CLICKHOUSE_CONNECT_TIMEOUT": "30"
      }
    }
  }
}

Pour chDB (moteur ClickHouse embarqué), ajoutez la configuration suivante :

{
  "mcpServers": {
    "mcp-clickhouse": {
      "command": "uv",
      "args": [
        "run",
        "--with",
        "mcp-clickhouse[chdb]",
        "--python",
        "3.12",
        "mcp-clickhouse"
      ],
      "env": {
        "CHDB_ENABLED": "true",
        "CLICKHOUSE_ENABLED": "false",
        "CHDB_DATA_PATH": "/path/to/chdb/data"
      }
    }
  }
}

Vous pouvez également activer à la fois ClickHouse et chDB simultanément :

{
  "mcpServers": {
    "mcp-clickhouse": {
      "command": "uv",
      "args": [
        "run",
        "--with",
        "mcp-clickhouse[chdb]",
        "--python",
        "3.12",
        "mcp-clickhouse"
      ],
      "env": {
        "CLICKHOUSE_HOST": "<clickhouse-host>",
        "CLICKHOUSE_PORT": "<clickhouse-port>",
        "CLICKHOUSE_USER": "<clickhouse-user>",
        "CLICKHOUSE_PASSWORD": "<clickhouse-password>",
        "CLICKHOUSE_SECURE": "true",
        "CLICKHOUSE_VERIFY": "true",
        "CLICKHOUSE_CONNECT_TIMEOUT": "30",
        "CHDB_ENABLED": "true",
        "CHDB_DATA_PATH": "/path/to/chdb/data"
      }
    }
  }
}
  1. Localisez l'entrée de commande pour uv et remplacez-la par le chemin absolu vers l'exécutable uv. Cela garantit que la version correcte de uv est utilisée au démarrage du serveur. Sur un Mac, vous pouvez trouver ce chemin en utilisant which uv.

  2. Redémarrez Claude Desktop pour appliquer les modifications.

Accès en Écriture Optionnel

Par défaut, ce MCP impose des requêtes en lecture seule afin que des mutations accidentelles ne puissent pas se produire pendant l'exploration. Pour autoriser les instructions DDL ou INSERT, définissez la variable d'environnement CLICKHOUSE_ALLOW_WRITE_ACCESS sur true. Le serveur continue d'imposer le mode lecture seule si l'instance ClickHouse elle-même interdit les écritures.

Protection contre les Opérations Destructrices

Même lorsque l'accès en écriture est activé (CLICKHOUSE_ALLOW_WRITE_ACCESS=true), les opérations destructrices nécessitent un indicateur d'adhésion supplémentaire pour la sécurité. La vérification couvre toute instruction DROP (y compris les clauses ALTER TABLE ... DROP PARTITION / DROP PART / DROP COLUMN), tout TRUNCATE, DELETE et UPDATE (à la fois les instructions légères et les mutations ALTER TABLE ... DELETE / ALTER TABLE ... UPDATE), REPLACE TABLE, CREATE OR REPLACE, ALTER TABLE ... REPLACE PARTITION, ALTER TABLE ... CLEAR COLUMN / CLEAR INDEX / CLEAR PROJECTION, et DETACH ... PERMANENTLY. Les mots-clés dans les littéraux de chaîne, les identifiants entre guillemets, les commentaires SQL et les noms de paramètres {name:Type} sont ignorés, donc ils ne déclenchent pas la vérification ni ne masquent une instruction de celle-ci.

Cette vérification s'exécute dans le serveur MCP et constitue une protection de bonne foi contre les accidents. Ce n'est pas une frontière de sécurité. La frontière de sécurité est constituée par les privilèges de l'utilisateur ClickHouse. Le mode lecture seule (par défaut) est appliqué côté serveur via readonly=1. La barrière des opérations destructrices n'est pas appliquée côté serveur.

Pour le mode écriture, donnez au serveur MCP un utilisateur ClickHouse dédié avec uniquement les privilèges dont il a besoin :

CREATE USER mcp_agent IDENTIFIED BY '...';
GRANT SELECT, INSERT, CREATE TABLE, ALTER ADD COLUMN ON mydb.* TO mcp_agent;

Toute instruction en dehors de ces privilèges échoue alors côté serveur avec ACCESS_DENIED, indépendamment des indicateurs MCP. Les paramètres serveur max_table_size_to_drop et max_partition_size_to_drop peuvent également limiter le rayon d'impact s'ils sont épinglés avec des contraintes de paramètres.

Pour activer les opérations destructrices, définissez les deux indicateurs :

"env": {
  "CLICKHOUSE_ALLOW_WRITE_ACCESS": "true",
  "CLICKHOUSE_ALLOW_DROP": "true"
}

Cette approche à deux niveaux rend la suppression accidentelle difficile :

  • Opérations d'écriture (INSERT, CREATE, ALTER ADD COLUMN) nécessitent CLICKHOUSE_ALLOW_WRITE_ACCESS=true
  • Opérations destructrices (DROP, TRUNCATE, DELETE, UPDATE, et le reste de la liste ci-dessus) nécessitent en plus CLICKHOUSE_ALLOW_DROP=true

Exécution Sans uv (Utilisation de Python Système)

Si vous préférez utiliser l'installation Python système au lieu de uv, vous pouvez installer le paquet depuis PyPI et l'exécuter directement :

  1. Installez le paquet en utilisant pip :

    python3 -m pip install mcp-clickhouse
    

    Pour installer également le support chDB :

    python3 -m pip install 'mcp-clickhouse[chdb]'
    

    Pour mettre à niveau vers la dernière version :

    python3 -m pip install --upgrade mcp-clickhouse
    
  2. Mettez à jour votre configuration Claude Desktop pour utiliser Python directement :

{
  "mcpServers": {
    "mcp-clickhouse": {
      "command": "python3",
      "args": [
        "-m",
        "mcp_clickhouse.main"
      ],
      "env": {
        "CLICKHOUSE_HOST": "<clickhouse-host>",
        "CLICKHOUSE_PORT": "<clickhouse-port>",
        "CLICKHOUSE_USER": "<clickhouse-user>",
        "CLICKHOUSE_PASSWORD": "<clickhouse-password>",
        "CLICKHOUSE_SECURE": "true",
        "CLICKHOUSE_VERIFY": "true",
        "CLICKHOUSE_CONNECT_TIMEOUT": "30"
      }
    }
  }
}

Alternativement, vous pouvez utiliser le script installé directement :

{
  "mcpServers": {
    "mcp-clickhouse": {
      "command": "mcp-clickhouse",
      "env": {
        "CLICKHOUSE_HOST": "<clickhouse-host>",
        "CLICKHOUSE_PORT": "<clickhouse-port>",
        "CLICKHOUSE_USER": "<clickhouse-user>",
        "CLICKHOUSE_PASSWORD": "<clickhouse-password>",
        "CLICKHOUSE_SECURE": "true",
        "CLICKHOUSE_VERIFY": "true",
        "CLICKHOUSE_CONNECT_TIMEOUT": "30"
      }
    }
  }
}

Remarque : Assurez-vous d'utiliser le chemin complet vers l'exécutable Python ou le script mcp-clickhouse s'ils ne sont pas dans votre PATH système. Vous pouvez trouver les chemins en utilisant :

  • which python3 pour l'exécutable Python
  • which mcp-clickhouse pour le script installé

Middleware Personnalisé

Vous pouvez ajouter un middleware personnalisé au serveur MCP sans modifier le code source. FastMCP fournit un système de middleware qui vous permet d'intercepter et de traiter les messages du protocole MCP (appels d'outils, lectures de ressources, invites, etc.).

Comment l'Utiliser

  1. Créez un module Python avec des classes de middleware étendant Middleware et une fonction setup_middleware(mcp) :
# my_middleware.py
import logging
from fastmcp.server.middleware import Middleware, MiddlewareContext, CallNext

logger = logging.getLogger("my-middleware")

class LoggingMiddleware(Middleware):
    """Log all tool calls."""
    
    async def on_call_tool(self, context: MiddlewareContext, call_next: CallNext):
        tool_name = context.message.name if hasattr(context.message, 'name') else 'unknown'
        logger.info(f"Calling tool: {tool_name}")
        result = await call_next(context)
        logger.info(f"Tool {tool_name} completed")
        return result

def setup_middleware(mcp):
    """Register middleware with the MCP server."""
    mcp.add_middleware(LoggingMiddleware())
  1. Définissez la variable d'environnement MCP_MIDDLEWARE_MODULE sur le nom du module (sans l'extension .py) :
{
  "mcpServers": {
    "mcp-clickhouse": {
      "command": "uv",
      "args": ["run", "--with", "mcp-clickhouse", "--python", "3.12", "mcp-clickhouse"],
      "env": {
        "CLICKHOUSE_HOST": "<clickhouse-host>",
        "CLICKHOUSE_USER": "<clickhouse-user>",
        "CLICKHOUSE_PASSWORD": "<clickhouse-password>",
        "MCP_MIDDLEWARE_MODULE": "my_middleware"
      }
    }
  }
}
  1. Assurez-vous que votre module de middleware est dans le chemin d'importation de Python (par exemple, dans le même répertoire où le serveur MCP s'exécute, ou installé comme un paquet).

Exemple de Middleware

Un module de middleware d'exemple est fourni dans example_middleware.py montrant des modèles courants :

  • Journalisation de toutes les requêtes MCP
  • Journalisation des appels d'outils spécifiquement
  • Mesure du temps de traitement des requêtes

Pour utiliser l'exemple :

"env": {
  "MCP_MIDDLEWARE_MODULE": "example_middleware"
}

Capacités du Middleware

La classe de base Middleware fournit des hooks pour différentes opérations MCP :

  • on_message(context, call_next) - Appelé pour tous les messages
  • on_request(context, call_next) - Appelé pour toutes les requêtes
  • on_notification(context, call_next) - Appelé pour toutes les notifications
  • on_call_tool(context, call_next) - Appelé lorsqu'un outil est exécuté
  • on_read_resource(context, call_next) - Appelé lorsqu'une ressource est lue
  • on_get_prompt(context, call_next) - Appelé lorsqu'une invite est récupérée
  • on_list_tools(context, call_next) - Appelé lors de la liste des outils
  • on_list_resources(context, call_next) - Appelé lors de la liste des ressources
  • on_list_resource_templates(context, call_next) - Appelé lors de la liste des modèles de ressources
  • on_list_prompts(context, call_next) - Appelé lors de la liste des invites

Chaque hook reçoit un objet MiddlewareContext contenant le message et les métadonnées, et une fonction call_next pour continuer le pipeline.

Configuration Dynamique du Client via l'État de Contexte

Le middleware peut remplacer la configuration du client ClickHouse par requête en utilisant la clé d'état de contexte CLIENT_CONFIG_OVERRIDES_KEY. Le serveur fusionne ces remplacements avec la configuration de base provenant des variables d'environnement.

from fastmcp.server.dependencies import get_context
from fastmcp.server.middleware import CallNext, Middleware, MiddlewareContext
from mcp_clickhouse.mcp_server import CLIENT_CONFIG_OVERRIDES_KEY


class ClientConfigMiddleware(Middleware):
    async def on_call_tool(self, context: MiddlewareContext, call_next: CallNext):
        ctx = get_context()
        await ctx.set_state(
            CLIENT_CONFIG_OVERRIDES_KEY,
            {
                "connect_timeout": 60,
                "send_receive_timeout": 120,
            },
            serializable=False,
        )
        return await call_next(context)

Cela permet des cas d'utilisation avancés comme les ajustements dynamiques de délai d'attente, le routage spécifique au locataire ou les paramètres de connexion par utilisateur.

La valeur d'état doit être un dictionnaire. Les valeurs imbriquées settings et generic_args doivent être des mappings et sont fusionnées avec la configuration de base. Les valeurs invalides font échouer l'appel d'outil avant qu'un client ClickHouse ne soit créé. CLICKHOUSE_ROLE reste actif sauf si le remplacement fournit explicitement settings.role. Les clés de niveau supérieur role et ch_role, ainsi que les mêmes clés sous generic_args, sont rejetées.

Définissez verify, ca_cert, client_cert, client_cert_key, tls_mode, server_host_name, et pool_mgr uniquement comme remplacements de niveau supérieur. Ils ne peuvent pas être imbriqués sous generic_args. Un pool_mgr personnalisé ne peut pas être combiné avec les paramètres de certificat client ou d'autorité de certification gérés. Les paramètres de requête DSN ne peuvent pas définir ces clés, et un DSN ne peut pas sélectionner le backend chdb. Utilisez des remplacements explicites de niveau supérieur host, port, username, password, database et secure pour modifier la connexion. Un DSN transféré ne remplace pas les champs de connexion de base remplis ni ne sélectionne TLS. Il peut remplir les champs vides et fournir des paramètres de requête pris en charge tels que query_limit. Les remplacements secure et verify acceptent les booléens ou les chaînes true et false. verify accepte également proxy, qui se comporte comme tls_mode: proxy lorsque tls_mode n'est pas défini et utilise donc l'authentification Basic avec le mot de passe de l'environnement. Un remplacement secure sélectionne l'interface https ou http correspondante et ne change pas le port. Un remplacement explicite interface doit être http ou https et être en accord avec secure. Après la fusion des remplacements, les modes de certificat client par défaut et mutual omettent le mot de passe. Les modes proxy et strict utilisent l'authentification Basic avec le mot de passe de l'environnement sauf si le remplacement fournit ses propres informations d'identification.

Traitez ces remplacements comme une entrée de middleware de confiance. Le middleware doit authentifier et autoriser les valeurs dérivées des requêtes avant de les définir. Utilisez serializable=False afin que FastMCP conserve la valeur dans l'état local de la requête. Le serializable=True par défaut stocke l'état de session et est rejeté par le serveur. Le serveur prend un instantané de la valeur avant de répartir le travail de base de données bloquant. Ne stockez pas de données de locataire dans l'état de contexte de session. Un remplacement de session rejeté reste attaché à une session MCP héritée et provoque l'échec des appels d'outils ultérieurs dans cette session jusqu'à ce que le client se reconnecte. Un rôle ClickHouse par requête est une configuration de connexion, pas une frontière d'autorisation de locataire. Appliquez l'isolation des locataires avec les utilisateurs, rôles et privilèges ClickHouse.

Développement

  1. Dans le répertoire test-services, exécutez docker compose up -d pour démarrer le cluster ClickHouse.

  2. Ajoutez les variables suivantes à un fichier .env à la racine du dépôt.

Remarque : L'utilisation de l'utilisateur default dans ce contexte est destinée uniquement au développement local.

CLICKHOUSE_HOST=localhost
CLICKHOUSE_PORT=8123
CLICKHOUSE_USER=default
CLICKHOUSE_PASSWORD=clickhouse
  1. Exécutez uv sync pour installer les dépendances. Pour installer uv, suivez les instructions ici. Ensuite, faites source .venv/bin/activate.

  2. Pour des tests faciles avec l'inspecteur MCP, exécutez uv run fastmcp dev inspector mcp_clickhouse/mcp_server.py:mcp pour démarrer le serveur MCP.

  3. Pour tester avec le transport HTTP et le point de terminaison de vérification de santé :

    # For development, disable authentication
    CLICKHOUSE_MCP_SERVER_TRANSPORT=http CLICKHOUSE_MCP_AUTH_DISABLED=true CLICKHOUSE_MCP_ALLOWED_HOSTS=127.0.0.1:8000,localhost:8000 python -m mcp_clickhouse.main
    
    # Or with authentication (generate a token first)
    CLICKHOUSE_MCP_SERVER_TRANSPORT=http CLICKHOUSE_MCP_AUTH_TOKEN="your-token" python -m mcp_clickhouse.main
    
    # Then in another terminal:
    curl http://localhost:8000/health
    

Variables d'Environnement

La configuration est divisée en groupes indépendants. Les mélanger est une cause fréquente d’échecs de connexion difficiles à déboguer :

GroupeVariablesContrôle
Connexion à la base de données ClickHouseCLICKHOUSE_HOST, CLICKHOUSE_PORT, CLICKHOUSE_SECURE, CLICKHOUSE_VERIFY, variables de certificatComment ce serveur MCP se connecte à votre cluster ClickHouse via l’interface HTTP
Serveur MCP / transportCLICKHOUSE_MCP_*, FASTMCP_SERVER_AUTH, FASTMCP_SERVER_AUTH_*, FASTMCP_ENV_FILETransport MCP, authentification et limites d’exécution des outils de requête
Middleware / chDBMCP_MIDDLEWARE_MODULE, CHDB_*Extensions optionnelles

[!IMPORTANT] CLICKHOUSE_SECURE, CLICKHOUSE_VERIFY, CLICKHOUSE_CA_CERT, CLICKHOUSE_CLIENT_CERT, CLICKHOUSE_CLIENT_CERT_KEY, CLICKHOUSE_TLS_MODE et CLICKHOUSE_PORT s’appliquent uniquement à la connexion sortante à la base de données ClickHouse. Ils ne configurent pas TLS, certificats clients, ports ou authentification pour le point de terminaison MCP entrant HTTP/SSE.

Exemple : si le serveur MCP s’exécute dans Kubernetes derrière une passerelle d’entrée qui termine TLS, cela relève du transport MCP. Gardez CLICKHOUSE_SECURE aligné sur la façon dont le pod atteint ClickHouse lui-même (HTTPS → true, HTTP simple → false). Définir CLICKHOUSE_SECURE=false parce que le serveur MCP est derrière une passerelle d’entrée fera que le serveur se connectera à ClickHouse via HTTP—souvent sur un port HTTPS uniquement—et produira des erreurs HTTP/TLS opaques dans les journaux du serveur.

Connexion à la base de données ClickHouse

Ces variables configurent le client HTTP clickhouse-connect et le comportement des outils basés sur ClickHouse tels que run_query, list_databases et list_tables. mcp-clickhouse nécessite clickhouse-connect 1.x, à partir de 1.0.0.

Variables requises
  • CLICKHOUSE_HOST : Le nom d’hôte de votre serveur ClickHouse (point de terminaison de la base de données, pas l’adresse de liaison du serveur MCP)
  • CLICKHOUSE_USER : Le nom d’utilisateur pour l’authentification ClickHouse
  • CLICKHOUSE_PASSWORD : Le mot de passe pour l’authentification ClickHouse
    • Requis sauf si CLICKHOUSE_CLIENT_CERT utilise la valeur par défaut ou le mode TLS "mutual"
    • En mode par défaut ou "mutual", l’authentification par certificat est utilisée et le mot de passe n’est pas envoyé

[!CAUTION] Il est important de traiter votre utilisateur de base de données MCP comme vous le feriez pour tout client externe se connectant à votre base de données, en n’accordant que les privilèges minimum nécessaires à son fonctionnement. L’utilisation d’utilisateurs par défaut ou administratifs doit être strictement évitée à tout moment.

Variables optionnelles
  • CLICKHOUSE_PORT : Port de l’interface HTTP de votre serveur ClickHouse
    • Défaut : 8443 si CLICKHOUSE_SECURE=true, 8123 si CLICKHOUSE_SECURE=false
    • Généralement inutile à définir sauf en cas de port non standard
    • Doit être un port d’interface HTTP, pas le port du protocole TCP natif utilisé par clickhouse-client
    • Valeurs courantes :
      • HTTP : 8123 (simple) / 8443 (TLS) — utilisé par ce serveur et ClickHouse Cloud HTTPS
      • TCP natif (non pris en charge ici) : 9000 (simple) / 9440 (TLS) — utilisé par clickhouse-client
    • Si le serveur répond avec Port 9000 is for clickhouse-client program, vous êtes dirigé vers le protocole natif ; passez au port HTTP (8123/8443 ou le mappage HTTP de votre déploiement)
  • CLICKHOUSE_ROLE : Le rôle ClickHouse à utiliser pour l’authentification
    • Défaut : Aucun
    • Définissez-le si votre utilisateur nécessite un rôle spécifique
  • CLICKHOUSE_SECURE : Active HTTPS pour la connexion à la base de données ClickHouse (pas pour les clients MCP)
    • Défaut : "true"
    • Définissez sur "false" uniquement lorsque le serveur MCP atteint ClickHouse via HTTP simple (typique pour Docker Compose local sur le port 8123)
    • Laissez "true" pour ClickHouse Cloud et tout point de terminaison de base de données HTTPS—même si le serveur MCP lui-même est exposé via HTTP, stdio ou une passerelle d’entrée qui termine TLS séparément
    • Une inadéquation de ce drapeau avec le port de la base de données (par ex. CLICKHOUSE_SECURE=false contre le port 8443) est une erreur de configuration fréquente et se manifeste généralement par des erreurs de client HTTP déroutantes plutôt qu’un message clair de « schéma incorrect »
  • CLICKHOUSE_VERIFY : Active/désactive la vérification des certificats SSL pour la connexion HTTPS ClickHouse
    • Défaut : "true"
    • Définissez sur "false" pour désactiver la vérification des certificats (non recommandé en production)
    • Certificats TLS : Le package utilise le magasin de confiance de votre système d’exploitation via truststore.inject_into_ssl() au démarrage. La gestion SSL par défaut de Python est utilisée si l’injection est désactivée avec MCP_CLICKHOUSE_TRUSTSTORE_DISABLE=1 ou échoue.
  • MCP_CLICKHOUSE_TRUSTSTORE_DISABLE : Désactive l’intégration du magasin de confiance du système d’exploitation à l’échelle du processus pour TLS
    • Défaut : non défini (l’intégration du magasin de confiance est activée)
    • Définissez exactement sur "1" avant le démarrage pour ignorer truststore.inject_into_ssl() et utiliser la gestion SSL par défaut de Python. D’autres valeurs ne désactivent pas l’intégration.
    • Cela ne désactive pas la vérification des certificats. CLICKHOUSE_VERIFY contrôle toujours la vérification pour la connexion HTTPS ClickHouse.
  • CLICKHOUSE_CA_CERT : Chemin vers un bundle de certificats CA PEM pour la connexion HTTPS ClickHouse
    • Défaut : Aucun (utilise le magasin de confiance du système d’exploitation sauf si l’injection du magasin de confiance est désactivée ou échoue)
    • Utilisez-le seul lorsqu’un serveur ClickHouse ou un proxy privé présente un certificat signé par une CA privée. Cela modifie la vérification du certificat du serveur et n’active pas l’authentification par certificat client.
    • Nécessite CLICKHOUSE_SECURE=true et CLICKHOUSE_VERIFY=true
  • CLICKHOUSE_CLIENT_CERT : Chemin vers un certificat client PEM pour la connexion HTTPS ClickHouse
    • Défaut : Aucun
    • Le fichier peut également contenir la clé privée. Sinon, définissez CLICKHOUSE_CLIENT_CERT_KEY.
    • L’utilisateur ClickHouse provient toujours de CLICKHOUSE_USER.
  • CLICKHOUSE_CLIENT_CERT_KEY : Chemin vers la clé privée PEM pour CLICKHOUSE_CLIENT_CERT
    • Défaut : Aucun
    • Optionnel lorsque la clé privée est incluse dans le fichier de certificat client
    • Ne peut pas être utilisé sans CLICKHOUSE_CLIENT_CERT
  • CLICKHOUSE_TLS_MODE : Comment clickhouse-connect utilise CLICKHOUSE_CLIENT_CERT
    • Défaut : Aucun, ce qui se comporte comme "mutual" lorsqu’un certificat client est défini
    • "mutual" : Utilisez le certificat client pour l’authentification utilisateur X.509 ClickHouse. CLICKHOUSE_PASSWORD est optionnel et n’est pas envoyé.
    • "proxy" : Présentez le certificat client à un proxy de terminaison TLS, puis utilisez l’authentification Basic ClickHouse. CLICKHOUSE_PASSWORD est requis.
    • "strict" : Présentez le certificat client parce que le serveur ClickHouse en exige un au niveau de la couche TLS, puis utilisez l’authentification Basic ClickHouse. CLICKHOUSE_PASSWORD est requis. Ce mode ne renforce pas la vérification du certificat du serveur. CLICKHOUSE_VERIFY contrôle cette vérification.
    • clickhouse-connect traite "proxy" et "strict" de manière identique. Les deux noms documentent l’intention.
    • Les valeurs sont tronquées et insensibles à la casse. Une valeur vide est traitée comme non définie. D’autres valeurs sont rejetées avant la création d’un client ClickHouse, lors du premier appel d’outil ClickHouse ou de la sonde /health.
    • Nécessite CLICKHOUSE_CLIENT_CERT. Toutes les options de certificat client nécessitent CLICKHOUSE_SECURE=true.
  • CLICKHOUSE_SERVER_HOST_NAME : Nom d’hôte du serveur pour le remplacement SNI et la validation du certificat sur la connexion ClickHouse
    • Défaut : Aucun (utilise le nom d’hôte de la connexion)
    • Utile lors de la connexion via des proxys ou des équilibreurs de charge où le nom d’hôte du certificat diffère du nom d’hôte de la connexion. Lorsqu’il est défini, ce nom d’hôte sera utilisé à la fois pour SNI (Server Name Indication) pendant la poignée de main TLS et pour la validation du nom d’hôte du certificat.
  • CLICKHOUSE_PROXY_PATH : Préfixe de chemin d’URL pour le point de terminaison HTTP ClickHouse
    • Défaut : Aucun
    • Définissez-le lorsque l’interface HTTP ClickHouse est exposée derrière un proxy inverse sous un préfixe de chemin (par exemple, /clickhouse)
  • CLICKHOUSE_CONNECT_TIMEOUT : Délai d’expiration de connexion en secondes pour le client ClickHouse
    • Défaut : "30"
    • Augmentez cette valeur si vous rencontrez des délais d’expiration de connexion
  • CLICKHOUSE_SEND_RECEIVE_TIMEOUT : Délai d’expiration d’envoi/réception en secondes pour le client ClickHouse
    • Défaut : la plus basse de 300 ou CLICKHOUSE_MCP_QUERY_TIMEOUT + 5, afin que les threads de travail se débloquent peu après un délai d’expiration de requête
    • Si défini explicitement, la valeur est utilisée telle quelle (par ex. "300" pour les requêtes de longue durée)
  • CLICKHOUSE_DATABASE : Base de données ClickHouse par défaut à utiliser
    • Défaut : Aucun (utilise la valeur par défaut du serveur)
    • Définissez-la pour vous connecter automatiquement à une base de données spécifique
  • CLICKHOUSE_ENABLED : Active/désactive les outils de base de données ClickHouse
    • Défaut : "true"
    • Définissez sur "false" pour désactiver les outils ClickHouse lors de l’utilisation de chDB uniquement
  • CLICKHOUSE_ALLOW_WRITE_ACCESS : Autorise les opérations d’écriture (DDL et DML) contre ClickHouse
    • Défaut : "false"
    • Définissez sur "true" pour autoriser les DDL et DML non destructifs (CREATE, INSERT, ALTER ADD COLUMN). Les instructions destructives nécessitent en plus CLICKHOUSE_ALLOW_DROP=true
    • Lorsqu’elle est désactivée (par défaut), les requêtes s’exécutent avec le paramètre readonly=1 pour empêcher les modifications de données
  • CLICKHOUSE_ALLOW_DROP : Autorise les opérations destructives (tout DROP ou TRUNCATE, DELETE et UPDATE y compris les variantes ALTER TABLE, REPLACE TABLE / REPLACE PARTITION / CREATE OR REPLACE, CLEAR COLUMN / CLEAR INDEX / CLEAR PROJECTION et DETACH ... PERMANENTLY)
    • Défaut : "false"
    • N’a d’effet que lorsque CLICKHOUSE_ALLOW_WRITE_ACCESS=true est également défini
    • Cette barrière est une protection contre les accidents au mieux dans le serveur MCP, pas une frontière de sécurité. Restreignez les autorisations de l’utilisateur ClickHouse pour une application réelle (voir Protection contre les opérations destructives)
Fichiers de certificats TLS ClickHouse

Les variables de certificat contiennent des chemins de fichiers, pas des contenus PEM. mcp-clickhouse transmet ces chemins à clickhouse-connect. Pour Docker ou Kubernetes, montez le certificat et la clé privée en tant que fichiers en lecture seule et utilisez leurs chemins à l’intérieur du conteneur. Ne gravez pas une clé privée dans une image, ne la committez pas dans le contrôle de source et ne mettez pas son contenu dans une variable d’environnement.

En mode mutual, le certificat client configuré identifie ce processus mcp-clickhouse comme CLICKHOUSE_USER. Il n’authentifie pas les clients MCP entrants et ne transmet pas leurs identités à ClickHouse. Configurez l’authentification du transport MCP séparément.

Redémarrez mcp-clickhouse après avoir remplacé un certificat ou une clé au même chemin lorsqu’une rotation ou révocation immédiate est requise. Les clients mis en cache peuvent conserver des connexions TLS existantes, et le cache ne suit pas les contenus de fichiers ni les heures de modification.

ClickHouse Cloud ne prend pas en charge l’authentification par certificat client X.509 pour les utilisateurs de base de données. Utilisez CLICKHOUSE_USER et CLICKHOUSE_PASSWORD pour ClickHouse Cloud. Un certificat CA peut toujours être utile lorsqu’un proxy privé devant un point de terminaison présente un certificat signé par une CA privée.

Serveur MCP et transport

Ces variables contrôlent le processus MCP lui-même, y compris le transport, l’authentification et les limites d’exécution des outils de requête. Elles sont indépendantes des paramètres de base de données ClickHouse ci-dessus. Voir aussi Authentification pour les transports HTTP/SSE.

  • CLICKHOUSE_MCP_SERVER_TRANSPORT : définit la méthode de transport pour le serveur MCP
    • Par défaut : "stdio"
    • Options valides : "stdio", "http", "sse". Utile pour le développement local avec des outils comme MCP Inspector.
    • stdio est typique pour Claude Desktop ; http/sse exposent un écouteur réseau (lier l'hôte/le port ci-dessous)
    • "sse" sélectionne le transport autonome obsolète HTTP+SSE et journalise un avertissement. Utilisez "http" pour Streamable HTTP dans les nouveaux déploiements.
  • CLICKHOUSE_MCP_BIND_HOST : hôte auquel lier le serveur MCP lors de l'utilisation du transport HTTP ou SSE
    • Par défaut : "127.0.0.1"
    • Définissez "0.0.0.0" pour lier à toutes les interfaces réseau (utile pour Docker ou l'accès à distance)
    • Utilisé uniquement lorsque le transport est "http" ou "sse" — sans rapport avec CLICKHOUSE_HOST
  • CLICKHOUSE_MCP_BIND_PORT : port auquel lier le serveur MCP lors de l'utilisation du transport HTTP ou SSE
    • Par défaut : "8000"
    • Utilisé uniquement lorsque le transport est "http" ou "sse" — sans rapport avec CLICKHOUSE_PORT
  • CLICKHOUSE_MCP_QUERY_TIMEOUT : délai d'expiration en secondes pour les appels d'outils de requête
    • Par défaut : "30"
    • Augmentez-le si vous voyez des erreurs Query timed out after ... pour les requêtes lourdes
    • Lorsqu'une requête expire, le serveur tente de l'annuler avec KILL QUERY
    • Sauf si CLICKHOUSE_SEND_RECEIVE_TIMEOUT est explicitement défini, le délai d'expiration de lecture HTTP est plafonné à cette valeur plus cinq secondes
  • CLICKHOUSE_MCP_MAX_WORKERS : nombre maximal de threads de travail de requête simultanés
    • Par défaut : "10"
    • Augmentez si votre charge de travail nécessite de nombreux appels d'outils simultanés
    • Les outils de métadonnées utilisent un pool séparé avec min(4, CLICKHOUSE_MCP_MAX_WORKERS) threads afin que la découverte de schéma ne puisse pas retarder les requêtes
  • CLICKHOUSE_MCP_AUTH_TOKEN : jeton porteur statique pour les transports HTTP/SSE
    • Par défaut : aucun
    • L'un de CLICKHOUSE_MCP_AUTH_TOKEN, FASTMCP_SERVER_AUTH ou CLICKHOUSE_MCP_AUTH_DISABLED=true est requis pour les transports HTTP/SSE
    • Générez-le avec uuidgen ou openssl rand -hex 32
    • Les clients doivent envoyer ce jeton dans l'en-tête Authorization: Bearer <token>
  • FASTMCP_SERVER_AUTH : délégation de l'authentification à un fournisseur d'authentification FastMCP
    • Par défaut : aucun
    • La valeur est le chemin de classe complet d'une sous-classe AuthProvider, par exemple fastmcp.server.auth.providers.azure.AzureProvider ou fastmcp.server.auth.providers.google.GoogleProvider
    • Lorsqu'il est défini, mcp-clickhouse charge le fournisseur à partir des variables d'environnement FASTMCP_SERVER_AUTH_* existantes ; laissez CLICKHOUSE_MCP_AUTH_TOKEN non défini dans ce mode
    • Les fournisseurs personnalisés ne reçoivent aucun argument de constructeur dérivé de l'environnement et doivent prendre en charge la construction sans argument
    • FastMCP 4 ne prend plus en charge la vérification Supabase HS256. Les déploiements Supabase doivent utiliser RS256 ou ES256.
  • FASTMCP_ENV_FILE : fichier facultatif contenant FASTMCP_SERVER_AUTH et les variables d'environnement spécifiques au fournisseur
    • Par défaut : aucun. Lorsqu'il n'est pas défini, le chargeur de compatibilité lit les champs de fournisseur manquants à partir de .env dans le répertoire de travail. Il ne lit pas FASTMCP_SERVER_AUTH à partir de ce repli
    • Définissez-le dans l'environnement du processus avant le démarrage. Une valeur chargée depuis le .env par défaut ne peut pas rediriger le chargeur de compatibilité
    • S'il est défini par le processus, ce fichier peut fournir à la fois FASTMCP_SERVER_AUTH et les champs du fournisseur et remplace le repli du répertoire de travail
    • Les valeurs de l'environnement du processus ont priorité sans tenir compte de la casse
    • Le chargeur de compatibilité mcp-clickhouse lit ce fichier uniquement lors de la construction de l'authentification HTTP/SSE et lit uniquement les entrées FASTMCP_SERVER_AUTH et FASTMCP_SERVER_AUTH_*. FastMCP 4 peut lire le même fichier pour ses paramètres plus larges
    • Le chargement par défaut de .env est séparé. Il commence dans le répertoire du paquet mcp_clickhouse installé, résout les liens symboliques, remonte jusqu'à la racine du système de fichiers et charge le premier .env trouvé ou rien. Il ne lit jamais le répertoire de travail, quelle que soit la méthode de lancement. Ce fichier peut fournir FASTMCP_SERVER_AUTH et les champs du fournisseur ainsi que d'autres paramètres du serveur. Une copie source trouve normalement le .env racine du dépôt
  • CLICKHOUSE_MCP_AUTH_DISABLED : désactivation de l'authentification pour les transports HTTP/SSE
    • Par défaut : "false" (l'authentification est activée)
    • Définissez "true" pour désactiver l'authentification uniquement pour le développement/les tests locaux
    • AVERTISSEMENT : à utiliser uniquement pour le développement local. Ne désactivez pas lorsque vous êtes exposé aux réseaux
  • CLICKHOUSE_MCP_ALLOWED_HOSTS : valeurs d'en-tête Host séparées par des virgules auxquelles le serveur HTTP/SSE répond
    • Par défaut pour une liaison en boucle : formes nues et tout-port de 127.0.0.1, localhost et [::1]
    • S'il est défini, la valeur doit contenir au moins une entrée Host.
    • Une adresse de liaison concrète non-boucle par défaut correspond à cette adresse et au port configuré. Une liaison générique telle que 0.0.0.0 ou :: nécessite une valeur explicite non vide car le Host public ne peut pas être déduit.
    • La validation du Host est une défense en profondeur contre le rebinding DNS. La validation de l'origine ci-dessous est requise séparément par MCP.
    • Les entrées sont exactes (localhost:8000) ou acceptent n'importe quel port (localhost:*). Exemple : CLICKHOUSE_MCP_ALLOWED_HOSTS=127.0.0.1:8000,localhost:8000
    • La forme host:* correspond uniquement aux valeurs qui portent un port. Un Host sans port (un déploiement à port standard où le client omet :80/:443) doit également être répertorié comme entrée exacte nue (example.com).
    • Les requêtes avec un en-tête Host non correspondant ou manquant reçoivent 421 Misdirected Request. Les requêtes GET et HEAD vers /health sont exemptées de la validation Host et Origin afin que les sondes d'orchestration continuent de fonctionner.
    • Derrière un proxy inverse, préférez préserver l'en-tête Host d'origine. Vous pouvez plutôt répertorier la valeur Host en amont que le proxy envoie. Définissez une liste explicite lorsqu'un lanceur tel que fastmcp run remplace l'adresse de liaison pour l'accès à distance.
    • mcp-clickhouse force la désactivation de la garde Host et Origin séparée de FastMCP. FASTMCP_HTTP_HOST_ORIGIN_PROTECTION, FASTMCP_HTTP_ALLOWED_HOSTS et FASTMCP_HTTP_ALLOWED_ORIGINS ne s'appliquent pas. CLICKHOUSE_MCP_ALLOWED_HOSTS et CLICKHOUSE_MCP_ALLOWED_ORIGINS sont faisant autorité.
  • CLICKHOUSE_MCP_TRUSTED_PROXIES : adresses IP proxy ou réseaux CIDR dont les en-têtes X-Forwarded-* sont approuvés
    • Par défaut : aucun. X-Forwarded-Host est ignoré. La gestion existante d'Uvicorn de X-Forwarded-For et X-Forwarded-Proto est inchangée.
    • Les entrées doivent être des adresses IP ou des réseaux CIDR, tels que 127.0.0.1,10.20.0.0/24,2001:db8::1. Les CIDR doivent utiliser leur adresse réseau, donc 10.20.0.1/24 est rejeté. Les noms d'hôte, les adresses IPv6 à portée, *, 0.0.0.0/0 et ::/0 sont également rejetés.
    • La confiance est basée sur le pair de socket brut immédiat. Une requête de tout autre pair, ou une requête sans adresse client, ignore X-Forwarded-Host et valide Host.
    • Un pair approuvé peut envoyer exactement un en-tête X-Forwarded-Host contenant une valeur non vide. Les champs en double, les valeurs vides et les listes séparées par des virgules reçoivent 421 Misdirected Request. Si l'en-tête est absent, Host est validé.
    • Utilisez l'adresse ou le réseau le plus étroit possible. Le serveur MCP ne doit être accessible que via des proxys dans les plages configurées. Chaque proxy approuvé doit supprimer et écraser les valeurs X-Forwarded-Host et X-Forwarded-Proto fournies par le client, et construire X-Forwarded-For à partir du pair de connexion vérifié.
    • Le serveur intégré et fastmcp run désactivent la gestion externe des en-têtes proxy d'Uvicorn, valident le Host à partir du pair brut, puis appliquent X-Forwarded-For et X-Forwarded-Proto. L'activation explicite de uvicorn_config["proxy_headers"] échoue au démarrage dans ce mode.
    • L'intégration ASGI directe doit désactiver la gestion des en-têtes proxy dans le serveur ASGI externe et appeler mcp.http_app(raw_client_address_preserved=True). Sans cette assertion explicite, la construction de l'application échoue lorsque des proxys approuvés sont configurés.
  • CLICKHOUSE_MCP_ALLOWED_ORIGINS : valeurs d'en-tête Origin séparées par des virgules acceptées sur HTTP/SSE
    • Par défaut : aucun, ce qui rejette chaque requête portant un en-tête Origin
    • MCP exige la validation de l'origine pour les connexions de transport HTTP/SSE. Les requêtes sans Origin sont acceptées car les clients MCP non-navigateur l'omettent normalement. Une origine non correspondante reçoit 403 Forbidden. Le point de terminaison /health est exempté comme décrit ci-dessus.
    • Les entrées sont exactes (http://localhost:3000) ou acceptent n'importe quel port (http://localhost:*). Comme pour les hôtes, la forme tout-port correspond uniquement aux origines qui portent un port ; une origine à port standard (https://app.example.com) doit être répertoriée exactement.
Gestion du Host du proxy inverse

Préservez Host lorsque c'est possible. Cela maintient la confiance du Host transféré désactivée :

location / {
    proxy_pass http://mcp-clickhouse:8000;
    proxy_set_header Host $http_host;
    proxy_set_header X-Forwarded-Host "";
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_set_header X-Forwarded-Proto $scheme;
}

Assainissez X-Forwarded-For et X-Forwarded-Proto indépendamment de la confiance X-Forwarded-Host. Uvicorn peut faire confiance à ces en-têtes en fonction du pair proxy même lorsque CLICKHOUSE_MCP_TRUSTED_PROXIES n'est pas défini.

CLICKHOUSE_MCP_ALLOWED_HOSTS=mcp.example.com

Le nginx standard change Host en nom en amont pour les requêtes proxyées. Il ne crée ni n'écrase X-Forwarded-Host. Si la préservation de Host n'est pas possible, écrasez l'en-tête transféré à la périphérie approuvée :

location / {
    proxy_pass http://mcp-clickhouse:8000;
    proxy_set_header X-Forwarded-Host $http_host;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_set_header X-Forwarded-Proto $scheme;
}
CLICKHOUSE_MCP_ALLOWED_HOSTS=mcp.example.com
CLICKHOUSE_MCP_TRUSTED_PROXIES=10.20.0.8

La deuxième configuration n'est sûre que lorsque 10.20.0.8 est l'adresse source immédiate du proxy, que le port du serveur est isolé des autres clients et que nginx écrase les en-têtes de transfert entrants comme indiqué. Pour une chaîne de proxys, chaque saut approuvé doit supprimer les valeurs entrantes non vérifiées avant de construire les nouveaux en-têtes de transfert.

Sur une liaison IPv6 ou double pile, les proxys IPv4 peuvent apparaître comme des adresses mappées IPv4 telles que ::ffff:10.20.0.8 ; celles-ci sont automatiquement comparées aux entrées IPv4. Le append_x_forwarded_host d'Envoy ajoute à un X-Forwarded-Host existant plutôt que de l'écraser, produisant une liste séparée par des virgules qui est rejetée, alors configurez le saut approuvé pour écraser l'en-tête à la place. Sur Kubernetes avec NAT source (par exemple externalTrafficPolicy: Cluster), le pair observé peut être une IP de nœud plutôt que le pod proxy, alors faites confiance au pod ou au CIDR du nœud selon le cas ; ingress-nginx écrase lui-même à la fois Host et X-Forwarded-Host.

Variables de middleware

  • MCP_MIDDLEWARE_MODULE : nom du module Python contenant le middleware personnalisé à injecter dans le serveur MCP
    • Par défaut : aucun (aucun middleware chargé)
    • Définissez le nom du module (sans l'extension .py) de votre module middleware
    • Le module doit fournir une fonction setup_middleware(mcp)
    • Voir Middleware personnalisé pour les détails et les exemples

Variables chDB

  • CHDB_ENABLED : activer/désactiver la fonctionnalité chDB
    • Par défaut : "false"
    • Définissez "true" pour activer les outils chDB
    • Nécessite l'installation de l'extra optionnel : mcp-clickhouse[chdb]
  • CHDB_DATA_PATH : le chemin vers le répertoire de données chDB
    • Par défaut : ":memory:" (base de données en mémoire)
    • Utilisez :memory: pour la base de données en mémoire
    • Utilisez un chemin de fichier pour le stockage persistant (par exemple, /path/to/chdb/data)

Pièges de configuration courants

  • CLICKHOUSE_SECURE vs TLS MCP / ingress — La désactivation de CLICKHOUSE_SECURE parce que le serveur MCP se trouve derrière un ingress Kubernetes, un proxy inverse, ou est atteint sur HTTP simple ne désactive pas le TLS de la base de données ; cela change uniquement la façon dont ce processus se connecte à ClickHouse. Configurez le TLS de l'ingress séparément des paramètres du client de base de données.
  • Ports du protocole natifCLICKHOUSE_PORT doit cibler l'interface HTTP de ClickHouse (8123/8443 par défaut). Les ports 9000/9440 sont pour le protocole TCP natif (clickhouse-client) et ne fonctionneront pas avec ce serveur.
  • Confusion d'hôteCLICKHOUSE_HOST est le nom d'hôte de la base de données. CLICKHOUSE_MCP_BIND_HOST est uniquement l'adresse sur laquelle le serveur MCP HTTP/SSE écoute.

Exemples de configurations

Pour le développement local avec Docker :

# Required variables
CLICKHOUSE_HOST=localhost
CLICKHOUSE_USER=default
CLICKHOUSE_PASSWORD=clickhouse

# Optional: Override defaults for local development
CLICKHOUSE_SECURE=false  # Uses port 8123 automatically
CLICKHOUSE_VERIFY=false

Pour ClickHouse Cloud :

# Required variables
CLICKHOUSE_HOST=your-instance.clickhouse.cloud
CLICKHOUSE_USER=default
CLICKHOUSE_PASSWORD=your-password

# Optional: These use secure defaults
# CLICKHOUSE_SECURE=true  # Uses port 8443 automatically
# CLICKHOUSE_DATABASE=your_database

Pour ClickHouse SQL Playground :

CLICKHOUSE_HOST=sql-clickhouse.clickhouse.com
CLICKHOUSE_USER=demo
CLICKHOUSE_PASSWORD=
# Uses secure defaults (HTTPS on port 8443)

Pour une CA de serveur privée sans authentification par certificat client :

CLICKHOUSE_HOST=your-secure-clickhouse.example.com
CLICKHOUSE_USER=your-user
CLICKHOUSE_PASSWORD=your-password
CLICKHOUSE_SECURE=true
CLICKHOUSE_VERIFY=true
CLICKHOUSE_CA_CERT=/run/secrets/clickhouse-ca.pem

Pour l'authentification par certificat client X.509 ClickHouse :

CLICKHOUSE_HOST=your-secure-clickhouse.example.com
CLICKHOUSE_USER=your-certificate-user
CLICKHOUSE_SECURE=true
CLICKHOUSE_CLIENT_CERT=/run/secrets/clickhouse-client.pem
CLICKHOUSE_CLIENT_CERT_KEY=/run/secrets/clickhouse-client-key.pem
# CLICKHOUSE_CA_CERT=/run/secrets/clickhouse-ca.pem  # Only for a private server CA
# CLICKHOUSE_TLS_MODE=mutual  # Optional. This is the default with a client certificate.

Pour un certificat client requis par un serveur TLS strict tandis que ClickHouse utilise l'authentification Basic :

CLICKHOUSE_HOST=your-secure-clickhouse.example.com
CLICKHOUSE_USER=your-user
CLICKHOUSE_PASSWORD=your-password
CLICKHOUSE_SECURE=true
CLICKHOUSE_CLIENT_CERT=/run/secrets/clickhouse-client.pem
CLICKHOUSE_CLIENT_CERT_KEY=/run/secrets/clickhouse-client-key.pem
CLICKHOUSE_TLS_MODE=strict

Utilisez CLICKHOUSE_TLS_MODE=proxy à la place lorsqu’un proxy de terminaison TLS exige le certificat client et que ClickHouse utilise toujours l’authentification Basic.

Pour chDB uniquement (en mémoire) :

# chDB configuration
CHDB_ENABLED=true
CLICKHOUSE_ENABLED=false
# CHDB_DATA_PATH defaults to :memory:

Pour chDB avec stockage persistant :

# chDB configuration
CHDB_ENABLED=true
CLICKHOUSE_ENABLED=false
CHDB_DATA_PATH=/path/to/chdb/data

Pour MCP Inspector ou un accès distant avec transport HTTP :

CLICKHOUSE_HOST=localhost
CLICKHOUSE_USER=default
CLICKHOUSE_PASSWORD=clickhouse
CLICKHOUSE_MCP_SERVER_TRANSPORT=http
CLICKHOUSE_MCP_BIND_HOST=0.0.0.0  # Bind to all interfaces
CLICKHOUSE_MCP_BIND_PORT=4200  # Custom port (default: 8000)
CLICKHOUSE_MCP_AUTH_TOKEN=your-generated-token  # One auth mode required for HTTP/SSE (or FASTMCP_SERVER_AUTH, or CLICKHOUSE_MCP_AUTH_DISABLED=true)
CLICKHOUSE_MCP_ALLOWED_HOSTS=127.0.0.1:4200,localhost:4200,mcp.example.com:4200  # Include every Host value clients and proxies send

Pour le développement local avec transport HTTP (authentification désactivée) :

CLICKHOUSE_HOST=localhost
CLICKHOUSE_USER=default
CLICKHOUSE_PASSWORD=clickhouse
CLICKHOUSE_MCP_SERVER_TRANSPORT=http
CLICKHOUSE_MCP_AUTH_DISABLED=true  # Only for local development!
CLICKHOUSE_MCP_ALLOWED_HOSTS=127.0.0.1:8000,localhost:8000

Lorsque vous utilisez le transport HTTP, le serveur s’exécutera sur le port configuré (par défaut 8000). Par exemple, avec la configuration ci-dessus :

  • Point de terminaison MCP : http://localhost:8000/mcp
  • Vérification de santé : http://localhost:8000/health

Vous pouvez définir ces variables dans votre environnement, dans un fichier .env, ou dans la configuration de Claude Desktop :

{
  "mcpServers": {
    "mcp-clickhouse": {
      "command": "uv",
      "args": [
        "run",
        "--with",
        "mcp-clickhouse",
        "--python",
        "3.12",
        "mcp-clickhouse"
      ],
      "env": {
        "CLICKHOUSE_HOST": "<clickhouse-host>",
        "CLICKHOUSE_USER": "<clickhouse-user>",
        "CLICKHOUSE_PASSWORD": "<clickhouse-password>",
        "CLICKHOUSE_DATABASE": "<optional-database>",
        "CLICKHOUSE_MCP_SERVER_TRANSPORT": "stdio",
        "CLICKHOUSE_MCP_BIND_HOST": "127.0.0.1",
        "CLICKHOUSE_MCP_BIND_PORT": "8000"
      }
    }
  }
}

Remarque : Les paramètres d’hôte et de port de liaison ne sont utilisés que lorsque le transport est défini sur « http » ou « sse ».

Exécution des tests

uv sync --all-extras --dev # install dev dependencies
uv run ruff check . # run linting

docker compose up -d test_services # start ClickHouse
uv run pytest -v tests
uv run pytest -v tests/test_tool.py # ClickHouse only
CHDB_ENABLED=true uv run --extra chdb pytest -v tests/test_chdb_tool.py # chDB only

Aperçu YouTube

YouTube