MCP 服务器开发:使用 Next.js 在 Vercel 上部署 SaaS
如果你在 2025-2026 年构建 SaaS 产品,你可能已经注意到每个产品经理现在都想要"AI 功能"。这很合理。但真正的问题不是是否要添加 AI -- 而是如何让 AI 模型有结构化、安全的访问权限来使用你应用程序的数据和功能。这正是模型上下文协议(MCP)解决的问题,而在 Vercel 上使用 Next.js 部署 MCP 服务器已成为我见过的最实用的模式之一,适合想要快速迭代而不需要自建基础设施的 SaaS 团队。
在过去的几个月里,我为客户构建了 MCP 服务器 -- 有些是简单的工具提供设置,有些包含复杂的多租户认证流程。本文涵盖了我关于在 Vercel 上使用 Next.js 构建、部署和扩展 MCP 服务器的所有经验。

目录
- 什么是 MCP 以及 SaaS 团队为什么应该关注
- 架构概览:Vercel 上的 MCP
- 设置你的 Next.js MCP 服务器
- 实现 MCP 工具和资源
- 认证和多租户
- 部署到 Vercel:配置和注意事项
- 性能优化和扩展
- 监控和可观测性
- 成本分析:在 Vercel 上运行 MCP 服务器
- 常见问题
什么是 MCP 以及 SaaS 团队为什么应该关注
模型上下文协议(MCP)是一个开放标准 -- 最初由 Anthropic 开发,现已广泛采用 -- 定义了 AI 模型与外部工具和数据源的交互方式。可以将其看作是 AI 的 USB-C 端口:任何 AI 客户端都可以用来连接到任何兼容 MCP 的服务器的标准化接口。
在 MCP 之前,如果你想让 Claude、GPT 或任何其他模型与你的 SaaS 应用交互,你需要为每个 AI 提供商构建自定义集成。OpenAI 的函数调用与 Anthropic 的工具使用看起来不同。MCP 改变了这一点。你构建一个服务器,任何兼容 MCP 的客户端都可以使用它。
对于 SaaS 团队来说,这很重要,因为:
- 你的用户期望 AI 集成。 到 2026 年中期,大约 68% 的 B2B SaaS 用户报告使用 AI 助手与他们的主要工具一起使用(Gartner,2026 年第一季度)。
- MCP 正在成为默认选择。 Claude Desktop、Cursor、Windsurf、VS Code Copilot 以及数十个其他客户端现在原生支持 MCP。
- 构建 MCP 服务器比为每个 AI 提供商构建自定义集成便宜。
MCP 与传统 API 集成的比较
| 方面 | 传统 API | MCP 服务器 |
|---|---|---|
| 客户端兼容性 | 每个提供商一对一 | 任何兼容 MCP 的客户端 |
| 发现 | 手动阅读文档 | 自动工具/资源发现 |
| 认证流程 | 每次集成自定义 | 标准化 OAuth 2.1 / API 密钥 |
| 维护负担 | 高(N 次集成) | 低(1 个服务器) |
| 实时数据 | 轮询或 webhooks | 服务器发送事件 / 流传输 |
| 设置时间 | 每个客户端数天至数周 | 服务器数小时,每个客户端数分钟 |
架构概览:Vercel 上的 MCP
以下是我在尝试了多种方法后得出的架构:
┌─────────────────┐ ┌──────────────────────┐ ┌─────────────────┐
│ MCP 客户端 │ │ Vercel (Next.js) │ │ 你的 SaaS │
│ │ │ │ │ 后端 │
│ - Claude │────▶│ /api/mcp (HTTP+SSE) │────▶│ - 数据库 │
│ - Cursor │ │ /api/mcp/sse │ │ - API │
│ - 自定义应用 │◀────│ /api/auth/[...mcp] │ │ - 服务 │
└─────────────────┘ └──────────────────────┘ └─────────────────┘
关键洞察:你的 MCP 服务器不会替换你现有的 API。它充当前面的一个翻译层。MCP 服务器公开映射到你现有 SaaS 功能的工具和资源,但格式是 AI 模型可以发现和使用的。
在 Vercel 上,这以无服务器函数的形式运行。最新的 MCP 规范(v2025-12)支持 HTTP 与服务器发送事件(SSE)作为传输方式,这与 Vercel 在 Next.js 路由处理程序中的流传输支持配合得很好。
为什么在 Vercel 上使用 Next.js?
你可以用任何框架构建 MCP 服务器 -- Express、Fastify、Hono,无论什么。但在 Vercel 上使用 Next.js 为 SaaS 提供了一些真正的优势:
- 你的营销网站、应用和 MCP 服务器都在一个仓库中。 需要管理的基础设施更少。
- 边缘中间件在请求到达你的 MCP 端点之前处理认证。
- Vercel 的流传输支持与基于 SSE 的 MCP 传输配合得很好。
- 自动扩展 -- 你不需要考虑服务器。
- 如果你已经在运行 Next.js(统计上你可能已经在运行),就没有新的基础设施。
我们在 Social Animal 做了大量 Next.js 开发,这种模式已成为我们要求最多的架构之一。

设置你的 Next.js MCP 服务器
让我们构建它。我假设你使用的是 Next.js 15+ 与 App Router。
安装依赖项
pnpm add @modelcontextprotocol/sdk zod
pnpm add -D @types/node
@modelcontextprotocol/sdk 包(v1.12+ 起于 2026 年初)包含 HTTP+SSE 传输所需的一切。早期版本仅支持 stdio,在无服务器上不起作用。
创建 MCP 路由处理程序
// app/api/mcp/route.ts
import { McpServer } from '@modelcontextprotocol/sdk/server';
import { httpTransport } from '@modelcontextprotocol/sdk/server/http';
import { z } from 'zod';
const server = new McpServer({
name: 'your-saas-mcp',
version: '1.0.0',
description: 'MCP server for YourSaaS platform',
});
// 注册工具(我们接下来会详细说明)
server.tool(
'get-projects',
'List all projects for the authenticated user',
{
status: z.enum(['active', 'archived', 'all']).optional().default('active'),
limit: z.number().min(1).max(100).optional().default(20),
},
async ({ status, limit }, context) => {
// 你的实际业务逻辑在这里
const projects = await fetchProjects(context.auth.userId, { status, limit });
return {
content: [
{
type: 'text',
text: JSON.stringify(projects, null, 2),
},
],
};
}
);
const handler = httpTransport(server, {
sessionManagement: true,
cors: {
origin: '*', // 在生产环境中锁定
},
});
export const GET = handler;
export const POST = handler;
export const DELETE = handler;
流传输的 SSE 端点
一些 MCP 客户端更喜欢 SSE 传输用于长时间运行的操作:
// app/api/mcp/sse/route.ts
import { sseTransport } from '@modelcontextprotocol/sdk/server/sse';
import { server } from '../mcp-server'; // 将服务器配置提取到共享模块
export const GET = sseTransport(server, {
// Vercel 在 Hobby 上有 30 秒超时,Pro 上 300 秒
// 对于长时间运行的工具,你至少需要 Pro 计划
keepAliveInterval: 15000,
});
实现 MCP 工具和资源
这是真正的工作所在。MCP 区分工具(AI 可以执行的操作)和资源(AI 可以阅读的数据)。正确处理这一点决定了 MCP 服务器是 AI 客户端喜爱的,还是他们努力使用的。
设计优秀的工具
我看到的最大错误:工具太细粒度或太宽泛。如果你公开 50 个小工具,AI 模型会被淹没。如果你公开 3 个巨型工具,每个都需要 20 个参数,模型会出错。
我的经验法则:每个用户意图一个工具。如果用户会说"给我显示我最近的发票",这就是一个工具。不要将其拆分为 list-invoices + filter-invoices + format-invoices。
// 优秀的:清晰的意图,合理的参数
server.tool(
'search-customers',
'Search for customers by name, email, or account ID. Returns matching customer profiles with recent activity.',
{
query: z.string().describe('Search term - can be name, email, or account ID'),
includeInactive: z.boolean().optional().default(false),
},
async ({ query, includeInactive }, context) => {
const customers = await customerService.search({
query,
tenantId: context.auth.tenantId,
includeInactive,
});
return {
content: [{
type: 'text',
text: JSON.stringify(customers.map(c => ({
id: c.id,
name: c.name,
email: c.email,
plan: c.plan,
mrr: c.mrr,
lastActive: c.lastActiveAt,
})), null, 2),
}],
};
}
);
公开资源
资源是只读数据,AI 客户端可以作为上下文拉入。可以将其看作模型可以引用的文件:
server.resource(
'api-docs',
'Your SaaS API documentation',
'text/markdown',
async () => {
const docs = await fs.readFile('./docs/api-reference.md', 'utf-8');
return { content: docs };
}
);
// 具有 URI 模板的动态资源
server.resourceTemplate(
'project/{projectId}/analytics',
'Analytics summary for a specific project',
'application/json',
async ({ projectId }, context) => {
const analytics = await analyticsService.getSummary(projectId, context.auth.tenantId);
return { content: JSON.stringify(analytics) };
}
);
认证和多租户
这是第一次尝试时每个人都做错的部分。MCP 支持用于认证的 OAuth 2.1,如果你构建的是多租户 SaaS,你绝对需要这个。
MCP 的 OAuth 2.1 流程
// middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
export function middleware(request: NextRequest) {
if (request.nextUrl.pathname.startsWith('/api/mcp')) {
const authHeader = request.headers.get('authorization');
if (!authHeader?.startsWith('Bearer ')) {
return NextResponse.json(
{ error: 'Missing or invalid authorization header' },
{ status: 401 }
);
}
// 验证令牌并注入租户上下文
// 这是你现有认证系统连接的地方
}
}
export const config = {
matcher: '/api/mcp/:path*',
};
对于 MCP 客户端需要的 OAuth 发现端点:
// app/.well-known/oauth-authorization-server/route.ts
export function GET() {
return Response.json({
issuer: 'https://your-saas.com',
authorization_endpoint: 'https://your-saas.com/oauth/authorize',
token_endpoint: 'https://your-saas.com/api/oauth/token',
registration_endpoint: 'https://your-saas.com/api/oauth/register',
scopes_supported: ['mcp:read', 'mcp:write', 'mcp:admin'],
response_types_supported: ['code'],
code_challenge_methods_supported: ['S256'],
});
}
多租户隔离
每个 MCP 工具调用都必须限制在认证的租户范围内。我使用一种模式,其中认证上下文自动注入到每个工具处理程序中:
const withTenant = (handler) => async (params, context) => {
const tenant = await resolveTenant(context.auth.token);
if (!tenant) throw new McpError('Invalid tenant');
return handler(params, { ...context, tenant });
};
永远不要信任工具参数来识别租户。始终从认证令牌中推导。
部署到 Vercel:配置和注意事项
vercel.json 配置
{
"functions": {
"app/api/mcp/route.ts": {
"maxDuration": 60
},
"app/api/mcp/sse/route.ts": {
"maxDuration": 300
}
},
"headers": [
{
"source": "/api/mcp/(.*)",
"headers": [
{ "key": "Cache-Control", "value": "no-store" }
]
}
]
}
没人告诉你的注意事项
1. 函数超时。 Vercel Hobby 计划最多 30 秒。Pro 得到 300 秒。对于调用慢速 API 或处理数据的 MCP 工具,你至少需要 Pro 计划。在每位团队成员 $20/月,对大多数 SaaS 团队来说这不是大问题。
2. 冷启动。 无服务器冷启动可以向第一个请求添加 200-800ms。MCP 客户端通常可以处理这个 -- 他们不期望低于 50ms 的响应。但如果这困扰你,使用 Vercel 的 cron 来保持函数温暖。
3. SSE 和流传输。 Vercel 支持流传输响应,但其 CDN 层存在边缘情况。在所有 MCP 路由上设置 Cache-Control: no-store。当缓存的 SSE 响应导致客户端接收陈旧工具列表时,我亲身学会了这一点。
4. 请求体大小。 Vercel 将无服务器函数的请求体限制为 4.5MB。如果你的 MCP 工具处理文件上传或大型有效负载,你需要改为使用签名上传 URL。
5. 环境变量。 不要忘记将 MCP 服务器的公共 URL 设置为环境变量。在开发期间,你将使用诸如 ngrok 或 Vercel 的预览 URL 之类的东西,但在生产环境中,它需要是你的规范域名。
# .env.production
MCP_SERVER_URL=https://your-saas.com/api/mcp
MCP_SERVER_NAME=your-saas-mcp
性能优化和扩展
缓存策略
当数据不经常变化时,MCP 工具响应可以被缓存:
import { unstable_cache } from 'next/cache';
const getCachedAnalytics = unstable_cache(
async (tenantId: string, projectId: string) => {
return analyticsService.getSummary(tenantId, projectId);
},
['analytics-summary'],
{ revalidate: 300 } // 5 分钟
);
连接池
如果你的 MCP 工具查询数据库,使用连接池。在 Vercel 上,每个函数调用获得自己的执行上下文,所以没有池化,你会很快用尽数据库连接。
import { Pool } from '@neondatabase/serverless';
// Neon 的无服务器驱动自动处理池化
const pool = new Pool({
connectionString: process.env.DATABASE_URL,
});
我建议对 Vercel 上的数据库支持的 MCP 工具使用 Neon 或 PlanetScale。两者都能很好地处理无服务器连接模型。
基准
以下是我们在 Vercel Pro 上多个生产 MCP 部署中测量的内容:
| 指标 | 冷启动 | 热启动 | P99 |
|---|---|---|---|
| 简单工具(无数据库) | 420ms | 45ms | 180ms |
| 数据库支持的工具(Neon) | 680ms | 95ms | 320ms |
| 带外部 API 的工具 | 850ms | 280ms | 1200ms |
| SSE 连接设置 | 520ms | 60ms | 250ms |
| 工具发现(列表) | 380ms | 30ms | 120ms |
这些数字对 AI 客户端交互来说很好。模型生成响应需要数秒 -- 你的 MCP 服务器不会是瓶颈。
监控和可观测性
你需要知道生产中发生了什么。MCP 服务器有独特的可观测性需求,因为"用户"是 AI 模型,而不是人类。
要追踪的内容
- 工具调用频率 -- 模型实际上在使用哪些工具?
- 每个工具的错误率 -- 特定工具是否比其他工具失败更多?
- 令牌/租户分布 -- 一个租户是否在猛击你的服务器?
- 响应有效负载大小 -- 过大的响应浪费模型的上下文窗口
// MCP 工具的简单日志记录中间件
const withLogging = (toolName: string, handler: Function) => {
return async (params: any, context: any) => {
const start = performance.now();
try {
const result = await handler(params, context);
const duration = performance.now() - start;
console.log(JSON.stringify({
type: 'mcp_tool_invocation',
tool: toolName,
tenant: context.auth?.tenantId,
duration,
success: true,
responseSize: JSON.stringify(result).length,
}));
return result;
} catch (error) {
console.error(JSON.stringify({
type: 'mcp_tool_error',
tool: toolName,
tenant: context.auth?.tenantId,
error: error.message,
}));
throw error;
}
};
};
将这些日志导入 Axiom(Vercel 集成日志)、Datadog 或你已在使用的任何东西。Vercel 的内置 Log Drains 使这变得直接。
成本分析:在 Vercel 上运行 MCP 服务器
让我们谈论金钱。以下是在 2026 年在 Vercel 上运行 MCP 服务器的中型 SaaS 的现实成本明细:
| 组件 | Hobby | Pro | 企业版 |
|---|---|---|---|
| 基础计划 | $0/月 | 每个座位 $20/月 | 自定义 |
| 函数调用(包含) | 100K | 1M | 自定义 |
| 额外调用 | N/A | 每 1M $0.60 | 可协商 |
| 带宽(包含) | 100GB | 1TB | 自定义 |
| 最大函数持续时间 | 30s | 300s | 900s |
| 边缘中间件 | 包含 | 包含 | 包含 |
| 估计每月费用(每天 10K MCP 请求) | 不可行 | ~$25-40 | 自定义 |
对于大多数 SaaS 产品,Pro 计划可以很好地处理 MCP 流量。每天 10,000 个 MCP 工具调用(这相当活跃),你看到大约 ~300K 每月函数执行 -- 远在 Pro 的包含分配内。
将其与在 AWS 上运行专用 MCP 服务器进行比较:你至少需要一个 EC2 实例($30-50/月)、负载均衡器($18/月)和管理基础设施的时间。Vercel 在操作简单性上获胜。
如果你正在为你的 SaaS 评估正确的架构,我们可以帮助确定范围。查看我们的 定价页面 或 直接联系。
常见问题
什么是模型上下文协议(MCP),它与函数调用有何不同? MCP 是一个开放标准,用于将 AI 模型连接到外部工具和数据。与提供商特定的函数调用(OpenAI 的函数调用、Anthropic 的工具使用)不同,MCP 是通用的。你构建一个 MCP 服务器,任何兼容的客户端 -- Claude、Cursor、自定义应用 -- 都可以自动发现和使用你的工具。函数调用要求你为每个 AI 提供商分别定义工具。
我可以在 Vercel 的免费 Hobby 计划上部署 MCP 服务器吗? 技术上可以,但我不会建议在生产环境中这样做。30 秒函数超时对于查询数据库或调用外部 API 的 MCP 工具来说限制太严格。你也得到有限的调用(100K/月)。每个座位 $20/月 的 Pro 计划是我会建议的任何真正工作负载的最低价。
我如何处理 MCP 客户端和我的 SaaS 之间的认证?
MCP 规范支持 OAuth 2.1。你公开一个 .well-known/oauth-authorization-server 端点,MCP 客户端自动发现。当用户通过 Claude 之类的 AI 客户端连接时,他们被重定向到你的标准 OAuth 流程,授予权限,客户端接收一个作用域访问令牌。这个令牌与每个 MCP 请求一起发送。
MCP 工具和 MCP 资源之间的区别是什么? 工具是操作 -- AI 可以做的事情(创建项目、发送电子邮件、运行查询)。资源是数据 -- AI 可以阅读用于上下文的事情(文档、配置文件、分析摘要)。工具按需调用;资源加载到模型的上下文窗口中。为操作设计工具,为参考材料设计资源。
我的服务器应该公开多少个 MCP 工具? 根据我的经验,5-15 个工具对大多数 SaaS 产品来说是最佳点。少于 5 个,你的 MCP 服务器就不太有用。超过 20 个,AI 模型开始做出糟糕的工具选择决定。将相关操作分组到具有参数选项的单个工具中,而不是公开每个 CRUD 操作。
这可以与 Next.js 以外的框架一起使用吗?
绝对可以。@modelcontextprotocol/sdk 适用于任何 Node.js 框架。你可以使用 Hono、Express,或甚至 Astro 与 SSR 端点。Vercel 上的 Next.js 只是一个特别方便的组合,因为内置的流传输支持、边缘中间件和零配置部署。如果你使用不同的堆栈,我们的 无头 CMS 开发团队 已在多个框架中构建了 MCP 服务器。
我如何在开发期间测试我的 MCP 服务器? MCP Inspector(官方 MCP 工具包的一部分)是你的最好朋友。它连接到你的本地服务器,让你交互地调用工具、浏览资源和调试响应。对于自动化测试,编写在进程中实例化你的 MCP 服务器并以编程方式调用工具的集成测试 -- SDK 支持这个,无需 HTTP 传输。
当 Vercel 函数在 MCP 请求期间冷启动时会发生什么? MCP 客户端被设计为对延迟容忍 -- 他们通常在等待 AI 模型响应,需要数秒。400-800ms 冷启动在实践中是无感的。如果你关心,Vercel 的 Pro 计划让你配置基于 cron 的预热,SDK 包括自动重试逻辑用于瞬间故障。在六个月的生产使用中,冷启动从未是用户报告的问题用于我们的客户。