Skip to main content
Glama

macro_play

Execute a saved macro on the OPNSense MCP Server to automate network tasks, configure firewall rules, or manage VLANs. Supports parameter substitution and dry-run mode for testing.

Instructions

Play a saved macro

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
dryRunNoExecute in dry-run mode without making actual API calls
idYesMacro ID
parametersNoParameters to substitute in the macro

Implementation Reference

  • Core handler function that loads a macro by ID, substitutes parameters in its API calls, executes them sequentially via the OPNSense API client, supports dry-run mode, error handling options, and pre/post call hooks.
    async playMacro(id: string, options?: MacroPlaybackOptions): Promise<any[]> { const macro = await this.loadMacro(id); if (!macro) { throw new Error(`Macro ${id} not found`); } const results: any[] = []; const params = options?.parameters || {}; for (const call of macro.calls) { try { // Apply parameter substitution const processedCall = this.substituteParameters(call, macro.parameters, params); // Allow pre-processing const finalCall = options?.beforeCall ? await options.beforeCall(processedCall) : processedCall; if (!finalCall) continue; // Skip if beforeCall returns null // Execute if not dry run if (!options?.dryRun) { const startTime = Date.now(); let response; switch (finalCall.method) { case 'GET': response = await this.client.get(finalCall.path); break; case 'POST': response = await this.client.post(finalCall.path, finalCall.payload); break; case 'PUT': response = await this.client.put(finalCall.path, finalCall.payload); break; case 'DELETE': response = await this.client.delete(finalCall.path); break; } const duration = Date.now() - startTime; // Record the result const result = { call: finalCall, response, duration }; results.push(result); // Allow post-processing if (options?.afterCall) { await options.afterCall(finalCall, response); } } else { // Dry run - just collect the calls results.push({ call: finalCall, response: null, duration: 0, dryRun: true }); } } catch (error) { if (options?.stopOnError) { throw error; } results.push({ call, error, duration: 0 }); } } return results; }
  • Type definition for options passed to the macro_play tool, defining parameters for substitution, execution modes, and callback hooks.
    export interface MacroPlaybackOptions { parameters?: Record<string, any>; dryRun?: boolean; stopOnError?: boolean; beforeCall?: (call: APICall) => Promise<APICall | null>; afterCall?: (call: APICall, response: any) => Promise<void>; }
  • Method signature in IMacroRecorder interface declaring the playMacro functionality, serving as the contract for macro playback tool implementation.
    playMacro(id: string, options?: MacroPlaybackOptions): Promise<any[]>;
  • Helper method that substitutes template parameters ({{param}} or JSONPath) in API calls using provided values, enabling dynamic macro execution.
    private substituteParameters( call: APICall, parameters: MacroParameter[], values: Record<string, any> ): APICall { // Deep clone the call object const substitutedCall = JSON.parse(JSON.stringify(call)); // Create a context object that includes all values plus any response data const context = { ...values, $: values // Allow $ as root context for JSONPath expressions }; // Convert call to string for pattern matching const callStr = JSON.stringify(substitutedCall); // Find all template expressions in the call const templateRegex = /\{\{([^}]+)\}\}/g; let modifiedStr = callStr; let match; while ((match = templateRegex.exec(callStr)) !== null) { const expression = match[1].trim(); let value; if (expression.startsWith('$')) { // JSONPath expression try { const results = jsonpath.query(context, expression); value = results.length > 0 ? results[0] : match[0]; // Keep original if no match } catch (error) { console.warn(`Invalid JSONPath expression: ${expression}`, error); value = match[0]; // Keep original on error } } else { // Simple variable substitution const param = parameters.find(p => p.name === expression); value = values[expression] ?? param?.defaultValue; } if (value !== undefined && value !== match[0]) { // Replace the template with the value modifiedStr = modifiedStr.replace(match[0], JSON.stringify(value)); } } return JSON.parse(modifiedStr); }

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/vespo92/OPNSenseMCP'

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