hasura/promptql-mcp
If you are the rightful owner of promptql-mcp and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to dayong@mcphub.com.
Connect Hasura PromptQL to AI assistants like Claude using the Model Context Protocol (MCP).
PromptQL MCP Server
Connect Hasura PromptQL to AI assistants like Claude using the Model Context Protocol (MCP).
Overview
This project provides a bridge between Hasura's PromptQL data agent and AI assistants through the Model Context Protocol. With this integration, AI assistants can directly query your enterprise data using natural language, leveraging PromptQL's powerful capabilities for data access, analysis, and visualization.
Features
- 🔍 Natural Language Data Queries - Ask questions about your enterprise data in plain English
- 📊 Table Artifact Support - Get formatted table results from your data queries
- 🔐 Secure Configuration - Safely store and manage your PromptQL API credentials
- 🔑 Dual Authentication Modes - Support for both public and private DDN deployments
- 📈 Data Analysis - Get insights and visualizations from your data
- 🛠️ Simple Integration - Works with Claude Desktop and other MCP-compatible clients
Authentication Modes
The PromptQL MCP server supports two authentication modes to work with different DDN deployment types:
Public Mode (Default)
- Uses
Auth-Tokenheader for authentication - Compatible with public DDN endpoints
- Backward compatible with existing configurations
- Use when: Your DDN deployment is publicly accessible
Private Mode
- Uses
x-hasura-ddn-tokenheader for authentication - Compatible with private DDN endpoints
- Enhanced security for private deployments
- Use when: Your DDN deployment is private/internal
You can specify the authentication mode during configuration using the --auth-mode flag or auth_mode parameter.
Installation
Prerequisites
- Python 3.10 or higher
- A Hasura PromptQL project with API key, playground URL, and DDN Auth Token
- Claude Desktop (for interactive use) or any MCP-compatible client
Install from Source
- Clone the repository:
git clone https://github.com/hasura/promptql-mcp.git
cd promptql-mcp
- Set up a virtual environment (recommended):
# Create a virtual environment
python -m venv venv
# Activate the virtual environment
source venv/bin/activate # On Windows: venv\Scripts\activate
- Install the package:
pip install -e .
Quick Start
- Configure your PromptQL credentials:
# For public DDN deployments (default)
python -m promptql_mcp_server setup --api-key YOUR_PROMPTQL_API_KEY --playground-url YOUR_PLAYGROUND_URL --auth-token YOUR_AUTH_TOKEN --auth-mode public
# For private DDN deployments
python -m promptql_mcp_server setup --api-key YOUR_PROMPTQL_API_KEY --playground-url YOUR_PLAYGROUND_URL --auth-token YOUR_AUTH_TOKEN --auth-mode private
Alternative: Environment Variables
export PROMPTQL_API_KEY="your-api-key"
export PROMPTQL_PLAYGROUND_URL="your-playground-url"
export PROMPTQL_AUTH_TOKEN="your-auth-token"
export PROMPTQL_AUTH_MODE="public" # or "private"
- Test the server:
python -m promptql_mcp_server
- In a new terminal, try the example client:
python examples/simple_client.py
Using with Claude Desktop
- Install Claude Desktop
- Open Claude Desktop and go to Settings > Developer
- Click "Edit Config" and add the following:
{
"mcpServers": {
"promptql": {
"command": "/full/path/to/python",
"args": ["-m", "promptql_mcp_server"]
}
}
}
Replace /full/path/to/python with the actual path to your Python executable.
If you're using a virtual environment (recommended):
{
"mcpServers": {
"promptql": {
"command": "/path/to/your/project/venv/bin/python",
"args": ["-m", "promptql_mcp_server"]
}
}
}
Alternative: Using Environment Variables in Claude Desktop
{
"mcpServers": {
"promptql": {
"command": "/full/path/to/python",
"args": ["-m", "promptql_mcp_server"],
"env": {
"PROMPTQL_API_KEY": "your-api-key",
"PROMPTQL_PLAYGROUND_URL": "your-playground-url",
"PROMPTQL_AUTH_TOKEN": "your-auth-token",
"PROMPTQL_AUTH_MODE": "public"
}
}
}
}
To find your Python path, run:
which python # On macOS/Linux
where python # On Windows
- Restart Claude Desktop
- Chat with Claude and use natural language to query your data
Example Prompts for Claude
- "What were our total sales last quarter?"
- "Who are our top five customers by revenue?"
- "Show me the trend of new user signups over the past 6 months"
- "Which products have the highest profit margin?"
Available Tools and Prompts
Tools
The server exposes the following MCP tools:
Thread Management Mode
- start_thread - Start a new conversation thread with an initial message and wait for completion (returns thread_id, interaction_id, and response)
- start_thread_without_polling - Start a new conversation thread without waiting for completion (returns thread_id and interaction_id immediately)
- continue_thread - Continue an existing thread with a new message (maintains conversation context)
- get_thread_status - Check the status of a thread (processing/complete) using GET /threads/v2/{thread_id}
- cancel_thread - Cancel the processing of the latest interaction in a thread
Configuration
- setup_config - Configure PromptQL API key, playground URL, DDN Auth Token, and authentication mode (public/private)
- check_config - Verify the current configuration status including authentication mode
Usage Examples
Multi-Turn Conversation Mode
Option 1: Start with polling (get immediate response)
# Start a new conversation thread (waits for completion and returns full response)
thread_result = await client.call_tool("start_thread", {
"message": "What tables are available in my database?"
})
# Extract thread_id from result (format: "Thread ID: abc-123\nInteraction ID: def-456\n\n[response content]")
thread_id = thread_result.split("Thread ID: ")[1].split("\n")[0].strip()
# Continue the conversation with context
result = await client.call_tool("continue_thread", {
"thread_id": thread_id,
"message": "Show me the schema of the users table"
})
Option 2: Start without polling (check status separately)
# Start a new conversation thread (returns immediately with thread_id)
thread_result = await client.call_tool("start_thread_without_polling", {
"message": "What tables are available in my database?"
})
# Extract thread_id from result (format: "Thread ID: abc-123\nInteraction ID: def-456\n\n...")
thread_id = thread_result.split("Thread ID: ")[1].split("\n")[0].strip()
# Check status manually
status_result = await client.call_tool("get_thread_status", {
"thread_id": thread_id
})
# Continue when ready
result = await client.call_tool("continue_thread", {
"thread_id": thread_id,
"message": "Show me the schema of the users table"
})
# Continue further
result = await client.call_tool("continue_thread", {
"thread_id": thread_id,
"message": "How many records are in that table?"
})
# Check thread status
status = await client.call_tool("get_thread_status", {
"thread_id": thread_id
})
# Cancel thread processing (if currently processing)
cancel_result = await client.call_tool("cancel_thread", {
"thread_id": thread_id
})
With System Instructions
# Start thread with system instructions
result = await client.call_tool("start_thread", {
"message": "Show me the top 10 products by revenue",
"system_instructions": "Format all results as markdown tables"
})
Configuration Examples
Setting Up Authentication Modes
Public Mode Configuration (Default)
# Using MCP tool
result = await client.call_tool("setup_config", {
"api_key": "your-api-key",
"playground_url": "https://promptql.your-domain.public-ddn.hasura.app/playground",
"auth_token": "your-auth-token",
"auth_mode": "public"
})
Private Mode Configuration
# Using MCP tool
result = await client.call_tool("setup_config", {
"api_key": "your-api-key",
"playground_url": "https://promptql.your-domain.private-ddn.hasura.app/playground",
"auth_token": "your-auth-token",
"auth_mode": "private"
})
Checking Current Configuration
# Check what authentication mode is currently configured
config_result = await client.call_tool("check_config", {})
# Returns configuration details including auth_mode
Prompts
- data_analysis - Create a specialized prompt for data analysis on a specific topic
Architecture
This integration follows a client-server architecture:
- PromptQL MCP Server - A Python server that exposes PromptQL capabilities through the MCP protocol
- MCP Client - Any client that implements the MCP protocol (e.g., Claude Desktop)
- PromptQL API - Hasura's Natural Language API for data access and analysis
The server translates between the MCP protocol and PromptQL's API, allowing seamless integration between AI assistants and your enterprise data.
Troubleshooting
Command not found: pip or python
On many systems, especially macOS, you may need to use python3 and pip3 instead of python and pip.
externally-managed-environment error
Modern Python installations often prevent global package installation. Use a virtual environment as described in the installation section.
No module named promptql_mcp_server
Ensure you've:
- Installed the package with
pip install -e . - Are using the correct Python environment (if using a virtual environment, make sure it's activated)
- Configured Claude Desktop to use the correct Python executable path
Python version issues
If you have multiple Python versions installed, make sure you're using Python 3.10 or higher:
python3.10 -m venv venv # Specify the exact version
Authentication Issues
Wrong authentication mode
If you're getting authentication errors, verify you're using the correct authentication mode:
- Public DDN deployments: Use
--auth-mode public(default) - Private DDN deployments: Use
--auth-mode private
Check your current configuration:
python -m promptql_mcp_server
# Then use check_config tool to see current auth_mode
Switching authentication modes
To switch between authentication modes, simply reconfigure:
# Switch to private mode
python -m promptql_mcp_server setup --api-key YOUR_API_KEY --playground-url YOUR_URL --auth-token YOUR_TOKEN --auth-mode private
# Switch back to public mode
python -m promptql_mcp_server setup --api-key YOUR_API_KEY --playground-url YOUR_URL --auth-token YOUR_TOKEN --auth-mode public
Development
Project Structure
promptql-mcp/
├── promptql_mcp_server/ # Main package
│ ├── __init__.py
│ ├── __main__.py # Entry point
│ ├── server.py # MCP server implementation
│ ├── config.py # Configuration management
│ └── api/ # API clients
│ ├── __init__.py
│ └── promptql_client.py # PromptQL API client
├── examples/ # Example clients
│ └── simple_client.py # Simple MCP client
├── setup.py # Package configuration
└── README.md # Documentation
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
License
This project is licensed under the MIT License - see the LICENSE file for details.
Acknowledgements
TODO
- process the thread response properly based on interaction_id returned as part of continue_thread and start_thread in mcp_server, at the moment, it only looks for the latest interaction_id
- process the interaction_response accordingly to figure out the code, plan and code_output
- ensure the simple_client.py shows the cancellation_thread demo properly, the current status call looks to be blocking
- Validate if the artifacts are processed accordingly