Skip to main content
Glama
workbackai
by workbackai

evaluate

Evaluate JavaScript expressions in the current NodeJS context to inspect values, test code snippets, or debug issues directly within the MCP NodeJS Debugger.

Instructions

Evaluates a JavaScript expression in the current context

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
expressionYesJavaScript expression to evaluate

Implementation Reference

  • The complete handler implementation for the 'evaluate' tool. It wraps the expression in try-catch, evaluates it using CDP Debugger.evaluateOnCallFrame if paused or Runtime.evaluate otherwise, captures console output, formats the result including complex objects, and returns structured content.
    server.tool( "evaluate", "Evaluates a JavaScript expression in the current context", { expression: z.string().describe("JavaScript expression to evaluate") }, async ({ expression }) => { try { // Ensure debugger is enabled if (!inspector.debuggerEnabled) { await inspector.enableDebugger(); } // Capture the current console output length to know where to start capturing new output const consoleStartIndex = inspector.consoleOutput.length; // Wrap the expression in a try-catch to better handle errors const wrappedExpression = ` try { ${expression} } catch (e) { e; // Return the error } `; let result; if (inspector.paused && inspector.currentCallFrames.length > 0) { // When paused at a breakpoint, evaluate in the context of the call frame const frame = inspector.currentCallFrames[0]; result = await inspector.evaluateOnCallFrame(frame.callFrameId, wrappedExpression); } else { // Otherwise, evaluate in the global context result = await inspector.send('Runtime.evaluate', { expression: wrappedExpression, contextId: 1, objectGroup: 'console', includeCommandLineAPI: true, silent: false, returnByValue: true, generatePreview: true, awaitPromise: true // This will wait for promises to resolve }); } // Give some time for console logs to be processed await new Promise(resolve => setTimeout(resolve, 200)); // Get any console output that was generated during execution const consoleOutputs = inspector.consoleOutput.slice(consoleStartIndex); const consoleText = consoleOutputs.map(output => `[${output.type}] ${output.message}` ).join('\n'); let valueRepresentation; if (result.result) { if (result.result.type === 'object') { if (result.result.value) { // If we have a value, use it valueRepresentation = JSON.stringify(result.result.value, null, 2); } else if (result.result.objectId) { // If we have an objectId but no value, the object was too complex to serialize directly // Get more details about the object try { const objectProps = await inspector.getProperties(result.result.objectId); const formattedObject = {}; for (const prop of objectProps.result) { if (prop.value) { if (prop.value.type === 'object' && prop.value.subtype !== 'null') { // For nested objects, try to get their details too if (prop.value.objectId) { try { const nestedProps = await inspector.getProperties(prop.value.objectId); const nestedObj = {}; for (const nestedProp of nestedProps.result) { if (nestedProp.value) { if (nestedProp.value.value !== undefined) { nestedObj[nestedProp.name] = nestedProp.value.value; } else { nestedObj[nestedProp.name] = nestedProp.value.description || `[${nestedProp.value.subtype || nestedProp.value.type}]`; } } } formattedObject[prop.name] = nestedObj; } catch (nestedErr) { formattedObject[prop.name] = prop.value.description || `[${prop.value.subtype || prop.value.type}]`; } } else { formattedObject[prop.name] = prop.value.description || `[${prop.value.subtype || prop.value.type}]`; } } else if (prop.value.type === 'function') { formattedObject[prop.name] = '[function]'; } else if (prop.value.value !== undefined) { formattedObject[prop.name] = prop.value.value; } else { formattedObject[prop.name] = `[${prop.value.type}]`; } } } valueRepresentation = JSON.stringify(formattedObject, null, 2); } catch (propErr) { // If we can't get properties, at least show the object description valueRepresentation = result.result.description || `[${result.result.subtype || result.result.type}]`; } } else { // Fallback for objects without value or objectId valueRepresentation = result.result.description || `[${result.result.subtype || result.result.type}]`; } } else if (result.result.type === 'undefined') { valueRepresentation = 'undefined'; } else if (result.result.value !== undefined) { valueRepresentation = result.result.value.toString(); } else { valueRepresentation = `[${result.result.type}]`; } } else { valueRepresentation = 'No result'; } // Prepare the response content let responseContent = []; // Add console output if there was any if (consoleText.length > 0) { responseContent.push({ type: "text", text: `Console output:\n${consoleText}` }); } // Add the evaluation result responseContent.push({ type: "text", text: `Evaluation result: ${valueRepresentation}` }); return { content: responseContent }; } catch (err) { return { content: [{ type: "text", text: `Error evaluating expression: ${err.message}` }] }; } } );
  • Zod schema for the 'evaluate' tool input, requiring a string 'expression'.
    { expression: z.string().describe("JavaScript expression to evaluate") },
  • Registration of the 'evaluate' tool using server.tool with name and description.
    server.tool( "evaluate", "Evaluates a JavaScript expression in the current context",
  • Helper method 'evaluateOnCallFrame' on the Inspector class, used by the evaluate tool handler when the debugger is paused at a breakpoint.
    async evaluateOnCallFrame(callFrameId, expression) { if (!this.paused) { throw new Error('Debugger is not paused'); } try { return await this.send('Debugger.evaluateOnCallFrame', { callFrameId, expression, objectGroup: 'console', includeCommandLineAPI: true, silent: false, returnByValue: true, generatePreview: true }); } catch (err) { throw err; } }

Other Tools

Related 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/workbackai/mcp-nodejs-debugger'

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