Skip to main content
Glama
rizaqpratama

CucumberStudio MCP Server

by rizaqpratama
mcpService.js12.8 kB
const cucumberStudioClient = require('./cucumberStudioClient'); const { logger } = require('../utils/logger'); /** * MCP Service * Handles operations for the Model Context Protocol */ class MCPService { /** * Get context based on query * @param {Object} query - The context query * @returns {Promise<Object>} Context data */ async getContext(query) { logger.info(`Getting context with query: ${JSON.stringify(query)}`); try { const { projectId, featureId, scenarioId, type } = query; // Validate required parameters based on type if (!type) { throw new Error('Query type is required'); } // Handle different query types switch (type) { case 'projects': return await this.getProjectsContext(); case 'project': if (!projectId) { throw new Error('Project ID is required for project context'); } return await this.getProjectContext(projectId); case 'features': if (!projectId) { throw new Error('Project ID is required for features context'); } return await this.getFeaturesContext(projectId); case 'feature': if (!projectId || !featureId) { throw new Error('Project ID and Feature ID are required for feature context'); } return await this.getFeatureContext(projectId, featureId); case 'scenarios': if (!projectId || !featureId) { throw new Error('Project ID and Feature ID are required for scenarios context'); } return await this.getScenariosContext(projectId, featureId); case 'scenario': if (!projectId || !scenarioId) { throw new Error('Project ID and Scenario ID are required for scenario context'); } return await this.getScenarioContext(projectId, scenarioId); default: throw new Error(`Unsupported context type: ${type}`); } } catch (error) { logger.error(`Error getting context: ${error.message}`); throw error; } } /** * Get context about all projects * @returns {Promise<Object>} Projects context */ async getProjectsContext() { try { const projects = await cucumberStudioClient.getProjects(); return { type: 'projects', data: projects, metadata: { count: projects.length, timestamp: new Date().toISOString() } }; } catch (error) { logger.error('Error getting projects context', error); throw error; } } /** * Get context about a specific project * @param {string} projectId - Project ID * @returns {Promise<Object>} Project context */ async getProjectContext(projectId) { try { const project = await cucumberStudioClient.getProject(projectId); const features = await cucumberStudioClient.getFeatures(projectId); const folders = await cucumberStudioClient.getFolders(projectId); const tags = await cucumberStudioClient.getTags(projectId); return { type: 'project', data: { project, features: { count: features.length, items: features.map(f => ({ id: f.id, name: f.name, description: f.description })) }, folders: { count: folders.length, items: folders }, tags: { count: tags.length, items: tags } }, metadata: { timestamp: new Date().toISOString() } }; } catch (error) { logger.error(`Error getting project context for ${projectId}`, error); throw error; } } /** * Get context about features in a project * @param {string} projectId - Project ID * @returns {Promise<Object>} Features context */ async getFeaturesContext(projectId) { try { const features = await cucumberStudioClient.getFeatures(projectId); return { type: 'features', data: features, metadata: { projectId, count: features.length, timestamp: new Date().toISOString() } }; } catch (error) { logger.error(`Error getting features context for project ${projectId}`, error); throw error; } } /** * Get context about a specific feature * @param {string} projectId - Project ID * @param {string} featureId - Feature ID * @returns {Promise<Object>} Feature context */ async getFeatureContext(projectId, featureId) { try { const feature = await cucumberStudioClient.getFeature(projectId, featureId); const scenarios = await cucumberStudioClient.getScenarios(projectId, featureId); return { type: 'feature', data: { feature, scenarios: { count: scenarios.length, items: scenarios } }, metadata: { projectId, timestamp: new Date().toISOString() } }; } catch (error) { logger.error(`Error getting feature context for ${featureId}`, error); throw error; } } /** * Get context about scenarios in a feature * @param {string} projectId - Project ID * @param {string} featureId - Feature ID * @returns {Promise<Object>} Scenarios context */ async getScenariosContext(projectId, featureId) { try { const scenarios = await cucumberStudioClient.getScenarios(projectId, featureId); return { type: 'scenarios', data: scenarios, metadata: { projectId, featureId, count: scenarios.length, timestamp: new Date().toISOString() } }; } catch (error) { logger.error(`Error getting scenarios context for feature ${featureId}`, error); throw error; } } /** * Get context about a specific scenario * @param {string} projectId - Project ID * @param {string} scenarioId - Scenario ID * @returns {Promise<Object>} Scenario context */ async getScenarioContext(projectId, scenarioId) { try { const scenario = await cucumberStudioClient.getScenario(projectId, scenarioId); return { type: 'scenario', data: scenario, metadata: { projectId, timestamp: new Date().toISOString() } }; } catch (error) { logger.error(`Error getting scenario context for ${scenarioId}`, error); throw error; } } /** * Apply changes to CucumberStudio resources * @param {Object} changes - Changes to apply * @returns {Promise<Object>} Result of applying changes */ async applyChanges(changes) { logger.info(`Applying changes: ${JSON.stringify(changes)}`); try { const { type, projectId, data } = changes; if (!type || !projectId || !data) { throw new Error('Type, project ID, and data are required'); } // Handle different change types switch (type) { case 'createScenario': return await this.createScenario(projectId, data); case 'updateScenario': if (!data.id) { throw new Error('Scenario ID is required for scenario update'); } return await this.updateScenario(projectId, data.id, data); case 'deleteScenario': if (!data.id) { throw new Error('Scenario ID is required for scenario deletion'); } return await this.deleteScenario(projectId, data.id); default: throw new Error(`Unsupported change type: ${type}`); } } catch (error) { logger.error(`Error applying changes: ${error.message}`); throw error; } } /** * Create a new scenario * @param {string} projectId - Project ID * @param {Object} scenarioData - Scenario data * @returns {Promise<Object>} Created scenario */ async createScenario(projectId, scenarioData) { try { const scenario = await cucumberStudioClient.createScenario(projectId, scenarioData); return { type: 'createScenario', data: scenario, metadata: { projectId, timestamp: new Date().toISOString() } }; } catch (error) { logger.error(`Error creating scenario in project ${projectId}`, error); throw error; } } /** * Update a scenario * @param {string} projectId - Project ID * @param {string} scenarioId - Scenario ID * @param {Object} scenarioData - Scenario data * @returns {Promise<Object>} Updated scenario */ async updateScenario(projectId, scenarioId, scenarioData) { try { const scenario = await cucumberStudioClient.updateScenario(projectId, scenarioId, scenarioData); return { type: 'updateScenario', data: scenario, metadata: { projectId, scenarioId, timestamp: new Date().toISOString() } }; } catch (error) { logger.error(`Error updating scenario ${scenarioId}`, error); throw error; } } /** * Delete a scenario * @param {string} projectId - Project ID * @param {string} scenarioId - Scenario ID * @returns {Promise<Object>} Result of deletion */ async deleteScenario(projectId, scenarioId) { try { await cucumberStudioClient.deleteScenario(projectId, scenarioId); return { type: 'deleteScenario', data: { id: scenarioId, deleted: true }, metadata: { projectId, scenarioId, timestamp: new Date().toISOString() } }; } catch (error) { logger.error(`Error deleting scenario ${scenarioId}`, error); throw error; } } /** * Get schema information for the MCP server * @returns {Object} Schema information */ getSchema() { return { name: 'CucumberStudio MCP Server', version: '1.0.0', description: 'Model Context Protocol server for CucumberStudio API', contextTypes: [ { type: 'projects', description: 'Get information about all projects', parameters: {} }, { type: 'project', description: 'Get information about a specific project, including its features, folders, and tags', parameters: { projectId: 'string' } }, { type: 'features', description: 'Get information about all features in a project', parameters: { projectId: 'string' } }, { type: 'feature', description: 'Get information about a specific feature, including its scenarios', parameters: { projectId: 'string', featureId: 'string' } }, { type: 'scenarios', description: 'Get information about all scenarios in a feature', parameters: { projectId: 'string', featureId: 'string' } }, { type: 'scenario', description: 'Get information about a specific scenario', parameters: { projectId: 'string', scenarioId: 'string' } } ], changeTypes: [ { type: 'createScenario', description: 'Create a new scenario', parameters: { projectId: 'string', data: { name: 'string', description: 'string', featureId: 'string', folderIds: 'string[]', tagIds: 'string[]', language: 'string', steps: 'object[]' } } }, { type: 'updateScenario', description: 'Update an existing scenario', parameters: { projectId: 'string', data: { id: 'string', name: 'string', description: 'string', featureId: 'string', folderIds: 'string[]', tagIds: 'string[]', language: 'string', steps: 'object[]' } } }, { type: 'deleteScenario', description: 'Delete a scenario', parameters: { projectId: 'string', data: { id: 'string' } } } ] }; } } // Export a singleton instance module.exports = new MCPService();

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/rizaqpratama/mcp-cucumberstudio'

If you have feedback or need assistance with the MCP directory API, please join our Discord server