execute_queryLABSCO SUMMARY
Discovery first, then the query.
The four listing tools exist so an assistant finds the right catalog, schema and table before it writes any SQL, and the plan tool lets it read what a query will do before the cluster spends time on it. On a large deployment the allowlist variables are what make that workable — restrict it to the handful of schemas that matter and it stops wandering through catalogs nobody asked about.
What it is
A Go MCP server for Trino, the distributed SQL query engine formerly called PrestoSQL. The same binary doubles as an interactive CLI in the shape of psql. It runs over STDIO or Streamable HTTP, with SSE endpoints kept for backward compatibility, and optional OAuth 2.1 through the oauth-mcp-proxy library with HMAC, Okta, Google and Azure AD as providers.
What you get
- SQL run against Trino with the columns and rows returned as structured data —
execute_query - Discovery down the hierarchy so the model finds the right table before writing SQL —
list_catalogs,list_schemas,list_tables,get_table_schema, the last returning column names, types and nullability - A query's distributed execution plan with stages and estimated rows and cost, read without running the query —
explain_query - An interactive CLI on the same binary:
mcp-trino --interactivefor a REPL,mcp-trino queryto run one statement, pluscatalogs,schemas,tables,describeandexplainsubcommands, with output astable(the default),jsonorcsv - REPL meta-commands for the same moves —
\catalogs,\schemas,\tables,\describe,\format,\history - Named connection profiles in
~/.config/trino/config.yamlorconfig.json, switched withmcp-trino config profile use prodor per-command with--profile dev; when both files exist the JSON one wins - Allowlists that shrink what the assistant can even see, at catalog, schema and table level, case-insensitive and independent of each other —
TRINO_ALLOWED_CATALOGS,TRINO_ALLOWED_SCHEMAS,TRINO_ALLOWED_TABLES - Query attribution: with OAuth enabled, queries are automatically tagged with the OAuth user through the
X-Trino-Client-TagsandX-Trino-Client-Infoheaders, and opt-in impersonation sendsX-Trino-Userso Trino applies that user's own permissions —TRINO_ENABLE_IMPERSONATION,TRINO_IMPERSONATION_FIELD - Exit codes worth scripting against:
0success,1runtime error such as a failed connection or query,2usage error - Distribution as a Homebrew formula, an install script and a Docker image on GitHub Container Registry, with SBOM and SLSA provenance published per release
Requirements
A reachable Trino cluster and its connection details in the environment: TRINO_HOST, TRINO_PORT, TRINO_USER, TRINO_PASSWORD, TRINO_CATALOG, TRINO_SCHEMA and TRINO_SSL; a local development run needs only TRINO_HOST and TRINO_USER. Install with brew install tuannvm/mcp/mcp-trino or the install script from the repository. Secrets are read purely from the process environment, and the README's recommended pattern is injecting them at launch from a secrets CLI such as 1Password or Vault rather than writing them to disk. OAuth is optional: OAUTH_ENABLED, OAUTH_MODE (native keeps all secrets on the client side, proxy centralises them on the server), OAUTH_PROVIDER, OIDC_ISSUER and OIDC_AUDIENCE, with OIDC_CLIENT_ID, OIDC_CLIENT_SECRET and OAUTH_REDIRECT_URI added in proxy mode; JWT_SECRET is required for multi-pod deployments. MIT licensed.
Setup effort
One command plus credentials — brew install tuannvm/mcp/mcp-trino, then supply credentials
USE CASES
Answering an analytics question without writing the SQL yourself
Let the assistant walk catalogs, schemas and tables to find the data, then run the query and read back columns and rows.
Checking what a query will do before it runs
Read the execution plan with its stages and estimated rows and cost, then decide whether to run it against production data.
Understanding an unfamiliar table
List the tables in the schema, then read the column names, types and nullability before writing anything against it.
Keeping the assistant inside the schemas that matter
Set the allowlist variables to the catalogs, schemas or tables you want visible — anything else disappears from discovery.
Telling from Trino's side who ran what
Enable OAuth so queries carry the user in the client tag headers, and turn on impersonation when you want Trino to enforce that user's own permissions.
6 tools
Listed in project docs. Your client may show a different list.
list_catalogslist_schemaslist_tablesget_table_schemaexplain_queryBEFORE YOU INSTALL
What to know first
Tools you get
6 tools named in the project's documentation. The mcp-trino CLI commands are a separate surface, not extra tools. TRINO_ALLOWED_SCHEMAS limits which schemas the tools reach, and TRINO_ENABLE_IMPERSONATION is an opt-in setting for user impersonation.
Requires
- A reachable Trino cluster
- TRINO_HOST, TRINO_PORT and TRINO_USER in your environment (defaults: localhost, 8080, trino)
- TRINO_PASSWORD, if your cluster requires one (default: empty)
INSTALLATION
Connect your client
Server setup
Install the binary: brew install tuannvm/mcp/mcp-trino, or curl -fsSL https://raw.githubusercontent.com/tuannvm/mcp-trino/main/install.sh | bash, or download a release binary and chmod +x it, or build from source (git clone https://github.com/tuannvm/mcp-trino.git; cd mcp-trino; make build)
Add the mcpServers block to your client config (~/.cursor/mcp.json, claude_desktop_config.json, Windsurf mcp_config.json) with your TRINO_* env values — or for Claude Code run: claude mcp add mcp-trino mcp-trino and export the TRINO_* variables
For HTTP transport instead of stdio, start the server separately (MCP_TRANSPORT=http ... mcp-trino) and point the client at http://localhost:8080/mcp
MCP Clients
Cursor
{
"mcpServers": {
"mcp-trino": {
"command": "mcp-trino",
"args": [],
"env": {
"TRINO_HOST": "<YOUR_TRINO_HOST>",
"TRINO_PORT": "<YOUR_TRINO_PORT>",
"TRINO_USER": "<YOUR_TRINO_USER>",
"TRINO_PASSWORD": "<YOUR_TRINO_PASSWORD>"
}
}
}
}Any MCP client — Docker
{
"mcpServers": {
"mcp-trino": {
"command": "docker",
"args": [
"run",
"--rm",
"-i",
"-e",
"TRINO_HOST=<YOUR_TRINO_HOST>",
"-e",
"TRINO_PORT=<YOUR_TRINO_PORT>",
"-e",
"TRINO_USER=<YOUR_TRINO_USER>",
"-e",
"TRINO_PASSWORD=<YOUR_TRINO_PASSWORD>",
"-e",
"TRINO_SCHEME=http",
"ghcr.io/tuannvm/mcp-trino:latest"
],
"env": {}
}
}
}Any MCP client — HTTP
{
"mcpServers": {
"mcp-trino-http": {
"url": "http://localhost:8080/mcp"
}
}
}Any MCP client — JWT
{
"mcpServers": {
"mcp-trino-remote": {
"url": "<YOUR_SERVER_URL>/mcp",
"headers": {
"Authorization": "Bearer <YOUR_JWT_TOKEN>"
}
}
}
}Any MCP client — SSE
{
"mcpServers": {
"mcp-trino-sse": {
"url": "http://localhost:8080/sse"
}
}
}Claude Desktop
{
"mcpServers": {
"mcp-trino": {
"command": "mcp-trino",
"args": [],
"env": {
"TRINO_HOST": "<YOUR_TRINO_HOST>",
"TRINO_PORT": "<YOUR_TRINO_PORT>",
"TRINO_USER": "<YOUR_TRINO_USER>",
"TRINO_PASSWORD": "<YOUR_TRINO_PASSWORD>"
}
}
}
}Add to claude_desktop_config.json (macOS: ~/Library/Application Support/Claude/, Windows: %APPDATA%\Claude\, Linux: ~/.config/Claude/), then restart Claude Desktop.
Windsurf
{
"mcpServers": {
"mcp-trino": {
"command": "mcp-trino",
"args": [],
"env": {
"TRINO_HOST": "<YOUR_TRINO_HOST>",
"TRINO_PORT": "<YOUR_TRINO_PORT>",
"TRINO_USER": "<YOUR_TRINO_USER>",
"TRINO_PASSWORD": "<YOUR_TRINO_PASSWORD>"
}
}
}
}Add to Windsurf's mcp_config.json, then restart Windsurf.
Chatwise
{
"mcpServers": {
"mcp-trino": {
"command": "mcp-trino",
"args": [],
"env": {
"TRINO_HOST": "<YOUR_TRINO_HOST>",
"TRINO_PORT": "<YOUR_TRINO_PORT>",
"TRINO_USER": "<YOUR_TRINO_USER>",
"TRINO_PASSWORD": "<YOUR_TRINO_PASSWORD>"
}
}
}
}Copy this JSON, then in ChatWise Settings > Tools click "+" and choose "Import JSON from Clipboard".