使用说明
MCP注册表
用于发现、共享和管理模型上下文协议(MCP)服务器和工具的生产质量web应用程序。
技术栈
- 框架:Next.js 15,带应用路由器
- 语言:TypeScript
- 样式:顺风CSS
- 数据库/身份验证:Supabase(Postgres+Auth)
- 部署:Vercel
- 程序包管理器:pnpm
先决条件
- Node.js 18.17.0或更高版本
- pnpm 9.x(
npm install -g pnpm) - Docker(用于本地Supabase)
- Supabase命令行界面(
npm install -g supabase)
地方发展设置
1.克隆存储库
git clone https://github.com/your-org/mcp-registry.git
cd mcp-registry
2.安装依赖项
pnpm install
3.启动本地数据库
本地开发使用在Docker中运行的Supabase:
# Start Supabase (requires Docker)
pnpm supabase:start
# Apply migrations and seed data
pnpm supabase:db:reset
# Generate TypeScript types
pnpm supabase:types
启动后,Supabase将输出本地URL和密钥。在你的 .env.local:
NEXT_PUBLIC_SUPABASE_URL=http://127.0.0.1:54321
NEXT_PUBLIC_SUPABASE_ANON_KEY=<anon-key-from-supabase-start-output>
本地Supabase服务:
- 工作室: http://localhost:54323(数据库管理UI)
- API: http://localhost:54321
- Inbucket: http://localhost:54324(电子邮件测试-在此处查看魔术链接!)
- 每日公报postgresql://postgres:postgres@本地主机:54322/postgres
4.设置第一个管理员用户
启动本地Supabase后:
- 启动开发服务器:
pnpm dev - 首选http://localhost:3000/signin
- 输入您的电子邮件并查看Inbucket(http://localhost:54324)对于魔术链接
- 单击魔术链接登录
- 开放式Supabase工作室(http://localhost:54323)
- 转到表编辑器→ 个人资料
- 查找您的用户行并更改
role从user到admin
或者,使用SQL:
-- Replace with your actual user ID from auth.users table
UPDATE public.profiles
SET role = 'admin'
WHERE id = '<your-user-id>';
5.启动开发服务器
pnpm dev
打开 http://localhost:3000 在您的浏览器中。
提交和审核工作流程
对于用户
- 登录 通过
/signin使用电子邮件魔术链接 - 提交 新的MCP服务器
/submit- 填写必填字段:slug、name、description、transport、auth
- 可选择添加URL、标签和功能
- 轨道 你的意见书在
/my/submissions- 查看状态:待定、已批准或已拒绝
- 请参阅管理员审核说明
对于管理员
- 访问
/admin/submissions(需要管理员角色) - 审查待提交的文件:
- 单击展开并查看完整详细信息
- 批准:将服务器发布到
/servers - 拒绝:必须提供原因(提交者可见)
- 显示以前审查过的提交文件以供参考
安全模型
- RLS(行级安全):所有数据访问都在数据库级别进行控制
- 管理员验证:除了RLS(深度防御)之外的服务器端检查
- 浏览器中没有服务角色:所有管理员操作都使用经过身份验证的用户上下文
- 魔术链接认证:无密码存储,电子邮件自动验证
可用脚本
| 命令 | 描述 |
|---|---|
pnpm dev |
启动开发服务器 |
pnpm build |
为生产而建 |
pnpm start |
启动生产服务器 |
pnpm lint |
运行ESLint |
pnpm lint:fix |
运行ESLint并自动修复 |
pnpm format |
使用Prettier格式化代码 |
pnpm format:check |
检查代码格式 |
pnpm typecheck |
运行TypeScript类型检查 |
pnpm test |
运行单元测试(Vitest) |
pnpm test:watch |
在监视模式下运行测试 |
pnpm test:coverage |
运行覆盖率测试 |
pnpm test:e2e |
运行E2E测试(剧作家) |
pnpm test:e2e:ui |
使用UI运行E2E测试 |
pnpm test:e2e:security |
运行以安全为重点的E2E烟雾测试 |
pnpm test:e2e:heuristics |
运行产品启发式缺口检测 |
pnpm perf:report |
生成性能趋势+回归报告 |
pnpm product:backlog |
根据差距报告生成降价积压 |
pnpm audit:sha <sha> |
对提交进行隔离的完整代理B审计 |
pnpm security:deps |
审核CVE的生产依赖关系 |
pnpm security:test |
运行依赖性审计+安全E2E测试 |
pnpm supabase:start |
启动本地Supabase(Docker) |
pnpm supabase:stop |
停止本地Supabase |
pnpm supabase:status |
检查本地数据库状态 |
pnpm supabase:db:reset |
重置本地数据库(应用迁移+种子) |
pnpm supabase:db:push |
将迁移推送到远程 |
pnpm supabase:types |
生成TypeScript类型 |
项目结构
mcp-registry/
├── app/ # Next.js App Router pages
│ ├── api/health/ # Health check endpoint
│ ├── auth/callback/ # Magic link auth callback
│ ├── signin/ # Sign in page
│ ├── submit/ # Submit new server form
│ ├── my/submissions/ # User's submission list
│ ├── admin/submissions/ # Admin moderation page
│ ├── servers/ # Browse MCP servers
│ │ ├── page.tsx # Server list with filters
│ │ └── [slug]/ # Server detail page
│ ├── layout.tsx # Root layout
│ ├── page.tsx # Homepage
│ └── globals.css # Global styles
├── components/ # React components
│ ├── header.tsx # Site header with auth state
│ ├── footer.tsx # Site footer
│ └── auth-buttons.tsx # Auth-aware navigation
├── lib/ # Utility libraries
│ └── supabase/ # Supabase client utilities
│ ├── client.ts # Browser client
│ ├── server.ts # Server client
│ ├── database.types.ts # Generated types
│ └── types.ts # Type helpers
├── supabase/ # Supabase CLI
│ ├── config.toml # Local config
│ ├── migrations/ # SQL migrations
│ └── seed.sql # Dev seed data
├── __tests__/ # Unit tests (Vitest)
├── e2e/ # E2E tests (Playwright)
├── middleware.ts # Auth session refresh
└── .github/workflows/ # GitHub Actions CI
数据库模式
表格
mcp服务器 -已发布的MCP服务器
id,slug,name,description,homepage_url,repo_url,docs_urltags,transport,auth,capabilities,verifiedcreated_at,updated_at
个人资料 -带有角色的用户配置文件
id(引用auth.users)role(“用户”或“管理员”)created_at
mcp_server_提交 -用户提交等待审核
id,submitted_by,status,submitted_payloadreview_notes,reviewed_at,reviewed_bycreated_at
RLS政策
- mcp服务器:公共读取,仅管理员插入
- 个人资料:用户自行阅读/更新,管理员全部阅读
- 提交:用户拥有CRUD,管理员读取/更新所有
环境变量
| 变量 | 必填 | 描述 |
|---|---|---|
NEXT_PUBLIC_SUPABASE_URL |
是 | 您的Supabase项目URL |
NEXT_PUBLIC_SUPABASE_ANON_KEY |
是 | 支持匿名/公钥 |
SUPABASE_SERVICE_ROLE_KEY |
否* | 服务角色密钥(仅限服务器,用于引导) |
ADMIN_BOOTSTRAP_TOKEN |
否* | 一次性引导身份验证令牌 |
ADMIN_BOOTSTRAP_EMAIL |
否* | 引导的第一个管理员的电子邮件 |
*仅在初始管理员引导时需要。可以在引导完成后删除。
重要:前缀为的变量 NEXT_PUBLIC_ 暴露在浏览器中。切勿在这些变量中隐藏秘密。
数据库和迁移
本地开发(使用Docker)
# Start local Supabase (requires Docker)
pnpm supabase:start
# Apply migrations and seed data
pnpm supabase:db:reset
# Generate TypeScript types from local schema
pnpm supabase:types
# Stop local Supabase
pnpm supabase:stop
远程开发(无Docker)
如果你没有Docker,直接连接到远程Supabase项目:
# Link to remote project (one-time setup)
supabase link --project-ref <your-project-ref>
# Push migrations to remote
pnpm supabase:db:push
# Generate types from remote
supabase gen types typescript --linked > lib/supabase/database.types.ts
创建迁移
# Create a new migration
supabase migration new <migration_name>
# Edit the migration file in supabase/migrations/
# Apply locally
pnpm supabase:db:reset
# Push to remote when ready
pnpm supabase:db:push
迁移不变性规则
重要:一旦迁移被提交到git或应用于任何环境(本地、暂存、生产),就不得对其进行修改。这对于数据库的一致性至关重要。
如果您需要更改应用程序迁移中的某些内容:
- 不要 编辑现有迁移文件
- 做 创建进行必要更改的新迁移
- 新的迁移应该是累加的(ALTER、CREATE或REPLACE等)
示例-修复函数:
# Wrong: Editing 20260101_create_function.sql after it was applied
# Correct: Create a new migration
supabase migration new fix_function_xyz
# Then add ALTER/CREATE OR REPLACE statements in the new file
这确保了:
- 所有环境都可以一致地重播迁移
supabase db reset从头开始工作- 本地、临时和生产数据库之间没有漂移
连接到生产数据库
1.创建一个Supabase项目
- 首选 网站 supabase.com 并创建一个新项目
- 等待项目配置
2.获取您的证书
- 首选 项目设置 → API
- 复制 项目Url →
NEXT_PUBLIC_SUPABASE_URL - 复制 匿名公众 key →
NEXT_PUBLIC_SUPABASE_ANON_KEY
3.推动迁移
supabase link --project-ref <your-project-ref>
supabase db push
4.设置第一管理员(生产)
使用一次性引导端点(推荐):
# 1. Set environment variables in Vercel:
# - SUPABASE_SERVICE_ROLE_KEY (from Supabase Dashboard → Settings → API)
# - ADMIN_BOOTSTRAP_TOKEN (generate a random string)
# - ADMIN_BOOTSTRAP_EMAIL (your email address)
# 2. Sign up first by visiting /signin and clicking the magic link
# 3. Call the bootstrap endpoint
curl -X POST https://your-app.vercel.app/api/admin/bootstrap \
-H "Content-Type: application/json" \
-H "x-bootstrap-token: YOUR_ADMIN_BOOTSTRAP_TOKEN" \
-d '{"email": "your-email@example.com"}'
# Expected response: {"success":true,"message":"Admin bootstrap completed","userId":"..."}
引导端点为:
- 一次性:首次成功使用后自动禁用
- 安全:需要匹配的令牌和电子邮件
- 频率限制:防止暴力攻击
- 已审核:将操作记录到audit_log表中
替代方案(手动SQL):
-- In Supabase SQL Editor
-- First, find your user ID after signing in
SELECT id, email FROM auth.users;
-- Then update their profile
UPDATE public.profiles
SET role = 'admin'
WHERE id = '<your-user-id>';
在Vercel上部署
自动部署
- 将代码推送到GitHub
- 将项目导入 维塞尔
- 在Vercel仪表板中配置环境变量
- 部署!
Vercel中的环境变量
在Vercel项目设置中添加以下内容:
NEXT_PUBLIC_SUPABASE_URLNEXT_PUBLIC_SUPABASE_ANON_KEY
测试
单元测试(Vitest)
# Run all tests
pnpm test
# Watch mode
pnpm test:watch
# With coverage
pnpm test:coverage
E2E测试(剧作家)
# Run E2E tests
pnpm test:e2e
# Interactive UI mode
pnpm test:e2e:ui
# Install browsers (first time)
pnpm exec playwright install
产品测试(测试正向开发)
该项目使用测试正向开发方法,有两种类型的产品测试:
产品规格测试(必须通过)
e2e/product-spec.spec.ts -定义产品合同。这些测试验证:
- 页面结构:每个公共页面都有
<main>地标只有一个<h1>以及跳过链接 - 导航:标题包含浏览、文档、API、变更日志、关于链接
- 页脚:包含关于、文档、API、验证、变更日志、贡献、隐私、条款的链接
- Footer链接健康状况:页脚链接解析,不返回4xx/5xx
- 元数据要素:存在页面标题和元描述
- 控制台错误:任何页面上都没有JavaScript错误
- 链接完整性:所有内部链接都能正确解析(上限为60个链接)
- 关键旅程:发现流程、带建议的搜索、验证透明度
# Run product spec tests only
pnpm exec playwright test product-spec
# Run with verbose output
pnpm exec playwright test product-spec --reporter=list
产品库存(无门控)
e2e/product-inventory.spec.ts -在不阻塞CI的情况下生成产品库存+差距报告。
每个公共页面的集合:
- URL、HTTP状态、页面标题、h1文本
- 内部/外部链接计数
- UI功能标志:面包屑、空状态、代码块、表、表单
- A11y快速检查:地标、跳转链接、标题导航
- 元数据存在检查(描述和Open Graph基础知识)
- 链接验证+衍生产品差距总结
输出:
e2e/reports/product-inventory.jsone2e/reports/product-gaps.json
# Run inventory + gap report generation
pnpm test:e2e:inventory
# View the generated reports
cat e2e/reports/product-inventory.json | jq '.summary'
cat e2e/reports/product-gaps.json | jq '.notes'
库存报告结构:
{
"generatedAt": "2026-02-14T...",
"pageCount": 12,
"totalInternalLinks": 45,
"pages": [
{
"url": "/servers",
"name": "Browse Servers",
"status": 200,
"h1Text": "MCP Server Registry",
"internalLinkCount": 15,
"hasBreadcrumbs": false,
"hasCodeBlock": false,
"a11y": { "hasMainLandmark": true, "hasH1": true, ... }
}
],
"summary": {
"pagesWithErrors": 0,
"pagesWithoutH1": 0,
"pagesWithCodeBlocks": 3
}
}
产品启发式(无门控)
e2e/product-heuristics.spec.ts -在所有公共路由上运行UX/内容差距检测。
每页启发式检查:
- 结构:正好一个
<h1>标题 - 主要行动:清除CTA按钮或主要内容中的突出链接
- 导航:下一步链接超出页眉/页脚(死端检测)
- 内容有用性:代码块,docs/api/about/等所需的部分。
- 信任可发现性:链接/验证(如适用)
- 摩擦旗:“即将推出”块,禁用控件
- 性能健全:DOM内容加载时间阈值
- 转换启发式:CTA存在、CTA层次结构、社会证明、CTA附近的信任、搜索匹配突出显示和长页面上的分段CTA
输出:
e2e/reports/product-heuristics.jsone2e/screenshots/product-heuristics/<route>/<theme>/<viewport>.png(关于失败)e2e/reports/product-gaps.json包括合并heuristicGaps.conversion[]针对以转换为重点的问题
严重性评分标准:
- 关键的:阻碍核心旅程或在关键页面上造成混淆
- 高:严重损害信任/转化
- 中等:波兰语/可用性问题
- 低:轻微一致性
# Run heuristics + merge into gap report
pnpm test:e2e:heuristics
# View heuristics summary
cat e2e/reports/product-heuristics.json | jq '.summary'
产品待办列表生成
在运行库存和启发式测试后,生成一个有优先级的降价待办事项列表:
# Generate backlog from gap report
pnpm product:backlog
product:backlog 以本地开发依赖关系运行 tsx (没有 npx fetch),因此之后它是离线安全的 pnpm install.
这创造了 docs/product-backlog.md 与:
- 按严重程度汇总所有差距
- 关键问题及全部细节
- 高/中/低优先级表
- 工作量估算(S/M/L)
- 建议修复
- 证据和截图路径
规范工作流程:
# 1. Run heuristics first (source of heuristic gaps)
pnpm test:e2e:heuristics
# 2. Run inventory (derives report + preserves merged heuristicGaps)
pnpm test:e2e:inventory
# 3. Validate deterministic merged report shape
pnpm exec playwright test e2e/product-gaps.spec.ts
# 4. Generate markdown backlog from canonical report
pnpm product:backlog
# 5. Review the backlog
cat docs/product-backlog.md
性能趋势(无门控)
e2e/perf-trends.spec.ts 在关键路线上捕获轻量级性能遥测数据:
/,/servers,/servers/github,/docs,/api,/verification- 导航定时代理:
ttfbMs,domContentLoadedMs,loadEventEndMs - 喷漆时间:
fcpMs(可用时) - 资源配置文件:JS/CSS请求计数,总资源计数
- 转账估算:
totalTransferredBytesApprox从响应标头
输出:
e2e/reports/perf-trends.jsone2e/reports/perf-regressions.json- 预算来源:
docs/perf-budgets.json
回归检测规则:
- 政策:
budget_only_trends_informational(配置于docs/perf-budgets.json) - 只有当当前指标超过路线/默认预算时,才会记录回归
- 基线趋势增量(>15%)仍被计算为信息性警告
- 默认情况下无门控(用于产品智能和冲刺计划)
# Run perf trend capture only
pnpm test:e2e:perf-trends
# Compare current trends vs last committed baseline
pnpm perf:compare
# Generate all perf outputs (smoke + trends + regressions)
pnpm perf:report
独立SHA审计
对干净提交状态运行完整的Agent B系统审核:
pnpm audit:sha <sha>
这有什么作用:
- 在分离的HEAD模式下检查目标提交
- 跑动
git clean -xfd强制执行干净的工作空间 - 安装依赖项
pnpm install --frozen-lockfile - 跑:
pnpm exec playwright test e2e/product-spec.spec.tspnpm test:e2e:heuristicspnpm test:e2e:inventorypnpm perf:reportpnpm product:backlog
该脚本在执行前需要一个干净的工作树,并在执行后恢复原始引用。
在本地验证所有内容
# Full local validation workflow
pnpm supabase:start
pnpm supabase:db:reset
pnpm supabase:types
pnpm dev &
pnpm test
pnpm test:e2e
Git挂钩
此项目使用Husky作为Git钩子:
- 预承诺:运行lint stage(ESLint+对stage文件进行预处理)
运行时会自动安装挂钩 pnpm install.
CI/CD
GitHub Actions在每个推送和拉取请求上运行:
- 棉绒和类型检查:ESLint、TypeScript、Prettier
- 单元测试:Vitest
- 构建:Next.js生产构建
- E2E测试:剧作家
许可证
麻省理工学院
