Examples

Connect a host, write an agent, run the server locally, all while keeping the user's identity.

All examples live in the examples/ folder of the repository. They share one rule: the model never sees the token; the server receives it, Trino decides.

1. A remote host (Cursor, Claude Desktop, VS Code, Le Chat)

The server runs somewhere on your network, behind HTTPS, with MCP_TRANSPORT=streamable-http (the default). The host sends the user’s token in the Authorization header, and the product key in X-Agent-Key if you registered any.

{
  "mcpServers": {
    "trino": {
      "url": "https://mcp.example.com/mcp",
      "headers": {
        "Authorization": "Bearer <the user's access token>",
        "X-Agent-Key": "<the key registered for this product, if any>"
      }
    }
  }
}

With MCP_RESOURCE_URL set on the server, a host that speaks OAuth finds the identity provider on its own (RFC 9728) and there is no token to paste.

2. A local host over stdio (Claude Desktop, Cursor, Mistral Vibe)

The host launches the server itself on your machine. The token comes from the environment; in strict mode, without a valid token, the server refuses to start.

Local hostClaude Desktop, Cursor, Vibeakko-mcp-trino (stdio)verifies the token at start, one identity per processTrinoX-Trino-User = the person at the keyboardIdentity providerJWKSlaunches the server (uvx akko-mcp-trino)JSON-RPC over stdin / stdoutverifies the signatureMCP_USER_TOKEN in the environmentstrict mode: no valid token, no startthe model decided nothing
{
  "mcpServers": {
    "trino": {
      "command": "uvx",
      "args": ["akko-mcp-trino"],
      "env": {
        "MCP_TRANSPORT": "stdio",
        "TRINO_HOST": "trino.example.internal",
        "TRINO_PORT": "8080",
        "MCP_AUTH_ENABLED": "true",
        "MCP_AUTH_REQUIRED": "true",
        "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": "data-platform",
        "MCP_USER_TOKEN": "<the user's access token>"
      }
    }
  }
}

uvx runs the published package without installing anything; pipx run akko-mcp-trino does the same. Without uv, use the akko-mcp-trino command after pip install akko-mcp-trino.

Note. Access tokens expire (typically after an hour). On a workstation the host will have to renew it; that is the known limit of stdio, and the reason the remote mode with OAuth discovery is preferable as soon as more than one person is involved.

3. A complete agent on an OpenAI-compatible model (Mistral, or any other)

examples/agent.py is eighty lines: it lists the server’s tools, exposes them to the model as function calls, executes each call over MCP and returns the answer. It works unchanged with Mistral on La Plateforme, through OpenRouter or LiteLLM, and with any provider that speaks the chat-completions API with tools.

pip install akko-mcp-trino openai
export LLM_BASE_URL=https://api.mistral.ai/v1
export LLM_API_KEY=...
export LLM_MODEL=mistral-small-latest
export MCP_URL=http://localhost:3000/mcp
export USER_TOKEN=<the user's access token>
export AGENT_KEY=<optional X-Agent-Key>
python examples/agent.py "Give me three customer e-mails with their country"

The agent’s system prompt tells the model two things, and both matter: explore the catalog before writing SQL, and take a masked value for what it is, the access policy, without retrying. Without the second, a model receiving ***@gmail.com may take it for an error and loop; we saw it happen.

Run twice with two people’s tokens, the agent gives two different answers to the same question. That is the demonstration for anyone asking what “governed” means.

4. From Python, with the official SDK

import anyio
from mcp import ClientSession
from mcp.client.streamable_http import streamablehttp_client

async def main(token: str):
    headers = {"Authorization": f"Bearer {token}", "X-Agent-Key": "my-agent-key"}
    async with streamablehttp_client("http://localhost:3000/mcp", headers=headers) as (read, write, _):
        async with ClientSession(read, write) as session:
            await session.initialize()
            tools = await session.list_tools()
            found = await session.call_tool("search_columns", {"pattern": "%email%"})
            print([t.name for t in tools.tools], found.content[0].text)

anyio.run(main, "<token>")

5. Checking from a terminal

# alive, reaches Trino, exposes metrics
curl -s localhost:3001/health ; curl -s localhost:3001/ready ; curl -s localhost:3001/metrics | head

# a host without a token learns where to log in
curl -si https://mcp.example.com/mcp | grep -i -e www-authenticate -e x-reason
curl -s https://mcp.example.com/.well-known/oauth-protected-resource

What is proven, and how to replay it

The proof scripts run against a real cluster and are replayable; they live in the AKKO platform repository because they know its cluster, but their logic is readable by anyone: an ephemeral pod with the server, two accounts, the same tools, two answers. The table on the akko-mcp-trino page summarises what they check.