apps/docs/content/guides/self-hosting/enable-mcp.mdx
The MCP (Model Context Protocol) server in self-hosted Supabase runs behind the internal API. Currently, it does not offer OAuth 2.1 authentication, and is not intended to be exposed to the Internet. The corresponding API route has to be protected by restricting network connections from the outside. By default, all connections to the MCP server are denied.
This guide explains how to securely enable access to your self-hosted MCP server.
Do not allow connections to the self-hosted MCP server from the Internet. Only access it via:
When connecting via an SSH tunnel to the Studio Docker container, the source IP will be that of the Docker bridge gateway. You need to allow connections from this IP address.
<Tabs scrollable size="small" type="underlined" defaultActiveId="kong"
<TabPanel id="kong" label="Kong">
Determine the Docker bridge gateway IP on the host running your Supabase containers:
docker inspect supabase-kong \
--format '{{range .NetworkSettings.Networks}}{{println .Gateway}}{{end}}'
Determine the Docker bridge gateway IP on the host running your Supabase containers:
docker inspect supabase-envoy \
--format '{{range .NetworkSettings.Networks}}{{println .Gateway}}{{end}}'
This command will output an IP address, e.g., 172.18.0.1.
<Tabs scrollable size="small" type="underlined" defaultActiveId="kong"
<TabPanel id="kong" label="Kong">
Add the IP address you discovered to the Kong configuration by editing the following section in ./volumes/api/kong.yml:
- name: cors, including deny: []## MCP endpoint - local access
- name: mcp
_comment: 'MCP: /mcp -> http://studio:3000/api/mcp (local access)'
url: http://studio:3000/api/mcp
routes:
- name: mcp
strip_path: true
paths:
- /mcp
plugins:
# Block access to /mcp by default
#- name: request-termination
# config:
# status_code: 403
# message: "Access is forbidden."
# Enable local access (danger zone!)
# 1. Comment out the 'request-termination' section above
# 2. Uncomment the entire section below, including 'deny'
# 3. Add your local IPs to the 'allow' list
- name: cors
- name: ip-restriction
config:
allow:
- 127.0.0.1
- ::1
# Add your Docker bridge gateway IP below
- 172.18.0.1
# Do not remove deny!
deny: []
Add the IP address you discovered to the Envoy configuration by editing the /mcp route in ./volumes/api/envoy/lds.template.yaml:
prefix: /mcprbac block that denies all traffic and uncomment the allow-list policy below127.0.0.1 and ::1) and add your Docker bridge gateway IP- match:
prefix: /mcp
route:
cluster: studio
prefix_rewrite: /api/mcp
timeout: 30s
request_headers_to_add:
- header:
key: X-Forwarded-Prefix
value: /mcp
append_action: ADD_IF_ABSENT
typed_per_filter_config:
envoy.filters.http.basic_auth:
'@type': >-
type.googleapis.com/envoy.config.route.v3.FilterConfig
disabled: true
envoy.filters.http.rbac:
'@type': >-
type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBACPerRoute
# Block access to /mcp by default
#rbac:
# rules:
# action: DENY
# policies:
# deny_all:
# permissions:
# - any: true
# principals:
# - any: true
# Enable local access (danger zone!)
# 1. Comment out the 'rbac' block above.
# 2. Uncomment and adjust the 'rbac' block below.
# 3. Add or adjust your local IPs in 'principals'.
rbac:
rules:
action: ALLOW
policies:
allow_local:
permissions:
- any: true
principals:
- direct_remote_ip:
address_prefix: 127.0.0.1
prefix_len: 32
- direct_remote_ip:
address_prefix: ::1
prefix_len: 128
- direct_remote_ip:
# Add your Docker bridge gateway IP below
address_prefix: 172.18.0.1
prefix_len: 32
After you've added the local IP address as above, restart your gateway:
<Tabs scrollable size="small" type="underlined" defaultActiveId="kong"
<TabPanel id="kong" label="Kong">
docker compose restart kong
docker compose -f docker-compose.yml -f docker-compose.envoy.yml restart api-gw
From your local machine, create an SSH tunnel to your Supabase host:
ssh -L localhost:8080:localhost:8000 you@your-supabase-host
This command forwards local port 8080 to port 8000 on your Supabase host.
Edit the settings for your MCP client and add the following to "mcpServers": {} or "servers": {}:
{
"mcpServers": {
"supabase-self-hosted": {
"url": "http://localhost:8080/mcp"
}
}
}
From your local machine, check that the MCP server is reachable:
curl http://localhost:8080/mcp \
-X POST \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "MCP-Protocol-Version: 2025-06-18" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-06-18",
"capabilities": {
"elicitation": {}
},
"clientInfo": {
"name": "test-client",
"title": "Test Client",
"version": "1.0.0"
}
}
}'
Start your MCP client (Claude Code, Cursor, etc.) and verify access to the MCP tools. For example, you can ask: "What is Supabase anon key? Use the Supabase MCP server tools."
If you are unable to connect to the MCP server:
./volumes/api/kong.ymldocker compose logs kong