基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
AIHT
内容
精选全部 AI 动态热点榜AI 日报收藏
分类
模型行业编程产品技术观点开源
更多
Agent 接入
返回首页开发者导航
AIHT
精选 / 资讯详情
8.0
热点
AI SCORE
技术实践2026-10-26 06:03

在 Next.js 中实现带鉴权的 MCP 服务

dev.to · AI#MCP#Next.js#鉴权
Editor brief · 编辑速览

教程通过 TypeScript SDK、Zod 工具参数定义及 App Router 路由,构建使用 Streamable HTTP 的 MCP 服务。实现包含 Origin 检查和 bearer token 鉴权,并以博客管理工具为案例,作者称代码已通过类型检查和运行验证。

文章思维导图
Knowledge map
拖拽缩放
AI deep read

AI 深度解读

给现有 Next.js 应用接上 MCP,不一定要再维护一套服务。作者的方案是把内容管理能力放进 App Router,通过一个经过鉴权的 HTTP 入口,让 AI 客户端调用现有业务代码。真正值得读的,是工具定义、请求隔离和权限边界怎样配合。

不过,这篇教程也有需要核对的地方:它采用的 SDK 与协议版本有明确前提,静态令牌和 OAuth 的表述存在张力,示例代码也没有覆盖作者列出的全部生产防护。可以参考架构,不能照抄后就当作完整上线方案。

为什么把 MCP 放进现有 Next.js 应用

MCP(Model Context Protocol)让 AI 应用发现并调用服务端能力。工具是可调用的函数,资源是通过 URI 读取的数据,提示词是可复用的模板。本文只实现工具,通过 JSON-RPC 接收调用。

作者的网站允许 Agent 查询、创建和发布博客、作品集。把入口放在 /api/mcp,工具就能复用页面和后台使用的 Prisma、校验逻辑与业务层;写入后,再刷新受影响的页面、站点地图和订阅源,让 Agent 发布与人工发布走同一条业务路径。

MCP 接入的价值,在于复用业务能力,同时让兼容客户端发现和调用它们。

这与 Next.js DevTools MCP 不同,后者帮助编程 Agent 检查开发服务器。这里是在应用里搭建自己的远程服务,也不要求使用 Vercel,作者的网站自托管在 Coolify。

传输方式则选 Streamable HTTP。stdio 由客户端启动本地子进程,不适合这个远程 HTTP 入口。按原文引用的 2026-07-28 协议修订,每条消息通过同一路径 POST,响应可以是 JSON,也可以是限定在当前请求内的 SSE 流;GET 流入口、协议会话、initialize 握手及 Mcp-Session-Id 均已移除。旧版 2024-11-05 的 HTTP+SSE,则在 2025-03-26 被 Streamable HTTP 替代。

这些是原文给出的版本前提,不能直接套到使用旧协议的项目。

工具定义决定模型能否正确调用

原文采用官方 TypeScript SDK v2,测试版本为 2.3.1,安装命令是 npm install @modelcontextprotocol/server zod。它将 @modelcontextprotocol/server 与旧版 @modelcontextprotocol/sdk 区分开,后者仍有 1.32.x 面向已有项目。

依赖要求是 Zod 4,即 zod ^4.2.0,导入路径为 zod/v4。使用 TypeScript 6 或更高版本时,作者要求在 tsconfig.json 的 compilerOptions 加上 "types": ["node"],因为发布的类型引用了 Buffer。

工具通过 server.registerTool(name, config, handler) 注册。其中,描述告诉模型何时调用,inputSchema 约束参数,outputSchema 配合 structuredContent 提供可校验的结构化结果。

例如,list_posts 允许按 draft、published 和最长 200 字符的搜索词过滤;create_post 要求标题为 8 至 180 字符,slug 符合 /^[a-z0-9]+(?:-[a-z0-9]+)*$/,正文至少 1 字符,并且只创建草稿。

字段上的 .describe() 也会进入客户端看到的 JSON Schema。给模型写清字段用途,比只起一个参数名更有用。参数校验失败时,按作者描述,SDK 会返回带有 isError: true 的可读结果;slug 重复这类业务错误也采用同样形式,让模型有机会修改后重试。

但示例只是内存数组:虽然接收了 content,处理函数并未保存它。它展示的是工具注册方式,不能充当完整 CMS 数据层。

另外,readOnlyHint、destructiveHint 都只是客户端提示。权限仍要由业务代码检查,工具声明只读或非破坏性,不会自动获得安全保障。

HTTP 入口接通之后,还缺哪些防护

作者将实现拆成 lib/mcp/server.ts、lib/mcp/auth.ts 和 app/api/mcp/route.ts 三个文件。请求先过 Origin 和 bearer 校验,再交给 SDK。

MCP 请求依次经过来源校验、令牌鉴权、限流和工具处理后访问数据库

下面这段负责把工具挂到 Next.js 路由,并把身份信息传给 SDK:

// app/api/mcp/route.ts
import { createMcpHandler, originValidationResponse } from "@modelcontextprotocol/server"
import { verifyBearer } from "@/lib/mcp/auth"
import { createServer } from "@/lib/mcp/server"

export const runtime = "nodejs"
export const dynamic = "force-dynamic"

const handler = createMcpHandler(() => createServer(), { responseMode: "json" })
const ALLOWED_ORIGINS = ["www.example.com", "localhost"]

async function handle(request: Request): Promise<Response> {
  const badOrigin = originValidationResponse(request, ALLOWED_ORIGINS)
  if (badOrigin) return badOrigin

  const authInfo = verifyBearer(request)
  if (!authInfo) {
    return Response.json(
      { error: { code: "UNAUTHORIZED", message: "Invalid or missing bearer token" } },
      { status: 401, headers: { "WWW-Authenticate": 'Bearer realm="mcp"' } }
    )
  }

  const response = await handler.fetch(request, { authInfo })
  const headers = new Headers(response.headers)
  headers.set("Cache-Control", "no-store")
  return new Response(response.body, { status: response.status, headers })
}

export { handle as POST }

重点看 handler.fetch(request, { authInfo }):身份已经由前面的代码验证,SDK 不替你完成令牌和 Origin 校验。

按作者说明,createMcpHandler 每次请求调用工厂,生成新的 McpServer;连接池和缓存应放在模块作用域。responseMode: "json" 固定返回 JSON,需要进度通知时可省略,让 SDK 使用 SSE。runtime = "nodejs" 则满足鉴权代码使用 node:crypto 的要求。

鉴权辅助函数读取 MCP_TOKEN,用 SHA-256 将两侧令牌变成等长摘要,再交给 timingSafeEqual 比较,避免直接比较不同长度时抛错。无 Origin 的 CLI、服务端 Agent 请求会继续进入鉴权,非法 Origin 则返回 403。

作者称在 SDK 2.3.1 上测得:缺令牌返回 401,Origin: https://evil.com 返回 403,有效令牌可取得工具列表并返回 200。接客户端前,可以先用这段命令检查入口:

curl -s https://www.example.com/api/mcp \
  -H "Authorization: Bearer $MCP_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'

重点保留 Accept 中的两种类型,原文要求客户端同时接受 JSON 与 SSE。Cursor 则在 ~/.cursor/mcp.json 的 mcpServers 中配置完整 url 和 Authorization 请求头;本地可运行 next dev,连接 http://localhost:3000/api/mcp,再用 MCP Inspector 逐个调用工具。

生产防护并未全部写进示例。作者实际采用鉴权失败每 IP 每 15 分钟 30 次、鉴权成功每 IP 每分钟 120 次的两档限流;删除要求 confirm: true,发布单独经过 publish_post,检查 SEO 字段和图片 alt。获取远程图片的工具还拒绝回环及私有地址,防止 SSRF。

部署到多实例时,共享限流可放到 Redis;serverless 则需为慢工具设置足够的 maxDuration。协议无会话,不代表业务数据和限流状态都能放进单实例内存。

我的判断

我认可工具复用现有业务层、创建默认落草稿、发布单独设门槛的设计。这些边界比让一个大工具处理所有操作更容易审查,也便于定位失败原因。

但原文有几处不能直接背书。

首先,文字说未设置令牌时返回 404,展示的代码却返回 401;文字要求所有响应 no-store,代码只在 SDK 返回后设置,Origin 和鉴权提前返回的分支没有覆盖。两处都需要补齐。

其次,作者一边推荐个人 Agent 使用静态 bearer,一边说 HTTP 鉴权必须遵循包含 Protected Resource Metadata(RFC 9728)的 OAuth 2.1 流程。这两种表述需要进一步澄清。多用户接入也不能只把 verifyBearer 换成 JWT 校验,就当作完整 OAuth 实现;发现流程、用户授权和权限范围仍需落实。

原文还提及 CVE-2026-104850,称实验中仅升级未能阻止泄漏,直到传入 expectedIssuer。这里没有完整复现材料,只能视为作者的安全提示,不能替代针对具体依赖的核验。

最后,MCP 有额外成本。作者引用另一项同数据测试:REST 的 p50 为 76 µs,MCP 为 424 µs,网站的 21 个工具占用 5,949 tokens 上下文。本文未提供完整测试条件,不能据此推广性能结论。如果调用方固定、只是执行几个确定动作,普通 REST API 仍然是合理选择。

能拿来做什么

  • 已有 Next.js 后台可以先接入 list_posts 这类只读工具,复用现有查询层,确认模型能够正确选工具、传参数后,再开放写入。
  • 给 Node 内容管理能力增加 Agent 入口时,把创建、发布、删除拆开,并在处理函数中检查权限、确认参数和发布条件。
  • 联调时先用 curl 或 MCP Inspector 检查工具列表、参数错误和业务错误,再接 Cursor,同时核对项目实际安装的 SDK 与协议版本。
  • 上线前补齐示例缺少的限流、提前返回分支的缓存头和持久化,并按个人使用或多用户接入分别落实鉴权方案。
Original source

本文由 AI 通读原文后重新编写,观点部分为站内判断,细节以原文为准,来源 dev.to · AI,原文版权归原作者所有。

阅读原文
上一篇
Forgekit 集成聊天、鉴权与 RAG 应用骨架
下一篇
给 Agent 链上支付加一道签名前检查

资讯速览

dev.to · AI · 2026-10-26 06:03

AI 评分 8.0 / 10

相关标签

#MCP#Next.js#鉴权

继续阅读

  • 用 MCP 让编程助手拆解应用功能
  • Forgekit 集成聊天、鉴权与 RAG 应用骨架
  • 给 Agent 链上支付加一道签名前检查
  • 模型评测涨分,如何排除随机波动
  • 南北阁发布 33B 开放编程模型