文章

Cusor 轻松集成 Supabase MCP 服务

见字如面,与大家分享实践中的经验与思考。

Cursor 作为一款强大的 AI 驱动代码编辑器,已经凭借其智能代码补全和理解能力为开发者带来便利。而 Supabase 作为一个开源的 Firebase 替代品,提供了数据库、身份验证、存储等完整的后端服务。

将 Cursor 与 Supabase 通过 MCP (Model Context Protocol) 集成起来,可以让 AI 助手直接与你的 Supabase 项目进行交互,极大地提升开发效率:

  • 无需频繁切换工具,直接在编辑器中管理 Supabase 项目

  • 通过自然语言命令执行 SQL 查询和数据库操作

  • 快速获取项目配置信息,简化开发流程

  • 使用 AI 助手自动生成符合数据库结构的代码

本文将详细介绍如何在 Cursor 中配置 Supabase MCP,实现这种无缝集成,帮助开发者创建更高效的工作流程。

Supabase 与 MCP

Supabase 简介

Supabase 是一个开源的 Firebase 替代方案,它提供了构建现代应用所需的全套后端服务。与 Firebase 不同,Supabase 基于 PostgreSQL 数据库构建,这意味着你可以享受到关系型数据库的全部功能和灵活性,同时又能获得类似 Firebase 的简便开发体验。

image-20250416下午94422072

Supabase 的免费计划也可满足个人研究与学习,支持一些小型 App 的后端数据开发。

image-20250416下午94554485

核心功能

  1. Postgres 数据库:每个 Supabase 项目都是一个完整的 PostgreSQL 数据库,支持关系型数据和复杂查询,使用 SQL 进行交互。

  2. 身份验证系统:支持电子邮件/密码、OAuth、手机号码等多种登录方式,并通过行级安全性(RLS)策略保护数据。

  3. 自动生成的 API:根据数据库结构自动创建 RESTful 和 GraphQL API,无需编写额外代码。

  4. 实时订阅:通过 WebSocket 提供实时数据同步,让应用能够实时响应数据变化。

  5. 文件存储:内置的存储服务,用于上传、下载和管理各种文件。

  6. 边缘函数:允许在全球边缘节点上运行自定义代码,无需部署或扩展服务器。

  7. 向量数据库:支持 AI 应用开发,可以存储、索引和搜索向量嵌入,与 OpenAI 等模型集成。

Supabase 的开发流程

使用 Supabase 开发应用的基本流程是:

  1. 创建 Supabase 项目

  2. 设计和创建数据库表结构

  3. 配置身份验证和安全策略

  4. 使用自动生成的 API 在前端应用中访问数据

  5. 根据需要添加自定义功能和业务逻辑

Supabase 支持本地开发和云端部署,提供了完善的文档和客户端库,涵盖多种编程语言和框架,包括 JavaScript/TypeScript、React、Vue、Flutter、Swift 等。

Supabase MCP 介绍

MCP(Model Context Protocol)是 Anthropic 推出的一个协议标准,它定义了大型语言模型(LLM)与外部服务交互的统一方式。通过 MCP,AI 助手能够直接与外部服务交互,执行各种操作。

Supabase MCP 是基于此协议开发的服务器,它允许 AI 助手(如 Cursor、Claude、Windsurf 等)直接连接到你的 Supabase 项目,并执行各种操作,如:

  • 管理 Supabase 项目和组织

  • 查询和修改数据库

  • 运行 SQL 和应用迁移

  • 获取项目配置信息

  • 管理分支(实验性功能)

  • 生成 TypeScript 类型定义

Supabase MCP 充当了 AI 助手和 Supabase 之间的桥梁,使 AI 能够通过自然语言理解你的需求,并与 Supabase 进行交互。

Cursor 中实操集成 Supabase MCP

将 Supabase MCP 集成到 Cursor 中只需几个简单步骤,下面是详细的操作指南:

步骤 1:创建 Supabase 个人访问令牌

首先,你需要创建一个 Supabase 个人访问令牌(PAT):

  1. 登录 Supabase 控制台(https://app.supabase.com

  2. 点击右上角的个人资料图标,选择"Account preferences"

  3. 在左侧菜单中选择"Access Tokens"

  4. 点击"Generate New Token"

  5. 给令牌起一个描述性的名称,例如"Cursor MCP Server"

  6. 点击"Generate"并复制生成的令牌(注意:令牌只会显示一次)

image-20250416下午85531557

步骤 2:在 Cursor 中配置 MCP

  1. 打开 Cursor 编辑器

  2. 在项目根目录创建.cursor文件夹(如果尚不存在)

  3. .cursor文件夹中创建mcp.json文件

  4. mcp.json文件中添加以下配置:

{
  "mcpServers": {
    "supabase": {
      "command": "npx",
      "args": [
        "-y",
        "@supabase/mcp-server-supabase@latest",
        "--access-token",
        "<personal-access-token>"
      ]
    }
  }
}
  1. <personal-access-token>替换为你在步骤 1 中创建的实际令牌

  2. 保存文件

image-20250416下午90120697

步骤 3:验证连接

  1. 在 Cursor 中,打开设置(可以通过按 Cmd+PCtrl+P 并输入 "Cursor Settings")

  2. 导航至 MCP 设置,确认 Supabase MCP 服务器已被识别并启用

  3. 如果服务器旁边显示绿色状态指示器,则表示连接成功

image-20250416下午85815934

步骤 4:使用 MCP 功能

现在,你可以在 Cursor 聊天中使用 Supabase MCP 功能。例如,你可以:

  1. 打开 Cursor 聊天(通过按 Cmd+ICtrl+I

  2. 在聊天中输入你的 Supabase 相关问题或命令,例如 "列出我的 Supabase 项目" 或 "在我的数据库中创建一个新表"

Cursor 的 AI 助手将识别这些请求,调用 Supabase MCP 服务器,并执行相应的操作。

image-20250416下午90724898

Windows 用户注意事项

如果你使用的是 Windows 系统,你需要在配置中添加额外的命令前缀:

{
  "mcpServers": {
    "supabase": {
      "command": "cmd",
      "args": [
        "/c",
        "npx",
        "-y",
        "@supabase/mcp-server-supabase@latest",
        "--access-token",
        "<personal-access-token>"
      ]
    }
  }
}

如果你使用的是 WSL (Windows Subsystem for Linux),则配置应该是:

{
  "mcpServers": {
    "supabase": {
      "command": "wsl",
      "args": [
        "npx",
        "-y",
        "@supabase/mcp-server-supabase@latest",
        "--access-token",
        "<personal-access-token>"
      ]
    }
  }
}

确保 Node.js 在你的系统 PATH 环境变量中可用。

实用操作示例

以下是几个使用 Cursor 集成 Supabase MCP 的实际操作示例,包含了初学者可以直接使用的示例数据和SQL代码:

示例 1:列出所有 Supabase 项目

提示词

列出我所有的 Supabase 项目

AI 助手会调用 Supabase MCP 的 list_projects 工具,并返回你的项目列表,包括项目名称、ID 和状态。

image-20250416下午90712908

示例 2:创建用户管理系统的数据库表

提示词

在我的supabase项目 "today-lunch-picker" 中创建一个用户管理系统,需要以下表:
1. 用户表(users)
2. 角色表(roles)
3. 用户角色关联表(user_roles)
先在聊天框中输出以上表结构的 sql 语句,然后再执行到 supabase 当中。

AI将生成并执行类似以下的SQL

-- 创建角色表
CREATE TABLE IF NOT EXISTS public.roles (
  id SERIAL PRIMARY KEY,
  name VARCHAR(50) NOT NULL UNIQUE,
  description TEXT,
  created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
​
-- 添加默认角色
INSERT INTO public.roles (name, description) 
VALUES 
  ('admin', '管理员角色,拥有所有权限'),
  ('user', '普通用户角色,拥有基本权限');
​
-- 启用行级安全
ALTER TABLE public.roles ENABLE ROW LEVEL SECURITY;
​
-- 创建策略
CREATE POLICY "Roles are viewable by authenticated users" ON public.roles
  FOR SELECT USING (auth.role() = 'authenticated');
​
CREATE POLICY "Roles are editable by admins" ON public.roles
  FOR ALL USING (auth.role() = 'authenticated' AND EXISTS (
    SELECT 1 FROM auth.users
    WHERE auth.users.id = auth.uid() AND auth.users.raw_app_meta_data->>'role' = 'admin'
  ));
​
-- 创建用户表
CREATE TABLE IF NOT EXISTS public.users (
  id UUID PRIMARY KEY REFERENCES auth.users(id) ON DELETE CASCADE,
  username VARCHAR(100) UNIQUE,
  display_name VARCHAR(100),
  avatar_url TEXT,
  phone VARCHAR(20),
  address TEXT,
  bio TEXT,
  is_active BOOLEAN DEFAULT TRUE,
  created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
​
-- 创建触发器函数,当新用户注册时自动创建记录
CREATE OR REPLACE FUNCTION public.handle_new_user() 
RETURNS TRIGGER AS $$
BEGIN
  INSERT INTO public.users (id, username, display_name)
  VALUES (
    NEW.id, 
    NEW.email, 
    COALESCE(NEW.raw_user_meta_data->>'display_name', split_part(NEW.email, '@', 1))
  );
  RETURN NEW;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
​
-- 创建触发器
CREATE OR REPLACE TRIGGER on_auth_user_created
  AFTER INSERT ON auth.users
  FOR EACH ROW EXECUTE FUNCTION public.handle_new_user();
​
-- 启用行级安全
ALTER TABLE public.users ENABLE ROW LEVEL SECURITY;
​
-- 创建策略
CREATE POLICY "Users can view all profiles" ON public.users
  FOR SELECT USING (auth.role() = 'authenticated');
​
CREATE POLICY "Users can update their own profile" ON public.users
  FOR UPDATE USING (auth.uid() = id);
​
CREATE POLICY "Admin can update all profiles" ON public.users
  FOR ALL USING (auth.role() = 'authenticated' AND EXISTS (
    SELECT 1 FROM auth.users
    WHERE auth.users.id = auth.uid() AND auth.users.raw_app_meta_data->>'role' = 'admin'
  ));
​
-- 创建用户角色关联表
CREATE TABLE IF NOT EXISTS public.user_roles (
  id SERIAL PRIMARY KEY,
  user_id UUID REFERENCES public.users(id) ON DELETE CASCADE,
  role_id INTEGER REFERENCES public.roles(id) ON DELETE CASCADE,
  created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  UNIQUE (user_id, role_id)
);
​
-- 创建默认角色分配函数
CREATE OR REPLACE FUNCTION public.assign_default_role() 
RETURNS TRIGGER AS $$
DECLARE
  default_role_id INTEGER;
BEGIN
  -- 获取默认 'user' 角色的 ID
  SELECT id INTO default_role_id FROM public.roles WHERE name = 'user';
  
  -- 为新用户分配默认角色
  IF default_role_id IS NOT NULL THEN
    INSERT INTO public.user_roles (user_id, role_id)
    VALUES (NEW.id, default_role_id);
  END IF;
  
  RETURN NEW;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
​
-- 创建触发器
CREATE OR REPLACE TRIGGER on_public_user_created
  AFTER INSERT ON public.users
  FOR EACH ROW EXECUTE FUNCTION public.assign_default_role();
​
-- 启用行级安全
ALTER TABLE public.user_roles ENABLE ROW LEVEL SECURITY;
​
-- 创建策略
CREATE POLICY "User roles are viewable by authenticated users" ON public.user_roles
  FOR SELECT USING (auth.role() = 'authenticated');
​
CREATE POLICY "Users can manage their own roles if they're admins" ON public.user_roles
  FOR ALL USING (
    auth.role() = 'authenticated' AND 
    EXISTS (
      SELECT 1 FROM auth.users
      WHERE auth.users.id = auth.uid() AND auth.users.raw_app_meta_data->>'role' = 'admin'
    )
  );
​
-- 创建用户角色视图
CREATE OR REPLACE VIEW public.users_with_roles AS
SELECT 
  u.id,
  u.username,
  u.display_name,
  u.avatar_url,
  u.is_active,
  ARRAY_AGG(r.name) AS roles
FROM public.users u
LEFT JOIN public.user_roles ur ON u.id = ur.user_id
LEFT JOIN public.roles r ON ur.role_id = r.id
GROUP BY u.id, u.username, u.display_name, u.avatar_url, u.is_active;
​
-- 创建角色管理函数
CREATE OR REPLACE FUNCTION public.user_has_role(user_id UUID, role_name TEXT)
RETURNS BOOLEAN AS $$
BEGIN
  RETURN EXISTS (
    SELECT 1
    FROM public.user_roles ur
    JOIN public.roles r ON ur.role_id = r.id
    WHERE ur.user_id = user_has_role.user_id AND r.name = user_has_role.role_name
  );
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
​
CREATE OR REPLACE FUNCTION public.add_role_to_user(user_id UUID, role_name TEXT)
RETURNS BOOLEAN AS $$
DECLARE
  selected_role_id INTEGER;
BEGIN
  -- 检查角色是否存在
  SELECT id INTO selected_role_id FROM public.roles WHERE name = add_role_to_user.role_name;
  
  IF selected_role_id IS NULL THEN
    RAISE EXCEPTION '角色 % 不存在', add_role_to_user.role_name;
  END IF;
  
  -- 如果不存在,则为用户添加角色
  INSERT INTO public.user_roles (user_id, role_id)
  VALUES (add_role_to_user.user_id, selected_role_id)
  ON CONFLICT (user_id, role_id) DO NOTHING;
  
  RETURN TRUE;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
​
CREATE OR REPLACE FUNCTION public.remove_role_from_user(user_id UUID, role_name TEXT)
RETURNS BOOLEAN AS $$
DECLARE
  selected_role_id INTEGER;
BEGIN
  -- 检查角色是否存在
  SELECT id INTO selected_role_id FROM public.roles WHERE name = remove_role_from_user.role_name;
  
  IF selected_role_id IS NULL THEN
    RAISE EXCEPTION '角色 % 不存在', remove_role_from_user.role_name;
  END IF;
  
  -- 从用户中移除角色
  DELETE FROM public.user_roles
  WHERE user_id = remove_role_from_user.user_id AND role_id = selected_role_id;
  
  RETURN TRUE;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

等待 AI 执行完成:

image-20250416下午93411481

image-20250416下午94759012

示例 3:查询数据

提示词

查询"today-lunch-picker"项目中角色有几种?
先输出 SQL,然后执行。

AI将生成并执行类似以下的SQL

SELECT id, name, description 
FROM public.roles
ORDER BY id;

image-20250416下午93607891

高级使用技巧

只读模式

如果你希望限制 Supabase MCP 服务器仅执行读取操作,可以在命令行参数中添加 --read-only 标志:

{
  "mcpServers": {
    "supabase": {
      "command": "npx",
      "args": [
        "-y",
        "@supabase/mcp-server-supabase@latest",
        "--access-token",
        "<personal-access-token>",
        "--read-only"
      ]
    }
  }
}

这样可以防止执行写入操作,通过以只读用户身份执行所有 SQL 查询。

注意事项

  1. 明确指定项目:在向 AI 助手提问时,始终明确指定你想要操作的 Supabase 项目名称或 ID。

  2. 分步操作:对于复杂的任务,尝试将其分解为多个步骤,逐步指导 AI 助手完成。

  3. 检查生成的 SQL:对于数据库结构变更,先要求 AI 助手展示它将要执行的 SQL,然后再确认执行。同时在重要项目中建议先关闭auto-run模式,例如:

    请为"my-blog"项目生成创建文章表的SQL,但不要执行,我想先查看SQL语句
  4. 利用上下文:AI 助手会记住对话上下文,这样你可以在多个请求中引用同一个项目或表。例如:

    1. "在my-app项目中查询所有用户表的结构"
    2. "为这个表创建一个索引,以提高按电子邮件查询的性能"
  5. 组合使用工具:例如,先获取表结构,然后生成符合该结构的查询或代码:

    1. "列出my-app项目中的所有表"
    2. "基于users表生成一个TypeScript接口"
    3. "编写一个基于该接口的React组件来显示用户列表"

最后

通过 Cursor 集成 Supabase MCP,利用 AI 助手的能力快速完成 Supabase 相关任务。这种集成特别适合需要频繁与 Supabase 交互的项目,无论是原型开发阶段还是维护现有应用。但在使用时需要结合本文中提到的注意事项,避免出现乱改你的数据库和数据。

开始使用 Cursor 和 Supabase MCP 来简化你的开发工作流程吧!

Cursor 系列精选阅读

如果你对 Cursor 感兴趣,可以按学习路径浏览我的更多专题文章:

入门篇

进阶篇

设计与开发实战

工作流整合


欢迎关注我的公众号"Eric技术圈",原创技术文章第一时间推送。

License:  CC BY 4.0