A comprehensive toolkit for working with Hex - includes Python SDK, CLI, and MCP integration for Claude.
- π Simple, Pythonic interface - Easy to use with clear method names
- π§ Complete API coverage - Projects, runs, and more
- π€ MCP Support - Use Hex directly in Claude Desktop and Claude Code
- π¦ Minimal dependencies - Built on httpx for reliability
- π Secure - API key authentication with environment variable support
# Basic installation
pip install hex-toolkit
# With CLI support
pip install "hex-toolkit[cli]"
# With MCP (Model Context Protocol) support
pip install "hex-toolkit[mcp]"
# Install everything
pip install "hex-toolkit[all]"
from hex_toolkit import HexClient
# Initialize the client
client = HexClient(api_key="your-api-key")
# List all projects
projects = client.projects.list()
for project in projects.values:
print(f"{project.title} - {project.id}")
# Get a specific project
project = client.projects.get("project-id")
print(project.title)
# Run a project
run = client.projects.run(
project_id="project-id",
input_params={"param1": "value1"}
)
print(f"Run started: {run.run_id}")
# Check run status
status = client.runs.get_status(project_id="project-id", run_id=run.run_id)
print(f"Status: {status.status}")
The client can be configured via environment variables:
export HEX_API_KEY="your-api-key"
export HEX_API_BASE_URL="https://app.hex.tech/api" # Optional
Or directly in code:
client = HexClient(
api_key="your-api-key",
base_url="https://custom.hex.tech/api",
timeout=60.0
)
# List projects with filters
projects = client.projects.list(
limit=50,
include_archived=False,
creator_email="user@example.com"
)
# Access project data - fields are converted to snake_case
for project in projects.values:
print(f"ID: {project.id}")
print(f"Title: {project.title}")
print(f"Type: {project.type}") # ProjectType.PROJECT or ProjectType.COMPONENT
print(f"Created: {project.created_at}")
print(f"Last edited: {project.last_edited_at}")
# List projects with pagination
after_cursor = None
all_projects = []
while True:
response = client.projects.list(limit=100, after=after_cursor)
all_projects.extend(response.values)
# Check if there are more pages
after_cursor = response.pagination.after if response.pagination else None
if not after_cursor:
break
print(f"Found {len(all_projects)} projects total")
# Simple run
run = client.projects.run("project-id")
# Run with parameters
run = client.projects.run(
project_id="project-id",
input_params={
"date_start": "2024-01-01",
"date_end": "2024-01-31",
"metric": "revenue"
},
update_published_results=True
)
# Run with notifications
run = client.projects.run(
project_id="project-id",
notifications=[{
"type": "ALL",
"includeSuccessScreenshot": True,
"slackChannelIds": ["C0123456789"],
}]
)
import time
# Wait for completion
run_id = run.run_id
project_id = run.project_id
while True:
status = client.runs.get_status(project_id, run_id)
print(f"Status: {status.status}")
if status.status in ["COMPLETED", "ERRORED", "KILLED"]:
print(f"Run finished with status: {status.status}")
if status.elapsed_time:
print(f"Elapsed time: {status.elapsed_time}ms")
break
time.sleep(5)
from hex_toolkit.exceptions import (
HexAPIError,
HexAuthenticationError,
HexNotFoundError,
HexRateLimitError
)
try:
project = client.projects.get("invalid-id")
except HexNotFoundError as e:
print(f"Project not found: {e.message}")
except HexAuthenticationError:
print("Invalid API key")
except HexRateLimitError as e:
print(f"Rate limited. Retry after: {e.retry_after} seconds")
except HexAPIError as e:
print(f"API error: {e.message}")
print(f"Status code: {e.status_code}")
print(f"Trace ID: {e.trace_id}")
# Create a basic embedded URL
embed = client.embedding.create_presigned_url("project-id")
print(f"Embed URL: {embed.url}")
# Create with options
embed = client.embedding.create_presigned_url(
project_id="project-id",
expires_in=300000, # 5 minutes
input_parameters={"filter": "Q1"},
display_options={
"theme": "dark",
"noEmbedFooter": True
}
)
The SDK includes built-in MCP support for using Hex directly within Claude Desktop and Claude Code. Learn more about MCP.
# Install the MCP server
hex mcp install
# Check installation status
hex mcp status
# Use in Claude - look for the π§ icon!
See the MCP documentation for detailed setup and usage instructions.
client.projects.list(**filters)
- List all projectsclient.projects.get(project_id)
- Get a specific projectclient.projects.run(project_id, **options)
- Run a project
client.runs.get_status(project_id, run_id)
- Get run statusclient.runs.list(project_id, **filters)
- List runs for a projectclient.runs.cancel(project_id, run_id)
- Cancel a run
client.embedding.create_presigned_url(project_id, **options)
- Create embedded URL
client.semantic_models.ingest(semantic_model_id, **options)
- Ingest semantic model (Note: File upload support is not yet implemented)
All methods return strongly-typed Pydantic models with convenient dot notation access. The SDK automatically converts the API's camelCase fields to Pythonic snake_case:
# Project object - access with dot notation
project = client.projects.get("project-id")
print(project.id) # "12345678-1234-1234-1234-123456789012"
print(project.title) # "Sales Dashboard"
print(project.type) # ProjectType.PROJECT (enum)
print(project.created_at) # datetime object (converted from "createdAt")
print(project.last_edited_at) # datetime object (converted from "lastEditedAt")
print(project.creator.email) # "user@example.com"
print(project.owner.email) # "user@example.com"
# Run response - also uses dot notation
run = client.projects.run("project-id")
print(run.project_id) # "12345678-1234-1234-1234-123456789012"
print(run.run_id) # "87654321-4321-4321-4321-210987654321"
print(run.run_url) # "https://app.hex.tech/app/runs/..."
print(run.run_status_url) # "https://app.hex.tech/api/v1/projects/.../runs/..."
# Paginated responses have a 'values' attribute
projects = client.projects.list()
for project in projects.values:
print(f"{project.title}: {project.status}")
The API returns camelCase field names, but the SDK automatically converts them to snake_case for a more Pythonic experience:
createdAt
βcreated_at
lastEditedAt
βlast_edited_at
runId
βrun_id
projectId
βproject_id
inputParams
βinput_params
All responses are validated Pydantic models, providing:
- Auto-completion in IDEs
- Type checking with mypy/pyright
- Automatic validation of API responses
- Clear error messages for invalid data
# Install with development dependencies using uv
uv pip install -e ".[dev]"
# Run tests
uv run pytest
# Run linting
uv run ruff format src tests
uv run ruff check src tests
# Run all tests
uv run pytest
# Run with coverage
uv run pytest --cov=src/hex_toolkit
# Run specific test file
uv run pytest tests/test_client.py
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests
- Submit a pull request