UNPKG

@utaba/ucm-mcp-server

Version:

Universal Context Manager MCP Server - AI-native artifact management

125 lines 6.75 kB
import { BaseToolController } from '../base/BaseToolController.js'; import { McpError, McpErrorCode } from '../../utils/McpErrorHandler.js'; export class CreateRepositoryTool extends BaseToolController { constructor(ucmClient, logger, publishingAuthorId) { super(ucmClient, logger, publishingAuthorId); } get name() { return 'mcp_ucm_create_repository'; } get description() { const authorInfo = this.publishingAuthorId ? ` Your author id is '${this.publishingAuthorId}'.` : ''; return `Create a new repository for a specific author. Repository names must be unique within the author namespace and follow UCM naming conventions (3-200 characters, start with letter, alphanumeric and hyphens only, no consecutive hyphens).${authorInfo}`; } get inputSchema() { return { type: 'object', properties: { author: { type: 'string', description: this.publishingAuthorId ? `Author identifier: ${this.publishingAuthorId}` : 'Author identifier (e.g., "utaba", "1064600359")', minLength: 1, maxLength: 50 }, repositoryName: { type: 'string', description: 'Unique repository name (3-200 characters, start with letter, alphanumeric and hyphens only)', minLength: 3, maxLength: 200, pattern: '^[a-z][a-z0-9-]{2,199}$' }, displayName: { type: 'string', description: 'Human-readable display name for the repository (optional)', maxLength: 255 }, description: { type: 'string', description: 'Repository description (optional)', maxLength: 1000 }, isPublic: { type: 'boolean', description: 'Whether the repository is public (defaults to false, public repositories not yet supported)', default: false } }, required: ['author', 'repositoryName'], additionalProperties: false }; } validateParams(params) { super.validateParams(params); // Additional validation if (!params.author || typeof params.author !== 'string' || params.author.trim() === '') { throw new McpError(McpErrorCode.InvalidParams, 'Author identifier is required and cannot be empty'); } if (!params.repositoryName || typeof params.repositoryName !== 'string' || params.repositoryName.trim() === '') { throw new McpError(McpErrorCode.InvalidParams, 'Repository name is required and cannot be empty'); } // Validate repository name format const namePattern = /^[a-z][a-z0-9-]{2,199}$/; if (!namePattern.test(params.repositoryName)) { throw new McpError(McpErrorCode.InvalidParams, 'Repository name must be 3-200 characters, start with a lowercase letter, and contain only lowercase letters, numbers, and hyphens (no consecutive hyphens)'); } // Check for consecutive hyphens if (params.repositoryName.includes('--')) { throw new McpError(McpErrorCode.InvalidParams, 'Repository name cannot contain consecutive hyphens'); } // Validate displayName length if provided if (params.displayName && params.displayName.length > 255) { throw new McpError(McpErrorCode.InvalidParams, 'Display name cannot exceed 255 characters'); } // Validate description length if provided if (params.description && params.description.length > 1000) { throw new McpError(McpErrorCode.InvalidParams, 'Description cannot exceed 1,000 characters'); } // Validate isPublic - public repositories are not yet supported if (params.isPublic === true) { throw new McpError(McpErrorCode.InvalidParams, 'Public repositories are not yet supported. Set isPublic to false or omit the parameter.'); } } async handleExecute(params) { this.logger.info('CreateRepositoryTool', `Creating repository ${params.repositoryName} for author ${params.author}`); try { const repositoryData = { repositoryName: params.repositoryName, displayName: params.displayName, description: params.description, isPublic: params.isPublic || false }; const result = await this.ucmClient.createRepository(params.author, repositoryData); this.logger.info('CreateRepositoryTool', `Repository created successfully: ${params.repositoryName}`); return { content: [ { type: 'text', text: JSON.stringify({ success: true, message: `Repository '${params.repositoryName}' created successfully for author '${params.author}'`, repository: result, webUrl: `${process.env.NEXT_PUBLIC_BASE_URL || 'http://localhost:3000'}/repository/${result.id || params.repositoryName}` }, null, 2) } ] }; } catch (error) { this.logger.error('CreateRepositoryTool', 'Failed to create repository', '', error); const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred'; // Handle specific error cases if (errorMessage.includes('already exists') || errorMessage.includes('NAME_EXISTS')) { throw new McpError(McpErrorCode.InvalidParams, `Repository name '${params.repositoryName}' already exists for author '${params.author}'. Please choose a different name.`); } if (errorMessage.includes('not found') || errorMessage.includes('404')) { throw new McpError(McpErrorCode.InvalidParams, `Author '${params.author}' not found. Please verify the author identifier.`); } if (errorMessage.includes('validation') || errorMessage.includes('invalid')) { throw new McpError(McpErrorCode.InvalidParams, `Repository creation failed due to validation error: ${errorMessage}`); } // Generic error throw new McpError(McpErrorCode.InternalError, `Failed to create repository: ${errorMessage}`); } } } //# sourceMappingURL=CreateRepositoryTool.js.map