Skip to main content
Glama

MCP Server Trello

javascript-examples.js17.4 kB
/** * JavaScript Examples for MCP Server Trello * * These examples demonstrate how to use the MCP Server Trello * with JavaScript/Node.js applications. */ // Example 1: Basic Setup and Configuration class TrelloMCPClient { constructor(serverName = 'trello') { this.serverName = serverName; } async callTool(toolName, /* args */) { // This would be replaced with your actual MCP client implementation // return await use_mcp_tool({ // server_name: this.serverName, // tool_name: toolName, // arguments: args, // }); return Promise.resolve({}); } } // Example 2: Sprint Management System class SprintManager { constructor(trelloClient) { this.trello = trelloClient; this.sprintNumber = null; this.sprintListId = null; } async initializeSprint(sprintNumber, startDate, endDate) { this.sprintNumber = sprintNumber; // Create sprint list const list = await this.trello.callTool('add_list_to_board', { name: `Sprint ${sprintNumber} (${startDate} - ${endDate})`, }); this.sprintListId = list.id; // Create sprint planning card const planningCard = await this.trello.callTool('add_card_to_list', { listId: this.sprintListId, name: `Sprint ${sprintNumber} Planning`, description: `# Sprint ${sprintNumber}\n\n**Duration**: ${startDate} to ${endDate}\n\n## Sprint Goals\n- [ ] Goal 1\n- [ ] Goal 2\n- [ ] Goal 3\n\n## Team Capacity\n- Dev: X points\n- QA: Y points`, dueDate: new Date(endDate).toISOString(), }); return { list, planningCard }; } async addTaskToSprint(task) { const card = await this.trello.callTool('add_card_to_list', { listId: this.sprintListId, name: task.name, description: task.description, labels: task.labels || ['sprint-task'], dueDate: task.dueDate, }); // Add acceptance criteria if (task.acceptanceCriteria) { for (const criteria of task.acceptanceCriteria) { await this.trello.callTool('add_checklist_item', { text: criteria, checkListName: 'Acceptance Criteria', }); } } return card; } async moveToInProgress(cardId) { const lists = await this.trello.callTool('get_lists', {}); const inProgressList = lists.find(l => l.name === 'In Progress'); if (inProgressList) { await this.trello.callTool('move_card', { cardId: cardId, listId: inProgressList.id, }); await this.trello.callTool('add_comment', { cardId: cardId, text: `Work started at ${new Date().toISOString()}`, }); } } async getSprintVelocity() { const cards = await this.trello.callTool('get_cards_by_list_id', { listId: this.sprintListId, }); let completed = 0; let total = cards.length; for (const card of cards) { const fullCard = await this.trello.callTool('get_card', { cardId: card.id, }); if (fullCard.dueComplete) { completed++; } } return { total, completed, velocity: (completed / total) * 100, }; } } // Example 3: Bug Tracking System class BugTracker { constructor(trelloClient) { this.trello = trelloClient; this.bugListId = null; } async initialize() { const lists = await this.trello.callTool('get_lists', {}); let bugList = lists.find(l => l.name === 'Bugs'); if (!bugList) { bugList = await this.trello.callTool('add_list_to_board', { name: 'Bugs', }); } this.bugListId = bugList.id; } async reportBug({ title, description, severity = 'medium', environment = 'production', stepsToReproduce = [], expectedBehavior, actualBehavior, screenshotUrl, userId, }) { // Determine priority based on severity const dueDateOffset = { critical: 1, // 1 day high: 3, // 3 days medium: 7, // 1 week low: 14, // 2 weeks }; const dueDate = new Date(); dueDate.setDate(dueDate.getDate() + (dueDateOffset[severity] || 7)); // Create bug card const bugCard = await this.trello.callTool('add_card_to_list', { listId: this.bugListId, name: `🐛 [${severity.toUpperCase()}] ${title}`, description: this.formatBugDescription({ description, environment, stepsToReproduce, expectedBehavior, actualBehavior, reportedBy: userId, reportedAt: new Date().toISOString(), }), labels: ['bug', severity, environment], dueDate: dueDate.toISOString(), }); // Add QA checklist const qaChecklist = [ 'Bug is reproducible', 'Root cause identified', 'Fix implemented', 'Unit tests added', 'Integration tests passed', 'Regression testing completed', 'Fix verified in staging', 'Documentation updated', ]; for (const item of qaChecklist) { await this.trello.callTool('add_checklist_item', { text: item, checkListName: 'QA Checklist', }); } // Attach screenshot if provided if (screenshotUrl) { await this.trello.callTool('attach_image_to_card', { cardId: bugCard.id, imageUrl: screenshotUrl, name: 'Bug Screenshot', }); } return bugCard; } formatBugDescription({ description, environment, stepsToReproduce, expectedBehavior, actualBehavior, reportedBy, reportedAt, }) { return `## Bug Report **Reported by**: ${reportedBy} **Date**: ${reportedAt} **Environment**: ${environment} ### Description ${description} ### Steps to Reproduce ${stepsToReproduce.map((step, i) => `${i + 1}. ${step}`).join('\n')} ### Expected Behavior ${expectedBehavior} ### Actual Behavior ${actualBehavior} ### Technical Details - Browser: [To be filled] - OS: [To be filled] - Version: [To be filled] ### Impact - Users affected: [To be estimated] - Business impact: [To be assessed]`; } async updateBugStatus(cardId, status, notes) { const statusToList = { triaged: 'Triaged', 'in-progress': 'In Progress', fixed: 'Fixed', verified: 'Verified', closed: 'Done', }; // Get the appropriate list const lists = await this.trello.callTool('get_lists', {}); const targetList = lists.find(l => l.name === statusToList[status]); if (targetList) { // Move card to new list await this.trello.callTool('move_card', { cardId: cardId, listId: targetList.id, }); // Add status update comment await this.trello.callTool('add_comment', { cardId: cardId, text: `**Status Update**: ${status}\n\n${notes}\n\nUpdated at: ${new Date().toISOString()}`, }); // Update labels const card = await this.trello.callTool('get_card', { cardId: cardId, }); const newLabels = card.labels.filter( l => !['triaged', 'in-progress', 'fixed', 'verified'].includes(l) ); newLabels.push(status); await this.trello.callTool('update_card_details', { cardId: cardId, labels: newLabels, }); } } async getBugMetrics() { const lists = await this.trello.callTool('get_lists', {}); const metrics = { total: 0, bySeverity: { critical: 0, high: 0, medium: 0, low: 0 }, byStatus: {}, overdue: [], }; for (const list of lists) { const cards = await this.trello.callTool('get_cards_by_list_id', { listId: list.id, }); const bugCards = cards.filter( card => card.labels && card.labels.some(label => label === 'bug' || label.name === 'bug') ); metrics.byStatus[list.name] = bugCards.length; metrics.total += bugCards.length; for (const card of bugCards) { // Count by severity for (const severity of ['critical', 'high', 'medium', 'low']) { if (card.labels.some(label => label === severity || label.name === severity)) { metrics.bySeverity[severity]++; } } // Check for overdue if (card.due && new Date(card.due) < new Date() && !card.dueComplete) { metrics.overdue.push({ name: card.name, due: card.due, list: list.name, }); } } } return metrics; } } // Example 4: Release Management class ReleaseManager { constructor(trelloClient) { this.trello = trelloClient; } async createRelease(version, targetDate, features = []) { // Create release card const releaseCard = await this.trello.callTool('add_card_to_list', { listId: 'releases-list-id', // You'd need to get this dynamically name: `Release v${version}`, description: this.formatReleaseNotes(version, targetDate, features), dueDate: new Date(targetDate).toISOString(), labels: ['release', 'milestone'], }); // Add release checklist const checklist = [ 'Code freeze announcement sent', 'Feature freeze confirmed', 'All PRs merged', 'Build pipeline successful', 'Automated tests passing', 'Security scan completed', 'Performance benchmarks met', 'Documentation updated', 'Release notes finalized', 'Staging deployment successful', 'UAT sign-off received', 'Production deployment approved', 'Deployment executed', 'Smoke tests passed', 'Monitoring alerts configured', 'Rollback plan tested', 'Stakeholders notified', ]; for (const item of checklist) { await this.trello.callTool('add_checklist_item', { text: item, checkListName: 'Release Checklist', }); } // Link feature cards for (const featureCardId of features) { await this.trello.callTool('add_comment', { cardId: featureCardId, text: `✅ Included in Release v${version}`, }); // Move to release column await this.trello.callTool('move_card', { cardId: featureCardId, listId: 'ready-for-release-list-id', }); } return releaseCard; } formatReleaseNotes(version, targetDate, features) { return `# Release v${version} **Target Date**: ${targetDate} **Status**: Planning ## Release Summary This release includes ${features.length} features and improvements. ## What's New - Feature 1 - Feature 2 - Improvements ## Bug Fixes - Fixed issue with... - Resolved problem in... ## Breaking Changes None ## Migration Guide No migration required ## Rollback Plan In case of critical issues: 1. Execute rollback script 2. Restore previous version 3. Notify stakeholders ## Deployment Schedule - **Code Freeze**: [Date] - **Staging Deployment**: [Date] - **Production Deployment**: ${targetDate} ## Stakeholders - Product: @product-team - Engineering: @eng-team - QA: @qa-team - DevOps: @devops-team`; } async updateReleaseProgress(releaseCardId) { // Get checklist status const card = await this.trello.callTool('get_card', { cardId: releaseCardId, }); // Calculate progress let totalItems = 0; let completedItems = 0; if (card.checklists) { for (const checklist of card.checklists) { totalItems += checklist.checkItems.length; completedItems += checklist.checkItems.filter(item => item.state === 'complete').length; } } const progress = totalItems > 0 ? (completedItems / totalItems) * 100 : 0; // Update card with progress await this.trello.callTool('add_comment', { cardId: releaseCardId, text: `📊 **Release Progress Update**\n\nProgress: ${progress.toFixed(1)}%\nCompleted: ${completedItems}/${totalItems} items\nUpdated: ${new Date().toISOString()}`, }); return { progress, completedItems, totalItems }; } } // Example 5: Daily Standup Assistant class StandupAssistant { constructor(trelloClient) { this.trello = trelloClient; } async generateStandupReport(userName) { // Get user's cards const myCards = await this.trello.callTool('get_my_cards', {}); const report = { date: new Date().toLocaleDateString(), user: userName, yesterday: [], today: [], blockers: [], metrics: { cardsInProgress: 0, cardsCompleted: 0, overdueCards: 0, }, }; // Get recent activity const recentActivity = await this.trello.callTool('get_recent_activity', { limit: 50, }); // Process cards for (const card of myCards) { const fullCard = await this.trello.callTool('get_card', { cardId: card.id, }); // Categorize by list if (fullCard.list.name === 'Done' || fullCard.list.name === 'Completed') { // Check if completed yesterday const yesterday = new Date(); yesterday.setDate(yesterday.getDate() - 1); const completedYesterday = recentActivity.some( activity => activity.data.card?.id === card.id && activity.type === 'updateCard' && new Date(activity.date) > yesterday ); if (completedYesterday) { report.yesterday.push({ name: card.name, url: card.url, }); report.metrics.cardsCompleted++; } } else if (fullCard.list.name === 'In Progress' || fullCard.list.name === 'Doing') { report.today.push({ name: card.name, url: card.url, progress: this.getCardProgress(fullCard), }); report.metrics.cardsInProgress++; } else if (fullCard.list.name === 'Blocked') { report.blockers.push({ name: card.name, url: card.url, reason: this.getBlockerReason(fullCard), }); } // Check for overdue if (card.due && new Date(card.due) < new Date() && !card.dueComplete) { report.metrics.overdueCards++; } } return this.formatStandupReport(report); } getCardProgress(card) { if (!card.checklists || card.checklists.length === 0) { return 'No checklist'; } let total = 0; let completed = 0; for (const checklist of card.checklists) { total += checklist.checkItems.length; completed += checklist.checkItems.filter(item => item.state === 'complete').length; } return `${completed}/${total} items complete`; } getBlockerReason(card) { // Look for blocker reason in comments if (card.actions) { const recentComment = card.actions .filter(action => action.type === 'commentCard') .sort((a, b) => new Date(b.date) - new Date(a.date))[0]; if (recentComment && recentComment.data.text.toLowerCase().includes('blocked')) { return recentComment.data.text; } } return 'No reason specified'; } formatStandupReport(report) { return `# Daily Standup - ${report.user} **Date**: ${report.date} ## 📅 Yesterday ${ report.yesterday.length > 0 ? report.yesterday.map(task => `- ✅ ${task.name}`).join('\n') : '- No completed tasks' } ## 📋 Today ${ report.today.length > 0 ? report.today.map(task => `- 🔄 ${task.name} (${task.progress})`).join('\n') : '- No tasks in progress' } ## 🚧 Blockers ${ report.blockers.length > 0 ? report.blockers .map(blocker => `- ⛔ ${blocker.name}\n - Reason: ${blocker.reason}`) .join('\n') : '- No blockers' } ## 📊 Metrics - Cards in Progress: ${report.metrics.cardsInProgress} - Cards Completed Yesterday: ${report.metrics.cardsCompleted} - Overdue Cards: ${report.metrics.overdueCards}`; } async postStandupToCard(report, standupCardId) { await this.trello.callTool('add_comment', { cardId: standupCardId, text: report, }); } } // Example Usage /* async function main() { const trello = new TrelloMCPClient(); // Initialize sprint management const sprintManager = new SprintManager(trello); await sprintManager.initializeSprint(23, '2025-01-22', '2025-02-05'); // Add task to sprint await sprintManager.addTaskToSprint({ name: 'Implement user authentication', description: 'Add OAuth 2.0 support', acceptanceCriteria: [ 'Users can login with Google', 'Users can login with GitHub', 'Session management works correctly', ], dueDate: '2025-01-30T17:00:00Z', }); // Initialize bug tracker const bugTracker = new BugTracker(trello); await bugTracker.initialize(); // Report a bug /* const bug = */ await bugTracker.reportBug({ title: 'Login button not responding', description: 'The login button on the homepage does not respond to clicks', severity: 'high', environment: 'production', stepsToReproduce: ['Navigate to homepage', 'Click on login button', 'Nothing happens'], expectedBehavior: 'Login modal should appear', actualBehavior: 'No response to click', screenshotUrl: 'https://example.com/screenshot.png', userId: 'john.doe@example.com', }); // Generate standup report const standupAssistant = new StandupAssistant(trello); /* const standupReport = */ await standupAssistant.generateStandupReport('John Doe'); // console.log(standupReport); } */ // Export for use in other modules module.exports = { TrelloMCPClient, SprintManager, BugTracker, ReleaseManager, StandupAssistant, };

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/delorenj/mcp-server-trello'

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