Skip to main content
Glama
omgwtfwow

MCP Server for Crawl4AI

by omgwtfwow

execute_js

Execute JavaScript on web pages to extract data, trigger dynamic content, and check page state, returning values directly from scripts with return statements.

Instructions

[STATELESS] Execute JavaScript and get return values + page content. Creates new browser each time. Use for: extracting data, triggering dynamic content, checking page state. Scripts with "return" statements return actual values (strings, numbers, objects, arrays). Note: null returns as {"success": true}. Returns values but page state is lost. For persistent JS execution, use crawl with session_id.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
urlYesThe URL to load
scriptsYesJavaScript to execute. Use "return" to get values back! Each string runs separately. Returns appear in results array. Examples: "return document.title", "return document.querySelectorAll('a').length", "return {url: location.href, links: [...document.links].map(a => a.href)}". Use proper JS syntax: real quotes, no HTML entities.

Implementation Reference

  • Core handler implementation for the 'execute_js' tool. Validates input, executes JS via Crawl4AI service, processes results from multiple scripts, formats output including return values and post-execution page markdown into MCP content blocks.
    async executeJS(options: JSExecuteEndpointOptions) { try { // Check if scripts is provided if (!options.scripts || options.scripts === null) { throw new Error( 'scripts is required. Please provide JavaScript code to execute. Use "return" statements to get values back.', ); } const result: JSExecuteEndpointResponse = await this.service.executeJS(options); // Extract JavaScript execution results const jsResults = result.js_execution_result?.results || []; // Ensure scripts is always an array for mapping const scripts = Array.isArray(options.scripts) ? options.scripts : [options.scripts]; // Format results for display let formattedResults = ''; if (jsResults.length > 0) { formattedResults = jsResults .map((res: unknown, idx: number) => { const script = scripts[idx] || 'Script ' + (idx + 1); // Handle the actual return value or success/error status let resultStr = ''; if (res && typeof res === 'object' && 'success' in res) { // This is a status object (e.g., from null return or execution without return) const statusObj = res as { success: unknown; error?: unknown }; resultStr = statusObj.success ? 'Executed successfully (no return value)' : `Error: ${statusObj.error || 'Unknown error'}`; } else { // This is an actual return value resultStr = JSON.stringify(res, null, 2); } return `Script: ${script}\nReturned: ${resultStr}`; }) .join('\n\n'); } else { formattedResults = 'No results returned'; } // Handle markdown content - can be string or object let markdownContent = ''; if (result.markdown) { if (typeof result.markdown === 'string') { markdownContent = result.markdown; } else if (typeof result.markdown === 'object' && result.markdown.raw_markdown) { // Use raw_markdown from the object structure markdownContent = result.markdown.raw_markdown; } } return { content: [ { type: 'text', text: `JavaScript executed on: ${options.url}\n\nResults:\n${formattedResults}${markdownContent ? `\n\nPage Content After Execution:\n${markdownContent}` : ''}`, }, ], }; } catch (error) { throw this.formatError(error, 'execute JavaScript'); } }
  • src/server.ts:842-845 (registration)
    Registration of the 'execute_js' tool in the MCP server request handler switch statement. Validates arguments using ExecuteJsSchema and delegates to utilityHandlers.executeJS.
    case 'execute_js': return await this.validateAndExecute('execute_js', args, ExecuteJsSchema, async (validatedArgs) => this.utilityHandlers.executeJS(validatedArgs), );
  • Zod schema for validating 'execute_js' tool inputs: requires URL and scripts (string or array of JS code). Uses JsCodeSchema for JS validation.
    export const ExecuteJsSchema = createStatelessSchema( z.object({ url: z.string().url(), scripts: JsCodeSchema, }), 'execute_js', );
  • src/server.ts:191-210 (registration)
    Tool specification for 'execute_js' in the MCP listTools response, including name, detailed description, and inputSchema definition.
    name: 'execute_js', description: '[STATELESS] Execute JavaScript and get return values + page content. Creates new browser each time. Use for: extracting data, triggering dynamic content, checking page state. Scripts with "return" statements return actual values (strings, numbers, objects, arrays). Note: null returns as {"success": true}. Returns values but page state is lost. For persistent JS execution, use crawl with session_id.', inputSchema: { type: 'object', properties: { url: { type: 'string', description: 'The URL to load', }, scripts: { type: ['string', 'array'], items: { type: 'string' }, description: 'JavaScript to execute. Use "return" to get values back! Each string runs separately. Returns appear in results array. Examples: "return document.title", "return document.querySelectorAll(\'a\').length", "return {url: location.href, links: [...document.links].map(a => a.href)}". Use proper JS syntax: real quotes, no HTML entities.', }, }, required: ['url', 'scripts'], }, },
  • Supporting schema for JavaScript code validation used in ExecuteJsSchema. Validates single string or array, rejects invalid JS with HTML entities or malformed syntax.
    export const JsCodeSchema = z .union([ z.string().refine(validateJavaScriptCode, { message: 'Invalid JavaScript: Contains HTML entities ("), literal \\n outside strings, or HTML tags. Use proper JS syntax with real quotes and newlines.', }), z.array( z.string().refine(validateJavaScriptCode, { message: 'Invalid JavaScript: Contains HTML entities ("), literal \\n outside strings, or HTML tags. Use proper JS syntax with real quotes and newlines.', }), ), ]) .describe('JavaScript code as string or array of strings');

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/omgwtfwow/mcp-crawl4ai-ts'

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