Skip to main content
Glama

ClickUp MCP

by TwoFeetUp
inspect-response-structure.js5.78 kB
/** * Inspect Response Structure * * Examines the actual structure of task responses at different detail levels * to identify optimization opportunities (repetitive data, excessive nesting, etc.) */ import { Client } from '@modelcontextprotocol/sdk/client/index.js'; import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js'; import dotenv from 'dotenv'; import fs from 'fs'; dotenv.config(); async function main() { console.log('Starting MCP server...'); const transport = new StdioClientTransport({ command: 'node', args: ['build/index.js'], env: { ...process.env, CLICKUP_API_KEY: process.env.CLICKUP_API_KEY, CLICKUP_TEAM_ID: process.env.CLICKUP_TEAM_ID } }); const client = new Client({ name: 'structure-inspector', version: '1.0.0' }, { capabilities: {} }); await client.connect(transport); console.log('MCP server connected\n'); // Fetch 5 tasks at detailed level console.log('Fetching 5 tasks at DETAILED level...'); const ninetyDaysAgo = Date.now() - (90 * 24 * 60 * 60 * 1000); const result = await client.callTool({ name: 'search_tasks', arguments: { detail_level: 'detailed', limit: 5, date_updated_gt: ninetyDaysAgo.toString() } }); const responseText = result.content.find(c => c.type === 'text')?.text; const parsed = JSON.parse(responseText); // Save full response fs.writeFileSync('playground/sample-detailed-response.json', JSON.stringify(parsed, null, 2)); console.log('✅ Saved full response to: playground/sample-detailed-response.json\n'); // Analyze structure const tasks = parsed.data || parsed.tasks || []; if (tasks.length === 0) { console.log('No tasks found'); await client.close(); return; } console.log(`📊 Analyzing ${tasks.length} tasks...\n`); // Get first task to analyze structure const sampleTask = tasks[0]; console.log('='.repeat(70)); console.log('STRUCTURE ANALYSIS - SINGLE TASK'); console.log('='.repeat(70)); // Analyze top-level fields const fieldSizes = {}; const fieldTypes = {}; for (const [key, value] of Object.entries(sampleTask)) { const valueStr = JSON.stringify(value); fieldSizes[key] = valueStr.length; fieldTypes[key] = Array.isArray(value) ? 'array' : typeof value; } // Sort by size const sortedFields = Object.entries(fieldSizes).sort((a, b) => b[1] - a[1]); console.log('\nFIELD SIZES (characters in JSON):'); sortedFields.forEach(([field, size]) => { const type = fieldTypes[field]; const percent = ((size / JSON.stringify(sampleTask).length) * 100).toFixed(1); console.log(` ${field.padEnd(20)} ${size.toString().padStart(6)} chars ${percent.padStart(5)}% (${type})`); }); // Check for repetitive data across tasks console.log('\n' + '='.repeat(70)); console.log('REPETITIVE DATA ANALYSIS'); console.log('='.repeat(70)); // Analyze which fields are the same across all tasks const sharedFields = {}; for (const key of Object.keys(tasks[0])) { const values = tasks.map(t => JSON.stringify(t[key])); const uniqueValues = new Set(values); if (uniqueValues.size === 1) { sharedFields[key] = { value: values[0], size: values[0].length }; } } console.log('\nFIELDS WITH IDENTICAL VALUES ACROSS ALL TASKS:'); if (Object.keys(sharedFields).length === 0) { console.log(' None - good! No repetitive data.'); } else { for (const [field, info] of Object.entries(sharedFields)) { const totalWasted = info.size * (tasks.length - 1); console.log(` ${field}: ${totalWasted} wasted chars (${info.size} × ${tasks.length - 1} tasks)`); } } // Analyze arrays console.log('\n' + '='.repeat(70)); console.log('ARRAY FIELD ANALYSIS'); console.log('='.repeat(70)); for (const [key, value] of Object.entries(sampleTask)) { if (Array.isArray(value) && value.length > 0) { console.log(`\n${key} (${value.length} items):`); // Check if array items have repetitive structure if (typeof value[0] === 'object') { const firstItem = value[0]; const itemKeys = Object.keys(firstItem); console.log(` Each item has ${itemKeys.length} fields: ${itemKeys.join(', ')}`); // Check for common fields across array items const itemFieldSizes = {}; for (const k of itemKeys) { itemFieldSizes[k] = JSON.stringify(firstItem[k]).length; } const sortedItemFields = Object.entries(itemFieldSizes).sort((a, b) => b[1] - a[1]); console.log(` Field sizes per item:`); sortedItemFields.forEach(([f, s]) => { console.log(` ${f}: ${s} chars`); }); } } } // Optimization suggestions console.log('\n' + '='.repeat(70)); console.log('OPTIMIZATION OPPORTUNITIES'); console.log('='.repeat(70)); console.log(` 1. LARGEST FIELDS (potential for reduction): ${sortedFields.slice(0, 5).map(([field, size], i) => ` ${i + 1}. ${field}: ${size} chars (${((size / JSON.stringify(sampleTask).length) * 100).toFixed(1)}%)` ).join('\n')} 2. NORMALIZATION OPPORTUNITIES: - Check if arrays contain repetitive structures that could be normalized - Look for deeply nested objects that could be flattened - Identify fields that could be shortened or removed at certain detail levels 3. RESPONSE STRUCTURE: Total size: ${JSON.stringify(parsed).length} characters Per task: ~${Math.round(JSON.stringify(parsed).length / tasks.length)} characters Metadata overhead: ${JSON.stringify(parsed.metadata || {}).length} characters Run 'cat playground/sample-detailed-response.json' to see full structure. `); await client.close(); } main().catch(console.error);

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/TwoFeetUp/clickup-mcp'

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