# Directory Structure
```
├── .gitignore
├── demo.js
├── Dockerfile
├── examples
│ ├── api-client-generator-example.js
│ ├── optimized-swagger-parser-example.js
│ ├── template-manager-example.js
│ └── typescript-generator-example.js
├── package.json
├── pnpm-lock.yaml
├── README.md
├── road.md
├── run-tools.sh
├── smithery.yaml
├── src
│ ├── generators
│ │ ├── api-client-generator.ts
│ │ ├── code-generator.ts
│ │ └── typescript-types-generator.ts
│ ├── index.ts
│ ├── mcp-tools-server.ts
│ ├── optimized-swagger-parser.ts
│ ├── swagger-parser.ts
│ ├── templates
│ │ ├── built-in
│ │ │ ├── api-client
│ │ │ │ ├── axios-client.tpl
│ │ │ │ ├── fetch-client.tpl
│ │ │ │ └── react-query-client.tpl
│ │ │ ├── config
│ │ │ │ ├── axios-config.tpl
│ │ │ │ └── fetch-config.tpl
│ │ │ ├── templates.json
│ │ │ └── typescript-types
│ │ │ ├── enum.tpl
│ │ │ └── interface.tpl
│ │ ├── custom
│ │ │ └── templates.json
│ │ ├── index.ts
│ │ ├── template-engine.ts
│ │ └── template-manager.ts
│ └── tools
│ ├── api-client-generator-tool.ts
│ ├── file-writer-tool.ts
│ ├── optimized-swagger-parser-tool.ts
│ ├── swagger-parser-tool.ts
│ ├── template-manager-tool.ts
│ └── typescript-types-generator-tool.ts
├── start-server.js
├── swagger-mcp-config.json
├── tools-client.js
└── tsconfig.json
```
# Files
--------------------------------------------------------------------------------
/src/templates/custom/templates.json:
--------------------------------------------------------------------------------
```json
{
"templates": []
}
```
--------------------------------------------------------------------------------
/swagger-mcp-config.json:
--------------------------------------------------------------------------------
```json
{
"name": "Swagger MCP Server",
"version": "1.0.0",
"transport": "stdio"
}
```
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
```json
{
"compilerOptions": {
"target": "ES2020",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"esModuleInterop": true,
"sourceMap": true,
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"noImplicitAny": true,
"resolveJsonModule": true,
"declaration": true,
"skipLibCheck": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist", "**/*.spec.ts"]
}
```
--------------------------------------------------------------------------------
/smithery.yaml:
--------------------------------------------------------------------------------
```yaml
# Smithery configuration file: https://smithery.ai/docs/config#smitheryyaml
startCommand:
type: stdio
configSchema:
# JSON Schema defining the configuration options for the MCP.
type: object
properties: {}
commandFunction:
# A JS function that produces the CLI command based on the given config to start the MCP on stdio.
|-
(config) => ({
command: 'node',
args: ['start-server.js'],
env: { }
})
exampleConfig: {}
```
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
```dockerfile
# Generated by https://smithery.ai. See: https://smithery.ai/docs/config#dockerfile
FROM node:lts-alpine
WORKDIR /app
# Copy package files
COPY package.json pnpm-lock.yaml ./
# Install dependencies without running lifecycle scripts
RUN npm install --ignore-scripts
# Copy rest of the application
COPY . .
# Build the project
RUN npm run build
# Expose port if needed. MCP transport is typically stdio, so port expose might not be needed.
CMD ["node", "start-server.js"]
```
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
```json
{
"name": "swagger-mcp-server",
"version": "0.1.0",
"description": "基于MCP的Swagger工具服务器,支持解析Swagger、生成类型定义和API客户端",
"main": "dist/index.js",
"bin": {
"swagger-mcp-server": "./start-server.js"
},
"scripts": {
"build": "tsc",
"watch": "tsc --watch",
"start": "node start-server.js",
"dev": "tsc --watch & node --watch dist/index.js",
"client": "node tools-client.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"swagger",
"openapi",
"mcp",
"model-context-protocol",
"code-generator",
"typescript"
],
"author": "",
"license": "MIT",
"dependencies": {
"@apidevtools/swagger-parser": "^10.1.1",
"@modelcontextprotocol/sdk": "^1.7.0",
"@types/swagger-parser": "^7.0.1",
"axios": "^1.6.2",
"fastmcp": "^1.20.5",
"openapi-types": "^12.1.3",
"swagger-parser": "^10.0.3",
"zod": "^3.22.4"
},
"devDependencies": {
"@types/node": "^22.13.0",
"typescript": "^5.2.2"
},
"packageManager": "[email protected]+sha512.398035c7bd696d0ba0b10a688ed558285329d27ea994804a52bad9167d8e3a72bcb993f9699585d3ca25779ac64949ef422757a6c31102c12ab932e5cbe5cc92"
}
```
--------------------------------------------------------------------------------
/src/templates/built-in/templates.json:
--------------------------------------------------------------------------------
```json
{
"templates": [
{
"id": "axios-client",
"name": "Axios Client",
"type": "api-client",
"framework": "axios",
"path": "api-client/axios-client.tpl",
"isBuiltIn": true,
"description": "默认Axios API客户端模板"
},
{
"id": "fetch-client",
"name": "Fetch Client",
"type": "api-client",
"framework": "fetch",
"path": "api-client/fetch-client.tpl",
"isBuiltIn": true,
"description": "默认Fetch API客户端模板"
},
{
"id": "react-query-client",
"name": "React Query Client",
"type": "api-client",
"framework": "react-query",
"path": "api-client/react-query-client.tpl",
"isBuiltIn": true,
"description": "默认React Query API客户端模板"
},
{
"id": "typescript-interface",
"name": "TypeScript Interface",
"type": "typescript-types",
"path": "typescript-types/interface.tpl",
"isBuiltIn": true,
"description": "默认TypeScript接口模板"
},
{
"id": "typescript-enum",
"name": "TypeScript Enum",
"type": "typescript-types",
"path": "typescript-types/enum.tpl",
"isBuiltIn": true,
"description": "默认TypeScript枚举模板"
},
{
"id": "axios-config",
"name": "Axios Config",
"type": "config-file",
"framework": "axios",
"path": "config/axios-config.tpl",
"isBuiltIn": true,
"description": "默认Axios配置文件模板"
},
{
"id": "fetch-config",
"name": "Fetch Config",
"type": "config-file",
"framework": "fetch",
"path": "config/fetch-config.tpl",
"isBuiltIn": true,
"description": "默认Fetch配置文件模板"
}
]
}
```
--------------------------------------------------------------------------------
/src/tools/file-writer-tool.ts:
--------------------------------------------------------------------------------
```typescript
/**
* MCP File Writer Tool
* Provides the ability to write files to the local file system, with support for automatic directory creation
*/
import * as fs from 'fs/promises';
import * as path from 'path';
import { z } from 'zod';
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
// File writer parameter validation schema
const fileWriterSchema = z.object({
filePath: z.string().min(1).describe('Complete path of the file'),
content: z.string().describe('Content to be written to the file'),
createDirs: z.boolean().optional().default(true).describe('Whether to automatically create parent directories if they do not exist'),
append: z.boolean().optional().default(false).describe('Whether to append to an existing file instead of overwriting it'),
encoding: z.string().optional().default('utf8').describe('File encoding'),
});
// File writer tool type definition
type FileWriterParams = z.infer<typeof fileWriterSchema>;
/**
* File Writer Tool Class
* Provides the ability to write files to the local file system
*/
export class FileWriterTool {
// Tool name and description
readonly name = 'file_writer';
readonly description = 'Write content to the specified file path, with support for automatic directory creation';
readonly version = '1.0.0';
readonly schema = fileWriterSchema;
/**
* Register the tool with the MCP server
*/
register(server: McpServer): void {
server.tool(
this.name,
this.description,
this.schema.shape,
async (params) => {
// 验证参数
const result = await this.writeFile(params);
// 返回符合MCP要求的格式
return {
...result,
content: [
{
type: "text",
text: JSON.stringify(result, null, 2)
}
]
};
}
);
}
/**
* Implementation of file writing
*/
async writeFile(params: FileWriterParams): Promise<object> {
try {
const { filePath, content, createDirs, append, encoding } = params;
// 确保父目录存在
if (createDirs) {
const dir = path.dirname(filePath);
await fs.mkdir(dir, { recursive: true });
}
// 写入文件
if (append) {
await fs.appendFile(filePath, content, { encoding: encoding as BufferEncoding });
} else {
await fs.writeFile(filePath, content, { encoding: encoding as BufferEncoding });
}
// 获取文件信息
const stats = await fs.stat(filePath);
return {
success: true,
filePath,
size: stats.size,
created: stats.birthtime,
modified: stats.mtime,
message: `文件已${append ? '追加' : '写入'}: ${filePath}`,
};
} catch (error) {
console.error('文件写入失败:', error);
return {
success: false,
error: error instanceof Error ? error.message : String(error),
filePath: params.filePath,
};
}
}
}
```
--------------------------------------------------------------------------------
/src/tools/swagger-parser-tool.ts:
--------------------------------------------------------------------------------
```typescript
/**
* Swagger Parser MCP Tool
*/
import { z } from 'zod';
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { OptimizedSwaggerApiParser } from '../optimized-swagger-parser';
// MCP tool names and descriptions
const SWAGGER_PARSER_TOOL_NAME = 'parse-swagger';
const SWAGGER_PARSER_TOOL_DESCRIPTION = 'Parse Swagger/OpenAPI document and return API operation information.';
/**
* Swagger Parser Tool Class
* Note: This is the original tool, kept for backward compatibility
* Recommended to use 'parse-swagger-optimized' or 'parse-swagger-lite' tools
*/
export class SwaggerParserTool {
name = SWAGGER_PARSER_TOOL_NAME;
description = SWAGGER_PARSER_TOOL_DESCRIPTION;
// Define parameter schema
schema = z.object({
/**
* Swagger/OpenAPI document URL
*/
url: z.string().describe('Swagger/OpenAPI document URL'),
/**
* Request headers
*/
headers: z.record(z.string()).optional().describe('Request headers'),
/**
* Whether to include schema definitions
*/
includeSchemas: z.boolean().optional().describe('Whether to include schema definitions'),
/**
* Whether to include all details
*/
includeDetails: z.boolean().optional().describe('Whether to include all details like request bodies, responses, etc.')
});
/**
* Register tool on the MCP server
*/
register(server: McpServer) {
server.tool(
this.name,
this.description,
this.schema.shape,
async ({ url, headers = {}, includeSchemas = false, includeDetails = false }) => {
return await this.execute({ url, headers, includeSchemas, includeDetails });
}
);
}
/**
* Execute Swagger parsing
*/
async execute({
url,
headers = {},
includeSchemas = false,
includeDetails = false
}: z.infer<typeof this.schema>) {
try {
console.log(`[SwaggerParserTool] 解析Swagger文档: ${url}`);
// 创建解析器实例
const parser = new OptimizedSwaggerApiParser({
url,
headers,
useCache: true,
skipValidation: true
});
// 解析API文档
const api = await parser.fetchApi();
// 获取API操作
const operations = await parser.getAllOperations();
// 构建结果对象
const result: any = {
success: true,
info: {
title: api.info.title,
version: api.info.version,
description: api.info.description
},
operationsCount: operations.length,
operations: operations.map(op => {
// 基本操作信息
const operation = {
operationId: op.operationId,
method: op.method,
path: op.path,
summary: op.summary,
tags: op.tags
};
// 如果需要详细信息,则包含参数和响应
if (includeDetails) {
return {
...operation,
parameters: op.parameters,
requestBody: op.requestBody,
responses: op.responses
};
}
return operation;
})
};
// 如果需要模式定义,则添加到结果中
if (includeSchemas) {
result.schemas = await parser.getAllSchemas();
}
console.log(`[SwaggerParserTool] 解析完成,找到 ${operations.length} 个API操作`);
// 返回结果
return {
content: [
{
type: 'text' as const,
text: JSON.stringify(result, null, 2)
}
]
};
} catch (error) {
console.error(`[SwaggerParserTool] 解析失败:`, error);
// 返回错误结果
return {
content: [
{
type: 'text' as const,
text: JSON.stringify({
success: false,
error: error instanceof Error ? error.message : String(error)
}, null, 2)
}
]
};
}
}
}
```
--------------------------------------------------------------------------------
/src/tools/api-client-generator-tool.ts:
--------------------------------------------------------------------------------
```typescript
/**
* API Client Generator MCP Tool
*/
import { z } from 'zod';
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { ApiClientGenerator, ApiClientGeneratorOptions } from '../generators/api-client-generator';
// MCP tool names and descriptions
const API_CLIENT_GENERATOR_TOOL_NAME = 'generate-api-client';
const API_CLIENT_GENERATOR_TOOL_DESCRIPTION = 'Generate API client code from Swagger/OpenAPI document.';
// Optimized version tool names and descriptions
const OPTIMIZED_API_CLIENT_GENERATOR_TOOL_NAME = 'generate-api-client-optimized';
const OPTIMIZED_API_CLIENT_GENERATOR_TOOL_DESCRIPTION = 'Generate API client code from Swagger/OpenAPI document (optimized version with caching and large document support).';
/**
* API Client Generator Tool Class
*/
export class ApiClientGeneratorTool {
name = API_CLIENT_GENERATOR_TOOL_NAME;
description = API_CLIENT_GENERATOR_TOOL_DESCRIPTION;
optimizedName = OPTIMIZED_API_CLIENT_GENERATOR_TOOL_NAME;
optimizedDescription = OPTIMIZED_API_CLIENT_GENERATOR_TOOL_DESCRIPTION;
// Define parameter schema
schema = z.object({
/**
* Swagger/OpenAPI document URL
*/
swaggerUrl: z.string().describe('Swagger/OpenAPI document URL'),
/**
* Output directory
*/
outputDir: z.string().optional().describe('Output directory'),
/**
* Whether to overwrite existing files
*/
overwrite: z.boolean().optional().describe('Whether to overwrite existing files'),
/**
* File prefix
*/
filePrefix: z.string().optional().describe('File prefix'),
/**
* File suffix
*/
fileSuffix: z.string().optional().describe('File suffix'),
/**
* API client technology stack
*/
clientType: z.enum(['axios', 'fetch', 'react-query']).optional().describe('API client technology stack'),
/**
* Whether to generate type imports
*/
generateTypeImports: z.boolean().optional().describe('Whether to generate type imports'),
/**
* Types import path
*/
typesImportPath: z.string().optional().describe('Types import path'),
/**
* Grouping method
*/
groupBy: z.enum(['tag', 'path', 'none']).optional().describe('Grouping method'),
/**
* Include tags filter
*/
includeTags: z.array(z.string()).optional().describe('Include tags filter'),
/**
* Exclude tags filter
*/
excludeTags: z.array(z.string()).optional().describe('Exclude tags filter'),
/**
* Request headers
*/
headers: z.record(z.string()).optional().describe('Request headers')
});
// Define optimized parameter schema
optimizedSchema = this.schema.extend({
/**
* Whether to use cache
*/
useCache: z.boolean().optional().describe('Whether to use cache'),
/**
* Cache TTL in minutes
*/
cacheTTLMinutes: z.number().optional().describe('Cache TTL in minutes'),
/**
* Whether to skip validation
*/
skipValidation: z.boolean().optional().describe('Whether to skip validation'),
/**
* Whether to use lazy loading
*/
lazyLoading: z.boolean().optional().describe('Whether to use lazy loading')
});
/**
* Register tool on the MCP server
*/
register(server: McpServer) {
// 注册标准版
server.tool(
this.name,
this.description,
this.schema.shape,
async (params) => {
return await this.execute(params);
}
);
// 注册优化版
server.tool(
this.optimizedName,
this.optimizedDescription,
this.optimizedSchema.shape,
async (params) => {
// 设置优化版默认选项
const optimizedParams = {
...params,
useCache: params.useCache !== false,
lazyLoading: params.lazyLoading !== false,
skipValidation: params.skipValidation || false
};
return await this.execute(optimizedParams);
}
);
console.log(`✅ 已注册API客户端生成器工具: ${this.name}, ${this.optimizedName}`);
}
/**
* Execute API client generation
*/
async execute(params: z.infer<typeof this.optimizedSchema>) {
try {
console.log(`[ApiClientGeneratorTool] 开始生成API客户端: ${params.swaggerUrl}`);
// 创建生成器实例
const generator = new ApiClientGenerator();
// 记录进度的函数
let progressUpdates: { progress: number, message: string }[] = [];
const progressCallback = (progress: number, message: string) => {
progressUpdates.push({ progress, message });
};
// 执行生成
const result = await generator.generate({
...params,
progressCallback
} as ApiClientGeneratorOptions);
// 处理结果
if (result.success) {
console.log(`[ApiClientGeneratorTool] 客户端生成成功,生成了 ${result.files.length} 个文件`);
return {
content: [
{
type: 'text' as const,
text: JSON.stringify({
success: true,
files: result.files,
warnings: result.warnings,
progress: progressUpdates
}, null, 2)
}
]
};
} else {
console.error(`[ApiClientGeneratorTool] 客户端生成失败: ${result.error}`);
return {
content: [
{
type: 'text' as const,
text: JSON.stringify({
success: false,
error: result.error,
progress: progressUpdates
}, null, 2)
}
]
};
}
} catch (error) {
console.error(`[ApiClientGeneratorTool] 执行异常:`, error);
// 返回错误结果
return {
content: [
{
type: 'text' as const,
text: JSON.stringify({
success: false,
error: error instanceof Error ? error.message : String(error)
}, null, 2)
}
]
};
}
}
}
```
--------------------------------------------------------------------------------
/src/tools/typescript-types-generator-tool.ts:
--------------------------------------------------------------------------------
```typescript
/**
* TypeScript Type Generator MCP Tool
*/
import { z } from 'zod';
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { TypeScriptTypesGenerator, TypeScriptTypesGeneratorOptions } from '../generators/typescript-types-generator';
// MCP tool names and descriptions
const TS_TYPES_GENERATOR_TOOL_NAME = 'generate-typescript-types';
const TS_TYPES_GENERATOR_TOOL_DESCRIPTION = 'Generate TypeScript type definitions from Swagger/OpenAPI document.';
// Optimized version tool names and descriptions
const TS_TYPES_GENERATOR_OPTIMIZED_TOOL_NAME = 'generate-typescript-types-optimized';
const TS_TYPES_GENERATOR_OPTIMIZED_TOOL_DESCRIPTION = 'Generate TypeScript type definitions from Swagger/OpenAPI document with optimized options for caching and large document support.';
/**
* TypeScript Type Generator Tool Class
*/
export class TypeScriptTypesGeneratorTool {
name = TS_TYPES_GENERATOR_TOOL_NAME;
description = TS_TYPES_GENERATOR_TOOL_DESCRIPTION;
// Define parameter schema
schema = z.object({
/**
* Swagger/OpenAPI document URL
*/
swaggerUrl: z.string().describe('Swagger/OpenAPI document URL'),
/**
* Output directory
*/
outputDir: z.string().optional().describe('Output directory'),
/**
* Whether to overwrite existing files
*/
overwrite: z.boolean().optional().describe('Whether to overwrite existing files'),
/**
* File prefix
*/
filePrefix: z.string().optional().describe('File prefix'),
/**
* File suffix
*/
fileSuffix: z.string().optional().describe('File suffix'),
/**
* Whether to use namespace
*/
useNamespace: z.boolean().optional().describe('Whether to use namespace for wrapping types'),
/**
* Namespace name
*/
namespace: z.string().optional().describe('Namespace name'),
/**
* Whether to generate enums
*/
generateEnums: z.boolean().optional().describe('Whether to generate enum types'),
/**
* Whether to use strict types
*/
strictTypes: z.boolean().optional().describe('Whether to use strict types'),
/**
* Excluded schema names
*/
excludeSchemas: z.array(z.string()).optional().describe('Array of schema names to exclude'),
/**
* Included schema names
*/
includeSchemas: z.array(z.string()).optional().describe('Array of schema names to include'),
/**
* Whether to generate index file
*/
generateIndex: z.boolean().optional().describe('Whether to generate an index file'),
/**
* Request headers
*/
headers: z.record(z.string()).optional().describe('Request headers'),
/**
* Whether to use cache
*/
useCache: z.boolean().optional().describe('Whether to use cache'),
/**
* Cache TTL in minutes
*/
cacheTTLMinutes: z.number().optional().describe('Cache TTL in minutes'),
/**
* Whether to skip validation
*/
skipValidation: z.boolean().optional().describe('Whether to skip validation'),
/**
* Whether to use lazy loading
*/
lazyLoading: z.boolean().optional().describe('Whether to use lazy loading')
});
/**
* Register tool on the MCP server
*/
register(server: McpServer) {
// 注册标准工具
server.tool(
this.name,
this.description,
this.schema.shape,
async (params) => {
// 使用默认参数
const options = {
...params,
useCache: true,
skipValidation: true,
lazyLoading: false
};
return await this.execute(options);
}
);
// 注册优化版工具
server.tool(
TS_TYPES_GENERATOR_OPTIMIZED_TOOL_NAME,
TS_TYPES_GENERATOR_OPTIMIZED_TOOL_DESCRIPTION,
this.schema.shape,
async (params) => {
// 默认启用性能优化选项
const options = {
...params,
useCache: params.useCache !== false,
skipValidation: params.skipValidation !== false,
lazyLoading: params.lazyLoading !== false
};
return await this.execute(options);
}
);
}
/**
* Execute TypeScript type generation
*/
async execute(params: z.infer<typeof this.schema>) {
let progress = 0;
let progressMessage = '';
// 定义进度回调
const progressCallback = (newProgress: number, message: string) => {
progress = newProgress;
progressMessage = message;
console.log(`[Progress] ${Math.round(newProgress * 100)}%: ${message}`);
};
try {
console.log(`[TypeScriptTypesGeneratorTool] 开始生成TypeScript类型: ${params.swaggerUrl}`);
console.log(`[TypeScriptTypesGeneratorTool] 缓存: ${params.useCache ? '启用' : '禁用'}, 懒加载: ${params.lazyLoading ? '启用' : '禁用'}`);
// 创建生成器实例
const generator = new TypeScriptTypesGenerator();
// 执行生成
const result = await generator.generate({
...params,
progressCallback
} as TypeScriptTypesGeneratorOptions);
// 处理结果
if (result.success) {
console.log(`[TypeScriptTypesGeneratorTool] 类型生成成功,生成了 ${result.files.length} 个文件`);
return {
content: [
{
type: 'text' as const,
text: JSON.stringify({
success: true,
files: result.files,
warnings: result.warnings,
progress: 1.0,
progressMessage: '完成'
}, null, 2)
}
]
};
} else {
console.error(`[TypeScriptTypesGeneratorTool] 类型生成失败: ${result.error}`);
return {
content: [
{
type: 'text' as const,
text: JSON.stringify({
success: false,
error: result.error,
progress: progress,
progressMessage: progressMessage
}, null, 2)
}
]
};
}
} catch (error) {
console.error(`[TypeScriptTypesGeneratorTool] 执行异常:`, error);
// 返回错误结果
return {
content: [
{
type: 'text' as const,
text: JSON.stringify({
success: false,
error: error instanceof Error ? error.message : String(error),
progress: progress,
progressMessage: progressMessage
}, null, 2)
}
]
};
}
}
}
```
--------------------------------------------------------------------------------
/src/tools/template-manager-tool.ts:
--------------------------------------------------------------------------------
```typescript
/**
* Template Manager MCP Tool
* Provides template query, add, update and delete functionality
*/
import { z } from 'zod';
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { TemplateManager, TemplateType, FrameworkType, Template } from '../templates/template-manager';
// MCP tool names and descriptions
const TEMPLATE_LIST_TOOL_NAME = 'template-list';
const TEMPLATE_LIST_TOOL_DESCRIPTION = 'Get available code generation template list';
const TEMPLATE_GET_TOOL_NAME = 'template-get';
const TEMPLATE_GET_TOOL_DESCRIPTION = 'Get specific template content';
const TEMPLATE_SAVE_TOOL_NAME = 'template-save';
const TEMPLATE_SAVE_TOOL_DESCRIPTION = 'Save or update template';
const TEMPLATE_DELETE_TOOL_NAME = 'template-delete';
const TEMPLATE_DELETE_TOOL_DESCRIPTION = 'Delete custom template';
/**
* Template Manager Tool Class
*/
export class TemplateManagerTool {
private templateManager: TemplateManager;
private initialized: boolean = false;
constructor() {
this.templateManager = new TemplateManager();
}
/**
* Register tools on the MCP server
*/
async register(server: McpServer) {
// 确保模板管理器已初始化
if (!this.initialized) {
await this.templateManager.initialize();
this.initialized = true;
}
// 注册获取模板列表工具
server.tool(
TEMPLATE_LIST_TOOL_NAME,
TEMPLATE_LIST_TOOL_DESCRIPTION,
{
type: z.enum(['all', 'api-client', 'typescript-types', 'config-file']).optional().describe('Template type filter'),
framework: z.enum(['axios', 'fetch', 'react-query', 'swr', 'angular', 'vue']).optional().describe('Framework type filter (only for API client and config file templates)'),
includeContent: z.boolean().optional().describe('Whether to include template content')
},
async (params) => {
return await this.listTemplates(params);
}
);
// 注册获取单个模板工具
server.tool(
TEMPLATE_GET_TOOL_NAME,
TEMPLATE_GET_TOOL_DESCRIPTION,
{
id: z.string().describe('Template ID'),
},
async (params) => {
return await this.getTemplate(params);
}
);
// 注册保存模板工具
server.tool(
TEMPLATE_SAVE_TOOL_NAME,
TEMPLATE_SAVE_TOOL_DESCRIPTION,
{
id: z.string().describe('Template ID'),
name: z.string().describe('Template name'),
type: z.enum(['api-client', 'typescript-types', 'config-file']).describe('Template type'),
framework: z.enum(['axios', 'fetch', 'react-query', 'swr', 'angular', 'vue']).optional().describe('Framework type (only for API client and config file templates)'),
content: z.string().describe('Template content'),
description: z.string().optional().describe('Template description')
},
async (params) => {
return await this.saveTemplate(params);
}
);
// 注册删除模板工具
server.tool(
TEMPLATE_DELETE_TOOL_NAME,
TEMPLATE_DELETE_TOOL_DESCRIPTION,
{
id: z.string().describe('Template ID')
},
async (params) => {
return await this.deleteTemplate(params);
}
);
console.log(`✅ 已注册模板管理器工具: ${TEMPLATE_LIST_TOOL_NAME}, ${TEMPLATE_GET_TOOL_NAME}, ${TEMPLATE_SAVE_TOOL_NAME}, ${TEMPLATE_DELETE_TOOL_NAME}`);
}
/**
* 获取模板列表
*/
private async listTemplates(params: {
type?: string;
framework?: string;
includeContent?: boolean;
}): Promise<any> {
try {
let templates: Template[] = [];
// 根据类型过滤
if (params.type && params.type !== 'all') {
const templateType = params.type as TemplateType;
templates = this.templateManager.getTemplatesByType(templateType);
// 根据框架类型进一步过滤
if (params.framework && (templateType === TemplateType.API_CLIENT || templateType === TemplateType.CONFIG_FILE)) {
const frameworkType = params.framework as FrameworkType;
templates = templates.filter(template => template.framework === frameworkType);
}
} else {
templates = this.templateManager.getAllTemplates();
// 根据框架类型过滤
if (params.framework) {
const frameworkType = params.framework as FrameworkType;
templates = templates.filter(template => template.framework === frameworkType);
}
}
// 处理返回结果
const result = templates.map(template => {
const { content, ...rest } = template;
// 如果不需要包含内容,则省略
if (!params.includeContent) {
return rest;
}
return template;
});
return {
content: [
{
type: 'text' as const,
text: JSON.stringify({
success: true,
templates: result
}, null, 2)
}
]
};
} catch (error) {
console.error('[TemplateManagerTool] 获取模板列表失败:', error);
return {
content: [
{
type: 'text' as const,
text: JSON.stringify({
success: false,
error: error instanceof Error ? error.message : String(error)
}, null, 2)
}
]
};
}
}
/**
* 获取模板
*/
private async getTemplate(params: { id: string }): Promise<any> {
try {
const template = this.templateManager.getTemplate(params.id);
if (!template) {
return {
content: [
{
type: 'text' as const,
text: JSON.stringify({
success: false,
error: `Template not found with ID: ${params.id}`
}, null, 2)
}
]
};
}
return {
content: [
{
type: 'text' as const,
text: JSON.stringify({
success: true,
template
}, null, 2)
}
]
};
} catch (error) {
console.error('[TemplateManagerTool] 获取模板失败:', error);
return {
content: [
{
type: 'text' as const,
text: JSON.stringify({
success: false,
error: error instanceof Error ? error.message : String(error)
}, null, 2)
}
]
};
}
}
/**
* 保存模板
*/
private async saveTemplate(params: {
id: string;
name: string;
type: string;
framework?: string;
content: string;
description?: string;
}): Promise<any> {
try {
const template = {
id: params.id,
name: params.name,
type: params.type as TemplateType,
framework: params.framework as FrameworkType | undefined,
content: params.content,
description: params.description
};
const result = await this.templateManager.saveCustomTemplate(template);
return {
content: [
{
type: 'text' as const,
text: JSON.stringify({
success: true,
template: result
}, null, 2)
}
]
};
} catch (error) {
console.error('[TemplateManagerTool] 保存模板失败:', error);
return {
content: [
{
type: 'text' as const,
text: JSON.stringify({
success: false,
error: error instanceof Error ? error.message : String(error)
}, null, 2)
}
]
};
}
}
/**
* 删除模板
*/
private async deleteTemplate(params: { id: string }): Promise<any> {
try {
const success = await this.templateManager.deleteCustomTemplate(params.id);
if (!success) {
return {
content: [
{
type: 'text' as const,
text: JSON.stringify({
success: false,
error: `Failed to delete template with ID: ${params.id}. It may be a built-in template or not exist.`
}, null, 2)
}
]
};
}
return {
content: [
{
type: 'text' as const,
text: JSON.stringify({
success: true,
message: `Template with ID: ${params.id} has been deleted.`
}, null, 2)
}
]
};
} catch (error) {
console.error('[TemplateManagerTool] 删除模板失败:', error);
return {
content: [
{
type: 'text' as const,
text: JSON.stringify({
success: false,
error: error instanceof Error ? error.message : String(error)
}, null, 2)
}
]
};
}
}
}
```
--------------------------------------------------------------------------------
/src/tools/optimized-swagger-parser-tool.ts:
--------------------------------------------------------------------------------
```typescript
/**
* Optimized Swagger Parser MCP Tool
*/
import { z } from 'zod';
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { OptimizedSwaggerApiParser } from '../optimized-swagger-parser';
// MCP tool names and descriptions
const OPTIMIZED_SWAGGER_PARSER_TOOL_NAME = 'parse-swagger-optimized';
const OPTIMIZED_SWAGGER_PARSER_TOOL_DESCRIPTION = 'Parse Swagger/OpenAPI document using optimized parser with caching and large document support.';
// Lite version tool names and descriptions
const LITE_SWAGGER_PARSER_TOOL_NAME = 'parse-swagger-lite';
const LITE_SWAGGER_PARSER_TOOL_DESCRIPTION = 'Lightweight parsing of Swagger/OpenAPI document, faster but returns only basic information (suitable for large documents).';
/**
* Optimized Swagger Parser Tool Class
*/
export class OptimizedSwaggerParserTool {
name = OPTIMIZED_SWAGGER_PARSER_TOOL_NAME;
description = OPTIMIZED_SWAGGER_PARSER_TOOL_DESCRIPTION;
// Define parameter schema
schema = z.object({
/**
* Swagger/OpenAPI document URL
*/
url: z.string().describe('Swagger/OpenAPI document URL'),
/**
* Request headers
*/
headers: z.record(z.string()).optional().describe('Request headers'),
/**
* Whether to include schema definitions
*/
includeSchemas: z.boolean().optional().describe('Whether to include schema definitions'),
/**
* Whether to include all details
*/
includeDetails: z.boolean().optional().describe('Whether to include all details like request bodies, responses, etc.'),
/**
* Whether to skip validation
*/
skipValidation: z.boolean().optional().describe('Whether to skip validation, used for handling non-fully compliant API documents'),
/**
* Whether to use cache
*/
useCache: z.boolean().optional().describe('Whether to use cache'),
/**
* Cache TTL in minutes
*/
cacheTTLMinutes: z.number().optional().describe('Cache TTL in minutes'),
/**
* Whether to use lazy loading for schema parsing
*/
lazyLoading: z.boolean().optional().describe('Whether to use lazy loading for schema parsing'),
/**
* Filter operations by tag
*/
filterTag: z.string().optional().describe('Filter operations by tag'),
/**
* Filter operations by path prefix
*/
pathPrefix: z.string().optional().describe('Filter operations by path prefix'),
});
/**
* Register tool on the MCP server
*/
register(server: McpServer) {
// 注册完整版解析工具
server.tool(
this.name,
this.description,
this.schema.shape,
async ({
url,
headers = {},
includeSchemas = false,
includeDetails = false,
skipValidation = true,
useCache = true,
cacheTTLMinutes = 60,
lazyLoading = false,
filterTag,
pathPrefix
}) => {
return await this.execute({
url,
headers,
includeSchemas,
includeDetails,
skipValidation,
useCache,
cacheTTLMinutes,
lazyLoading,
filterTag,
pathPrefix
});
}
);
// 注册轻量版解析工具
server.tool(
LITE_SWAGGER_PARSER_TOOL_NAME,
LITE_SWAGGER_PARSER_TOOL_DESCRIPTION,
this.schema.shape,
async ({
url,
headers = {},
includeSchemas = false,
includeDetails = false,
skipValidation = true,
useCache = true,
cacheTTLMinutes = 60,
filterTag,
pathPrefix
}) => {
return await this.execute({
url,
headers,
includeSchemas,
includeDetails,
skipValidation,
useCache,
cacheTTLMinutes,
lazyLoading: true, // 强制使用懒加载
filterTag,
pathPrefix
});
}
);
}
/**
* Execute Swagger parsing
*/
async execute({
url,
headers = {},
includeSchemas = false,
includeDetails = false,
skipValidation = true,
useCache = true,
cacheTTLMinutes = 60,
lazyLoading = false,
filterTag,
pathPrefix
}: z.infer<typeof this.schema> & {
cacheTTLMinutes?: number;
}) {
let progress = 0;
let progressMessage = '';
// 进度回调函数
const progressCallback = (newProgress: number, message: string) => {
progress = newProgress;
progressMessage = message;
console.log(`[Progress] ${Math.round(newProgress * 100)}%: ${message}`);
};
try {
console.log(`[OptimizedSwaggerParserTool] 解析Swagger文档: ${url}`);
console.log(`[OptimizedSwaggerParserTool] 缓存: ${useCache ? '启用' : '禁用'}, 懒加载: ${lazyLoading ? '启用' : '禁用'}`);
// 创建解析器实例
const parser = new OptimizedSwaggerApiParser({
url,
headers,
skipValidation,
useCache,
cacheTTL: cacheTTLMinutes * 60 * 1000, // 转换为毫秒
lazyLoading,
progressCallback
});
// 解析API文档
const api = await parser.fetchApi();
// 获取API操作
let operations;
if (filterTag) {
operations = await parser.getOperationsByTag(filterTag);
} else if (pathPrefix) {
operations = await parser.getOperationsByPathPrefix(pathPrefix);
} else {
operations = await parser.getAllOperations();
}
// 构建结果对象
const result: any = {
success: true,
progress: progress,
progressMessage: progressMessage,
info: {
title: api.info.title,
version: api.info.version,
description: api.info.description
},
operationsCount: operations.length,
operations: operations.map(op => {
// 基本操作信息
const operation = {
operationId: op.operationId,
method: op.method,
path: op.path,
summary: op.summary,
tags: op.tags
};
// 如果需要详细信息,则包含参数和响应
if (includeDetails) {
return {
...operation,
parameters: op.parameters,
requestBody: op.requestBody,
responses: op.responses
};
}
return operation;
})
};
// 如果需要模式定义
if (includeSchemas) {
if (lazyLoading) {
// 使用懒加载时,只获取必要的schema
result.schemas = {};
// 获取所有操作中引用的模式
const referencedSchemas = new Set<string>();
// 处理requestBody和responses中的引用
for (const op of operations) {
// 处理requestBody
if (op.requestBody && typeof op.requestBody === 'object') {
this.collectSchemaRefs(op.requestBody, referencedSchemas);
}
// 处理responses
if (op.responses) {
for (const response of Object.values(op.responses)) {
if (response && typeof response === 'object') {
this.collectSchemaRefs(response, referencedSchemas);
}
}
}
}
// 获取引用的模式
for (const schemaName of referencedSchemas) {
const schema = await parser.getSchema(schemaName);
if (schema) {
result.schemas[schemaName] = schema;
}
}
} else {
// 不使用懒加载时,获取所有模式
result.schemas = await parser.getAllSchemas();
}
}
console.log(`[OptimizedSwaggerParserTool] 解析完成,找到 ${operations.length} 个API操作`);
// 返回结果
return {
content: [
{
type: 'text' as const,
text: JSON.stringify(result, null, 2)
}
]
};
} catch (error) {
console.error(`[OptimizedSwaggerParserTool] 解析失败:`, error);
// 返回错误结果
return {
content: [
{
type: 'text' as const,
text: JSON.stringify({
success: false,
progress: progress,
progressMessage: progressMessage,
error: error instanceof Error ? error.message : String(error)
}, null, 2)
}
]
};
}
}
/**
* Collect schema references
*/
private collectSchemaRefs(obj: any, refs: Set<string>): void {
if (!obj) return;
// 处理直接引用
if (obj.$ref && typeof obj.$ref === 'string') {
const parts = obj.$ref.split('/');
const schemaName = parts[parts.length - 1];
refs.add(schemaName);
return;
}
// 处理内容对象
if (obj.content && typeof obj.content === 'object') {
for (const mediaType of Object.values(obj.content)) {
if (mediaType && typeof mediaType === 'object' && 'schema' in mediaType) {
this.collectSchemaRefs((mediaType as any).schema, refs);
}
}
}
// 处理模式对象
if (obj.schema) {
this.collectSchemaRefs(obj.schema, refs);
}
// 处理数组项
if (obj.items) {
this.collectSchemaRefs(obj.items, refs);
}
// 处理嵌套对象
if (typeof obj === 'object') {
for (const value of Object.values(obj)) {
if (value && typeof value === 'object') {
this.collectSchemaRefs(value, refs);
}
}
}
}
/**
* Clear cache
*/
static clearCache(url?: string): void {
OptimizedSwaggerApiParser.clearCache(url);
}
}
```