呱呱聚合
← 返回基因库
大模型应用

在 Netlify 上用 Function 搭建自己的…

当需要把自己的应用/API 以 MCP 工具形式暴露给 Claude、Cursor 等 AI 客户端,并部署在 Netlify 上时使用。

被复用0 次
复用有效—
置信度55%
沉淀时间2026-09-23
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
来自 jonas.ding 的小呱沉淀
GDI C 38/100

进化评分(GDI)

综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」

内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 59/100 ×0.15

适用场景

在 Netlify 上用 Functio特定

解决思路

  1. 先分清两种“Netlify MCP”:Netlify 官方托管的 MCP 服务器是让 AI 操作 Netlify 平台(建项目、触发部署、管理环境变量),你不需要写它;本技能讲的是另一种——用 Netlify Function 写你自己的 MCP 服务器,暴露你自己应用的工具和数据。
  2. 确定部署形态:可以是只做 MCP 端点的独立仓库,也可以是加在现有站点上的一个额外 function;若加在现有应用上,让工具调用与 UI/REST 路由相同的 service/data 层,避免逻辑重复。
  3. 构建前先决定鉴权模型:只有你自己用(单用户)就用单一共享密钥;多人各自以自己身份操作就用基于 Netlify Identity 的按用户 API key。不确定时先用共享密钥,之后再叠加按用户密钥。
  4. 安装依赖:npm install @modelcontextprotocol/sdk zod。
  5. 使用官方 MCP SDK 的 Web 标准 Streamable HTTP transport(WebStandardStreamableHTTPServerTransport),在 Netlify Function 中无状态运行;不要用 Node 版 StreamableHTTPServerTransport 加 fetch-to-node 桥接,Netlify 上不需要。
  6. 在 netlify/functions/mcp.ts 中实现:用 McpServer 构建服务器,用 server.tool(name, description, zod schema, handler) 定义工具,handler 返回 { content: [...] }。
  7. 在 handler 中先做鉴权(checkBearer 失败返回 401),再拒绝非 POST 方法(返回 405)——GET 会让 transport 打开永不关闭的 SSE 流,在 serverless 上会得到 502。
  8. 每个请求新建 server 和 transport,使用 sessionIdGenerator: undefined 和 enableJsonResponse: true,然后 await server.connect(transport) 并 return transport.handleRequest(req)。
  9. 导出 config:export const config: Config = { path: "/mcp" }。
  10. 注意 transport 会对 Accept 头不同时包含 application/json 和 text/event-stream 的 POST 返回 HTTP 406——这是 MCP 规范要求客户端满足的,406 应改客户端 Accept 头,而不是改服务器。
  11. 浏览器端客户端才需要 CORS:Netlify Functions 不会自动加 CORS 头,且服务器对非 POST(含 OPTIONS 预检)返回 405。原生 MCP 客户端(Claude Code、Cursor、Claude Desktop、mcp-remote)不是浏览器,不需要 CORS。
  12. 若客户端在浏览器中跨域调用,在 405 检查之前处理 OPTIONS 预检,返回 204 并带上 Access-Control-Allow-Origin、Access-Control-Allow-Methods(含 POST)、Access-Control-Allow-Headers(含 Authorization、Content-Type、Mcp-Session-Id),并在 POST 响应上也回显这些头。
  13. 工具定义:每个工具包含 name、一行 description、zod 输入 schema 和返回 { content: [...] } 的 handler;description 和参数的 .describe() 是模型唯一能看到的信息,要像给 agent 写 API 文档一样写清楚用途、何时使用、以及不可逆操作。
  14. 工具变多时,每个工具单独一个模块并在 buildServer() 中注册;也可维护 { name, description, inputSchema, handler } 注册表,统一接 tools/list 和 tools/call。
  15. 鉴权:每个请求带 Authorization: Bearer <token>,否则返回 401。单用户共享密钥用 netlify/lib/mcp/bearer.ts 中的 checkBearer,用 node:crypto 的 timingSafeEqual 做常量时间比较,先比较长度(timingSafeEqual 对不等长 buffer 会抛 RangeError),用 openssl rand -hex 32 生成 token 并作为 secret 环境变量存储。
  16. 多用户按用户 API key:用 Netlify Identity 让每个用户在 Web UI 生成自己的 key,只存 key 的哈希(绝不存明文)并关联用户,每次请求把 key 解析为用户并传入工具 handler,使工具以正确用户身份执行。
  17. 权限先简单后复杂:最简单模型是 all-or-nothing(有效 key 可以以所属用户身份调用所有工具),通常这是正确起点;有具体需求时再加按 key 的 scope(如只读 key),必要时再扩展到按工具 scope 或角色层级。
  18. 安全:只暴露完成工作所需的最小工具集,读写分离,慎重暴露破坏性工具;常见做法是完全不提供 delete 工具,把破坏性操作留在人工操作的 UI 中。
  19. 对不可逆或公开操作,在工具 description 中写明显式指令(如“先向用户展示确切文本并确认后再发布”),这是模型层面的软防护,必须配合可即时吊销 token 的真实 kill switch。
  20. 客户端凭证与后端凭证分离:客户端用 bearer/API key 认证你的服务器,你的服务器用自己的密钥认证数据库或第三方 API,绝不把后端 god-key 传给客户端。
  21. 后端凭证用最小权限(app password 或 scoped token,而非账号级凭证),以便泄露时可控可吊销。
  22. 用 zod schema 校验输入,并记录每次工具调用(console.info 会出现在 Netlify function 日志中)。
  23. 限流:在 function 的 config 导出中加 rateLimit 块(windowSize 秒,上限 180;windowLimit 每窗口最大请求数;aggregateBy 可选 ip、domain 或两者),超限默认返回 429,也可设 action: "rewrite" 和 to 路径。函数限流只能写在 function 的 config 导出中,不能写在 netlify.toml。
  24. 文件上传:不要让 agent 把文件以 base64 塞进工具调用(会撑大上下文并触发 payload 限制),而是给 agent 一个短期、单次使用的 presigned URL 去 PUT 原始字节,文件存到 Netlify Blobs,其他工具用稳定 key 引用。
  25. presigned URL 用 HMAC-SHA256 对 upload id、content-type、size、expiry 签名,密钥来自 secret 环境变量,并在常量时间内验证;签名本身就是授权,所以 PUT 不带 bearer token。上传端点要强制校验声明的 content-type 和大小并拒绝重放。
  26. 状态不跨请求存活:每个请求新建 server 和 transport,且可能落到不同或冷启动的实例,模块级内存不共享也不持久。单次使用/重放跟踪、幂等键、“已处理过此 id”防护、手工维护的按用户计数器等必须放在持久存储(Netlify Blobs 或数据库)中,按 upload/request id 做 check-and-mark。
  27. 接入客户端:Claude Code 用 claude mcp add --transport http my-mcp https://<site>.netlify.app/mcp --header "Authorization: Bearer <token>";Cursor 在 mcp.json 中加 URL 和 Authorization 头;Claude Desktop / claude.ai 加 Custom Connector(Settings → Connectors),静态 bearer 服务器可靠路径是 mcp-remote 桥接;旧版/仅 stdio 客户端用 npx mcp-remote https://<site>.netlify.app/mcp --header "Authorization: Bearer <token>"。
  28. 本地开发与部署:netlify dev 在 http://localhost:8888/mcp 提供 function;用 npx @modelcontextprotocol/inspector 通过 Streamable HTTP 加 Authorization: Bearer 头连接并列出/调用工具,或把 claude mcp add --transport http 指向 localhost。
  29. 注意 Netlify Identity 在 netlify dev 下不工作,按用户 key 鉴权必须在 deploy preview 上测试。
  30. 部署:push 到 Git,或 netlify deploy --build --prod;密钥用 netlify env:set MCP_BEARER_TOKEN <value> --secret 设置,绝不写进代码。
  31. 绝不硬编码密钥:token、API key、签名密钥都存为 Netlify 环境变量(标记为 secret)。写进源码或构建产物的 bearer token/签名密钥会触发 Netlify 的 secrets scanning 导致部署失败(即使构建本身是绿的),正确做法是移到 secret 环境变量并用 Netlify.env.get(...) 在运行时读取,若已提交则轮换 token,而不是关闭扫描器。
  32. 在 function 内用 Netlify.env.get("VAR") 读环境变量,不要用 process.env。
  33. 把 .netlify 加入 .gitignore。

适用边界 · 注意事项