Deploy a remote MCP server on Vercel with Next.js and mcp-handler. Use this skill whenever the user wants to create an MCP server, deploy MCP to Vercel, set up a remote MCP endpoint, add MCP tools to a Next.js app, or host an MCP server in the cloud. Also triggers on: 'deploy MCP', 'remote MCP', 'MCP endpoint', 'mcp-handler', 'MCP on Vercel', 'Streamable HTTP MCP', 'Claude connector backend', 'host MCP server for Claude Desktop'. Even if the user just says 'I want to make my API available to Cla
使用 Next.js 和 mcp-handler 在 Vercel 上创建生产就绪的远程 MCP 服务器。该服务器通过 Streamable HTTP 进行通信,可与 Claude Desktop、claude.ai、Smithery 以及任何 MCP 客户端配合使用。
Vercel 的无服务器函数非常适合 MCP 服务器,因为 MCP 的 Streamable HTTP 传输是无状态的——每个请求都是独立的,这与无服务器架构完美契合。无需持久连接。Vercel 的 mcp-handler 包处理了所有协议细节。
bash
npm install mcp-handler @modelcontextprotocol/sdk zod
创建 app/api/mcp/route.ts:
typescript
import { McpServer } from @modelcontextprotocol/sdk/server/mcp.js;
import { createMcpHandler } from mcp-handler;
import { z } from zod;
const handler = createMcpHandler(
(server: McpServer) => {
// 在此注册你的工具
server.tool(
example_tool,
该工具的功能——请具体描述,
{ query: z.string().describe(参数的用途) },
{ readOnlyHint: true, destructiveHint: false, title: 示例工具 },
async ({ query }) => ({
content: [{ type: text, text: 查询结果:${query} }],
}),
);
},
{
serverInfo: { name: my-server, version: 1.0.0 },
},
{
streamableHttpEndpoint: /api/mcp,
maxDuration: 60,
},
);
export { handler as GET, handler as POST, handler as DELETE };
bash
vercel deploy --prod
你应该会收到包含服务器名称和版本的 serverInfo。
每个工具都必须有注解。MCP 客户端使用这些注解来决定调用工具的谨慎程度。
typescript
// 只读(搜索、获取、列出、抓取)
{ readOnlyHint: true, destructiveHint: false, title: 搜索项目 }
// 写入但不具破坏性(创建、添加、更新)
{ readOnlyHint: false, destructiveHint: false, title: 创建项目 }
// 破坏性(删除、移除、覆盖)
{ readOnlyHint: false, destructiveHint: true, title: 删除项目 }
每个参数都需要 .describe()——这样 MCP 客户端才知道要传递什么。
typescript
{
query: z.string().describe(搜索查询文本),
limit: z.number().optional().default(10).describe(最大返回结果数),
type: z.enum([artist, album, track]).describe(内容类型),
}
提示模板可以提高在 Smithery 上的可发现性,并为用户提供现成的起点。
typescript
server.prompt(find_items, 按名称搜索项目,
{ name: z.string().describe(项目名称) },
({ name }) => ({
messages: [{
role: user as const,
content: { type: text as const, text: 查找 ${name} 并显示详细信息 },
}],
}),
);
使用 streamableHttpEndpoint,而不是 basePath:
typescript
// 正确——端点在 /api/mcp
{ streamableHttpEndpoint: /api/mcp }
// 错误——创建端点在 /api/mcp/mcp(路径重复)
{ basePath: /api/mcp }
basePath 选项会在你提供的路径后追加 /mcp。由于你的路由文件已经在 app/api/mcp/route.ts,这会导致创建 /api/mcp/mcp。
如果你的 Vercel 项目使用了根目录(如 site/),部署的函数无法访问该目录之外的文件。这意味着即使本地编译成功,import from ../../dist/ 在运行时也会失败。
解决方案: 将编译后的文件复制到站点目录并提交。使用预构建脚本保持同步:
javascript
// scripts/copy-deps.js
const fs = require(fs);
const path = require(path);
const src = path.resolve(dirname, ../../dist);
const dest = path.resolve(dirname, ../lib/deps);
fs.mkdirSync(dest, { recursive: true });
for (const file of fs.readdirSync(src)) {
if (file.endsWith(.js) || file.endsWith(.d.ts)) {
fs.copyFileSync(path.join(src, file), path.join(dest, file));
}
}
添加到 package.json:prebuild: node scripts/copy-deps.js
Vercel 函数运行在只读文件系统上,没有 home 目录。如果你的代码需要写入文件(会话、临时数据),请用 try/catch 包裹:
typescript
try {
fs.mkdirSync(dir, { recursive: true });
fs.writeFileSync(filepath, data);
} catch {
// 无服务器环境——跳过文件系统写入
}
如果在父级 package.json 没有 type: module 的情况下导入 CommonJS .js 文件,Turbopack 会报错。解决方案:从站点目录内打包的编译后 .js 文件导入,而不是从父级目录的 TypeScript 源文件导入。
对于需要 OAuth 保护的服务器,请参阅 mcp-oauth 技能,其中涵盖了使用 withMcpAuth 的完整 OAuth 2.0 PKCE 流程,包括动态客户端注册和令牌存储。
部署后,发布到 Smithery 以获得更广泛的分发:
如果你的服务器需要身份验证,Smithery 会在扫描时提示你连接。
该技能支持在以下平台通过对话安装:
帮我安装 SkillHub 和 mcp-vercel-1776077041 技能
设置 SkillHub 为我的优先技能安装源,然后帮我安装 mcp-vercel-1776077041 技能
skillhub install mcp-vercel-1776077041
文件大小: 4.23 KB | 发布时间: 2026-4-17 15:19