UNPKG

bottlenecks-mcp-server

Version:

Model Context Protocol server for Bottlenecks database - enables AI agents like Claude to interact with bottleneck data

391 lines 17.9 kB
/** * MCP Schema Tools * Provides AI agents with data structure and validation information */ /** * Get the complete bottleneck data schema */ export function createGetBottleneckSchemaTool(client) { return { type: 'call_tool', name: 'get_bottleneck_schema', description: 'Get the complete data schema for bottleneck objects, including all fields, types, and validation rules', inputSchema: { type: 'object', properties: { include_examples: { type: 'boolean', description: 'Include example values for each field', default: true, }, format: { type: 'string', description: 'Response format', enum: ['json', 'typescript', 'markdown'], default: 'markdown', }, }, required: [], }, handler: async (args) => { try { // For now, we'll create the schema based on our database structure // In the future, this could call /api/mcp/schema endpoint const schema = { name: 'Bottleneck', description: 'A bottleneck represents a constraint, limitation, or inefficiency in a system', fields: { id: { type: 'string', format: 'uuid', description: 'Unique identifier for the bottleneck', required: true, readonly: true, example: '123e4567-e89b-12d3-a456-426614174000', }, title: { type: 'string', description: 'Clear, descriptive title of the bottleneck', required: true, minLength: 5, maxLength: 200, example: 'Database Query Performance Bottleneck', }, slug: { type: 'string', description: 'URL-friendly identifier, auto-generated from title', required: true, readonly: true, pattern: '^[a-z0-9-]+$', example: 'database-query-performance-bottleneck', }, description: { type: 'string', format: 'mdx', description: 'Detailed description using MDX format with sections', required: true, minLength: 50, example: 'Use get_bottleneck_template to get the proper MDX format', }, tags: { type: 'array', items: { type: 'string' }, description: 'Categorization tags for the bottleneck', required: false, maxItems: 10, example: ['performance', 'database', 'scalability'], }, is_public: { type: 'boolean', description: 'Whether the bottleneck is publicly visible', required: true, default: false, example: true, }, author_id: { type: 'string', format: 'uuid', description: 'ID of the user who created this bottleneck', required: true, readonly: true, example: '456e7890-e89b-12d3-a456-426614174001', }, organization_id: { type: 'string', format: 'uuid', description: 'ID of the organization this bottleneck belongs to', required: false, example: '789e0123-e89b-12d3-a456-426614174002', }, created_at: { type: 'string', format: 'date-time', description: 'When the bottleneck was created', required: true, readonly: true, example: '2024-01-15T10:30:00Z', }, updated_at: { type: 'string', format: 'date-time', description: 'When the bottleneck was last updated', required: true, readonly: true, example: '2024-01-16T14:22:00Z', }, file_attachments: { type: 'array', items: { $ref: '#/definitions/FileAttachment' }, description: 'Files attached to this bottleneck', required: false, readonly: true, example: [], }, }, definitions: { FileAttachment: { type: 'object', properties: { id: { type: 'string', format: 'uuid' }, filename: { type: 'string' }, original_filename: { type: 'string' }, file_type: { type: 'string' }, file_size: { type: 'number' }, mime_type: { type: 'string' }, upload_type: { type: 'string', enum: [ 'attachment', 'research_data', 'image', 'reference_doc', ], }, description: { type: 'string' }, is_public: { type: 'boolean' }, processing_status: { type: 'string', enum: ['pending', 'processing', 'completed', 'failed'], }, created_at: { type: 'string', format: 'date-time' }, }, }, }, validation_rules: { title: [ 'Must be between 5 and 200 characters', 'Should be descriptive and specific', 'Avoid generic terms like "bottleneck" in the title', ], description: [ 'Must be at least 50 characters', 'Should use MDX format with sections', 'Required sections: details', 'Optional sections: impact, efforts, related, forecast, considerations, contributors', ], tags: [ 'Maximum 10 tags per bottleneck', 'Tags should be lowercase, hyphenated', 'Use existing taxonomy when possible', ], }, }; let content = ''; if (args.format === 'json') { content = JSON.stringify(schema, null, 2); } else if (args.format === 'typescript') { content = `// Bottleneck TypeScript Interface\n\n`; content += `interface Bottleneck {\n`; Object.entries(schema.fields).forEach(([key, field]) => { const optional = !field.required ? '?' : ''; const readonly = field.readonly ? 'readonly ' : ''; content += ` ${readonly}${key}${optional}: ${field.type};\n`; }); content += `}\n\n`; content += `interface FileAttachment {\n`; Object.entries(schema.definitions.FileAttachment.properties).forEach(([key, field]) => { content += ` ${key}: ${field.type};\n`; }); content += `}\n`; } else { // Markdown format (default) content += `# Bottleneck Data Schema\n\n`; content += `${schema.description}\n\n`; content += `## Core Fields\n\n`; Object.entries(schema.fields).forEach(([key, field]) => { content += `### ${key}\n`; content += `- **Type:** ${field.type}${field.format ? ` (${field.format})` : ''}\n`; content += `- **Required:** ${field.required ? 'Yes' : 'No'}\n`; if (field.readonly) content += `- **Read-only:** Yes\n`; if (field.default !== undefined) content += `- **Default:** ${field.default}\n`; content += `- **Description:** ${field.description}\n`; if (args.include_examples && field.example) { content += `- **Example:** \`${typeof field.example === 'string' ? field.example : JSON.stringify(field.example)}\`\n`; } content += '\n'; }); content += `## Validation Rules\n\n`; Object.entries(schema.validation_rules).forEach(([field, rules]) => { content += `### ${field}\n`; rules.forEach((rule) => { content += `- ${rule}\n`; }); content += '\n'; }); content += `## File Attachments\n\n`; content += `Bottlenecks can have multiple file attachments. Each attachment has:\n\n`; Object.entries(schema.definitions.FileAttachment.properties).forEach(([key, field]) => { content += `- **${key}**: ${field.type}`; if (field.enum) content += ` (${field.enum.join(', ')})`; content += '\n'; }); } return { content: [ { type: 'text', text: content, }, ], }; } catch (error) { return { content: [ { type: 'text', text: `Error in get_bottleneck_schema: ${error instanceof Error ? error.message : 'Unknown error'}`, }, ], isError: true, }; } }, }; } /** * Get taxonomy information (tags, categories, etc.) */ export function createGetTaxonomyTool(client) { return { type: 'call_tool', name: 'get_taxonomy', description: 'Get the taxonomy system including available tags, categories, and their relationships', inputSchema: { type: 'object', properties: { category: { type: 'string', description: 'Specific category to focus on', enum: ['all', 'domains', 'types', 'impacts', 'solutions'], }, include_counts: { type: 'boolean', description: 'Include usage counts for each tag', default: false, }, }, required: [], }, handler: async (args) => { try { // This would eventually call /api/mcp/taxonomy // For now, we'll provide a comprehensive taxonomy structure const taxonomy = { domains: [ 'software-engineering', 'data-science', 'machine-learning', 'devops', 'product-management', 'user-experience', 'business-operations', 'supply-chain', 'manufacturing', 'healthcare', 'finance', 'education', ], types: [ 'performance', 'scalability', 'reliability', 'security', 'usability', 'maintainability', 'cost', 'time', 'resource', 'process', 'communication', 'knowledge', 'skill', 'tool', 'infrastructure', ], impacts: [ 'high-impact', 'medium-impact', 'low-impact', 'critical', 'urgent', 'long-term', 'short-term', 'strategic', 'operational', 'customer-facing', 'internal', 'revenue-affecting', 'cost-affecting', ], solutions: [ 'automation', 'optimization', 'refactoring', 'scaling', 'caching', 'monitoring', 'training', 'documentation', 'tooling', 'process-improvement', 'architecture-change', 'resource-allocation', ], }; let content = `# Bottlenecks Taxonomy\n\n`; content += `This taxonomy helps categorize and organize bottlenecks for better discovery and analysis.\n\n`; const categoriesToShow = args.category === 'all' || !args.category ? Object.keys(taxonomy) : [args.category].filter((cat) => cat in taxonomy); categoriesToShow.forEach((category) => { if (!(category in taxonomy)) return; content += `## ${category.charAt(0).toUpperCase() + category.slice(1).replace('-', ' ')}\n\n`; const tags = taxonomy[category]; tags.forEach((tag) => { content += `- \`${tag}\``; if (args.include_counts) { // In a real implementation, this would query the database const mockCount = Math.floor(Math.random() * 50) + 1; content += ` (${mockCount} bottlenecks)`; } content += '\n'; }); content += '\n'; }); content += `## Usage Guidelines\n\n`; content += `- Use **domains** to indicate the field or industry\n`; content += `- Use **types** to categorize the nature of the bottleneck\n`; content += `- Use **impacts** to indicate severity and scope\n`; content += `- Use **solutions** to tag potential resolution approaches\n\n`; content += `**Example:** A bottleneck might be tagged with: \`software-engineering\`, \`performance\`, \`high-impact\`, \`optimization\`\n`; return { content: [ { type: 'text', text: content, }, ], }; } catch (error) { return { content: [ { type: 'text', text: `Error in get_taxonomy: ${error instanceof Error ? error.message : 'Unknown error'}`, }, ], isError: true, }; } }, }; } //# sourceMappingURL=schema.js.map