import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import {
CallToolRequestSchema,
ListToolsRequestSchema,
ListPromptsRequestSchema,
GetPromptRequestSchema
} from "@modelcontextprotocol/sdk/types.js";
import logger from "./utils/logger.js";
import { createTransport, getTransportConfig, validateTransportConfig, isTransportModeSupported } from './transport/TransportFactory.js';
// Import tool definitions and handlers
import { toolDefinitions,
handleGetSwaggerDefinition,
handleListEndpoints,
handleListEndpointModels,
handleGenerateModelCode,
handleGenerateEndpointToolCode,
handleDynamicSwaggerConfig,
handleSearchSwaggerEndpoints,
handleGetEndpointDetails,
handleGetSessionStats,
handleClearCache,
handleGetSearchSuggestions,
handleUnifiedSwagger // NEW: unified tool handler
} from "./tools/index.js";
// Import prompt definitions and handlers
import { promptDefinitions, promptHandlers } from "./prompts/index.js";
// Create MCP server
const server = new Server(
{
name: 'Improved Swagger MCP Server',
version: '2.0.0',
},
{
capabilities: {
tools: {},
prompts: {}
},
}
);
/**
* Handler that lists available tools.
* Exposes tools for interacting with Swagger API.
*/
server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: toolDefinitions
};
});
/**
* Handler that lists available prompts.
* Exposes prompts for guiding through common workflows.
*/
server.setRequestHandler(ListPromptsRequestSchema, async () => {
return {
prompts: promptDefinitions
};
});
/**
* Handler for getting a specific prompt.
* Returns the prompt template with messages.
*/
server.setRequestHandler(GetPromptRequestSchema, async (request) => {
try {
const promptName = request.params.name;
const promptArgs = request.params.arguments || {};
logger.info(`Prompt request received: ${promptName}`);
logger.info(`Prompt arguments: ${JSON.stringify(promptArgs)}`);
const promptHandler = promptHandlers[promptName];
if (!promptHandler) {
return {
error: {
code: -32601,
message: `Unknown prompt: ${promptName}`
}
};
}
// Validate arguments against schema
const validationResult = promptHandler.schema.safeParse(promptArgs);
if (!validationResult.success) {
return {
error: {
code: -32602,
message: `Invalid arguments: ${validationResult.error.message}`
}
};
}
// Call the prompt handler
const result = await promptHandler.handler(promptArgs);
return result;
} catch (error: any) {
logger.error(`MCP prompt error: ${error.message}`);
throw new Error(`Prompt execution failed: ${error.message}`);
}
});
/**
* Handler for tool calls.
* Processes requests to call Swagger API tools.
*/
server.setRequestHandler(CallToolRequestSchema, async (request) => {
try {
logger.info(`Tool call received: ${request.params.name}`);
logger.info(`Tool arguments: ${JSON.stringify(request.params.arguments || {})}`);
const name = request.params.name;
const input = request.params.arguments;
switch (name) {
// Original tools
case "getSwaggerDefinition":
return await handleGetSwaggerDefinition(input);
case "listEndpoints":
return await handleListEndpoints(input);
case "listEndpointModels":
return await handleListEndpointModels(input);
case "generateModelCode":
return await handleGenerateModelCode(input);
case "generateEndpointToolCode":
return await handleGenerateEndpointToolCode(input);
// New improved tools
case "configure_swagger_session":
return await handleDynamicSwaggerConfig(input);
case "search_swagger_endpoints":
return await handleSearchSwaggerEndpoints(input);
case "get_endpoint_details":
return await handleGetEndpointDetails(input);
case "get_session_stats":
return await handleGetSessionStats(input);
case "clear_swagger_cache":
return await handleClearCache(input);
case "get_search_suggestions":
return await handleGetSearchSuggestions(input);
// NEW: Unified tool (recommended for new usage)
case "swagger_explorer":
return await handleUnifiedSwagger(input);
default:
return {
content: [{
type: "text",
text: `Unknown tool: ${name}`
}]
};
}
} catch (error: any) {
logger.error(`MCP tool error: ${error.message}`);
throw new Error(`Tool execution failed: ${error.message}`);
}
});
/**
* Start the server using configured transport.
* This allows the server to communicate via various transport modes (stdio, sse, http).
*/
async function main() {
// Get transport configuration from environment
const transportConfig = getTransportConfig();
// Validate transport configuration
if (!validateTransportConfig(transportConfig)) {
logger.error(`Invalid transport configuration: ${JSON.stringify(transportConfig)}`);
process.exit(1);
}
// Check if transport mode is supported
if (!isTransportModeSupported(transportConfig.mode)) {
logger.error(`Transport mode '${transportConfig.mode}' is not yet implemented`);
logger.info(`Currently supported modes: stdio`);
process.exit(1);
}
// Create and connect the transport
const transport = createTransport(transportConfig);
await server.connect(transport);
logger.info(`MCP Server started with ${transportConfig.mode} transport`);
// For HTTP/SSE transports, we would need to keep the server running
// This is a placeholder for future HTTP server setup
if (transportConfig.mode === 'http' || transportConfig.mode === 'sse') {
logger.info(`HTTP/SSE server would listen on ${transportConfig.host}:${transportConfig.port}${transportConfig.path}`);
}
}
main().catch((error) => {
logger.error("Server error:", error);
process.exit(1);
});