Skip to main content
Glama
JMRMEDEV

Enhanced Web Scraper MCP Server

by JMRMEDEV

wait_for_react_state

Monitor React applications for state changes, data loading completion, or navigation events during web scraping and testing workflows.

Instructions

Wait for React component state changes, data loading, or navigation

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
browserNoBrowser engine to usechromium
conditionYesType of condition to wait for
selectorNoCSS selector or testID to wait for (for custom condition)
timeoutNoMaximum time to wait in milliseconds
urlYesURL to monitor

Implementation Reference

  • The main handler function 'waitForReactState' that implements the core logic of the 'wait_for_react_state' tool. It launches a browser, navigates to the URL, and waits for the specified condition (hydration, navigation, data-loading, animation, or custom selector) using Playwright methods.
    async waitForReactState(args) {
      this.validateArgs(args, ['url', 'condition']);
      const { 
        url, 
        condition, 
        selector, 
        timeout = TIMEOUTS.HYDRATION,
        browser: browserType = 'chromium'
      } = args;
      
      const { browser, context } = await this.getBrowser(browserType);
      const page = await context.newPage();
      
      try {
        await this.setupMobileViewport(page);
        await page.goto(url, { waitUntil: 'networkidle' });
        
        const startTime = Date.now();
        let result = '';
    
        switch (condition) {
          case 'hydration':
            const hydrated = await this.waitForReactHydration(page, timeout);
            result = hydrated ? '✅ React hydration completed' : '❌ React hydration timeout';
            break;
            
          case 'navigation':
            await page.waitForFunction(() => {
              return !document.querySelector('[aria-label*="loading"]') &&
                     !document.querySelector('[data-testid*="loading"]');
            }, { timeout });
            result = '✅ Navigation completed';
            break;
            
          case 'data-loading':
            await page.waitForFunction(() => {
              const loadingElements = document.querySelectorAll(
                '[data-testid*="loading"], [aria-label*="loading"], .loading, .spinner'
              );
              return loadingElements.length === 0;
            }, { timeout });
            result = '✅ Data loading completed';
            break;
            
          case 'animation':
            await page.waitForTimeout(2000);
            result = '✅ Animation wait completed';
            break;
            
          case 'custom':
            if (!selector) throw new Error('Selector required for custom condition');
            const { usedSelector } = await this.findElement(page, selector, timeout);
            result = `✅ Custom condition met: ${usedSelector}`;
            break;
            
          default:
            throw new Error(`Unknown condition: ${condition}`);
        }
        
        const waitTime = Date.now() - startTime;
        
        return {
          content: [{
            type: 'text',
            text: `${result}\nWait time: ${waitTime}ms`
          }]
        };
      } finally {
        await context.close();
        await browser.close();
      }
    }
  • server.js:242-275 (registration)
    Tool registration in the ListTools response, including the name, description, and inputSchema definition for 'wait_for_react_state'.
    {
      name: 'wait_for_react_state',
      description: 'Wait for React component state changes, data loading, or navigation',
      inputSchema: {
        type: 'object',
        properties: {
          url: {
            type: 'string',
            description: 'URL to monitor'
          },
          condition: {
            type: 'string',
            enum: ['hydration', 'navigation', 'data-loading', 'animation', 'custom'],
            description: 'Type of condition to wait for'
          },
          selector: {
            type: 'string',
            description: 'CSS selector or testID to wait for (for custom condition)'
          },
          timeout: {
            type: 'number',
            default: 15000,
            description: 'Maximum time to wait in milliseconds'
          },
          browser: {
            type: 'string',
            enum: ['chromium', 'firefox', 'webkit'],
            default: 'chromium',
            description: 'Browser engine to use'
          }
        },
        required: ['url', 'condition']
      }
    },
  • server.js:606-607 (registration)
    Registration/dispatch in the CallToolRequestSchema switch statement that maps the tool name to the handler method.
    case 'wait_for_react_state':
      return await this.waitForReactState(args);
  • Input schema definition specifying parameters: url (required), condition (required, enum: ['hydration', 'navigation', 'data-loading', 'animation', 'custom']), selector (optional), timeout (default 15000), browser (default 'chromium').
    inputSchema: {
      type: 'object',
      properties: {
        url: {
          type: 'string',
          description: 'URL to monitor'
        },
        condition: {
          type: 'string',
          enum: ['hydration', 'navigation', 'data-loading', 'animation', 'custom'],
          description: 'Type of condition to wait for'
        },
        selector: {
          type: 'string',
          description: 'CSS selector or testID to wait for (for custom condition)'
        },
        timeout: {
          type: 'number',
          default: 15000,
          description: 'Maximum time to wait in milliseconds'
        },
        browser: {
          type: 'string',
          enum: ['chromium', 'firefox', 'webkit'],
          default: 'chromium',
          description: 'Browser engine to use'
        }
      },
      required: ['url', 'condition']
    }
  • Helper function 'waitForReactHydration' used by the handler (and others) to detect React hydration completion via checks for React global, devtools hook, data-reactroot, etc., and waits for loading indicators to detach.
    async waitForReactHydration(page, timeout = TIMEOUTS.HYDRATION) {
      try {
        await page.waitForFunction(() => {
          return window.React || window.__REACT_DEVTOOLS_GLOBAL_HOOK__ || 
                 document.querySelector('[data-reactroot]') ||
                 document.querySelector('#root [data-testid]') ||
                 document.querySelector('.expo-web-view');
        }, { timeout });
    
        await page.waitForTimeout(1000);
        
        const loadingSelectors = [
          '[data-testid*="loading"]',
          '[data-testid*="spinner"]', 
          '.loading',
          '.spinner',
          '[aria-label*="loading"]'
        ];
        
        for (const selector of loadingSelectors) {
          try {
            await page.waitForSelector(selector, { state: 'detached', timeout: 5000 });
          } catch (e) {
            // Loading indicator might not exist, continue
          }
        }
        
        return true;
      } catch (error) {
        console.warn('React hydration wait failed:', error.message);
        return false;
      }
    }
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden of behavioral disclosure. It mentions waiting for conditions but doesn't describe what happens on success/failure, error handling, or side effects. For a tool with 5 parameters and no annotations, this is a significant gap in transparency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, efficient sentence that directly states the tool's purpose without unnecessary words. It's front-loaded with the core functionality, making it easy to understand at a glance while being appropriately sized for its complexity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with 5 parameters, no annotations, and no output schema, the description is minimal but covers the basic purpose. It doesn't address behavioral aspects like return values or error conditions, which are important given the lack of structured data. It's adequate but has clear gaps in completeness.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all parameters thoroughly. The description adds no additional parameter semantics beyond what's in the schema, such as explaining how conditions interact or providing examples. Baseline 3 is appropriate when the schema does the heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose as waiting for React component state changes, data loading, or navigation, which is specific and actionable. However, it doesn't explicitly differentiate from sibling tools like 'wait_for_element' or 'test_react_app', which might have overlapping functionality in a React testing context.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives. With sibling tools like 'wait_for_element' and 'test_react_app' present, there's no indication of scenarios where this tool is preferred or when other tools might be more appropriate, leaving usage context unclear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

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/JMRMEDEV/amazon-q-web-scraper-mcp'

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