> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mcp-use.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Supabase

> Deploy your MCP server on Supabase Edge Functions

This guide demonstrates how to deploy an MCP server on [Supabase Edge Functions](https://supabase.com/docs/guides/functions), which runs on Deno and provides a serverless environment for your MCP applications.

## Prerequisites

1. **Supabase CLI**: Install from [Supabase CLI Installation Guide](https://supabase.com/docs/guides/cli)
2. **Supabase Account**
3. **Docker** Required to solve bug [https://github.com/orgs/supabase/discussions/32815](https://github.com/orgs/supabase/discussions/32815)
4. **Node.js/Bun**: For building your MCP server

<iframe className="w-full aspect-video rounded-xl" src="https://www.youtube.com/embed/xua76KPhH9A" title="Deploying MCP Server to Supabase" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowFullScreen />

## Install the Supabase CLI

<CodeGroup>
  ```bash npm theme={null}
  npm install supabase --save-dev
  ```

  ```bash pnpm theme={null}
  pnpm add -D supabase
  ```

  ```bash yarn theme={null}
  yarn add -D supabase
  ```

  ```bash brew theme={null}
  brew install supabase/tap/supabase
  ```
</CodeGroup>

## Create your mcp-use project

```bash theme={null}
npx create-mcp-use-app@latest your-project-name
```

This will create a new directory called `your-project-name` with a basic MCP server setup.

## Install dependencies

```bash theme={null}
cd your-project-name
```

<CodeGroup>
  ```bash npm theme={null}
  npm install
  ```

  ```bash pnpm theme={null}
  pnpm install
  ```

  ```bash yarn theme={null}
  yarn
  ```
</CodeGroup>

## Initialize Supabase Project

### 1. Initialize the project

```bash theme={null}
supabase init
```

This will create a new directory called `supabase` with a basic Supabase project setup.

### 2. Login to Supabase

If you just installed the Supabase CLI, you'll need to login:

```bash theme={null}
supabase login
```

### 3. Link to your Supabase project

Link your local project to your Supabase project:

```bash theme={null}
supabase link --project-ref YOUR_PROJECT_REF
```

You can find your project reference ID in your [Supabase dashboard](https://supabase.com/dashboard) under Project Settings.

### 4. Start Docker

Docker must be running before deployment. Here's how to start it:

<CodeGroup>
  ```bash macOS theme={null}
  # If you have Docker Desktop installed:
  open -a Docker

  # Verify Docker is running:
  docker info
  ```

  ```bash Linux theme={null}
  # Start Docker service:
  sudo systemctl start docker

  # Verify Docker is running:
  docker info
  ```

  ```bash Windows theme={null}
  # Open Docker Desktop from Start Menu or run:
  # "C:\Program Files\Docker\Docker\Docker Desktop.exe"

  # Verify Docker is running (in PowerShell):
  docker info
  ```
</CodeGroup>

If you see "Docker is required for widgets data. Please start Docker and try again." error, make sure Docker Desktop is running and try the deployment again.

## Quick Deployment

Deploy your MCP server to Supabase in one command using our automated deployment script:

```bash theme={null}
# Download and run the deployment script (interactive mode)
curl -fsSL https://url.mcp-use.com/supabase | bash
```

Or download the script first to review it:

```bash theme={null}
# Download the script
curl -fsSL https://url.mcp-use.com/supabase -o deploy.sh
chmod +x deploy.sh

# Run with your project ID
./deploy.sh YOUR_PROJECT_ID

# Optional: specify custom function name and bucket name
./deploy.sh YOUR_PROJECT_ID my-function-name my-bucket-name
```

Done!
You can now inspect your MCP server at [https://inspector.mcp-use.com](https://inspector.mcp-use.com)

### What the script does

The deployment script automatically:

1. ✅ Validates Supabase CLI installation and authentication
2. ✅ Checks if the project is initialized and linked
3. ✅ Patches `config.toml` with your project ID
4. ✅ Builds your MCP application with the correct `MCP_URL` and `MCP_SERVER_URL`
5. ✅ Copies build artifacts to the function directory
6. ✅ Sets `MCP_URL` and `CSP_URLS` (Supabase project URL) environment variables
7. ✅ Deploys the function to Supabase Edge Functions
8. ✅ Uploads widgets to the storage bucket

<Note>
  **Prerequisites for the script**

  * Supabase CLI installed (`npm install -g supabase`)
  * Project initialized (`supabase init`)
  * Logged in to Supabase (`supabase login`)
  * Project linked (`supabase link --project-ref YOUR_PROJECT_REF`)
  * Docker running (for deployment)
</Note>

For manual deployment or to understand each step in detail, continue reading below.

## Manual Deployment

### Setting Up Your MCP Server for Supabase

### 1. Initialize a Supabase Project

If you don't have a Supabase project yet:

```bash theme={null}
supabase init
```

Then login to Supabase:

```bash theme={null}
supabase login
```

And link to your Supabase project:

```bash theme={null}
supabase link --project-ref YOUR_PROJECT_REF
```

### 2. Create an Edge Function

```bash theme={null}
supabase functions new mcp-server
```

This creates a new function at `supabase/functions/mcp-server/`.

### 3. Adapt your MCP Server to use Deno (required for Supabase Edge Functions)

Widgets in the resources folder are automatically registered. Additional widgets can be registered manually. (see [UI Widgets](/typescript/server/mcp-apps))

<Note>
  **Complete Example**

  A full working example is available in the repository: [Supabase Example](https://github.com/mcp-use/mcp-use/tree/main/libraries/typescript/packages/mcp-use/examples/server/supabase)
</Note>

```typescript theme={null}
// supabase/functions/mcp-server/index.ts

import { MCPServer } from "https://esm.sh/mcp-use@latest/server";

const PROJECT_REF = Deno.env.get("SUPABASE_PROJECT_REF") || "your-project-ref";
const BASE_URL =
  Deno.env.get("MCP_URL") ||
  `https://${PROJECT_REF}.supabase.co/functions/v1/mcp-server`;

// Create the mcp-use MCP server instance
const server = new MCPServer({
  name: "test-app",
  version: "1.0.0",
  description:
    "MCP server with automatic UI widget registration deployed on Supabase",
  baseUrl: BASE_URL,
});

// Define your tools
import { text } from 'mcp-use/server';

server.tool({
  name: "get-my-city",
  description: "Get my city",
  cb: async () => {
    return text(`My city is San Francisco`);
  },
});
await server.listen();
```

### 4. Widgets assets

Widget assets should be served from a CDN, for example Supabase Storage.
Upload the <ins>**content**</ins> of the dist/resources/widgets folder to Supabase Storage and set the MCP\_URL environment variable to the URL of the dist folder.

E.g if you created a bucket called "widgets" in Supabase Storage:

```bash theme={null}
# UPLOAD
supabase storage cp -r dist/resources/widgets ss://widgets/ --experimental
```

and then set the environment variables for Supabase deployments:

```bash theme={null}
# MCP_URL: Where widget assets (JS/CSS) are stored
export MCP_URL="https://YOUR_PROJECT_REF.supabase.co/storage/v1/object/public/widgets"

# MCP_SERVER_URL: Where the MCP server runs (for API calls in widgets)
export MCP_SERVER_URL="https://YOUR_PROJECT_REF.supabase.co/functions/v1/YOUR_FUNCTION_NAME"

# CSP_URLS: Supabase project URL (for Content Security Policy). See [Content Security Policy](../content-security-policy) for full CSP docs.
export CSP_URLS="https://YOUR_PROJECT_REF.supabase.co"
```

<Note>
  **URLs Required**: Supabase deployments need these URLs because widget files are served from static storage while API calls go to the edge function:

  * `MCP_URL`: Where widget assets are stored
  * `MCP_SERVER_URL`: Enables build-time URL injection for static deployments
  * `CSP_URLS`: Whitelists the Supabase project domain in the Content Security Policy (use base URL without path)
</Note>

### 5. Build the mcp-use app

```bash theme={null}
echo $MCP_URL
# should output: https://YOUR_PROJECT_REF.supabase.co/storage/v1/object/public/widgets
echo $MCP_SERVER_URL
# should output: https://YOUR_PROJECT_REF.supabase.co/functions/v1/YOUR_FUNCTION_NAME
```

<CodeGroup>
  ```bash npm theme={null}
  npm run build
  ```

  ```bash pnpm theme={null}
  pnpm build
  ```

  ```bash yarn theme={null}
  yarn build
  ```
</CodeGroup>

### 6. Copy the dist folder to the function directory

```bash theme={null}
cp -r dist supabase/functions/mcp-server/
```

### 7. Configure the function in config.toml

```toml theme={null}
[functions.mcp-server]
...
static_files = [ "./functions/mcp-server/dist/**/*.html", "./functions/mcp-server/dist/mcp-use.json" ]
...
```

### 8. Set Environment Variables for CSP

Set environment variables **before deploying** so the MCP server can configure Content Security Policy (CSP) to allow widgets to make API calls and load assets:

```bash theme={null}
# MCP_URL: Server URL for API calls
supabase secrets set MCP_URL="https://YOUR_PROJECT_REF.supabase.co/functions/v1/mcp-server" --project-ref YOUR_PROJECT_REF

# CSP_URLS: Supabase project URL (without path) to allow storage and function access
supabase secrets set CSP_URLS="https://YOUR_PROJECT_REF.supabase.co" --project-ref YOUR_PROJECT_REF
```

<Note>
  **Environment Variables:**

  * `MCP_URL`: Whitelists the edge function domain for API calls from widgets
  * `CSP_URLS`: Whitelists the Supabase project URL (without path) for widget assets (JS/CSS) and storage access. Use the base project URL like `https://nnpumlykjksvxivhywwo.supabase.co` (no `/storage/*` or other paths needed). Supports comma-separated values for multiple domains.

  **Important**: Set these before deploying the function. If you set them after deployment, you must redeploy for the changes to take effect.

  **Alternative**: You can also configure CSP per-widget in your widget's `appsSdkMetadata['openai/widgetCSP']` instead of using the global `CSP_URLS` environment variable. See [Content Security Policy](../content-security-policy) or [UI Widgets](/typescript/server/mcp-apps#apps-sdk-metadata) for examples.
</Note>

### 9. Deploy the Function

```bash theme={null}
supabase functions deploy mcp-server --use-docker
```

## Using the MCP Server

You can connect to the MCP Server from any MCP client. Below are examples for browser and Node.js using the `mcp-use` library.

### The MCP Server URL

```typescript theme={null}
// From your application
//const mcpUrl = `https://YOUR_PROJECT_ID.supabase.co/functions/v1/FUNCTION_NAME/mcp`;
// e.g. if your function name is "mcp-server" as above
const mcpUrl = `https://YOUR_PROJECT_ID.supabase.co/functions/v1/mcp-server/mcp`;
```

### Browser/Client-Side Usage

```typescript theme={null}
import { BrowserMCPClient } from "mcp-use";

const client = new BrowserMCPClient({
  mcpServers: {
    supabase: {
      url: `https://YOUR_PROJECT_ID.supabase.co/functions/v1/mcp-server/mcp`,
      transport: "http",
      headers: {
        Authorization: `Bearer ${SUPABASE_ANON_KEY}`,
        "Content-Type": "application/json",
        Accept: "application/json, text/event-stream",
      },
    },
  },
});

// Create a session and initialize
const session = await client.createSession("supabase");
await session.initialize();

// Now use the session to call tools, access resources, etc.
const response = await session.connector.callTool("greet", { name: "World" });
```

#### Node.js Usage

```typescript theme={null}
import { MCPClient } from "mcp-use";

const client = new MCPClient({
  mcpServers: {
    supabase: {
      url: `https://YOUR_PROJECT_ID.supabase.co/functions/v1/mcp-server/mcp`,
      transport: "http",
      headers: {
        Authorization: `Bearer ${SUPABASE_ANON_KEY}`,
        "Content-Type": "application/json",
        Accept: "application/json, text/event-stream",
      },
    },
  },
});

// Create a session and initialize
const session = await client.createSession("supabase");
await session.initialize();

// Now use the session to call tools, access resources, etc.
const response = await session.connector.callTool("greet", { name: "World" });
```

<Warning>
  **Important: Docker Required for Static Files**

  Static files configured in `static_files` are **only bundled when Docker is running** during deployment. This applies to both local development and production deployment.

  When deploying with `supabase functions deploy`, use the --use-docker flag.

  ```bash theme={null}
  docker info  # Verify Docker is running
  supabase functions deploy mcp-server --use-docker
  ```

  See the [Supabase static files documentation](https://github.com/orgs/supabase/discussions/32815) for more details.
</Warning>

### CORS Issues

* Ensure your CORS headers are correctly configured
* Check that the Accept header is included in requests
* Verify your Authorization header has the correct token

### "Initialising login role..." Appears Multiple Times

During deployment, you'll see `Initialising login role...` appear 2-3 times. This is **normal behavior** - the Supabase CLI authenticates separately for:

1. Project linking
2. Widget file upload to storage
3. Public file upload to storage

Each storage operation requires its own authentication.

### Deployment Stuck on "Initialising login role..."

If the deployment script **hangs** at `Initialising login role...` (no progress for several minutes) or you see authentication errors, Supabase may have temporarily banned your IP address. This is a [known issue tracked on GitHub](https://github.com/supabase/cli/issues/4419).

**Solution:**

1. Go to your database settings: `https://supabase.com/dashboard/project/{PROJECT_ID}/database/settings#banned-ips`
2. Check if your IP is listed under "Banned IPs"
3. Click "Unban" to restore access
4. Retry the deployment

<Note>
  This typically happens after multiple failed connection attempts or when the connection is interrupted unexpectedly. The ban is temporary and automatic.
</Note>

## Troubleshooting

### Zod "custom" is not a function error

If you encounter an error like `TypeError: e.custom is not a function` when deploying to Deno/Supabase using `esm.sh` imports, it is likely due to a version conflict between Zod v3 (required by `@modelcontextprotocol/sdk`) and Zod v4.

**Solution:**

Use `npm:` specifiers in your `deno.json` import map instead of `esm.sh` URLs for dependencies. Deno's npm compatibility layer handles peer dependencies better than esm.sh bundling in this case.

Recommended `deno.json`:

```json theme={null}
{
  "imports": {
    "mcp-use/": "npm:mcp-use@latest/",
    "zod": "npm:zod@^4.2.0"
  }
}
```

If you must use `esm.sh`, you need to manually map conflicting Zod versions:

```json theme={null}
{
  "imports": {
    "mcp-use/server": "https://esm.sh/mcp-use@latest/server?external=zod",
    "mcp-use/client": "https://esm.sh/mcp-use@latest/client?external=zod",
    "zod": "https://esm.sh/zod@3.24.4",
    "zod/v3": "https://esm.sh/zod@3.24.4",
    "zod/v4": "https://esm.sh/zod@4.2.0",
    "zod/v4-mini": "https://esm.sh/zod@4.2.0"
  }
}
```

## Learn More

* [Supabase Edge Functions Documentation](https://supabase.com/docs/guides/functions)
* [Deno Documentation](https://docs.deno.com/)
* [MCP Documentation](https://modelcontextprotocol.io)
* [mcp-use Documentation](/typescript/getting-started)
