UNPKG

@grebyn/toolflow-mcp-server

Version:

MCP server for managing other MCP servers - discover, install, organize into bundles, and automate with workflows. Uses StreamableHTTP transport with dual OAuth/API key authentication.

95 lines (94 loc) 3.75 kB
/** * List Bundles Tool * Search and paginate through bundles with unified scope model */ import { ApiClient } from '../../utils/api-client.js'; import { formatEmptyResults, formatPaginationInfo, formatNextSteps, formatDate, formatTags } from '../shared/formatters.js'; export const listBundlesTool = { name: 'list_bundles', description: 'Find bundles by searching name, description, and tags. Bundles are collections of MCP servers packaged together for easy installation. Returns your organization\'s bundles only. Supports pagination and full-text search.', inputSchema: { type: 'object', properties: { query: { type: 'string', description: 'Optional search term to find bundles by name, description, or tags. Examples: "web development", "github", "data analysis", "browser"' }, limit: { type: 'number', minimum: 1, maximum: 100, default: 20, description: 'Maximum number of bundles to return (1-100, default: 20)' }, offset: { type: 'number', minimum: 0, default: 0, description: 'Number of bundles to skip for pagination (default: 0)' } } }, async execute(args, context) { try { // Validate user context if (!context.userId) { throw new Error('User authentication required'); } // Set defaults const query = args.query || ''; const limit = Math.min(args.limit || 20, 100); const offset = args.offset || 0; // Use API client to fetch bundles (organization only) // Your Vercel API handles the Supabase query with service role key const bundles = await ApiClient.searchBundles({ query, limit, offset }, context); // Handle empty results const bundlesArray = bundles; if (!bundlesArray || bundlesArray.length === 0) { return formatEmptyResults({ query }, 'bundles'); } // Format results const searchText = query ? ` matching "${query}"` : ''; const resultsText = `🔍 Found ${bundlesArray.length} organization bundle${bundlesArray.length === 1 ? '' : 's'}${searchText}: `; const bundlesList = bundlesArray.map((bundle, index) => { const tagsText = formatTags(bundle.tags); const createdDate = formatDate(bundle.created_at); return `**${index + 1}. ${bundle.name}** 📝 ${bundle.description} 🆔 Bundle ID: ${bundle.id} 📅 Created: ${createdDate}${tagsText}`; }).join('\n\n'); const paginationInfo = formatPaginationInfo({ limit, offset, totalResults: bundlesArray.length }); const nextStepsText = formatNextSteps('bundles'); return { content: [ { type: 'text', text: resultsText + bundlesList + paginationInfo + nextStepsText } ] }; } catch (error) { console.error('List bundles error:', error); return { content: [ { type: 'text', text: `❌ Failed to list bundles: ${error.message}` } ] }; } } }; //# sourceMappingURL=list-bundles.js.map