Skip to content

Documentation navigation

Databases

SQLite, Postgres, MySQL, SQL Server, and Supabase toolsets.

#Databases

Transactional database connectors. Each toolset gives an agent read-only schema introspection and parameterized query tools over one database engine. For analytics warehouses see Warehouses.

The SQL toolsets expose read-oriented query surfaces. The Supabase connector also exposes writes, auth administration, storage mutations and function calls. Use database credentials restricted to the intended operations: parser checks and registration tags do not replace database permissions.

All five connectors in this group follow the same agent-ready pattern for catalog tools: list_schemas, list_tables, list_views, list_indexes, and list_databases return a summary envelope ({<key>, returned, total, truncated}) where each entry carries a response-local ordinal ref (schema_ref, table_ref, view_ref, index_ref, database_ref) plus the user-facing schema / table / view / column / index names. Those names are always present -- the connector never hides identifiers an agent needs to compose a follow-up query. The max_results argument caps each list (default 25). sample_table defaults to 5 rows so quick lookups stay tidy. The read-only safety checks include parser denylists and engine-specific restrictions. A permitted SELECT can still call a function with side effects; use a restricted database role.

#SQLiteToolSet

SQLiteToolSet exposes read-only schema introspection and parameterized query tools over a local SQLite database file. It is dependency-free (uses the standard-library sqlite3 module) and opens a fresh connection per call so the connector is safe to share across threads.

Python
from maivn import Agent
from maivn_tools import SQLiteToolSet, register_connector

connector = SQLiteToolSet("./reports.db", row_limit=500)
agent = Agent(name="database-agent", model="auto")
register_connector(agent, connector)

Tools: list_tables(include_views, max_results), list_views(max_results), list_indexes(table=None, max_results), list_foreign_keys(table), describe_table(name), get_schema_dump(), sample_table(name, limit), count_rows(name), explain_query(sql, plan), run_query(sql, parameters, row_limit).

run_query only accepts SELECT, WITH, and EXPLAIN. Compound statements (multiple semicolons) are rejected, and a regex denylist blocks INSERT, UPDATE, DELETE, DROP, ALTER, CREATE, REPLACE, TRUNCATE, ATTACH, DETACH, VACUUM, REINDEX, and PRAGMA. Identifier-taking tools validate name against [A-Za-z_][A-Za-z0-9_]* so the underlying PRAGMA calls cannot be hijacked.

ArgumentDefaultPurpose
databaserequiredPath to the SQLite file, or ":memory:".
row_limit500Maximum rows returned per query.
query_timeout_seconds5.0SQLite busy timeout.

#Agent-ready behavior

  • list_tables, list_views, and list_indexes return envelopes with ordinal table_ref / view_ref / index_ref plus user-facing name and (for indexes / views) the DDL sql. Internal sqlite_* objects are always filtered out.
  • describe_table returns column metadata, primary keys, and indexes -- the column name / type / notnull / default / primary_key fields a SELECT needs.
  • sample_table(name) defaults to 5 rows; raise limit (capped by the connector row_limit) when you need more.
  • run_query defaults to 100 rows per call; raise row_limit per call up to the configured connector ceiling.
  • No write tools -- SQLiteToolSet is read-only by design.

Example:

Python
tables = connector.list_tables()
# {"tables": [{"table_ref": "table_1", "name": "orders", "type": "table"}, ...], "returned": 25, "total": 47, "truncated": True}
sample = connector.sample_table(tables["tables"][0]["name"])
# {"columns": ["id", "customer_id", ...], "rows": [{"id": 1, ...}, ...], "row_count": 5, "truncated": True}

#PostgresToolSet

PostgresToolSet exposes read-only schema introspection and query tools over a PostgreSQL database. The connector wraps any DB-API 2.0 driver behind a small connection-factory protocol so tests can inject fakes and so the base package does not require psycopg to be installed.

Python
from maivn_tools import PostgresToolSet

connector = PostgresToolSet(
    dsn="postgresql://reader:password@localhost:5432/analytics",
    row_limit=500,
)

If psycopg is not installed the connector falls back to psycopg2. To use a different driver, supply a connection_factory:

Python
import psycopg

connector = PostgresToolSet(
    connection_factory=lambda: psycopg.connect(dsn, autocommit=False),
)

Tools: list_schemas(max_results), list_tables(schema, max_results), list_views(schema, max_results), list_indexes(schema, table=None, max_results), list_foreign_keys(name, schema), list_extensions(), describe_table(name, schema), get_table_size(name, schema), sample_table(name, schema, limit), count_rows(name, schema), server_version(), explain_query(sql, analyze, verbose), run_query(sql, parameters, row_limit).

run_query only accepts SELECT, WITH, and EXPLAIN. The connector attempts SET TRANSACTION READ ONLY per call, but catches failures from that statement. Do not assume it established read-only mode. Custom factories should use transactions rather than autocommit and a database role without write rights. explain_query refuses analyze=True because EXPLAIN ANALYZE executes the underlying query and may have side effects.

ArgumentDefaultPurpose
dsnNoneConnection string used by the default factory.
connection_factoryNoneCustom DB-API factory; mutually exclusive with dsn.
row_limit500Maximum rows returned per query.

#Agent-ready behavior

  • list_schemas, list_tables, list_views, and list_indexes return envelopes with ordinal refs (schema_ref, table_ref, view_ref, index_ref) plus the user-facing schema / name / type columns. Default max_results is 25.
  • describe_table returns {"name", "schema", "columns", "primary_key"} -- columns[*] carries name, type, nullable, default.
  • sample_table(name) defaults to 5 rows.
  • run_query defaults to 100 rows per call; raise row_limit per call up to the configured ceiling.

Example:

Python
tables = connector.list_tables(schema="public")
# {"tables": [{"table_ref": "table_1", "schema": "public", "name": "orders", "type": "BASE TABLE"}, ...], ...}

#MySQLToolSet

MySQLToolSet is a read-only DB-API 2.0 connector for MySQL and MariaDB, mirroring PostgresToolSet. The driver (mysql-connector-python or pymysql) is not a hard dependency -- pass connection_factory or install one of the supported drivers.

Python
from maivn_tools import MySQLToolSet

connector = MySQLToolSet(connect_kwargs={
    "host": "db.example.com",
    "user": "reader",
    "password": secrets["MYSQL_PASSWORD"],
    "database": "analytics",
})

Tools: list_databases(max_results), list_tables(schema, max_results), describe_table(name, schema), list_indexes(name, schema, max_results), explain_query(sql, analyze), server_version(), sample_table(name, schema, limit), count_rows(name, schema), run_query(sql, parameters, row_limit).

run_query only accepts statements whose first keyword is SELECT, WITH, EXPLAIN, DESCRIBE, DESC, or SHOW. Compound statements and a denylist of mutation keywords are rejected.

#Agent-ready behavior

  • list_databases, list_tables, and list_indexes return envelopes with database_ref / table_ref / index_ref plus the user-facing MySQL column names (Database, name, type, plus SHOW INDEXES columns like Key_name, Column_name, Non_unique). Default max_results is 25.
  • describe_table returns {"schema", "name", "columns", "primary_key"} with the MySQL column key flag (PRI, MUL, ...).
  • sample_table(name) defaults to 5 rows.
  • run_query defaults to 100 rows per call.

#SQLServerToolSet

SQLServerToolSet is a read-only DB-API 2.0 connector for Microsoft SQL Server. Pass connection_string to use pyodbc, connect_kwargs to use pymssql, or a custom connection_factory for tests.

Python
from maivn_tools import SQLServerToolSet

connector = SQLServerToolSet(connection_string="DRIVER=ODBC Driver 18 ...")

Tools: list_databases(max_results), list_schemas(max_results), list_tables(schema="dbo", max_results), describe_table(name, schema="dbo"), list_views(schema="dbo", max_results), server_version(), sample_table(name, schema, limit), count_rows(name, schema), run_query(sql, parameters, row_limit).

run_query accepts only SELECT and WITH statements; compound statements and a denylist of mutation keywords (including EXEC / EXECUTE / MERGE) are rejected.

#Agent-ready behavior

  • list_databases, list_schemas, list_tables, and list_views return envelopes with ordinal refs plus user-facing name / schema / type columns. Default max_results is 25.
  • describe_table returns {"schema", "name", "columns", "primary_key"}.
  • sample_table(name) defaults to 5 rows and uses SELECT TOP.
  • run_query defaults to 100 rows per call.

#SupabaseToolSet

SupabaseToolSet is a single connector spanning Supabase Platform's public surfaces: PostgREST data access (incl. RPC and pgvector matching), GoTrue auth admin, Storage objects, and Edge Functions. Authentication uses the project's anon or service_role key (passed as apikey) plus an optional separate access token for end-user impersonation.

Python
from maivn_tools import SupabaseToolSet

connector = SupabaseToolSet(
    project_url="https://abcd.supabase.co",
    api_key=secrets["SUPABASE_SERVICE_ROLE"],
)
Service-role keys grant unrestricted access; treat them as destructive credentials.

PostgREST data tools: select(table, ...), insert(table, rows, ...), update(table, filter, values, ...), delete(table, filter, ...) (destructive), rpc(function_name, args, ...), match_vectors(function_name, embedding, ...).

Auth admin tools: list_users(include_metadata, include_ids), get_user(user_id), create_user(...), update_user(user_id, fields), delete_user(user_id) (destructive), invite_user(email, ...).

Storage tools: list_buckets(include_metadata), create_bucket(...), delete_bucket(bucket_id) (destructive), list_objects(bucket_id, include_metadata, ...), create_signed_url(bucket_id, path, ...), delete_object(bucket_id, path) (destructive).

Edge Functions: invoke_function(function_name, body, ...).

#Agent-ready behavior

  • list_users, list_buckets, and list_objects return compact summaries by default with display refs (user_ref, bucket_ref, object_ref). User-facing fields always shown: user email / phone / role, bucket name, object name (the bucket-relative path), size, content_type. Pass include_metadata=False for the raw GoTrue / Supabase response.
  • For list_users, raw UUIDs are hidden by default -- set include_ids=True to expose user_id. update_user, delete_user, and get_user accept either the raw UUID string or the dict from list_users(include_ids=True).
  • list_buckets / list_objects always show the bucket / object names (those are the user-facing identifiers -- not internal handles). delete_bucket, delete_object, and create_signed_url accept either the raw ID / path string or the dict returned by the corresponding list.
  • Default per_page for list_users is 25; default limit for list_objects is 25; default PostgREST select limit is 100.
  • Destructive tools: delete (PostgREST row delete), delete_user, delete_bucket, delete_object. delete and update require a non-empty filter so a full-table mutation is rejected up front.

Example:

Python
users = connector.list_users()
# {"users": [{"user_ref": "user_1", "email": "alice@example.com", "role": "authenticated", ...}, ...], "page": 1, "per_page": 25}
users_with_ids = connector.list_users(include_ids=True)
connector.update_user(users_with_ids["users"][0], {"banned_until": "..."})