MCP 伺服器開發:使用 Next.js 在 Vercel 上部署 SaaS
如果你在2025-2026年期間一直在構建SaaS產品,你可能已經注意到每個產品經理現在都想要「AI功能」。這沒問題。但真正的問題不是是否添加AI——而是如何給AI模型提供結構化、安全的方式存取你的應用程式資料和功能。這正是模型上下文協議(MCP)所解決的,在Vercel上部署MCP伺服器並使用Next.js已成為我見過的最實用的模式之一,適合那些想快速行動而不需要建立新基礎設施的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個伺服器) |
| 實時資料 | 輪詢或Webhook | 伺服器發送事件/串流 |
| 設置時間 | 每個客戶端需數天到數週 | 伺服器數小時,每個客戶端數分鐘 |
架構概覽: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套件(2026年初的v1.12+)包含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可以讀取的資料)。正確設計這一點可以區分AI客戶端喜歡的MCP伺服器和他們難以使用的伺服器。
設計優秀的工具
我看到最大的錯誤:工具要麼太細粒度,要麼太寬泛。如果你公開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的內建日誌Drains使這變得簡單。
成本分析:在Vercel上運行MCP伺服器
讓我們談談金錢。以下是2026年在Vercel上運行MCP伺服器的中型SaaS的現實成本分解:
| 元件 | Hobby | Pro | Enterprise |
|---|---|---|---|
| 基本計畫 | $0/月 | $20/月每個座位 | 自訂 |
| 函數呼叫(包括) | 100K | 1M | 自訂 |
| 額外呼叫 | N/A | $0.60每1M | 可協商 |
| 頻寬(包括) | 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)。Pro計畫每個座位$20是我對任何真實工作負載建議的最低。
我如何處理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包括對瞬時失敗的自動重試邏輯。在六個月的生產使用中,冷啟動從未是用戶報告的問題,對於我們的客戶。