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
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries full burden for behavioral disclosure. While 'Create' implies a write/mutation operation, the description doesn't mention required permissions, whether this operation is idempotent, potential side effects, rate limits, or error conditions. The return format is mentioned but without behavioral context about what happens during creation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with clear sections (Args, Returns) and uses bullet-like formatting. The opening sentence is front-loaded with the core purpose. Some parameter descriptions could be more detailed (e.g., 'Connection details' is vague), but overall the structure is efficient with minimal wasted space.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complexity (9 parameters, mutation operation, no annotations) but with output schema present, the description is moderately complete. It covers parameters well and mentions the return type, but lacks behavioral context about the creation process, permissions, or error handling. For a mutation tool with this many parameters, more operational guidance would be beneficial.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage and 9 parameters (3 required), the description provides excellent parameter semantics. Each parameter is listed with name, type, and brief explanation of purpose (e.g., 'Connection details' for details, 'Enable auto run' for auto_run_queries). This fully compensates for the lack of schema descriptions and helps the agent understand what each parameter controls.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the specific action ('Create a new database connection') and resource ('in Metabase'), distinguishing it from sibling tools like create_metabase_card or create_metabase_dashboard which create different Metabase resources. The verb 'create' paired with 'database connection' provides unambiguous purpose.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives. There are sibling tools like update_metabase_database and delete_metabase_database, but no indication of when to create versus update, or what prerequisites might be needed. No exclusions or contextual recommendations are provided.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

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