SuperAPI AI 工具集

convex-mcp

编程与开发

查看项目

更新于 10-28 16:47

技能介绍

用途

@convex-dev/mcp 用于把 Convex 应用变成带内置 OAuth 的远程 MCP 服务器。用户在智能体中粘贴形如 https://<deployment>.convex.site/mcp 的地址,在同意页登录应用后,智能体即可调用对应用户数据执行操作的工具。组件负责协议与认证,开发者负责设计工具面,让智能体能正确使用应用。

主要能力与工作流

  1. 理解应用:阅读 convex/schema.ts、公开函数与认证配置,明确用户身份(如 getAuthUserId、Clerk tokenIdentifier)、核心对象、用户最常做的 5–10 件事,以及现有所有权校验方式。
  2. 先设计工具面再写代码:参考 references/tool-design.md,给出表格(工具名、一句话描述、参数、读/写、scope、annotations),并说明有意省略的内容及原因,取得用户确认。
  3. 安装接线:用应用自身包管理器(npm i / pnpm add / yarn add / bun add,匹配锁文件)安装 @convex-dev/mcp,配置 app.use(mcp)、convex/mcp.ts、http.ts、/connect 同意页,以及设置中的“已连接智能体”区域。
  4. 在内部函数上实现工具,参数包含 MCP 用户(args: { user: vMcpUser(v.id("users")), … }),在事务内用与 UI 相同的访问辅助函数鉴权,并由连接 scope 收窄权限(只读 scope 即查看者)。不得在未经校验的情况下信任模型传入的 ID。
  5. 验证:在测试中加入 expect(mcp.lint()).toEqual([]),运行 npx convex dev --once 与类型检查,再通过真实端点用 api key 调用 tools/list 及每个工具一次,修正模型可能误读的描述。

接线要点(代码示例)

convex/convex.config.ts 中导入 @convex-dev/mcp/convex.config.js 并调用 app.use(mcp);应用本身不得设置 httpPrefix。

convex/mcp.ts 中通过 createTool<Id<"users">>() 创建工具,用 McpServer 配置 name、title、version、instructions、consentUrl(显式设置,如 MCP_CONSENT_URL 环境变量,不要从既有 SITE_URL 变量推导而未确认其含义)、scopes 与 tools。示例工具 search_documents 声明 description、args、returns、annotations(readOnlyHint: true)、scope(docs:read)与 handler,handler 调用 ctx.runQuery(internal.documents.searchForMcp, { user, ...args }),传入完整 user 以便访问辅助函数感知连接 scope。

导出 mcp.api({ getUserId: getAuthUserId }) 得到 getAuthRequest、authorize、listConnections、revokeConnection、createApiKey;用 mcp.internalApi() 得到 createApiKeyForUser 供 CLI 与测试使用。在 convex/http.ts 中调用 mcp.registerRoutes(http),注册 /mcp、/mcp/oauth/、/.well-known/。

getUserId 必须返回稳定且唯一的用户 ID:用户表 ID(Convex Auth 的 getAuthUserId)或 identity.tokenIdentifier;不可单独使用 identity.subject(多 issuer 场景)或邮箱。工具处理器运行在 HTTP action 中,没有 ctx.auth 身份,身份仅通过 user.userId 传入,需以它调用内部函数。

两个 URL 不要混淆

consentUrl:前端同意页地址(如 https://app.example.com/connect),需显式设置。siteUrl:Convex HTTP action 的公开源,即用户粘贴的 MCP 服务器地址,默认取 CONVEX_SITE_URL,自定义域名时需设置。

同意页与设置

/connect?request=…:未登录先登录并回到同一 URL;展示 getAuthRequest(客户端名、scopes、重定向主机);Allow/Deny 调用 authorize({ requestId, approve }) 后 window.location.assign(redirectUrl);redirectUrl 为 null 表示设备流程,提示可返回智能体。kind: "device" 的请求还需展示 userCode 并要求勾选“与我的智能体匹配”,作为 userCode 传给 authorize(不匹配的设备批准会被拒绝);无 ?request= 时提供代码输入框(findAuthRequest)。

防止点击劫持:优先由托管方返回 Content-Security-Policy: frame-ancestors 'none'(vercel.json、Netlify/Cloudflare _headers、Next headers())。无法按路由设置响应头的托管环境(Convex 静态托管、静态导出)还应拒绝在框架内渲染批准 UI,例如 if (window.top !== window.self) return <p>Open this page directly.</p>。

为返回对象的工具添加 returns,结果会按其校验,也能阻止未列出的字段泄露给智能体。设置页展示 MCP URL、listConnections 与“断开连接”(revokeConnection),以及“创建 API 密钥”(createApiKey,仅显示一次),供 CLI 智能体使用:claude mcp add --transport http acme <url> --header "Authorization: Bearer <key>"。包的 example/ 目录是完整参考(待办应用、同意页、连接 UI、example/e2e.mjs 端到端脚本)。

验证方法

可用 npx convex run mcp:createApiKeyForUser '{"userId":"<getUserId 返回的 id>"}' 为测试用户免 UI 生成密钥,再以 curl 请求 $CONVEX_SITE_URL/mcp 调用 tools/list。userId 即 getUserId 返回值(Convex Auth 为 users 表 ID,可用 npx convex data users --limit 1 查看),优先于 --identity 方式。对每个工具用真实参数调用一次,再用非法 ID 调用一次(应得到 isError 结果而非崩溃)。

跨用户检查(凡接收 ID 的工具均必须):创建第二个用户及其数据和密钥,用第二个用户的密钥传第一个用户的有效 ID 调用每个工具,所有调用必须失败或返回空,绝不能返回他人数据;格式错误或不存在的 ID 不能证明隔离有效。也应为该检查编写 convex-test 测试(@convex-dev/mcp/test + t.fetch("/mcp", …),见 example/convex/mcp.test.ts)。完整 OAuth 检查可把 MCP Inspector(npx @modelcontextprotocol/inspector)或 Claude 连接到该 URL。

禁止事项

不得把 userId、ownerId、未校验的 orgId 或邮箱作为工具参数决定操作谁的数据;未经用户明确要求,不得把内部 admin 函数、跨用户查询或计费 mutation 暴露为工具;不得返回带内部字段(令牌、哈希、_creationTime 噪声)的整份文档,结果应按模型需要裁剪;不要 1:1 镜像每个 query/mutation。

适用场景与限制

适用于基于 Convex 的应用希望向 Claude、ChatGPT、Cursor 等智能体开放受控数据操作能力的场景。其前提是应用已有认证体系与所有权校验逻辑,且开发者需自行完成工具设计与安全验证。资料未提供该组件的收费、价格、平台兼容范围或性能指标等信息。