惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

T
Threat Research - Cisco Blogs
量子位
L
LINUX DO - 热门话题
Jina AI
Jina AI
J
Java Code Geeks
U
Unit 42
V
Vulnerabilities – Threatpost
The Hacker News
The Hacker News
Blog — PlanetScale
Blog — PlanetScale
博客园 - 聂微东
WordPress大学
WordPress大学
D
Docker
T
The Exploit Database - CXSecurity.com
博客园 - Franky
Project Zero
Project Zero
F
Full Disclosure
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
NISL@THU
NISL@THU
D
Darknet – Hacking Tools, Hacker News & Cyber Security
MongoDB | Blog
MongoDB | Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
B
Blog
Simon Willison's Weblog
Simon Willison's Weblog
月光博客
月光博客
V
Visual Studio Blog
腾讯CDC
The Cloudflare Blog
V
V2EX
C
Cybersecurity and Infrastructure Security Agency CISA
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Security Latest
Security Latest
博客园 - 三生石上(FineUI控件)
Know Your Adversary
Know Your Adversary
I
Intezer
S
Securelist
A
Arctic Wolf
小众软件
小众软件
P
Privacy International News Feed
Spread Privacy
Spread Privacy
The GitHub Blog
The GitHub Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Cyberwarzone
Cyberwarzone
T
Tailwind CSS Blog
Latest news
Latest news
H
Help Net Security
S
Schneier on Security
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
P
Proofpoint News Feed
Scott Helme
Scott Helme
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org

Supabase Blog

AI Agents Know About Supabase. They Don't Always Use It Right. Custom OIDC Providers for Supabase Auth 100,000 GitHub stars Supabase docs over SSH Navigating Regional Network Blocks Supabase Joins the Stripe Projects Developer Preview Log Drains: Now available on Pro Supabase Storage: major performance, security, and reliability updates Supabase incident on February 12, 2026 Hydra joins Supabase X / Twitter OAuth 2.0 is now available for Supabase Auth BKND joins Supabase Supabase is now an official Claude connector Supabase PrivateLink is now available Introducing: Postgres Best Practices When to use Read Replicas vs. bigger compute Introducing TRAE SOLO integration with Supabase Supabase Security Retro: 2025 Sync Stripe Data to Your Supabase Database in One Click Own Your Observability: Supabase Metrics API Introducing iceberg-js: A JavaScript Client for Apache Iceberg Introducing Supabase for Platforms Adding Async Streaming to Postgres Foreign Data Wrappers Build "Sign in with Your App" using Supabase Auth Introducing Seven New Email Templates for Supabase Auth The new Supabase power for Kiro Introducing Supabase ETL Introducing Analytics Buckets Introducing Vector Buckets Snap, Inc. Launches Snap Cloud, Powered by Supabase Triplit joins Supabase Supabase Series E 1000 Y Combinator Founders Choose Supabase gm 👋 web3, welcome aboard to Sign in with Web3 (Solana, Ethereum) Announcing the Supabase Remote MCP Server Enterprise speed, enterprise standards with Bolt Cloud + Supabase PostgREST 13 Lovable Cloud + Supabase: The Default Platform for AI Builders Processing large jobs with Edge Functions, Cron, and Queues Defense in Depth for MCP Servers OrioleDB Patent: now freely available to the Postgres community Supabase Launch Week 15 Hackathon Winner Announcement The Vibe Coder's Guide to Supabase Environments Testing for Vibe Coders: From Zero to Production Confidence The Vibe Coding Master Checklist Vibe Coding: Best Practices for Prompting Supabase Auth: Build vs. Buy Top 10 Launches of Launch Week 15 Supabase Launch Week 15 Hackathon Storage: 10x Larger Uploads, 3x Cheaper Cached Egress, and 2x Egress Quota Persistent Storage and 97% Faster Cold Starts for Edge Functions Algolia Connector for Supabase New Observability Features in Supabase Improved Security Controls and A New Home for Security Introducing Branching 2.0 Stripe-To-Postgres Sync Engine as standalone Library Supabase Analytics Buckets with Iceberg Support Create a Supabase backend using Figma Make Introducing JWT Signing Keys Supabase UI: Platform Kit Build a Personalized AI Assistant with Postgres Announcing Multigres: Vitess for Postgres Building on open table formats Open Data Standards: Postgres, OTel, and Iceberg Simplifying back-end complexity with Supabase Data APIs PostgreSQL Event Triggers without superuser access Top 10 Launches of Launch Week 14 Supabase MCP Server Data API Routes to Nearest Read Replica Declarative Schemas for Simpler Database Management Realtime: Broadcast from Database Keeping Tabs on What's New in Supabase Studio Edge Functions: Deploy from the Dashboard + Deno 2.1 Automatic Embeddings in Postgres Introducing the Supabase UI Library Supabase Auth: Bring Your Own Clerk Postgres Language Server: Initial Release Migrating from Fauna to Supabase Migrating from the MongoDB Data API to Supabase Dedicated Poolers Postgres as a Graph Database: (Ab)using pgRouting AI Hackathon at Y Combinator Calendars in Postgres using Foreign Data Wrappers Supabase Launch Week 13 Hackathon Winners How to Hack the Base! Running Durable Workflows in Postgres using DBOS database.build v2: Bring-your-own-LLM Restore to a New Project Hack the Base! with Supabase Top 10 Launches of Launch Week 13 Supabase Queues High Performance Disk Supabase Cron Supabase CLI v2: Config as Code Supabase Edge Functions: Introducing Background Tasks, Ephemeral Storage, and WebSockets Supabase AI Assistant v2 OrioleDB Public Alpha Executing Dynamic JavaScript Code on Supabase with Edge Functions ClickHouse Partnership, improved Postgres Replication, and Disk Management Live Share: Connect to in-browser PGlite with any Postgres client
Building ChatGPT Apps with Supabase Edge Functions and mcp-use
Pedro Rodrigues · 2025-12-17 · via Supabase Blog

Building ChatGPT Apps with Supabase Edge Functions and mcp-use

ChatGPT is no longer just a chat app. OpenAI recently launched the Apps SDK, which turns ChatGPT into a platform where developers can build interactive applications. These apps run inside ChatGPT and can display custom interfaces, connect to databases, and perform real actions.

In this guide, you will learn how to build a ChatGPT app that connects to your Supabase database. You will use mcp-use, an open source SDK that makes it easy to deploy MCP servers on Supabase Edge Functions. By the end, you will have an app that lets ChatGPT users explore your database schema, view table data, and run SQL queries, all through interactive widgets.

ChatGPT apps extend what ChatGPT can do. Instead of just answering questions, ChatGPT can now show interactive interfaces and connect to external services.

Every ChatGPT app has two parts:

  • MCP server. This is your backend. It defines the tools and capabilities your app provides. When a user asks ChatGPT to do something, ChatGPT calls your MCP server to get the data or perform the action.
  • Web component. This is your frontend. It renders inside ChatGPT as an iframe. Your MCP server can return UI metadata that tells ChatGPT which component to display and what data to pass to it.

The MCP server and web component work together. ChatGPT acts as the bridge. When a user asks a question, ChatGPT figures out which tool to call. Your MCP server runs the tool and returns both data and UI instructions. ChatGPT then renders your component with the data.

This architecture is powerful because it separates what your app can do from how it looks. Your MCP server handles all the logic. Your components handle all the display. ChatGPT handles the conversation.

mcp-use is an open source TypeScript SDK for building MCP servers. It solves a specific problem: the official MCP SDK uses Express, which depends on Node.js features that do not work in edge environments like Supabase Edge Functions.

mcp-use uses Hono instead of Express. Hono is a lightweight web framework designed for edge runtimes. This means your MCP server can run on Supabase Edge Functions, Cloudflare Workers, and other serverless platforms.

Here is what mcp-use gives you:

  • Edge runtime support. Works on Deno, Cloudflare Workers, and Supabase Edge Functions.
  • OpenAI Apps SDK integration. Built-in support for ChatGPT app widgets and UI components.
  • Supabase Auth integration. Native support for authenticating users with Supabase Auth.
  • Full MCP compliance. Scores 100/100 on the official MCP conformance tests.

Supabase Edge Functions are a good fit for MCP servers for several reasons.

  • Everything in one place. Your database, authentication, and server code all live in the same Supabase project. Your MCP server can query your database directly. It can check user permissions using Supabase Auth. There is no need to manage separate services or configure connections between them.
  • Fast cold starts. Edge Functions run on Deno and start quickly. When ChatGPT calls your MCP server, users do not wait for a container to spin up.
  • Built-in authentication. Supabase Auth works out of the box with mcp-use. You can require users to log in before using your app. You can check their roles and permissions. You can scope data access to specific users.
  • Simple deployment. A single command deploys your MCP server. Supabase handles scaling, HTTPS, and infrastructure.

You will build a ChatGPT app that explores Supabase databases. The app provides four tools:

  • List tables. Shows all tables in your database with an interactive schema explorer widget.
  • Show table. Displays data from a specific table with sorting and filtering.
  • Execute SQL. Runs read-only SQL queries and shows results with syntax highlighting.
  • Supabase status. Shows the current status of Supabase services and recent incidents.

Each tool returns both data and a React widget. ChatGPT users see interactive interfaces, not just text responses.

This guide provides the key points for building a ChatGPT app. For the full implementation, please visit or clone the repository: github.com/mcp-use/supabase-mcp-server

Start by creating a new project with mcp-use:


_10

npx create-mcp-use-app my-supabase-app --template apps-sdk

_10

cd my-supabase-app

_10

npm install


This creates a project with everything you need: the mcp-use SDK, widget templates, and build configuration for Supabase Edge Functions.

Note: the default apps-sdk template includes a "fruit shop" demo to show how widgets work. You will need to modify or replace these files to align with the Supabase explorer tools described in this guide.

Next, initialize Supabase in your project:


_10

supabase init

_10

supabase login

_10

supabase link --project-ref YOUR_PROJECT_ID


You can find your project ID in your Supabase dashboard under Project Settings.

Open index.ts and set up your MCP server:


_10

//index.ts

_10

import { MCPServer, object, text, widget, error } from 'mcp-use/server'

_10

_10

const server = new MCPServer({

_10

name: 'supabase-explorer',

_10

version: '1.0.0',

_10

description: 'A Supabase MCP server with Apps SDK widgets',

_10

})


Widgets can be organized in two ways: single-file widgets or folder-based widgets. Choose the organization style that best fits your widget's complexity.


_10

├── index.ts # Main server file using mcp-use

_10

├── resources/ # React widget components

_10

│ ├── components/ # Reusable UI components

_10

│ ├── schema-explorer/ # Schema explorer widget (in this article)

_10

│ ├── table-viewer/ # Table viewer widget

_10

│ └── query-results/ # Query results widget

_10

│ └── supabase-status.tsx # 1 file widget

_10

└── package.json # Dependencies


See the widgets implementation here and the widget docs.

Two types of widgets#

mcp-use SDK supports two widget patterns.

  1. Display-only widgets
  2. Display and return data widgets

1. Display-only widgets#

Display-only widgets do not fetch data on the server. They receive tool parameters as props and render UI. The supabase-status (resources/supabase-status.tsx) widget works this way. It fetches status data client-side from the Supabase status API in the React component.

You don't need to register the widget as tool in index.ts because it doesn't need custom logic on the tool side, and mcp-use automatically registers all the display-only widgets in resources/ folder as MCP tools.


_65

// resources/supabase-status.tsx

_65

import { McpUseProvider, useWidget, type WidgetMetadata } from "mcp-use/react";

_65

import React, { useEffect, useState } from "react";

_65

import z from "zod/v4";

_65

import "./styles.css";

_65

_65

// Tool args that will be passed to the widget props

_65

const propSchema = z.object({

_65

daysBack: z.number().default(7).describe("Number of days back to show incidents"),

_65

});

_65

_65

// Define widget metadata - auto-generates tool

_65

export const widgetMetadata: WidgetMetadata = {

_65

description: "Display Supabase service status and recent incidents from the status page",

_65

props: propSchema,

_65

exposeAsTool: true, // Important for display-only widgets, that are auto registered

_65

annotations: { readOnlyHint: true },

_65

appsSdkMetadata: {

_65

"openai/widgetCSP": {

_65

connect_domains: ["https://status.supabase.com"],

_65

resource_domains: ["https://*.supabase.com"],

_65

},

_65

},

_65

};

_65

_65

// Your widget component

_65

const SupabaseStatusWidget: React.FC = () => {

_65

// Get props from mcp-use hook: useWidget -> Everything you need in one hook!

_65

const { props, isPending } = useWidget<z.infer<typeof propSchema>>();

_65

const [incidents, setIncidents] = useState<Incident[]>([]);

_65

_65

useEffect(() => {

_65

const fetchStatus = async () => {

_65

try {

_65

setLoading(true);

_65

const response = await fetch("https://status.supabase.com/history.rss");

_65

// ...

_65

// Fetch APIs from the widget

_65

}

_65

};

_65

fetchStatus();

_65

}, [props.daysBack]);

_65

_65

return (

_65

<McpUseProvider viewControls="fullscreen" autoSize>

_65

<Card className="relative p-6 rounded-3xl w-full">

_65

<div className="mb-6">

_65

<div className="flex items-center justify-between mb-2">

_65

<div>

_65

<h2 className="text-3xl font-bold text-[hsl(var(--foreground))] mb-1">

_65

Supabase Status

_65

</h2>

_65

<p className="text-sm text-[hsl(var(--foreground-muted))]">

_65

Last {props.daysBack} days

_65

</p>

_65

</div>

_65

</div>

_65

</div>

_65

{/* Full component implementation: https://github.com/mcp-use/supabase-mcp-server/blob/main/resources/supabase-status.tsx */}

_65

</Card>

_65

</McpUseProvider>

_65

);

_65

};

_65

_65

export default SupabaseStatusWidget;


As we defined in the widgetMetadata props daysBack, the MCP tool expects an argument specifying the number of days to retrieve incidents from the LLM.

2. Display and return data widgets#

Display and return data widgets fetch data server-side and pass it to both the LLM and the widget. The list-tables tool works this way. The server queries the database, returns data to ChatGPT for reasoning, and passes the same data to the widget for display.

This separation is useful. Sometimes you want to show the user more than you tell the LLM. Sometimes you want to tell the LLM more than you show the user. You control both independently.

You need to register the widget as a tool in index.ts. The following section goes through it.

Tools define what your app can do. Each tool has a name, parameters, and a callback function. For tools that return UI widgets, as in our case, we need to specify the widget argument and set the widget name from the component in resources/, in this case: "schema-explorer".

Here is the list-tables tool that returns the schema-explorer widget:


_44

// index.ts

_44

server.tool(

_44

{

_44

name: 'list-tables',

_44

description: 'List all tables in your Supabase database',

_44

schema: z.object({

_44

schemas: z.array(z.string()).optional().describe('Schemas to include (default: all)'),

_44

}),

_44

widget: {

_44

name: 'schema-explorer',

_44

invoking: 'Loading database tables...',

_44

invoked: 'Tables loaded successfully',

_44

},

_44

annotations: { readOnlyHint: true },

_44

},

_44

async ({ schemas }) => {

_44

try {

_44

const result = await supabaseClient?.callTool('list_tables', { schemas: ['public'] })

_44

const content = result?.content[0]

_44

let tables: any[] = []

_44

_44

if (content?.type === 'text') {

_44

const data = extractJsonFromResponse(content?.text ?? '')

_44

tables = Array.isArray(data) ? data : []

_44

}

_44

_44

return widget({

_44

// Props passed to the React component in /resources folder

_44

props: {

_44

tables,

_44

schemas: schemas || ['public'],

_44

},

_44

// Output returned by the MCP tool to the LLM (what the LLM sees)

_44

output: object({

_44

tables: tables.map((table) => ({

_44

name: table.name,

_44

})),

_44

}),

_44

})

_44

} catch (err) {

_44

return error(`Error listing tables: ${err instanceof Error ? err.message : String(err)}`)

_44

}

_44

}

_44

)


The tool queries your database for table information. It returns both text content for the LLM and widget metadata for the UI. ChatGPT uses the text content to understand the data. The widget renders in the chat for the user.

Supabase Edge Functions provide a great place to host your server. They are fast, scalable, and easy to manage.

For the complete step-by-step guide, see our Supabase deployment documentation.

Prerequisites: Docker must be running before deployment


_10

# Verify Docker is running, otherwise install it

_10

docker info


mcp-use includes a deployment script that handles everything:


_10

curl -fsSL https://url.mcp-use.com/supabase | bash


This script checks your authentication, builds your application, sets environment variables, and deploys to Supabase Edge Functions.

After deployment, your MCP server is live at:


_10

https://<YOUR_PROJECT_ID>.supabase.co/functions/v1/<YOUR_FUNCTION_NAME>/mcp


Check out the Official Developer Mode Guide to enable it in your ChatGPT profile.

To use your app in ChatGPT:

  1. Go to your ChatGPT profile settings
  2. Enable developer mode: Go to Settings → Apps & ConnectorsAdvanced → Developer mode.
  3. Click on "Create App" to add the MCP server and enter your Edge Function URL with /mcp at the end.

Open a new ChatGPT App:

  1. Click the "+" button to add a new connector
  2. Select "More" and then select the MCP Server you just added.

Now you can start a new chat and use your tools. Ask ChatGPT to list your tables, show data from a specific table, or run a SQL query. ChatGPT will call your MCP server and display the interactive widgets.

For example, with the execute-sql tool, you can ask ChatGPT to write queries, execute them, and display the results.

You now have a working ChatGPT app powered by Supabase Edge Functions. Here are some ways to extend it:

  • Add more tools that interact with your specific database tables
  • Build custom widgets for your data types
  • Implement write operations with proper authorization checks
  • Add tool chaining so ChatGPT can combine multiple operations

For more details on mcp-use, see the mcp-use documentation or the mcp-use GitHub repository. For more on Supabase Edge Functions, see the Edge Functions guide.

For the full implementation, please visit or clone the repository: github.com/mcp-use/supabase-mcp-server