Skip to main content
Glama

Dune MCP Server

A comprehensive MCP (Model Context Protocol) server for interacting with Dune Analytics - the leading platform for blockchain data analysis.

Features

Tools

This server exposes all major Dune Analytics API endpoints as MCP tools:

SQL Execution

  • execute_sql - Execute raw SQL queries against Dune's data engine

  • get_execution_status - Check query execution status

  • get_execution_results - Retrieve query results (JSON)

  • get_execution_results_csv - Retrieve query results (CSV)

  • cancel_execution - Cancel a running query

Saved Query Management

  • execute_query - Execute a saved query by ID

  • get_query - Get query details

  • get_query_results - Get latest cached results without re-executing

  • get_query_results_csv - Get latest results as CSV

  • create_query - Create and save a new query

  • update_query - Update an existing query

  • archive_query - Archive a query

  • make_query_private / make_query_public - Change query visibility

Data Upload

  • upload_csv - Upload CSV data to create/update a table

  • create_table - Create a new table with schema

  • insert_table_rows - Insert rows into an existing table

  • clear_table - Clear all data from a table

  • delete_table - Permanently delete a table

Resources

The server exposes comprehensive documentation as MCP resources to help LLMs write valid DuneSQL queries:

Resource URI

Description

dune://guide/sql-syntax

DuneSQL (Trino) syntax reference, data types, functions

dune://guide/tables

Available tables: dex.trades, prices.usd, chain-specific tables

dune://guide/query-patterns

Common analytics patterns: volume, holders, whales, gas

dune://guide/parameters

How to use query parameters

dune://guide/errors

Common errors and troubleshooting

Related MCP server: Dune API MCP Server

Installation

cd dune-mcp
pip install -e .

Configuration

Set your Dune API key as an environment variable:

export DUNE_API_KEY="your-api-key-here"

Get your API key from Dune Settings.

Usage

Running the Server

# Direct execution
python server.py

# Or via installed script
dune-mcp

Claude Desktop Configuration

Add to your Claude Desktop config (~/Library/Application Support/Claude/claude_desktop_config.json):

{
  "mcpServers": {
    "dune": {
      "command": "python",
      "args": ["/path/to/dune-mcp/server.py"],
      "env": {
        "DUNE_API_KEY": "your-api-key-here"
      }
    }
  }
}

Or using uv:

{
  "mcpServers": {
    "dune": {
      "command": "uv",
      "args": ["run", "--directory", "/path/to/dune-mcp", "python", "server.py"],
      "env": {
        "DUNE_API_KEY": "your-api-key-here"
      }
    }
  }
}

Example Queries

Simple DEX Volume Query

# Using execute_sql tool
result = await execute_sql(
    sql="""
    SELECT 
        project,
        SUM(amount_usd) as volume
    FROM dex.trades
    WHERE block_time > now() - interval '24' hour
    GROUP BY 1
    ORDER BY 2 DESC
    LIMIT 10
    """,
    performance="medium"
)

Cross-Chain Analysis

result = await execute_sql(
    sql="""
    SELECT 
        blockchain,
        COUNT(*) as tx_count,
        SUM(amount_usd) as volume_usd
    FROM dex.trades
    WHERE block_time > now() - interval '7' day
    GROUP BY 1
    ORDER BY 3 DESC
    """
)

Create Parameterized Query

result = await create_query(
    name="Token Volume Analysis",
    query_sql="""
    SELECT 
        DATE_TRUNC('day', block_time) as day,
        SUM(amount_usd) as volume
    FROM dex.trades
    WHERE token_bought_symbol = '{{token}}'
        AND block_time > now() - interval '{{days}}' day
    GROUP BY 1
    ORDER BY 1
    """,
    parameters=[
        {"key": "token", "value": "UNI", "type": "text"},
        {"key": "days", "value": "30", "type": "number"}
    ]
)

Available Tables

Curated (Cross-Chain)

  • dex.trades - DEX trades across all EVM chains

  • dex_solana.trades - Solana DEX trades

  • nft.trades - NFT trades

  • prices.usd - Token prices

  • tokens.erc20 - ERC20 token metadata

Chain-Specific

  • ethereum.transactions, ethereum.logs, ethereum.traces

  • polygon.transactions, polygon.logs, etc.

  • arbitrum.transactions, optimism.transactions, base.transactions

Decoded Protocol Tables

  • uniswap_v3_ethereum.Pair_evt_Swap

  • aave_v3_ethereum.Pool_evt_Supply

  • And many more...

API Reference

See Dune API Documentation for complete API details.

License

MIT

Available Tools

19 tools
archive_queryB

Archive a query, making it uneditable and unexecutable.

Args: query_id: The unique identifier of the query to archive.

Returns: Archive confirmation.

Inputs: query_id (required). Returns: object

cancel_executionC

Cancel an ongoing query execution.

Args: execution_id: The execution ID of the running query.

Returns: Success status of the cancellation.

Inputs: execution_id (required). Returns: object

clear_tableA

Remove all data from a table while preserving its schema.

Args: namespace: Namespace of the table. table_name: Name of the table to clear.

Returns: Clear confirmation.

Inputs: namespace (required), table_name (required). Returns: object

create_queryA

Create and save a new query on Dune.

Args: name: Name for the query. query_sql: The SQL query text. Use {{param_name}} for parameters. description: Optional description of what the query does. is_private: Whether the query should be private (default False). parameters: Optional list of parameter definitions, each with: - key: Parameter name - value: Default value - type: "text", "number", or "enum" - enumOptions: List of allowed values (for enum type) tags: Optional list of tags for organization.

Returns: Created query details including query_id.

Example: create_query( name="Top DEX Volume", query_sql="SELECT project, SUM(amount_usd) as volume FROM dex.trades WHERE block_time > now() - interval '{{days}}' day GROUP BY 1 ORDER BY 2 DESC LIMIT 10", parameters=[{"key": "days", "value": "7", "type": "number"}] )

Inputs: name (required), query_sql (required), description, is_private, +2 more. Returns: object

create_tableB

Create a new table with a defined schema.

Args: namespace: Namespace for the table (usually your username). table_name: Name for the table. columns: List of column definitions, each with: - name: Column name - type: Data type ("string", "integer", "double", "timestamp", "boolean") - nullable: Whether nulls are allowed (default True) is_public: Whether the table is publicly accessible.

Returns: Table creation confirmation.

Example: create_table( namespace="my_namespace", table_name="token_metrics", columns=[ {"name": "date", "type": "timestamp", "nullable": False}, {"name": "token", "type": "string"}, {"name": "volume", "type": "double"} ] )

Inputs: namespace (required), table_name (required), columns (required), is_public. Returns: object

delete_tableA

Permanently delete a table and all its data.

WARNING: This operation is irreversible!

Args: namespace: Namespace of the table. table_name: Name of the table to delete.

Returns: Deletion confirmation.

Inputs: namespace (required), table_name (required). Returns: object

execute_queryC

Execute a saved query by its ID.

Args: query_id: The unique identifier of the saved query. query_parameters: Optional parameters to pass to the query (key-value pairs). performance: Performance tier - "medium" (default) or "large".

Returns: Execution details including execution_id.

Inputs: query_id (required), query_parameters, performance. Returns: object

execute_sqlA

Execute a raw SQL query against Dune's data engine.

This is the primary tool for running custom SQL queries on blockchain data. Returns an execution_id that can be used to check status and retrieve results.

Args: sql: The SQL query to execute. Use DuneSQL (Trino) syntax. Read dune://guide/sql-syntax for syntax reference. performance: Performance tier - "medium" (default) or "large" for complex queries.

Returns: Execution details including execution_id and initial state.

Example SQL queries: - SELECT * FROM dex.trades WHERE block_time > now() - interval '1' day LIMIT 10 - SELECT blockchain, SUM(amount_usd) as volume FROM dex.trades GROUP BY 1

Inputs: sql (required), performance. Returns: object

get_execution_resultsB

Retrieve the results of a completed query execution.

Args: execution_id: The execution ID from a completed query. limit: Maximum number of rows to return (default 100, max per page). offset: Row offset for pagination (default 0).

Returns: Query results including rows, column metadata, and pagination info.

Inputs: execution_id (required), limit, offset. Returns: object

get_execution_results_csvA

Retrieve query execution results in CSV format.

Args: execution_id: The execution ID from a completed query. allow_partial_results: Allow truncated results if data exceeds 8GB.

Returns: Query results as CSV string.

Inputs: execution_id (required), allow_partial_results. Returns: object

get_execution_statusA

Check the status of a query execution.

Use this to poll for completion after executing a query.

Args: execution_id: The execution ID returned from execute_sql or execute_query.

Returns: Execution status including state (QUERY_STATE_EXECUTING, QUERY_STATE_COMPLETED, etc.), queue position, and timing information.

Inputs: execution_id (required). Returns: object

get_queryB

Retrieve details about a saved query.

Args: query_id: The unique identifier of the query.

Returns: Query details including SQL, parameters, name, tags, and state.

Inputs: query_id (required). Returns: object

get_query_resultsA

Get the latest results of a saved query without re-executing.

This retrieves cached results from the most recent execution. Does not trigger a new execution but consumes credits.

Args: query_id: The unique identifier of the query. limit: Maximum rows to return. offset: Row offset for pagination. allow_partial_results: Allow truncated results if data is too large.

Returns: Latest query results in JSON format.

Inputs: query_id (required), limit, offset, allow_partial_results. Returns: object

get_query_results_csvA

Get the latest results of a saved query in CSV format.

Args: query_id: The unique identifier of the query. allow_partial_results: Allow truncated results if data exceeds limit. columns: Comma-separated list of column names to return. sort_by: SQL ORDER BY expression (e.g., "volume DESC"). filters: SQL WHERE clause expression for filtering rows. limit: Maximum number of rows to return. offset: Row offset for pagination.

Returns: Query results as CSV string.

Inputs: query_id (required), allow_partial_results, columns, sort_by, +3 more. Returns: object

insert_table_rowsB

Insert rows into an existing table.

Args: namespace: Namespace of the table. table_name: Name of the table. rows: List of row objects where keys match column names.

Returns: Insert confirmation with row count.

Example: insert_table_rows( namespace="my_namespace", table_name="token_metrics", rows=[ {"date": "2024-01-01T00:00:00Z", "token": "ETH", "volume": 1000000}, {"date": "2024-01-02T00:00:00Z", "token": "ETH", "volume": 1200000} ] )

Inputs: namespace (required), table_name (required), rows (required). Returns: object

make_query_privateB

Make a query private, restricting access to the owner.

Args: query_id: The unique identifier of the query.

Returns: Privacy change confirmation.

Inputs: query_id (required). Returns: object

make_query_publicA

Make a private query public, allowing broader access.

Args: query_id: The unique identifier of the query.

Returns: Privacy change confirmation.

Inputs: query_id (required). Returns: object

update_queryA

Update an existing saved query.

Only fields provided will be updated.

Args: query_id: The unique identifier of the query to update. query_sql: New SQL query text. name: New name for the query. description: New description. parameters: New parameter definitions. tags: New tags list. is_private: Change privacy setting.

Returns: Update confirmation.

Inputs: query_id (required), query_sql, name, description, +3 more. Returns: object

upload_csvA

Upload CSV data to create or overwrite a table in Dune.

Maximum file size is 200MB. Uploading to an existing table overwrites all data.

Args: table_name: Name for the table (will be accessible as dune.your_namespace.table_name). data: CSV data as string, including headers. description: Optional description of the data. is_private: Whether the table should be private.

Returns: Upload confirmation.

Example: upload_csv( table_name="my_token_prices", data="date,token,price\n2024-01-01,ETH,2500\n2024-01-02,ETH,2600" )

Inputs: table_name (required), data (required), description, is_private. Returns: object

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A3.7/5.0

    Scored across 19 tools

    Disambiguation4/5

    Most tools have distinct purposes, but there is some potential for confusion between execute_query and execute_sql (both execute queries, with one using saved queries and the other raw SQL) and between get_query_results and get_execution_results (both retrieve results, with one for saved queries and the other for executions). The descriptions help clarify these distinctions, but an agent might initially misselect without careful reading.

    Naming Consistency5/5

    All tool names follow a consistent snake_case verb_noun pattern (e.g., archive_query, cancel_execution, create_table). The verbs are clear and descriptive (e.g., create, get, update, delete), and there are no deviations in style or convention throughout the set.

    Tool Count4/5

    With 19 tools, the count is slightly high but reasonable for a comprehensive data query and management platform like Dune. It covers query execution, result retrieval, table management, and query lifecycle operations, which justifies the number, though it might feel a bit heavy for simpler use cases.

    Completeness5/5

    The tool set provides complete coverage for Dune's domain, including CRUD operations for queries (create, get, update, archive, privacy toggles) and tables (create, clear, delete, insert rows, upload CSV), plus execution management (execute, cancel, status, results retrieval). There are no obvious gaps; agents can handle full workflows from query creation to result analysis.

    Maintenance

    ActivityInactive
    ResponsivenessOutdated data

    Related MCP Connectors

    Related MCP Servers