Claude Code Plugins

Community-maintained marketplace

Feedback

Sophisticated MCP tool management to prevent massive responses from WordPress, Playwright, and other MCPs that can kill conversations on first call. Finely tuned for token efficiency.

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name MCP Response Optimization
description Sophisticated MCP tool management to prevent massive responses from WordPress, Playwright, and other MCPs that can kill conversations on first call. Finely tuned for token efficiency.
when_to_use ALWAYS before ANY MCP tool call, especially: (1) WordPress MCP operations, (2) Playwright browser automation, (3) Notion API queries, (4) Any search/list operations, (5) Large data retrievals. This skill is MANDATORY for all MCP usage.
version 1.0.0
dependencies none

MCP Response Optimization - Advanced Token Management

⚠️ THE CRITICAL PROBLEM

Single MCP calls can kill entire conversations:

  • WordPress query returns 50 full pages → 100,000+ tokens
  • Playwright DOM query returns entire page HTML → 80,000+ tokens
  • Notion search returns 100 full pages → 120,000+ tokens
  • Result: Conversation dead on first message

🎯 CORE PRINCIPLE

REQUEST MINIMAL, DISPLAY NOTHING, SAVE EVERYTHING

Every MCP call must be:

  1. Filtered - Request only needed fields
  2. Limited - Cap result counts aggressively
  3. Silent - Process without displaying
  4. Extracted - Pull only essential data
  5. Saved - Store full results in files if needed

🔴 WORDPRESS MCP - THE WORST OFFENDER

The Problem

WordPress returns EVERYTHING by default:

  • Full post content (can be 50KB per post)
  • All metadata fields
  • Revision history
  • Featured images (base64)
  • Author details
  • Comments
  • Categories, tags, custom fields
  • One query = conversation killer

The Solution: Aggressive Filtering

Rule 1: Always Use Field Filters

// ❌ NEVER DO THIS:
wordpress.list_posts({ per_page: 100 })
// Returns: 5MB of data, 1,250,000 tokens

// ✅ ALWAYS DO THIS:
wordpress.list_posts({ 
  per_page: 10,  // Start small
  fields: 'id,title,date,status',  // ONLY what you need
  context: 'view'  // Minimal context
})
// Returns: 5KB of data, 1,250 tokens

Rule 2: Limit Results Aggressively

// Default limits for WordPress MCP:
per_page: 10  // NEVER use 100
page: 1       // Paginate if needed, don't bulk load

Rule 3: Request Specific Fields Only

For Posts:

// Minimal post fields (when listing):
fields: 'id,title,status,date'

// Add fields only when needed:
fields: 'id,title,status,date,excerpt'  // If need preview
fields: 'id,title,content'  // Only when editing specific post

For Pages:

// Minimal page fields:
fields: 'id,title,status,parent'

For Media:

// NEVER load full images in queries
fields: 'id,title,source_url'  // URL only, not base64

Rule 4: Use Specific Queries, Not Broad Searches

// ❌ BAD - Returns everything:
wordpress.list_posts({ search: 'conference' })

// ✅ GOOD - Targeted with filters:
wordpress.list_posts({ 
  search: 'conference',
  per_page: 5,
  fields: 'id,title,date',
  status: 'publish',
  orderby: 'date',
  order: 'desc'
})

Rule 5: Never Display Full WordPress Responses

// After WordPress MCP call:

// ❌ DON'T:
console.log(response)  // Displays everything, huge token waste

// ✅ DO:
const ids = response.map(post => ({ id: post.id, title: post.title }))
console.log(`Found ${ids.length} posts`)
// Then work with IDs only

WordPress MCP Response Patterns

Pattern: List Posts

// Query with minimal data:
const posts = wordpress.list_posts({
  per_page: 10,
  fields: 'id,title,status,date',
  status: 'publish'
})

// Process silently:
const post_ids = posts.map(p => p.id)

// Display only summary:
"Found ${posts.length} posts. Working with: ${post_ids.join(', ')}"

Pattern: Get Single Post

// Even for single posts, limit fields:
const post = wordpress.get_post({
  id: 123,
  fields: 'id,title,content,status'  // Only needed fields
})

// Don't display content in conversation:
"Retrieved post: ${post.title} (${post.id})"
// Save full content to file if needed for editing

Pattern: Search and Filter

// Multi-stage filtering:
const results = wordpress.list_posts({
  search: 'keyword',
  per_page: 5,  // Tiny initial batch
  fields: 'id,title,date'
})

// Client-side filtering if needed:
const filtered = results.filter(/* your criteria */)

// Display IDs only:
"Found ${filtered.length} matches: [${filtered.map(p => p.id).join(', ')}]"

🔴 PLAYWRIGHT MCP - THE OTHER KILLER

The Problem

Playwright returns massive DOM data:

  • Full page HTML (can be 200KB)
  • Complete DOM tree with all attributes
  • Inline styles and scripts
  • Base64 screenshots (500KB-2MB)
  • One screenshot = conversation over

The Solution: Selective Queries

Rule 1: Use CSS Selectors, Not Full DOM

// ❌ NEVER DO THIS:
playwright.evaluate("document.documentElement.outerHTML")
// Returns: Entire page HTML, 50,000+ tokens

// ✅ ALWAYS DO THIS:
playwright.locator('.product-title').textContent()
// Returns: Just the text you need, 10 tokens

Rule 2: Target Specific Elements

// Extract minimal data:
const data = {
  title: await page.locator('h1').textContent(),
  price: await page.locator('.price').textContent(),
  available: await page.locator('.stock-status').textContent()
}

// DON'T extract full page content

Rule 3: Screenshots - Handle Carefully

// ❌ NEVER include screenshot in response:
const screenshot = await page.screenshot()
// This is 500KB-2MB of base64 data

// ✅ SAVE screenshot, don't display:
await page.screenshot({ path: '/outputs/screenshot.png' })
"Screenshot saved: /outputs/screenshot.png"
// 20 tokens vs 125,000 tokens

Rule 4: Use Specific Selectors

// Target exactly what you need:
const products = await page.locator('.product-card').all()

// Extract minimal fields:
const product_data = []
for (const product of products.slice(0, 10)) {  // Limit to 10
  product_data.push({
    name: await product.locator('.name').textContent(),
    price: await product.locator('.price').textContent()
  })
}

// Save to file, don't display all:
fs.writeFileSync('/outputs/products.json', JSON.stringify(product_data))
"Extracted ${product_data.length} products → /outputs/products.json"

Playwright MCP Response Patterns

Pattern: Page Scraping

// Navigate:
await page.goto(url)

// Extract target data only:
const data = {
  title: await page.title(),
  h1: await page.locator('h1').first().textContent(),
  meta_description: await page.locator('meta[name="description"]').getAttribute('content')
}

// Save, don't display:
fs.writeFileSync('/outputs/page_data.json', JSON.stringify(data))
"Page data saved: /outputs/page_data.json"

Pattern: Element Analysis

// Count elements without loading all:
const count = await page.locator('.product-item').count()
"Found ${count} products"

// Work with first few only:
const sample = await page.locator('.product-item').first().textContent()
"Sample product: ${sample}"

Pattern: Screenshots for User

// Take screenshot, save to outputs:
await page.screenshot({ 
  path: '/mnt/user-data/outputs/page.png',
  fullPage: false  // Viewport only, smaller file
})

// Return link only:
"[View screenshot](computer:///mnt/user-data/outputs/page.png)"

🔴 NOTION MCP - ALSO PROBLEMATIC

The Problem

Notion returns full page objects with all blocks, which can be massive.

The Solution

// ❌ DON'T:
notion.search({ query: 'project' })  // Returns 100 full pages

// ✅ DO:
notion.search({ 
  query: 'project',
  page_size: 10,  // Limit results
  filter: { property: 'Status', select: { equals: 'Active' } }
})

// Then extract IDs only:
const page_ids = results.map(r => r.id)
"Found ${page_ids.length} pages: ${page_ids}"

🔴 GOOGLE DRIVE MCP - CAN BE LARGE

The Problem

Drive returns full file contents or large metadata sets.

The Solution

// ❌ DON'T:
drive.search({ query: 'report' })  // Returns 1000 files with metadata

// ✅ DO:
drive.search({ 
  query: 'report',
  pageSize: 10,  // Limit results
  fields: 'files(id,name,mimeType)'  // Minimal fields
})

📊 TOKEN ESTIMATION GUIDE

Before any MCP call, estimate token impact:

Operation Bad Approach Good Approach
List 100 WP posts 1,000,000 tokens 2,500 tokens (IDs only)
Get WP page content 50,000 tokens 200 tokens (title + ID)
Playwright full DOM 100,000 tokens 500 tokens (target elements)
Playwright screenshot 125,000 tokens 50 tokens (save to file)
Notion page search 80,000 tokens 1,000 tokens (IDs + titles)
Drive file list 50,000 tokens 800 tokens (minimal fields)

🎯 UNIVERSAL MCP RULES

Rule 1: Pre-Call Token Budget

Before EVERY MCP call, ask:

  • What's minimum data I actually need?
  • Can I filter to specific fields?
  • Can I limit result count?
  • Will response fit in 2,000 tokens?

If answer to last question is NO → Adjust parameters

Rule 2: Pagination Over Bulk

// ❌ NEVER:
get_all_items({ limit: 1000 })

// ✅ ALWAYS:
get_items({ limit: 10, page: 1 })
// If need more, paginate with user awareness

Rule 3: Save Large Responses

// Any response >5KB → Save to file

// ❌ DON'T:
console.log(large_response)

// ✅ DO:
fs.writeFileSync('/outputs/response.json', JSON.stringify(large_response))
"Response saved: /outputs/response.json"

Rule 4: ID-Based Workflows

// Step 1: Get IDs only
const ids = get_minimal_list()

// Step 2: User picks which ID to work with
"Found ${ids.length} items: ${ids}"

// Step 3: Fetch full details for THAT ONE
const full_item = get_item_by_id(selected_id)

Rule 5: Never Display Raw MCP Responses

// ❌ FATAL ERROR:
"Here's what I found: " + JSON.stringify(mcp_response)

// ✅ CORRECT:
const summary = {
  count: mcp_response.length,
  items: mcp_response.map(i => i.id)
}
"Found ${summary.count} items: ${summary.items.join(', ')}"

🔧 TOOL-SPECIFIC OPTIMIZATION TABLES

WordPress MCP Field Reference

Never include these fields unless absolutely necessary:

  • content - Can be 50KB per post
  • excerpt - Usually 2-5KB
  • featured_media - Base64 images
  • meta - Custom fields can be huge
  • _links - Unnecessary metadata

Safe fields (always use these):

  • id - Essential
  • title - Small
  • status - Tiny
  • date - Small
  • modified - Small
  • slug - Small

Playwright Selector Optimization

Target specific data points:

// Good selectors (minimal data):
'.product-name'
'.price'
'h1'
'meta[name="description"]'

// Bad selectors (huge data):
'body'
'*'
'[class]'  // Selects everything

Notion Query Optimization

Minimal query structure:

{
  page_size: 10,  // Never more than 20
  filter: { /* specific filter */ },
  sorts: [{ property: 'Modified', direction: 'descending' }]
}

📋 PRE-CALL CHECKLIST

Before EVERY MCP tool call:

  1. Minimum fields requested?
  2. Result limit set to <20?
  3. Estimated response <2,000 tokens?
  4. Plan to save, not display?
  5. ID-based workflow possible?
  6. Pagination strategy ready?

If all YES → Proceed If any NO → Adjust parameters

🚨 EMERGENCY PATTERNS

If MCP Response Already Too Large

// Response came back huge (>50,000 tokens)

// DON'T try to work with it in conversation
// DO this immediately:

// 1. Save full response to file
fs.writeFileSync('/outputs/large_response.json', JSON.stringify(response))

// 2. Extract minimal summary
const summary = {
  count: response.length,
  first_id: response[0]?.id,
  last_id: response[response.length - 1]?.id
}

// 3. Return summary only
"Response too large, saved to /outputs/large_response.json"
"Summary: ${summary.count} items (${summary.first_id} to ${summary.last_id})"

If Conversation Already Dying

// Recognize early warning signs:
// - Response was truncated
// - Error: "context too long"
// - Slow response times

// Immediately save state:
fs.writeFileSync('/outputs/conversation_state.json', {
  last_action: "WordPress query",
  context: "Querying posts",
  next_step: "Process post IDs 123, 456, 789"
})

"⚠️ Large response detected. State saved."
"Continue with: [continuation prompt]"

💡 ADVANCED PATTERNS

Pattern: Progressive Loading

// For large datasets:

// Step 1: Count only
const count = get_count()
"Found ${count} total items"

// Step 2: First batch
const batch1 = get_items({ limit: 10, offset: 0 })
"Loaded first 10: ${batch1.map(i => i.id)}"

// Step 3: Ask before loading more
"Load next batch? (${count - 10} remaining)"

Pattern: Filtered Streaming

// For search operations:

// Apply filters before MCP call:
const filtered_query = {
  search: 'keyword',
  status: 'publish',
  date_after: '2025-01-01',
  per_page: 5  // Start tiny
}

const results = wordpress.search(filtered_query)

// Show count, not content:
"${results.length} matches found"

Pattern: Sampling

// For analysis:

// Get first 3 items only:
const sample = get_items({ limit: 3 })

// Analyze pattern:
"Sample structure: ${Object.keys(sample[0])}"
"Apply this pattern to remaining ${total - 3} items?"

📈 SUCCESS METRICS

This skill is working correctly when:

  • ✅ No MCP call exceeds 2,000 tokens in response
  • ✅ WordPress queries use field filters 100% of time
  • ✅ Playwright saves screenshots, never displays
  • ✅ Raw MCP responses NEVER appear in conversation
  • ✅ ID-based workflows used consistently
  • ✅ Large datasets saved to files automatically

🎯 INTEGRATION WITH OTHER SKILLS

Works synergistically with:

  • reference-file-system: Save MCP responses, reference by path
  • concise-execution-mode: Process MCP calls silently
  • data-processing-templates: Save MCP data to files
  • conversation-state-persistence: Save state before large MCP operations

⚠️ CRITICAL REMINDERS

  1. WordPress default is dangerous - Always set field filters
  2. Playwright screenshots kill conversations - Always save to file
  3. Notion search is greedy - Always set page_size
  4. "List all" is forbidden - Always limit results
  5. Display nothing - Save everything to files

🏆 THE GOLDEN RULES

  1. Request minimal fields - Only what you need
  2. Limit results aggressively - 10 items max initially
  3. Save, don't display - Files, not conversation
  4. IDs, not content - Work with identifiers
  5. Paginate on demand - Never bulk load
  6. Estimate before call - Budget tokens first

Deployment Path: /mnt/skills/user/mcp-response-optimization/SKILL.md Restart Required: Yes (restart Claude Desktop after deployment) Token Impact: Prevents 50,000-100,000+ token MCP response disasters Conversation Survival Rate: From 1 message → full conversation capacity