使用说明
@n47vc/mcp
在几分钟内将MCP服务器部署到Vercel。构建自己的或使用附带的Gmail、Google Drive和Apollo.io服务器——所有这些服务器都具有可插拔的OAuth身份验证。
为什么存在: 从头开始构建MCP服务器意味着自己连接OAuth、令牌管理、发现端点和Vercel部署。这个包可以处理所有这些。你编写工具逻辑,其他一切都完成了。
快速开始
选项A:分叉和部署(最快)
分叉此仓库,然后:
cd app
cp .env.example .env.local # fill in your credentials
npm install
vercel deploy
看 app/.env.示例 对于所有配置选项。
选项B:安装为npm包
-
创建一个新的Next.js项目:
npx create-next-app@latest my-mcp-servers --typescript cd my-mcp-servers npm install @n47vc/mcp -
创建
pages/api/mcp/[...mcp].ts:import { createMCPApp, createGoogleAuthProvider, gmail, gdrive } from '@n47vc/mcp'; export const config = { api: { bodyParser: false } }; export default createMCPApp({ secret: process.env.MCP_SECRET!, authProvider: createGoogleAuthProvider({ clientId: process.env.GOOGLE_CLIENT_ID!, clientSecret: process.env.GOOGLE_CLIENT_SECRET!, }), servers: [gmail, gdrive], }); -
将众所周知的重写添加到
next.config.js:module.exports = { async rewrites() { return [ { source: '/.well-known/:path*', destination: '/api/mcp/well-known/:path*' }, ]; }, }; -
设置环境变量并部署:
vercel env add MCP_SECRET vercel env add GOOGLE_CLIENT_ID vercel env add GOOGLE_CLIENT_SECRET vercel deploy
构建自己的服务器
创建自定义MCP服务器是一个单独的文件。这是一个完整的模板:
// src/servers/myapi/index.ts
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
import { z } from 'zod';
import type { MCPUserContext, MCPServerDefinition } from '../../types';
// 1. Define input schemas
const SearchSchema = z.object({
query: z.string().min(1),
limit: z.number().int().positive().max(100).optional().default(10),
});
// 2. Create server factory
export function createMyApiServer(context?: MCPUserContext): Server {
const server = new Server(
{ name: 'myapi', version: '1.0.0' },
{ capabilities: { tools: {} } }
);
// 3. List available tools
server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [
{
name: 'myapi_search',
description: 'Search my API for results',
inputSchema: {
type: 'object' as const,
properties: {
query: { type: 'string' as const, description: 'Search query' },
limit: { type: 'number' as const, description: 'Max results', default: 10 },
},
required: ['query'],
},
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
},
],
}));
// 4. Handle tool calls
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
try {
switch (name) {
case 'myapi_search': {
const input = SearchSchema.parse(args);
const resp = await fetch(`https://api.example.com/search?q=${encodeURIComponent(input.query)}&limit=${input.limit}`);
const data = await resp.json();
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
}
default:
throw new Error(`Unknown tool: ${name}`);
}
} catch (error) {
return {
content: [{ type: 'text', text: JSON.stringify({ error: (error as Error).message }, null, 2) }],
isError: true,
};
}
});
return server;
}
// 5. Export the server definition
export const myapi: MCPServerDefinition = {
slug: 'myapi',
name: 'My API MCP Server',
createServer: createMyApiServer,
auth: { scopes: [] }, // Add OAuth scopes if your API needs them
};
然后将其添加到您的应用程序中:
import { createMCPApp, createGoogleAuthProvider, gmail, myapi } from '@n47vc/mcp';
export default createMCPApp({
secret: process.env.MCP_SECRET!,
authProvider: createGoogleAuthProvider({
clientId: process.env.GOOGLE_CLIENT_ID!,
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
}),
servers: [gmail, myapi],
});
就是这样。OAuth、令牌管理、PKCE和发现端点都为您处理。
生成新服务器的Claude代码提示
将此提示复制到Claude Code中,以便从任何API构建新服务器:
在此项目中构建一个新的MCP服务器。看
src/servers/apollo/index.ts作为参考实现,它是现有最简单的服务器。我的新服务器应该:
- 活在
src/servers/{name}/index.ts- 遵循完全相同的模式:Zod输入模式
create{Name}Server工厂函数、switch语句中的工具处理程序和导出的MCPServerDefinition- 使用
{name}_作为工具名称前缀- 包括与阿波罗模式匹配的正确错误处理
- 我想要包装的API是:{描述你的API,粘贴文档,或者给出一个URL}
可用服务器
| 服务器 | 导入 | 描述 | 其他环境变量 |
|---|---|---|---|
| Gmail | gmail |
阅读帖子、撰写草稿、发送电子邮件 | -- |
| 谷歌云端硬盘 | gdrive |
搜索、读取和上传文件 | -- |
| 阿波罗 | apollo |
公司丰富,人员搜索 | APOLLO_API_KEY |
有关完整的工具文档,请参阅每台服务器的README:
配置
createMCPApp(config)
| 选项 | 类型 | 必填 | 描述 |
|---|---|---|---|
secret |
string |
是 | JWT签名和令牌加密的秘密。生成方式 openssl rand -base64 32 |
authProvider |
AuthProviderConfig |
是 | OAuth提供者(见下文) |
servers |
MCPServerDefinition[] |
是 | 要启用的MCP服务器阵列 |
baseUrl |
string |
否 | 覆盖自动检测到的基本URL |
allowedDomain |
string |
否 | 仅限于来自此域的电子邮件(例如。, 'mycompany.com') |
onToolCall |
function |
否 | 钩子在工具执行之前被触发。返回a CallToolResult 阻止执行。 |
onToolComplete |
function |
否 | 工具执行后钩子被触发。返回a CallToolResult 以覆盖响应。 |
onAuthGranted |
function |
否 | 每当生成访问令牌时都会触发Hook——第一次OAuth授权和每次后续刷新。接收 { email, name, refresh_token?, scopes }。可用于持久化提供程序刷新令牌。会记录错误,但不会导致身份验证失败。 |
tokenLifetimes |
object |
否 | 覆盖令牌生命周期(accessToken, refreshToken, authCode --jose持续时间字符串如下 '1h', '90d', '5m') |
createGoogleAuthProvider(options)
| 选项 | 类型 | 必填 | 描述 |
|---|---|---|---|
clientId |
string |
是 | 谷歌OAuth客户端ID |
clientSecret |
string |
是 | 谷歌OAuth客户端密码 |
allowedDomain |
string |
否 | 限制Google登录到此域 |
所有服务器都通过Google OAuth(openid+电子邮件+个人资料)对用户进行身份验证。需要额外API作用域(例如Gmail、Drive)的服务器在其 MCPServerDefinition.auth.scopes --不需要单独的作用域配置。
谷歌云控制台设置
- 首选 谷歌云控制台
- 创建新项目(或使用现有项目)
- 启用所需的API:
- Gmail API --如果使用Gmail服务器
- Google Drive API --如果使用Google Drive服务器
- 谷歌文档API --如果使用Google Drive服务器
- 谷歌网页API --如果使用Google Drive服务器
- 谷歌幻灯片API --如果使用Google Drive服务器
- 首选 凭证 > 创建凭据 > OAuth 2.0客户端ID
- 应用程序类型: 网络应用程序
- 添加授权重定向URI:
https://your-domain.com/api/mcp/oauth/callback - 将客户端ID和客户端密钥复制到环境变量中
身份验证提供者接口
要添加新的身份验证提供者(例如Microsoft、GitHub),请实现 AuthProviderConfig 接口:
interface AuthProviderConfig {
id: string;
name: string;
getAuthorizationUrl(callbackUrl: string, state: string, scopes: string[]): string;
exchangeCode(code: string, callbackUrl: string): Promise<AuthProviderTokens>;
refreshAccessToken(refreshToken: string): Promise<{ access_token: string } | undefined>;
getBaseScopes(): string[];
}
建筑
- 无状态 --每个请求都会创建一个新的MCP服务器实例。没有会话存储。
- 基于JWT的代币 --访问令牌(1h)和刷新令牌(90d)是使用AES-256-GCM加密的提供者令牌签名的JWT。不需要数据库。
- PKCE --OAuth授权代码流,带有用于代码交换的证明密钥。
- 批准文号8414/9728 --用于自动客户端配置的标准OAuth发现端点。
已知限制
- 身份验证码是可重放的 --授权码是无状态的JWT,因此同一代码可以在5分钟的到期窗口内多次交换。RFC 6749要求使用一次性身份验证码,但强制执行此要求需要服务器端存储。PKCE验证降低了风险,因为只有原始客户端拥有
code_verifier.
许可证
麻省理工学院