Skip to content

Commit 1780f3f

Browse files
Merge pull request #25 from alexander-zuev/feat/small-improv
feat(sdk): enable python sdk usage locally
2 parents 29e3619 + 224cd3e commit 1780f3f

File tree

4 files changed

+37
-12
lines changed

4 files changed

+37
-12
lines changed

README.md

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
<a href="https://www.python.org/downloads/"><img src="https://img.shields.io/badge/python-3.12%2B-blue.svg" alt="Python 3.12+" /></a>
2727
<a href="https://github.com/astral-sh/uv"><img src="https://img.shields.io/badge/uv-package%20manager-blueviolet" alt="uv package manager" /></a>
2828
<a href="https://pepy.tech/project/supabase-mcp-server"><img src="https://static.pepy.tech/badge/supabase-mcp-server" alt="PyPI Downloads" /></a>
29+
<a href="https://smithery.ai/badge/@alexander-zuev/supabase-mcp-server"><img src="https://smithery.ai/badge/@alexander-zuev/supabase-mcp-server" alt="Smithery.ai Downloads" /></a>
2930
<a href="https://modelcontextprotocol.io/introduction"><img src="https://img.shields.io/badge/MCP-Server-orange" alt="MCP Server" /></a>
3031
<a href="LICENSE"><img src="https://img.shields.io/badge/license-Apache%202.0-blue.svg" alt="License" /></a>
3132
</p>
@@ -117,6 +118,8 @@ After installing the package, you'll need to configure your database connection
117118
Server is pre-configured to connect to the local Supabase instance using default settings:
118119
- `Host`: 127.0.0.1:54322
119120
- `Password`: postgres
121+
- `API URL` : http://127.0.0.1:54321
122+
120123

121124
>💡 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.
122125
@@ -129,6 +132,7 @@ For remote Supabase projects, you need to configure:
129132
- `SUPABASE_DB_PASSWORD` - Your database password
130133
- `SUPABASE_REGION` - (Optional) Defaults to `us-east-1`
131134
- `SUPABASE_ACCESS_TOKEN` - (Optional) For Management API access
135+
- `SUPABASE_SERVICE_ROLE_KEY` - (Optional) For Auth Admin SDK access
132136

133137
You can get your SUPABASE_PROJECT_REF from your project's dashboard URL:
134138
- `https://supabase.com/dashboard/project/<supabase-project-ref>`
@@ -168,11 +172,11 @@ You can create project-specific MCP by:
168172
```json
169173
{
170174
"mcpServers": {
171-
"filesystem": {
172-
"command": "supabase-mcp-server",
175+
"supabase": {
176+
"command": "supabase-mcp-server"
173177
}
174178
}
175-
}
179+
}
176180
```
177181

178182
Alternatively, if you want to configure MCP servers globally (i.e. not for each project), you can use configure connection settings by updating an `.env` file in a global config folder by running the following commands:
@@ -203,6 +207,7 @@ SUPABASE_PROJECT_REF=your-project-ref
203207
SUPABASE_DB_PASSWORD=your-db-password
204208
SUPABASE_REGION=us-east-1 # optional, defaults to us-east-1
205209
SUPABASE_ACCESS_TOKEN=your-access-token # optional, for management API
210+
SUPABASE_SERVICE_ROLE_KEY=your-service-role-key # optional, for Auth Admin SDK
206211
```
207212

208213
Verify the file exists - you should see the values you have just set:
@@ -230,7 +235,8 @@ Windsurf supports de facto standard .json format for MCP Servers configuration.
230235
"SUPABASE_PROJECT_REF": "your-project-ref",
231236
"SUPABASE_DB_PASSWORD": "your-db-password",
232237
"SUPABASE_REGION": "us-east-1", // optional, defaults to us-east-1
233-
"SUPABASE_ACCESS_TOKEN": "your-access-token" // optional, for management API
238+
"SUPABASE_ACCESS_TOKEN": "your-access-token", // optional, for management API
239+
"SUPABASE_SERVICE_ROLE_KEY": "your-service-role-key" // optional, for Auth Admin SDK
234240
}
235241
}
236242
}
@@ -279,7 +285,8 @@ Go to Cascade -> Click on the hammer icon -> Configure -> Fill in the configurat
279285
"SUPABASE_PROJECT_REF": "your-project-ref",
280286
"SUPABASE_DB_PASSWORD": "your-db-password",
281287
"SUPABASE_REGION": "us-east-1", // optional, defaults to us-east-1
282-
"SUPABASE_ACCESS_TOKEN": "your-access-token" // optional, for management API
288+
"SUPABASE_ACCESS_TOKEN": "your-access-token", // optional, for management API
289+
"SUPABASE_SERVICE_ROLE_KEY": "your-service-role-key" // optional, for Auth Admin SDK
283290
}
284291
}
285292
}
@@ -386,6 +393,7 @@ Since v0.3.0 server supports sending arbitrary requests to Supabase Management A
386393
- Divides API methods into `safe`, `unsafe` and `blocked` categories based on the risk of the operation
387394
- Allows to switch between safe and unsafe modes dynamically
388395
- Blocked operations (delete project, delete database) are not allowed regardless of the mode
396+
- **Note**: Management API tools only work with remote Supabase instances and are not compatible with local Supabase development setups.
389397
390398
### Auth Admin tools
391399
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.

supabase_mcp/main.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ async def get_table_schema(schema_name: str, table: str):
7171
3. NEVER mix READ and WRITE operations in the same query
7272
4. NEVER use single DDL statements without transaction control
7373
5. Remember to enable unsafe mode first with live_dangerously('database', True)
74-
6. For auth operations (primarily creating, updating, deleting users, generating links, etc), prefer using the Auth Admin SDK methods
74+
6. For auth operations (primarily creating, updating, deleting users, generating links, etc), prefer using the Auth Admin SDK methods
7575
instead of direct SQL manipulation to ensure correctness and prevent security issues
7676
7777
TRANSACTION HANDLING:
@@ -229,12 +229,10 @@ async def get_auth_admin_methods_spec() -> dict:
229229
2. Create user:
230230
method: "create_user"
231231
params: {
232-
"attributes": {
233-
"email": "user@example.com",
234-
"password": "secure-password",
235-
"email_confirm": true,
236-
"user_metadata": {"name": "John Doe"}
237-
}
232+
"email": "user@example.com",
233+
"password": "secure-password",
234+
"email_confirm": true,
235+
"user_metadata": {"name": "John Doe"}
238236
}
239237
240238
3. Generate link:

supabase_mcp/sdk_client/python_client.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ def __init__(self, project_ref: str, service_role_key: str):
4343

4444
def get_supabase_url(self) -> str:
4545
"""Returns the Supabase URL based on the project reference"""
46+
if self.project_ref.startswith("127.0.0.1"):
47+
# Return the default Supabase API URL
48+
return "http://127.0.0.1:54321"
4649
return f"https://{self.project_ref}.supabase.co"
4750

4851
@classmethod

tests/sdk_client/test_python_client.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,3 +104,19 @@ async def test_method_exception_handling(self, sdk_client, mock_supabase_client)
104104

105105
assert error_message in str(excinfo.value)
106106
assert "Error calling get_user_by_id" in str(excinfo.value)
107+
108+
async def test_local_url_construction_with_port(self):
109+
"""Test URL construction for local instance with IP and port"""
110+
# Test that the implementation correctly handles a project_ref with a port
111+
client = SupabaseSDKClient("127.0.0.1:5432", "my-key")
112+
url = client.get_supabase_url()
113+
# The implementation should extract just the host and use port 54321
114+
assert url == "http://127.0.0.1:54321"
115+
116+
async def test_local_url_construction_with_default_settings(self):
117+
"""Test URL construction for local instance with default settings"""
118+
# Test with the default project_ref from settings (127.0.0.1:54322)
119+
client = SupabaseSDKClient("127.0.0.1:54322", "my-key")
120+
url = client.get_supabase_url()
121+
# The implementation should extract just the host and use port 54321
122+
assert url == "http://127.0.0.1:54321"

0 commit comments

Comments
 (0)