Skip to main content
Glama
CW-Codewalnut

Metabase MCP Server

create_metabase_database

Set up a new database connection in Metabase to integrate data sources for analysis, with options for sync schedules, caching, and query automation.

Instructions

Create a new database connection in Metabase.

Args: name (str): Name of the database. engine (str): Database engine. details (Dict[str, Any]): Connection details. auto_run_queries (bool, optional): Enable auto run. cache_ttl (int, optional): Cache time-to-live. is_full_sync (bool, optional): Whether to perform full sync. schedule (Dict[str, Any], optional): Sync schedule. timezone (str, optional): Timezone for the database. metadata_sync (bool, optional): Enable metadata sync.

Returns: Dict[str, Any]: Created database metadata.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
nameYes
engineYes
detailsYes
auto_run_queriesNo
cache_ttlNo
is_full_syncNo
scheduleNo
timezoneNo
metadata_syncNo

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Implementation Reference

  • The main handler function for the 'create_metabase_database' tool. It accepts database connection parameters (name, engine, details, and optional settings), constructs a payload, and makes a POST request to the Metabase API endpoint '/api/database' to create a new database connection.
    @mcp.tool()
    async def create_metabase_database(
        name: str,
        engine: str,
        details: Dict[str, Any],
        auto_run_queries: Optional[bool] = None,
        cache_ttl: Optional[int] = None,
        is_full_sync: Optional[bool] = None,
        schedule: Optional[Dict[str, Any]] = None,
        timezone: Optional[str] = None,
        metadata_sync: Optional[bool] = None
    ) -> Dict[str, Any]:
        """
        Create a new database connection in Metabase.
    
        Args:
            name (str): Name of the database.
            engine (str): Database engine.
            details (Dict[str, Any]): Connection details.
            auto_run_queries (bool, optional): Enable auto run.
            cache_ttl (int, optional): Cache time-to-live.
            is_full_sync (bool, optional): Whether to perform full sync.
            schedule (Dict[str, Any], optional): Sync schedule.
            timezone (str, optional): Timezone for the database.
            metadata_sync (bool, optional): Enable metadata sync.
    
        Returns:
            Dict[str, Any]: Created database metadata.
        """
        payload = {
            "name": name,
            "engine": engine,
            "details": details
        }
        if auto_run_queries is not None:
            payload["auto_run_queries"] = auto_run_queries
        if cache_ttl is not None:
            payload["cache_ttl"] = cache_ttl
        if is_full_sync is not None:
            payload["is_full_sync"] = is_full_sync
        if schedule is not None:
            payload["schedule"] = schedule
        if timezone is not None:
            payload["timezone"] = timezone
        if metadata_sync is not None:
            payload["metadata_sync"] = metadata_sync
    
        logger.info(f"Creating database '{name}'")
        return await make_metabase_request(RequestMethod.POST, "/api/database", json=payload)
  • Initialization of the FastMCP server instance named 'metabase' with an application lifespan manager. This creates the MCP server that registers tools via the @mcp.tool() decorator.
    mcp = FastMCP("metabase", lifespan=app_lifespan)
  • Helper function that makes HTTP requests to the Metabase API. It handles session management, request construction, error handling, and response parsing. This utility is used by create_metabase_database to execute the actual API call.
    async def make_metabase_request(
        method: RequestMethod,
        endpoint: str,
        data: Optional[Dict[str, Any] | bytes] = None,
        params: Optional[Dict[str, Any]] = None,
        json: Any = None,
        headers: Optional[Dict[str, str]] = None,
    ) -> Dict[str, Any]:
        """
        Make a request to the Metabase API.
        
        Args:
            method: HTTP method to use (GET, POST, PUT, DELETE)
            endpoint: API endpoint path
            data: Request data (for form data)
            params: URL parameters
            json: JSON request body
            headers: Additional headers
            
        Returns:
            Dict[str, Any]: Response data
            
        Raises:
            MetabaseConnectionError: When the Metabase server is unreachable
            MetabaseResponseError: When Metabase returns a non-2xx status code
            RuntimeError: For other errors
        """
        
        if not METABASE_URL or not METABASE_API_KEY:
            raise RuntimeError("METABASE_URL or METABASE_API_KEY environment variable is not set. Metabase API requests will fail.")
    
        if session is None:
            raise RuntimeError("HTTP session is not initialized. Ensure app_lifespan was called.")
    
        try:
            request_headers = headers or {}
            
            logger.debug(f"Making {method.name} request to {METABASE_URL}{endpoint}")
            
            # Log request payload for debugging (omit sensitive info)
            if json and logger.level <= logging.DEBUG:
                sanitized_json = {**json}
                if 'password' in sanitized_json:
                    sanitized_json['password'] = '********'
                logger.debug(f"Request payload: {sanitized_json}")
                
            response = await session.request(
                method=method.name,
                url=endpoint,
                timeout=aiohttp.ClientTimeout(total=30),
                headers=request_headers,
                data=data,
                params=params,
                json=json,
            )
    
            try:
                # Handle 500 errors with more detailed info
                if response.status >= 500:
                    error_text = await response.text()
                    logger.error(f"Server error {response.status}: {error_text[:200]}")
                    raise MetabaseResponseError(response.status, f"Server Error: {error_text[:200]}", endpoint)
                
                response.raise_for_status()
                response_data = await response.json()
                
                # Ensure the response is a dictionary for FastMCP compatibility
                return ensure_dict_response(response_data)
                
            except aiohttp.ContentTypeError:
                # Handle empty responses or non-JSON responses
                content = await response.text()
                if not content:
                    return {"data": {}}
                logger.warning(f"Received non-JSON response: {content}")
                return {"data": content}
    
        except aiohttp.ClientConnectionError as e:
            logger.error(f"Connection error: {str(e)}")
            raise MetabaseConnectionError("Metabase is unreachable. Is the Metabase server running?") from e
        except aiohttp.ClientResponseError as e:
            logger.error(f"Response error: {e.status}, {e.message}, {e.request_info.url}")
            raise MetabaseResponseError(e.status, e.message, str(e.request_info.url)) from e
        except Exception as e:
            logger.error(f"Request error: {str(e)}")
            raise RuntimeError(f"Request error: {str(e)}") from e

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/CW-Codewalnut/metabase-mcp-server'

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