How to integrate Metabase MCP with Pydantic AI

Framework Integration Gradient
Metabase Logo
Pydantic AI Logo
divider

Introduction

This guide walks you through connecting Metabase to Pydantic AI using the Composio tool router. By the end, you'll have a working Metabase agent that can get all charts from marketing dashboard, run sql query for revenue last quarter, share dashboard link with analytics team through natural language commands.

This guide will help you understand how to give your Pydantic AI agent real control over a Metabase account through Composio's Metabase MCP server.

Before we dive in, let's take a quick look at the key ideas and tools involved.

TL;DR

Here's what you'll learn:
  • How to set up your Composio API key and User ID
  • How to create a Composio Tool Router session for Metabase
  • How to attach an MCP Server to a Pydantic AI agent
  • How to stream responses and maintain chat history
  • How to build a simple REPL-style chat interface to test your Metabase workflows

What is Pydantic AI?

Pydantic AI is a Python framework for building AI agents with strong typing and validation. It leverages Pydantic's data validation capabilities to create robust, type-safe AI applications.

Key features include:

  • Type Safety: Built on Pydantic for automatic data validation
  • MCP Support: Native support for Model Context Protocol servers
  • Streaming: Built-in support for streaming responses
  • Async First: Designed for async/await patterns

What is the Metabase MCP server, and what's possible with it?

The Metabase MCP server is an implementation of the Model Context Protocol that connects your AI agent and assistants like Claude, Cursor, etc directly to your Metabase account. It provides structured and secure access so your agent can perform Metabase operations on your behalf.

Supported Tools & Triggers

Tools
Create BookmarkTool to create a new bookmark for a Metabase item (card, dashboard, collection, or dataset).
Create BookmarkTool to create a new bookmark for a Metabase item (card, dashboard, collection, or dataset).
Run Card Pivot QueryTool to run a pivot table query on a Metabase card (question).
Run Card QueryTool to run the query associated with a Card and return its results.
Copy DashboardTool to create a copy of an existing Metabase dashboard.
Run Dashboard Pivot DashCard QueryTool to run a pivot table query for a specific DashCard.
Save Dashboard to CollectionTool to save a denormalized dashboard description into a collection.
Discard Database Field ValuesTool to discard all saved field values for a specific database.
Dismiss Database Sync SpinnerTool to manually set the initial sync status of a Database and corresponding tables to complete.
Trigger Database Field Values RescanTool to trigger a manual scan of field values for a Database.
Trigger Database Schema SyncTool to trigger a manual update of the schema metadata for a Database.
Search Dataset Parameter ValuesTool to search for parameter values in datasets when editing cards or dashboards.
Create Field DimensionTool to set the dimension for a field at the specified ID in Metabase.
Discard Field ValuesTool to discard the FieldValues belonging to a Metabase field.
Update Field ValuesTool to update field values and human-readable values for a Field whose semantic type is category/city/state/country or whose base type is type/Boolean.
Unpersist CardTool to unpersist a Metabase card/model.
Disable Database Model PersistenceTool to disable model persistence for a Metabase database.
Discard Table Field ValuesTool to discard the FieldValues belonging to the Fields in a Metabase Table.
Rescan Table Field ValuesTool to manually trigger an update for FieldValues for Fields belonging to a specific Table.
Sync Table SchemaTool to trigger a manual update of the schema metadata for a specific Table.
Delete ActionTool to delete an Action from Metabase.
Delete ActionTool to delete a Metabase action by its ID.
Delete BookmarkTool to delete a bookmark from a Metabase item (card, dashboard, or collection).
Delete API CacheTool to delete/clear cached data in Metabase for specific entities.
Delete CardTool to delete a Metabase card (question) by its ID.
Delete DashboardTool to delete a Metabase dashboard by its ID.
Delete Model IndexTool to delete a Metabase model index by its ID.
Delete Timeline EventTool to delete a timeline event by ID.
Delete TimelineTool to delete a timeline by ID.
Delete User Key-ValueTool to delete a user key-value pair from Metabase.
Delete BookmarkTool to delete a bookmark by model and ID.
Delete CardTool to hard delete a Metabase card.
Delete DashboardTool to hard delete a Metabase dashboard by its ID.
Delete User SubscriptionsTool to delete all Alert and DashboardSubscription subscriptions for a User.
Delete Field DimensionTool to remove the dimension associated with a field at the specified ID.
Delete Glossary EntryTool to delete a glossary entry from Metabase.
Delete Glossary ItemTool to delete a glossary item by ID.
Delete Model IndexTool to delete a ModelIndex by ID from Metabase.
Delete TimelineTool to delete a Metabase timeline and cascade delete all its associated events.
Delete Timeline EventTool to delete a Metabase timeline event.
Delete User Key-Value PairTool to delete a user key-value pair by namespace and key.
Delete User SubscriptionsTool to delete all Alert and DashboardSubscription subscriptions for a User.
Get ActionTool to retrieve a Metabase action by ID.
Get Action Execute ParametersTool to fetch values for filling in action execution parameters.
Get all Metabase actionsTool to retrieve all actions available in the Metabase instance.
Get Popular ItemsTool to get the list of 5 popular items on the Metabase instance.
Get Recent Activity ViewsTool to retrieve recently viewed items in Metabase.
Get All AlertsTool to retrieve all alerts in Metabase.
Get Automagic Dashboard CandidatesTool to retrieve automagic dashboard candidates for a specific database.
Get Automagic Dashboard Cell AnalysisTool to return an automagic dashboard analyzing a specific cell in an entity's data.
Get Automagic Dashboard Cell Rule AnalysisTool to fetch an automagic dashboard analyzing a specific cell using a template rule.
Get Automagic Dashboard Query MetadataTool to retrieve all metadata for an automagic dashboard for the specified entity type and ID.
Get Automagic Dashboard with Rule and TemplateTool to retrieve an automagic dashboard for a specified entity using a specific rule prefix and dashboard template.
Get User BookmarksTool to retrieve all bookmarks for the authenticated user.
Get API CardTool to list all cards (questions) available to the authenticated user in Metabase.
Search Card Parameter ValuesTool to search for values of a specific parameter in a Metabase card.
Get Card by IDTool to retrieve a specific card (question) by its ID.
Get Card DashboardsTool to get a list of dashboards containing a specific card.
Get Card SeriesTool to retrieve series data for a specific card.
Get all collectionsTool to retrieve all collections that the current user has read permissions for.
Get Collection by IDTool to retrieve detailed information about a Metabase collection by its ID.
Get Collection ItemsTool to retrieve items from a specific Metabase collection.
Get Root CollectionTool to fetch the Root Collection and its top-level objects.
Get Collection TreeTool to retrieve the collection tree structure from Metabase.
Get Dashboard Parameter RemappingTool to get parameter remapping for a dashboard parameter value.
Get Dashboard Parameter ValuesTool to fetch available values for a specific dashboard parameter.
Get Dashboard Related EntitiesTool to retrieve related entities for a Metabase dashboard.
Get All DatabasesTool to retrieve a list of all Database instances configured in Metabase.
Get Database DetailsTool to retrieve complete details for a specific database in Metabase.
Get Database Autocomplete SuggestionsTool to retrieve autocomplete suggestions for table and field names in a database.
Get Database Card Autocomplete SuggestionsTool to get card autocomplete suggestions for a specific database in Metabase.
Get Database FieldsTool to retrieve all fields from a specific database in Metabase.
Check Database HealthTool to check the health status of a specific database connection in Metabase.
Get Database MetadataTool to retrieve complete metadata for a specific database including all tables and fields.
Get Virtual Database DatasetsTool to retrieve all datasets from a Metabase virtual database.
Get User Audit InfoTool to get audit info for the current authenticated user.
Get Billing API VersionTool to retrieve the billing API version information for the Metabase Enterprise Edition instance.
Get Resource DependentsTool to get dependents of a resource in Metabase's dependency graph.
Get Embedding Hub ChecklistTool to retrieve the embedding hub checklist status for Metabase Enterprise Edition.
Get Current Remote Sync TaskTool to retrieve the current remote sync task status in Metabase.
Get Stale Data By IDTool to retrieve stale data information by ID from Metabase Enterprise Edition.
Get Uploaded TablesTool to retrieve all uploaded tables in Metabase Enterprise Edition.
Get Field Related EntitiesTool to retrieve related entities for a Metabase field.
Search Field ValuesTool to search for field values in Metabase that start with a given string.
Get Field ValuesTool to retrieve distinct values for a Metabase field.
Get API GlossaryTool to retrieve all glossary items from Metabase.
Get Current User Login HistoryTool to retrieve login history for the currently authenticated user.
Get Model Index ValuesTool to retrieve indexed field values for a specific Metabase model.
Get Model Index DetailsTool to retrieve details of a specific model index by its ID.
Get all native query snippetsTool to retrieve all native query snippets available in the Metabase instance.
Get Native Query Snippet by IDTool to retrieve a specific native query snippet by its ID.
Get NotificationsTool to retrieve notifications from Metabase with optional filtering.
Get Public Card by UUIDTool to fetch a publicly-accessible card by its public UUID and return card information including query definition, visualization settings, and parameters.
Get Public oEmbed MetadataTool to get oEmbed metadata for public Metabase resources.
Get Public Pivot Card QueryTool to fetch a publicly-accessible pivot card and return query results including data rows, column metadata, and query status.
Get All PulsesTool to retrieve all pulses (scheduled reports/subscriptions) in Metabase.
Get Pulse Form Input ConfigurationTool to retrieve configuration information for creating or updating Pulses (scheduled email reports).
Get Pulse by IDTool to retrieve a specific pulse (subscription) by its ID.
Get Pulse Preview CardTool to retrieve the HTML preview of a Metabase card formatted for pulse emails.
Get Pulse Preview Card InfoTool to retrieve preview information for a Metabase card formatted for pulse emails.
Get Pulse Preview DashboardTool to retrieve the pulse preview for a specific dashboard by its ID.
Get Revision by ID and EntityTool to retrieve a specific revision by ID and entity type.
Get Entity Revision HistoryTool to retrieve the revision history for a Metabase entity (dashboard, card, metric, or segment).
Search Metabase objectsTool to search Cards, Dashboards, Collections, Tables, Databases, and Pulses for a substring.
Get Search WeightsTool to retrieve the current search weight configuration for the Metabase instance.
Get All SegmentsTool to retrieve all segments from Metabase.
Validate Password Reset TokenTool to validate a password reset token in Metabase.
Get Session PropertiesTool to retrieve all global session properties and their values that are public.
Get Card Table Foreign KeysTool to retrieve foreign key relationships for a card-based virtual table.
Get Card Virtual Table Query MetadataTool to retrieve metadata for a virtual table created from a card (saved question).
Get Table Foreign KeysTool to retrieve foreign key relationships for a Metabase table.
Get Table Query MetadataTool to retrieve metadata about a table useful for running queries.
Get Table Data by IDTool to retrieve data from a specific Metabase table by ID.
Get All TimelinesTool to retrieve all timelines in Metabase.
Get Collection TimelinesTool to retrieve timelines associated with a specific Metabase collection.
Get Root Collection TimelinesTool to retrieve all timelines associated with the root collection.
Get Timeline EventTool to retrieve a timeline event by ID.
Get Timeline by IDTool to fetch a timeline by its ID from Metabase.
Get Current UserTool to retrieve information about the currently authenticated user.
Get User by IDTool to retrieve a specific user by their ID.
Get User Key-Value by NamespaceTool to retrieve all user key-value pairs for a specified namespace.
Get User RecipientsTool to retrieve users for recipient selection.
Generate Random Security TokenTool to generate a cryptographically secure random token for Metabase.
Get Automagic DashboardTool to generate an automagic dashboard for a given entity.
Get Automagic DashboardTool to retrieve an automagic dashboard for a specified entity with its ID.
Get Automagic Dashboard Cell AnalysisTool to return an automagic dashboard analyzing a specific cell in an entity's data.
Get Automagic Dashboard Cell RuleTool to fetch an automagic dashboard analyzing a specific cell in a table or query.
Get Automagic Dashboards CompareTool to return an automagic comparison dashboard for entity with id compared with comparison-entity with comparison-entity-id-or-query.
Get Automagic Dashboard Query MetadataTool to retrieve all metadata for an automagic dashboard for a specific entity and ID.
Get automagic dashboard by ruleTool to return an automagic dashboard for a specific entity using a dashboard template with rule prefix.
Get Card DashboardsTool to get a list of dashboards that a specific card appears in.
Search Card Parameter ValuesTool to fetch possible values for a card parameter that match a search query.
Get Card Query MetadataTool to get comprehensive query metadata for a Metabase card (saved question).
Get Card SeriesTool to fetch a list of cards compatible as series with a specified card.
Get Collection by IDTool to fetch a specific Metabase collection with standard details added.
Get Collection ItemsTool to fetch items from a specific Metabase collection.
Get Automagic Comparison DashboardTool to retrieve an automagic comparison dashboard comparing a cell in one entity with another entity.
Get Dashboard by IDTool to retrieve details of a specific Metabase dashboard by ID.
Get Dashboard by IDTool to retrieve a dashboard by its ID from Metabase.
Search dashboard parameter valuesTool to search for dashboard parameter values in Metabase.
Get Dashboard Params RemappingTool to fetch the remapped value for a given dashboard parameter in Metabase.
Search Dashboard Parameter ValuesTool to fetch possible values of a dashboard parameter that contain the search query.
Get Dashboard Query MetadataTool to get all of the required query metadata for the cards on a dashboard.
Get Dashboard Related EntitiesTool to retrieve related entities for a Metabase dashboard.
Get Database Autocomplete SuggestionsTool to get autocomplete suggestions for table and field names in a Metabase database.
Get Database By IDTool to retrieve a single database by ID from Metabase.
Get Database Card Autocomplete SuggestionsTool to return a list of Card autocomplete suggestions for a given query in a given Database.
Get Database DatasetsTool to retrieve tables (models and metrics) from a virtual database schema in Metabase.
Get Database FieldsTool to retrieve all field metadata from a Metabase database.
Get Database HealthcheckTool to check if a Metabase database can currently connect.
Get Database MetadataTool to retrieve complete metadata for a specific database including all tables and fields.
Get Database SchemasTool to retrieve all schemas with tables for a specific database in Metabase.
Get Database Settings AvailableTool to get all database-local settings and their availability for a given database.
Get Database Syncable SchemasTool to retrieve all syncable schemas for a specific database in Metabase.
Get Stale Entities from CollectionTool to retrieve stale entities (cards and dashboards) from a Metabase collection that haven't been used recently.
Get Field RemappingTool to fetch remapped field values for a specific field in Metabase.
Get Field SummaryTool to get summary statistics for a Metabase field by its ID.
Get ModelIndex by IDTool to retrieve a ModelIndex by ID.
Get Most Recently Viewed DashboardTool to retrieve the most recently viewed dashboard for the authenticated user.
Get Native Query Snippet by IDTool to retrieve a specific native query snippet by its ID.
Get Pulse Preview CardTool to get HTML rendering of a Metabase card by ID.
Get Pulse Preview Card InfoTool to get JSON object containing HTML rendering of a card and additional information.
Get Dashboard HTML PreviewTool to retrieve an HTML preview rendering of a dashboard.
Get Revision History by IDTool to retrieve the complete revision history for a Metabase entity by its ID.
Get Table By IDTool to retrieve basic table information by ID from Metabase.
Get Table DataTool to retrieve data from a specific table in Metabase.
Get Table Foreign KeysTool to get all foreign keys whose destination is a field that belongs to a specific table.
Get Table Query MetadataTool to get metadata about a Table useful for running queries.
Get Timeline by IDTool to fetch a timeline by its ID.
Get Collection TimelinesTool to fetch timelines associated with a specific Metabase collection.
Get Timeline EventTool to fetch a timeline event by ID.
Get User by IDTool to fetch a Metabase user by their ID.
Get User Key-Value SettingTool to retrieve a user-specific key-value pair from Metabase storage.
Get All User Key-Values in NamespaceTool to retrieve all key-value pairs in a given namespace for the current user.
Get User Key-Value SettingTool to retrieve a user-specific key-value pair from Metabase storage.
Record Recent ActivityTool to record recent activity for a Metabase item.
Create BookmarkTool to create a bookmark for a Metabase item (card, dashboard, or collection).
Create CardTool to create a new Metabase card (question or model).
Execute Card QueryTool to execute a query for a saved Metabase card/question and retrieve results.
Bulk Move Cards to CollectionTool to bulk move multiple Metabase cards into a target collection or remove them from collections.
Copy CardTool to create a copy of an existing Metabase card (question) by its ID.
Execute Pivot Card QueryTool to execute a pivot query on a Metabase card and return the results.
Get Card Dashboard AssociationsTool to retrieve dashboard associations for given card IDs.
Bulk Move CardsTool to bulk move cards to a collection or remove them from collections.
Create CollectionTool to create a new Metabase collection for organizing content.
Create DashboardTool to create a new Metabase dashboard.
Copy DashboardTool to copy an existing Metabase dashboard.
Execute Dashboard Pivot QueryTool to execute a pivot table query for a specific card on a dashboard.
Create Dashboard in CollectionTool to create a new dashboard in a specific Metabase collection.
Discard Database Field ValuesTool to discard all saved field values for a specific database.
Dismiss Database SpinnerTool to dismiss the spinner for a specific database.
Rescan Database Field ValuesTool to trigger a manual rescan of field values for a specific database.
Sync Database SchemaTool to trigger a schema synchronization for a specific database.
Execute Dataset QueryTool to execute a query against a Metabase database and retrieve results.
Convert Query to Native SQLTool to convert a Metabase query to native SQL format.
Remap Dataset Parameter ValueTool to remap dataset parameter values in Metabase.
Get Dataset Parameter ValuesTool to fetch parameter values for dataset fields in Metabase.
Execute Pivot Table QueryTool to execute a pivot table query and retrieve results.
Get Dataset Query MetadataTool to retrieve query metadata for a dataset query including databases, tables, fields, and snippets.
Check Snippet DependenciesTool to check dependencies for a native query snippet in Metabase Enterprise Edition.
Create Dashboard SubscriptionTool to create a dashboard subscription using Metabot tools.
Filter RecordsTool to filter records from a Metabase data source using metabot tools.
Generate InsightsTool to generate insights for a table using Metabot tools.
Get Current UserTool to retrieve information about the current authenticated user in a Metabase metabot conversation.
Get Dashboard DetailsTool to retrieve dashboard details for a Metabase metabot conversation.
Get Document Details via MetabotTool to retrieve document details using Metabase metabot tools.
Get Query DetailsTool to get query details using Metabot tools API.
Get Snippet DetailsTool to retrieve SQL snippet details via Metabase metabot tools.
Get Metabot SnippetsTool to retrieve SQL snippets for a Metabase metabot conversation.
Get Table DetailsTool to retrieve comprehensive table details via Metabase metabot tools.
Query Datasource via MetabotTool to query a Metabase datasource using Metabot tools.
Metabot SearchTool to search Metabase entities using the metabot search API.
Search Metabase Items (Metabot V2)Tool to search Metabase items using the Metabot search v2 endpoint.
Cancel Current Remote Sync TaskTool to cancel the current active Remote Sync task in Metabase Enterprise Edition.
Translate Entity IDsTool to translate Metabase entity IDs (21-character strings) to their numeric IDs.
Discard Field ValuesTool to discard cached FieldValues for a specific field.
Rescan Field ValuesTool to manually trigger an update for the FieldValues for a specific field.
Create Glossary EntryTool to create a new glossary entry in Metabase.
Create Model IndexTool to create a new model index in Metabase.
Create native query snippetTool to create a new native query snippet in Metabase.
Create NotificationTool to create a new notification in Metabase.
Send NotificationTool to trigger sending an unsaved notification in Metabase.
Unpersist CardTool to unpersist a Metabase card by its ID.
Unpersist DatabaseTool to disable model persistence for a specific database.
Submit Product FeedbackTool to submit product feedback to Metabase.
Create PulseTool to create a new pulse (scheduled report/subscription) in Metabase.
Revert Entity to Previous RevisionTool to revert a Metabase entity (card, dashboard, document, or segment) to a previous revision.
Send Password Reset EmailTool to send a password reset email when user has forgotten their password.
Check Password ComplexityTool to check if a password meets Metabase's configured password complexity rules.
Submit Bug Report to SlackTool to submit a bug report to Slack via Metabase's bug reporting endpoint.
Discard Table Field ValuesTool to discard cached FieldValues for all Fields belonging to a specific Table.
Rescan Table Field ValuesTool to trigger a manual rescan of field values for a specific table.
Sync Table SchemaTool to trigger a manual update of the schema metadata for a specific Table.
Create TimelineTool to create a new timeline in Metabase.
Execute Dashboard Card QueryTool to execute a query for a specific card within a dashcard on a dashboard.
Update Action by IDTool to update an existing Metabase action by its ID.
Update Bookmark OrderingTool to update the order of bookmarks for the authenticated user.
Update Card by IDTool to update a specific card (question) by its ID.
Update Collection by IDTool to update an existing Metabase collection by its ID.
Update DashboardTool to update a Metabase dashboard by its ID.
Update Dashboard CardsTool to update dashboard cards and tabs.
Update Database ConfigurationTool to update a database configuration in Metabase.
Update Field MetadataTool to update a Metabase field by its ID.
Update Glossary Entry by IDTool to update an existing glossary entry in Metabase by its ID.
Update Native Query Snippet by IDTool to update an existing native query snippet by its ID.
Update Pulse by IDTool to update an existing pulse (scheduled report/subscription) by ID.
Update Search WeightsTool to update search weights configuration in Metabase.
Update Table MetadataTool to update a Metabase table by its ID.
Update Table MetadataTool to update a Metabase table metadata by its ID.
Update Table Field Display OrderTool to update the display order of fields in a Metabase table.
Update Timeline Event by IDTool to update an existing timeline event by its ID.
Update Timeline by IDTool to update an existing timeline by its ID.
Update User by IDTool to update an existing Metabase user by their ID.
Update ActionTool to update an existing Action in Metabase.
Update CollectionTool to update an existing Metabase collection.
Update DashboardTool to update a Metabase dashboard by ID.
Update Dashboard Cards (Deprecated)Tool to bulk update dashboard cards and tabs.
Update DatabaseTool to update a Database in Metabase.
Update Field MetadataTool to update metadata for a Metabase field by its ID.
Update Glossary EntryTool to update an existing glossary entry in Metabase.
Update Native Query SnippetTool to update an existing native query snippet by ID.
Update PulseTool to update an existing pulse (scheduled report/subscription) by ID.
Update Table by IDTool to update a Table in Metabase by its ID.
Update Table Fields OrderTool to reorder fields in a Metabase table.
Update TimelineTool to update a Metabase timeline by its ID.
Update Timeline EventTool to update an existing Metabase timeline event by its ID.

What is the Composio tool router, and how does it fit here?

What is Tool Router?

Composio's Tool Router helps agents find the right tools for a task at runtime. You can plug in multiple toolkits (like Gmail, HubSpot, and GitHub), and the agent will identify the relevant app and action to complete multi-step workflows. This can reduce token usage and improve the reliability of tool calls. Read more here: Getting started with Tool Router

The tool router generates a secure MCP URL that your agents can access to perform actions.

How the Tool Router works

The Tool Router follows a three-phase workflow:

  1. Discovery: Searches for tools matching your task and returns relevant toolkits with their details.
  2. Authentication: Checks for active connections. If missing, creates an auth config and returns a connection URL via Auth Link.
  3. Execution: Executes the action using the authenticated connection.

Step-by-step Guide

Prerequisites

Before starting, make sure you have:
  • Python 3.9 or higher
  • A Composio account with an active API key
  • Basic familiarity with Python and async programming

Getting API Keys for OpenAI and Composio

OpenAI API Key
  • Go to the OpenAI dashboard and create an API key. You'll need credits to use the models, or you can connect to another model provider.
  • Keep the API key safe.
Composio API Key
  • Log in to the Composio dashboard.
  • Navigate to your API settings and generate a new API key.
  • Store this key securely as you'll need it for authentication.

Install dependencies

bash
pip install composio pydantic-ai python-dotenv

Install the required libraries.

What's happening:

  • composio connects your agent to external SaaS tools like Metabase
  • pydantic-ai lets you create structured AI agents with tool support
  • python-dotenv loads your environment variables securely from a .env file

Set up environment variables

bash
COMPOSIO_API_KEY=your_composio_api_key_here
USER_ID=your_user_id_here
OPENAI_API_KEY=your_openai_api_key

Create a .env file in your project root.

What's happening:

  • COMPOSIO_API_KEY authenticates your agent to Composio's API
  • USER_ID associates your session with your account for secure tool access
  • OPENAI_API_KEY to access OpenAI LLMs

Import dependencies

python
import asyncio
import os
from dotenv import load_dotenv
from composio import Composio
from pydantic_ai import Agent
from pydantic_ai.mcp import MCPServerStreamableHTTP

load_dotenv()
What's happening:
  • We load environment variables and import required modules
  • Composio manages connections to Metabase
  • MCPServerStreamableHTTP connects to the Metabase MCP server endpoint
  • Agent from Pydantic AI lets you define and run the AI assistant

Create a Tool Router Session

python
async def main():
    api_key = os.getenv("COMPOSIO_API_KEY")
    user_id = os.getenv("USER_ID")
    if not api_key or not user_id:
        raise RuntimeError("Set COMPOSIO_API_KEY and USER_ID in your environment")

    # Create a Composio Tool Router session for Metabase
    composio = Composio(api_key=api_key)
    session = composio.create(
        user_id=user_id,
        toolkits=["metabase"],
    )
    url = session.mcp.url
    if not url:
        raise ValueError("Composio session did not return an MCP URL")
What's happening:
  • We're creating a Tool Router session that gives your agent access to Metabase tools
  • The create method takes the user ID and specifies which toolkits should be available
  • The returned session.mcp.url is the MCP server URL that your agent will use

Initialize the Pydantic AI Agent

python
# Attach the MCP server to a Pydantic AI Agent
metabase_mcp = MCPServerStreamableHTTP(url, headers={"x-api-key": COMPOSIO_API_KEY})
agent = Agent(
    "openai:gpt-5",
    toolsets=[metabase_mcp],
    instructions=(
        "You are a Metabase assistant. Use Metabase tools to help users "
        "with their requests. Ask clarifying questions when needed."
    ),
)
What's happening:
  • The MCP client connects to the Metabase endpoint
  • The agent uses GPT-5 to interpret user commands and perform Metabase operations
  • The instructions field defines the agent's role and behavior

Build the chat interface

python
# Simple REPL with message history
history = []
print("Chat started! Type 'exit' or 'quit' to end.\n")
print("Try asking the agent to help you with Metabase.\n")

while True:
    user_input = input("You: ").strip()
    if user_input.lower() in {"exit", "quit", "bye"}:
        print("\nGoodbye!")
        break
    if not user_input:
        continue

    print("\nAgent is thinking...\n", flush=True)

    async with agent.run_stream(user_input, message_history=history) as stream_result:
        collected_text = ""
        async for chunk in stream_result.stream_output():
            text_piece = None
            if isinstance(chunk, str):
                text_piece = chunk
            elif hasattr(chunk, "delta") and isinstance(chunk.delta, str):
                text_piece = chunk.delta
            elif hasattr(chunk, "text"):
                text_piece = chunk.text
            if text_piece:
                collected_text += text_piece
        result = stream_result

    print(f"Agent: {collected_text}\n")
    history = result.all_messages()
What's happening:
  • The agent reads input from the terminal and streams its response
  • Metabase API calls happen automatically under the hood
  • The model keeps conversation history to maintain context across turns

Run the application

python
if __name__ == "__main__":
    asyncio.run(main())
What's happening:
  • The asyncio loop launches the agent and keeps it running until you exit

Complete Code

Here's the complete code to get you started with Metabase and Pydantic AI:

python
import asyncio
import os
from dotenv import load_dotenv
from composio import Composio
from pydantic_ai import Agent
from pydantic_ai.mcp import MCPServerStreamableHTTP

load_dotenv()

async def main():
    api_key = os.getenv("COMPOSIO_API_KEY")
    user_id = os.getenv("USER_ID")
    if not api_key or not user_id:
        raise RuntimeError("Set COMPOSIO_API_KEY and USER_ID in your environment")

    # Create a Composio Tool Router session for Metabase
    composio = Composio(api_key=api_key)
    session = composio.create(
        user_id=user_id,
        toolkits=["metabase"],
    )
    url = session.mcp.url
    if not url:
        raise ValueError("Composio session did not return an MCP URL")

    # Attach the MCP server to a Pydantic AI Agent
    metabase_mcp = MCPServerStreamableHTTP(url, headers={"x-api-key": COMPOSIO_API_KEY})
    agent = Agent(
        "openai:gpt-5",
        toolsets=[metabase_mcp],
        instructions=(
            "You are a Metabase assistant. Use Metabase tools to help users "
            "with their requests. Ask clarifying questions when needed."
        ),
    )

    # Simple REPL with message history
    history = []
    print("Chat started! Type 'exit' or 'quit' to end.\n")
    print("Try asking the agent to help you with Metabase.\n")

    while True:
        user_input = input("You: ").strip()
        if user_input.lower() in {"exit", "quit", "bye"}:
            print("\nGoodbye!")
            break
        if not user_input:
            continue

        print("\nAgent is thinking...\n", flush=True)

        async with agent.run_stream(user_input, message_history=history) as stream_result:
            collected_text = ""
            async for chunk in stream_result.stream_output():
                text_piece = None
                if isinstance(chunk, str):
                    text_piece = chunk
                elif hasattr(chunk, "delta") and isinstance(chunk.delta, str):
                    text_piece = chunk.delta
                elif hasattr(chunk, "text"):
                    text_piece = chunk.text
                if text_piece:
                    collected_text += text_piece
            result = stream_result

        print(f"Agent: {collected_text}\n")
        history = result.all_messages()

if __name__ == "__main__":
    asyncio.run(main())

Conclusion

You've built a Pydantic AI agent that can interact with Metabase through Composio's Tool Router. With this setup, your agent can perform real Metabase actions through natural language. You can extend this further by:
  • Adding other toolkits like Gmail, HubSpot, or Salesforce
  • Building a web-based chat interface around this agent
  • Using multiple MCP endpoints to enable cross-app workflows (for example, Gmail + Metabase for workflow automation)
This architecture makes your AI agent "agent-native", able to securely use APIs in a unified, composable way without custom integrations.

How to build Metabase MCP Agent with another framework

FAQ

What are the differences in Tool Router MCP and Metabase MCP?

With a standalone Metabase MCP server, the agents and LLMs can only access a fixed set of Metabase tools tied to that server. However, with the Composio Tool Router, agents can dynamically load tools from Metabase and many other apps based on the task at hand, all through a single MCP endpoint.

Can I use Tool Router MCP with Pydantic AI?

Yes, you can. Pydantic AI fully supports MCP integration. You get structured tool calling, message history handling, and model orchestration while Tool Router takes care of discovering and serving the right Metabase tools.

Can I manage the permissions and scopes for Metabase while using Tool Router?

Yes, absolutely. You can configure which Metabase scopes and actions are allowed when connecting your account to Composio. You can also bring your own OAuth credentials or API configuration so you keep full control over what the agent can do.

How safe is my data with Composio Tool Router?

All sensitive data such as tokens, keys, and configuration is fully encrypted at rest and in transit. Composio is SOC 2 Type 2 compliant and follows strict security practices so your Metabase data and credentials are handled as safely as possible.

Used by agents from

Context
Letta
glean
HubSpot
Agent.ai
Altera
DataStax
Entelligence
Rolai
Context
Letta
glean
HubSpot
Agent.ai
Altera
DataStax
Entelligence
Rolai
Context
Letta
glean
HubSpot
Agent.ai
Altera
DataStax
Entelligence
Rolai

Never worry about agent reliability

We handle tool reliability, observability, and security so you never have to second-guess an agent action.