# MCP Swagger Server 交互式 CLI 技术解读文档
## 1. 项目概述
MCP Swagger Server 的交互式 CLI 是一个功能完整的命令行界面工具,用于管理和运行 MCP (Model Context Protocol) 服务器实例。该 CLI 提供了会话管理、服务器启动/停止、配置管理等核心功能,采用模块化设计,具有良好的用户体验和扩展性。
## 2. 整体架构设计
### 2.1 模块划分
交互式 CLI 采用分层架构设计,主要包含以下模块:
```
interactive-cli/
├── index.ts # CLI 入口点
├── types.ts # 类型定义
├── commands/ # 命令处理模块
│ ├── interactive-command.ts # 交互式命令处理器
│ └── menu-handler.ts # 菜单处理器
├── managers/ # 核心管理模块
│ ├── session-manager.ts # 会话管理器
│ └── openapi-wizard.ts # OpenAPI 配置向导
├── ui/ # 用户界面模块
│ └── ui-manager.ts # UI 管理器
└── utils/ # 工具模块
├── config-manager.ts # 配置管理器
└── server-manager.ts # 服务器管理器
```
### 2.2 架构特点
- **分离关注点**:每个模块负责特定的功能领域
- **依赖注入**:通过构造函数注入依赖,便于测试和维护
- **事件驱动**:使用 EventEmitter 实现模块间的松耦合通信
- **配置驱动**:通过配置文件管理应用行为
- **单例模式**:关键管理器采用单例模式确保状态一致性
## 3. 核心模块详细分析
### 3.1 CLI 入口模块 (index.ts)
#### 功能概述
CLI 入口模块负责解析命令行参数,初始化应用环境,并启动相应的命令处理器。
#### 核心代码分析
```typescript
export async function runInteractiveCLI(options: CLIOptions = {}): Promise<void> {
try {
// 初始化配置管理器
await configManager.initConfig();
// 初始化会话管理器
await sessionManager.initialize();
// 创建交互式命令处理器
const interactiveCommand = new InteractiveCommand({
configManager,
sessionManager,
serverManager,
uiManager
});
// 启动交互式界面
await interactiveCommand.run();
} catch (error) {
console.error(chalk.red('启动交互式 CLI 失败:'), error);
process.exit(1);
}
}
```
#### 设计亮点
- **错误处理**:统一的错误捕获和处理机制
- **依赖初始化**:按顺序初始化各个管理器
- **优雅退出**:异常情况下的优雅退出机制
### 3.2 交互式命令处理器 (InteractiveCommand)
#### 功能概述
交互式命令处理器是 CLI 的核心控制器,负责处理用户交互、菜单导航和命令执行。
#### 核心代码分析
```typescript
export class InteractiveCommand {
private isRunning = false;
private currentMenu: string = 'main';
constructor(private dependencies: {
configManager: ConfigManager;
sessionManager: SessionManager;
serverManager: ServerManager;
uiManager: UIManager;
}) {
this.setupEventListeners();
}
async run(): Promise<void> {
this.isRunning = true;
// 显示欢迎信息
this.dependencies.uiManager.showWelcome();
// 主循环
while (this.isRunning) {
try {
await this.showCurrentMenu();
const choice = await this.getMenuChoice();
await this.handleMenuChoice(choice);
} catch (error) {
this.dependencies.uiManager.showError('操作失败', error);
}
}
}
}
```
#### 设计模式
- **状态机模式**:通过 `currentMenu` 管理不同的界面状态
- **命令模式**:将用户操作封装为命令对象
- **观察者模式**:监听服务器事件并响应
### 3.3 会话管理器 (SessionManager)
#### 功能概述
会话管理器负责管理 MCP 服务器的配置会话,包括创建、编辑、删除和持久化存储。
#### 核心数据结构
```typescript
export interface SessionConfig {
id: string;
name: string;
description?: string;
openApiUrl: string;
transport: TransportType;
port?: number;
host?: string;
auth?: AuthConfig;
customHeaders?: Record<string, string>;
operationFilter?: OperationFilter;
createdAt: string;
lastUsed: string;
}
```
#### 核心实现
```typescript
export class SessionManager {
private sessions: Map<string, SessionConfig> = new Map();
private configPath: string;
async saveSession(config: SessionConfig): Promise<void> {
// 生成唯一 ID
if (!config.id) {
config.id = this.generateId();
}
// 设置时间戳
const now = new Date().toISOString();
if (!config.createdAt) {
config.createdAt = now;
}
config.lastUsed = now;
// 保存到内存
this.sessions.set(config.id, config);
// 持久化到文件
await this.persistSessions();
}
private async persistSessions(): Promise<void> {
const sessionsArray = Array.from(this.sessions.values());
const data = {
version: '1.0.0',
sessions: sessionsArray,
lastModified: new Date().toISOString()
};
await fs.writeFile(this.configPath, JSON.stringify(data, null, 2), 'utf8');
}
}
```
#### 设计特点
- **内存 + 持久化**:内存操作提高性能,文件持久化保证数据安全
- **版本控制**:配置文件包含版本信息,便于未来升级
- **时间戳管理**:自动维护创建和使用时间
### 3.4 服务器管理器 (ServerManager)
#### 功能概述
服务器管理器负责 MCP 服务器实例的生命周期管理,包括启动、停止、监控和日志收集。
#### 核心架构
```typescript
export class ServerManager extends EventEmitter {
private runningServers: Map<string, ServerStatus> = new Map();
private logBuffer: Map<string, string[]> = new Map();
private readonly maxLogLines = 1000;
async startServer(config: SessionConfig): Promise<string> {
const serverId = this.generateServerId(config);
// 检查服务器是否已运行
if (this.isServerRunning(serverId)) {
throw new Error(`服务器 ${serverId} 已在运行`);
}
// 启动服务器进程
const { serverPromise, abortController } = await this.startServerProcess(config);
// 创建服务器状态
const serverStatus: ServerStatus = {
isRunning: true,
config,
stats: {
startTime: new Date(),
uptime: 0,
requests: 0,
errors: 0
},
serverPromise,
abortController
};
this.runningServers.set(serverId, serverStatus);
// 设置监控
this.setupServerMonitoring(serverId, serverPromise, abortController);
this.startStatsTracking(serverId);
this.emit('serverStarted', { serverId, config });
return serverId;
}
}
```
#### 关键特性
- **进程隔离**:每个服务器实例运行在独立的进程中
- **生命周期管理**:完整的启动、运行、停止流程
- **监控和日志**:实时监控服务器状态和收集日志
- **事件通知**:通过事件机制通知状态变化
### 3.5 配置管理器 (ConfigManager)
#### 功能概述
配置管理器负责全局配置的管理,包括用户偏好、默认设置和配置验证。
#### 配置结构
```typescript
export interface GlobalConfig {
global: {
transport: TransportType;
port: number;
autoSave: boolean;
debugMode: boolean;
};
ui: {
theme: 'default' | 'dark' | 'light';
showWelcome: boolean;
confirmExit: boolean;
};
server: {
timeout: number;
retries: number;
};
development: {
watchFiles: boolean;
hotReload: boolean;
logLevel: 'debug' | 'info' | 'warn' | 'error';
};
recent: {
configs: string[];
maxCount: number;
};
}
```
#### 核心实现
```typescript
export class ConfigManager {
private config: Conf<GlobalConfig>;
async initConfig(): Promise<void> {
this.config = new Conf({
configName: 'mcp-swagger-server',
defaults: DEFAULT_CONFIG,
schema: {
global: {
type: 'object',
properties: {
transport: { type: 'string', enum: ['stdio', 'sse', 'streamable'] },
port: { type: 'number', minimum: 1, maximum: 65535 },
autoSave: { type: 'boolean' },
debugMode: { type: 'boolean' }
}
}
// ... 其他配置项的 schema
}
});
}
validateConfig(config: Partial<GlobalConfig>): { valid: boolean; errors: string[] } {
const errors: string[] = [];
// 验证传输协议
if (config.global?.transport && !['stdio', 'sse', 'streamable'].includes(config.global.transport)) {
errors.push('无效的传输协议');
}
// 验证端口
if (config.global?.port && (config.global.port < 1 || config.global.port > 65535)) {
errors.push('端口必须在 1-65535 范围内');
}
return { valid: errors.length === 0, errors };
}
}
```
#### 设计优势
- **Schema 验证**:使用 JSON Schema 确保配置的有效性
- **默认值管理**:提供合理的默认配置
- **类型安全**:TypeScript 类型定义确保类型安全
### 3.6 OpenAPI 配置向导 (OpenAPIWizard)
#### 功能概述
OpenAPI 配置向导提供分步式的配置创建流程,帮助用户轻松创建和编辑 MCP 服务器配置。
#### 核心流程
```typescript
export class OpenAPIWizard {
async runWizard(): Promise<SessionConfig | null> {
const config: Partial<SessionConfig> = {};
try {
// 步骤 1: 获取基本信息
const baseConfig = await this.getBaseConfig();
Object.assign(config, baseConfig);
// 步骤 2: 配置 OpenAPI
const openApiConfig = await this.getOpenAPIConfig();
Object.assign(config, openApiConfig);
// 步骤 3: 配置传输
const transportConfig = await this.getTransportConfig();
Object.assign(config, transportConfig);
// 步骤 4: 高级配置(可选)
const advancedConfig = await this.getAdvancedConfig();
Object.assign(config, advancedConfig);
// 步骤 5: 确认配置
const confirmed = await this.confirmConfiguration(config as SessionConfig);
return confirmed ? config as SessionConfig : null;
} catch (error) {
this.uiManager.showError('配置向导失败', error);
return null;
}
}
private async getOpenAPIConfig(): Promise<Partial<SessionConfig>> {
const choices = [
{ name: '在线 URL', value: 'url' },
{ name: '本地文件', value: 'file' },
{ name: '预设 URL', value: 'preset' },
{ name: '手动输入', value: 'manual' }
];
const { source } = await inquirer.prompt({
type: 'list',
name: 'source',
message: '选择 OpenAPI 文档来源:',
choices
});
let openApiUrl: string;
switch (source) {
case 'url':
openApiUrl = await this.getOnlineUrl();
break;
case 'file':
openApiUrl = await this.getLocalFilePath();
break;
case 'preset':
openApiUrl = await this.selectPresetUrl();
break;
case 'manual':
openApiUrl = await this.getManualUrl();
break;
default:
throw new Error('无效的来源选择');
}
// 验证 OpenAPI 文档
const validation = await this.validateOpenApiDocument(openApiUrl);
if (!validation.valid) {
throw new Error(`OpenAPI 文档验证失败: ${validation.errors?.join(', ')}`);
}
return { openApiUrl };
}
}
```
#### 设计特点
- **分步引导**:将复杂配置分解为简单步骤
- **输入验证**:每个步骤都进行输入验证
- **用户友好**:提供清晰的提示和选项
- **错误处理**:优雅处理各种错误情况
### 3.7 UI 管理器 (UIManager)
#### 功能概述
UI 管理器负责所有用户界面的展示,包括菜单、表格、消息框和进度指示器。
#### 核心功能
```typescript
export class UIManager {
private chalk = require('chalk');
private boxen = require('boxen');
private Table = require('cli-table3');
showWelcome(): void {
const welcomeText = `
${this.chalk.cyan.bold('🚀 MCP Swagger Server CLI')}
${this.chalk.gray('交互式命令行界面')}
${this.chalk.yellow('功能特性:')}
• 会话管理 - 创建和管理服务器配置
• 服务器控制 - 启动、停止和监控服务器
• 实时日志 - 查看服务器运行日志
• 配置向导 - 分步创建 OpenAPI 配置
`;
console.log(boxen(welcomeText, {
padding: 1,
margin: 1,
borderStyle: 'round',
borderColor: 'cyan'
}));
}
showSessionList(sessions: SessionConfig[]): void {
if (sessions.length === 0) {
console.log(this.chalk.yellow('\n暂无会话配置'));
return;
}
const table = new Table({
head: ['名称', '传输协议', '端口', '最后使用', '状态'],
colWidths: [20, 12, 8, 20, 10]
});
sessions.forEach(session => {
const status = this.getSessionStatus(session.id);
table.push([
this.chalk.cyan(session.name),
session.transport.toUpperCase(),
session.port || 'N/A',
this.formatDate(session.lastUsed),
status === 'running' ? this.chalk.green('运行中') : this.chalk.gray('已停止')
]);
});
console.log('\n' + table.toString());
}
}
```
#### 设计优势
- **一致性**:统一的 UI 风格和交互模式
- **可读性**:使用颜色和格式化提高可读性
- **响应式**:根据终端大小调整显示
## 4. 依赖包分析
### 4.1 核心依赖
#### inquirer
- **作用**:提供交互式命令行界面
- **选择理由**:成熟稳定,支持多种输入类型,用户体验好
- **使用场景**:菜单选择、用户输入、确认对话框
```typescript
const { choice } = await inquirer.prompt({
type: 'list',
name: 'choice',
message: '请选择操作:',
choices: menuItems
});
```
#### chalk
- **作用**:终端文本着色和样式
- **选择理由**:轻量级,API 简洁,广泛使用
- **使用场景**:错误信息、成功提示、状态显示
```typescript
console.log(chalk.green('✓ 服务器启动成功'));
console.log(chalk.red('✗ 操作失败'));
```
#### boxen
- **作用**:创建终端文本框
- **选择理由**:美观的边框样式,可配置性强
- **使用场景**:欢迎信息、重要提示、配置摘要
#### cli-table3
- **作用**:创建终端表格
- **选择理由**:功能完整,支持多种表格样式
- **使用场景**:会话列表、服务器状态、统计信息
#### conf
- **作用**:配置文件管理
- **选择理由**:支持 JSON Schema 验证,跨平台兼容
- **使用场景**:全局配置存储和管理
#### chokidar
- **作用**:文件系统监听
- **选择理由**:跨平台,性能好,API 简洁
- **使用场景**:配置文件变化监听
### 4.2 工具依赖
#### ora
- **作用**:终端进度指示器
- **选择理由**:动画效果好,可定制性强
- **使用场景**:长时间操作的进度提示
#### axios
- **作用**:HTTP 客户端
- **选择理由**:功能完整,Promise 支持,拦截器机制
- **使用场景**:获取在线 OpenAPI 文档
## 5. 实现思路和设计模式
### 5.1 整体设计思路
1. **模块化设计**:将功能按职责分离到不同模块
2. **依赖注入**:通过构造函数注入依赖,提高可测试性
3. **事件驱动**:使用事件机制实现模块间通信
4. **配置驱动**:通过配置文件控制应用行为
5. **用户体验优先**:提供直观的交互界面和清晰的反馈
### 5.2 应用的设计模式
#### 单例模式 (Singleton)
```typescript
// 确保全局只有一个服务器管理器实例
export const serverManager = new ServerManager();
```
#### 工厂模式 (Factory)
```typescript
class SessionFactory {
static createSession(config: Partial<SessionConfig>): SessionConfig {
return {
id: generateId(),
createdAt: new Date().toISOString(),
lastUsed: new Date().toISOString(),
...config
} as SessionConfig;
}
}
```
#### 观察者模式 (Observer)
```typescript
class ServerManager extends EventEmitter {
startServer(config: SessionConfig): Promise<string> {
// ...
this.emit('serverStarted', { serverId, config });
// ...
}
}
```
#### 策略模式 (Strategy)
```typescript
class TransportStrategy {
static getStrategy(transport: TransportType) {
switch (transport) {
case 'stdio': return new StdioStrategy();
case 'sse': return new SseStrategy();
case 'streamable': return new StreamableStrategy();
}
}
}
```
#### 命令模式 (Command)
```typescript
interface Command {
execute(): Promise<void>;
}
class StartServerCommand implements Command {
constructor(private config: SessionConfig) {}
async execute(): Promise<void> {
await serverManager.startServer(this.config);
}
}
```
## 6. 关键功能实现细节
### 6.1 会话持久化机制
```typescript
private async persistSessions(): Promise<void> {
const sessionsArray = Array.from(this.sessions.values());
const data = {
version: '1.0.0',
sessions: sessionsArray,
lastModified: new Date().toISOString(),
checksum: this.calculateChecksum(sessionsArray)
};
// 原子写入,避免数据损坏
const tempPath = this.configPath + '.tmp';
await fs.writeFile(tempPath, JSON.stringify(data, null, 2), 'utf8');
await fs.rename(tempPath, this.configPath);
}
```
### 6.2 服务器进程管理
```typescript
private async startServerProcess(config: SessionConfig): Promise<{
serverPromise: Promise<void>;
abortController: AbortController;
}> {
const abortController = new AbortController();
// 根据传输协议启动不同的服务器
let serverPromise: Promise<void>;
switch (config.transport.toLowerCase()) {
case 'stdio':
serverPromise = runStdioServer(
openApiData,
authConfig,
config.customHeaders,
this.debugMode,
operationFilter
);
break;
case 'sse':
serverPromise = runSseServer(
'/sse',
config.port || 3322,
openApiData,
authConfig,
config.customHeaders,
this.debugMode,
operationFilter
);
break;
// ...
}
return { serverPromise, abortController };
}
```
### 6.3 配置验证机制
```typescript
validateConfig(config: Partial<GlobalConfig>): {
valid: boolean;
errors: string[];
warnings: string[];
} {
const errors: string[] = [];
const warnings: string[] = [];
// 验证传输协议
if (config.global?.transport) {
const validTransports = ['stdio', 'sse', 'streamable'];
if (!validTransports.includes(config.global.transport)) {
errors.push(`无效的传输协议: ${config.global.transport}`);
}
}
// 验证端口范围
if (config.global?.port) {
if (config.global.port < 1 || config.global.port > 65535) {
errors.push('端口必须在 1-65535 范围内');
} else if (config.global.port < 1024) {
warnings.push('使用系统端口可能需要管理员权限');
}
}
return {
valid: errors.length === 0,
errors,
warnings
};
}
```
### 6.4 错误处理和恢复
```typescript
private setupErrorHandling(): void {
// 全局错误处理
process.on('uncaughtException', (error) => {
this.logger.error('未捕获的异常:', error);
this.gracefulShutdown();
});
process.on('unhandledRejection', (reason) => {
this.logger.error('未处理的 Promise 拒绝:', reason);
});
// 优雅关闭
process.on('SIGTERM', () => this.gracefulShutdown());
process.on('SIGINT', () => this.gracefulShutdown());
}
private async gracefulShutdown(): Promise<void> {
console.log(chalk.yellow('\n正在关闭所有服务器...'));
try {
await this.stopAllServers();
console.log(chalk.green('所有服务器已安全关闭'));
} catch (error) {
console.error(chalk.red('关闭服务器时出错:'), error);
} finally {
process.exit(0);
}
}
```
## 7. 性能优化和最佳实践
### 7.1 内存管理
- **日志缓冲区限制**:限制每个服务器的日志行数,防止内存泄漏
- **会话缓存**:使用 Map 结构提高查找性能
- **事件监听器清理**:及时清理不再需要的事件监听器
### 7.2 异步操作优化
- **并发控制**:使用 Promise.all 并行执行独立操作
- **超时处理**:为网络请求设置合理的超时时间
- **错误边界**:在关键操作周围设置错误边界
### 7.3 用户体验优化
- **进度指示**:长时间操作显示进度指示器
- **即时反馈**:操作结果的即时反馈
- **键盘快捷键**:支持常用操作的快捷键
## 8. 扩展性设计
### 8.1 插件机制
```typescript
interface Plugin {
name: string;
version: string;
init(context: PluginContext): Promise<void>;
destroy(): Promise<void>;
}
class PluginManager {
private plugins: Map<string, Plugin> = new Map();
async loadPlugin(pluginPath: string): Promise<void> {
const plugin = await import(pluginPath);
await plugin.init(this.createContext());
this.plugins.set(plugin.name, plugin);
}
}
```
### 8.2 主题系统
```typescript
interface Theme {
colors: {
primary: string;
secondary: string;
success: string;
error: string;
warning: string;
};
styles: {
border: string;
padding: number;
};
}
class ThemeManager {
private currentTheme: Theme;
applyTheme(themeName: string): void {
this.currentTheme = this.loadTheme(themeName);
this.updateUIComponents();
}
}
```
## 9. 测试策略
### 9.1 单元测试
```typescript
describe('SessionManager', () => {
let sessionManager: SessionManager;
beforeEach(() => {
sessionManager = new SessionManager();
});
it('should save session correctly', async () => {
const config: SessionConfig = {
id: 'test-1',
name: 'Test Session',
openApiUrl: 'http://example.com/api.json',
transport: 'stdio'
};
await sessionManager.saveSession(config);
const saved = sessionManager.getSession('test-1');
expect(saved).toEqual(expect.objectContaining(config));
});
});
```
### 9.2 集成测试
```typescript
describe('CLI Integration', () => {
it('should start and stop server successfully', async () => {
const cli = new InteractiveCLI();
const serverId = await cli.startServer(testConfig);
expect(serverId).toBeDefined();
expect(cli.isServerRunning(serverId)).toBe(true);
await cli.stopServer(serverId);
expect(cli.isServerRunning(serverId)).toBe(false);
});
});
```
## 10. 部署和维护
### 10.1 构建流程
```json
{
"scripts": {
"build": "tsc",
"dev": "ts-node src/interactive-cli/index.ts",
"test": "jest",
"lint": "eslint src/**/*.ts",
"package": "pkg dist/index.js"
}
}
```
### 10.2 配置管理
- **环境变量**:支持通过环境变量覆盖配置
- **配置文件**:支持多种格式的配置文件
- **命令行参数**:支持命令行参数覆盖配置
### 10.3 日志和监控
```typescript
class Logger {
private winston = require('winston');
constructor() {
this.winston.configure({
level: process.env.LOG_LEVEL || 'info',
format: winston.format.combine(
winston.format.timestamp(),
winston.format.json()
),
transports: [
new winston.transports.Console(),
new winston.transports.File({ filename: 'cli.log' })
]
});
}
}
```
## 11. 总结
MCP Swagger Server 的交互式 CLI 是一个设计良好、功能完整的命令行工具。它采用了现代的软件架构模式和最佳实践,具有以下特点:
1. **模块化架构**:清晰的模块划分和职责分离
2. **用户友好**:直观的交互界面和良好的用户体验
3. **可扩展性**:支持插件机制和主题系统
4. **健壮性**:完善的错误处理和恢复机制
5. **可维护性**:良好的代码结构和文档
该 CLI 为 MCP 服务器的管理提供了强大而灵活的工具,是一个值得学习和参考的优秀项目。