Skip to main content
Glama
franccesco

Hex API MCP Server

by franccesco

hex-mcp MCP server

A MCP server for Hex that implements orchestration, monitoring, cell content access, permission management, collection organization, and group management tools.

What This Does (And Doesn't Do)

Practical Use Cases

Orchestration and Automation:

  • Trigger Hex project runs from external systems (Airflow DAGs, CI/CD pipelines)

  • Monitor run status programmatically

  • Cancel long-running or stuck executions

  • Discover and search projects across workspaces

Operational Monitoring:

  • Check if scheduled runs completed successfully

  • Get run history for auditing

  • Programmatic access to project metadata (owner, last edited, description)

Cell Content Access (NEW):

  • Read notebook structure and cell metadata

  • Read SQL query source code from SQL cells

  • Read Python/R code from CODE cells

  • Good for query migration, code analysis, and content auditing

Permission Management (NEW):

  • Programmatically manage user and group access to projects

  • Bulk update permissions across multiple projects

  • Manage workspace-wide and public access settings

  • Add or remove projects from collections

Collection Organization (NEW):

  • Create and manage collections for organizing projects

  • Organize projects by department, team, or topic

  • Control collection visibility and access

  • Bulk organize projects into collections

Group Management (NEW):

  • Create and manage user groups for permission management

  • Add and remove users from groups in bulk

  • Use groups to simplify permission management across projects

  • Maintain organized team structures

Data Connection Management (NEW):

  • List and manage database and warehouse connections

  • Create connections for BigQuery, Snowflake, Postgres, Redshift, Athena, Databricks

  • Update connection configurations and credentials

  • Control data connection sharing across workspace

Critical Limitations

Limited notebook content access:

  • ✅ Can read SQL and CODE cell source content

  • ❌ Cannot read MARKDOWN, INPUT, or visualization cells

  • ❌ Cannot create or delete cells

  • ❌ Cannot modify notebook structure

  • ❌ Cannot view query results or charts

  • ❌ Cannot manage notebook dependencies or parameters

Not suitable for:

  • Building or authoring notebooks from scratch

  • Collaborative notebook development

  • Debugging queries or code execution

  • Full notebook backup (only SQL/CODE cells accessible)

  • Reading markdown documentation or input parameters

When to Use This

Use hex-mcp when you need to:

  • Orchestrate Hex executions from external systems

  • Monitor run status and history

  • Read SQL queries and code from existing notebooks

  • Audit or migrate SQL/CODE content across projects

  • Manage permissions and access control across projects

  • Automate bulk permission updates for users, groups, and collections

  • Organize projects into collections by department, team, or topic

  • Maintain user groups for simplified permission management

  • Standardize workspace organization across your Hex instance

  • Manage data connections and database integrations programmatically

  • Automate connection setup for new workspaces or environments

For full notebook development and editing, use the Hex web UI directly.

Related MCP server: Unity MCP Integration

Available Tools

Project Operations

  • list_hex_projects: Lists available Hex projects

  • search_hex_projects: Search for Hex projects by pattern

  • get_hex_project: Get detailed information about a specific project

Project Execution

  • run_hex_project: Execute a Hex project

  • get_hex_run_status: Check the status of a project run

  • get_hex_project_runs: Get the history of project runs

  • cancel_hex_run: Cancel a running project

Cell Operations (NEW)

  • list_hex_cells: List all cells in a project with source code for SQL/CODE cells

  • update_hex_cell: Update SQL or CODE cell source and/or data connection

Permission Management (NEW)

  • update_hex_project_user_sharing: Grant or revoke user access to projects

  • update_hex_project_group_sharing: Grant or revoke group access to projects

  • update_hex_project_collection_sharing: Add or remove projects from collections

  • update_hex_project_workspace_sharing: Update workspace-wide and public access

Collection Management (NEW)

  • list_hex_collections: List all collections in the workspace

  • get_hex_collection: Get detailed information about a specific collection

  • create_hex_collection: Create a new collection with optional sharing settings

  • update_hex_collection: Update collection name, description, or sharing settings

Group Management (NEW)

  • list_hex_groups: List all groups in the workspace

  • get_hex_group: Get detailed information about a specific group

  • create_hex_group: Create a new group with optional initial members

  • update_hex_group: Update group name and/or membership (add/remove users)

  • delete_hex_group: Delete a group from the workspace

Data Connection Management (NEW)

  • list_hex_data_connections: List all data connections in the workspace

  • get_hex_data_connection: Get detailed information about a specific data connection

  • create_hex_data_connection: Create a new database/warehouse connection

  • update_hex_data_connection: Update connection configuration, credentials, or sharing

Installation

Using uv is the recommended way to install hex-mcp:

uv add hex-mcp

Or using pip:

pip install hex-mcp

To confirm it's working, you can run:

hex-mcp --version

Configuration

The easiest way to configure hex-mcp is by using the config command and passing your API key and API URL (optional and defaults to https://app.hex.tech/api/v1):

hex-mcp config --api-key "your_hex_api_key" --api-url "https://app.hex.tech/api/v1"
NOTE

This saves your configuration to a file in your home directory (e.g.~/.hex-mcp/config.yml), making it available for all hex-mcp invocations.

Using environment variables

Alternatively, the Hex MCP server can be configured with environment variables:

  • HEX_API_KEY: Your Hex API key

  • HEX_API_URL: The Hex API base URL

When setting up environment variables for MCP servers they need to be either global for Cursor to pick them up or make use of uv's --env-file flag when invoking the server.

Using with Cursor

Cursor allows AI agents to interact with Hex via the MCP protocol. Follow these steps to set up and use hex-mcp with Cursor. You can create a .cursor/mcp.json file in your project root with the following content:

{ "mcpServers": { "hex-mcp": { "command": "uv", "args": ["run", "hex-mcp", "run"] } } }

Alternatively, you can use the hex-mcp command directly if it's in your PATH:

{ "mcpServers": { "hex-mcp": { "command": "hex-mcp", "args": ["run"] } } }

Once it's up and running, you can use it in Cursor by initiating a new AI (Agent) conversation and ask it to list or run a Hex project.

IMPORTANT

The MCP server and CLI is still in development and subject to breaking changes.

Usage Examples

Reading Cell Content

Use list_hex_cells to read the structure and source code of a Hex notebook:

# List all cells in a project cells = list_hex_cells(project_id="your-project-uuid") # The response includes cell metadata and source code for SQL/CODE cells # Example response structure: { "values": [ { "id": "cell-uuid-123", "staticId": "static-id-456", "cellType": "SQL", "label": "Load Customer Data", "dataConnectionId": "connection-uuid-789", "contents": { "sqlCell": { "source": "SELECT * FROM customers WHERE active = true" }, "codeCell": null } }, { "id": "cell-uuid-456", "cellType": "CODE", "label": "Process Data", "dataConnectionId": null, "contents": { "sqlCell": null, "codeCell": { "source": "import pandas as pd\ndf = df.dropna()" } } }, { "id": "cell-uuid-789", "cellType": "MARKDOWN", "label": "Documentation", "dataConnectionId": null, "contents": { "sqlCell": null, "codeCell": null } } ], "pagination": { "next": null, "previous": null } }

Note: Only SQL and CODE cells include source content. MARKDOWN, INPUT, and visualization cells return null for both sqlCell and codeCell.

Pagination

For projects with many cells, use pagination:

# First page page1 = list_hex_cells(project_id="your-project-uuid", limit=50) # Next page using cursor if page1["pagination"]["next"]: page2 = list_hex_cells( project_id="your-project-uuid", limit=50, after=page1["pagination"]["next"] ) # Previous page if page2["pagination"]["previous"]: page1_again = list_hex_cells( project_id="your-project-uuid", limit=50, before=page2["pagination"]["previous"] )

Updating Cell Content

Update SQL or CODE cells programmatically:

# Update SQL cell source code result = update_hex_cell( cell_id="cell-uuid-123", sql_source="SELECT * FROM updated_table WHERE active = true" ) # Update CODE cell source code result = update_hex_cell( cell_id="cell-uuid-456", code_source="import pandas as pd\ndf = df.dropna()" ) # Update SQL cell data connection (without changing source) result = update_hex_cell( cell_id="cell-uuid-123", data_connection_id="new-connection-uuid" ) # Update both SQL source and connection in one call result = update_hex_cell( cell_id="cell-uuid-123", sql_source="SELECT * FROM production.customers", data_connection_id="production-connection-uuid" )

Important:

  • Can only update SQL and CODE cell types

  • Cannot update MARKDOWN, INPUT, or visualization cells

  • Requires EDIT_PROJECT_CONTENTS permission

  • Cannot update both sql_source and code_source in same call (cells are either SQL or CODE)

Query Migration Example

Extract and update SQL queries across projects:

import json # Get all cells from source project cells_response = list_hex_cells(project_id="source-project-uuid") cells = json.loads(cells_response) # Filter for SQL cells sql_cells = [ cell for cell in cells["values"] if cell["cellType"] == "SQL" and cell["contents"]["sqlCell"] ] # Migrate queries to new data connection new_connection_id = "production-bigquery-connection" for cell in sql_cells: original_query = cell["contents"]["sqlCell"]["source"] # Update table references (example: dev -> prod) updated_query = original_query.replace("dev.schema", "prod.schema") # Update the cell with new query and connection result = update_hex_cell( cell_id=cell["id"], sql_source=updated_query, data_connection_id=new_connection_id ) print(f"Updated cell: {cell['label']}") print(f"Migrated {len(sql_cells)} SQL cells to production")

Code Refactoring Example

Bulk update Python code across multiple cells:

import json # Get all CODE cells cells_response = list_hex_cells(project_id="project-uuid") cells = json.loads(cells_response) code_cells = [ cell for cell in cells["values"] if cell["cellType"] == "CODE" and cell["contents"]["codeCell"] ] # Update import statements for cell in code_cells: original_code = cell["contents"]["codeCell"]["source"] # Replace deprecated import if "from old_library" in original_code: updated_code = original_code.replace( "from old_library import func", "from new_library import func" ) # Update the cell result = update_hex_cell( cell_id=cell["id"], code_source=updated_code ) print(f"Updated cell: {cell['label']}")

Managing Project Permissions

Control access to Hex projects programmatically using the sharing endpoints.

Grant User Access

from hex_mcp.server import update_hex_project_user_sharing # Grant edit access to a single user result = update_hex_project_user_sharing( project_id="project-123", user_permissions=[ {"user_id": "user-456", "access": "CAN_EDIT"} ] ) # Grant access to multiple users with different permissions result = update_hex_project_user_sharing( project_id="project-123", user_permissions=[ {"user_id": "user-001", "access": "CAN_VIEW"}, {"user_id": "user-002", "access": "CAN_EDIT"}, {"user_id": "user-003", "access": "FULL_ACCESS"} ] ) # Revoke user access result = update_hex_project_user_sharing( project_id="project-123", user_permissions=[ {"user_id": "user-456", "access": "NONE"} ] )

Access Levels:

  • NONE: Revoke all access

  • APP_ONLY: Access only within apps (published versions)

  • CAN_VIEW: View project in logic view (read-only)

  • CAN_EDIT: Edit project contents

  • FULL_ACCESS: Edit contents and manage project settings/permissions

Grant Group Access

from hex_mcp.server import update_hex_project_group_sharing # Grant access to a group result = update_hex_project_group_sharing( project_id="project-123", group_permissions=[ {"group_id": "group-789", "access": "CAN_VIEW"} ] ) # Grant access to multiple groups result = update_hex_project_group_sharing( project_id="project-123", group_permissions=[ {"group_id": "analytics-team", "access": "CAN_EDIT"}, {"group_id": "leadership-team", "access": "CAN_VIEW"} ] )

Add Projects to Collections

from hex_mcp.server import update_hex_project_collection_sharing # Add project to a collection result = update_hex_project_collection_sharing( project_id="project-123", collection_permissions=[ {"collection_id": "collection-456", "access": "CAN_VIEW"} ] ) # Add to multiple collections with different access levels result = update_hex_project_collection_sharing( project_id="project-123", collection_permissions=[ {"collection_id": "public-dashboards", "access": "APP_ONLY"}, {"collection_id": "internal-analytics", "access": "CAN_EDIT"} ] ) # Remove from collection result = update_hex_project_collection_sharing( project_id="project-123", collection_permissions=[ {"collection_id": "collection-456", "access": "NONE"} ] )

Manage Workspace and Public Access

from hex_mcp.server import update_hex_project_workspace_sharing # Make project viewable by entire workspace result = update_hex_project_workspace_sharing( project_id="project-123", workspace_access="CAN_VIEW" ) # Make project publicly accessible result = update_hex_project_workspace_sharing( project_id="project-123", public_access="APP_ONLY" ) # Update both workspace and public access result = update_hex_project_workspace_sharing( project_id="project-123", workspace_access="CAN_EDIT", public_access="APP_ONLY" ) # Revoke public access (keep workspace access) result = update_hex_project_workspace_sharing( project_id="project-123", public_access="NONE" )

Bulk Permission Management Example

Standardize permissions across multiple projects:

import json from hex_mcp.server import ( list_hex_projects, update_hex_project_user_sharing, update_hex_project_workspace_sharing ) # Get all projects projects_response = list_hex_projects() projects = json.loads(projects_response) # Define standard access policies analytics_team_users = ["user-001", "user-002", "user-003"] leadership_users = ["user-100", "user-101"] for project in projects: project_id = project["projectId"] # Grant analytics team edit access update_hex_project_user_sharing( project_id=project_id, user_permissions=[ {"user_id": user_id, "access": "CAN_EDIT"} for user_id in analytics_team_users ] ) # Grant leadership view access update_hex_project_user_sharing( project_id=project_id, user_permissions=[ {"user_id": user_id, "access": "CAN_VIEW"} for user_id in leadership_users ] ) # Make viewable by workspace, not public update_hex_project_workspace_sharing( project_id=project_id, workspace_access="CAN_VIEW", public_access="NONE" ) print(f"Updated permissions for: {project['name']}")

Important Notes:

  • All sharing operations require appropriate workspace permissions

  • User/group IDs must exist in your Hex workspace

  • Collection IDs must be valid collections you have access to

  • Workspace access applies to all workspace members

  • Public access (publicWeb) allows anyone with the link to access

Managing Collections

Organize projects into collections for better workspace organization.

List Collections

from hex_mcp.server import list_hex_collections import json # List all collections collections = list_hex_collections() data = json.loads(collections) for collection in data["values"]: print(f"{collection['name']}: {collection['id']}") print(f" Created by: {collection.get('creator', {}).get('email', 'N/A')}") # List with pagination page1 = list_hex_collections(limit=10) data = json.loads(page1) if data["pagination"]["next"]: page2 = list_hex_collections(limit=10, after=data["pagination"]["next"])

Get Collection Details

from hex_mcp.server import get_hex_collection import json # Get specific collection collection = get_hex_collection(collection_id="collection-123") data = json.loads(collection) print(f"Collection: {data['name']}") print(f"Description: {data.get('description', 'No description')}") print(f"Sharing with {len(data['sharing'].get('users', []))} users") print(f"Sharing with {len(data['sharing'].get('groups', []))} groups")

Create Collections

from hex_mcp.server import create_hex_collection import json # Create simple collection collection = create_hex_collection( name="Q4 2026 Analytics", description="Analytics projects for Q4 2026" ) data = json.loads(collection) print(f"Created collection: {data['id']}") # Create with sharing settings collection = create_hex_collection( name="Executive Dashboards", description="Dashboards for executive team", sharing_users=[ {"id": "user-ceo", "access": "CAN_VIEW"}, {"id": "user-cfo", "access": "CAN_VIEW"} ], workspace_access="NONE" # Only specified users can access ) # Create with group access collection = create_hex_collection( name="Finance Reports", description="Financial reporting and analysis", sharing_groups=[ {"id": "finance-team", "access": "CAN_EDIT"} ], workspace_access="CAN_VIEW" )

Update Collections

from hex_mcp.server import update_hex_collection import json # Update collection name and description result = update_hex_collection( collection_id="collection-123", name="Q1 2027 Analytics", description="Updated for Q1 2027" ) # Update sharing settings result = update_hex_collection( collection_id="collection-123", sharing_users=[ {"id": "user-456", "access": "CAN_EDIT"} ], workspace_access="CAN_VIEW" ) # Update multiple fields at once result = update_hex_collection( collection_id="collection-123", name="Updated Collection Name", description="Updated description", sharing_groups=[ {"id": "analytics-team", "access": "CAN_EDIT"} ], workspace_access="CAN_VIEW" )

Collection Organization Example

Organize all projects by department:

import json from hex_mcp.server import ( list_hex_projects, list_hex_collections, create_hex_collection, update_hex_project_collection_sharing ) # Define department structure departments = { "Engineering": ["user-eng-lead", "group-engineering"], "Finance": ["user-fin-lead", "group-finance"], "Marketing": ["user-mkt-lead", "group-marketing"] } # Create collections for each department collection_ids = {} for dept_name, members in departments.items(): # Create collection collection = create_hex_collection( name=f"{dept_name} Projects", description=f"All {dept_name} department projects", workspace_access="CAN_VIEW" ) data = json.loads(collection) collection_ids[dept_name] = data["id"] print(f"Created collection for {dept_name}: {data['id']}") # Get all projects projects = list_hex_projects() projects_data = json.loads(projects) # Organize projects into collections based on name patterns for project in projects_data: project_id = project["projectId"] project_name = project["name"].lower() # Determine which collection(s) this project belongs to if "engineering" in project_name or "technical" in project_name: update_hex_project_collection_sharing( project_id=project_id, collection_permissions=[ {"collection_id": collection_ids["Engineering"], "access": "CAN_EDIT"} ] ) print(f"Added '{project['name']}' to Engineering collection") elif "finance" in project_name or "revenue" in project_name: update_hex_project_collection_sharing( project_id=project_id, collection_permissions=[ {"collection_id": collection_ids["Finance"], "access": "CAN_EDIT"} ] ) print(f"Added '{project['name']}' to Finance collection") elif "marketing" in project_name or "campaign" in project_name: update_hex_project_collection_sharing( project_id=project_id, collection_permissions=[ {"collection_id": collection_ids["Marketing"], "access": "CAN_EDIT"} ] ) print(f"Added '{project['name']}' to Marketing collection") print("Collection organization complete!")

Collection Management Notes:

  • Collections help organize projects by team, department, or topic

  • Collections can have their own sharing settings independent of projects

  • A project can belong to multiple collections

  • Workspace access on collections controls who can see the collection exists

  • Creating collections requires appropriate workspace permissions

Managing Groups

Organize users into groups for simplified permission management.

List Groups

from hex_mcp.server import list_hex_groups import json # List all groups groups = list_hex_groups() data = json.loads(groups) for group in data["values"]: print(f"{group['name']}: {group['id']}") print(f" Created: {group['createdAt']}") # List with pagination and sorting page1 = list_hex_groups( limit=10, sort_by="name", sort_direction="asc" ) data = json.loads(page1) if data["pagination"]["next"]: page2 = list_hex_groups(limit=10, after=data["pagination"]["next"])

Get Group Details

from hex_mcp.server import get_hex_group import json # Get specific group group = get_hex_group(group_id="group-123") data = json.loads(group) print(f"Group: {data['name']}") print(f"ID: {data['id']}") print(f"Created: {data['createdAt']}")

Create Groups

from hex_mcp.server import create_hex_group import json # Create simple group group = create_hex_group(name="Analytics Team") data = json.loads(group) print(f"Created group: {data['id']}") # Create with initial members group = create_hex_group( name="Finance Team", member_user_ids=[ "user-123", "user-456", "user-789" ] ) data = json.loads(group) print(f"Created group with 3 members: {data['id']}")

Update Groups

from hex_mcp.server import update_hex_group import json # Update group name result = update_hex_group( group_id="group-123", name="Senior Analytics Team" ) # Add members to group result = update_hex_group( group_id="group-123", add_member_user_ids=["user-new-1", "user-new-2"] ) # Remove members from group result = update_hex_group( group_id="group-123", remove_member_user_ids=["user-old-1"] ) # Update name and membership together result = update_hex_group( group_id="group-123", name="Lead Analytics Team", add_member_user_ids=["user-lead"], remove_member_user_ids=["user-junior"] )

Delete Groups

from hex_mcp.server import delete_hex_group # Delete a group (does not delete the users, only the group) result = delete_hex_group(group_id="group-old-team") print(result) # "Group deleted successfully"

Bulk Group Management Example

Create department-based groups and assign users:

import json from hex_mcp.server import ( create_hex_group, update_hex_group, update_hex_project_group_sharing ) # Define department structure with user lists departments = { "Engineering": { "leads": ["user-eng-lead-1", "user-eng-lead-2"], "members": ["user-eng-1", "user-eng-2", "user-eng-3"] }, "Data Science": { "leads": ["user-ds-lead"], "members": ["user-ds-1", "user-ds-2", "user-ds-3", "user-ds-4"] }, "Analytics": { "leads": ["user-analytics-lead"], "members": ["user-analyst-1", "user-analyst-2"] } } # Create groups for each department group_ids = {} for dept_name, users in departments.items(): # Create main department group all_members = users["leads"] + users["members"] group = create_hex_group( name=f"{dept_name} Team", member_user_ids=all_members ) data = json.loads(group) group_ids[dept_name] = data["id"] print(f"Created {dept_name} Team: {data['id']} ({len(all_members)} members)") # Create leadership sub-group lead_group = create_hex_group( name=f"{dept_name} Leadership", member_user_ids=users["leads"] ) lead_data = json.loads(lead_group) group_ids[f"{dept_name}_Leadership"] = lead_data["id"] print(f"Created {dept_name} Leadership: {lead_data['id']} ({len(users['leads'])} members)") # Grant group access to relevant projects # Engineering team gets edit access to technical projects update_hex_project_group_sharing( project_id="technical-project-123", group_permissions=[ {"group_id": group_ids["Engineering"], "access": "CAN_EDIT"} ] ) # Analytics team gets view access to all dashboards update_hex_project_group_sharing( project_id="dashboard-project-456", group_permissions=[ {"group_id": group_ids["Analytics"], "access": "CAN_VIEW"} ] ) # Leadership groups get view access to executive dashboards for dept in ["Engineering", "Data Science", "Analytics"]: leadership_group_id = group_ids[f"{dept}_Leadership"] update_hex_project_group_sharing( project_id="executive-dashboard-789", group_permissions=[ {"group_id": leadership_group_id, "access": "CAN_VIEW"} ] ) print("Group-based permission management complete!")

Team Reorganization Example

Handle team changes by updating group memberships:

import json from hex_mcp.server import ( list_hex_groups, update_hex_group ) # Get all groups groups = list_hex_groups() groups_data = json.loads(groups) # Find specific groups that need updates engineering_group = None for group in groups_data["values"]: if group["name"] == "Engineering Team": engineering_group = group break if engineering_group: # New hires joining new_engineers = ["user-new-eng-1", "user-new-eng-2"] # Engineers leaving departing_engineers = ["user-old-eng-1"] # Update group membership result = update_hex_group( group_id=engineering_group["id"], add_member_user_ids=new_engineers, remove_member_user_ids=departing_engineers ) print(f"Updated {engineering_group['name']}") print(f" Added: {len(new_engineers)} members") print(f" Removed: {len(departing_engineers)} members")

Group Management Notes:

  • Groups simplify permission management by allowing you to grant access to multiple users at once

  • A user can belong to multiple groups

  • Maximum 100 users can be added or removed in a single update operation

  • Deleting a group does not delete the users, only the group itself

  • Group permissions are inherited by all group members

  • Use groups with project sharing endpoints to grant team-wide access

Managing Data Connections

Manage database and warehouse connections for Hex projects.

List Data Connections

from hex_mcp.server import list_hex_data_connections import json # List all data connections connections = list_hex_data_connections() data = json.loads(connections) for conn in data["values"]: print(f"{conn['name']} ({conn['type']}): {conn['id']}") if conn.get('description'): print(f" Description: {conn['description']}") # List with pagination and sorting page1 = list_hex_data_connections( limit=10, sort_by="NAME", sort_direction="asc" ) data = json.loads(page1) if data["pagination"]["next"]: page2 = list_hex_data_connections(limit=10, after=data["pagination"]["next"])

Get Data Connection Details

from hex_mcp.server import get_hex_data_connection import json # Get specific connection connection = get_hex_data_connection(connection_id="conn-123") data = json.loads(connection) print(f"Connection: {data['name']}") print(f"Type: {data['type']}") print(f"Description: {data.get('description', 'N/A')}") print(f"Include Magic: {data.get('includeMagic', False)}") print(f"Allow Writeback: {data.get('allowWritebackCells', False)}") # Check sharing settings if 'sharing' in data: workspace = data['sharing'].get('workspace', {}) print(f"Workspace Access: {workspace.get('members', 'None')}")

Create Data Connections

from hex_mcp.server import create_hex_data_connection import json # Create BigQuery connection bigquery_conn = create_hex_data_connection( name="Production BigQuery", connection_type="bigquery", connection_details={ "bigquery": { "serviceAccountJsonConfig": json.dumps(service_account_config), "projectId": "my-gcp-project", "enableStorageApi": True, "enableDriveAccess": False } }, description="Production data warehouse for analytics", include_magic=True, allow_writeback_cells=False, sharing={ "workspace": { "members": "CAN_USE" } } ) data = json.loads(bigquery_conn) print(f"Created BigQuery connection: {data['id']}") # Create Snowflake connection snowflake_conn = create_hex_data_connection( name="Snowflake Analytics", connection_type="snowflake", connection_details={ "snowflake": { "account": "my-account", "warehouse": "ANALYTICS_WH", "database": "ANALYTICS_DB", "schema": "PUBLIC", "username": "hex_service", "password": "secure_password" } }, description="Snowflake warehouse for analytics", include_magic=True ) data = json.loads(snowflake_conn) print(f"Created Snowflake connection: {data['id']}") # Create Postgres connection postgres_conn = create_hex_data_connection( name="Application Database", connection_type="postgres", connection_details={ "postgres": { "hostname": "db.example.com", "port": 5432, "database": "app_db", "username": "readonly_user", "password": "secure_password", "ssl": True } }, description="Production application database (read-only)", connect_via_ssh=False, include_magic=True, allow_writeback_cells=False ) data = json.loads(postgres_conn) print(f"Created Postgres connection: {data['id']}")

Update Data Connections

from hex_mcp.server import update_hex_data_connection import json # Update connection name and description result = update_hex_data_connection( connection_id="conn-123", name="Updated Production BigQuery", description="Updated production data warehouse for analytics and reporting" ) data = json.loads(result) print(f"Updated connection: {data['name']}") # Update connection settings result = update_hex_data_connection( connection_id="conn-123", include_magic=False, allow_writeback_cells=True ) print("Updated connection settings") # Update connection sharing result = update_hex_data_connection( connection_id="conn-123", sharing={ "workspace": { "members": "CAN_USE", "guests": "NONE" }, "groups": { "upsert": [ {"group": {"id": "analytics-team-group-id"}, "access": "CAN_USE"}, {"group": {"id": "data-eng-group-id"}, "access": "CAN_ADMIN"} ] } } ) print("Updated connection sharing") # Rotate credentials by updating connection details result = update_hex_data_connection( connection_id="conn-123", connection_details={ "bigquery": { "serviceAccountJsonConfig": json.dumps(new_service_account), "projectId": "my-gcp-project", "enableStorageApi": True, "enableDriveAccess": False } } ) print("Rotated connection credentials")

Bulk Connection Setup

Automate connection setup for new workspaces or environments:

from hex_mcp.server import create_hex_data_connection import json # Define standard connections for a workspace connection_configs = { "Production BigQuery": { "type": "bigquery", "details": { "bigquery": { "serviceAccountJsonConfig": json.dumps(prod_bq_creds), "projectId": "prod-project", "enableStorageApi": True } }, "description": "Production BigQuery warehouse" }, "Staging BigQuery": { "type": "bigquery", "details": { "bigquery": { "serviceAccountJsonConfig": json.dumps(staging_bq_creds), "projectId": "staging-project", "enableStorageApi": True } }, "description": "Staging BigQuery warehouse" }, "Production Snowflake": { "type": "snowflake", "details": { "snowflake": { "account": "prod-account", "warehouse": "PROD_WH", "database": "PROD_DB", "username": "hex_prod", "password": prod_sf_password } }, "description": "Production Snowflake warehouse" }, "Application DB": { "type": "postgres", "details": { "postgres": { "hostname": "prod-db.example.com", "port": 5432, "database": "app_db", "username": "readonly", "password": postgres_password, "ssl": True } }, "description": "Application database (read-only)" } } # Create all connections created_connections = {} for name, config in connection_configs.items(): connection = create_hex_data_connection( name=name, connection_type=config["type"], connection_details=config["details"], description=config["description"], include_magic=True, allow_writeback_cells=False, sharing={ "workspace": { "members": "CAN_USE" } } ) data = json.loads(connection) created_connections[name] = data["id"] print(f"Created {name}: {data['id']}") print(f"\nCreated {len(created_connections)} data connections")

Data Connection Management Notes:

  • Supported connection types: BigQuery, Snowflake, Postgres, Redshift, Athena, Databricks

  • Each connection type has specific configuration requirements in connection_details

  • Connection credentials are stored securely by Hex

  • Use sharing settings to control who can use each connection

  • CAN_USE access allows users to query data, CAN_ADMIN allows configuration changes

  • SSH tunneling supported via connect_via_ssh parameter for secure connections

  • Consider using connection-level access control for sensitive data sources

About This Fork

This fork extends the upstream hex-mcp package with bug fixes and new cell operations functionality.

Bug Fixes (v0.1.10 upstream)

  • Five tools declared -> str return type but returned Python dicts/lists

  • Caused pydantic validation errors in Claude Code MCP integration

  • Fixed by adding json.dumps() to return statements in src/hex_mcp/server.py

Fixed Tools (lines 74, 172, 187, 206, 229):

  • list_hex_projects()

  • get_hex_project()

  • get_hex_run_status()

  • get_hex_project_runs()

  • run_hex_project()

New Features

Cell Operations (Phase 1 of complete Hex API implementation):

  • list_hex_cells() - Read notebook structure and cell source code (SQL/CODE cells)

  • update_hex_cell() - Update SQL/CODE cell source and data connections

  • Comprehensive test suite with 29 passing tests (all mocked, no credentials required)

  • Full documentation with usage examples for query migration and code refactoring

Permission Management (Phase 2 of complete Hex API implementation):

  • update_hex_project_user_sharing() - Grant or revoke user access to projects

  • update_hex_project_group_sharing() - Grant or revoke group access to projects

  • update_hex_project_collection_sharing() - Add or remove projects from collections

  • update_hex_project_workspace_sharing() - Manage workspace-wide and public access

  • 18 additional passing tests for all sharing scenarios

  • Complete examples for bulk permission management

Collection Management (Phase 3 of complete Hex API implementation):

  • list_hex_collections() - List all collections in workspace

  • get_hex_collection() - Get collection details with sharing settings

  • create_hex_collection() - Create collections with optional sharing

  • update_hex_collection() - Update collection metadata and sharing

  • 18 additional passing tests for collection CRUD operations

  • Complete examples for workspace organization by department

Group Management (Phase 4 of complete Hex API implementation):

  • list_hex_groups() - List all groups in workspace

  • get_hex_group() - Get group details

  • create_hex_group() - Create groups with optional initial members

  • update_hex_group() - Update group name and membership (add/remove up to 100 users)

  • delete_hex_group() - Delete groups from workspace

  • 21 additional passing tests for full group CRUD operations

  • Complete examples for department-based group management and team reorganization

  • All functions include comprehensive Google-style docstrings

Data Connection Management (Phase 5 of complete Hex API implementation):

  • list_hex_data_connections() - List all data connections with pagination and sorting

  • get_hex_data_connection() - Get connection details including credentials and sharing

  • create_hex_data_connection() - Create BigQuery, Snowflake, Postgres, Redshift, Athena, Databricks connections

  • update_hex_data_connection() - Update connection configuration, credentials, and sharing settings

  • 18 additional passing tests for data connection CRUD operations

  • Complete examples for connection setup, credential rotation, and bulk deployment

  • Support for all 6 major database/warehouse connection types

  • Full Google-style docstrings with detailed connection type specifications

Testing Infrastructure:

  • Comprehensive test fixtures with mocked authentication

  • 105 passing tests, 0 skipped (all mocked, no credentials required)

  • Test coverage growing with each phase

  • Security checks to prevent production credentials in tests

  • pytest, pytest-asyncio, pytest-cov integration

  • Fixed backoff handler to work in both production and test environments

Documentation:

  • Complete OpenAPI spec analysis (see OPENAPI-VALIDATION.md)

  • Detailed implementation plan (see IMPLEMENTATION-PLAN.md)

  • Test strategy guide (see TEST-STRATEGY.md)

  • Usage examples for all new features

Upstream: https://github.com/franccesco/hex-mcp

Status: Branch bugfix/fast-mcp-return-types includes both bug fixes and new cell operations functionality. Ready for upstream PR submission if desired.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/franccesco/hex-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server