MCP 服务器模板
MCP(Model Context Protocol)服务器模板提供了简化的框架封装,降低使用门槛,方便创建可供 Cursor 等 AI 客户端使用的工具。
技术栈
- Node.js - JavaScript 运行时
- TypeScript - 类型安全的开发
- Model Context Protocol SDK - 官方 MCP SDK
- Fastify - 快速的 Web 框架
- JWT - 认证支持
快速开始
1. 创建项目
bash
# 初始化项目
vup init my-mcp-project
cd my-mcp-project
# 添加 MCP 模板
vup add my-mcp2. 安装依赖
bash
# 安装依赖
pnpm install3. 启动开发
bash
# STDIO 模式(本地,供 Cursor 直接调用)
cd apps/my-mcp
pnpm dev
# SSE 模式(远程)
pnpm dev:remote项目结构
apps/my-mcp/
├── src/
│ ├── framework/ # 框架核心
│ │ ├── defineTool.ts # 工具定义辅助函数
│ │ ├── requireAuth.ts # 认证处理
│ │ ├── toolRegistry.ts # 工具注册表
│ │ ├── createServer.ts # 服务器创建
│ │ ├── types.ts # 类型定义
│ │ └── index.ts # 框架入口
│ ├── tools/ # 工具定义
│ │ ├── auth.ts # 认证相关工具
│ │ ├── public.ts # 公开工具(简单示例)
│ │ ├── demo.ts # 示例工具(文档搜索)
│ │ └── index.ts # 工具导出
│ └── server.ts # 服务器入口
├── public/
│ └── login.html # 登录页面
├── data/
│ └── docs.csv # 示例数据
├── package.json
└── tsconfig.json核心特性
简化 API
使用 defineTool() 一行代码定义工具:
typescript
// src/tools/my-tool.ts
import { defineTool } from '../framework';
import type { ToolContext } from '../framework';
export const my_tool = defineTool({
name: 'my_tool',
description: '我的工具描述',
inputSchema: {
properties: {
param: { type: 'string', description: '参数说明' },
},
required: ['param'],
},
requiresAuth: true, // 一行代码启用认证
handler: async (args, context: ToolContext) => {
// context.userId 已自动注入,无需手动检查
return {
content: [{ type: 'text', text: `结果: ${args.param}` }],
};
},
});自动认证
通过 requiresAuth: true 自动处理认证:
typescript
export const my_tool = defineTool({
name: 'my_tool',
requiresAuth: true, // 自动检查认证
handler: async (args, context) => {
// context.userId 已确保存在
},
});工具注册
在 src/tools/index.ts 中注册工具:
typescript
import { my_tool } from './my-tool';
export const TOOLS = [my_tool];框架 API
defineTool()
定义工具的辅助函数,自动处理认证、类型转换等。
typescript
defineTool({
name: string;
description: string;
inputSchema: {
properties: Record<string, any>;
required?: string[];
};
requiresAuth?: boolean; // 是否需要认证
handler: (args, context) => Promise<{ content: ... }>;
})requireAuth()
手动包装工具处理器,自动检查认证。
typescript
import { requireAuth } from '../framework';
const handler = requireAuth(async (args, context) => {
// 这里已确保 context.userId 存在
});setAuthConfig()
设置认证配置。
typescript
import { setAuthConfig } from '../framework';
setAuthConfig({
loginUrl: 'http://localhost:9316/login.html',
checkAuth: (context) => !!context.userId,
});createMcpServer()
创建 MCP 服务器。
typescript
import { createMcpServer, createToolRegistry } from './framework';
import { TOOLS } from './tools';
const registry = createToolRegistry();
TOOLS.forEach((tool) => registry.register(tool));
createMcpServer(
{
name: 'mcp-server',
version: '1.0.0',
mode: 'stdio', // 或 'sse'
port: 9316,
auth: {
loginUrl: 'http://localhost:9316/login.html',
checkAuth: (context) => !!context.userId,
},
},
registry
);开发模式
STDIO 模式(本地)
用于 Cursor 等 AI 客户端直接调用:
bash
pnpm devSSE 模式(远程)
用于远程服务器部署:
bash
pnpm dev:remote访问:
- MCP 端点:
http://localhost:9316/mcp - 登录页:
http://localhost:9316/login.html
工具示例
search_docs - 文档搜索工具
这是一个完整的示例工具(src/tools/demo.ts),展示如何实现一个实用的工具。
功能特性:
- 从 CSV 文件读取文档数据
- 支持按标题、内容、作者、分类搜索
- 返回格式化的搜索结果
- 可限制返回数量(默认 10 条,最大 50 条)
数据来源:
- CSV 文件:
data/docs.csv - 包含 50 条示例文档数据
- 字段:id, title, content, author, category, created_at
代码示例:
typescript
// src/tools/demo.ts
export const search_docs = defineTool({
name: 'search_docs',
description: '搜索文档库,支持按标题、内容、作者、分类搜索',
inputSchema: {
properties: {
query: { type: 'string', description: '搜索关键词' },
limit: { type: 'number', description: '返回数量限制(默认 10)' },
},
required: ['query'],
},
handler: async (args, context) => {
// 从 CSV 读取数据
const docs = loadDocs();
// 搜索并返回结果
// ...
},
});认证机制
自动认证
使用 requiresAuth: true 自动处理认证:
typescript
export const my_tool = defineTool({
name: 'my_tool',
requiresAuth: true, // 自动检查认证
handler: async (args, context) => {
// context.userId 已确保存在
},
});手动认证
使用 requireAuth() 包装处理器:
typescript
import { requireAuth } from '../framework';
const handler = requireAuth(async (args, context) => {
// 认证已通过
});认证流程
- 工具调用时,如果
requiresAuth: true,框架自动检查context.userId - 如果未认证,抛出
UrlElicitationRequiredError - Cursor 等客户端识别错误码
-32042和elicitations数组 - 客户端自动打开登录页面
- 用户登录后,客户端携带 JWT token 重新调用工具
可用脚本
json
{
"scripts": {
"dev": "tsx watch src/server.ts",
"dev:remote": "tsx watch src/server.ts --remote",
"build": "tsc",
"start": "node .output/server.js",
"start:remote": "node .output/server.js --remote"
}
}最佳实践
错误处理
typescript
try {
// 工具逻辑
} catch (error) {
return {
content: [
{
type: 'text',
text: `错误: ${error.message}`,
},
],
};
}类型安全
始终为工具参数定义正确的类型:
typescript
inputSchema: {
properties: {
query: { type: 'string', description: '搜索关键词' },
limit: { type: 'number', description: '结果限制' },
},
required: ['query'],
}工具组织
按功能组织工具:
src/tools/
├── auth.ts # 认证工具
├── database.ts # 数据库工具
├── file.ts # 文件操作
└── index.ts # 导出所有工具