This page explains how database adapters fit into sql-query-mcp, which
methods the current code calls on an adapter, and what you need to implement if
you want to propose a new one. Current runtime support remains PostgreSQL and
MySQL only, so treat any work on other engines as a candidate contribution
until the project accepts it.
Adapter implementations live in sql_query_mcp/adapters/. The current runtime
adapters are sql_query_mcp/adapters/postgres.py and
sql_query_mcp/adapters/mysql.py.
sql_query_mcp/adapters/postgres.pyimplements PostgreSQL-specific metadata, sampling, explain formatting, connection pooling, and result handling.sql_query_mcp/adapters/mysql.pyimplements MySQL-specific metadata, sampling, explain formatting, DSN parsing, and result handling.sql_query_mcp/adapters/__init__.pyexposesPostgresAdapterandMySQLAdapterthrough package-level imports.sql_query_mcp/registry.pyinstantiates adapters and routes each configured connection to the correct engine implementation.
An adapter is not a standalone plugin. It works inside the code that opens a database connection, serves metadata tools, executes read-only queries, and records audit logs for each request.
sql_query_mcp/registry.pymapsconfig.enginevalues to adapter instances and opens connections by engine.sql_query_mcp/introspection.pycalls adapter methods for metadata tools, such as listing namespaces, tables, and table descriptions.sql_query_mcp/executor.pyuses adapter methods to build sample queries, formatEXPLAIN, extract plans, and normalize column names.- The adapter must preserve current engine-specific behavior instead of forcing a fake universal namespace model.
Before you start a candidate adapter, study the practical method surface that
the current code already relies on. ConnectionRegistry, MetadataService,
and QueryExecutor call adapter methods directly, so a new adapter must match
that behavior.
The current adapter API includes the following members.
| Member | Called from | What it needs to do |
|---|---|---|
connection(connection_id, dsn) |
sql_query_mcp/registry.py |
Open a database connection with a context manager and yield a live connection object. |
close() |
sql_query_mcp/registry.py |
Clean up pooled or cached resources when the registry shuts down. |
set_statement_timeout(conn, timeout_ms) |
sql_query_mcp/introspection.py, sql_query_mcp/executor.py |
Apply the per-request statement timeout if one is configured. |
list_schemas(conn) |
sql_query_mcp/introspection.py for PostgreSQL |
Return visible PostgreSQL schemas. This is engine-specific. |
list_databases(conn) |
sql_query_mcp/introspection.py for MySQL |
Return visible MySQL databases. This is engine-specific. |
list_tables(conn, namespace) |
sql_query_mcp/introspection.py |
Return tables and views for the resolved schema or database. |
describe_table(conn, namespace, table_name) |
sql_query_mcp/introspection.py |
Return normalized column and index metadata, or None when the table is not found. |
build_sample_query(namespace, table_name, sentinel_limit) |
sql_query_mcp/executor.py |
Build a safe sample query that fetches one extra row so truncation can be detected. |
build_explain_query(sql_text, analyze=False) |
sql_query_mcp/executor.py |
Wrap a validated read-only query in the engine's EXPLAIN form and reject unsupported options when needed. |
extract_plan(rows) |
sql_query_mcp/executor.py |
Convert raw EXPLAIN rows into the plan value returned by the tool. |
column_names(description) |
sql_query_mcp/executor.py |
Normalize cursor description output into a list of column names. |
If you propose a candidate adapter, implement the same integration points that the PostgreSQL and MySQL adapters already satisfy. Keep behavior read-only, and avoid broadening runtime support claims until the project has accepted the new engine.
- Add an adapter module under
sql_query_mcp/adapters/. - Update
sql_query_mcp/adapters/__init__.pyto expose the new adapter. The current registry imports adapters from the package withfrom .adapters import MySQLAdapter, PostgresAdapter, so the package export file must include any newly supported adapter class. - Register the engine in
sql_query_mcp/registry.pyso configured connections resolve to the new adapter. - Implement connection handling, statement timeout handling, metadata access, sample query generation, explain query generation, plan extraction, and column name normalization.
- Preserve engine-native namespace semantics. For example, PostgreSQL uses
schema, and MySQL usesdatabase; a future candidate adapter must define its own compatible namespace behavior clearly. - Keep the adapter compatible with
sql_query_mcp/introspection.pyandsql_query_mcp/executor.pywithout weakening read-only validation or the audit log fields those services already write.
The existing adapters show more than method names. They show the return shapes and edge cases that the rest of the project already expects.
- In
sql_query_mcp/adapters/postgres.py, study howdescribe_table()returnscolumnsandindexes, howbuild_sample_query()quotes identifiers withpsycopg.sql, and howbuild_explain_query()returns JSON-format plans. - In
sql_query_mcp/adapters/mysql.py, study howdescribe_table()normalizes MySQL metadata, howbuild_explain_query()rejectsanalyze=True, and howextract_plan()parses JSON text from MySQL'sEXPLAINoutput. - In
sql_query_mcp/registry.py, study how adapter instances are created once and reused from the_adaptersmap. - In
sql_query_mcp/introspection.py, study how missing table metadata is turned into aQueryExecutionErrorand how timeout and audit logging happen around adapter calls. - In
sql_query_mcp/executor.py, study how sample queries detect truncation, how validated SQL is wrapped forEXPLAIN, and how column names and rows are returned to tool callers.
Adapter work needs tests at the layer users actually hit through the MCP tools, not only tests inside the adapter module. The existing test suite shows the behavior that must remain stable when a new engine is introduced.
- Use
tests/test_metadata.pyas a reference for metadata service behavior, namespace validation, and engine-specific restrictions. - Use
tests/test_executor.pyas a reference for executor behavior, explain handling, sample query behavior, and connection-avoidance checks on invalid input. - Add tests for success paths and failure paths, including unsupported
namespace combinations and engine-specific
EXPLAINbehavior. - Verify that audit logs and error responses still match what
sql_query_mcp/introspection.pyandsql_query_mcp/executor.pycurrently produce.
Because adapter work changes long-term scope, start with project process before implementation. The contribution and Git workflow docs define how to propose, branch, test, and submit the change.
- Open or join an issue as described in the contribution guide.
- Confirm branch and pull request expectations in the Git workflow guide.
- Keep documentation updated so the roadmap and other affected pages reflect the accepted list of supported databases.
If you want to contribute a candidate adapter, align on scope before touching runtime support claims.
- Review the roadmap for the current list of supported databases and future candidate examples.
- Read the contribution guide before opening implementation work.
- Follow the Git workflow guide when you prepare your branch.