使用说明
MCP演示服务器
模型上下文协议(MCP)服务器实现,演示TypeScript中的生产就绪模式。 四种并行实现 比较裸金属和框架方法。
概述
该项目展示了MCP服务器的实现,包括:
- 三种核心模式:计算(计算)、API集成(天气)、文件系统访问
- 四种实施方式:裸金属、FastMCP、EasyMCP*、mcp框架
- 框架比较:MCP开发方法的现实评估
*注意:由于npm包(v0.0.0-developing)不稳定,EasyMCP实现可能无法运行。
- 企业模式:所有实现都证明了安全性、可观察性和可靠性
- 双重运输:Stdio用于桌面应用程序,HTTP/SSE用于远程访问
快速开始
先决条件
- Node.js 20+
- pnpm 8+
- OpenWeatherMap API密钥(免费层:https://openweathermap.org/api)
安装
# Clone and install
git clone <repository-url>
cd mcp-demo
pnpm install
# Configure
cp .env.example .env
# Edit .env and add your WEATHER_API_KEY
与Claude Code一起使用
# Build the server
pnpm build
# Add to Claude Code
claude mcp add demo-server node -- $(pwd)/dist/servers/bare-metal/index.js
# Verify connection
claude mcp list
手动测试(HTTP模式)
# Development
TRANSPORT_MODE=http pnpm dev
# Production
pnpm build
TRANSPORT_MODE=http pnpm start
备注:对于Claude Code(stdio模式),您不需要手动运行服务器,它会自动启动!
建筑
高级设计
┌─────────────┐
│ Client │
└──────┬──────┘
│
┌──────▼───────────────────┐
│ Transport Layer │
│ • Stdio (stdin/stdout) │
│ • HTTP/SSE (Express) │
└──────┬───────────────────┘
│
┌──────▼───────────────┐
│ Middleware Pipeline │
│ • Auth │
│ • Rate Limiting │
│ • Logging/Tracing │
│ • Metrics │
└──────┬───────────────┘
│
┌──────▼────────────┐
│ Message Router │
│ • tools/list │
│ • tools/call │
│ • resources/list │
│ • resources/read │
└──────┬────────────┘
│
┌──────▼──────────────────┐
│ Handler Registries │
│ • ToolRegistry │
│ • ResourceRegistry │
└──────┬──────────────────┘
│
┌──────▼────────────────────┐
│ Capability Handlers │
│ • CalculateTool │
│ • WeatherTool │
│ • FileResourceHandler │
└───────────────────────────┘
处理器模式
所有功能都实现了一个通用接口:
interface CapabilityHandler<TParams, TResult> {
validate(input: unknown): ValidationResult<TParams>;
execute(params: TParams, context: ExecutionContext): Promise<Result<TResult>>;
handleError(error: Error): MCPError;
}
这消除了重复,使添加新功能变得简单:
- 实现接口
- 在适当的注册表中注册
- 完成-自动路由和运输工作
框架比较
该项目包括 四种并行实现 相同的MCP服务器功能,允许您比较方法:
| 实现 | 代码行 | 模式 | 最适合 |
|---|---|---|---|
裸机 (/servers/bare-metal) |
~2000 | 直接MCP SDK | 学习MCP内部,完全控制,自定义需求 |
FastMCP (/servers/fastmcp-impl) |
~420 | 生成器API | 生产应用程序,类似于表达式的熟悉程度 |
EasyMCP (/servers/easymcp-impl) ⚠️ |
~400 | 装饰师 | 快速原型制作,最小化样板(包装不稳定) |
mcp框架 (/servers/mcp-framework-impl) |
~455 | 自动发现 | 具有多种功能的大型项目 |
⚠️ EasyMCP实现可能无法运行- easy-mcp npm包在v0.0.0开发中破坏了导出
特征矩阵
| 功能 | 裸金属 | FastMCP | EasyMCP | mcp框架 |
|---|---|---|---|---|
| 运输:stdio | ✓ | ✓ | ✓ | ✓ |
| 传输:HTTP/SSE | ✓ | ✓ | ✗ | ✓ |
| 输入验证 | 手动Zod | Zod模式 | 类型推理 | Zod+助手 |
| 自动发现 | ✗ | ✗ | ✗ | ✓ (from /tools) |
| 类型安全性 | 手动 | 基于模式 | 装饰推理 | MCPInput<this> |
| 设置复杂性 | 高 | 中 | 低 | 中 |
| 样板文件 | 高 | 低 | 最小 | 低-中 |
| 框架依赖性 | 无 | FastMCP | EasyMCP | mcp框架 |
| 学习曲线 | 陡峭 | 温和 | 温和 | 中等 |
代码比较:添加工具
裸机 (必须实现完整接口):
class MyTool implements CapabilityHandler {
validate(input: unknown): ValidationResult { /* ... */ }
execute(params: MyParams, ctx: ExecutionContext): Promise<Result> { /* ... */ }
handleError(error: Error): MCPError { /* ... */ }
}
// Register manually
toolRegistry.register('my_tool', new MyTool());
FastMCP (建设者模式):
server.addTool({
name: 'my_tool',
parameters: z.object({ input: z.string() }),
execute: async (args) => processInput(args.input),
});
EasyMCP (装饰师):
class MyMCP extends EasyMCP {
@Tool({ description: 'Process input' })
async myTool(input: string) {
return processInput(input);
}
}
mcp框架 (自动发现):
// In /tools/my_tool.ts
class MyTool extends MCPTool {
name = 'my_tool';
schema = defineSchema({ input: z.string().describe('Input') });
async execute(input: MCPInput<this>) {
return processInput(input.input);
}
}
export default MyTool;
// Automatically discovered - no registration needed
何时选择每种方法
在以下情况下选择裸金属:
- 学习MCP协议内部
- 需要最大程度的控制和定制
- 建造一些不寻常或实验性的东西
- 想要最小的依赖关系
- 性能优化至关重要
在以下情况下选择FastMCP:
- 快速构建生产应用程序
- 团队熟悉Express.js模式
- 需要会话管理和身份验证
- 想要一个经过验证、久经考验的框架
在以下情况下选择EasyMCP:
- ⚠️ 注: 目前不推荐-软件包存在稳定性问题
- 快速原型或MVP
- 构建简单的小型服务器
- 团队更喜欢TypeScript装饰器
- 想要绝对最小的样板
- 开发人员经验是首要任务
在以下情况下选择mcp框架:
- 构建具有多种功能的大型项目
- 想要CLI工具(
mcp validate,mcp add) - 团队更喜欢惯例而不是配置
- 可扩展性和组织性很重要
- 需要结构化的文件组织
运行实现
每个实现都在其自己的目录中 /servers:
# Bare-metal
cd servers/bare-metal
pnpm build
node dist/index.js
# FastMCP
cd servers/fastmcp-impl
npm install
npm run dev
# EasyMCP (⚠️ may not work - package unstable)
cd servers/easymcp-impl
npm install
npm run dev
# mcp-framework
cd servers/mcp-framework-impl
npm install
npm run dev
所有实现都支持相同的三种功能(计算、get_weather、文件访问)和相同的API。
能力
1.计算(计算模式)
使用安全控件计算数学表达式。
方法: tools/call
参数:
{
"name": "calculate",
"arguments": {
"expression": "2 + 2 * 10"
}
}
退货:
{
"expression": "2 + 2 * 10",
"result": 22
}
安全:表达式净化可防止代码注入。只允许使用数学运算符。
2.get_weather(API集成模式)
从OpenWeatherMap获取当前天气数据。
方法: tools/call
参数:
{
"name": "get_weather",
"arguments": {
"location": "San Francisco"
}
}
退货:
{
"location": "San Francisco, US",
"temperature": 18.5,
"conditions": "partly cloudy",
"timestamp": "2025-10-20T10:37:00Z"
}
特性:10分钟结果缓存,可配置超时,API故障的错误处理。
3.文件://资源(文件系统模式)
提供对允许目录中文件的安全读取访问。
列出资源:
{
"method": "resources/list"
}
读取资源:
{
"method": "resources/read",
"params": {
"uri": "file:///tmp/example.txt"
}
}
安全:路径遍历保护,仅限于 ALLOWED_FILE_PATHSMIME类型检测。
配置
所有配置均通过环境变量进行。看 .env.example 了解详情。
关键变量
# Transport
TRANSPORT_MODE=stdio # or "http"
HTTP_PORT=3000 # HTTP mode only
# Weather API
WEATHER_API_KEY=your_key # Required for weather tool
WEATHER_CACHE_TTL=600 # Seconds (10 min default)
# Security
ALLOWED_FILE_PATHS=/tmp # Colon-separated paths
API_KEYS=key1,key2 # HTTP mode only
RATE_LIMIT_REQUESTS=60 # Requests/min per client
# Observability
LOG_LEVEL=info # debug|info|warn|error
LOG_FORMAT=pretty # json|pretty
部署
本地开发
# Stdio mode with auto-reload
pnpm dev
# HTTP mode with auto-reload
TRANSPORT_MODE=http pnpm dev
码头工人
# Build image
docker build -t mcp-demo .
# Run container
docker run -p 3000:3000 \
-e WEATHER_API_KEY=your_key \
-e API_KEYS=your_api_key \
mcp-demo
MCP客户端集成
Claude 代码命令行界面 (推荐):
# Build the server first
pnpm build
# Add to Claude Code (stdio mode)
claude mcp add demo-server node -- /path/to/mcp-demo/dist/servers/bare-metal/index.js
# Verify it's connected
claude mcp list
# The server will auto-start when Claude Code needs it
# No need to manually run pnpm start!
克劳德桌面版 (标准版本):
{
"mcpServers": {
"demo-server": {
"command": "node",
"args": ["/path/to/mcp-demo/dist/servers/bare-metal/index.js"]
}
}
}
HTTP客户端:
curl -X POST http://localhost:3000/mcp \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your_api_key" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "calculate",
"arguments": {"expression": "2 + 2"}
}
}'
共享您的服务器
Stdio与HTTP:何时使用
标准模式 (本地,单用户):
- ✅ 个人使用Claude Code/桌面
- ✅ 安全(仅限操作系统级权限)
- ✅ 无网络暴露
- ✅ 客户端自动启动/停止
HTTP模式 (共享、多用户):
- ✅ 与其他Claude Code用户共享
- ✅ 远程访问(部署到云端)
- ✅ 多个同时运行的客户端
- ✅ 使用curl/Postman进行测试
- ✅ 基于浏览器的集成
共享部署
快速测试(ngrok):
# Terminal 1: Start server
TRANSPORT_MODE=http pnpm start
# Terminal 2: Create tunnel
ngrok http 3000
# Share URL: Others add with
# claude mcp add --transport http your-server https://abc123.ngrok.io/mcp
生产(云):
# Deploy to Railway, Render, Fly.io, AWS, etc.
# Set environment:
# TRANSPORT_MODE=http
# API_KEYS=key1,key2,key3
# Users connect:
claude mcp add --transport http your-server \
https://your-domain.com/mcp \
--header "Authorization: Bearer user_api_key"
自主机(GitHub):
# Share repo - users run their own instance
git clone your-repo
pnpm install && pnpm build
claude mcp add demo-server node -- $(pwd)/dist/servers/bare-metal/index.js
实现细节
裸金属方法
此实现最低限度地使用官方MCP SDK,手动实现核心模式:
优势:
- 完全控制和透明
- 对MCP机制有清晰的理解
- 易于根据特定需求进行定制
- 最小依赖性
组件:
- 手动请求路由和处理程序注册
- 自定义中间件管道
- 直接传输设置(stdio读线、Express HTTP)
- 显式错误处理模式
代码行:~2500(不包括测试)
安全注意事项
生产清单:
- [x] 使用Zod模式进行输入验证
- [x] 文件访问的路径遍历保护
- [x] 表达式净化以防止代码注入
- [x] API密钥认证(HTTP模式)
- [x] 速率限制(令牌桶算法)
- [x] 请求跟踪审计日志
- [x] 安全的环境变量处理
- []用于HTTP传输的HTTPS/TLS(配置反向代理)
- []API键旋转机制(添加到配置中)
扩展指南
添加新工具很简单:
1.创建处理程序 (服务器/裸机/处理器/MyTool.ts):
export class MyTool implements CapabilityHandler<MyParams, MyResult> {
validate(input: unknown): ValidationResult<MyParams> {
return validateWithSchema(MyParamsSchema, input);
}
async execute(params: MyParams, context: ExecutionContext): Promise<Result<MyResult>> {
// Your logic here
return { success: true, data: result };
}
handleError(error: Error): MCPError {
return { code: MCPErrorCode.InternalError, message: error.message };
}
}
2.在index.ts中注册:
toolRegistry.register('my_tool', new MyTool(), {
name: 'my_tool',
description: 'Does something useful',
inputSchema: { /* JSON schema */ }
});
完成! 传输、路由、日志记录和度量自动工作。
测试
# Run all tests
pnpm test
# Watch mode
pnpm test:watch
# Coverage report
pnpm test:coverage
测试包括:
- 所有处理程序的单元测试
- 安全验证(路径遍历、注入尝试)
- 中间件功能(身份验证、速率限制)
- 两种运输工具的集成测试
项目结构
/mcp-demo
/shared # Common utilities
/types # TypeScript interfaces
/security # Validation, sanitization
/observability # Logging, metrics, tracing
/config # Configuration management
/utils # HTTP client, helpers
/servers/bare-metal # Bare-metal implementation
/handlers # Tool and resource handlers
/transport # Stdio and HTTP transports
/middleware # Auth, rate limiting
/registry # Capability registration
/core # Message routing
index.ts # Main entry point
/tests # Test suites
/docs # Specifications
许可证
麻省理工学院
贡献
欢迎投稿!该项目旨在为生产MCP服务器提供学习资源和模板。
重点领域:
- 其他功能示例(数据库、缓存等)
- 增强的安全模式
- 性能优化
- 框架比较实现
