Skip to content

Commit 3257a85

Browse files
feat(infrastructure): streamline services startup and testing patterns
This commit enhances the project's infrastructure and testing capabilities: - Updated CHANGELOG.md with new infrastructure improvements - Modified pyproject.toml to adjust pytest asyncio fixture scope - Refactored core container initialization to support synchronous startup - Updated services to support clean singleton instance reset - Improved test fixtures and integration test coverage - Restructured project test directories for better organization - Added comprehensive integration tests for various services
1 parent d9f0131 commit 3257a85

40 files changed

+1254
-883
lines changed

.github/workflows/ci.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ jobs:
1717
SUPABASE_PROJECT_REF: ${{ secrets.SUPABASE_PROJECT_REF }}
1818
SUPABASE_DB_PASSWORD: ${{ secrets.SUPABASE_DB_PASSWORD }}
1919
SUPABASE_ACCESS_TOKEN: ${{ secrets.SUPABASE_ACCESS_TOKEN }}
20+
SUPABASE_SERVICE_ROLE_KEY: ${{ secrets.SUPABASE_SERVICE_ROLE_KEY }}
2021
steps:
2122
- uses: actions/checkout@v4
2223

.github/workflows/docs/release-checklist.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,23 @@ Post-release
1616
- Clean install from PyPi works
1717

1818

19+
## v0.3.8 - 2025-03-07
20+
21+
Pre-release
22+
1. Tests pass - [X]
23+
2. CI passes - [X]
24+
3. Build succeeds - [X]
25+
4. Documentation is up to date - [X]
26+
5. Changelog is up to date - [X]
27+
6. Tag and release on GitHub
28+
7. Release is published to PyPI
29+
8. Update dockerfile - [X]
30+
9. Update .env.example (if necessary) - [X]
31+
32+
Post-release
33+
10. Clean install from PyPi works
34+
35+
1936

2037
## v0.3.0 - 2025-02-22
2138

CHANGELOG.MD

Lines changed: 24 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -5,41 +5,34 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
66

77

8-
## [0.3.8] - Planned
9-
## Added
10-
1. Runtime SQL query validation
11-
2. Automatic versioning of database changes
12-
3. Improvement of SQL execution safety mode
13-
- Categorizes all queries into three safety levels:
14-
- `safe` - includes all read operations, plus basic postgres commands which do not modify the data or database structure. Always allowed.
15-
- `write` - includes write operations. Requires `write` db_client mode to be enabled for use.
16-
- `destructive` - include operations which modify database structure, or can lead to data loss. Require 2-step confirmation to be executed AND a `write` mode enabled.
17-
4. Exception
18-
5. More modern postgresql client - `asyncpg`
19-
6. Eliminated depenente on PostgreSQL client libary
20-
7. Documentation
21-
- Management API uses encrytpedHTTPS for connecting
22-
8. Reliability
23-
- Implemented retry logic for
24-
- Establishing connection to the database or API
25-
- Sending requests / executing statements
26-
- Improved API management spec tool:
27-
- return all domains
28-
- return a specific path and method
29-
- return all paths and emthods
30-
- Added code coverage
31-
9. Infra:
32-
- Streamlined dependency injection for easier testing
33-
34-
## Changed
35-
- Updated README.md with detailed feature description.
8+
## [0.3.8] - 2025-03-07
9+
### Added
10+
- SQL query validation using PostgreSQL's parser (pglast v7.3+)
11+
- Automatic migration script generation for schema changes
12+
- Universal safety system with standardized risk levels (Low/Medium/High/Extreme)
13+
- Switched to asyncpg v0.30.0+ from psycopg2
14+
- Enhanced API spec tool with multiple query modes and risk assessment
15+
- Connection retry logic for database and API operations
16+
- Code coverage with pytest-cov
17+
- SQL linting with SQLFluff
18+
- Added pyyaml v6.0.2+ for configuration
19+
20+
### Changed
21+
- Refactored to use dependency injection pattern
22+
- Standardized service initialization to synchronous pattern
23+
- Improved SQL safety categorization:
24+
- `safe`: Read-only operations (always allowed)
25+
- `write`: Data modification (requires unsafe mode)
26+
- `destructive`: Schema changes (requires unsafe mode + confirmation)
27+
- Updated Ruff to v0.9.9
28+
- Added asyncpg-stubs and pytest-mock for testing
3629

3730
## [0.3.7] - 2025-03-02
38-
### Fixed:
39-
- fixed various documentation inaccuracies
31+
### Fixed
32+
- Documentation inaccuracies
4033

4134
### Added
42-
- enabled auth admin SDK use with local Supabase instances
35+
- Auth admin SDK support for local Supabase instances
4336

4437

4538
## [0.3.6] - 2025-02-26

README.md

Lines changed: 99 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -45,23 +45,28 @@ A feature-rich MCP server that enables Cursor and Windsurf to safely interact wi
4545
## ✨ Key features
4646
- 💻 Compatible with Cursor, Windsurf, Cline and other MCP clients supporting `stdio` protocol
4747
- 🔐 Control read-only and read-write modes of SQL query execution
48+
- 🔍 Runtime SQL query validation with risk level assessment
49+
- 🛡️ Three-tier safety system for SQL operations: safe, write, and destructive
4850
- 🔄 Robust transaction handling for both direct and pooled database connections
51+
- 📝 Automatic versioning of database schema changes
4952
- 💻 Manage your Supabase projects with Supabase Management API
5053
- 🧑‍💻 Manage users with Supabase Auth Admin methods via Python SDK
5154
- 🔨 Pre-built tools to help Cursor & Windsurf work with MCP more effectively
5255
- 📦 Dead-simple install & setup via package manager (uv, pipx, etc.)
5356

57+
5458
## Getting Started
5559

5660
### Prerequisites
5761
Installing the server requires the following on your system:
5862
- Python 3.12+
59-
- PostgresSQL 16+
6063

6164
If you plan to install via `uv`, ensure it's [installed](https://docs.astral.sh/uv/getting-started/installation/#__tabbed_1_1).
6265

6366
### PostgreSQL Installation
64-
> ⚠️ **Important**: PostgreSQL must be installed BEFORE installing project dependencies, as psycopg2 requires PostgreSQL development libraries during compilation.
67+
PostgreSQL installation is no longer required for the MCP server itself, as it now uses asyncpg which doesn't depend on PostgreSQL development libraries.
68+
69+
However, you'll still need PostgreSQL if you're running a local Supabase instance:
6570

6671
**MacOS**
6772
```bash
@@ -86,9 +91,7 @@ uv pip install supabase-mcp-server
8691

8792
`pipx` is recommended because it creates isolated environments for each package.
8893

89-
You can also install the server manually by cloning the repository and running `pipx` install -editable . from the root directory.
90-
91-
> ⚠️ If you run into psycopg2 compilation issues, you might be missing PostgreSQL development packages. See above.
94+
You can also install the server manually by cloning the repository and running `pipx install -e .` from the root directory.
9295

9396
#### Installing from source
9497
If you would like to install from source, for example for local development:
@@ -116,11 +119,10 @@ npx -y @smithery/cli install @alexander-zuev/supabase-mcp --client claude
116119
After installing the package, you'll need to configure your database connection settings. The server supports both local and remote Supabase instances.
117120

118121
#### Local Supabase instance (Default)
119-
Server is pre-configured to connect to the local Supabase instance using default settings:
122+
Server is pre-configured to connect to the local Supabase instance using default settings:
120123
- `Host`: 127.0.0.1:54322
121124
- `Password`: postgres
122-
- `API URL` : http://127.0.0.1:54321
123-
125+
- `API URL`: http://127.0.0.1:54321
124126

125127
>💡 As long as you didn't modify the default settings and you want to connect to the local instance, you don't need to set environment variables.
126128
@@ -156,14 +158,21 @@ The server supports all Supabase regions:
156158
- `ap-southeast-2` - Oceania (Sydney)
157159
- `sa-east-1` - South America (São Paulo)
158160

159-
Method of MCP configuration differs between Cursor and Windsurf. Read the relevant section to understand how to configure connection.
161+
#### Configuration Methods
162+
163+
The server looks for configuration in this order:
164+
1. Environment variables (highest priority)
165+
2. Local `.env` file in current directory
166+
3. Global config file:
167+
- Windows: `%APPDATA%/supabase-mcp/.env`
168+
- macOS/Linux: `~/.config/supabase-mcp/.env`
169+
4. Default settings (local development)
160170

161171
##### Cursor
162-
Since v0.46 there are two ways to configure MCP servers in Cursor:
172+
Since Cursor v0.46 there are two ways to configure MCP servers:
163173
- per project basis -> create `mcp.json` in your project / repo folder and `.env` to configure connection
164174
- globally -> create an MCP server in Settings and configure using `.env` which is supported by this MCP server only
165175

166-
167176
You can create project-specific MCP by:
168177
- creating .cursor folder in your repo, if doesn't exist
169178
- creating or updating `mcp.json` file with the following settings
@@ -333,76 +342,69 @@ A super useful tool to help debug MCP server issues is MCP Inspector. If you ins
333342

334343
### Database query tools
335344

336-
Since v0.3.0 server supports both read-only and data modification operations:
337-
338-
- **Read operations**: SELECT queries for data retrieval
339-
- **Data Manipulation Language (DML)**: INSERT, UPDATE, DELETE operations for data changes
340-
- **Data Definition Language (DDL)**: CREATE, ALTER, DROP operations for schema changes*
341-
342-
*Note: DDL operations require:
343-
1. Read-write mode enabled via `live_dangerously`
344-
2. Sufficient permissions for the connected database role
345-
346-
#### Transaction Handling
347-
348-
The server supports two approaches for executing write operations:
349-
350-
1. **Explicit Transaction Control** (Recommended):
351-
```sql
352-
BEGIN;
353-
CREATE TABLE public.test_table (id SERIAL PRIMARY KEY, name TEXT);
354-
COMMIT;
355-
```
356-
357-
2. **Single Statements**:
358-
```sql
359-
CREATE TABLE public.test_table (id SERIAL PRIMARY KEY, name TEXT);
360-
```
361-
362-
For DDL operations (CREATE/ALTER/DROP), tool description appropriately guides Cursor/Windsurft to use explicit transaction control with BEGIN/COMMIT blocks.
363-
364-
#### Connection Types
365-
366-
This MCP server uses::
367-
- **Direct Database Connection**: when connecting to a local Supabase instance
368-
- **Transaction Pooler Connections**: when connecting to a remote Supabase instance
369-
370-
371-
When connecting via Supabase's Transaction Pooler, some complex transaction patterns may not work as expected. For schema changes in these environments, use explicit transaction blocks or consider using Supabase migrations or the SQL Editor in the dashboard.
372-
373-
Available database tools:
374-
- `get_db_schemas` - Lists all database schemas with their sizes and table counts
375-
- `get_tables` - Lists all tables in a schema with their sizes, row counts, and metadata
376-
- `get_table_schema` - Gets detailed table structure including columns, keys, and relationships
377-
- `execute_sql_query` - Executes raw SQL queries with comprehensive support for all PostgreSQL operations:
378-
- Supports all query types (SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER, DROP, etc.)
379-
- Handles transaction control statements (BEGIN, COMMIT, ROLLBACK)
380-
381-
382-
- Supported modes:
383-
- `read-only` - only read-only queries are allowed (default mode)
384-
- `read-write` - all SQL operations are allowed when explicitly enabled
385-
- Safety features:
386-
- Starts in read-only mode by default
387-
- Requires explicit mode switch for write operations
388-
- Automatically resets to read-only mode after write operations
389-
- Intelligent transaction state detection to prevent errors
390-
- SQL query validation [TODO]
345+
Since v0.3+ server provides comprehensive database management capabilities with built-in safety controls:
346+
347+
- **SQL Query Execution**: Execute any PostgreSQL query with intelligent risk assessment
348+
- **Three-tier safety system**:
349+
- `safe`: Read-only operations (SELECT, EXPLAIN) - always allowed
350+
- `write`: Data modification operations (INSERT, UPDATE, DELETE) - require unsafe mode
351+
- `destructive`: Schema-changing operations (DROP, TRUNCATE) - require unsafe mode and confirmation
352+
353+
- **SQL Parsing and Validation**:
354+
- Uses PostgreSQL's own parser (via pglast) for accurate query analysis
355+
- Precisely identifies query types and potential risks
356+
- Validates syntax before execution to prevent errors
357+
- Categorizes statements into DQL, DML, DDL, DCL, and TCL types
358+
- Provides detailed feedback on query safety and required permissions
359+
360+
- **Automatic Migration Versioning**:
361+
- All schema-changing operations (DDL) are automatically versioned
362+
- Creates timestamped migration entries in Supabase's migration system
363+
- Generates descriptive migration names based on operation type and target
364+
- Includes CREATE, ALTER, DROP, GRANT, REVOKE operations
365+
- Maintains a complete history of schema changes for better tracking and rollback capabilities
366+
367+
- **Safety Controls**:
368+
- All database tools start in SAFE mode by default (only read-only operations are allowed)
369+
- All statements are executed in transaction mode by the `asyncpg` client
370+
- 2-step confirmation is required for high-risk / destructive operations
371+
372+
- **Available Tools**:
373+
- `get_schemas`: Lists all database schemas with their sizes and table counts
374+
- `get_tables`: Lists tables, foreign tables, and views in a schema with metadata
375+
- `get_table_schema`: Gets detailed table structure including columns, keys, and relationships
376+
- `execute_postgresql`: Executes PostgreSQL statements against your Supabase database
377+
- `confirm_destructive_operation`: Executes high-risk operations after explicit confirmation
378+
- `retrieve_migrations`: Gets all migrations from the supabase_migrations schema
379+
- `live_dangerously`: Toggles between safe and unsafe operation modes
391380

392381
### Management API tools
393-
Since v0.3.0 server supports sending arbitrary requests to Supabase Management API with auto-injection of project ref and safety mode control:
394-
- Includes the following tools:
395-
- `send_management_api_request` to send arbitrary requests to Supabase Management API, with auto-injection of project ref and safety mode control
396-
- `get_management_api_spec` to get the enriched API specification with safety information
397-
- `get_management_api_safety_rules` to get all safety rules including blocked and unsafe operations with human-readable explanations
398-
- `live_dangerously` to switch between safe and unsafe modes
399-
- Safety features:
400-
- Divides API methods into `safe`, `unsafe` and `blocked` categories based on the risk of the operation
401-
- Allows to switch between safe and unsafe modes dynamically
402-
- Blocked operations (delete project, delete database) are not allowed regardless of the mode
403-
- **Note**: Management API tools only work with remote Supabase instances and are not compatible with local Supabase development setups.
382+
383+
Since v0.3.0 server provides secure access to the Supabase Management API with built-in safety controls:
384+
385+
- **Available Tools**:
386+
- `send_management_api_request`: Sends arbitrary requests to Supabase Management API with auto-injection of project ref
387+
- `get_management_api_spec`: Gets the enriched API specification with safety information
388+
- Supports multiple query modes: by domain, by specific path/method, or all paths
389+
- Includes risk assessment information for each endpoint
390+
- Provides detailed parameter requirements and response formats
391+
- Helps LLMs understand the full capabilities of the Supabase Management API
392+
- `get_management_api_safety_rules`: Gets all safety rules with human-readable explanations
393+
- `live_dangerously`: Toggles between safe and unsafe operation modes
394+
395+
- **Safety Controls**:
396+
- Uses the same safety manager as database operations for consistent risk management
397+
- Operations categorized by risk level:
398+
- `safe`: Read-only operations (GET) - always allowed
399+
- `unsafe`: State-changing operations (POST, PUT, PATCH, DELETE) - require unsafe mode
400+
- `blocked`: Destructive operations (delete project, etc.) - never allowed
401+
- Default safe mode prevents accidental state changes
402+
- Path-based pattern matching for precise safety rules
403+
404+
**Note**: Management API tools only work with remote Supabase instances and are not compatible with local Supabase development setups.
404405

405406
### Auth Admin tools
407+
406408
I was planning to add support for Python SDK methods to the MCP server. Upon consideration I decided to only add support for Auth admin methods as I often found myself manually creating test users which was prone to errors and time consuming. Now I can just ask Cursor to create a test user and it will be done seamlessly. Check out the full Auth Admin SDK method docs to know what it can do.
407409

408410
Since v0.3.6 server supports direct access to Supabase Auth Admin methods via Python SDK:
@@ -440,13 +442,29 @@ The Auth Admin SDK provides several key advantages over direct SQL manipulation:
440442

441443
### Automatic Versioning of Database Changes
442444

443-
"With great power comes great responsibility." While `execute_sql_query` tool coupled with aptly named `live_dangerously` tool provide a powerful and simple way to manage your Supabase database, it also means that dropping a table or modifying one is one chat message away. In order to reduce the risk of irreversible changes, since v0.3.8 the server supports:
445+
"With great power comes great responsibility." While `execute_postgresql` tool coupled with aptly named `live_dangerously` tool provide a powerful and simple way to manage your Supabase database, it also means that dropping a table or modifying one is one chat message away. In order to reduce the risk of irreversible changes, since v0.3.8 the server supports:
444446
- automatic creation of migration scripts for all write & destructive sql operations executed on the database
445447
- improved safety mode of query execution, in which all queries are categorized in:
446448
- `safe` type: always allowed. Includes all read-only ops.
447449
- `write`type: requires `write` mode to be enabled by the user.
448450
- `destructive` type: requires `write` mode to be enabled by the user AND a 2-step confirmation of query execution for clients that do not execute tools automatically.
449451

452+
### Universal Safety Mode
453+
Since v0.3.8 Safety Mode has been standardized across all services (database, API, SDK) using a universal safety manager. This provides consistent risk management and a unified interface for controlling safety settings across the entire MCP server.
454+
455+
All operations (SQL queries, API requests, SDK methods) are categorized into risk levels:
456+
- `Low` risk: Read-only operations that don't modify data or structure (SELECT queries, GET API requests)
457+
- `Medium` risk: Write operations that modify data but not structure (INSERT/UPDATE/DELETE, most POST/PUT API requests)
458+
- `High` risk: Destructive operations that modify database structure or could cause data loss (DROP/TRUNCATE, DELETE API endpoints)
459+
- `Extreme` risk: Operations with severe consequences that are blocked entirely (deleting projects)
460+
461+
Safety controls are applied based on risk level:
462+
- Low risk operations are always allowed
463+
- Medium risk operations require unsafe mode to be enabled
464+
- High risk operations require unsafe mode AND explicit confirmation
465+
- Extreme risk operations are never allowed
466+
467+
This universal approach ensures consistent protection across all server components while providing flexibility for legitimate operations when needed.
450468
451469
## Feature Changelog
452470
@@ -457,12 +475,10 @@ The Auth Admin SDK provides several key advantages over direct SQL manipulation:
457475
- 🔄 Robust transaction handling for both direct and pooled connections - ✅ (v0.3.2)
458476
- 🐍 Support methods and objects available in native Python SDK - ✅ (v0.3.6)
459477
- 🔍 Stronger SQL query validation ✅ (v0.3.8)
460-
- 📝 Automatic versioning of DDL queries ✅ (v0.3.8)
478+
- 📝 Automatic versioning of database changes ✅ (v0.3.8)
479+
- 📖 Radically improved knowledge and tools of api spec ✅ (v0.3.8)
461480
- 🪵 Tools / resources to more easily access database, edge functions logs (?)
462-
- 👨‍💻 Supabase CLI integration (?)
463-
- 📖 Radically improved knowledge and tools of api spec
464-
- Resources to more easily access and check api spec
465-
- Atomic url paths and ops (right now LLM trips more often then not)
481+
466482
467483
For a more detailed roadmap, please see this [discussion](github.com) on GitHub.
468484

pyproject.toml

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -114,14 +114,11 @@ python_classes = ["Test*"]
114114
python_functions = ["test_*"]
115115
addopts = "-v --no-header --tb=short"
116116

117-
# addopts = "-v --no-header --tb=short --showlocals --log-cli-level=INFO"
118117

119118
[tool.pytest.ini_options]
120-
# log_cli = true
121-
# log_cli_format = "%(asctime)s [%(levelname)8s] %(message)s (%(filename)s:%(lineno)s)"
122-
# log_cli_date_format = "%Y-%m-%d %H:%M:%S"
123119
asyncio_mode = "auto"
124-
asyncio_default_fixture_loop_scope = "function"
120+
asyncio_default_fixture_loop_scope = "module"
121+
125122
markers = [
126123
"unit: marks a test as a unit test",
127124
"integration: marks a test as an integration test that requires database access"

supabase_mcp/core/container.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,3 @@ def initialize(self, settings: Settings) -> "Container":
5757

5858
logger.info("✓ All services initialized successfully.")
5959
return self
60-
61-
async def shutdown(self) -> None:
62-
"""Shuts down all services in a synchronous manner to satisfy MCP runtime requirements"""
63-
await self.postgres_client.close()

supabase_mcp/core/mcp_server.py

Lines changed: 0 additions & 9 deletions
This file was deleted.

0 commit comments

Comments
 (0)