第7章:Server配置和生命周期
2025/9/1大约 11 分钟
第7章:Server配置和生命周期
学习目标
- 掌握MCP Server的初始化和配置
- 学习连接建立和握手过程
- 理解Server的生命周期管理
- 掌握优雅关闭和资源清理
- 学习Server的监控和健康检查
7.1 MCP Server初始化和配置
7.1.1 基础配置结构
MCP Server的配置是整个服务运行的基础,包含服务元信息、能力声明、运行时参数等。
// src/config/ServerConfig.ts
export interface ServerConfig {
// 服务基本信息
server: {
name: string;
version: string;
description?: string;
author?: string;
};
// 服务能力配置
capabilities: {
tools?: ToolsCapability;
resources?: ResourcesCapability;
prompts?: PromptsCapability;
logging?: LoggingCapability;
experimental?: Record<string, unknown>;
};
// 运行时配置
runtime: {
maxConnections?: number;
timeout?: number;
keepAlive?: boolean;
enableMetrics?: boolean;
};
// 安全配置
security: {
allowedOrigins?: string[];
rateLimiting?: RateLimitConfig;
authentication?: AuthConfig;
};
}
export interface ToolsCapability {
listChanged?: boolean;
}
export interface ResourcesCapability {
subscribe?: boolean;
listChanged?: boolean;
}
export interface PromptsCapability {
listChanged?: boolean;
}
export interface LoggingCapability {
level?: 'error' | 'warn' | 'info' | 'debug';
}
export interface RateLimitConfig {
maxRequests: number;
windowMs: number;
}
export interface AuthConfig {
required: boolean;
methods: ('apiKey' | 'jwt' | 'oauth')[];
}
7.1.2 配置加载和验证
// src/config/ConfigLoader.ts
import { z } from 'zod';
import fs from 'fs/promises';
import path from 'path';
const ServerConfigSchema = z.object({
server: z.object({
name: z.string().min(1),
version: z.string().min(1),
description: z.string().optional(),
author: z.string().optional(),
}),
capabilities: z.object({
tools: z.object({
listChanged: z.boolean().optional(),
}).optional(),
resources: z.object({
subscribe: z.boolean().optional(),
listChanged: z.boolean().optional(),
}).optional(),
prompts: z.object({
listChanged: z.boolean().optional(),
}).optional(),
logging: z.object({
level: z.enum(['error', 'warn', 'info', 'debug']).optional(),
}).optional(),
experimental: z.record(z.unknown()).optional(),
}),
runtime: z.object({
maxConnections: z.number().positive().optional().default(100),
timeout: z.number().positive().optional().default(30000),
keepAlive: z.boolean().optional().default(true),
enableMetrics: z.boolean().optional().default(false),
}).optional().default({}),
security: z.object({
allowedOrigins: z.array(z.string()).optional(),
rateLimiting: z.object({
maxRequests: z.number().positive(),
windowMs: z.number().positive(),
}).optional(),
authentication: z.object({
required: z.boolean(),
methods: z.array(z.enum(['apiKey', 'jwt', 'oauth'])),
}).optional(),
}).optional().default({}),
});
export class ConfigLoader {
static async loadFromFile(configPath: string): Promise<ServerConfig> {
try {
const configData = await fs.readFile(configPath, 'utf-8');
const rawConfig = JSON.parse(configData);
// 验证配置结构
const validatedConfig = ServerConfigSchema.parse(rawConfig);
console.log(`✓ 配置文件加载成功: ${configPath}`);
return validatedConfig;
} catch (error) {
if (error instanceof z.ZodError) {
console.error('配置验证失败:', error.errors);
throw new Error(`配置文件验证失败: ${error.errors.map(e => e.message).join(', ')}`);
}
console.error(`配置文件加载失败: ${configPath}`, error);
throw error;
}
}
static async loadFromEnvironment(): Promise<Partial<ServerConfig>> {
return {
server: {
name: process.env.MCP_SERVER_NAME || 'mcp-server',
version: process.env.MCP_SERVER_VERSION || '1.0.0',
description: process.env.MCP_SERVER_DESCRIPTION,
author: process.env.MCP_SERVER_AUTHOR,
},
runtime: {
maxConnections: process.env.MCP_MAX_CONNECTIONS ?
parseInt(process.env.MCP_MAX_CONNECTIONS) : undefined,
timeout: process.env.MCP_TIMEOUT ?
parseInt(process.env.MCP_TIMEOUT) : undefined,
keepAlive: process.env.MCP_KEEP_ALIVE === 'true',
enableMetrics: process.env.MCP_ENABLE_METRICS === 'true',
},
};
}
static mergeConfigs(baseConfig: ServerConfig, overrideConfig: Partial<ServerConfig>): ServerConfig {
return {
server: { ...baseConfig.server, ...overrideConfig.server },
capabilities: { ...baseConfig.capabilities, ...overrideConfig.capabilities },
runtime: { ...baseConfig.runtime, ...overrideConfig.runtime },
security: { ...baseConfig.security, ...overrideConfig.security },
};
}
}
7.2 连接建立和握手过程
7.2.1 连接管理器
// src/connection/ConnectionManager.ts
import { EventEmitter } from 'events';
import { Transport } from '@modelcontextprotocol/sdk/types.js';
export interface Connection {
id: string;
transport: Transport;
clientInfo?: ClientInfo;
connectedAt: Date;
lastActivity: Date;
state: ConnectionState;
capabilities?: ClientCapabilities;
}
export interface ClientInfo {
name: string;
version: string;
}
export interface ClientCapabilities {
experimental?: Record<string, unknown>;
sampling?: Record<string, unknown>;
}
export enum ConnectionState {
CONNECTING = 'connecting',
HANDSHAKING = 'handshaking',
CONNECTED = 'connected',
DISCONNECTING = 'disconnecting',
DISCONNECTED = 'disconnected',
}
export class ConnectionManager extends EventEmitter {
private connections = new Map<string, Connection>();
private maxConnections: number;
constructor(maxConnections: number = 100) {
super();
this.maxConnections = maxConnections;
}
async addConnection(transport: Transport): Promise<string> {
if (this.connections.size >= this.maxConnections) {
throw new Error('Maximum connections exceeded');
}
const connectionId = this.generateConnectionId();
const connection: Connection = {
id: connectionId,
transport,
connectedAt: new Date(),
lastActivity: new Date(),
state: ConnectionState.CONNECTING,
};
this.connections.set(connectionId, connection);
this.setupConnectionHandlers(connection);
console.log(`新连接建立: ${connectionId}`);
this.emit('connectionAdded', connection);
return connectionId;
}
private setupConnectionHandlers(connection: Connection): void {
const { transport } = connection;
// 监听消息
transport.onmessage = (message) => {
connection.lastActivity = new Date();
this.emit('message', connection, message);
};
// 监听连接关闭
transport.onclose = () => {
this.removeConnection(connection.id);
};
// 监听错误
transport.onerror = (error) => {
console.error(`连接错误 ${connection.id}:`, error);
this.emit('connectionError', connection, error);
};
}
async startHandshake(connectionId: string, serverInfo: any, serverCapabilities: any): Promise<void> {
const connection = this.connections.get(connectionId);
if (!connection) {
throw new Error(`Connection not found: ${connectionId}`);
}
connection.state = ConnectionState.HANDSHAKING;
try {
// 发送初始化请求
await this.sendInitializeRequest(connection, serverInfo, serverCapabilities);
// 等待客户端响应
const response = await this.waitForInitializeResponse(connection);
// 处理响应并完成握手
connection.clientInfo = response.clientInfo;
connection.capabilities = response.capabilities;
connection.state = ConnectionState.CONNECTED;
console.log(`握手完成: ${connectionId}`);
this.emit('handshakeComplete', connection);
} catch (error) {
connection.state = ConnectionState.DISCONNECTED;
console.error(`握手失败 ${connectionId}:`, error);
this.emit('handshakeFailed', connection, error);
throw error;
}
}
private async sendInitializeRequest(
connection: Connection,
serverInfo: any,
serverCapabilities: any
): Promise<void> {
const initMessage = {
jsonrpc: '2.0',
id: this.generateRequestId(),
method: 'initialize',
params: {
protocolVersion: '2024-11-05',
serverInfo,
capabilities: serverCapabilities,
},
};
await connection.transport.send(initMessage);
}
private async waitForInitializeResponse(connection: Connection): Promise<any> {
return new Promise((resolve, reject) => {
const timeout = setTimeout(() => {
reject(new Error('Initialize timeout'));
}, 30000);
const messageHandler = (conn: Connection, message: any) => {
if (conn.id !== connection.id) return;
if (message.method === 'initialized') {
clearTimeout(timeout);
this.removeListener('message', messageHandler);
resolve({
clientInfo: message.params?.clientInfo,
capabilities: message.params?.capabilities,
});
}
};
this.on('message', messageHandler);
});
}
removeConnection(connectionId: string): void {
const connection = this.connections.get(connectionId);
if (!connection) return;
connection.state = ConnectionState.DISCONNECTED;
this.connections.delete(connectionId);
console.log(`连接关闭: ${connectionId}`);
this.emit('connectionRemoved', connection);
}
getConnection(connectionId: string): Connection | undefined {
return this.connections.get(connectionId);
}
getAllConnections(): Connection[] {
return Array.from(this.connections.values());
}
getConnectionCount(): number {
return this.connections.size;
}
private generateConnectionId(): string {
return `conn_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
}
private generateRequestId(): string {
return `req_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
}
}
7.2.2 握手协议实现
// src/protocol/HandshakeProtocol.ts
export interface HandshakeManager {
handleInitialize(params: InitializeParams): Promise<InitializeResult>;
handleInitialized(params?: InitializedParams): Promise<void>;
}
export interface InitializeParams {
protocolVersion: string;
clientInfo: {
name: string;
version: string;
};
capabilities: ClientCapabilities;
}
export interface InitializeResult {
protocolVersion: string;
serverInfo: {
name: string;
version: string;
};
capabilities: ServerCapabilities;
}
export interface InitializedParams {
// 目前为空,预留扩展
}
export class HandshakeManager implements HandshakeManager {
private serverInfo: { name: string; version: string };
private serverCapabilities: ServerCapabilities;
private supportedProtocolVersions: string[];
constructor(
serverInfo: { name: string; version: string },
serverCapabilities: ServerCapabilities,
supportedVersions: string[] = ['2024-11-05']
) {
this.serverInfo = serverInfo;
this.serverCapabilities = serverCapabilities;
this.supportedProtocolVersions = supportedVersions;
}
async handleInitialize(params: InitializeParams): Promise<InitializeResult> {
// 验证协议版本
if (!this.supportedProtocolVersions.includes(params.protocolVersion)) {
throw new Error(`Unsupported protocol version: ${params.protocolVersion}`);
}
// 记录客户端信息
console.log(`客户端连接: ${params.clientInfo.name} v${params.clientInfo.version}`);
console.log('客户端能力:', JSON.stringify(params.capabilities, null, 2));
// 协商能力
const negotiatedCapabilities = this.negotiateCapabilities(params.capabilities);
return {
protocolVersion: params.protocolVersion,
serverInfo: this.serverInfo,
capabilities: negotiatedCapabilities,
};
}
async handleInitialized(params?: InitializedParams): Promise<void> {
console.log('握手完成,服务器已就绪');
// 可以在这里执行握手完成后的初始化操作
}
private negotiateCapabilities(clientCapabilities: ClientCapabilities): ServerCapabilities {
// 根据客户端能力调整服务器能力
const capabilities = { ...this.serverCapabilities };
// 示例:如果客户端不支持某些实验性功能,则禁用
if (!clientCapabilities.experimental) {
delete capabilities.experimental;
}
return capabilities;
}
}
7.3 Server生命周期管理
7.3.1 生命周期状态机
// src/lifecycle/LifecycleManager.ts
export enum ServerState {
INITIAL = 'initial',
STARTING = 'starting',
RUNNING = 'running',
STOPPING = 'stopping',
STOPPED = 'stopped',
ERROR = 'error',
}
export interface LifecycleHook {
name: string;
execute(): Promise<void>;
}
export class LifecycleManager extends EventEmitter {
private state: ServerState = ServerState.INITIAL;
private startupHooks: LifecycleHook[] = [];
private shutdownHooks: LifecycleHook[] = [];
private healthChecks: Map<string, HealthCheck> = new Map();
private shutdownTimeout = 30000; // 30秒
constructor() {
super();
this.setupSignalHandlers();
}
async start(): Promise<void> {
if (this.state !== ServerState.INITIAL) {
throw new Error(`Cannot start server from state: ${this.state}`);
}
this.setState(ServerState.STARTING);
try {
console.log('🚀 服务器启动中...');
// 执行启动钩子
for (const hook of this.startupHooks) {
console.log(`执行启动钩子: ${hook.name}`);
await hook.execute();
}
this.setState(ServerState.RUNNING);
console.log('✅ 服务器启动成功');
} catch (error) {
this.setState(ServerState.ERROR);
console.error('❌ 服务器启动失败:', error);
throw error;
}
}
async stop(reason?: string): Promise<void> {
if (this.state !== ServerState.RUNNING) {
console.log(`服务器已停止或正在停止: ${this.state}`);
return;
}
this.setState(ServerState.STOPPING);
console.log(`🛑 服务器停止中... ${reason ? `原因: ${reason}` : ''}`);
try {
// 设置停止超时
const timeoutPromise = new Promise<void>((_, reject) => {
setTimeout(() => {
reject(new Error('Shutdown timeout exceeded'));
}, this.shutdownTimeout);
});
// 执行停止流程
const shutdownPromise = this.executeShutdownHooks();
await Promise.race([shutdownPromise, timeoutPromise]);
this.setState(ServerState.STOPPED);
console.log('✅ 服务器已优雅停止');
} catch (error) {
console.error('❌ 服务器停止过程中出现错误:', error);
this.setState(ServerState.ERROR);
throw error;
}
}
private async executeShutdownHooks(): Promise<void> {
// 反向执行停止钩子
const reversedHooks = [...this.shutdownHooks].reverse();
for (const hook of reversedHooks) {
try {
console.log(`执行停止钩子: ${hook.name}`);
await hook.execute();
} catch (error) {
console.error(`停止钩子执行失败: ${hook.name}`, error);
// 继续执行其他钩子,确保资源能尽可能清理
}
}
}
addStartupHook(hook: LifecycleHook): void {
this.startupHooks.push(hook);
}
addShutdownHook(hook: LifecycleHook): void {
this.shutdownHooks.push(hook);
}
private setState(newState: ServerState): void {
const previousState = this.state;
this.state = newState;
console.log(`状态变化: ${previousState} -> ${newState}`);
this.emit('stateChange', { from: previousState, to: newState });
}
getState(): ServerState {
return this.state;
}
isRunning(): boolean {
return this.state === ServerState.RUNNING;
}
private setupSignalHandlers(): void {
// 优雅停止信号
process.on('SIGTERM', () => {
this.stop('收到SIGTERM信号').catch(console.error);
});
process.on('SIGINT', () => {
this.stop('收到SIGINT信号').catch(console.error);
});
// 异常处理
process.on('uncaughtException', (error) => {
console.error('未捕获异常:', error);
this.setState(ServerState.ERROR);
this.stop('未捕获异常').catch(console.error);
});
process.on('unhandledRejection', (reason, promise) => {
console.error('未处理的Promise拒绝:', reason);
console.error('Promise:', promise);
});
}
}
7.3.2 健康检查系统
// src/health/HealthChecker.ts
export interface HealthCheck {
name: string;
check(): Promise<HealthCheckResult>;
timeout?: number;
}
export interface HealthCheckResult {
status: 'healthy' | 'unhealthy' | 'degraded';
message?: string;
details?: Record<string, any>;
timestamp: Date;
}
export class HealthChecker {
private checks = new Map<string, HealthCheck>();
private lastResults = new Map<string, HealthCheckResult>();
private checkInterval: NodeJS.Timeout | null = null;
private intervalMs = 30000; // 30秒
addCheck(check: HealthCheck): void {
this.checks.set(check.name, check);
}
removeCheck(name: string): void {
this.checks.delete(name);
this.lastResults.delete(name);
}
async runCheck(name: string): Promise<HealthCheckResult> {
const check = this.checks.get(name);
if (!check) {
throw new Error(`Health check not found: ${name}`);
}
const timeout = check.timeout || 5000;
try {
const result = await Promise.race([
check.check(),
this.createTimeoutPromise(timeout),
]);
this.lastResults.set(name, result);
return result;
} catch (error) {
const result: HealthCheckResult = {
status: 'unhealthy',
message: error instanceof Error ? error.message : 'Unknown error',
timestamp: new Date(),
};
this.lastResults.set(name, result);
return result;
}
}
async runAllChecks(): Promise<Map<string, HealthCheckResult>> {
const results = new Map<string, HealthCheckResult>();
const promises = Array.from(this.checks.entries()).map(async ([name, check]) => {
const result = await this.runCheck(name);
results.set(name, result);
});
await Promise.allSettled(promises);
return results;
}
getOverallHealth(): { status: 'healthy' | 'unhealthy' | 'degraded'; checks: Record<string, HealthCheckResult> } {
const checks: Record<string, HealthCheckResult> = {};
let hasUnhealthy = false;
let hasDegraded = false;
for (const [name, result] of this.lastResults) {
checks[name] = result;
if (result.status === 'unhealthy') {
hasUnhealthy = true;
} else if (result.status === 'degraded') {
hasDegraded = true;
}
}
let status: 'healthy' | 'unhealthy' | 'degraded';
if (hasUnhealthy) {
status = 'unhealthy';
} else if (hasDegraded) {
status = 'degraded';
} else {
status = 'healthy';
}
return { status, checks };
}
startPeriodicChecks(): void {
if (this.checkInterval) {
return;
}
this.checkInterval = setInterval(async () => {
try {
await this.runAllChecks();
} catch (error) {
console.error('健康检查执行失败:', error);
}
}, this.intervalMs);
console.log(`开始定期健康检查,间隔: ${this.intervalMs}ms`);
}
stopPeriodicChecks(): void {
if (this.checkInterval) {
clearInterval(this.checkInterval);
this.checkInterval = null;
console.log('停止定期健康检查');
}
}
private createTimeoutPromise(timeout: number): Promise<never> {
return new Promise((_, reject) => {
setTimeout(() => {
reject(new Error(`Health check timeout after ${timeout}ms`));
}, timeout);
});
}
}
// 内置健康检查
export class MemoryHealthCheck implements HealthCheck {
name = 'memory';
private maxHeapUsagePercent: number;
constructor(maxHeapUsagePercent = 90) {
this.maxHeapUsagePercent = maxHeapUsagePercent;
}
async check(): Promise<HealthCheckResult> {
const memUsage = process.memoryUsage();
const heapUsedMB = Math.round(memUsage.heapUsed / 1024 / 1024);
const heapTotalMB = Math.round(memUsage.heapTotal / 1024 / 1024);
const usagePercent = Math.round((memUsage.heapUsed / memUsage.heapTotal) * 100);
let status: 'healthy' | 'unhealthy' | 'degraded';
let message: string;
if (usagePercent >= this.maxHeapUsagePercent) {
status = 'unhealthy';
message = `堆内存使用率过高: ${usagePercent}%`;
} else if (usagePercent >= this.maxHeapUsagePercent * 0.8) {
status = 'degraded';
message = `堆内存使用率较高: ${usagePercent}%`;
} else {
status = 'healthy';
message = `堆内存使用正常: ${usagePercent}%`;
}
return {
status,
message,
details: {
heapUsed: heapUsedMB,
heapTotal: heapTotalMB,
usagePercent,
rss: Math.round(memUsage.rss / 1024 / 1024),
external: Math.round(memUsage.external / 1024 / 1024),
},
timestamp: new Date(),
};
}
}
export class EventLoopHealthCheck implements HealthCheck {
name = 'eventLoop';
private maxDelayMs: number;
constructor(maxDelayMs = 100) {
this.maxDelayMs = maxDelayMs;
}
async check(): Promise<HealthCheckResult> {
const start = Date.now();
await new Promise(resolve => setImmediate(resolve));
const delay = Date.now() - start;
let status: 'healthy' | 'unhealthy' | 'degraded';
let message: string;
if (delay >= this.maxDelayMs) {
status = 'unhealthy';
message = `事件循环延迟过高: ${delay}ms`;
} else if (delay >= this.maxDelayMs * 0.5) {
status = 'degraded';
message = `事件循环延迟较高: ${delay}ms`;
} else {
status = 'healthy';
message = `事件循环正常: ${delay}ms`;
}
return {
status,
message,
details: { delayMs: delay },
timestamp: new Date(),
};
}
}
7.4 优雅关闭和资源清理
7.4.1 资源管理器
// src/resources/ResourceManager.ts
export interface ManagedResource {
name: string;
close(): Promise<void>;
isHealthy?(): Promise<boolean>;
}
export class ResourceManager {
private resources = new Map<string, ManagedResource>();
private cleanupOrder: string[] = [];
register(resource: ManagedResource): void {
this.resources.set(resource.name, resource);
this.cleanupOrder.push(resource.name);
console.log(`注册资源: ${resource.name}`);
}
unregister(name: string): void {
this.resources.delete(name);
const index = this.cleanupOrder.indexOf(name);
if (index > -1) {
this.cleanupOrder.splice(index, 1);
}
console.log(`注销资源: ${name}`);
}
async closeAll(): Promise<void> {
console.log('开始清理资源...');
// 按注册的逆序清理资源
const reverseOrder = [...this.cleanupOrder].reverse();
for (const name of reverseOrder) {
const resource = this.resources.get(name);
if (!resource) continue;
try {
console.log(`清理资源: ${name}`);
await resource.close();
console.log(`✓ 资源清理完成: ${name}`);
} catch (error) {
console.error(`✗ 资源清理失败: ${name}`, error);
// 继续清理其他资源
}
}
this.resources.clear();
this.cleanupOrder.length = 0;
console.log('所有资源清理完成');
}
async checkHealth(): Promise<{ healthy: string[]; unhealthy: string[] }> {
const healthy: string[] = [];
const unhealthy: string[] = [];
for (const [name, resource] of this.resources) {
try {
if (resource.isHealthy) {
const isHealthy = await resource.isHealthy();
if (isHealthy) {
healthy.push(name);
} else {
unhealthy.push(name);
}
} else {
// 如果没有健康检查方法,假设健康
healthy.push(name);
}
} catch (error) {
unhealthy.push(name);
}
}
return { healthy, unhealthy };
}
getResourceNames(): string[] {
return Array.from(this.resources.keys());
}
}
7.4.2 完整的MCP Server实现
// src/MCPServer.ts
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { ConfigLoader, ServerConfig } from './config/ConfigLoader.js';
import { ConnectionManager } from './connection/ConnectionManager.js';
import { LifecycleManager, ServerState } from './lifecycle/LifecycleManager.js';
import { HealthChecker, MemoryHealthCheck, EventLoopHealthCheck } from './health/HealthChecker.js';
import { ResourceManager } from './resources/ResourceManager.js';
export class MCPServer {
private config: ServerConfig;
private server: Server;
private connectionManager: ConnectionManager;
private lifecycleManager: LifecycleManager;
private healthChecker: HealthChecker;
private resourceManager: ResourceManager;
private transport: StdioServerTransport;
constructor(config: ServerConfig) {
this.config = config;
this.initializeComponents();
this.setupLifecycleHooks();
this.setupHealthChecks();
}
private initializeComponents(): void {
// 初始化SDK Server
this.server = new Server(
{
name: this.config.server.name,
version: this.config.server.version,
},
{
capabilities: this.config.capabilities,
}
);
// 初始化各个管理器
this.connectionManager = new ConnectionManager(this.config.runtime?.maxConnections);
this.lifecycleManager = new LifecycleManager();
this.healthChecker = new HealthChecker();
this.resourceManager = new ResourceManager();
// 初始化传输层
this.transport = new StdioServerTransport();
}
private setupLifecycleHooks(): void {
// 启动钩子
this.lifecycleManager.addStartupHook({
name: 'server-initialization',
execute: async () => {
console.log('初始化MCP Server...');
await this.server.connect(this.transport);
},
});
this.lifecycleManager.addStartupHook({
name: 'health-checks',
execute: async () => {
console.log('启动健康检查...');
this.healthChecker.startPeriodicChecks();
},
});
// 停止钩子
this.lifecycleManager.addShutdownHook({
name: 'health-checks',
execute: async () => {
console.log('停止健康检查...');
this.healthChecker.stopPeriodicChecks();
},
});
this.lifecycleManager.addShutdownHook({
name: 'resources',
execute: async () => {
console.log('清理资源...');
await this.resourceManager.closeAll();
},
});
this.lifecycleManager.addShutdownHook({
name: 'server',
execute: async () => {
console.log('关闭MCP Server...');
await this.server.close();
},
});
}
private setupHealthChecks(): void {
// 添加内置健康检查
this.healthChecker.addCheck(new MemoryHealthCheck());
this.healthChecker.addCheck(new EventLoopHealthCheck());
// 添加自定义健康检查
this.healthChecker.addCheck({
name: 'server-state',
check: async () => {
const isRunning = this.lifecycleManager.isRunning();
return {
status: isRunning ? 'healthy' : 'unhealthy',
message: `服务器状态: ${this.lifecycleManager.getState()}`,
details: { state: this.lifecycleManager.getState() },
timestamp: new Date(),
};
},
});
}
async start(): Promise<void> {
try {
await this.lifecycleManager.start();
console.log(`🎉 MCP Server '${this.config.server.name}' 启动成功!`);
console.log(`版本: ${this.config.server.version}`);
console.log(`能力: ${Object.keys(this.config.capabilities).join(', ')}`);
} catch (error) {
console.error('服务器启动失败:', error);
throw error;
}
}
async stop(reason?: string): Promise<void> {
await this.lifecycleManager.stop(reason);
}
getState(): ServerState {
return this.lifecycleManager.getState();
}
async getHealth(): Promise<any> {
return this.healthChecker.getOverallHealth();
}
// 静态工厂方法
static async fromConfigFile(configPath: string): Promise<MCPServer> {
const config = await ConfigLoader.loadFromFile(configPath);
return new MCPServer(config);
}
static async fromEnvironment(): Promise<MCPServer> {
const envConfig = await ConfigLoader.loadFromEnvironment();
const defaultConfig: ServerConfig = {
server: {
name: 'mcp-server',
version: '1.0.0',
},
capabilities: {
tools: {},
resources: {},
prompts: {},
},
runtime: {},
security: {},
};
const finalConfig = ConfigLoader.mergeConfigs(defaultConfig, envConfig);
return new MCPServer(finalConfig);
}
}
// 示例配置文件
// config/server.json
const exampleConfig = {
"server": {
"name": "my-mcp-server",
"version": "1.0.0",
"description": "示例MCP服务器",
"author": "Your Name"
},
"capabilities": {
"tools": {
"listChanged": true
},
"resources": {
"subscribe": true,
"listChanged": true
},
"prompts": {
"listChanged": true
},
"logging": {
"level": "info"
}
},
"runtime": {
"maxConnections": 50,
"timeout": 30000,
"keepAlive": true,
"enableMetrics": true
},
"security": {
"allowedOrigins": ["*"],
"rateLimiting": {
"maxRequests": 100,
"windowMs": 60000
}
}
};
// 使用示例
// src/main.ts
export async function main() {
try {
// 从配置文件启动
const server = await MCPServer.fromConfigFile('./config/server.json');
// 或从环境变量启动
// const server = await MCPServer.fromEnvironment();
await server.start();
// 监听状态变化
server.lifecycleManager.on('stateChange', (change) => {
console.log(`状态变化: ${change.from} -> ${change.to}`);
});
} catch (error) {
console.error('启动失败:', error);
process.exit(1);
}
}
if (require.main === module) {
main().catch(console.error);
}
7.5 实践示例
7.5.1 带监控的生产级Server
// src/production/ProductionServer.ts
export class ProductionMCPServer extends MCPServer {
private metricsCollector: MetricsCollector;
private alertManager: AlertManager;
constructor(config: ServerConfig) {
super(config);
this.setupProductionFeatures();
}
private setupProductionFeatures(): void {
// 指标收集
this.metricsCollector = new MetricsCollector();
this.resourceManager.register(this.metricsCollector);
// 告警管理
this.alertManager = new AlertManager();
this.resourceManager.register(this.alertManager);
// 添加生产环境健康检查
this.healthChecker.addCheck({
name: 'database-connection',
check: this.checkDatabaseConnection.bind(this),
});
this.healthChecker.addCheck({
name: 'external-services',
check: this.checkExternalServices.bind(this),
});
}
private async checkDatabaseConnection(): Promise<HealthCheckResult> {
// 数据库连接检查逻辑
try {
// 假设的数据库ping
await this.pingDatabase();
return {
status: 'healthy',
message: '数据库连接正常',
timestamp: new Date(),
};
} catch (error) {
return {
status: 'unhealthy',
message: '数据库连接失败',
details: { error: error.message },
timestamp: new Date(),
};
}
}
private async checkExternalServices(): Promise<HealthCheckResult> {
// 外部服务检查逻辑
return {
status: 'healthy',
message: '外部服务正常',
timestamp: new Date(),
};
}
private async pingDatabase(): Promise<void> {
// 实际的数据库ping实现
throw new Error('Database ping not implemented');
}
}
本章总结
第7章深入学习了MCP Server的配置和生命周期管理:
核心知识点
- 服务器配置系统:建立了完整的配置加载、验证和合并机制
- 连接管理:实现了连接的建立、握手和状态管理
- 生命周期管理:构建了完整的启动、运行、停止状态机
- 健康检查:建立了全面的健康监控体系
- 资源管理:实现了优雅的资源清理机制
实践要点
- 使用配置文件和环境变量进行灵活配置
- 实现完整的握手协议确保连接建立
- 建立钩子系统管理生命周期事件
- 添加健康检查保证服务可靠性
- 实现优雅关闭避免资源泄露
通过本章学习,掌握了构建生产级MCP Server的完整生命周期管理能力,为后续的错误处理、安全控制等高级特性打下了坚实基础。